‪TYPO3CMS  9.5
TreeControllerTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
3 
5 
6 /*
7  * This file is part of the TYPO3 CMS project.
8  *
9  * It is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License, either version 2
11  * of the License, or any later version.
12  *
13  * For the full copyright and license information, please read the
14  * LICENSE.txt file that was distributed with this source code.
15  *
16  * The TYPO3 project - inspiring people to share!
17  */
18 
27 use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
28 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
29 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
30 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
31 
35 class ‪TreeControllerTest extends FunctionalTestCase
36 {
38 
42  protected ‪$coreExtensionsToLoad = ['workspaces'];
43 
47  private ‪$subject;
48 
52  private ‪$backendUser;
53 
57  private ‪$regularBackendUser;
58 
62  private ‪$context;
63 
69  protected ‪$backendUserFixture = 'EXT:core/Tests/Functional/Fixtures/be_users.xml';
70 
71  protected function ‪setUp(): void
72  {
73  parent::setUp();
74  //admin user for importing dataset
75  $this->backendUser = $this->setUpBackendUserFromFixture(1);
76  $this->‪setUpDatabase();
77 
78  //regular editor, non admin
79  $this->backendUser = $this->setUpBackendUser(9);
80  $this->context = GeneralUtility::makeInstance(Context::class);
81  $this->context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $this->backendUser));
82 
83  $this->subject = $this->getAccessibleMock(TreeController::class, ['dummy']);
84  }
85 
86  protected function ‪tearDown(): void
87  {
88  unset($this->subject, $this->backendUser, $this->context);
89  parent::tearDown();
90  }
91 
92  protected function ‪setUpDatabase()
93  {
95  $scenarioFile = __DIR__ . '/Fixtures/PagesWithBEPermissions.yaml';
96  $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
97  $writer = DataHandlerWriter::withBackendUser($this->backendUser);
98  $writer->invokeFactory($factory);
99  static::failIfArrayIsNotEmpty(
100  $writer->getErrors()
101  );
102  }
103 
107  public function ‪getAllEntryPointPageTrees()
108  {
109  $actual = $this->subject->_call('getAllEntryPointPageTrees');
110  $keepProperties = array_flip(['uid', 'title', '_children']);
111  $actual = $this->‪sortTreeArray($actual);
112  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
113 
114  $expected = [
115  [
116  'uid' => 1000,
117  'title' => 'ACME Inc',
118  '_children' => [
119  [
120  'uid' => 1100,
121  'title' => 'EN: Welcome',
122  '_children' => [
123  ],
124  ],
125  [
126  'uid' => 1200,
127  'title' => 'EN: Features',
128  '_children' => [
129  [
130  'uid' => 1210,
131  'title' => 'EN: Frontend Editing',
132  '_children' => [
133  ],
134  ],
135  [
136  'uid' => 1230,
137  'title' => 'EN: Managing content',
138  '_children' => [
139  ],
140  ],
141  ],
142  ],
143  [
144  'uid' => 1400,
145  'title' => 'EN: ACME in your Region',
146  '_children' => [
147  [
148  'uid' => 1410,
149  'title' => 'EN: Groups',
150  '_children' => [
151  ],
152  ],
153  ],
154  ],
155  [
156  'uid' => 1500,
157  'title' => 'Internal',
158  '_children' => [
159  [
160  'uid' => 1520,
161  'title' => 'Forecasts',
162  '_children' => [],
163  ],
164  [
165  'uid' => 1530,
166  'title' => 'Reports',
167  '_children' => [
168  ],
169  ],
170  ],
171  ],
172  [
173  'uid' => 1700,
174  'title' => 'Announcements & News',
175  '_children' => [
176  ],
177  ],
178  [
179  'uid' => 404,
180  'title' => 'Page not found',
181  '_children' => [
182  ],
183  ],
184  [
185  'uid' => 1930,
186  'title' => 'Our Blog',
187  '_children' => [
188  ],
189  ],
190  [
191  'uid' => 1990,
192  'title' => 'Storage',
193  '_children' => [
194  ],
195  ],
196  ],
197  ],
198  [
199  'uid' => 8110,
200  'title' => 'Europe',
201  '_children' => [
202  [
203  'uid' => 811000,
204  'title' => 'France',
205  '_children' => [],
206  ],
207  ],
208  ],
209  ];
210  self::assertEquals($expected, $actual);
211  }
212 
217  {
218  $actual = $this->subject->_call('getAllEntryPointPageTrees', 0, 'Groups');
219  $keepProperties = array_flip(['uid', 'title', '_children']);
220  $actual = $this->‪sortTreeArray($actual);
221  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
222 
223  $expected = [
224  [
225  'uid' => 1000,
226  'title' => 'ACME Inc',
227  '_children' => [
228  [
229  'uid' => 1400,
230  'title' => 'EN: ACME in your Region',
231  '_children' => [
232  [
233  'uid' => 1410,
234  'title' => 'EN: Groups',
235  '_children' => [
236  ],
237  ],
238  ],
239  ],
240  ],
241  ],
242  [
243  'uid' => 8110,
244  'title' => 'Europe',
245  '_children' => [
246  ],
247  ],
248  ];
249  self::assertEquals($expected, $actual);
250  }
251 
255  public function ‪getSubtreeForAccessiblePage()
256  {
257  $actual = $this->subject->_call('getAllEntryPointPageTrees', 1200);
258  $keepProperties = array_flip(['uid', 'title', '_children']);
259  $actual = $this->‪sortTreeArray($actual);
260  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
261 
262  $expected = [
263  [
264  'uid' => 1200,
265  'title' => 'EN: Features',
266  '_children' => [
267  [
268  'uid' => 1210,
269  'title' => 'EN: Frontend Editing',
270  '_children' => [
271  ],
272  ],
273  [
274  'uid' => 1230,
275  'title' => 'EN: Managing content',
276  '_children' => [
277  ],
278  ],
279  ],
280  ],
281  ];
282  self::assertEquals($expected, $actual);
283  }
284 
288  public function ‪getSubtreeForNonAccessiblePage()
289  {
290  $actual = $this->subject->_call('getAllEntryPointPageTrees', 1510);
291  $keepProperties = array_flip(['uid', 'title', '_children']);
292  $actual = $this->‪sortTreeArray($actual);
293  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
294 
295  $expected = [];
296  self::assertEquals($expected, $actual);
297  }
298 
302  public function ‪getSubtreeForPageOutsideMountPoint()
303  {
304  $actual = $this->subject->_call('getAllEntryPointPageTrees', 7000);
305  $keepProperties = array_flip(['uid', 'title', '_children']);
306  $actual = $this->‪sortTreeArray($actual);
307  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
308 
309  $expected = [];
310  self::assertEquals($expected, $actual);
311  }
312 
317  {
318  $this->‪setWorkspace(1);
319  $actual = $this->subject->_call('getAllEntryPointPageTrees');
320  $keepProperties = array_flip(['uid', 'title', '_children']);
321  $actual = $this->‪sortTreeArray($actual);
322  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
323 
324  $expected = [
325  [
326  'uid' => 1000,
327  'title' => 'ACME Inc',
328  '_children' => [
329  [
330  'uid' => 1950,
331  'title' => 'EN: Goodbye',
332  '_children' => [
333  [
334  'uid' => 10015,
335  'title' => 'EN: Really Goodbye',
336  '_children' => [
337  ],
338  ],
339  ],
340  ],
341  [
342  'uid' => 1100,
343  'title' => 'EN: Welcome',
344  '_children' => [
345  ],
346  ],
347  [
348  'uid' => 1200,
349  'title' => 'EN: Features modified',
350  '_children' => [
351  [
352  'uid' => 1240,
353  'title' => 'EN: Managing data',
354  '_children' => [],
355  ],
356  [
357  'uid' => 1230,
358  'title' => 'EN: Managing content',
359  '_children' => [
360  ],
361  ],
362  ],
363  ],
364  [
365  'uid' => 1500,
366  'title' => 'Internal',
367  '_children' => [
368  [
369  'uid' => 1520,
370  'title' => 'Forecasts',
371  '_children' => [],
372  ],
373  [
374  'uid' => 1530,
375  'title' => 'Reports',
376  '_children' => [
377  ],
378  ],
379  ],
380  ],
381  [
382  'uid' => 1700,
383  'title' => 'Announcements & News',
384  '_children' => [
385  [
386  // page moved in workspace 1
387  // from pid 8110 to pid 1700 (visible now)
388  'uid' => 811000,
389  'title' => 'France',
390  '_children' => [],
391  ],
392  [
393  // page with sub-pages moved in workspace 1
394  // from pid 1510 (missing permissions) to pid 1700 (visible now)
395  'uid' => 1511,
396  'title' => 'Products',
397  '_children' => [],
398  ],
399  ],
400  ],
401  [
402  'uid' => 404,
403  'title' => 'Page not found',
404  '_children' => [
405  ],
406  ],
407  [
408  'uid' => 1930,
409  'title' => 'Our Blog',
410  '_children' => [
411  ],
412  ],
413  [
414  'uid' => 1990,
415  'title' => 'Storage',
416  '_children' => [
417  ],
418  ],
419  ],
420  ],
421  [
422  'uid' => 8110,
423  'title' => 'Europe',
424  '_children' => [
425  ],
426  ],
427  ];
428  self::assertEquals($expected, $actual);
429  }
430 
432  {
433  return [
434  'search for "ACME in your Region" (live value, but deleted in workspace)' => [
435  'ACME in your Region',
436  [],
437  ],
438  'search for non-existing value' => [
439  sha1(random_bytes(10)),
440  [],
441  ],
442  'search for "groups" (live value, but changed in workspace)' => [
443  'Groups',
444  [],
445  ],
446  'search for "teams" (workspace value)' => [
447  'Teams',
448  [
449  [
450  'uid' => 1400,
451  'title' => 'EN: ACME in your Region',
452  '_children' => [
453  [
454  'uid' => 1410,
455  'title' => 'EN: Teams modified',
456  '_children' => [],
457  ],
458  ],
459  ],
460  ],
461  ],
462  // page with sub-pages moved in workspace 1
463  // from pid 1510 (missing permissions) to pid 1700 (visible now)
464  'search for "products" (moved from pid 1510 to pid 1700 in workspace)' => [
465  'Product',
466  [
467  [
468  'uid' => 1700,
469  'title' => 'Announcements & News',
470  '_children' => [
471  [
472  'uid' => 1511,
473  'title' => 'Products',
474  '_children' => [
475  [
476  'uid' => 151110,
477  'title' => 'Product 1',
478  '_children' => [],
479  ],
480  ],
481  ],
482  ],
483  ],
484  ],
485  ],
486  ];
487  }
488 
496  public function ‪getAllEntryPointPageTreesInWorkspaceWithSearch(string $search, array $expectedChildren)
497  {
498  $this->‪setWorkspace(1);
499  // the record was changed from live "Groups" to "Teams modified" in a workspace
500  $actual = $this->subject->_call('getAllEntryPointPageTrees', 0, $search);
501  $keepProperties = array_flip(['uid', 'title', '_children']);
502  $actual = $this->‪sortTreeArray($actual);
503  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
504 
505  $expected = [
506  [
507  'uid' => 1000,
508  'title' => 'ACME Inc',
509  '_children' => $expectedChildren,
510  ],
511  [
512  'uid' => 8110,
513  'title' => 'Europe',
514  '_children' => [
515  ],
516  ],
517  ];
518  self::assertEquals($expected, $actual);
519  }
520 
525  {
526  $this->‪setWorkspace(1);
527  $actual = $this->subject->_call('getAllEntryPointPageTrees', 1200);
528  $keepProperties = array_flip(['uid', 'title', '_children']);
529  $actual = $this->‪sortTreeArray($actual);
530  $actual = $this->‪normalizeTreeArray($actual, $keepProperties);
531 
532  $expected = [
533  [
534  'uid' => 1200,
535  'title' => 'EN: Features modified',
536  '_children' => [
537  [
538  'uid' => 1240,
539  'title' => 'EN: Managing data',
540  '_children' => [
541  [
542  'uid' => 124010,
543  'title' => 'EN: Managing complex data',
544  '_children' => []
545  ]
546  ],
547  ],
548  [
549  'uid' => 1230,
550  'title' => 'EN: Managing content',
551  '_children' => [
552  ],
553  ],
554  ],
555  ],
556  ];
557  self::assertEquals($expected, $actual);
558  }
559 
563  private function ‪setWorkspace(int $workspaceId)
564  {
565  $this->backendUser->workspace = $workspaceId;
566  $this->context->setAspect('workspace', new ‪WorkspaceAspect($workspaceId));
567  }
568 
575  private function ‪sortTreeArray(array $tree): array
576  {
577  ksort($tree);
578  return array_map(
579  function (array $item) {
580  foreach ($item as $propertyName => $propertyValue) {
581  if (!is_array($propertyValue)) {
582  continue;
583  }
584  $item[$propertyName] = $this->‪sortTreeArray($propertyValue);
585  }
586  return $item;
587  },
588  $tree
589  );
590  }
591 
599  private function ‪normalizeTreeArray(array $tree, array $keepProperties): array
600  {
601  return array_map(
602  function (array $item) use ($keepProperties) {
603  // only keep these property names
604  $item = array_intersect_key($item, $keepProperties);
605  foreach ($item as $propertyName => $propertyValue) {
606  if (!is_array($propertyValue)) {
607  continue;
608  }
609  // process recursively for nested array items (e.g. `_children`)
610  $item[$propertyName] = $this->‪normalizeTreeArray($propertyValue, $keepProperties);
611  }
612  return $item;
613  },
614  // normalize numeric indexes (remove sorting markers)
615  array_values($tree)
616  );
617  }
618 }
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getSubtreeForNonAccessiblePage
‪getSubtreeForNonAccessiblePage()
Definition: TreeControllerTest.php:281
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\setUp
‪setUp()
Definition: TreeControllerTest.php:64
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\$coreExtensionsToLoad
‪string[] $coreExtensionsToLoad
Definition: TreeControllerTest.php:40
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:29
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getAllEntryPointPageTreesWithSearch
‪getAllEntryPointPageTreesWithSearch()
Definition: TreeControllerTest.php:209
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\sortTreeArray
‪array sortTreeArray(array $tree)
Definition: TreeControllerTest.php:568
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getSubtreeForAccessiblePageInWorkspace
‪getSubtreeForAccessiblePageInWorkspace()
Definition: TreeControllerTest.php:517
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait
Definition: SiteBasedTestTrait.php:34
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getAllEntryPointPageTreesInWorkspace
‪getAllEntryPointPageTreesInWorkspace()
Definition: TreeControllerTest.php:309
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getSubtreeForPageOutsideMountPoint
‪getSubtreeForPageOutsideMountPoint()
Definition: TreeControllerTest.php:295
‪TYPO3\CMS\Backend\Controller\Page\TreeController
Definition: TreeController.php:45
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\$subject
‪TreeController AccessibleObjectInterface $subject
Definition: TreeControllerTest.php:44
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getAllEntryPointPageTrees
‪getAllEntryPointPageTrees()
Definition: TreeControllerTest.php:100
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\normalizeTreeArray
‪array normalizeTreeArray(array $tree, array $keepProperties)
Definition: TreeControllerTest.php:592
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getAllEntryPointPageTreesInWorkspaceWithSearchDataProvider
‪getAllEntryPointPageTreesInWorkspaceWithSearchDataProvider()
Definition: TreeControllerTest.php:424
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getAllEntryPointPageTreesInWorkspaceWithSearch
‪getAllEntryPointPageTreesInWorkspaceWithSearch(string $search, array $expectedChildren)
Definition: TreeControllerTest.php:489
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\$regularBackendUser
‪BackendUserAuthentication $regularBackendUser
Definition: TreeControllerTest.php:52
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\setWorkspace
‪setWorkspace(int $workspaceId)
Definition: TreeControllerTest.php:556
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\setUpDatabase
‪setUpDatabase()
Definition: TreeControllerTest.php:85
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\$backendUserFixture
‪string $backendUserFixture
Definition: TreeControllerTest.php:62
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page
Definition: LocalizationControllerTest.php:4
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:50
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\$backendUser
‪BackendUserAuthentication $backendUser
Definition: TreeControllerTest.php:48
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\$context
‪Context $context
Definition: TreeControllerTest.php:56
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest
Definition: TreeControllerTest.php:36
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\getSubtreeForAccessiblePage
‪getSubtreeForAccessiblePage()
Definition: TreeControllerTest.php:248
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:36
‪TYPO3\CMS\Backend\Tests\Functional\Controller\Page\TreeControllerTest\tearDown
‪tearDown()
Definition: TreeControllerTest.php:79
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static Bootstrap null initializeLanguageObject()
Definition: Bootstrap.php:986