[CLEANUP] Replace strlen() with === for zero length check
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / Menu / TextMenuContentObject.php
1 <?php
2 namespace TYPO3\CMS\Frontend\ContentObject\Menu;
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
17 /**
18 * Extension class creating text based menus
19 *
20 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
21 */
22 class TextMenuContentObject extends AbstractMenuContentObject {
23
24 /**
25 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
26 * Sets the result for the new "normal state" in $this->result
27 *
28 * @return void
29 * @see AbstractMenuContentObject::procesItemStates()
30 */
31 public function generate() {
32 $splitCount = count($this->menuArr);
33 if ($splitCount) {
34 list($NOconf) = $this->procesItemStates($splitCount);
35 }
36 if ($this->mconf['debugItemConf']) {
37 echo '<h3>$NOconf:</h3>';
38 debug($NOconf);
39 }
40 $this->result = $NOconf;
41 }
42
43 /**
44 * Traverses the ->result array of menu items configuration (made by ->generate()) and renders each item.
45 * During the execution of this function many internal methods prefixed "extProc_" from this class is called and many of these are for now dummy functions. But they can be used for processing as they are used by the TMENU_LAYERS
46 * 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.
47 *
48 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
49 */
50 public function writeMenu() {
51 if (is_array($this->result) && count($this->result)) {
52 // Create new \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer for our use
53 $this->WMcObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class);
54 $this->WMresult = '';
55 $this->INPfixMD5 = substr(md5(microtime() . 'tmenu'), 0, 4);
56 $this->WMmenuItems = count($this->result);
57 $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(array('sOSuffix' => $this->mconf['submenuObjSuffixes']), $this->WMmenuItems);
58 $this->extProc_init();
59 foreach ($this->result as $key => $val) {
60 $GLOBALS['TSFE']->register['count_HMENU_MENUOBJ']++;
61 $GLOBALS['TSFE']->register['count_MENUOBJ']++;
62 // Initialize the cObj with the page record of the menu item
63 $this->WMcObj->start($this->menuArr[$key], 'pages');
64 $this->I = array();
65 $this->I['key'] = $key;
66 $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_' . $this->INPfixMD5) . '_' . $key;
67 $this->I['val'] = $val;
68 $this->I['title'] = isset($this->I['val']['stdWrap.']) ? $this->WMcObj->stdWrap($this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']), $this->I['val']['stdWrap.']) : $this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']);
69 $this->I['uid'] = $this->menuArr[$key]['uid'];
70 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
71 $this->I['pid'] = $this->menuArr[$key]['pid'];
72 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
73 // Set access key
74 if ($this->mconf['accessKey']) {
75 $this->I['accessKey'] = $this->accessKey($this->I['title']);
76 } else {
77 $this->I['accessKey'] = array();
78 }
79 // Make link tag
80 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
81 if (isset($this->I['val']['additionalParams.'])) {
82 $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
83 }
84 $this->I['linkHREF'] = $this->link($key, $this->I['val']['altTarget'], $this->mconf['forceTypeValue']);
85 // Title attribute of links:
86 $titleAttrValue = isset($this->I['val']['ATagTitle.']) ? $this->WMcObj->stdWrap($this->I['val']['ATagTitle'], $this->I['val']['ATagTitle.']) . $this->I['accessKey']['alt'] : $this->I['val']['ATagTitle'] . $this->I['accessKey']['alt'];
87 if ($titleAttrValue !== '') {
88 $this->I['linkHREF']['title'] = $titleAttrValue;
89 }
90
91 // Calling extra processing function
92 $this->extProc_beforeLinking($key);
93 // stdWrap for doNotLinkIt
94 if (isset($this->I['val']['doNotLinkIt.'])) {
95 $this->I['val']['doNotLinkIt'] = $this->WMcObj->stdWrap($this->I['val']['doNotLinkIt'], $this->I['val']['doNotLinkIt.']);
96 }
97 // Compile link tag
98 if (!$this->I['val']['doNotLinkIt']) {
99 $this->I['val']['doNotLinkIt'] = 0;
100 }
101 if (!$this->I['spacer'] && $this->I['val']['doNotLinkIt'] != 1) {
102 $this->setATagParts();
103 } else {
104 $this->I['A1'] = '';
105 $this->I['A2'] = '';
106 }
107 // ATagBeforeWrap processing:
108 if ($this->I['val']['ATagBeforeWrap']) {
109 $wrapPartsBefore = explode('|', $this->I['val']['linkWrap']);
110 $wrapPartsAfter = array('', '');
111 } else {
112 $wrapPartsBefore = array('', '');
113 $wrapPartsAfter = explode('|', $this->I['val']['linkWrap']);
114 }
115 if ($this->I['val']['stdWrap2'] || isset($this->I['val']['stdWrap2.'])) {
116 $stdWrap2 = isset($this->I['val']['stdWrap2.']) ? $this->WMcObj->stdWrap('|', $this->I['val']['stdWrap2.']) : '|';
117 $wrapPartsStdWrap = explode($this->I['val']['stdWrap2'] ? $this->I['val']['stdWrap2'] : '|', $stdWrap2);
118 } else {
119 $wrapPartsStdWrap = array('', '');
120 }
121 // Make before, middle and after parts
122 $this->I['parts'] = array();
123 $this->I['parts']['before'] = $this->getBeforeAfter('before');
124 $this->I['parts']['stdWrap2_begin'] = $wrapPartsStdWrap[0];
125 // stdWrap for doNotShowLink
126 if (isset($this->I['val']['doNotShowLink.'])) {
127 $this->I['val']['doNotShowLink'] = $this->WMcObj->stdWrap($this->I['val']['doNotShowLink'], $this->I['val']['doNotShowLink.']);
128 }
129 if (!$this->I['val']['doNotShowLink']) {
130 $this->I['parts']['notATagBeforeWrap_begin'] = $wrapPartsAfter[0];
131 $this->I['parts']['ATag_begin'] = $this->I['A1'];
132 $this->I['parts']['ATagBeforeWrap_begin'] = $wrapPartsBefore[0];
133 $this->I['parts']['title'] = $this->I['title'];
134 $this->I['parts']['ATagBeforeWrap_end'] = $wrapPartsBefore[1];
135 $this->I['parts']['ATag_end'] = $this->I['A2'];
136 $this->I['parts']['notATagBeforeWrap_end'] = $wrapPartsAfter[1];
137 }
138 $this->I['parts']['stdWrap2_end'] = $wrapPartsStdWrap[1];
139 $this->I['parts']['after'] = $this->getBeforeAfter('after');
140 // Passing I to a user function
141 if ($this->mconf['IProcFunc']) {
142 $this->I = $this->userProcess('IProcFunc', $this->I);
143 }
144 // Merge parts + beforeAllWrap
145 $this->I['theItem'] = implode('', $this->I['parts']);
146 $this->I['theItem'] = $this->extProc_beforeAllWrap($this->I['theItem'], $key);
147 // allWrap:
148 $allWrap = isset($this->I['val']['allWrap.']) ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.']) : $this->I['val']['allWrap'];
149 $this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $allWrap);
150 if ($this->I['val']['subst_elementUid']) {
151 $this->I['theItem'] = str_replace('{elementUid}', $this->I['uid'], $this->I['theItem']);
152 }
153 // allStdWrap:
154 if (is_array($this->I['val']['allStdWrap.'])) {
155 $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
156 }
157 // Calling extra processing function
158 $this->extProc_afterLinking($key);
159 }
160 return $this->extProc_finish();
161 }
162 }
163
164 /**
165 * Generates the before* and after* images for TMENUs
166 *
167 * @param string $pref Can be "before" or "after" and determines which kind of image to create (basically this is the prefix of the TypoScript properties that are read from the ->I['val'] array
168 * @return string The resulting HTML of the image, if any.
169 */
170 public function getBeforeAfter($pref) {
171 $res = '';
172 if ($imgInfo = $this->WMcObj->getImgResource($this->I['val'][$pref . 'Img'], $this->I['val'][$pref . 'Img.'])) {
173 $imgInfo[3] = \TYPO3\CMS\Core\Utility\GeneralUtility::png_to_gif_by_imagemagick($imgInfo[3]);
174 $theName = $this->imgNamePrefix . $this->I['uid'] . $this->I['INPfix'] . $pref;
175 $name = ' ' . $this->nameAttribute . '="' . $theName . '"';
176 $GLOBALS['TSFE']->imagesOnPage[] = $imgInfo[3];
177 $res = '<img' . ' src="' . $GLOBALS['TSFE']->absRefPrefix . $imgInfo[3] . '"' . ' width="' . $imgInfo[0] . '"' . ' height="' . $imgInfo[1] . '"' . $name . ($this->I['val'][$pref . 'ImgTagParams'] ? ' ' . $this->I['val'][($pref . 'ImgTagParams')] : '') . $this->parent_cObj->getBorderAttr(' border="0"');
178 if (!strstr($res, 'alt="')) {
179 // Adding alt attribute if not set.
180 $res .= ' alt=""';
181 }
182 $res .= ' />';
183 if ($this->I['val'][$pref . 'ImgLink']) {
184 $res = $this->I['A1'] . $res . $this->I['A2'];
185 }
186 }
187 $processedPref = isset($this->I['val'][$pref . '.']) ? $this->WMcObj->stdWrap($this->I['val'][$pref], $this->I['val'][$pref . '.']) : $this->I['val'][$pref];
188 if (isset($this->I['val'][$pref . 'Wrap'])) {
189 return $this->WMcObj->wrap($res . $processedPref, $this->I['val'][$pref . 'Wrap']);
190 } else {
191 return $res . $processedPref;
192 }
193 }
194
195 /**
196 * Called right before the traversing of $this->result begins.
197 * Can be used for various initialization
198 *
199 * @return void
200 * @access private
201 * @see writeMenu()
202 */
203 public function extProc_init() {
204
205 }
206
207 /**
208 * Called right before the creation of the link for the menu item
209 *
210 * @param int Pointer to $this->menuArr[$key] where the current menu element record is found
211 * @return void
212 * @access private
213 * @see writeMenu()
214 */
215 public function extProc_beforeLinking($key) {
216
217 }
218
219 /**
220 * 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.
221 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
222 *
223 * @param int Pointer to $this->menuArr[$key] where the current menu element record is found
224 * @return void
225 * @access private
226 * @see writeMenu()
227 */
228 public function extProc_afterLinking($key) {
229 // Add part to the accumulated result + fetch submenus
230 if (!$this->I['spacer']) {
231 $this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
232 }
233 $part = isset($this->I['val']['wrapItemAndSub.']) ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.']) : $this->I['val']['wrapItemAndSub'];
234 $this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
235 }
236
237 /**
238 * Called before the "allWrap" happens on the menu item.
239 *
240 * @param string $item The current content of the menu item, $this->I['theItem'], passed along.
241 * @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
242 * @return string The modified version of $item, going back into $this->I['theItem']
243 * @access private
244 * @see writeMenu()
245 */
246 public function extProc_beforeAllWrap($item, $key) {
247 return $item;
248 }
249
250 /**
251 * Called before the writeMenu() function returns (only if a menu was generated)
252 *
253 * @return string The total menu content should be returned by this function
254 * @access private
255 * @see writeMenu()
256 */
257 public function extProc_finish() {
258 // stdWrap:
259 if (is_array($this->mconf['stdWrap.'])) {
260 $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
261 }
262 return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap']) . $this->WMextraScript;
263 }
264
265 }