Skip to content
Snippets Groups Projects
Commit a396dadd authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Clean up TMENU code

This change reduces the logic within TMENU in order
to further unify link generation within the menu rendering.

Resolves: #97865
Releases: main
Change-Id: I495b167b7e6e302fc7e8b04757eab1eb8e359528
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75043


Tested-by: default avatarcore-ci <typo3@b13.com>
Tested-by: default avatarNikita Hovratov <nikita.h@live.de>
Tested-by: default avatarOliver Bartsch <bo@cedev.de>
Tested-by: default avatarBenni Mack <benni@typo3.org>
Reviewed-by: default avatarNikita Hovratov <nikita.h@live.de>
Reviewed-by: default avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: default avatarBenni Mack <benni@typo3.org>
parent 3fcd8ae9
Branches
Tags
No related merge requests found
...@@ -24,16 +24,6 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; ...@@ -24,16 +24,6 @@ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
*/ */
class TextMenuContentObject extends AbstractMenuContentObject class TextMenuContentObject extends AbstractMenuContentObject
{ {
protected ?ContentObjectRenderer $cObjectForCurrentMenu = null;
protected string $menuContent = '';
protected int $totalMenuItems = 0;
/**
* @var array[]
*/
protected array $subMenuObjSuffixes = [];
/** /**
* Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item. * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
* An instance of ContentObjectRenderer is also made and for each menu item rendered it is loaded with * An instance of ContentObjectRenderer is also made and for each menu item rendered it is loaded with
...@@ -48,46 +38,42 @@ class TextMenuContentObject extends AbstractMenuContentObject ...@@ -48,46 +38,42 @@ class TextMenuContentObject extends AbstractMenuContentObject
} }
$frontendController = $this->getTypoScriptFrontendController(); $frontendController = $this->getTypoScriptFrontendController();
$this->cObjectForCurrentMenu = GeneralUtility::makeInstance(ContentObjectRenderer::class); $cObjectForCurrentMenu = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$this->menuContent = ''; $menuContent = '';
$this->totalMenuItems = count($this->result);
$typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class); $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
$this->subMenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes'] ?? null], $this->totalMenuItems); $subMenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes'] ?? null], count($this->result));
$explicitSpacerRenderingEnabled = ($this->mconf['SPC'] ?? false);
foreach ($this->result as $key => $val) { foreach ($this->result as $key => $val) {
$frontendController->register['count_HMENU_MENUOBJ']++; $frontendController->register['count_HMENU_MENUOBJ']++;
$frontendController->register['count_MENUOBJ']++; $frontendController->register['count_MENUOBJ']++;
// Initialize the cObj with the page record of the menu item // Initialize the cObj with the page record of the menu item
$this->cObjectForCurrentMenu->start($this->menuArr[$key], 'pages', $this->request); $cObjectForCurrentMenu->start($this->menuArr[$key], 'pages', $this->request);
$this->I = []; $this->I = [];
$this->I['key'] = $key; $this->I['key'] = $key;
$this->I['val'] = $val; $this->I['val'] = $val;
$this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'] ?? '', $this->menuArr[$key]['nav_title'] ?? ''); $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'] ?? '', $this->menuArr[$key]['nav_title'] ?? '');
$this->I['title.'] = $this->I['val']['stdWrap.'] ?? []; $this->I['title.'] = $this->I['val']['stdWrap.'] ?? [];
$this->I['title'] = $this->cObjectForCurrentMenu->stdWrapValue('title', $this->I ?? []); $this->I['title'] = $cObjectForCurrentMenu->stdWrapValue('title', $this->I ?? []);
$this->I['uid'] = $this->menuArr[$key]['uid'] ?? 0; $this->I['uid'] = $this->menuArr[$key]['uid'] ?? 0;
$this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'] ?? 0; $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'] ?? 0;
$this->I['pid'] = $this->menuArr[$key]['pid'] ?? 0; $this->I['pid'] = $this->menuArr[$key]['pid'] ?? 0;
$this->I['spacer'] = $this->menuArr[$key]['isSpacer'] ?? false; $this->I['spacer'] = $this->menuArr[$key]['isSpacer'] ?? false;
// Make link tag // Make link tag
$this->I['val']['additionalParams'] = $this->cObjectForCurrentMenu->stdWrapValue('additionalParams', $this->I['val']); $this->I['val']['additionalParams'] = $cObjectForCurrentMenu->stdWrapValue('additionalParams', $this->I['val']);
$this->I['linkHREF'] = $this->link((int)$key, (string)($this->I['val']['altTarget'] ?? ''), ($this->mconf['forceTypeValue'] ?? '')); $this->I['linkHREF'] = $this->link((int)$key, (string)($this->I['val']['altTarget'] ?? ''), ($this->mconf['forceTypeValue'] ?? ''));
if (empty($this->I['linkHREF'])) { if (empty($this->I['linkHREF'])) {
$this->I['val']['doNotLinkIt'] = 1; $this->I['val']['doNotLinkIt'] = 1;
} }
// Title attribute of links: // Title attribute of links
$titleAttrValue = $this->cObjectForCurrentMenu->stdWrapValue('ATagTitle', $this->I['val']); $titleAttrValue = $cObjectForCurrentMenu->stdWrapValue('ATagTitle', $this->I['val']);
if ($titleAttrValue !== '') { if ($titleAttrValue !== '') {
$this->I['linkHREF']['title'] = $titleAttrValue; $this->I['linkHREF']['title'] = $titleAttrValue;
} }
// stdWrap for doNotLinkIt $this->I['val']['doNotLinkIt'] = (bool)$cObjectForCurrentMenu->stdWrapValue('doNotLinkIt', $this->I['val']);
$this->I['val']['doNotLinkIt'] = $this->cObjectForCurrentMenu->stdWrapValue('doNotLinkIt', $this->I['val']);
// Compile link tag // Compile link tag
if (!$this->I['val']['doNotLinkIt']) { if (!$this->I['spacer'] && !$this->I['val']['doNotLinkIt']) {
$this->I['val']['doNotLinkIt'] = 0;
}
if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt'] != 1) {
$this->setATagParts(); $this->setATagParts();
} else { } else {
$this->I['A1'] = ''; $this->I['A1'] = '';
...@@ -102,17 +88,17 @@ class TextMenuContentObject extends AbstractMenuContentObject ...@@ -102,17 +88,17 @@ class TextMenuContentObject extends AbstractMenuContentObject
$wrapPartsAfter = explode('|', $this->I['val']['linkWrap'] ?? ''); $wrapPartsAfter = explode('|', $this->I['val']['linkWrap'] ?? '');
} }
if (($this->I['val']['stdWrap2'] ?? false) || isset($this->I['val']['stdWrap2.'])) { if (($this->I['val']['stdWrap2'] ?? false) || isset($this->I['val']['stdWrap2.'])) {
$stdWrap2 = (string)(isset($this->I['val']['stdWrap2.']) ? $this->cObjectForCurrentMenu->stdWrap('|', $this->I['val']['stdWrap2.']) : '|'); $stdWrap2 = (string)(isset($this->I['val']['stdWrap2.']) ? $cObjectForCurrentMenu->stdWrap('|', $this->I['val']['stdWrap2.']) : '|');
$wrapPartsStdWrap = explode($this->I['val']['stdWrap2'] ?: '|', $stdWrap2); $wrapPartsStdWrap = explode($this->I['val']['stdWrap2'] ?: '|', $stdWrap2);
} else { } else {
$wrapPartsStdWrap = ['', '']; $wrapPartsStdWrap = ['', ''];
} }
// Make before, middle and after parts // Make before, middle and after parts
$this->I['parts'] = []; $this->I['parts'] = [];
$this->I['parts']['before'] = $this->getBeforeAfter('before'); $this->I['parts']['before'] = $this->getBeforeAfter('before', $cObjectForCurrentMenu);
$this->I['parts']['stdWrap2_begin'] = $wrapPartsStdWrap[0]; $this->I['parts']['stdWrap2_begin'] = $wrapPartsStdWrap[0];
// stdWrap for doNotShowLink // stdWrap for doNotShowLink
$this->I['val']['doNotShowLink'] = $this->cObjectForCurrentMenu->stdWrapValue('doNotShowLink', $this->I['val']); $this->I['val']['doNotShowLink'] = $cObjectForCurrentMenu->stdWrapValue('doNotShowLink', $this->I['val']);
if (!$this->I['val']['doNotShowLink']) { if (!$this->I['val']['doNotShowLink']) {
$this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0] ?? ''; $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0] ?? '';
$this->I['parts']['ATag_begin'] = $this->I['A1']; $this->I['parts']['ATag_begin'] = $this->I['A1'];
...@@ -123,37 +109,34 @@ class TextMenuContentObject extends AbstractMenuContentObject ...@@ -123,37 +109,34 @@ class TextMenuContentObject extends AbstractMenuContentObject
$this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1] ?? ''; $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1] ?? '';
} }
$this->I['parts']['stdWrap2_end'] = $wrapPartsStdWrap[1]; $this->I['parts']['stdWrap2_end'] = $wrapPartsStdWrap[1];
$this->I['parts']['after'] = $this->getBeforeAfter('after'); $this->I['parts']['after'] = $this->getBeforeAfter('after', $cObjectForCurrentMenu);
// Passing I to a user function // Passing I to a user function
if ($this->mconf['IProcFunc'] ?? false) { if ($this->mconf['IProcFunc'] ?? false) {
$this->I = $this->userProcess('IProcFunc', $this->I); $this->I = $this->userProcess('IProcFunc', $this->I);
} }
// Merge parts + beforeAllWrap // Merge parts + beforeAllWrap
$this->I['theItem'] = implode('', $this->I['parts']); $this->I['theItem'] = implode('', $this->I['parts']);
// allWrap: $allWrap = $cObjectForCurrentMenu->stdWrapValue('allWrap', $this->I['val']);
$allWrap = $this->cObjectForCurrentMenu->stdWrapValue('allWrap', $this->I['val']); $this->I['theItem'] = $cObjectForCurrentMenu->wrap($this->I['theItem'], $allWrap);
$this->I['theItem'] = $this->cObjectForCurrentMenu->wrap($this->I['theItem'], $allWrap);
if ($this->I['val']['subst_elementUid'] ?? false) { if ($this->I['val']['subst_elementUid'] ?? false) {
$this->I['theItem'] = str_replace('{elementUid}', (string)$this->I['uid'], $this->I['theItem']); $this->I['theItem'] = str_replace('{elementUid}', (string)$this->I['uid'], $this->I['theItem']);
} }
// allStdWrap:
if (is_array($this->I['val']['allStdWrap.'] ?? null)) { if (is_array($this->I['val']['allStdWrap.'] ?? null)) {
$this->I['theItem'] = $this->cObjectForCurrentMenu->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']); $this->I['theItem'] = $cObjectForCurrentMenu->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
} }
$explicitSpacerRenderingEnabled = ($this->mconf['SPC'] ?? false);
$isSpacerPage = $this->I['spacer'] ?? false; $isSpacerPage = $this->I['spacer'] ?? false;
// If rendering of SPACERs is enabled, also allow rendering submenus with Spacers // If rendering of SPACERs is enabled, also allow rendering submenus with Spacers
if (!$isSpacerPage || $explicitSpacerRenderingEnabled) { if (!$isSpacerPage || $explicitSpacerRenderingEnabled) {
// Add part to the accumulated result + fetch submenus // Add part to the accumulated result + fetch submenus
$this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->subMenuObjSuffixes[$key]['sOSuffix'] ?? '', $key); $this->I['theItem'] .= $this->subMenu($this->I['uid'], $subMenuObjSuffixes[$key]['sOSuffix'] ?? '', $key);
} }
$part = $this->cObjectForCurrentMenu->stdWrapValue('wrapItemAndSub', $this->I['val']); $part = $cObjectForCurrentMenu->stdWrapValue('wrapItemAndSub', $this->I['val']);
$this->menuContent .= $part ? $this->cObjectForCurrentMenu->wrap($this->I['theItem'], $part) : $this->I['theItem']; $menuContent .= $part ? $cObjectForCurrentMenu->wrap($this->I['theItem'], $part) : $this->I['theItem'];
} }
if (is_array($this->mconf['stdWrap.'] ?? null)) { if (is_array($this->mconf['stdWrap.'] ?? null)) {
$this->menuContent = (string)$this->cObjectForCurrentMenu->stdWrap($this->menuContent, $this->mconf['stdWrap.']); $menuContent = (string)$cObjectForCurrentMenu->stdWrap($menuContent, $this->mconf['stdWrap.']);
} }
return $this->cObjectForCurrentMenu->wrap($this->menuContent, $this->mconf['wrap'] ?? ''); return $cObjectForCurrentMenu->wrap($menuContent, $this->mconf['wrap'] ?? '');
} }
/** /**
...@@ -165,13 +148,14 @@ class TextMenuContentObject extends AbstractMenuContentObject ...@@ -165,13 +148,14 @@ class TextMenuContentObject extends AbstractMenuContentObject
* - afterWrap * - afterWrap
* *
* @param string $pref Can be "before" or "after" and determines which kind of stdWrap to process (basically this is the prefix of the TypoScript properties that are read from the ->I['val'] array * @param string $pref Can be "before" or "after" and determines which kind of stdWrap to process (basically this is the prefix of the TypoScript properties that are read from the ->I['val'] array
* @param ContentObjectRenderer $cObjectForCurrentMenu
* @return string The resulting HTML * @return string The resulting HTML
*/ */
protected function getBeforeAfter(string $pref): string protected function getBeforeAfter(string $pref, ContentObjectRenderer $cObjectForCurrentMenu): string
{ {
$processedPref = $this->cObjectForCurrentMenu->stdWrapValue($pref, $this->I['val']); $processedPref = $cObjectForCurrentMenu->stdWrapValue($pref, $this->I['val']);
if (isset($this->I['val'][$pref . 'Wrap'])) { if (isset($this->I['val'][$pref . 'Wrap'])) {
return $this->cObjectForCurrentMenu->wrap($processedPref, $this->I['val'][$pref . 'Wrap']); return $cObjectForCurrentMenu->wrap($processedPref, $this->I['val'][$pref . 'Wrap']);
} }
return $processedPref; return $processedPref;
} }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment