TextMenuContentObject.php 10 KB
Newer Older
1
<?php
2

3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
7
8
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
9
 *
10
11
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
14
 * The TYPO3 project - inspiring people to share!
 */
15

16
17
namespace TYPO3\CMS\Frontend\ContentObject\Menu;

18
19
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
20

21
22
23
/**
 * Extension class creating text based menus
 */
24
25
26
class TextMenuContentObject extends AbstractMenuContentObject
{
    /**
27
     * Calls processItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
28
29
     * Sets the result for the new "normal state" in $this->result
     *
30
     * @see AbstractMenuContentObject::processItemStates()
31
32
33
     */
    public function generate()
    {
34
        $itemConfiguration = [];
35
36
        $splitCount = count($this->menuArr);
        if ($splitCount) {
37
            $itemConfiguration = $this->processItemStates($splitCount);
38
39
        }
        if (!empty($this->mconf['debugItemConf'])) {
40
41
            echo '<h3>$itemConfiguration:</h3>';
            debug($itemConfiguration);
42
        }
43
        $this->result = $itemConfiguration;
44
    }
45

46
47
48
    /**
     * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
     * During the execution of this function many internal methods prefixed "extProc_" from this class is called and
49
     * many of these are for now dummy functions.
50
51
52
53
54
55
56
57
58
59
     * An instance of ContentObjectRenderer is also made and for each menu item rendered it is loaded with
     * the record for that page so that any stdWrap properties that applies will have the current menu items record available.
     *
     * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
     */
    public function writeMenu()
    {
        if (empty($this->result)) {
            return '';
        }
60

61
62
        $this->WMresult = '';
        $this->WMmenuItems = count($this->result);
63
        $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
64
        $this->WMsubmenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes'] ?? null], $this->WMmenuItems);
65
66
67
68
        foreach ($this->result as $key => $val) {
            $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
            $GLOBALS['TSFE']->register['count_MENUOBJ']++;
            // Initialize the cObj with the page record of the menu item
69
            $this->WMcObj->start($this->menuArr[$key], 'pages', $this->request);
70
            $this->I = [];
71
72
            $this->I['key'] = $key;
            $this->I['val'] = $val;
73
            $this->I['title'] = $this->getPageTitle(($this->menuArr[$key]['title'] ?? ''), ($this->menuArr[$key]['nav_title'] ?? ''));
74
            $this->I['title.'] = $this->I['val']['stdWrap.'] ?? [];
75
            $this->I['title'] = $this->WMcObj->stdWrapValue('title', $this->I ?? []);
76
77
78
            $this->I['uid'] = $this->menuArr[$key]['uid'] ?? 0;
            $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'] ?? 0;
            $this->I['pid'] = $this->menuArr[$key]['pid'] ?? 0;
79
80
            $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
            // Set access key
81
            if ($this->mconf['accessKey'] ?? false) {
82
                $this->I['accessKey'] = $this->accessKey((string)($this->I['title'] ?? ''));
83
            } else {
84
                $this->I['accessKey'] = [];
85
86
87
            }
            // Make link tag
            $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
88
            $this->I['val']['additionalParams'] = $this->WMcObj->stdWrapValue('additionalParams', $this->I['val']);
89
            $this->I['linkHREF'] = $this->link((int)$key, (string)($this->I['val']['altTarget'] ?? ''), ($this->mconf['forceTypeValue'] ?? ''));
90
91
92
93
            if (empty($this->I['linkHREF'])) {
                $this->I['val']['doNotLinkIt'] = 1;
            }
            // Title attribute of links:
94
            $titleAttrValue = $this->WMcObj->stdWrapValue('ATagTitle', $this->I['val']);
95
            $titleAttrValue .= $this->I['accessKey']['alt'] ?? '';
96
97
98
            if ($titleAttrValue !== '') {
                $this->I['linkHREF']['title'] = $titleAttrValue;
            }
99

100
            // stdWrap for doNotLinkIt
101
            $this->I['val']['doNotLinkIt'] = $this->WMcObj->stdWrapValue('doNotLinkIt', $this->I['val']);
102
103
104
105
106
107
108
109
110
111
112
            // Compile link tag
            if (!$this->I['val']['doNotLinkIt']) {
                $this->I['val']['doNotLinkIt'] = 0;
            }
            if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt'] != 1) {
                $this->setATagParts();
            } else {
                $this->I['A1'] = '';
                $this->I['A2'] = '';
            }
            // ATagBeforeWrap processing:
113
            if ($this->I['val']['ATagBeforeWrap'] ?? false) {
114
                $wrapPartsBefore = explode('|', $this->I['val']['linkWrap'] ?? '');
115
                $wrapPartsAfter = ['', ''];
116
            } else {
117
                $wrapPartsBefore = ['', ''];
118
                $wrapPartsAfter = explode('|', $this->I['val']['linkWrap'] ?? '');
119
            }
120
            if (($this->I['val']['stdWrap2'] ?? false) || isset($this->I['val']['stdWrap2.'])) {
121
                $stdWrap2 = isset($this->I['val']['stdWrap2.']) ? $this->WMcObj->stdWrap('|', $this->I['val']['stdWrap2.']) : '|';
122
                $wrapPartsStdWrap = explode($this->I['val']['stdWrap2'] ?: '|', $stdWrap2);
123
            } else {
124
                $wrapPartsStdWrap = ['', ''];
125
126
            }
            // Make before, middle and after parts
127
            $this->I['parts'] = [];
128
129
130
            $this->I['parts']['before'] = $this->getBeforeAfter('before');
            $this->I['parts']['stdWrap2_begin'] = $wrapPartsStdWrap[0];
            // stdWrap for doNotShowLink
131
            $this->I['val']['doNotShowLink'] = $this->WMcObj->stdWrapValue('doNotShowLink', $this->I['val']);
132
            if (!$this->I['val']['doNotShowLink']) {
133
                $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0] ?? '';
134
                $this->I['parts']['ATag_begin'] = $this->I['A1'];
135
                $this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0] ?? '';
136
                $this->I['parts']['title'] = $this->I['title'];
137
                $this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1] ?? '';
