‪TYPO3CMS  ‪main
AbstractMenuContentObjectTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Doctrine\DBAL\Result;
21 use PHPUnit\Framework\Attributes\DataProvider;
22 use PHPUnit\Framework\Attributes\Test;
36 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
37 
38 final class ‪AbstractMenuContentObjectTest extends UnitTestCase
39 {
40  protected function ‪tearDown(): void
41  {
42  GeneralUtility::purgeInstances();
43  parent::tearDown();
44  }
45 
46  private function ‪prepareSectionIndexTest(): void
47  {
48  $connectionMock = $this->createMock(Connection::class);
49  $connectionMock->method('getExpressionBuilder')->willReturn(new ‪ExpressionBuilder($connectionMock));
50  $connectionMock->method('quoteIdentifier')->willReturnArgument(0)->withAnyParameters();
51  $connectionPoolMock = $this->createMock(ConnectionPool::class);
52  $connectionPoolMock->method('getConnectionForTable')->with('tt_content')->willReturn($connectionMock);
53  GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolMock);
54  }
55 
56  #[Test]
58  {
60  $pageRepository = $this->createMock(PageRepository::class);
61  $pageRepository->expects(self::once())->method('getPage')->willReturn([]);
62  $subject = new ‪AbstractMenuContentObjectFixture();
63  $subject->sys_page = $pageRepository;
64  self::assertEquals([], $subject->sectionIndex('field'));
65  }
66 
67  #[Test]
69  {
71  $pageRepository = $this->createMock(PageRepository::class);
72  $pageRepository->expects(self::once())->method('getPage')->with(10)->willReturn([]);
73  $subject = new ‪AbstractMenuContentObjectFixture();
74  $subject->sys_page = $pageRepository;
75  $subject->id = 10;
76  self::assertEquals([], $subject->sectionIndex('field'));
77  }
78 
79  #[Test]
81  {
82  $this->expectException(\UnexpectedValueException::class);
83  $this->expectExceptionCode(1337334849);
85  $pageRepository = $this->createMock(PageRepository::class);
86  $pageRepository->expects(self::once())->method('getPage')->willReturn(['uid' => 10]);
87  $cObject = $this->createMock(ContentObjectRenderer::class);
88  $cObject->expects(self::once())->method('exec_getQuery')->willReturn(0);
89  $subject = new ‪AbstractMenuContentObjectFixture();
90  $subject->sys_page = $pageRepository;
91  $subject->id = 10;
92  $subject->parent_cObj = $cObject;
93  $subject->sectionIndex('field');
94  }
95 
96  #[Test]
98  {
100  $statementMock = $this->createMock(Result::class);
101  $statementMock->expects(self::exactly(2))->method('fetchAssociative')->willReturn(['uid' => 0, 'header' => 'NOT_OVERLAID'], false);
102  $subject = new ‪AbstractMenuContentObjectFixture();
103  $subject->mconf = [
104  'sectionIndex.' => [
105  'type' => 'all',
106  ],
107  ];
108  $context = GeneralUtility::makeInstance(Context::class);
109  $context->setAspect('language', new ‪LanguageAspect(1, 1, ‪LanguageAspect::OVERLAYS_MIXED));
110  $pageRepository = $this->getMockBuilder(PageRepository::class)->setConstructorArgs([$context])->onlyMethods(['init', 'getPage', 'getLanguageOverlay'])->getMock();
111  $pageRepository->expects(self::once())->method('getPage')->willReturn(['sys_language_uid' => 1]);
112  $pageRepository->expects(self::once())->method('getLanguageOverlay')->willReturn(['uid' => 0, 'header' => 'OVERLAID']);
113  $subject->sys_page = $pageRepository;
114  $cObject = $this->createMock(ContentObjectRenderer::class);
115  $cObject->expects(self::once())->method('exec_getQuery')->willReturn($statementMock);
116  $subject->parent_cObj = $cObject;
117  $result = $subject->sectionIndex('field');
118  self::assertEquals('OVERLAID', $result[0]['title']);
119  }
120 
121  public static function ‪sectionIndexFiltersDataProvider(): array
122  {
123  return [
124  'unfiltered fields' => [
125  1,
126  [
127  'sectionIndex' => 1,
128  'header' => 'foo',
129  'header_layout' => 1,
130  ],
131  ],
132  'with unset section index' => [
133  0,
134  [
135  'sectionIndex' => 0,
136  'header' => 'foo',
137  'header_layout' => 1,
138  ],
139  ],
140  'with unset header' => [
141  0,
142  [
143  'sectionIndex' => 1,
144  'header' => '',
145  'header_layout' => 1,
146  ],
147  ],
148  'with header layout 100' => [
149  0,
150  [
151  'sectionIndex' => 1,
152  'header' => 'foo',
153  'header_layout' => 100,
154  ],
155  ],
156  ];
157  }
158 
159  #[DataProvider('sectionIndexFiltersDataProvider')]
160  #[Test]
161  public function ‪sectionIndexFilters(int $expectedAmount, array $dataRow): void
162  {
164  $statementMock = $this->createMock(Result::class);
165  $statementMock->method('fetchAssociative')->willReturn($dataRow, false);
166  $subject = new ‪AbstractMenuContentObjectFixture();
167  $subject->mconf = [
168  'sectionIndex.' => [
169  'type' => 'header',
170  ],
171  ];
172  $pageRepository = $this->createMock(PageRepository::class);
173  $pageRepository->expects(self::once())->method('getPage')->willReturn(['sys_language_uid' => 1]);
174  $pageRepository->expects(self::once())->method('getPage')->willReturn([]);
175  $subject->sys_page = $pageRepository;
176  $cObject = $this->createMock(ContentObjectRenderer::class);
177  $cObject->expects(self::once())->method('exec_getQuery')->willReturn($statementMock);
178  $subject->parent_cObj = $cObject;
179  self::assertCount($expectedAmount, $subject->sectionIndex('field'));
180  }
181 
183  {
184  return [
185  'no configuration' => [
186  [],
187  '0',
188  'colPos = 0',
189  ],
190  'with useColPos 2' => [
191  [
192  'useColPos' => 2,
193  ],
194  '2',
195  'colPos = 2',
196  ],
197  'with useColPos -1' => [
198  [
199  'useColPos' => -1,
200  ],
201  '-1',
202  '',
203  ],
204  'with stdWrap useColPos' => [
205  [
206  'useColPos.' => [
207  'wrap' => '2|',
208  ],
209  ],
210  '2',
211  'colPos = 2',
212  ],
213  ];
214  }
215 
216  #[DataProvider('sectionIndexQueriesWithDifferentColPosDataProvider')]
217  #[Test]
218  public function ‪sectionIndexQueriesWithDifferentColPos(array $configuration, string $colPosFromStdWrapValue, string $whereClausePrefix): void
219  {
221  $statementMock = $this->createMock(Result::class);
222  $statementMock->method('fetchAssociative')->willReturn([]);
223  $subject = new ‪AbstractMenuContentObjectFixture();
224  $subject->mconf = ['sectionIndex.' => $configuration];
225  $pageRepository = $this->getMockBuilder(PageRepository::class)->disableOriginalConstructor()->getMock();
226  $pageRepository->expects(self::once())->method('getPage')->willReturn(['uid' => 12]);
227  $subject->sys_page = $pageRepository;
228  $queryConfiguration = [
229  'pidInList' => 12,
230  'orderBy' => 'field',
231  'languageField' => 'sys_language_uid',
232  'where' => $whereClausePrefix,
233  ];
234  $cObject = $this->createMock(ContentObjectRenderer::class);
235  $cObject->expects(self::once())->method('stdWrapValue')->with('useColPos', $configuration)->willReturn($colPosFromStdWrapValue);
236  $cObject->expects(self::once())->method('exec_getQuery')->with('tt_content', $queryConfiguration)->willReturn($statementMock);
237  $subject->parent_cObj = $cObject;
238  $subject->sectionIndex('field', 12);
239  }
240 
241  public static function ‪isItemStateChecksExcludeUidListDataProvider(): array
242  {
243  return [
244  'none excluded' => [
245  [
246  [
247  'uid' => 12,
248  'pid' => 42,
249  ],
250  [
251  'uid' => 34,
252  'pid' => 42,
253  ],
254  [
255  'uid' => 56,
256  'pid' => 42,
257  ],
258  ],
259  '1, 23, 456',
260  true,
261  ],
262  'one excluded' => [
263  [
264  [
265  'uid' => 1,
266  'pid' => 42,
267  ],
268  [
269  'uid' => 234,
270  'pid' => 42,
271  ],
272  [
273  'uid' => 567,
274  'pid' => 42,
275  ],
276  ],
277  '1, 23, 456',
278  true,
279  ],
280  'three excluded' => [
281  [
282  [
283  'uid' => 1,
284  'pid' => 42,
285  ],
286  [
287  'uid' => 23,
288  'pid' => 42,
289  ],
290  [
291  'uid' => 456,
292  'pid' => 42,
293  ],
294  ],
295  '1, 23, 456',
296  false,
297  ],
298  'empty excludeList' => [
299  [
300  [
301  'uid' => 1,
302  'pid' => 42,
303  ],
304  [
305  'uid' => 123,
306  'pid' => 42,
307  ],
308  [
309  'uid' => 45,
310  'pid' => 42,
311  ],
312  ],
313  '',
314  true,
315  ],
316  'empty menu' => [
317  [],
318  '1, 23, 456',
319  false,
320  ],
321  ];
322  }
323 
324  #[DataProvider('isItemStateChecksExcludeUidListDataProvider')]
325  #[Test]
326  public function ‪isItemStateChecksExcludeUidList(array $menuItems, string $excludeUidList, bool $expectedResult): void
327  {
329  $request = new ‪ServerRequest();
330  $pageInformation = new ‪PageInformation();
331  $pageInformation->setPageRecord([]);
332  $request = $request->withAttribute('frontend.page.information', $pageInformation);
333  $subject = new ‪AbstractMenuContentObjectFixture();
334  $subject->request = $request;
335  $cObjectMock = $this->createMock(ContentObjectRenderer::class);
336  $cObjectMock->expects(self::once())->method('stdWrapValue')->with('excludeUidList', ['excludeUidList' => $excludeUidList])->willReturn($excludeUidList);
337  $typoScriptFrontendControllerMock = $this->createMock(TypoScriptFrontendController::class);
338  $cObjectMock->method('getTypoScriptFrontendController')->willReturn($typoScriptFrontendControllerMock);
339  $subject->parent_cObj = $cObjectMock;
340  $pageRepository = $this->createMock(PageRepository::class);
341  $pageRepository->expects(self::once())->method('getMenu')->willReturn($menuItems);
342  $subject->sys_page = $pageRepository;
343  $subject->menuArr = [
344  0 => ['uid' => 42],
345  ];
346  $subject->conf = ['excludeUidList' => $excludeUidList];
347  self::assertEquals($expectedResult, $subject->isItemState('IFSUB', 0));
348  }
349 
351  {
352  return [
353  'standard parameter without access protected setting' => [
354  [
355  'parameter' => 1,
356  ],
357  [
358  'showAccessRestrictedPages' => false,
359  ],
360  ['uid' => 1],
361  '',
362  0,
363  '',
364  ],
365  'standard parameter with access protected setting' => [
366  [
367  'parameter' => 10,
368  ],
369  [
370  'showAccessRestrictedPages' => true,
371  ],
372  ['uid' => 10],
373  '',
374  0,
375  '',
376  ],
377  'standard parameter with access protected setting "NONE" casts to boolean linkAccessRestrictedPages (delegates resolving to typoLink method internals)' => [
378  [
379  'parameter' => 10,
380  ],
381  [
382  'showAccessRestrictedPages' => 'NONE',
383  ],
384  ['uid' => 10],
385  '',
386  0,
387  '',
388  ],
389  'standard parameter with access protected setting (int)67 casts to boolean linkAccessRestrictedPages (delegates resolving to typoLink method internals)' => [
390  [
391  'parameter' => 10,
392  ],
393  [
394  'showAccessRestrictedPages' => 67,
395  ],
396  ['uid' => 10],
397  '',
398  0,
399  '',
400  ],
401  'standard parameter with target' => [
402  [
403  'parameter' => 1,
404  'target' => '_blank',
405  ],
406  [
407  'showAccessRestrictedPages' => false,
408  ],
409  ['uid' => 1],
410  '_blank',
411  0,
412  '',
413  ],
414  'parameter with typeOverride=10' => [
415  [
416  'parameter' => '10,10',
417  ],
418  [
419  'showAccessRestrictedPages' => false,
420  ],
421  ['uid' => 10],
422  '',
423  '',
424  10,
425  ],
426  'parameter with target and typeOverride=10' => [
427  [
428  'parameter' => '10,10',
429  'target' => '_self',
430  ],
431  [
432  'showAccessRestrictedPages' => false,
433  ],
434  ['uid' => 10],
435  '_self',
436  '',
437  '10',
438  ],
439  'parameter with invalid value in typeOverride=foobar ignores typeOverride' => [
440  [
441  'parameter' => 20,
442  'target' => '_self',
443  ],
444  [
445  'showAccessRestrictedPages' => false,
446  ],
447  ['uid' => 20],
448  '_self',
449  '',
450  'foobar',
451  20,
452  ],
453  'standard parameter with section name' => [
454  [
455  'parameter' => 10,
456  'target' => '_blank',
457  'section' => 'section-name',
458  ],
459  [
460  'showAccessRestrictedPages' => false,
461  ],
462  [
463  'uid' => 10,
464  'sectionIndex_uid' => 'section-name',
465  ],
466  '_blank',
467  '',
468  '',
469  ],
470  'standard parameter with additional parameters' => [
471  [
472  'parameter' => 10,
473  'section' => 'section-name',
474  'additionalParams' => '&test=foobar',
475  ],
476  [
477  'showAccessRestrictedPages' => false,
478  ],
479  [
480  'uid' => 10,
481  'sectionIndex_uid' => 'section-name',
482  ],
483  '',
484  '&test=foobar',
485  '',
486  ],
487  'overridden page array uid value gets used as parameter' => [
488  [
489  'parameter' => 99,
490  'section' => 'section-name',
491  ],
492  [
493  'showAccessRestrictedPages' => false,
494  ],
495  [
496  'uid' => 10,
497  'sectionIndex_uid' => 'section-name',
498  ],
499  '',
500  '',
501  '',
502  99,
503  ],
504  ];
505  }
506 
507  #[DataProvider('menuTypoLinkCreatesExpectedTypoLinkConfigurationDataProvider')]
508  #[Test]
509  public function ‪menuTypoLinkCreatesExpectedTypoLinkConfiguration(array $expected, array $mconf, array $page, string $oTarget, string|int $addParams = '', string|int $typeOverride = '', int|string|null $overrideId = null): void
510  {
511  $expected['page'] = new ‪Page($page);
512  $cObject = $this->createMock(ContentObjectRenderer::class);
513  $cObject->expects(self::once())->method('createLink')->with('|', $expected);
514  $subject = new ‪AbstractMenuContentObjectFixture();
515  $subject->parent_cObj = $cObject;
516  $subject->mconf = $mconf;
517  $subject->menuTypoLink($page, $oTarget, $addParams, $typeOverride, $overrideId);
518  }
519 }
‪TYPO3\CMS\Core\Domain\Page
Definition: Page.php:24
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Core\Context\LanguageAspect\OVERLAYS_MIXED
‪const OVERLAYS_MIXED
Definition: LanguageAspect.php:75
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexReturnsOverlaidRowBasedOnTheLanguageOfTheGivenPage
‪sectionIndexReturnsOverlaidRowBasedOnTheLanguageOfTheGivenPage()
Definition: AbstractMenuContentObjectTest.php:97
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\isItemStateChecksExcludeUidList
‪isItemStateChecksExcludeUidList(array $menuItems, string $excludeUidList, bool $expectedResult)
Definition: AbstractMenuContentObjectTest.php:326
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexUsesTheInternalIdIfNoPageIdWasGiven
‪sectionIndexUsesTheInternalIdIfNoPageIdWasGiven()
Definition: AbstractMenuContentObjectTest.php:68
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexFiltersDataProvider
‪static sectionIndexFiltersDataProvider()
Definition: AbstractMenuContentObjectTest.php:121
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexFilters
‪sectionIndexFilters(int $expectedAmount, array $dataRow)
Definition: AbstractMenuContentObjectTest.php:161
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\menuTypoLinkCreatesExpectedTypoLinkConfigurationDataProvider
‪static menuTypoLinkCreatesExpectedTypoLinkConfigurationDataProvider()
Definition: AbstractMenuContentObjectTest.php:350
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\tearDown
‪tearDown()
Definition: AbstractMenuContentObjectTest.php:40
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\Fixtures\AbstractMenuContentObjectFixture
Definition: AbstractMenuContentObjectFixture.php:25
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:39
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexReturnsEmptyArrayIfTheRequestedPageCouldNotBeFetched
‪sectionIndexReturnsEmptyArrayIfTheRequestedPageCouldNotBeFetched()
Definition: AbstractMenuContentObjectTest.php:57
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\isItemStateChecksExcludeUidListDataProvider
‪static isItemStateChecksExcludeUidListDataProvider()
Definition: AbstractMenuContentObjectTest.php:241
‪TYPO3\CMS\Core\Context\LanguageAspect
Definition: LanguageAspect.php:57
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest
Definition: AbstractMenuContentObjectTest.php:39
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\menuTypoLinkCreatesExpectedTypoLinkConfiguration
‪menuTypoLinkCreatesExpectedTypoLinkConfiguration(array $expected, array $mconf, array $page, string $oTarget, string|int $addParams='', string|int $typeOverride='', int|string|null $overrideId=null)
Definition: AbstractMenuContentObjectTest.php:509
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:58
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexQueriesWithDifferentColPosDataProvider
‪static sectionIndexQueriesWithDifferentColPosDataProvider()
Definition: AbstractMenuContentObjectTest.php:182
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexQueriesWithDifferentColPos
‪sectionIndexQueriesWithDifferentColPos(array $configuration, string $colPosFromStdWrapValue, string $whereClausePrefix)
Definition: AbstractMenuContentObjectTest.php:218
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:102
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\prepareSectionIndexTest
‪prepareSectionIndexTest()
Definition: AbstractMenuContentObjectTest.php:46
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu\AbstractMenuContentObjectTest\sectionIndexThrowsAnExceptionIfTheInternalQueryFails
‪sectionIndexThrowsAnExceptionIfTheInternalQueryFails()
Definition: AbstractMenuContentObjectTest.php:80
‪TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Menu
Definition: AbstractMenuContentObjectTest.php:18
‪TYPO3\CMS\Frontend\Page\PageInformation
Definition: PageInformation.php:28