‪TYPO3CMS  10.4
MenuProcessor.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
27 
65 {
66  const ‪LINK_PLACEHOLDER = '###LINKPLACEHOLDER###';
67  const ‪TARGET_PLACEHOLDER = '###TARGETPLACEHOLDER###';
68 
74  public ‪$cObj;
75 
82 
90  'cache_period',
91  'entryLevel',
92  'entryLevel.',
93  'special',
94  'special.',
95  'minItems',
96  'minItems.',
97  'maxItems',
98  'maxItems.',
99  'begin',
100  'begin.',
101  'alternativeSortingField',
102  'alternativeSortingField.',
103  'showAccessRestrictedPages',
104  'showAccessRestrictedPages.',
105  'excludeUidList',
106  'excludeUidList.',
107  'excludeDoktypes',
108  'includeNotInMenu',
109  'includeNotInMenu.',
110  'alwaysActivePIDlist',
111  'alwaysActivePIDlist.',
112  'protectLvar',
113  'addQueryString',
114  'addQueryString.',
115  'if',
116  'if.',
117  'levels',
118  'levels.',
119  'expandAll',
120  'expandAll.',
121  'includeSpacer',
122  'includeSpacer.',
123  'as',
124  'titleField',
125  'titleField.',
126  'dataProcessing',
127  'dataProcessing.'
128  ];
129 
137  'levels',
138  'levels.',
139  'expandAll',
140  'expandAll.',
141  'includeSpacer',
142  'includeSpacer.',
143  'as',
144  'titleField',
145  'titleField.',
146  'dataProcessing',
147  'dataProcessing.'
148  ];
149 
153  protected ‪$menuConfig = [
154  'wrap' => '[|]'
155  ];
156 
160  protected ‪$menuLevelConfig = [
161  'doNotLinkIt' => '1',
162  'wrapItemAndSub' => '{|}, |*| {|}, |*| {|}',
163  'stdWrap.' => [
164  'cObject' => 'COA',
165  'cObject.' => [
166  '10' => 'USER',
167  '10.' => [
168  'userFunc' => 'TYPO3\CMS\Frontend\DataProcessing\MenuProcessor->getDataAsJson',
169  'stdWrap.' => [
170  'wrap' => '"data":|'
171  ]
172  ],
173  '20' => 'TEXT',
174  '20.' => [
175  'field' => 'nav_title // title',
176  'trim' => '1',
177  'wrap' => ',"title":|',
178  'preUserFunc' => 'TYPO3\CMS\Frontend\DataProcessing\MenuProcessor->jsonEncodeUserFunc'
179  ],
180  '21' => 'TEXT',
181  '21.' => [
182  'value' => ‪self::LINK_PLACEHOLDER,
183  'wrap' => ',"link":|',
184  ],
185  '22' => 'TEXT',
186  '22.' => [
187  'value' => ‪self::TARGET_PLACEHOLDER,
188  'wrap' => ',"target":|',
189  ],
190  '30' => 'TEXT',
191  '30.' => [
192  'value' => '0',
193  'wrap' => ',"active":|'
194  ],
195  '40' => 'TEXT',
196  '40.' => [
197  'value' => '0',
198  'wrap' => ',"current":|'
199  ],
200  '50' => 'TEXT',
201  '50.' => [
202  'value' => '0',
203  'wrap' => ',"spacer":|'
204  ]
205  ]
206  ]
207  ];
208 
212  public ‪$menuDefaults = [
213  'levels' => 1,
214  'expandAll' => 1,
215  'includeSpacer' => 0,
216  'as' => 'menu',
217  'titleField' => 'nav_title // title'
218  ];
219 
223  protected ‪$menuLevels;
224 
228  protected ‪$menuExpandAll;
229 
233  protected ‪$menuIncludeSpacer;
234 
238  protected ‪$menuTitleField;
239 
244 
248  protected ‪$menuTargetVariableName;
249 
253  protected ‪$contentDataProcessor;
254 
258  public function ‪__construct()
259  {
260  $this->contentDataProcessor = GeneralUtility::makeInstance(ContentDataProcessor::class);
261  }
262 
269  protected function ‪getConfigurationValue($key)
270  {
271  return $this->cObj->stdWrapValue($key, $this->processorConfiguration, $this->menuDefaults[$key]);
272  }
273 
279  public function ‪validateConfiguration()
280  {
281  $invalidArguments = [];
282  foreach ($this->processorConfiguration as $key => $value) {
283  if (!in_array($key, $this->allowedConfigurationKeys)) {
284  $invalidArguments[str_replace('.', '', $key)] = $key;
285  }
286  }
287  if (!empty($invalidArguments)) {
288  throw new \InvalidArgumentException('MenuProcessor Configuration contains invalid Arguments: ' . implode(', ', $invalidArguments), 1478806566);
289  }
290  }
291 
295  public function ‪prepareConfiguration()
296  {
297  $this->menuConfig += ‪$this->processorConfiguration;
298  // Filter configuration
299  foreach ($this->menuConfig as $key => $value) {
300  if (in_array($key, $this->removeConfigurationKeysForHmenu)) {
301  unset($this->menuConfig[$key]);
302  }
303  }
304  // Process special value
305  if (isset($this->menuConfig['special.']['value.'])) {
306  $this->menuConfig['special.']['value'] = $this->cObj->stdWrap($this->menuConfig['special.']['value'], $this->menuConfig['special.']['value.']);
307  unset($this->menuConfig['special.']['value.']);
308  }
309  }
310 
314  public function ‪prepareLevelConfiguration()
315  {
316  $this->menuLevelConfig['stdWrap.']['cObject.'] = array_replace_recursive(
317  $this->menuLevelConfig['stdWrap.']['cObject.'],
318  [
319  '20.' => [
320  'field' => $this->menuTitleField,
321  ]
322  ]
323  );
324  }
325 
329  public function ‪prepareLevelLanguageConfiguration()
330  {
331  if ($this->menuConfig['special'] === 'language') {
332  $languageUids = $this->menuConfig['special.']['value'];
333  if ($this->menuConfig['special.']['value'] === 'auto') {
334  $site = $this->‪getCurrentSite();
335  $languageUids = implode(',', array_keys($site->getLanguages()));
336  }
337  $this->menuLevelConfig['stdWrap.']['cObject.'] = array_replace_recursive(
338  $this->menuLevelConfig['stdWrap.']['cObject.'],
339  [
340  '60' => 'TEXT',
341  '60.' => [
342  'value' => '1',
343  'wrap' => ',"available":|'
344  ],
345  '70' => 'TEXT',
346  '70.' => [
347  'value' => $languageUids,
348  'listNum.' => [
349  'stdWrap.' => [
350  'data' => 'register:count_HMENU_MENUOBJ',
351  'wrap' => '|-1'
352  ],
353  'splitChar' => ','
354  ],
355  'wrap' => ',"languageUid":"|"'
356  ]
357  ]
358  );
359  }
360  }
361 
365  public function ‪buildConfiguration()
366  {
367  for ($i = 1; $i <= ‪$this->menuLevels; $i++) {
368  $this->menuConfig[$i] = 'TMENU';
369  $this->menuConfig[$i . '.']['IProcFunc'] = 'TYPO3\CMS\Frontend\DataProcessing\MenuProcessor->replacePlaceholderInRenderedMenuItem';
370  if ($i > 1) {
371  $this->menuConfig[$i . '.']['stdWrap.']['wrap'] = ',"children": [|]';
372  }
373  if (array_key_exists('showAccessRestrictedPages', $this->menuConfig)) {
374  $this->menuConfig[$i . '.']['showAccessRestrictedPages'] = $this->menuConfig['showAccessRestrictedPages'];
375  if (array_key_exists('showAccessRestrictedPages.', $this->menuConfig)
376  && is_array($this->menuConfig['showAccessRestrictedPages.'])) {
377  $this->menuConfig[$i . '.']['showAccessRestrictedPages.'] = $this->menuConfig['showAccessRestrictedPages.'];
378  }
379  }
380  $this->menuConfig[$i . '.']['expAll'] = ‪$this->menuExpandAll;
381  $this->menuConfig[$i . '.']['alternativeSortingField'] = ‪$this->menuAlternativeSortingField;
382  $this->menuConfig[$i . '.']['NO'] = '1';
383  $this->menuConfig[$i . '.']['NO.'] = ‪$this->menuLevelConfig;
384  if ($this->menuIncludeSpacer) {
385  $this->menuConfig[$i . '.']['SPC'] = '1';
386  $this->menuConfig[$i . '.']['SPC.'] = $this->menuConfig[$i . '.']['NO.'];
387  $this->menuConfig[$i . '.']['SPC.']['stdWrap.']['cObject.']['50.']['value'] = '1';
388  }
389  $this->menuConfig[$i . '.']['IFSUB'] = '1';
390  $this->menuConfig[$i . '.']['IFSUB.'] = $this->menuConfig[$i . '.']['NO.'];
391  $this->menuConfig[$i . '.']['ACT'] = '1';
392  $this->menuConfig[$i . '.']['ACT.'] = $this->menuConfig[$i . '.']['NO.'];
393  $this->menuConfig[$i . '.']['ACT.']['stdWrap.']['cObject.']['30.']['value'] = '1';
394  $this->menuConfig[$i . '.']['ACTIFSUB'] = '1';
395  $this->menuConfig[$i . '.']['ACTIFSUB.'] = $this->menuConfig[$i . '.']['ACT.'];
396  $this->menuConfig[$i . '.']['CUR'] = '1';
397  $this->menuConfig[$i . '.']['CUR.'] = $this->menuConfig[$i . '.']['ACT.'];
398  $this->menuConfig[$i . '.']['CUR.']['stdWrap.']['cObject.']['40.']['value'] = '1';
399  $this->menuConfig[$i . '.']['CURIFSUB'] = '1';
400  $this->menuConfig[$i . '.']['CURIFSUB.'] = $this->menuConfig[$i . '.']['CUR.'];
401  if ($this->menuConfig['special'] === 'language') {
402  $this->menuConfig[$i . '.']['USERDEF1'] = $this->menuConfig[$i . '.']['NO'];
403  $this->menuConfig[$i . '.']['USERDEF1.'] = $this->menuConfig[$i . '.']['NO.'];
404  $this->menuConfig[$i . '.']['USERDEF1.']['stdWrap.']['cObject.']['60.']['value'] = '0';
405  $this->menuConfig[$i . '.']['USERDEF2'] = $this->menuConfig[$i . '.']['ACT'];
406  $this->menuConfig[$i . '.']['USERDEF2.'] = $this->menuConfig[$i . '.']['ACT.'];
407  $this->menuConfig[$i . '.']['USERDEF2.']['stdWrap.']['cObject.']['60.']['value'] = '0';
408  }
409  }
410  }
411 
419  public function ‪process(ContentObjectRenderer ‪$cObj, array $contentObjectConfiguration, array ‪$processorConfiguration, array $processedData)
420  {
421  $this->cObj = ‪$cObj;
422  $this->processorConfiguration = ‪$processorConfiguration;
423 
424  // Get Configuration
425  $this->menuLevels = (int)$this->‪getConfigurationValue('levels') ?: 1;
426  $this->menuExpandAll = (int)$this->‪getConfigurationValue('expandAll');
427  $this->menuIncludeSpacer = (int)$this->‪getConfigurationValue('includeSpacer');
428  $this->menuTargetVariableName = $this->‪getConfigurationValue('as');
429  $this->menuTitleField = $this->‪getConfigurationValue('titleField');
430  $this->menuAlternativeSortingField = $this->‪getConfigurationValue('alternativeSortingField');
431 
432  // Validate Configuration
433  $this->‪validateConfiguration();
434 
435  // Build Configuration
436  $this->‪prepareConfiguration();
439  $this->‪buildConfiguration();
440 
441  // Process Configuration
442  $menuContentObject = ‪$cObj->‪getContentObject('HMENU');
443  $renderedMenu = $menuContentObject->‪render($this->menuConfig);
444  if (!$renderedMenu) {
445  return $processedData;
446  }
447 
448  // Process menu
449  $menu = json_decode($renderedMenu, true);
450  $processedMenu = [];
451 
452  foreach ($menu as $key => $page) {
453  $processedMenu[$key] = $this->‪processAdditionalDataProcessors($page, ‪$processorConfiguration);
454  }
455 
456  // Return processed data
457  $processedData[‪$this->menuTargetVariableName] = $processedMenu;
458  return $processedData;
459  }
460 
469  {
470  if (is_array($page['children'])) {
471  foreach ($page['children'] as $key => $item) {
472  $page['children'][$key] = $this->‪processAdditionalDataProcessors($item, ‪$processorConfiguration);
473  }
474  }
476  $recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
477  $recordContentObjectRenderer->start($page['data'], 'pages');
478  $processedPage = $this->contentDataProcessor->process($recordContentObjectRenderer, ‪$processorConfiguration, $page);
479  return $processedPage;
480  }
481 
487  public function ‪getDataAsJson()
488  {
489  return $this->‪jsonEncode($this->cObj->data);
490  }
491 
499  public function ‪jsonEncodeUserFunc($content, $conf)
500  {
501  $content = $this->‪jsonEncode($content);
502  return $content;
503  }
504 
511  public function ‪jsonEncode($value)
512  {
513  return json_encode($value, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
514  }
515 
523  public function ‪replacePlaceholderInRenderedMenuItem($menuItem, $conf)
524  {
525  $link = $this->‪jsonEncode($menuItem['linkHREF']['HREF']);
526  $target = $this->‪jsonEncode($menuItem['linkHREF']['TARGET']);
527 
528  $menuItem['parts']['title'] = str_replace(self::LINK_PLACEHOLDER, $link, $menuItem['parts']['title']);
529  $menuItem['parts']['title'] = str_replace(self::TARGET_PLACEHOLDER, $target, $menuItem['parts']['title']);
530 
531  return $menuItem;
532  }
533 
539  protected function ‪getCurrentSite(): ‪SiteInterface
540  {
541  try {
542  return GeneralUtility::makeInstance(SiteFinder::class)
543  ->getSiteByPageId((int)$this->‪getTypoScriptFrontendController()->id);
544  } catch (SiteNotFoundException $e) {
545  return new NullSite();
546  }
547  }
548 
552  protected function ‪getTypoScriptFrontendController()
553  {
554  return ‪$GLOBALS['TSFE'];
555  }
556 }
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$removeConfigurationKeysForHmenu
‪array $removeConfigurationKeysForHmenu
Definition: MenuProcessor.php:132
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:26
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuExpandAll
‪int $menuExpandAll
Definition: MenuProcessor.php:219
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getTypoScriptFrontendController
‪TypoScriptFrontendController getTypoScriptFrontendController()
Definition: MenuProcessor.php:538
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$cObj
‪ContentObjectRenderer $cObj
Definition: MenuProcessor.php:73
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\jsonEncode
‪string jsonEncode($value)
Definition: MenuProcessor.php:497
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$contentDataProcessor
‪ContentDataProcessor $contentDataProcessor
Definition: MenuProcessor.php:239
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\validateConfiguration
‪validateConfiguration()
Definition: MenuProcessor.php:265
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\prepareLevelConfiguration
‪prepareLevelConfiguration()
Definition: MenuProcessor.php:300
‪TYPO3\CMS\Frontend\ContentObject\ContentDataProcessor
Definition: ContentDataProcessor.php:25
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuLevelConfig
‪array $menuLevelConfig
Definition: MenuProcessor.php:154
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\buildConfiguration
‪buildConfiguration()
Definition: MenuProcessor.php:351
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$allowedConfigurationKeys
‪array $allowedConfigurationKeys
Definition: MenuProcessor.php:86
‪TYPO3\CMS\Core\Site\Entity\NullSite
Definition: NullSite.php:32
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:26
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\prepareLevelLanguageConfiguration
‪prepareLevelLanguageConfiguration()
Definition: MenuProcessor.php:315
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\TARGET_PLACEHOLDER
‪const TARGET_PLACEHOLDER
Definition: MenuProcessor.php:67
‪TYPO3\CMS\Frontend\DataProcessing
Definition: CommaSeparatedValueProcessor.php:16
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\jsonEncodeUserFunc
‪string jsonEncodeUserFunc($content, $conf)
Definition: MenuProcessor.php:485
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuConfig
‪array $menuConfig
Definition: MenuProcessor.php:148
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
Definition: MenuProcessor.php:65
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getContentObject
‪AbstractContentObject null getContentObject($name)
Definition: ContentObjectRenderer.php:754
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuTargetVariableName
‪string $menuTargetVariableName
Definition: MenuProcessor.php:235
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\prepareConfiguration
‪prepareConfiguration()
Definition: MenuProcessor.php:281
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$processorConfiguration
‪array $processorConfiguration
Definition: MenuProcessor.php:79
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuLevels
‪int $menuLevels
Definition: MenuProcessor.php:215
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getDataAsJson
‪string getDataAsJson()
Definition: MenuProcessor.php:473
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getConfigurationValue
‪string getConfigurationValue($key)
Definition: MenuProcessor.php:255
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\LINK_PLACEHOLDER
‪const LINK_PLACEHOLDER
Definition: MenuProcessor.php:66
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuIncludeSpacer
‪int $menuIncludeSpacer
Definition: MenuProcessor.php:223
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuAlternativeSortingField
‪string $menuAlternativeSortingField
Definition: MenuProcessor.php:231
‪TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface
Definition: DataProcessorInterface.php:23
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:98
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuDefaults
‪array $menuDefaults
Definition: MenuProcessor.php:205
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\process
‪array process(ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData)
Definition: MenuProcessor.php:405
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:97
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\__construct
‪__construct()
Definition: MenuProcessor.php:244
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getCurrentSite
‪SiteInterface getCurrentSite()
Definition: MenuProcessor.php:525
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuTitleField
‪string $menuTitleField
Definition: MenuProcessor.php:227
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject\render
‪string render($conf=[])
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\replacePlaceholderInRenderedMenuItem
‪array replacePlaceholderInRenderedMenuItem($menuItem, $conf)
Definition: MenuProcessor.php:509
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\processAdditionalDataProcessors
‪array processAdditionalDataProcessors($page, $processorConfiguration)
Definition: MenuProcessor.php:454