b8c7807af2689bad10d07a65f46ea10efefb4540
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / Menu / GraphicalMenuContentObject.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 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
20 use TYPO3\CMS\Frontend\Imaging\GifBuilder;
21
22 /**
23 * Extension class creating graphic based menus (PNG or GIF files)
24 */
25 class GraphicalMenuContentObject extends AbstractMenuContentObject
26 {
27 /**
28 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
29 * Calls makeGifs() for all "normal" items and if configured for, also the "rollover" items.
30 *
31 * @see AbstractMenuContentObject::procesItemStates(), makeGifs()
32 */
33 public function generate()
34 {
35 $splitCount = count($this->menuArr);
36 if ($splitCount) {
37 list($NOconf, $ROconf) = $this->procesItemStates($splitCount);
38 //store initial count value
39 $tsfe = $this->getTypoScriptFrontendController();
40 $temp_HMENU_MENUOBJ = $tsfe->register['count_HMENU_MENUOBJ'];
41 $temp_MENUOBJ = $tsfe->register['count_MENUOBJ'];
42 // Now we generate the giffiles:
43 $this->makeGifs($NOconf, 'NO');
44 // store count from NO obj
45 $tempcnt_HMENU_MENUOBJ = $tsfe->register['count_HMENU_MENUOBJ'];
46 $tempcnt_MENUOBJ = $tsfe->register['count_MENUOBJ'];
47 if ($this->mconf['debugItemConf']) {
48 echo '<h3>$NOconf:</h3>';
49 debug($NOconf);
50 }
51 // RollOver
52 if ($ROconf) {
53 // Start recount for rollover with initial values
54 $tsfe->register['count_HMENU_MENUOBJ'] = $temp_HMENU_MENUOBJ;
55 $tsfe->register['count_MENUOBJ'] = $temp_MENUOBJ;
56 $this->makeGifs($ROconf, 'RO');
57 if ($this->mconf['debugItemConf']) {
58 echo '<h3>$ROconf:</h3>';
59 debug($ROconf);
60 }
61 }
62 // Use count from NO obj
63 $tsfe->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
64 $tsfe->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
65 }
66 }
67
68 /**
69 * Will traverse input array with configuration per-item and create corresponding GIF files for the menu.
70 * The data of the files are stored in $this->result
71 *
72 * @param array $conf Array with configuration for each item.
73 * @param string $resKey Type of images: normal ("NO") or rollover ("RO"). Valid values are "NO" and "RO
74 * @internal
75 * @see generate()
76 */
77 public function makeGifs($conf, $resKey)
78 {
79 $isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
80 if (!is_array($conf)) {
81 $conf = [];
82 }
83 $totalWH = [];
84 $items = count($conf);
85 $minDim = 0;
86 $maxDim = 0;
87 $Hcounter = 0;
88 $Wcounter = 0;
89 $Hobjs = [];
90 $Wobjs = [];
91 if ($isGD) {
92 // Generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
93 $Hobjs = $this->mconf['applyTotalH'];
94 if ($Hobjs) {
95 $Hobjs = GeneralUtility::intExplode(',', $Hobjs);
96 }
97 $Wobjs = $this->mconf['applyTotalW'];
98 if ($Wobjs) {
99 $Wobjs = GeneralUtility::intExplode(',', $Wobjs);
100 }
101 $minDim = $this->mconf['min'];
102 if ($minDim) {
103 $minDim = $this->parent_cObj->calcIntExplode(',', $minDim . ',');
104 }
105 $maxDim = $this->mconf['max'];
106 if ($maxDim) {
107 $maxDim = $this->parent_cObj->calcIntExplode(',', $maxDim . ',');
108 }
109 if ($minDim) {
110 $conf[$items] = $conf[$items - 1];
111 $this->menuArr[$items] = [];
112 $items = count($conf);
113 }
114 // TOTAL width
115 if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY']) {
116 $totalWH = $this->findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim);
117 }
118 }
119 $c = 0;
120 $maxFlag = 0;
121 $distributeAccu = ['H' => 0, 'W' => 0];
122 foreach ($conf as $key => $val) {
123 $this->getTypoScriptFrontendController()->register['count_HMENU_MENUOBJ']++;
124 $this->getTypoScriptFrontendController()->register['count_MENUOBJ']++;
125 if ($items === $c + 1 && $minDim) {
126 $Lobjs = $this->mconf['removeObjectsOfDummy'];
127 if ($Lobjs) {
128 $Lobjs = GeneralUtility::intExplode(',', $Lobjs);
129 foreach ($Lobjs as $remItem) {
130 unset($val[$remItem]);
131 unset($val[$remItem . '.']);
132 }
133 }
134 $flag = 0;
135 $tempXY = explode(',', $val['XY']);
136 if ($Wcounter < $minDim[0]) {
137 $tempXY[0] = $minDim[0] - $Wcounter;
138 $flag = 1;
139 }
140 if ($Hcounter < $minDim[1]) {
141 $tempXY[1] = $minDim[1] - $Hcounter;
142 $flag = 1;
143 }
144 $val['XY'] = implode(',', $tempXY);
145 if (!$flag) {
146 break;
147 }
148 }
149 $c++;
150 $gifCreator = null;
151 if ($isGD) {
152 // Pre-working the item
153 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
154 $gifCreator->init();
155 $gifCreator->start($val, $this->menuArr[$key]);
156 // If useLargestItemH/W is specified
157 if (!empty($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'])) {
158 $tempXY = explode(',', $gifCreator->setup['XY']);
159 if ($this->mconf['useLargestItemX']) {
160 $tempXY[0] = max($totalWH['W']);
161 }
162 if ($this->mconf['useLargestItemY']) {
163 $tempXY[1] = max($totalWH['H']);
164 }
165 // Regenerate the new values...
166 $val['XY'] = implode(',', $tempXY);
167 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
168 $gifCreator->init();
169 $gifCreator->start($val, $this->menuArr[$key]);
170 }
171 // If distributeH/W is specified
172 if (!empty($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY'])) {
173 $tempXY = explode(',', $gifCreator->setup['XY']);
174 if ($this->mconf['distributeX']) {
175 $diff = $this->mconf['distributeX'] - $totalWH['W_total'] - $distributeAccu['W'];
176 $compensate = round($diff / ($items - $c + 1));
177 $distributeAccu['W'] += $compensate;
178 $tempXY[0] = $totalWH['W'][$key] + $compensate;
179 }
180 if ($this->mconf['distributeY']) {
181 $diff = $this->mconf['distributeY'] - $totalWH['H_total'] - $distributeAccu['H'];
182 $compensate = round($diff / ($items - $c + 1));
183 $distributeAccu['H'] += $compensate;
184 $tempXY[1] = $totalWH['H'][$key] + $compensate;
185 }
186 // Regenerate the new values...
187 $val['XY'] = implode(',', $tempXY);
188 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
189 $gifCreator->init();
190 $gifCreator->start($val, $this->menuArr[$key]);
191 }
192 // If max dimensions are specified
193 if ($maxDim) {
194 $tempXY = explode(',', $val['XY']);
195 if ($maxDim[0] && $Wcounter + $gifCreator->XY[0] >= $maxDim[0]) {
196 $tempXY[0] = $maxDim[0] - $Wcounter;
197 $maxFlag = 1;
198 }
199 if ($maxDim[1] && $Hcounter + $gifCreator->XY[1] >= $maxDim[1]) {
200 $tempXY[1] = $maxDim[1] - $Hcounter;
201 $maxFlag = 1;
202 }
203 if ($maxFlag) {
204 $val['XY'] = implode(',', $tempXY);
205 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
206 $gifCreator->init();
207 $gifCreator->start($val, $this->menuArr[$key]);
208 }
209 }
210 // displace
211 if ($Hobjs) {
212 foreach ($Hobjs as $index) {
213 if ($gifCreator->setup[$index] && $gifCreator->setup[$index . '.']) {
214 $oldOffset = explode(',', $gifCreator->setup[$index . '.']['offset']);
215 $gifCreator->setup[$index . '.']['offset'] = implode(',', $gifCreator->applyOffset($oldOffset, [0, -$Hcounter]));
216 }
217 }
218 }
219 if ($Wobjs) {
220 foreach ($Wobjs as $index) {
221 if ($gifCreator->setup[$index] && $gifCreator->setup[$index . '.']) {
222 $oldOffset = explode(',', $gifCreator->setup[$index . '.']['offset']);
223 $gifCreator->setup[$index . '.']['offset'] = implode(',', $gifCreator->applyOffset($oldOffset, [-$Wcounter, 0]));
224 }
225 }
226 }
227 }
228 // Finding alternative GIF names if any (by altImgResource)
229 $gifFileName = '';
230 if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.'])) {
231 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
232 $cObj->start($this->menuArr[$key], 'pages');
233 $altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'], $conf[$key]['altImgResource.']);
234 $gifFileName = $altImgInfo[3];
235 }
236 // If an alternative name was NOT given, find the GIFBUILDER name.
237 if (!$gifFileName && $isGD) {
238 GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/assets/menu/');
239 $gifFileName = $gifCreator->fileName('assets/menu/');
240 }
241 $this->result[$resKey][$key] = $conf[$key];
242 // Generation of image file:
243 // File exists
244 if (file_exists($gifFileName)) {
245 $info = @getimagesize($gifFileName);
246 $this->result[$resKey][$key]['output_w'] = (int)$info[0];
247 $this->result[$resKey][$key]['output_h'] = (int)$info[1];
248 $this->result[$resKey][$key]['output_file'] = $gifFileName;
249 } elseif ($isGD) {
250 // file is generated
251 $gifCreator->make();
252 $this->result[$resKey][$key]['output_w'] = $gifCreator->w;
253 $this->result[$resKey][$key]['output_h'] = $gifCreator->h;
254 $this->result[$resKey][$key]['output_file'] = $gifFileName;
255 $gifCreator->output($this->result[$resKey][$key]['output_file']);
256 $gifCreator->destroy();
257 }
258 // counter is increased
259 $Hcounter += $this->result[$resKey][$key]['output_h'];
260 // counter is increased
261 $Wcounter += $this->result[$resKey][$key]['output_w'];
262 if ($maxFlag) {
263 break;
264 }
265 }
266 }
267
268 /**
269 * Function searching for the largest width and height of the menu items to be generated.
270 * Uses some of the same code as makeGifs and even instantiates some gifbuilder objects BUT does not render the images - only reading out which width they would have.
271 * Remember to upgrade the code in here if the makeGifs function is updated.
272 *
273 * @param array $conf Same configuration array as passed to makeGifs()
274 * @param int $items The number of menu items
275 * @param array $Hobjs Array with "applyTotalH" numbers (unused)
276 * @param array $Wobjs Array with "applyTotalW" numbers (unused)
277 * @param array $minDim Array with "min" x/y
278 * @param array $maxDim Array with "max" x/y
279 * @return array Array with keys "H" and "W" which are in themselves arrays with the heights and widths of menu items inside. This can be used to find the max/min size of the menu items.
280 * @internal
281 * @see makeGifs()
282 */
283 public function findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim)
284 {
285 $items = (int)$items;
286 $totalWH = [
287 'W' => [],
288 'H' => [],
289 'W_total' => 0,
290 'H_total' => 0
291 ];
292 $Hcounter = 0;
293 $Wcounter = 0;
294 $c = 0;
295 $maxFlag = 0;
296 foreach ($conf as $key => $val) {
297 // SAME CODE AS makeGifs()! BEGIN
298 if ($items === $c + 1 && $minDim) {
299 $Lobjs = $this->mconf['removeObjectsOfDummy'];
300 if ($Lobjs) {
301 $Lobjs = GeneralUtility::intExplode(',', $Lobjs);
302 foreach ($Lobjs as $remItem) {
303 unset($val[$remItem]);
304 unset($val[$remItem . '.']);
305 }
306 }
307 $flag = 0;
308 $tempXY = explode(',', $val['XY']);
309 if ($Wcounter < $minDim[0]) {
310 $tempXY[0] = $minDim[0] - $Wcounter;
311 $flag = 1;
312 }
313 if ($Hcounter < $minDim[1]) {
314 $tempXY[1] = $minDim[1] - $Hcounter;
315 $flag = 1;
316 }
317 $val['XY'] = implode(',', $tempXY);
318 if (!$flag) {
319 break;
320 }
321 }
322 $c++;
323 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
324 $gifCreator->init();
325 $gifCreator->start($val, $this->menuArr[$key]);
326 if ($maxDim) {
327 $tempXY = explode(',', $val['XY']);
328 if ($maxDim[0] && $Wcounter + $gifCreator->XY[0] >= $maxDim[0]) {
329 $tempXY[0] = $maxDim[0] - $Wcounter;
330 $maxFlag = 1;
331 }
332 if ($maxDim[1] && $Hcounter + $gifCreator->XY[1] >= $maxDim[1]) {
333 $tempXY[1] = $maxDim[1] - $Hcounter;
334 $maxFlag = 1;
335 }
336 if ($maxFlag) {
337 $val['XY'] = implode(',', $tempXY);
338 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
339 $gifCreator->init();
340 $gifCreator->start($val, $this->menuArr[$key]);
341 }
342 }
343 // SAME CODE AS makeGifs()! END
344 // Setting the width/height
345 $totalWH['W'][$key] = $gifCreator->XY[0];
346 $totalWH['H'][$key] = $gifCreator->XY[1];
347 $totalWH['W_total'] += $gifCreator->XY[0];
348 $totalWH['H_total'] += $gifCreator->XY[1];
349 // counter is increased
350 $Hcounter += $gifCreator->XY[1];
351 // counter is increased
352 $Wcounter += $gifCreator->XY[0];
353 if ($maxFlag) {
354 break;
355 }
356 }
357 return $totalWH;
358 }
359
360 /**
361 * Traverses the ->result['NO'] array of menu items configuration (made by ->generate()) and renders the HTML of each item (the images themselves was made with makeGifs() before this. See ->generate())
362 * 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 GMENU_LAYERS
363 *
364 * @return string The HTML for the menu (returns result through $this->extProc_finish(); )
365 */
366 public function writeMenu()
367 {
368 if (!is_array($this->menuArr) || empty($this->result) || !is_array($this->result['NO'])) {
369 return '';
370 }
371 $this->WMresult = '';
372 $this->INPfixMD5 = substr(md5(microtime() . $this->GMENU_fixKey), 0, 4);
373 $this->WMmenuItems = count($this->result['NO']);
374 $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
375 $this->WMsubmenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes']], $this->WMmenuItems);
376 $this->extProc_init();
377 $tsfe = $this->getTypoScriptFrontendController();
378 if (!isset($tsfe->additionalJavaScript['JSImgCode'])) {
379 $tsfe->additionalJavaScript['JSImgCode'] = '';
380 }
381 for ($key = 0; $key < $this->WMmenuItems; $key++) {
382 if ($this->result['NO'][$key]['output_file']) {
383 // Initialize the cObj with the page record of the menu item
384 $this->WMcObj->start($this->menuArr[$key], 'pages');
385 $this->I = [];
386 $this->I['key'] = $key;
387 $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_' . $this->INPfixMD5) . '_' . $key;
388 $this->I['val'] = $this->result['NO'][$key];
389 $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']);
390 $this->I['uid'] = $this->menuArr[$key]['uid'];
391 $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
392 $this->I['pid'] = $this->menuArr[$key]['pid'];
393 $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
394 if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {
395 $this->I['spacer'] = 1;
396 }
397 $this->I['noLink'] = $this->I['spacer'] || $this->I['val']['noLink'] || empty($this->menuArr[$key]);
398 // !count($this->menuArr[$key]) means that this item is a dummyItem
399 $this->I['name'] = '';
400 // Set access key
401 if ($this->mconf['accessKey']) {
402 $this->I['accessKey'] = $this->accessKey($this->I['title']);
403 } else {
404 $this->I['accessKey'] = [];
405 }
406 // Make link tag
407 $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
408 if (isset($this->I['val']['additionalParams.'])) {
409 $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
410 }
411 $this->I['linkHREF'] = $this->link($key, $this->I['val']['altTarget'], $this->mconf['forceTypeValue']);
412 // Title attribute of links:
413 $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'];
414 if ($titleAttrValue !== '') {
415 $this->I['linkHREF']['title'] = $titleAttrValue;
416 }
417 // Set rollover
418 if ($this->result['RO'][$key] && !$this->I['noLink']) {
419 $this->I['theName'] = $this->imgNamePrefix . $this->I['uid'] . $this->I['INPfix'];
420 $this->I['name'] = ' ' . $this->nameAttribute . '="' . $this->I['theName'] . '"';
421 $this->I['linkHREF']['onMouseover'] = $this->WMfreezePrefix . 'over(' . GeneralUtility::quoteJSvalue($this->I['theName']) . ');';
422 $this->I['linkHREF']['onMouseout'] = $this->WMfreezePrefix . 'out(' . GeneralUtility::quoteJSvalue($this->I['theName']) . ');';
423 $tsfe->additionalJavaScript['JSImgCode'] .= LF . $this->I['theName'] . '_n=new Image(); ' . $this->I['theName'] . '_n.src = ' . GeneralUtility::quoteJSvalue($tsfe->absRefPrefix . $this->I['val']['output_file']) . '; ';
424 $tsfe->additionalJavaScript['JSImgCode'] .= LF . $this->I['theName'] . '_h=new Image(); ' . $this->I['theName'] . '_h.src = ' . GeneralUtility::quoteJSvalue($tsfe->absRefPrefix . $this->result['RO'][$key]['output_file']) . '; ';
425 $tsfe->imagesOnPage[] = $this->result['RO'][$key]['output_file'];
426 $tsfe->setJS('mouseOver');
427 $this->extProc_RO($key);
428 }
429 // Set altText
430 $this->I['altText'] = $this->I['title'] . $this->I['accessKey']['alt'];
431 // Calling extra processing function
432 $this->extProc_beforeLinking($key);
433 // Set linking
434 if (!$this->I['noLink']) {
435 $this->setATagParts();
436 } else {
437 $this->I['A1'] = '';
438 $this->I['A2'] = '';
439 }
440 $this->I['IMG'] = '<img src="' . $tsfe->absRefPrefix . $this->I['val']['output_file'] . '" width="' . $this->I['val']['output_w'] . '" height="' . $this->I['val']['output_h'] . '" ' . $this->parent_cObj->getBorderAttr('border="0"') . ($this->mconf['disableAltText'] ? '' : ' alt="' . htmlspecialchars($this->I['altText']) . '"') . $this->I['name'] . ($this->I['val']['imgParams'] ? ' ' . $this->I['val']['imgParams'] : '') . ' />';
441 // Make before, middle and after parts
442 $this->I['parts'] = [];
443 $this->I['parts']['ATag_begin'] = $this->I['A1'];
444 $this->I['parts']['image'] = $this->I['IMG'];
445 $this->I['parts']['ATag_end'] = $this->I['A2'];
446 // Passing I to a user function
447 if ($this->mconf['IProcFunc']) {
448 $this->I = $this->userProcess('IProcFunc', $this->I);
449 }
450 // Putting the item together.
451 // Merge parts + beforeAllWrap
452 $this->I['theItem'] = implode('', $this->I['parts']);
453 $this->I['theItem'] = $this->extProc_beforeAllWrap($this->I['theItem'], $key);
454 // wrap:
455 $this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $this->I['val']['wrap']);
456 // allWrap:
457 $allWrap = isset($this->I['val']['allWrap.']) ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.']) : $this->I['val']['allWrap'];
458 $this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $allWrap);
459 if ($this->I['val']['subst_elementUid']) {
460 $this->I['theItem'] = str_replace('{elementUid}', $this->I['uid'], $this->I['theItem']);
461 }
462 // allStdWrap:
463 if (is_array($this->I['val']['allStdWrap.'])) {
464 $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
465 }
466 $tsfe->imagesOnPage[] = $this->I['val']['output_file'];
467 $this->extProc_afterLinking($key);
468 }
469 }
470 return $this->extProc_finish();
471 }
472
473 /**
474 * Called right before the traversing of $this->result begins.
475 * Can be used for various initialization
476 *
477 * @internal
478 * @see writeMenu()
479 */
480 public function extProc_init()
481 {
482 }
483
484 /**
485 * Called after all processing for RollOver of an element has been done.
486 *
487 * @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found OR $this->result['RO'][$key] where the configuration for that elements RO version is found!
488 * @internal
489 * @see writeMenu()
490 */
491 public function extProc_RO($key)
492 {
493 }
494
495 /**
496 * Called right before the creation of the link for the menu item
497 *
498 * @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
499 * @internal
500 * @see writeMenu()
501 */
502 public function extProc_beforeLinking($key)
503 {
504 }
505
506 /**
507 * Called right after the creation of links for the menu item. This is also the last function call before the
508 * for-loop traversing menu items goes to the next item.
509 * This function MUST set $this->WMresult.=[HTML for menu item] to add the generated menu item to the internal accumulation of items.
510 * Further this calls the subMenu function in the parent class to create any submenu there might be.
511 *
512 * @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found
513 * @internal
514 * @see writeMenu(), AbstractMenuContentObject::subMenu()
515 */
516 public function extProc_afterLinking($key)
517 {
518 // Add part to the accumulated result + fetch submenus
519 if (!$this->I['spacer']) {
520 $this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
521 }
522 $part = isset($this->I['val']['wrapItemAndSub.']) ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.']) : $this->I['val']['wrapItemAndSub'];
523 $this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
524 }
525
526 /**
527 * Called before the "wrap" happens on the menu item.
528 *
529 * @param string $item The current content of the menu item, $this->I['theItem'], passed along.
530 * @param int $key Pointer to $this->menuArr[$key] where the current menu element record is found (unused)
531 * @return string The modified version of $item, going back into $this->I['theItem']
532 * @internal
533 * @see writeMenu()
534 */
535 public function extProc_beforeAllWrap($item, $key)
536 {
537 return $item;
538 }
539
540 /**
541 * Called before the writeMenu() function returns (only if a menu was generated)
542 *
543 * @return string The total menu content should be returned by this function
544 * @internal
545 * @see writeMenu()
546 */
547 public function extProc_finish()
548 {
549 // stdWrap:
550 if (is_array($this->mconf['stdWrap.'])) {
551 $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
552 }
553 return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap']) . $this->WMextraScript;
554 }
555 }