‪TYPO3CMS  9.5
LinkGeneratorTest.php
Go to the documentation of this file.
1 <?php
2 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 
21 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
22 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
23 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Internal\TypoScriptInstruction;
24 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
25 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext;
26 
32 {
36  private ‪$siteTitle = 'A Company that Manufactures Everything Inc';
37 
42 
43  public static function ‪setUpBeforeClass()
44  {
45  parent::setUpBeforeClass();
46  static::initializeDatabaseSnapshot();
47  }
48 
49  public static function ‪tearDownAfterClass()
50  {
51  static::destroyDatabaseSnapshot();
52  parent::tearDownAfterClass();
53  }
54 
55  protected function ‪setUp()
56  {
57  parent::setUp();
58 
59  // these settings are forwarded to the frontend sub-request as well
60  $this->internalRequestContext = (new InternalRequestContext())
61  ->withGlobalSettings(['TYPO3_CONF_VARS' => static::TYPO3_CONF_VARS]);
62 
63  $this->withDatabaseSnapshot(function () {
64  $this->‪setUpDatabase();
65  });
66  }
67 
68  protected function ‪setUpDatabase()
69  {
70  $backendUser = $this->setUpBackendUserFromFixture(1);
72 
73  $scenarioFile = __DIR__ . '/Fixtures/PlainScenario.yaml';
74  $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
75  $writer = DataHandlerWriter::withBackendUser($backendUser);
76  $writer->invokeFactory($factory);
77  static::failIfArrayIsNotEmpty(
78  $writer->getErrors()
79  );
80 
81  $this->setUpFrontendRootPage(
82  1000,
83  [
84  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
85  ],
86  [
87  'title' => 'ACME Root',
88  'sitetitle' => $this->siteTitle,
89  ]
90  );
91  $this->setUpFrontendRootPage(
92  2000,
93  [
94  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
95  ],
96  [
97  'title' => 'ACME Blog',
98  'sitetitle' => $this->siteTitle,
99  ]
100  );
101  }
102 
103  protected function ‪tearDown()
104  {
105  unset($this->internalRequestContext);
106  parent::tearDown();
107  }
108 
112  public function ‪linkIsGeneratedDataProvider(): array
113  {
114  $instructions = [
115  // acme.com -> acme.com (same site)
116  [1100, 1000, 'index.php?id=acme-root'],
117  [1100, 1100, 'index.php?id=acme-first'],
118  [1100, 1200, 'index.php?id=1200'],
119  [1100, 1210, 'index.php?id=1210'],
120  [1100, 404, 'index.php?id=404'],
121  // acme.com -> products.acme.com (nested sub-site)
122  [1100, 1300, 'index.php?id=1300'],
123  [1100, 1310, 'index.php?id=1310'],
124  // acme.com -> blog.acme.com (different site)
125  [1100, 2000, 'index.php?id=blog-root'],
126  [1100, 2100, 'index.php?id=2100'],
127  [1100, 2110, 'index.php?id=2110'],
128  [1100, 2111, 'index.php?id=2111'],
129  // blog.acme.com -> acme.com (different site)
130  [2100, 1000, 'index.php?id=acme-root'],
131  [2100, 1100, 'index.php?id=acme-first'],
132  [2100, 1200, 'index.php?id=1200'],
133  [2100, 1210, 'index.php?id=1210'],
134  [2100, 404, 'index.php?id=404'],
135  // blog.acme.com -> products.acme.com (different sub-site)
136  [2100, 1300, 'index.php?id=1300'],
137  [2100, 1310, 'index.php?id=1310'],
138  ];
139 
140  return $this->keysFromTemplate(
141  $instructions,
142  '%1$d->%2$d'
143  );
144  }
145 
154  public function ‪linkIsGenerated(int $sourcePageId, int $targetPageId, string $expectation)
155  {
156  $response = $this->executeFrontendRequest(
157  (new InternalRequest())
158  ->withPageId($sourcePageId)
159  ->withInstructions([
160  $this->createTypoLinkUrlInstruction([
161  'parameter' => $targetPageId,
162  ])
163  ]),
164  $this->internalRequestContext
165  );
166 
167  static::assertSame($expectation, (string)$response->getBody());
168  }
169 
173  public function ‪linkIsGeneratedFromMountPointDataProvider(): array
174  {
175  $instructions = [
176  // acme.com -> acme.com (same site)
177  [[7100, 1700], 7110, 1000, 'index.php?id=acme-root'],
178  [[7100, 1700], 7110, 1100, 'index.php?id=acme-first'],
179  [[7100, 1700], 7110, 1200, 'index.php?id=1200'],
180  [[7100, 1700], 7110, 1210, 'index.php?id=1210'],
181  [[7100, 1700], 7110, 404, 'index.php?id=404'],
182  // acme.com -> products.acme.com (nested sub-site)
183  [[7100, 1700], 7110, 1300, 'index.php?id=1300'],
184  [[7100, 1700], 7110, 1310, 'index.php?id=1310'],
185  // acme.com -> blog.acme.com (different site)
186  [[7100, 1700], 7110, 2000, 'index.php?id=blog-root'],
187  [[7100, 1700], 7110, 2100, 'index.php?id=2100'],
188  [[7100, 1700], 7110, 2110, 'index.php?id=2110'],
189  [[7100, 1700], 7110, 2111, 'index.php?id=2111'],
190  // blog.acme.com -> acme.com (different site)
191  [[7100, 2700], 7110, 1000, 'index.php?id=acme-root'],
192  [[7100, 2700], 7110, 1100, 'index.php?id=acme-first'],
193  [[7100, 2700], 7110, 1200, 'index.php?id=1200'],
194  [[7100, 2700], 7110, 1210, 'index.php?id=1210'],
195  [[7100, 2700], 7110, 404, 'index.php?id=404'],
196  // blog.acme.com -> products.acme.com (different sub-site)
197  [[7100, 2700], 7110, 1300, 'index.php?id=1300'],
198  [[7100, 2700], 7110, 1310, 'index.php?id=1310'],
199  ];
200 
201  return $this->keysFromTemplate(
202  $instructions,
203  '%2$d->%3$d (mount:%1$s)',
204  function (array $items) {
205  array_splice(
206  $items,
207  0,
208  1,
209  [implode('->', $items[0])]
210  );
211  return $items;
212  }
213  );
214  }
215 
225  public function ‪linkIsGeneratedFromMountPoint(array $pageMount, int $sourcePageId, int $targetPageId, string $expectation)
226  {
227  // @todo Fix mount point resolving for for pseudo-sites
228  // (PseudoSite should be resolved based on MP-value instead of ID in middleware)
229  $this->markTestSkipped('Mount points currently cannot be resolved in legacy mode');
230 
231  $response = $this->executeFrontendRequest(
232  (new InternalRequest())
233  ->withMountPoint(...$pageMount)
234  ->withPageId($sourcePageId)
235  ->withInstructions([
236  $this->createTypoLinkUrlInstruction([
237  'parameter' => $targetPageId,
238  ])
239  ]),
240  $this->internalRequestContext
241  );
242 
243  static::assertSame($expectation, (string)$response->getBody());
244  }
245 
249  public function ‪linkIsGeneratedForLanguageDataProvider(): array
250  {
251  $instructions = [
252  // acme.com -> acme.com (same site)
253  [1100, 1100, 0, 'index.php?id=acme-first&L=0'],
254  [1100, 1100, 1, 'index.php?id=acme-first&L=1'],
255  [1100, 1100, 2, 'index.php?id=acme-first&L=2'],
256  [1100, 1101, 0, 'index.php?id=acme-first&L=1'],
257  [1100, 1102, 0, 'index.php?id=acme-first&L=2'],
258  // acme.com -> products.acme.com (nested sub-site)
259  [1100, 1300, 0, 'index.php?id=1300&L=0'],
260  [1100, 1310, 0, 'index.php?id=1310&L=0'],
261  // acme.com -> products.acme.com (nested sub-site, l18n_cfg=1)
262  [1100, 1410, 0, ''],
263  [1100, 1410, 1, 'index.php?id=1410&L=1'],
264  [1100, 1410, 2, 'index.php?id=1410&L=2'],
265  [1100, 1411, 0, 'index.php?id=1410&L=1'],
266  [1100, 1412, 0, 'index.php?id=1410&L=2'],
267  // acme.com -> archive (outside site)
268  [1100, 3100, 0, 'index.php?id=3100&L=0'],
269  [1100, 3100, 1, 'index.php?id=3100&L=1'],
270  [1100, 3100, 2, 'index.php?id=3100&L=2'],
271  [1100, 3101, 0, 'index.php?id=3100&L=1'],
272  [1100, 3102, 0, 'index.php?id=3100&L=2'],
273  // blog.acme.com -> acme.com (different site)
274  [2100, 1100, 0, 'index.php?id=acme-first&L=0'],
275  [2100, 1100, 1, 'index.php?id=acme-first&L=1'],
276  [2100, 1100, 2, 'index.php?id=acme-first&L=2'],
277  [2100, 1101, 0, 'index.php?id=acme-first&L=1'],
278  [2100, 1102, 0, 'index.php?id=acme-first&L=2'],
279  // blog.acme.com -> archive (outside site)
280  [2100, 3100, 0, 'index.php?id=3100&L=0'],
281  [2100, 3100, 1, 'index.php?id=3100&L=1'],
282  [2100, 3100, 2, 'index.php?id=3100&L=2'],
283  [2100, 3101, 0, 'index.php?id=3100&L=1'],
284  [2100, 3102, 0, 'index.php?id=3100&L=2'],
285  // blog.acme.com -> products.acme.com (different sub-site)
286  [2100, 1300, 0, 'index.php?id=1300&L=0'],
287  [2100, 1310, 0, 'index.php?id=1310&L=0'],
288  ];
289 
290  return $this->keysFromTemplate(
291  $instructions,
292  '%1$d->%2$d (lang:%3$d)'
293  );
294  }
295 
305  public function ‪linkIsGeneratedForLanguage(int $sourcePageId, int $targetPageId, int $targetLanguageId, string $expectation)
306  {
307  $response = $this->executeFrontendRequest(
308  (new InternalRequest())
309  ->withPageId($sourcePageId)
310  ->withInstructions([
311  $this->createTypoLinkUrlInstruction([
312  'parameter' => $targetPageId,
313  'additionalParams' => '&L=' . $targetLanguageId,
314  ])
315  ]),
316  $this->internalRequestContext
317  );
318 
319  static::assertSame($expectation, (string)$response->getBody());
320  }
321 
326  {
327  $instructions = [
328  // acme.com -> acme.com (same site)
329  [1100, 1000, 'index.php?id=acme-root&testing%5Bvalue%5D=1&cHash=7d1f13fa91159dac7feb3c824936b39d'],
330  [1100, 1100, 'index.php?id=acme-first&testing%5Bvalue%5D=1&cHash=f42b850e435f0cedd366f5db749fc1af'],
331  [1100, 1200, 'index.php?id=1200&testing%5Bvalue%5D=1&cHash=784e11c50ea1a13fd7d969df4ec53ea3'],
332  [1100, 1210, 'index.php?id=1210&testing%5Bvalue%5D=1&cHash=ccb7067022b9835ebfd8f720722bc708'],
333  [1100, 404, 'index.php?id=404&testing%5Bvalue%5D=1&cHash=864e96f586a78a53452f3bf0f4d24591'],
334  // acme.com -> products.acme.com (nested sub-site)
335  [1100, 1300, 'index.php?id=1300&testing%5Bvalue%5D=1&cHash=dbd6597d72ed5098cce3d03eac1eeefe'],
336  [1100, 1310, 'index.php?id=1310&testing%5Bvalue%5D=1&cHash=e64bfc7ab7dd6b70d161e4d556be9726'],
337  // acme.com -> blog.acme.com (different site)
338  [1100, 2000, 'index.php?id=blog-root&testing%5Bvalue%5D=1&cHash=a14da633e46dba71640cb85226cd12c5'],
339  [1100, 2100, 'index.php?id=2100&testing%5Bvalue%5D=1&cHash=d23d74cb50383f8788a9930ec8ba679f'],
340  [1100, 2110, 'index.php?id=2110&testing%5Bvalue%5D=1&cHash=bf25eea89f44a9a79dabdca98f38a432'],
341  [1100, 2111, 'index.php?id=2111&testing%5Bvalue%5D=1&cHash=42dbaeb9172b6b1ca23b49941e194db2'],
342  // blog.acme.com -> acme.com (different site)
343  [2100, 1000, 'index.php?id=acme-root&testing%5Bvalue%5D=1&cHash=7d1f13fa91159dac7feb3c824936b39d'],
344  [2100, 1100, 'index.php?id=acme-first&testing%5Bvalue%5D=1&cHash=f42b850e435f0cedd366f5db749fc1af'],
345  [2100, 1200, 'index.php?id=1200&testing%5Bvalue%5D=1&cHash=784e11c50ea1a13fd7d969df4ec53ea3'],
346  [2100, 1210, 'index.php?id=1210&testing%5Bvalue%5D=1&cHash=ccb7067022b9835ebfd8f720722bc708'],
347  [2100, 404, 'index.php?id=404&testing%5Bvalue%5D=1&cHash=864e96f586a78a53452f3bf0f4d24591'],
348  // blog.acme.com -> products.acme.com (different sub-site)
349  [2100, 1300, 'index.php?id=1300&testing%5Bvalue%5D=1&cHash=dbd6597d72ed5098cce3d03eac1eeefe'],
350  [2100, 1310, 'index.php?id=1310&testing%5Bvalue%5D=1&cHash=e64bfc7ab7dd6b70d161e4d556be9726'],
351  ];
352 
353  return $this->keysFromTemplate(
354  $instructions,
355  '%1$d->%2$d'
356  );
357  }
358 
367  public function ‪linkIsGeneratedWithQueryParameters(int $sourcePageId, int $targetPageId, string $expectation)
368  {
369  $response = $this->executeFrontendRequest(
370  (new InternalRequest())
371  ->withPageId($sourcePageId)
372  ->withInstructions([
373  $this->createTypoLinkUrlInstruction([
374  'parameter' => $targetPageId,
375  'additionalParams' => '&testing[value]=1',
376  'useCacheHash' => 1,
377  ])
378  ]),
379  $this->internalRequestContext
380  );
381 
382  static::assertSame($expectation, (string)$response->getBody());
383  }
384 
388  public function ‪linkIsGeneratedForRestrictedPageDataProvider(): array
389  {
390  $instructions = [
391  [1100, 1510, 0, ''],
392  // [1100, 1511, 0, ''], // @todo Fails, not expanded to sub-pages
393  [1100, 1512, 0, ''],
394  [1100, 1515, 0, ''],
395  [1100, 1520, 0, ''],
396  // [1100, 1521, 0, ''], // @todo Fails, not expanded to sub-pages
397  //
398  [1100, 1510, 1, 'index.php?id=1510'],
399  [1100, 1511, 1, 'index.php?id=1511'],
400  [1100, 1512, 1, 'index.php?id=1512'],
401  [1100, 1515, 1, ''],
402  [1100, 1520, 1, ''],
403  // [1100, 1521, 1, ''], // @todo Fails, not expanded to sub-pages
404  //
405  [1100, 1510, 2, 'index.php?id=1510'],
406  [1100, 1511, 2, 'index.php?id=1511'],
407  [1100, 1512, 2, ''],
408  [1100, 1515, 2, 'index.php?id=1515'],
409  [1100, 1520, 2, 'index.php?id=1520'],
410  [1100, 1521, 2, 'index.php?id=1521'],
411  //
412  [1100, 1510, 3, 'index.php?id=1510'],
413  [1100, 1511, 3, 'index.php?id=1511'],
414  [1100, 1512, 3, 'index.php?id=1512'],
415  [1100, 1515, 3, 'index.php?id=1515'],
416  [1100, 1520, 3, 'index.php?id=1520'],
417  [1100, 1521, 3, 'index.php?id=1521'],
418  ];
419 
420  return $this->keysFromTemplate(
421  $instructions,
422  '%1$d->%2$d (user:%3$d)'
423  );
424  }
425 
435  public function ‪linkIsGeneratedForRestrictedPage(int $sourcePageId, int $targetPageId, int $frontendUserId, string $expectation)
436  {
437  $response = $this->executeFrontendRequest(
438  (new InternalRequest())
439  ->withPageId($sourcePageId)
440  ->withInstructions([
441  $this->createTypoLinkUrlInstruction([
442  'parameter' => $targetPageId,
443  ])
444  ]),
445  $this->internalRequestContext
446  ->withFrontendUserId($frontendUserId)
447  );
448 
449  static::assertSame($expectation, (string)$response->getBody());
450  }
451 
456  {
457  $instructions = [
458  // no frontend user given
459  [1100, 1510, 1500, 0, 'index.php?id=1500&pageId=1510'],
460  // [1100, 1511, 1500, 0, 'index.php?id=1500&pageId=1511'], // @todo Fails, not expanded to sub-pages
461  [1100, 1512, 1500, 0, 'index.php?id=1500&pageId=1512'],
462  [1100, 1515, 1500, 0, 'index.php?id=1500&pageId=1515'],
463  [1100, 1520, 1500, 0, 'index.php?id=1500&pageId=1520'],
464  // [1100, 1521, 1500, 0, 'index.php?id=1500&pageId=1521'], // @todo Fails, not expanded to sub-pages
465  // frontend user 1
466  [1100, 1510, 1500, 1, 'index.php?id=1510'],
467  [1100, 1511, 1500, 1, 'index.php?id=1511'],
468  [1100, 1512, 1500, 1, 'index.php?id=1512'],
469  [1100, 1515, 1500, 1, 'index.php?id=1500&pageId=1515'],
470  [1100, 1520, 1500, 1, 'index.php?id=1500&pageId=1520'],
471  // [1100, 1521, 1500, 1, 'index.php?id=1500&pageId=1521'], // @todo Fails, not expanded to sub-pages
472  // frontend user 2
473  [1100, 1510, 1500, 2, 'index.php?id=1510'],
474  [1100, 1511, 1500, 2, 'index.php?id=1511'],
475  [1100, 1512, 1500, 2, 'index.php?id=1500&pageId=1512'],
476  [1100, 1515, 1500, 2, 'index.php?id=1515'],
477  [1100, 1520, 1500, 2, 'index.php?id=1520'],
478  [1100, 1521, 1500, 2, 'index.php?id=1521'],
479  // frontend user 3
480  [1100, 1510, 1500, 3, 'index.php?id=1510'],
481  [1100, 1511, 1500, 3, 'index.php?id=1511'],
482  [1100, 1512, 1500, 3, 'index.php?id=1512'],
483  [1100, 1515, 1500, 3, 'index.php?id=1515'],
484  [1100, 1520, 1500, 3, 'index.php?id=1520'],
485  [1100, 1521, 1500, 3, 'index.php?id=1521'],
486  ];
487 
488  return $this->keysFromTemplate(
489  $instructions,
490  '%1$d->%2$d (via: %3$d, user:%4$d)'
491  );
492  }
493 
504  public function ‪linkIsGeneratedForRestrictedPageUsingLoginPage(int $sourcePageId, int $targetPageId, int $loginPageId, int $frontendUserId, string $expectation)
505  {
506  $response = $this->executeFrontendRequest(
507  (new InternalRequest())
508  ->withPageId($sourcePageId)
509  ->withInstructions([
510  (new TypoScriptInstruction(TemplateService::class))
511  ->withTypoScript([
512  'config.' => [
513  'typolinkLinkAccessRestrictedPages' => $loginPageId,
514  'typolinkLinkAccessRestrictedPages_addParams' => '&pageId=###PAGE_ID###'
515  ],
516  ]),
517  $this->createTypoLinkUrlInstruction([
518  'parameter' => $targetPageId,
519  ])
520  ]),
521  $this->internalRequestContext
522  ->withFrontendUserId($frontendUserId)
523  );
524 
525  static::assertSame($expectation, (string)$response->getBody());
526  }
527 
531  public function ‪linkIsGeneratedForPageVersionDataProvider(): array
532  {
533  $instructions = [
534  // acme.com -> acme.com (same site)
535  [1100, 1100, false, 'index.php?id=acme-first'],
536  [1100, 1100, true, 'index.php?id=acme-first'], // @todo Alias not removed, yet
537  [1100, 1950, false, 'index.php?id=1950'],
538  [1100, 1950, true, 'index.php?id={targetPageId}'],
539  // blog.acme.com -> acme.com (different site)
540  [2100, 1100, false, 'index.php?id=acme-first'],
541  // @todo https://acme.us/ not prefixed for resolved version
542  [2100, 1100, true, 'index.php?id=acme-first'], // @todo Alias not removed, yet
543  [2100, 1950, false, 'index.php?id=1950'],
544  // @todo https://acme.us/ not prefixed for resolved version
545  [2100, 1950, true, 'index.php?id={targetPageId}'],
546  ];
547 
548  return $this->keysFromTemplate(
549  $instructions,
550  '%1$d->%2$d (resolve:%3$d)'
551  );
552  }
553 
563  public function ‪linkIsGeneratedForPageVersion(int $sourcePageId, int $targetPageId, bool $resolveVersion, string $expectation)
564  {
565  $workspaceId = 1;
566  $backendUserId = 1;
567  if ($resolveVersion) {
569  $workspaceId,
570  'pages',
571  $targetPageId,
572  'uid'
573  )['uid'] ?? null;
574  }
575 
576  $response = $this->executeFrontendRequest(
577  (new InternalRequest())
578  ->withPageId($sourcePageId)
579  ->withInstructions([
580  $this->createTypoLinkUrlInstruction([
581  'parameter' => $targetPageId,
582  ])
583  ]),
584  $this->internalRequestContext
585  ->withWorkspaceId($workspaceId)
586  ->withBackendUserId($backendUserId)
587  );
588 
589  $expectation = str_replace(
590  ['{targetPageId}'],
591  [$targetPageId],
592  $expectation
593  );
594 
595  static::assertSame($expectation, (string)$response->getBody());
596  }
597 
601  public function ‪hierarchicalMenuIsGeneratedDataProvider(): array
602  {
603  return [
604  'ACME Inc' => [
605  1100,
606  [
607  ['title' => 'EN: Welcome', 'link' => 'index.php?id=acme-first'],
608  [
609  'title' => 'EN: Features',
610  'link' => 'index.php?id=1200',
611  'children' => [
612  [
613  'title' => 'EN: Frontend Editing',
614  'link' => 'index.php?id=1210',
615  ],
616  ],
617  ],
618  [
619  'title' => 'EN: Products',
620  'link' => 'index.php?id=1300',
621  'children' => [
622  [
623  'title' => 'EN: Planets',
624  'link' => 'index.php?id=1310',
625  ],
626  [
627  'title' => 'EN: Spaceships',
628  'link' => 'index.php?id=1320',
629  ],
630  [
631  'title' => 'EN: Dark Matter',
632  'link' => 'index.php?id=1330',
633  ],
634  ],
635  ],
636  ['title' => 'EN: ACME in your Region', 'link' => 'index.php?id=1400'],
637  ['title' => 'Internal', 'link' => 'index.php?id=1500'],
638  ['title' => 'About us', 'link' => 'index.php?id=1600'],
639  [
640  'title' => 'Announcements & News',
641  'link' => 'index.php?id=1700',
642  'children' => [
643  [
644  'title' => 'Markets',
645  'link' => 'index.php?id=7110&MP=7100-1700',
646  ],
647  [
648  'title' => 'Products',
649  'link' => 'index.php?id=7120&MP=7100-1700',
650  ],
651  [
652  'title' => 'Partners',
653  'link' => 'index.php?id=7130&MP=7100-1700',
654  ],
655  ],
656  ],
657  ['title' => 'Page not found', 'link' => 'index.php?id=404'],
658  ['title' => 'Our Blog', 'link' => 'index.php?id=2100'],
659  ]
660  ],
661  'ACME Blog' => [
662  2100,
663  [
664  [
665  'title' => 'Authors',
666  'link' => 'index.php?id=2100',
667  'children' => [
668  [
669  'title' => 'John Doe',
670  'link' => 'index.php?id=2110',
671  ],
672  [
673  'title' => 'Jane Doe',
674  'link' => 'index.php?id=2120',
675  ],
676  ],
677  ],
678  1 =>
679  [
680  'title' => 'Announcements & News',
681  'link' => 'index.php?id=2700',
682  'children' => [
683  [
684  'title' => 'Markets',
685  'link' => 'index.php?id=7110&MP=7100-2700',
686  ],
687  [
688  'title' => 'Products',
689  'link' => 'index.php?id=7120&MP=7100-2700',
690  ],
691  [
692  'title' => 'Partners',
693  'link' => 'index.php?id=7130&MP=7100-2700',
694  ],
695  ],
696  ],
697  ['title' => 'ACME Inc', 'link' => 'index.php?id=acme-first'],
698  ]
699  ]
700  ];
701  }
702 
710  public function ‪hierarchicalMenuIsGenerated(int $sourcePageId, array $expectation)
711  {
712  $response = $this->executeFrontendRequest(
713  (new InternalRequest())
714  ->withPageId($sourcePageId)
715  ->withInstructions([
716  $this->createHierarchicalMenuProcessorInstruction([
717  'levels' => 2,
718  'entryLevel' => 0,
719  'expandAll' => 1,
720  'includeSpacer' => 1,
721  'titleField' => 'title',
722  'as' => 'results',
723  ])
724  ]),
725  $this->internalRequestContext
726  );
727 
728  $json = json_decode((string)$response->getBody(), true);
729  $json = $this->filterMenu($json);
730 
731  static::assertSame($expectation, $json);
732  }
733 
737  public function ‪languageMenuIsGeneratedDataProvider(): array
738  {
739  return [
740  'ACME Inc' => [
741  1100,
742  [
743  ['title' => 'Default', 'link' => 'index.php?id=acme-first&L=0'],
744  ['title' => 'French', 'link' => 'index.php?id=acme-first&L=1'],
745  ['title' => 'Franco-Canadian', 'link' => 'index.php?id=acme-first&L=2'],
746  ]
747  ],
748  'ACME Blog' => [
749  2100,
750  [
751  ['title' => 'Default', 'link' => 'index.php?id=2100&L=0'],
752  ['title' => 'French', 'link' => 'index.php?id=2100&L=1'],
753  ['title' => 'Franco-Canadian', 'link' => 'index.php?id=2100&L=2'],
754  ]
755  ]
756  ];
757  }
758 
766  public function ‪languageMenuIsGenerated(int $sourcePageId, array $expectation)
767  {
768  $response = $this->executeFrontendRequest(
769  (new InternalRequest())
770  ->withPageId($sourcePageId)
771  ->withInstructions([
772  $this->createLanguageMenuProcessorInstruction([
773  'languages' => 'auto',
774  ])
775  ]),
776  $this->internalRequestContext
777  );
778 
779  $json = json_decode((string)$response->getBody(), true);
780  $json = $this->filterMenu($json);
781 
782  static::assertSame($expectation, $json);
783  }
784 }
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\AbstractTestCase
Definition: AbstractTestCase.php:29
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceVersionOfRecord
‪static array bool getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
Definition: BackendUtility.php:4166
‪TYPO3\CMS\Core\TypoScript\TemplateService
Definition: TemplateService.php:50
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling
Definition: AbstractTestCase.php:3
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:50
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static Bootstrap null initializeLanguageObject()
Definition: Bootstrap.php:986