‪TYPO3CMS  ‪main
BrokenLinkRepositoryTest.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 
23 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
24 
25 final class ‪BrokenLinkRepositoryTest extends FunctionalTestCase
26 {
27  protected array ‪$coreExtensionsToLoad = [
28  'info',
29  'linkvalidator',
30  'seo',
31  ];
32 
33  private const ‪beusers = [
34  'admin' => [
35  'fixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_users.csv',
36  'uid' => 1,
37  'groupFixture' => '',
38  ],
39  'no group' => [
40  'fixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_users.csv',
41  'uid' => 2,
42  'groupFixture' => '',
43  ],
44  // write access to pages, tt_content
45  'group 1' => [
46  'fixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_users.csv',
47  'uid' => 3,
48  'groupFixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_groups.csv',
49  ],
50  // write access to pages, tt_content, exclude field pages.header_link
51  'group 2' => [
52  'fixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_users.csv',
53  'uid' => 4,
54  'groupFixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_groups.csv',
55  ],
56  // write access to pages, tt_content (restricted to default language)
57  'group 3' => [
58  'fixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_users.csv',
59  'uid' => 5,
60  'groupFixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_groups.csv',
61  ],
62  // group 6: access to all, but restricted via explicit allow to CType=texmedia and text
63  'group 6' => [
64  'fixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_users.csv',
65  'uid' => 6,
66  'groupFixture' => __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/be_groups.csv',
67  ],
68 
69  ];
70 
72  {
73  yield 'Admin user should see all broken links' =>
74  [
75  self::beusers['admin'], // backend user
76  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input.csv', // input file for DB
77  [1], // pids
78  [ // expected result
79  'db' => 1,
80  'file' => 1,
81  'external' => 2,
82  'total' => 4,
83  ],
84  ];
85  yield 'User with no group should see none' =>
86  [
87  self::beusers['no group'],
88  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input.csv',
89  [1],
90  [
91  'total' => 0,
92  ],
93  ];
94  yield 'User with permission to pages but not to specific tables should see none' =>
95  [
96  self::beusers['no group'],
97  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_2.csv',
98  [1],
99  [
100  'total' => 0,
101  ],
102  ];
103  yield 'User with permission to pages and to specific tables, but no exclude fields should see 3 of 4 broken links' =>
104  [
105  self::beusers['group 1'],
106  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_3.csv',
107  [1],
108  [
109  'db' => 1,
110  'file' => 1,
111  'external' => 1,
112  'total' => 3,
113  ],
114  ];
115  yield 'User with permission to pages, specific tables and exclude fields should see all broken links' =>
116  [
117  self::beusers['group 2'],
118  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_4.csv',
119  [1],
120  [
121  'db' => 1,
122  'file' => 1,
123  'external' => 2,
124  'total' => 4,
125  ],
126  ];
127  yield 'User has write permission only for Ctype textmedia and text, should see only broken links from textmedia records' =>
128  [
129  self::beusers['group 6'],
130  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_6_explicit_allow.csv',
131  [1],
132  [
133  'external' => 1,
134  'total' => 1,
135  ],
136  ];
137 
138  yield 'User has write permission only for default language and should see only 1 of 2 broken links' =>
139  [
140  self::beusers['group 3'],
141  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_5.csv',
142  [1],
143  [
144  'external' => 1,
145  'total' => 1,
146  ],
147  ];
148  }
149 
155  array $beuser,
156  string $inputFile,
157  array $pidList,
158  array $expectedOutput
159  ): void {
160  $tsConfig = [
161  'searchFields.' => [
162  'pages' => 'media,url,canonical_link',
163  'tt_content' => 'bodytext,header_link,records',
164  ],
165  'linktypes' => 'db,file,external',
166  'checkhidden' => '0',
167  ];
168  $linkTypes = explode(',', $tsConfig['linktypes']);
169 
170  $searchFields = $tsConfig['searchFields.'];
171  foreach ($searchFields as $table => ‪$fields) {
172  $searchFields[$table] = explode(',', ‪$fields);
173  }
174 
175  $this->‪setupBackendUserAndGroup($beuser['uid'], $beuser['fixture'], $beuser['groupFixture']);
176 
177  $this->importCSVDataSet($inputFile);
178 
179  $linkAnalyzer = $this->get(LinkAnalyzer::class);
180  $linkAnalyzer->init($searchFields, $pidList, $tsConfig);
181  $linkAnalyzer->getLinkStatistics($linkTypes);
182  $result = (new ‪BrokenLinkRepository())->getNumberOfBrokenLinksForRecordsOnPages(
183  $pidList,
184  $searchFields
185  );
186 
187  self::assertEquals($expectedOutput, $result);
188  }
189 
191  {
192  yield 'Admin user should see all broken links' =>
193  [
194  self::beusers['admin'], // backend user
195  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input.csv', // input file for DB
196  [1], // pids
197  4, // count
198  ];
199 
200  yield 'User with no group should see none' =>
201  [
202  self::beusers['no group'],
203  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input.csv',
204  [1],
205  0,
206  ];
207  yield 'User with permission to pages but not to specific tables should see none' =>
208  [
209  self::beusers['no group'],
210  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_2.csv',
211  [1],
212  0,
213  ];
214  yield 'User with permission to pages and to specific tables, but no exclude fields should see 3 of 4 broken links' =>
215  [
216  self::beusers['group 1'],
217  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_3.csv',
218  [1],
219  3,
220  ];
221  yield 'User with permission to pages, specific tables and exclude fields should see all broken links' =>
222  [
223  self::beusers['group 2'],
224  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_4.csv',
225  [1],
226  4,
227  ];
228  yield 'User has write permission only for Ctype textmedia and text, should see only broken links from textmedia records' =>
229  [
230  self::beusers['group 6'],
231  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_6_explicit_allow.csv',
232  [1],
233  1,
234  ];
235 
236  yield 'User has write permission only for default language and should see only 1 of 2 broken links' =>
237  [
238  self::beusers['group 3'],
239  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_5.csv',
240  [1],
241  1,
242  ];
243  }
244 
250  array $beuser,
251  string $inputFile,
252  array $pidList,
253  int $expectedCount
254  ): void {
255  $tsConfig = [
256  'searchFields.' => [
257  'pages' => 'media,url,canonical_link',
258  'tt_content' => 'bodytext,header_link,records',
259  ],
260  'linktypes' => 'db,file,external',
261  'checkhidden' => '0',
262  ];
263  $linkTypes = explode(',', $tsConfig['linktypes']);
264 
265  $searchFields = $tsConfig['searchFields.'];
266  foreach ($searchFields as $table => ‪$fields) {
267  $searchFields[$table] = explode(',', ‪$fields);
268  }
269 
270  $this->‪setupBackendUserAndGroup($beuser['uid'], $beuser['fixture'], $beuser['groupFixture']);
271 
272  $this->importCSVDataSet($inputFile);
273 
274  $linkAnalyzer = $this->get(LinkAnalyzer::class);
275  $linkAnalyzer->init($searchFields, $pidList, $tsConfig);
276  $linkAnalyzer->getLinkStatistics($linkTypes);
277 
278  $results = (new ‪BrokenLinkRepository())->getAllBrokenLinksForPages(
279  $pidList,
280  $linkTypes,
281  $searchFields
282  );
283 
284  self::assertCount($expectedCount, $results);
285  }
286 
288  {
289  yield 'Admin user should see all broken links' =>
290  [
291  self::beusers['admin'], // backend user
292  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input.csv', // input file for DB
293  [1], // pids
294  [ // expected result
295  [
296  'record_uid' => 1,
297  'record_pid' => 1,
298  'language' => 0,
299  'headline' => 'link',
300  'field' => 'bodytext',
301  'table_name' => 'tt_content',
302  'element_type' => 'textmedia',
303  'link_title' => 'link',
304  'url' => 'http://localhost/iAmInvalid',
305  'link_type' => 'external',
306  'needs_recheck' => 0,
307  ],
308  [
309  'record_uid' => 2,
310  'record_pid' => 1,
311  'language' => 0,
312  'headline' => '[No title]',
313  'field' => 'header_link',
314  'table_name' => 'tt_content',
315  'element_type' => 'textmedia',
316  'link_title' => null,
317  'url' => 'http://localhost/iAmInvalid',
318  'link_type' => 'external',
319  'needs_recheck' => 0,
320  ],
321  [
322  'record_uid' => 3,
323  'record_pid' => 1,
324  'language' => 0,
325  'headline' => 'broken link',
326  'field' => 'bodytext',
327  'table_name' => 'tt_content',
328  'element_type' => 'textmedia',
329  'link_title' => 'broken link',
330  'url' => '85',
331  'link_type' => 'db',
332  'needs_recheck' => 0,
333  ],
334  [
335  'record_uid' => 5,
336  'record_pid' => 1,
337  'language' => 0,
338  'headline' => 'broken link',
339  'field' => 'bodytext',
340  'table_name' => 'tt_content',
341  'element_type' => 'textmedia',
342  'link_title' => 'broken link',
343  'url' => 'file:88',
344  'link_type' => 'file',
345  'needs_recheck' => 0,
346  ],
347  ],
348  ];
349 
350  yield 'User with no group should see none' =>
351  [
352  self::beusers['no group'],
353  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input.csv',
354  [1],
355  [],
356  ];
357  yield 'User with permission to pages but not to specific tables should see none' =>
358  [
359  self::beusers['no group'],
360  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_2.csv',
361  [1],
362  [],
363  ];
364  yield 'User with permission to pages and to specific tables, but no exclude fields should see 3 of 4 broken links' =>
365  [
366  self::beusers['group 1'],
367  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_3.csv',
368  [1],
369  [
370  [
371  'record_uid' => 1,
372  'record_pid' => 1,
373  'language' => 0,
374  'headline' => 'link',
375  'field' => 'bodytext',
376  'table_name' => 'tt_content',
377  'element_type' => 'textmedia',
378  'link_title' => 'link',
379  'url' => 'http://localhost/iAmInvalid',
380  'link_type' => 'external',
381  'needs_recheck' => 0,
382  ],
383  [
384  'record_uid' => 3,
385  'record_pid' => 1,
386  'language' => 0,
387  'headline' => 'broken link',
388  'field' => 'bodytext',
389  'table_name' => 'tt_content',
390  'element_type' => 'textmedia',
391  'link_title' => 'broken link',
392  'url' => '85',
393  'link_type' => 'db',
394  'needs_recheck' => 0,
395  ],
396  [
397  'record_uid' => 5,
398  'record_pid' => 1,
399  'language' => 0,
400  'headline' => 'broken link',
401  'field' => 'bodytext',
402  'table_name' => 'tt_content',
403  'element_type' => 'textmedia',
404  'link_title' => 'broken link',
405  'url' => 'file:88',
406  'link_type' => 'file',
407  'needs_recheck' => 0,
408  ],
409  ],
410  ];
411  yield 'User with permission to pages, specific tables and exclude fields should see all broken links' =>
412  [
413  self::beusers['group 2'],
414  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_4.csv',
415  [1],
416  [
417  [
418  'record_uid' => 1,
419  'record_pid' => 1,
420  'language' => 0,
421  'headline' => 'link',
422  'field' => 'bodytext',
423  'table_name' => 'tt_content',
424  'element_type' => 'textmedia',
425  'link_title' => 'link',
426  'url' => 'http://localhost/iAmInvalid',
427  'link_type' => 'external',
428  'needs_recheck' => 0,
429  ],
430  [
431  'record_uid' => 2,
432  'record_pid' => 1,
433  'language' => 0,
434  'headline' => '[No title]',
435  'field' => 'header_link',
436  'table_name' => 'tt_content',
437  'element_type' => 'textmedia',
438  'link_title' => null,
439  'url' => 'http://localhost/iAmInvalid',
440  'link_type' => 'external',
441  'needs_recheck' => 0,
442  ],
443  [
444  'record_uid' => 3,
445  'record_pid' => 1,
446  'language' => 0,
447  'headline' => 'broken link',
448  'field' => 'bodytext',
449  'table_name' => 'tt_content',
450  'element_type' => 'textmedia',
451  'link_title' => 'broken link',
452  'url' => '85',
453  'link_type' => 'db',
454  'needs_recheck' => 0,
455  ],
456  [
457  'record_uid' => 5,
458  'record_pid' => 1,
459  'language' => 0,
460  'headline' => 'broken link',
461  'field' => 'bodytext',
462  'table_name' => 'tt_content',
463  'element_type' => 'textmedia',
464  'link_title' => 'broken link',
465  'url' => 'file:88',
466  'link_type' => 'file',
467  'needs_recheck' => 0,
468  ],
469  ],
470  ];
471  yield 'User has write permission only for Ctype textmedia and text, should see only broken links from textmedia records' =>
472  [
473  self::beusers['group 6'],
474  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_6_explicit_allow.csv',
475  [1],
476  [
477  [
478  'record_uid' => 1,
479  'record_pid' => 1,
480  'language' => 0,
481  'headline' => 'link',
482  'field' => 'bodytext',
483  'table_name' => 'tt_content',
484  'element_type' => 'textmedia',
485  'link_title' => 'link',
486  'url' => 'http://localhost/iAmInvalid',
487  'link_type' => 'external',
488  'needs_recheck' => 0,
489  ],
490  ],
491  ];
492 
493  yield 'User has write permission only for default language and should see only 1 of 2 broken links' =>
494  [
495  self::beusers['group 3'],
496  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_permissions_user_5.csv',
497  [1],
498  [
499  [
500  'record_uid' => 1,
501  'record_pid' => 1,
502  'language' => 0,
503  'headline' => 'link',
504  'field' => 'bodytext',
505  'table_name' => 'tt_content',
506  'element_type' => 'textmedia',
507  'link_title' => 'link',
508  'url' => 'http://localhost/iAmInvalid',
509  'link_type' => 'external',
510  'needs_recheck' => 0,
511  ],
512  ],
513  ];
514  }
515 
521  array $beuser,
522  string $inputFile,
523  array $pidList,
524  array $expectedResult
525  ): void {
526  $tsConfig = [
527  'searchFields.' => [
528  'pages' => 'media,url,canonical_link',
529  'tt_content' => 'bodytext,header_link,records',
530  ],
531  'linktypes' => 'db,file,external',
532  'checkhidden' => '0',
533  ];
534  $linkTypes = explode(',', $tsConfig['linktypes']);
535 
536  $searchFields = $tsConfig['searchFields.'];
537  foreach ($searchFields as $table => ‪$fields) {
538  $searchFields[$table] = explode(',', ‪$fields);
539  }
540 
541  $this->‪setupBackendUserAndGroup($beuser['uid'], $beuser['fixture'], $beuser['groupFixture']);
542 
543  $this->importCSVDataSet($inputFile);
544 
545  $linkAnalyzer = $this->get(LinkAnalyzer::class);
546  $linkAnalyzer->init($searchFields, $pidList, $tsConfig);
547  $linkAnalyzer->getLinkStatistics($linkTypes);
548 
549  $results = (new ‪BrokenLinkRepository())->getAllBrokenLinksForPages(
550  $pidList,
551  $linkTypes,
552  $searchFields
553  );
554 
555  foreach ($results as &$result) {
556  unset($result['url_response']);
557  unset($result['uid']);
558  unset($result['last_check']);
559  }
560  self::assertEquals($expectedResult, $results);
561  }
562 
564  {
565  yield 'All languages should be returend' =>
566  [
567  self::beusers['admin'], // backend user
568  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_languages.csv', // input file for DB
569  [1, 2, 3], // pids
570  [], // languages
571  [ // expected result
572  [
573  'record_uid' => 1,
574  'record_pid' => 1,
575  'language' => 0,
576  'headline' => 'link',
577  'field' => 'bodytext',
578  'table_name' => 'tt_content',
579  'element_type' => 'textmedia',
580  'link_title' => 'link',
581  'url' => 'http://localhost/iAmInvalid',
582  'link_type' => 'external',
583  ],
584  [
585  'record_uid' => 2,
586  'record_pid' => 1,
587  'language' => 1,
588  'headline' => 'link',
589  'field' => 'bodytext',
590  'table_name' => 'tt_content',
591  'element_type' => 'textmedia',
592  'link_title' => 'link',
593  'url' => 'http://localhost/iAmInvalid',
594  'link_type' => 'external',
595  ],
596  [
597  'record_uid' => 3,
598  'record_pid' => 1,
599  'language' => 2,
600  'headline' => 'link',
601  'field' => 'bodytext',
602  'table_name' => 'tt_content',
603  'element_type' => 'textmedia',
604  'link_title' => 'link',
605  'url' => 'http://localhost/iAmInvalid',
606  'link_type' => 'external',
607  ],
608  ],
609  ];
610 
611  yield 'Only defined languages should be returend' =>
612  [
613  self::beusers['admin'],
614  __DIR__ . '/Fixtures/BrokenLinkRepositoryTest/input_languages.csv',
615  [1, 2, 3],
616  [0, 2],
617  [
618  [
619  'record_uid' => 1,
620  'record_pid' => 1,
621  'language' => 0,
622  'headline' => 'link',
623  'field' => 'bodytext',
624  'table_name' => 'tt_content',
625  'element_type' => 'textmedia',
626  'link_title' => 'link',
627  'url' => 'http://localhost/iAmInvalid',
628  'link_type' => 'external',
629  ],
630  [
631  'record_uid' => 3,
632  'record_pid' => 1,
633  'language' => 2,
634  'headline' => 'link',
635  'field' => 'bodytext',
636  'table_name' => 'tt_content',
637  'element_type' => 'textmedia',
638  'link_title' => 'link',
639  'url' => 'http://localhost/iAmInvalid',
640  'link_type' => 'external',
641  ],
642  ],
643  ];
644  }
645 
651  array $beuser,
652  string $inputFile,
653  array $pidList,
654  array ‪$languages,
655  array $expectedResult
656  ): void {
657  $tsConfig = [
658  'searchFields.' => [
659  'tt_content' => 'bodytext',
660  ],
661  'linktypes' => 'external',
662  'checkhidden' => '0',
663  ];
664  $linkTypes = explode(',', $tsConfig['linktypes']);
665 
666  $searchFields = $tsConfig['searchFields.'];
667  foreach ($searchFields as $table => ‪$fields) {
668  $searchFields[$table] = explode(',', ‪$fields);
669  }
670 
671  $this->‪setupBackendUserAndGroup($beuser['uid'], $beuser['fixture'], $beuser['groupFixture']);
672  $this->importCSVDataSet($inputFile);
673 
674  $linkAnalyzer = $this->get(LinkAnalyzer::class);
675  $linkAnalyzer->init($searchFields, $pidList, $tsConfig);
676  $linkAnalyzer->getLinkStatistics($linkTypes);
677 
678  $results = (new ‪BrokenLinkRepository())->getAllBrokenLinksForPages(
679  $pidList,
680  $linkTypes,
681  $searchFields,
683  );
684 
685  foreach ($results as &$result) {
686  unset($result['url_response'], $result['uid'], $result['last_check'], $result['needs_recheck']);
687  }
688 
689  self::assertEquals($expectedResult, $results);
690  }
691 
695  private function ‪setupBackendUserAndGroup(int ‪$uid, string $fixtureFile, string $groupFixtureFile): void
696  {
697  if ($groupFixtureFile) {
698  $this->importCSVDataSet($groupFixtureFile);
699  }
700  $this->importCSVDataSet($fixtureFile);
701  $this->setUpBackendUser(‪$uid);
703  }
704 }
‪$languages
‪$languages
Definition: updateIsoDatabase.php:104
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Linkvalidator\Tests\Functional\Repository
Definition: BrokenLinkRepositoryTest.php:18
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static initializeLanguageObject()
Definition: Bootstrap.php:539
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:64