138
                $this->I['parts']['ATag_end'] = $this->I['A2'];
139
                $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1] ?? '';
140
141
142
143
            }
            $this->I['parts']['stdWrap2_end'] = $wrapPartsStdWrap[1];
            $this->I['parts']['after'] = $this->getBeforeAfter('after');
            // Passing I to a user function
144
            if ($this->mconf['IProcFunc'] ?? false) {
145
146
147
148
149
                $this->I = $this->userProcess('IProcFunc', $this->I);
            }
            // Merge parts + beforeAllWrap
            $this->I['theItem'] = implode('', $this->I['parts']);
            // allWrap:
150
            $allWrap = $this->WMcObj->stdWrapValue('allWrap', $this->I['val']);
151
            $this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $allWrap);
152
            if ($this->I['val']['subst_elementUid'] ?? false) {
153
                $this->I['theItem'] = str_replace('{elementUid}', (string)$this->I['uid'], $this->I['theItem']);
154
155
            }
            // allStdWrap:
156
            if (is_array($this->I['val']['allStdWrap.'] ?? null)) {
157
158
159
                $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
            }
            // Calling extra processing function
160
            $this->extProc_afterLinking((int)$key);
161
162
163
        }
        return $this->extProc_finish();
    }
164

165
    /**
166
167
168
169
170
171
     * Generates the before* and after* stdWrap for TMENUs
     * Evaluates:
     * - before.stdWrap*
     * - beforeWrap
     * - after.stdWrap*
     * - afterWrap
172
     *
173
174
     * @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
     * @return string The resulting HTML
175
     */
176
    protected function getBeforeAfter($pref)
177
    {
178
        $processedPref = $this->WMcObj->stdWrapValue($pref, $this->I['val']);
179
        if (isset($this->I['val'][$pref . 'Wrap'])) {
180
            return $this->WMcObj->wrap($processedPref, $this->I['val'][$pref . 'Wrap']);
181
        }
182
        return $processedPref;
183
    }
184

185
186
187
188
189
190
191
    /**
     * Called right after the creation of links for the menu item. This is also the last function call before the while-loop traversing menu items goes to the next item.
     * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
     *
     * @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
     * @see writeMenu()
     */
192
    protected function extProc_afterLinking($key)
193
194
195
    {
        // Add part to the accumulated result + fetch submenus
        if (!$this->I['spacer']) {
196
            $this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix'] ?? '');
197
        }
198
        $part = $this->WMcObj->stdWrapValue('wrapItemAndSub', $this->I['val']);
199
200
        $this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
    }
201

202
203
204
205
206
207
    /**
     * Called before the writeMenu() function returns (only if a menu was generated)
     *
     * @return string The total menu content should be returned by this function
     * @see writeMenu()
     */
208
    protected function extProc_finish()
209
    {
210
        if (is_array($this->mconf['stdWrap.'] ?? null)) {
211
212
            $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
        }
213
        return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap'] ?? '');
214
    }
215
}