‪TYPO3CMS  9.5
MenuProcessor.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 
24 
62 {
63  const ‪LINK_PLACEHOLDER = '###LINKPLACEHOLDER###';
64  const ‪TARGET_PLACEHOLDER = '###TARGETPLACEHOLDER###';
65 
71  public ‪$cObj;
72 
79 
87  'cache_period',
88  'entryLevel',
89  'entryLevel.',
90  'special',
91  'special.',
92  'minItems',
93  'minItems.',
94  'maxItems',
95  'maxItems.',
96  'begin',
97  'begin.',
98  'alternativeSortingField',
99  'alternativeSortingField.',
100  'showAccessRestrictedPages',
101  'showAccessRestrictedPages.',
102  'excludeUidList',
103  'excludeUidList.',
104  'excludeDoktypes',
105  'includeNotInMenu',
106  'includeNotInMenu.',
107  'alwaysActivePIDlist',
108  'alwaysActivePIDlist.',
109  'protectLvar',
110  'addQueryString',
111  'addQueryString.',
112  'if',
113  'if.',
114  'levels',
115  'levels.',
116  'expandAll',
117  'expandAll.',
118  'includeSpacer',
119  'includeSpacer.',
120  'as',
121  'titleField',
122  'titleField.',
123  'dataProcessing',
124  'dataProcessing.'
125  ];
126 
134  'levels',
135  'levels.',
136  'expandAll',
137  'expandAll.',
138  'includeSpacer',
139  'includeSpacer.',
140  'as',
141  'titleField',
142  'titleField.',
143  'dataProcessing',
144  'dataProcessing.'
145  ];
146 
150  protected ‪$menuConfig = [
151  'wrap' => '[|]'
152  ];
153 
157  protected ‪$menuLevelConfig = [
158  'doNotLinkIt' => '1',
159  'wrapItemAndSub' => '{|}, |*| {|}, |*| {|}',
160  'stdWrap.' => [
161  'cObject' => 'COA',
162  'cObject.' => [
163  '10' => 'USER',
164  '10.' => [
165  'userFunc' => 'TYPO3\CMS\Frontend\DataProcessing\MenuProcessor->getDataAsJson',
166  'stdWrap.' => [
167  'wrap' => '"data":|'
168  ]
169  ],
170  '20' => 'TEXT',
171  '20.' => [
172  'field' => 'nav_title // title',
173  'trim' => '1',
174  'wrap' => ',"title":|',
175  'preUserFunc' => 'TYPO3\CMS\Frontend\DataProcessing\MenuProcessor->jsonEncodeUserFunc'
176  ],
177  '21' => 'TEXT',
178  '21.' => [
179  'value' => ‪self::LINK_PLACEHOLDER,
180  'wrap' => ',"link":|',
181  ],
182  '22' => 'TEXT',
183  '22.' => [
184  'value' => ‪self::TARGET_PLACEHOLDER,
185  'wrap' => ',"target":|',
186  ],
187  '30' => 'TEXT',
188  '30.' => [
189  'value' => '0',
190  'wrap' => ',"active":|'
191  ],
192  '40' => 'TEXT',
193  '40.' => [
194  'value' => '0',
195  'wrap' => ',"current":|'
196  ],
197  '50' => 'TEXT',
198  '50.' => [
199  'value' => '0',
200  'wrap' => ',"spacer":|'
201  ]
202  ]
203  ]
204  ];
205 
209  public ‪$menuDefaults = [
210  'levels' => 1,
211  'expandAll' => 1,
212  'includeSpacer' => 0,
213  'as' => 'menu',
214  'titleField' => 'nav_title // title'
215  ];
216 
220  protected ‪$menuLevels;
221 
225  protected ‪$menuExpandAll;
226 
230  protected ‪$menuIncludeSpacer;
231 
235  protected ‪$menuTitleField;
236 
241 
245  protected ‪$menuTargetVariableName;
246 
250  protected ‪$contentDataProcessor;
251 
255  public function ‪__construct()
256  {
257  $this->contentDataProcessor = GeneralUtility::makeInstance(ContentDataProcessor::class);
258  }
259 
266  protected function ‪getConfigurationValue($key)
267  {
268  return $this->cObj->stdWrapValue($key, $this->processorConfiguration, $this->menuDefaults[$key]);
269  }
270 
276  public function ‪validateConfiguration()
277  {
278  $invalidArguments = [];
279  foreach ($this->processorConfiguration as $key => $value) {
280  if (!in_array($key, $this->allowedConfigurationKeys)) {
281  $invalidArguments[str_replace('.', '', $key)] = $key;
282  }
283  }
284  if (!empty($invalidArguments)) {
285  throw new \InvalidArgumentException('MenuProcessor Configuration contains invalid Arguments: ' . implode(', ', $invalidArguments), 1478806566);
286  }
287  }
288 
292  public function ‪prepareConfiguration()
293  {
294  $this->menuConfig += ‪$this->processorConfiguration;
295  // Filter configuration
296  foreach ($this->menuConfig as $key => $value) {
297  if (in_array($key, $this->removeConfigurationKeysForHmenu)) {
298  unset($this->menuConfig[$key]);
299  }
300  }
301  // Process special value
302  if (isset($this->menuConfig['special.']['value.'])) {
303  $this->menuConfig['special.']['value'] = $this->cObj->stdWrap($this->menuConfig['special.']['value'], $this->menuConfig['special.']['value.']);
304  unset($this->menuConfig['special.']['value.']);
305  }
306  }
307 
311  public function ‪prepareLevelConfiguration()
312  {
313  $this->menuLevelConfig['stdWrap.']['cObject.'] = array_replace_recursive(
314  $this->menuLevelConfig['stdWrap.']['cObject.'],
315  [
316  '20.' => [
317  'field' => $this->menuTitleField,
318  ]
319  ]
320  );
321  }
322 
326  public function ‪prepareLevelLanguageConfiguration()
327  {
328  if ($this->menuConfig['special'] === 'language') {
329  $languageUids = $this->menuConfig['special.']['value'];
330  if ($this->menuConfig['special.']['value'] === 'auto') {
331  $site = $this->‪getCurrentSite();
332  $languageUids = implode(',', array_keys($site->getLanguages()));
333  }
334  $this->menuLevelConfig['stdWrap.']['cObject.'] = array_replace_recursive(
335  $this->menuLevelConfig['stdWrap.']['cObject.'],
336  [
337  '60' => 'TEXT',
338  '60.' => [
339  'value' => '1',
340  'wrap' => ',"available":|'
341  ],
342  '70' => 'TEXT',
343  '70.' => [
344  'value' => $languageUids,
345  'listNum.' => [
346  'stdWrap.' => [
347  'data' => 'register:count_HMENU_MENUOBJ',
348  'wrap' => '|-1'
349  ],
350  'splitChar' => ','
351  ],
352  'wrap' => ',"languageUid":"|"'
353  ]
354  ]
355  );
356  }
357  }
358 
362  public function ‪buildConfiguration()
363  {
364  for ($i = 1; $i <= ‪$this->menuLevels; $i++) {
365  $this->menuConfig[$i] = 'TMENU';
366  $this->menuConfig[$i . '.']['IProcFunc'] = 'TYPO3\CMS\Frontend\DataProcessing\MenuProcessor->replacePlaceholderInRenderedMenuItem';
367  if ($i > 1) {
368  $this->menuConfig[$i . '.']['stdWrap.']['wrap'] = ',"children": [|]';
369  }
370  if (array_key_exists('showAccessRestrictedPages', $this->menuConfig)) {
371  $this->menuConfig[$i . '.']['showAccessRestrictedPages'] = $this->menuConfig['showAccessRestrictedPages'];
372  if (array_key_exists('showAccessRestrictedPages.', $this->menuConfig)
373  && is_array($this->menuConfig['showAccessRestrictedPages.'])) {
374  $this->menuConfig[$i . '.']['showAccessRestrictedPages.'] = $this->menuConfig['showAccessRestrictedPages.'];
375  }
376  }
377  $this->menuConfig[$i . '.']['expAll'] = ‪$this->menuExpandAll;
378  $this->menuConfig[$i . '.']['alternativeSortingField'] = ‪$this->menuAlternativeSortingField;
379  $this->menuConfig[$i . '.']['NO'] = '1';
380  $this->menuConfig[$i . '.']['NO.'] = ‪$this->menuLevelConfig;
381  if ($this->menuIncludeSpacer) {
382  $this->menuConfig[$i . '.']['SPC'] = '1';
383  $this->menuConfig[$i . '.']['SPC.'] = $this->menuConfig[$i . '.']['NO.'];
384  $this->menuConfig[$i . '.']['SPC.']['stdWrap.']['cObject.']['50.']['value'] = '1';
385  }
386  $this->menuConfig[$i . '.']['IFSUB'] = '1';
387  $this->menuConfig[$i . '.']['IFSUB.'] = $this->menuConfig[$i . '.']['NO.'];
388  $this->menuConfig[$i . '.']['ACT'] = '1';
389  $this->menuConfig[$i . '.']['ACT.'] = $this->menuConfig[$i . '.']['NO.'];
390  $this->menuConfig[$i . '.']['ACT.']['stdWrap.']['cObject.']['30.']['value'] = '1';
391  $this->menuConfig[$i . '.']['ACTIFSUB'] = '1';
392  $this->menuConfig[$i . '.']['ACTIFSUB.'] = $this->menuConfig[$i . '.']['ACT.'];
393  $this->menuConfig[$i . '.']['CUR'] = '1';
394  $this->menuConfig[$i . '.']['CUR.'] = $this->menuConfig[$i . '.']['ACT.'];
395  $this->menuConfig[$i . '.']['CUR.']['stdWrap.']['cObject.']['40.']['value'] = '1';
396  $this->menuConfig[$i . '.']['CURIFSUB'] = '1';
397  $this->menuConfig[$i . '.']['CURIFSUB.'] = $this->menuConfig[$i . '.']['CUR.'];
398  if ($this->menuConfig['special'] === 'language') {
399  $this->menuConfig[$i . '.']['USERDEF1'] = $this->menuConfig[$i . '.']['NO'];
400  $this->menuConfig[$i . '.']['USERDEF1.'] = $this->menuConfig[$i . '.']['NO.'];
401  $this->menuConfig[$i . '.']['USERDEF1.']['stdWrap.']['cObject.']['60.']['value'] = '0';
402  $this->menuConfig[$i . '.']['USERDEF2'] = $this->menuConfig[$i . '.']['ACT'];
403  $this->menuConfig[$i . '.']['USERDEF2.'] = $this->menuConfig[$i . '.']['ACT.'];
404  $this->menuConfig[$i . '.']['USERDEF2.']['stdWrap.']['cObject.']['60.']['value'] = '0';
405  }
406  }
407  }
408 
416  public function ‪process(ContentObjectRenderer ‪$cObj, array $contentObjectConfiguration, array ‪$processorConfiguration, array $processedData)
417  {
418  $this->cObj = ‪$cObj;
419  $this->processorConfiguration = ‪$processorConfiguration;
420 
421  // Get Configuration
422  $this->menuLevels = (int)$this->‪getConfigurationValue('levels') ?: 1;
423  $this->menuExpandAll = (int)$this->‪getConfigurationValue('expandAll');
424  $this->menuIncludeSpacer = (int)$this->‪getConfigurationValue('includeSpacer');
425  $this->menuTargetVariableName = $this->‪getConfigurationValue('as');
426  $this->menuTitleField = $this->‪getConfigurationValue('titleField');
427  $this->menuAlternativeSortingField = $this->‪getConfigurationValue('alternativeSortingField');
428 
429  // Validate Configuration
430  $this->‪validateConfiguration();
431 
432  // Build Configuration
433  $this->‪prepareConfiguration();
436  $this->‪buildConfiguration();
437 
438  // Process Configuration
439  $menuContentObject = ‪$cObj->‪getContentObject('HMENU');
440  $renderedMenu = $menuContentObject->‪render($this->menuConfig);
441  if (!$renderedMenu) {
442  return $processedData;
443  }
444 
445  // Process menu
446  $menu = json_decode($renderedMenu, true);
447  $processedMenu = [];
448 
449  foreach ($menu as $key => $page) {
450  $processedMenu[$key] = $this->‪processAdditionalDataProcessors($page, ‪$processorConfiguration);
451  }
452 
453  // Return processed data
454  $processedData[‪$this->menuTargetVariableName] = $processedMenu;
455  return $processedData;
456  }
457 
466  {
467  if (is_array($page['children'])) {
468  foreach ($page['children'] as $key => $item) {
469  $page['children'][$key] = $this->‪processAdditionalDataProcessors($item, ‪$processorConfiguration);
470  }
471  }
473  $recordContentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
474  $recordContentObjectRenderer->start($page['data'], 'pages');
475  $processedPage = $this->contentDataProcessor->process($recordContentObjectRenderer, ‪$processorConfiguration, $page);
476  return $processedPage;
477  }
478 
484  public function ‪getDataAsJson()
485  {
486  return $this->‪jsonEncode($this->cObj->data);
487  }
488 
496  public function ‪jsonEncodeUserFunc($content, $conf)
497  {
498  $content = $this->‪jsonEncode($content);
499  return $content;
500  }
501 
508  public function ‪jsonEncode($value)
509  {
510  return json_encode($value, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
511  }
512 
520  public function ‪replacePlaceholderInRenderedMenuItem($menuItem, $conf)
521  {
522  $link = $this->‪jsonEncode($menuItem['linkHREF']['HREF']);
523  $target = $this->‪jsonEncode($menuItem['linkHREF']['TARGET']);
524 
525  $menuItem['parts']['title'] = str_replace(self::LINK_PLACEHOLDER, $link, $menuItem['parts']['title']);
526  $menuItem['parts']['title'] = str_replace(self::TARGET_PLACEHOLDER, $target, $menuItem['parts']['title']);
527 
528  return $menuItem;
529  }
530 
537  protected function ‪getCurrentSite(): ‪SiteInterface
538  {
539  $matcher = GeneralUtility::makeInstance(SiteMatcher::class);
540  return $matcher->matchByPageId((int)$this->‪getTypoScriptFrontendController()->id);
541  }
542 
546  protected function ‪getTypoScriptFrontendController()
547  {
548  return ‪$GLOBALS['TSFE'];
549  }
550 }
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$removeConfigurationKeysForHmenu
‪array $removeConfigurationKeysForHmenu
Definition: MenuProcessor.php:129
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:25
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuExpandAll
‪int $menuExpandAll
Definition: MenuProcessor.php:216
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getTypoScriptFrontendController
‪TypoScriptFrontendController getTypoScriptFrontendController()
Definition: MenuProcessor.php:532
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$cObj
‪ContentObjectRenderer $cObj
Definition: MenuProcessor.php:70
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\jsonEncode
‪string jsonEncode($value)
Definition: MenuProcessor.php:494
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$contentDataProcessor
‪ContentDataProcessor $contentDataProcessor
Definition: MenuProcessor.php:236
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\validateConfiguration
‪validateConfiguration()
Definition: MenuProcessor.php:262
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\prepareLevelConfiguration
‪prepareLevelConfiguration()
Definition: MenuProcessor.php:297
‪TYPO3\CMS\Frontend\ContentObject\ContentDataProcessor
Definition: ContentDataProcessor.php:24
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuLevelConfig
‪array $menuLevelConfig
Definition: MenuProcessor.php:151
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\buildConfiguration
‪buildConfiguration()
Definition: MenuProcessor.php:348
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$allowedConfigurationKeys
‪array $allowedConfigurationKeys
Definition: MenuProcessor.php:83
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\prepareLevelLanguageConfiguration
‪prepareLevelLanguageConfiguration()
Definition: MenuProcessor.php:312
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\TARGET_PLACEHOLDER
‪const TARGET_PLACEHOLDER
Definition: MenuProcessor.php:64
‪TYPO3\CMS\Frontend\DataProcessing
Definition: CommaSeparatedValueProcessor.php:2
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\jsonEncodeUserFunc
‪string jsonEncodeUserFunc($content, $conf)
Definition: MenuProcessor.php:482
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuConfig
‪array $menuConfig
Definition: MenuProcessor.php:145
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
Definition: MenuProcessor.php:62
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getContentObject
‪AbstractContentObject null getContentObject($name)
Definition: ContentObjectRenderer.php:748
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuTargetVariableName
‪string $menuTargetVariableName
Definition: MenuProcessor.php:232
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\prepareConfiguration
‪prepareConfiguration()
Definition: MenuProcessor.php:278
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$processorConfiguration
‪array $processorConfiguration
Definition: MenuProcessor.php:76
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuLevels
‪int $menuLevels
Definition: MenuProcessor.php:212
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getDataAsJson
‪string getDataAsJson()
Definition: MenuProcessor.php:470
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getConfigurationValue
‪string getConfigurationValue($key)
Definition: MenuProcessor.php:252
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\LINK_PLACEHOLDER
‪const LINK_PLACEHOLDER
Definition: MenuProcessor.php:63
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuIncludeSpacer
‪int $menuIncludeSpacer
Definition: MenuProcessor.php:220
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuAlternativeSortingField
‪string $menuAlternativeSortingField
Definition: MenuProcessor.php:228
‪TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface
Definition: DataProcessorInterface.php:22
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:97
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuDefaults
‪array $menuDefaults
Definition: MenuProcessor.php:202
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\process
‪array process(ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData)
Definition: MenuProcessor.php:402
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:91
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\__construct
‪__construct()
Definition: MenuProcessor.php:241
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\getCurrentSite
‪SiteInterface getCurrentSite()
Definition: MenuProcessor.php:523
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\$menuTitleField
‪string $menuTitleField
Definition: MenuProcessor.php:224
‪TYPO3\CMS\Core\Routing\SiteMatcher
Definition: SiteMatcher.php:53
‪TYPO3\CMS\Frontend\ContentObject\AbstractContentObject\render
‪string render($conf=[])
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\replacePlaceholderInRenderedMenuItem
‪array replacePlaceholderInRenderedMenuItem($menuItem, $conf)
Definition: MenuProcessor.php:506
‪TYPO3\CMS\Frontend\DataProcessing\MenuProcessor\processAdditionalDataProcessors
‪array processAdditionalDataProcessors($page, $processorConfiguration)
Definition: MenuProcessor.php:451