TYPO3 CMS  TYPO3_8-7
ContentObjectRendererTest.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
23 
27 class ContentObjectRendererTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
28 {
32  protected $subject;
33 
34  protected function setUp()
35  {
36  parent::setUp();
37 
38  $typoScriptFrontendController = GeneralUtility::makeInstance(
39  TypoScriptFrontendController::class,
40  null,
41  1,
42  0
43  );
44  $typoScriptFrontendController->sys_page = GeneralUtility::makeInstance(PageRepository::class);
45  $typoScriptFrontendController->tmpl = GeneralUtility::makeInstance(TemplateService::class);
46  $GLOBALS['TSFE'] = $typoScriptFrontendController;
47 
48  $this->subject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
49  }
50 
57  public function getQueryDataProvider(): array
58  {
59  $data = [
60  'testing empty conf' => [
61  'tt_content',
62  [],
63  [
64  'SELECT' => '*'
65  ]
66  ],
67  'testing #17284: adding uid/pid for workspaces' => [
68  'tt_content',
69  [
70  'selectFields' => 'header,bodytext'
71  ],
72  [
73  'SELECT' => 'header,bodytext, [tt_content].[uid] AS [uid], [tt_content].[pid] AS [pid], [tt_content].[t3ver_state] AS [t3ver_state]'
74  ]
75  ],
76  'testing #17284: no need to add' => [
77  'tt_content',
78  [
79  'selectFields' => 'tt_content.*'
80  ],
81  [
82  'SELECT' => 'tt_content.*'
83  ]
84  ],
85  'testing #17284: no need to add #2' => [
86  'tt_content',
87  [
88  'selectFields' => '*'
89  ],
90  [
91  'SELECT' => '*'
92  ]
93  ],
94  'testing #29783: joined tables, prefix tablename' => [
95  'tt_content',
96  [
97  'selectFields' => 'tt_content.header,be_users.username',
98  'join' => 'be_users ON tt_content.cruser_id = be_users.uid'
99  ],
100  [
101  'SELECT' => 'tt_content.header,be_users.username, [tt_content].[uid] AS [uid], [tt_content].[pid] AS [pid], [tt_content].[t3ver_state] AS [t3ver_state]'
102  ]
103  ],
104  'testing #34152: single count(*), add nothing' => [
105  'tt_content',
106  [
107  'selectFields' => 'count(*)'
108  ],
109  [
110  'SELECT' => 'count(*)'
111  ]
112  ],
113  'testing #34152: single max(crdate), add nothing' => [
114  'tt_content',
115  [
116  'selectFields' => 'max(crdate)'
117  ],
118  [
119  'SELECT' => 'max(crdate)'
120  ]
121  ],
122  'testing #34152: single min(crdate), add nothing' => [
123  'tt_content',
124  [
125  'selectFields' => 'min(crdate)'
126  ],
127  [
128  'SELECT' => 'min(crdate)'
129  ]
130  ],
131  'testing #34152: single sum(is_siteroot), add nothing' => [
132  'tt_content',
133  [
134  'selectFields' => 'sum(is_siteroot)'
135  ],
136  [
137  'SELECT' => 'sum(is_siteroot)'
138  ]
139  ],
140  'testing #34152: single avg(crdate), add nothing' => [
141  'tt_content',
142  [
143  'selectFields' => 'avg(crdate)'
144  ],
145  [
146  'SELECT' => 'avg(crdate)'
147  ]
148  ]
149  ];
150 
151  return $data;
152  }
153 
163  public function getQuery(string $table, array $conf, array $expected)
164  {
165  $GLOBALS['TCA'] = [
166  'pages' => [
167  'ctrl' => [
168  'enablecolumns' => [
169  'disabled' => 'hidden'
170  ]
171  ]
172  ],
173  'tt_content' => [
174  'ctrl' => [
175  'enablecolumns' => [
176  'disabled' => 'hidden'
177  ],
178  'versioningWS' => true
179  ]
180  ],
181  ];
182 
183  $result = $this->subject->getQuery($table, $conf, true);
184 
185  $databasePlatform = (new ConnectionPool())->getConnectionForTable('tt_content')->getDatabasePlatform();
186  foreach ($expected as $field => $value) {
187  if (!($databasePlatform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform)) {
188  // Replace the MySQL backtick quote character with the actual quote character for the DBMS,
189  if ($field === 'SELECT') {
190  $quoteChar = $databasePlatform->getIdentifierQuoteCharacter();
191  $value = str_replace('[', $quoteChar, $value);
192  $value = str_replace(']', $quoteChar, $value);
193  }
194  }
195  $this->assertEquals($value, $result[$field]);
196  }
197  }
198 
203  {
204  $this->subject = $this->getAccessibleMock(ContentObjectRenderer::class, ['getTreeList']);
205  $this->subject->start([], 'tt_content');
206 
207  $conf = [
208  'recursive' => '15',
209  'pidInList' => '16, -35'
210  ];
211 
212  $this->subject->expects($this->at(0))
213  ->method('getTreeList')
214  ->with(-16, 15)
215  ->will($this->returnValue('15,16'));
216  $this->subject->expects($this->at(1))
217  ->method('getTreeList')
218  ->with(-35, 15)
219  ->will($this->returnValue('15,35'));
220 
221  $this->subject->getQuery('tt_content', $conf, true);
222  }
223 
228  {
229  $GLOBALS['TSFE']->id = 27;
230 
231  $this->subject = $this->getAccessibleMock(ContentObjectRenderer::class, ['getTreeList']);
232  $this->subject->start([], 'tt_content');
233 
234  $conf = [
235  'pidInList' => 'this',
236  'recursive' => '4'
237  ];
238 
239  $this->subject->expects($this->once())
240  ->method('getTreeList')
241  ->with(-27)
242  ->will($this->returnValue('27'));
243 
244  $this->subject->getQuery('tt_content', $conf, true);
245  }
246 
251  {
252  return [
253  [
254  [
255  'tt_content' => [
256  'ctrl' => [
257  ],
258  'columns' => [
259  ]
260  ],
261  ],
262  'tt_content',
263  [
264  'uidInList' => '42',
265  'pidInList' => 43,
266  'where' => 'tt_content.cruser_id=5',
267  'groupBy' => 'tt_content.title',
268  'orderBy' => 'tt_content.sorting',
269  ],
270  'WHERE ([tt_content].[uid] IN (42)) AND ([tt_content].[pid] IN (43)) AND (tt_content.cruser_id=5) GROUP BY [tt_content].[title] ORDER BY [tt_content].[sorting]',
271  ],
272  [
273  [
274  'tt_content' => [
275  'ctrl' => [
276  'delete' => 'deleted',
277  'enablecolumns' => [
278  'disabled' => 'hidden',
279  'starttime' => 'startdate',
280  'endtime' => 'enddate',
281  ],
282  'languageField' => 'sys_language_uid',
283  'transOrigPointerField' => 'l18n_parent',
284  ],
285  'columns' => [
286  ]
287  ],
288  ],
289  'tt_content',
290  [
291  'uidInList' => 42,
292  'pidInList' => 43,
293  'where' => 'tt_content.cruser_id=5',
294  'groupBy' => 'tt_content.title',
295  'orderBy' => 'tt_content.sorting',
296  ],
297  'WHERE ([tt_content].[uid] IN (42)) AND ([tt_content].[pid] IN (43)) AND (tt_content.cruser_id=5) AND ([tt_content].[sys_language_uid] = 13) AND (([tt_content].[deleted] = 0) AND ([tt_content].[hidden] = 0) AND ([tt_content].[startdate] <= 4242) AND (([tt_content].[enddate] = 0) OR ([tt_content].[enddate] > 4242))) GROUP BY [tt_content].[title] ORDER BY [tt_content].[sorting]',
298  ],
299  [
300  [
301  'tt_content' => [
302  'ctrl' => [
303  'languageField' => 'sys_language_uid',
304  'transOrigPointerField' => 'l18n_parent',
305  ],
306  'columns' => [
307  ]
308  ],
309  ],
310  'tt_content',
311  [
312  'uidInList' => 42,
313  'pidInList' => 43,
314  'where' => 'tt_content.cruser_id=5',
315  'languageField' => 0,
316  ],
317  'WHERE ([tt_content].[uid] IN (42)) AND ([tt_content].[pid] IN (43)) AND (tt_content.cruser_id=5)',
318  ],
319  ];
320  }
321 
330  public function getWhereReturnCorrectQuery(array $tca, string $table, array $configuration, string $expectedResult)
331  {
332  $GLOBALS['TCA'] = $tca;
333  $GLOBALS['SIM_ACCESS_TIME'] = '4242';
334  $GLOBALS['TSFE']->sys_language_content = 13;
336  $contentObjectRenderer = $this->getMockBuilder(ContentObjectRenderer::class)
337  ->setMethods(['checkPidArray'])
338  ->getMock();
339  $contentObjectRenderer->expects($this->any())
340  ->method('checkPidArray')
341  ->willReturn(explode(',', $configuration['pidInList']));
342 
343  // Replace the [] quote chars of mssql with the actual quote character of other DBMS
344  $databasePlatform = (new ConnectionPool())->getConnectionForTable('tt_content')->getDatabasePlatform();
345  if (!($databasePlatform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform)) {
346  $quoteChar = $databasePlatform->getIdentifierQuoteCharacter();
347  $expectedResult = str_replace('[', $quoteChar, $expectedResult);
348  $expectedResult = str_replace(']', $quoteChar, $expectedResult);
349  }
350 
351  // Embed the enable fields string into the expected result as the database
352  // connection is still unconfigured when the data provider is being run.
353  $expectedResult = sprintf($expectedResult, $GLOBALS['TSFE']->sys_page->enableFields($table));
354 
355  $this->assertSame($expectedResult, $contentObjectRenderer->getWhere($table, $configuration));
356  }
357 
362  {
363  return [
364  'Link to page' => [
365  'My page',
366  [
367  'parameter' => 42,
368  ],
369  [
370  'uid' => 42,
371  'title' => 'Page title',
372  ],
373  '<a href="index.php?id=42">My page</a>',
374  ],
375  'Link to page without link text' => [
376  '',
377  [
378  'parameter' => 42,
379  ],
380  [
381  'uid' => 42,
382  'title' => 'Page title',
383  ],
384  '<a href="index.php?id=42">Page title</a>',
385  ],
386  'Link to page with attributes' => [
387  'My page',
388  [
389  'parameter' => '42',
390  'ATagParams' => 'class="page-class"',
391  'target' => '_self',
392  'title' => 'Link to internal page',
393  ],
394  [
395  'uid' => 42,
396  'title' => 'Page title',
397  ],
398  '<a href="index.php?id=42" title="Link to internal page" target="_self" class="page-class">My page</a>',
399  ],
400  'Link to page with attributes in parameter' => [
401  'My page',
402  [
403  'parameter' => '42 _self page-class "Link to internal page"',
404  ],
405  [
406  'uid' => 42,
407  'title' => 'Page title',
408  ],
409  '<a href="index.php?id=42" title="Link to internal page" target="_self" class="page-class">My page</a>',
410  ],
411  'Link to page with bold tag in title' => [
412  '',
413  [
414  'parameter' => 42,
415  ],
416  [
417  'uid' => 42,
418  'title' => 'Page <b>title</b>',
419  ],
420  '<a href="index.php?id=42">Page <b>title</b></a>',
421  ],
422  'Link to page with script tag in title' => [
423  '',
424  [
425  'parameter' => 42,
426  ],
427  [
428  'uid' => 42,
429  'title' => '<script>alert(123)</script>Page title',
430  ],
431  '<a href="index.php?id=42">&lt;script&gt;alert(123)&lt;/script&gt;Page title</a>',
432  ],
433  ];
434  }
435 
444  public function typolinkReturnsCorrectLinksForPages($linkText, $configuration, $pageArray, $expectedResult)
445  {
446  $pageRepositoryMockObject = $this->getMockBuilder(PageRepository::class)
447  ->setMethods(['getPage'])
448  ->getMock();
449  $pageRepositoryMockObject->expects($this->any())->method('getPage')->willReturn($pageArray);
450 
451  $typoScriptFrontendController = GeneralUtility::makeInstance(
452  TypoScriptFrontendController::class,
453  null,
454  1,
455  0
456  );
457  $typoScriptFrontendController->config = [
458  'config' => [],
459  'mainScript' => 'index.php',
460  ];
461  $typoScriptFrontendController->sys_page = $pageRepositoryMockObject;
462  $typoScriptFrontendController->tmpl = GeneralUtility::makeInstance(TemplateService::class);
463  $typoScriptFrontendController->tmpl->setup = [
464  'lib.' => [
465  'parseFunc.' => $this->getLibParseFunc(),
466  ],
467  ];
468  $GLOBALS['TSFE'] = $typoScriptFrontendController;
469 
470  $subject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
471  $this->assertEquals($expectedResult, $subject->typoLink($linkText, $configuration));
472  }
473 
478  {
479  $pageRepositoryMockObject = $this->getMockBuilder(PageRepository::class)
480  ->setMethods(['getPage'])
481  ->getMock();
482  $pageRepositoryMockObject->expects($this->any())->method('getPage')->willReturn([
483  'uid' => 1,
484  'title' => 'Page title',
485  ]);
486 
487  $templateServiceMockObject = $this->getMockBuilder(TemplateService::class)
488  ->setMethods(['linkData'])
489  ->getMock();
490  $templateServiceMockObject->setup = [
491  'lib.' => [
492  'parseFunc.' => $this->getLibParseFunc(),
493  ],
494  ];
495  $templateServiceMockObject->expects($this->once())->method('linkData')->willReturn([
496  'url' => '/index.php?id=1',
497  'target' => '',
498  'type' => '',
499  'orig_type' => '',
500  'no_cache' => '',
501  'linkVars' => '',
502  'sectionIndex' => '',
503  'totalURL' => '/',
504  ]);
505 
506  $typoScriptFrontendController = GeneralUtility::makeInstance(
507  TypoScriptFrontendController::class,
508  null,
509  1,
510  0
511  );
512  $typoScriptFrontendController->config = [
513  'config' => [],
514  'mainScript' => 'index.php',
515  ];
516  $typoScriptFrontendController->sys_page = $pageRepositoryMockObject;
517  $typoScriptFrontendController->tmpl = $templateServiceMockObject;
518  $GLOBALS['TSFE'] = $typoScriptFrontendController;
519 
520  $configuration = [
521  'parameter' => 1,
522  'section' => 'content',
523  ];
524 
525  $subject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
526  $this->assertEquals('<a href="#content">Page title</a>', $subject->typoLink('', $configuration));
527  }
528 
532  protected function getLibParseTarget()
533  {
534  return [
535  'override' => '',
536  'override.' => [
537  'if.' => [
538  'isTrue.' => [
539  'data' => 'TSFE:dtdAllowsFrames',
540  ],
541  ],
542  ],
543  ];
544  }
545 
549  protected function getLibParseFunc()
550  {
551  return [
552  'makelinks' => '1',
553  'makelinks.' => [
554  'http.' => [
555  'keep' => '{$styles.content.links.keep}',
556  'extTarget' => '',
557  'extTarget.' => $this->getLibParseTarget(),
558  'mailto.' => [
559  'keep' => 'path',
560  ],
561  ],
562  ],
563  'tags' => [
564  'link' => 'TEXT',
565  'link.' => [
566  'current' => '1',
567  'typolink.' => [
568  'parameter.' => [
569  'data' => 'parameters : allParams',
570  ],
571  'extTarget.' => $this->getLibParseTarget(),
572  'target.' => $this->getLibParseTarget(),
573  ],
574  'parseFunc.' => [
575  'constants' => '1',
576  ],
577  ],
578  ],
579 
580  'allowTags' => 'a, abbr, acronym, address, article, aside, b, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, dd, del, dfn, dl, div, dt, em, font, footer, header, h1, h2, h3, h4, h5, h6, hr, i, img, ins, kbd, label, li, link, meta, nav, ol, p, pre, q, samp, sdfield, section, small, span, strike, strong, style, sub, sup, table, thead, tbody, tfoot, td, th, tr, title, tt, u, ul, var',
581  'denyTags' => '*',
582  'sword' => '<span class="csc-sword">|</span>',
583  'constants' => '1',
584  'nonTypoTagStdWrap.' => [
585  'HTMLparser' => '1',
586  'HTMLparser.' => [
587  'keepNonMatchedTags' => '1',
588  'htmlSpecialChars' => '2',
589  ],
590  ],
591  ];
592  }
593 }
typolinkReturnsCorrectLinksForPages($linkText, $configuration, $pageArray, $expectedResult)
static makeInstance($className,... $constructorArguments)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']