TYPO3 CMS  TYPO3_8-7
GraphicalMenuContentObject.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 
22 
27 {
34  public function generate()
35  {
36  $splitCount = count($this->menuArr);
37  if ($splitCount) {
38  list($NOconf, $ROconf) = $this->procesItemStates($splitCount);
39  //store initial count value
40  $tsfe = $this->getTypoScriptFrontendController();
41  $temp_HMENU_MENUOBJ = $tsfe->register['count_HMENU_MENUOBJ'];
42  $temp_MENUOBJ = $tsfe->register['count_MENUOBJ'];
43  // Now we generate the giffiles:
44  $this->makeGifs($NOconf, 'NO');
45  // store count from NO obj
46  $tempcnt_HMENU_MENUOBJ = $tsfe->register['count_HMENU_MENUOBJ'];
47  $tempcnt_MENUOBJ = $tsfe->register['count_MENUOBJ'];
48  if ($this->mconf['debugItemConf']) {
49  echo '<h3>$NOconf:</h3>';
50  debug($NOconf);
51  }
52  // RollOver
53  if ($ROconf) {
54  // Start recount for rollover with initial values
55  $tsfe->register['count_HMENU_MENUOBJ'] = $temp_HMENU_MENUOBJ;
56  $tsfe->register['count_MENUOBJ'] = $temp_MENUOBJ;
57  $this->makeGifs($ROconf, 'RO');
58  if ($this->mconf['debugItemConf']) {
59  echo '<h3>$ROconf:</h3>';
60  debug($ROconf);
61  }
62  }
63  // Use count from NO obj
64  $tsfe->register['count_HMENU_MENUOBJ'] = $tempcnt_HMENU_MENUOBJ;
65  $tsfe->register['count_MENUOBJ'] = $tempcnt_MENUOBJ;
66  }
67  }
68 
78  public function makeGifs($conf, $resKey)
79  {
80  $isGD = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'];
81  if (!is_array($conf)) {
82  $conf = [];
83  }
84  $totalWH = [];
85  $items = count($conf);
86  $minDim = 0;
87  $maxDim = 0;
88  $Hcounter = 0;
89  $Wcounter = 0;
90  $Hobjs = [];
91  $Wobjs = [];
92  if ($isGD) {
93  // Generate the gif-files. the $menuArr is filled with some values like output_w, output_h, output_file
94  $Hobjs = $this->mconf['applyTotalH'];
95  if ($Hobjs) {
96  $Hobjs = GeneralUtility::intExplode(',', $Hobjs);
97  }
98  $Wobjs = $this->mconf['applyTotalW'];
99  if ($Wobjs) {
100  $Wobjs = GeneralUtility::intExplode(',', $Wobjs);
101  }
102  $minDim = $this->mconf['min'];
103  if ($minDim) {
104  $minDim = $this->parent_cObj->calcIntExplode(',', $minDim . ',');
105  }
106  $maxDim = $this->mconf['max'];
107  if ($maxDim) {
108  $maxDim = $this->parent_cObj->calcIntExplode(',', $maxDim . ',');
109  }
110  if ($minDim) {
111  $conf[$items] = $conf[$items - 1];
112  $this->menuArr[$items] = [];
113  $items = count($conf);
114  }
115  // TOTAL width
116  if ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'] || $this->mconf['distributeX'] || $this->mconf['distributeY']) {
117  $totalWH = $this->findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim);
118  }
119  }
120  $c = 0;
121  $maxFlag = 0;
122  $distributeAccu = ['H' => 0, 'W' => 0];
123  foreach ($conf as $key => $val) {
124  $this->getTypoScriptFrontendController()->register['count_HMENU_MENUOBJ']++;
125  $this->getTypoScriptFrontendController()->register['count_MENUOBJ']++;
126  if ($items === $c + 1 && $minDim) {
127  $Lobjs = $this->mconf['removeObjectsOfDummy'];
128  if ($Lobjs) {
129  $Lobjs = GeneralUtility::intExplode(',', $Lobjs);
130  foreach ($Lobjs as $remItem) {
131  unset($val[$remItem]);
132  unset($val[$remItem . '.']);
133  }
134  }
135  $flag = 0;
136  $tempXY = explode(',', $val['XY']);
137  if ($Wcounter < $minDim[0]) {
138  $tempXY[0] = $minDim[0] - $Wcounter;
139  $flag = 1;
140  }
141  if ($Hcounter < $minDim[1]) {
142  $tempXY[1] = $minDim[1] - $Hcounter;
143  $flag = 1;
144  }
145  $val['XY'] = implode(',', $tempXY);
146  if (!$flag) {
147  break;
148  }
149  }
150  $c++;
151  $gifCreator = null;
152  if ($isGD) {
153  // Pre-working the item
154  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
155  $gifCreator->init();
156  $gifCreator->start($val, $this->menuArr[$key]);
157  // If useLargestItemH/W is specified
158  if (!empty($totalWH) && ($this->mconf['useLargestItemX'] || $this->mconf['useLargestItemY'])) {
159  $tempXY = explode(',', $gifCreator->setup['XY']);
160  if ($this->mconf['useLargestItemX']) {
161  $tempXY[0] = max($totalWH['W']);
162  }
163  if ($this->mconf['useLargestItemY']) {
164  $tempXY[1] = max($totalWH['H']);
165  }
166  // Regenerate the new values...
167  $val['XY'] = implode(',', $tempXY);
168  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
169  $gifCreator->init();
170  $gifCreator->start($val, $this->menuArr[$key]);
171  }
172  // If distributeH/W is specified
173  if (!empty($totalWH) && ($this->mconf['distributeX'] || $this->mconf['distributeY'])) {
174  $tempXY = explode(',', $gifCreator->setup['XY']);
175  if ($this->mconf['distributeX']) {
176  $diff = $this->mconf['distributeX'] - $totalWH['W_total'] - $distributeAccu['W'];
177  $compensate = round($diff / ($items - $c + 1));
178  $distributeAccu['W'] += $compensate;
179  $tempXY[0] = $totalWH['W'][$key] + $compensate;
180  }
181  if ($this->mconf['distributeY']) {
182  $diff = $this->mconf['distributeY'] - $totalWH['H_total'] - $distributeAccu['H'];
183  $compensate = round($diff / ($items - $c + 1));
184  $distributeAccu['H'] += $compensate;
185  $tempXY[1] = $totalWH['H'][$key] + $compensate;
186  }
187  // Regenerate the new values...
188  $val['XY'] = implode(',', $tempXY);
189  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
190  $gifCreator->init();
191  $gifCreator->start($val, $this->menuArr[$key]);
192  }
193  // If max dimensions are specified
194  if ($maxDim) {
195  $tempXY = explode(',', $val['XY']);
196  if ($maxDim[0] && $Wcounter + $gifCreator->XY[0] >= $maxDim[0]) {
197  $tempXY[0] = $maxDim[0] - $Wcounter;
198  $maxFlag = 1;
199  }
200  if ($maxDim[1] && $Hcounter + $gifCreator->XY[1] >= $maxDim[1]) {
201  $tempXY[1] = $maxDim[1] - $Hcounter;
202  $maxFlag = 1;
203  }
204  if ($maxFlag) {
205  $val['XY'] = implode(',', $tempXY);
206  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
207  $gifCreator->init();
208  $gifCreator->start($val, $this->menuArr[$key]);
209  }
210  }
211  // displace
212  if ($Hobjs) {
213  foreach ($Hobjs as $index) {
214  if ($gifCreator->setup[$index] && $gifCreator->setup[$index . '.']) {
215  $oldOffset = explode(',', $gifCreator->setup[$index . '.']['offset']);
216  $gifCreator->setup[$index . '.']['offset'] = implode(',', $gifCreator->applyOffset($oldOffset, [0, -$Hcounter]));
217  }
218  }
219  }
220  if ($Wobjs) {
221  foreach ($Wobjs as $index) {
222  if ($gifCreator->setup[$index] && $gifCreator->setup[$index . '.']) {
223  $oldOffset = explode(',', $gifCreator->setup[$index . '.']['offset']);
224  $gifCreator->setup[$index . '.']['offset'] = implode(',', $gifCreator->applyOffset($oldOffset, [-$Wcounter, 0]));
225  }
226  }
227  }
228  }
229  // Finding alternative GIF names if any (by altImgResource)
230  $gifFileName = '';
231  if ($conf[$key]['altImgResource'] || is_array($conf[$key]['altImgResource.'])) {
232  $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
233  $cObj->start($this->menuArr[$key], 'pages');
234  $altImgInfo = $cObj->getImgResource($conf[$key]['altImgResource'], $conf[$key]['altImgResource.']);
235  $gifFileName = $altImgInfo[3];
236  }
237  // If an alternative name was NOT given, find the GIFBUILDER name.
238  if (!$gifFileName && $isGD) {
239  GeneralUtility::mkdir_deep(PATH_site . 'typo3temp/assets/menu/');
240  $gifFileName = $gifCreator->fileName('assets/menu/');
241  }
242  $this->result[$resKey][$key] = $conf[$key];
243  // Generation of image file:
244  // File exists
245  if (file_exists($gifFileName)) {
246  $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $gifFileName);
247  $this->result[$resKey][$key]['output_w'] = (int)$imageInfo->getWidth();
248  $this->result[$resKey][$key]['output_h'] = (int)$imageInfo->getHeight();
249  $this->result[$resKey][$key]['output_file'] = $gifFileName;
250  } elseif ($isGD) {
251  // file is generated
252  $gifCreator->make();
253  $this->result[$resKey][$key]['output_w'] = $gifCreator->w;
254  $this->result[$resKey][$key]['output_h'] = $gifCreator->h;
255  $this->result[$resKey][$key]['output_file'] = $gifFileName;
256  $gifCreator->output($this->result[$resKey][$key]['output_file']);
257  $gifCreator->destroy();
258  }
259  // counter is increased
260  $Hcounter += $this->result[$resKey][$key]['output_h'];
261  // counter is increased
262  $Wcounter += $this->result[$resKey][$key]['output_w'];
263  if ($maxFlag) {
264  break;
265  }
266  }
267  }
268 
284  public function findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim)
285  {
286  $items = (int)$items;
287  $totalWH = [
288  'W' => [],
289  'H' => [],
290  'W_total' => 0,
291  'H_total' => 0
292  ];
293  $Hcounter = 0;
294  $Wcounter = 0;
295  $c = 0;
296  $maxFlag = 0;
297  foreach ($conf as $key => $val) {
298  // SAME CODE AS makeGifs()! BEGIN
299  if ($items === $c + 1 && $minDim) {
300  $Lobjs = $this->mconf['removeObjectsOfDummy'];
301  if ($Lobjs) {
302  $Lobjs = GeneralUtility::intExplode(',', $Lobjs);
303  foreach ($Lobjs as $remItem) {
304  unset($val[$remItem]);
305  unset($val[$remItem . '.']);
306  }
307  }
308  $flag = 0;
309  $tempXY = explode(',', $val['XY']);
310  if ($Wcounter < $minDim[0]) {
311  $tempXY[0] = $minDim[0] - $Wcounter;
312  $flag = 1;
313  }
314  if ($Hcounter < $minDim[1]) {
315  $tempXY[1] = $minDim[1] - $Hcounter;
316  $flag = 1;
317  }
318  $val['XY'] = implode(',', $tempXY);
319  if (!$flag) {
320  break;
321  }
322  }
323  $c++;
324  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
325  $gifCreator->init();
326  $gifCreator->start($val, $this->menuArr[$key]);
327  if ($maxDim) {
328  $tempXY = explode(',', $val['XY']);
329  if ($maxDim[0] && $Wcounter + $gifCreator->XY[0] >= $maxDim[0]) {
330  $tempXY[0] = $maxDim[0] - $Wcounter;
331  $maxFlag = 1;
332  }
333  if ($maxDim[1] && $Hcounter + $gifCreator->XY[1] >= $maxDim[1]) {
334  $tempXY[1] = $maxDim[1] - $Hcounter;
335  $maxFlag = 1;
336  }
337  if ($maxFlag) {
338  $val['XY'] = implode(',', $tempXY);
339  $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
340  $gifCreator->init();
341  $gifCreator->start($val, $this->menuArr[$key]);
342  }
343  }
344  // SAME CODE AS makeGifs()! END
345  // Setting the width/height
346  $totalWH['W'][$key] = $gifCreator->XY[0];
347  $totalWH['H'][$key] = $gifCreator->XY[1];
348  $totalWH['W_total'] += $gifCreator->XY[0];
349  $totalWH['H_total'] += $gifCreator->XY[1];
350  // counter is increased
351  $Hcounter += $gifCreator->XY[1];
352  // counter is increased
353  $Wcounter += $gifCreator->XY[0];
354  if ($maxFlag) {
355  break;
356  }
357  }
358  return $totalWH;
359  }
360 
367  public function writeMenu()
368  {
369  if (!is_array($this->menuArr) || empty($this->result) || !is_array($this->result['NO'])) {
370  return '';
371  }
372  $this->WMresult = '';
373  $this->INPfixMD5 = substr(md5(microtime() . $this->GMENU_fixKey), 0, 4);
374  $this->WMmenuItems = count($this->result['NO']);
375  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
376  $this->WMsubmenuObjSuffixes = $typoScriptService->explodeConfigurationForOptionSplit(['sOSuffix' => $this->mconf['submenuObjSuffixes']], $this->WMmenuItems);
377  $this->extProc_init();
378  $tsfe = $this->getTypoScriptFrontendController();
379  if (!isset($tsfe->additionalJavaScript['JSImgCode'])) {
380  $tsfe->additionalJavaScript['JSImgCode'] = '';
381  }
382  for ($key = 0; $key < $this->WMmenuItems; $key++) {
383  if ($this->result['NO'][$key]['output_file']) {
384  // Initialize the cObj with the page record of the menu item
385  $this->WMcObj->start($this->menuArr[$key], 'pages');
386  $this->I = [];
387  $this->I['key'] = $key;
388  $this->I['INPfix'] = ($this->imgNameNotRandom ? '' : '_' . $this->INPfixMD5) . '_' . $key;
389  $this->I['val'] = $this->result['NO'][$key];
390  $this->I['title'] = $this->getPageTitle($this->menuArr[$key]['title'], $this->menuArr[$key]['nav_title']);
391  $this->I['uid'] = $this->menuArr[$key]['uid'];
392  $this->I['mount_pid'] = $this->menuArr[$key]['mount_pid'];
393  $this->I['pid'] = $this->menuArr[$key]['pid'];
394  $this->I['spacer'] = $this->menuArr[$key]['isSpacer'];
395  if (!$this->I['uid'] && !$this->menuArr[$key]['_OVERRIDE_HREF']) {
396  $this->I['spacer'] = 1;
397  }
398  $this->I['noLink'] = $this->I['spacer'] || $this->I['val']['noLink'] || empty($this->menuArr[$key]);
399  // !count($this->menuArr[$key]) means that this item is a dummyItem
400  $this->I['name'] = '';
401  // Set access key
402  if ($this->mconf['accessKey']) {
403  $this->I['accessKey'] = $this->accessKey($this->I['title']);
404  } else {
405  $this->I['accessKey'] = [];
406  }
407  // Make link tag
408  $this->I['val']['ATagParams'] = $this->WMcObj->getATagParams($this->I['val']);
409  if (isset($this->I['val']['additionalParams.'])) {
410  $this->I['val']['additionalParams'] = $this->WMcObj->stdWrap($this->I['val']['additionalParams'], $this->I['val']['additionalParams.']);
411  }
412  $this->I['linkHREF'] = $this->link($key, $this->I['val']['altTarget'], $this->mconf['forceTypeValue']);
413  // Title attribute of links:
414  $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'];
415  if ($titleAttrValue !== '') {
416  $this->I['linkHREF']['title'] = $titleAttrValue;
417  }
418  // Set rollover
419  if ($this->result['RO'][$key] && !$this->I['noLink']) {
420  $this->I['theName'] = $this->imgNamePrefix . $this->I['uid'] . $this->I['INPfix'];
421  $this->I['name'] = ' ' . $this->nameAttribute . '="' . $this->I['theName'] . '"';
422  $this->I['linkHREF']['onMouseover'] = $this->WMfreezePrefix . 'over(' . GeneralUtility::quoteJSvalue($this->I['theName']) . ');';
423  $this->I['linkHREF']['onMouseout'] = $this->WMfreezePrefix . 'out(' . GeneralUtility::quoteJSvalue($this->I['theName']) . ');';
424  $tsfe->additionalJavaScript['JSImgCode'] .= LF . $this->I['theName'] . '_n=new Image(); ' . $this->I['theName'] . '_n.src = ' . GeneralUtility::quoteJSvalue($tsfe->absRefPrefix . $this->I['val']['output_file']) . '; ';
425  $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']) . '; ';
426  $tsfe->imagesOnPage[] = $this->result['RO'][$key]['output_file'];
427  $tsfe->setJS('mouseOver');
428  $this->extProc_RO($key);
429  }
430  // Set altText
431  $this->I['altText'] = $this->I['title'] . $this->I['accessKey']['alt'];
432  // Calling extra processing function
433  $this->extProc_beforeLinking($key);
434  // Set linking
435  if (!$this->I['noLink']) {
436  $this->setATagParts();
437  } else {
438  $this->I['A1'] = '';
439  $this->I['A2'] = '';
440  }
441  $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'] : '') . ' />';
442  // Make before, middle and after parts
443  $this->I['parts'] = [];
444  $this->I['parts']['ATag_begin'] = $this->I['A1'];
445  $this->I['parts']['image'] = $this->I['IMG'];
446  $this->I['parts']['ATag_end'] = $this->I['A2'];
447  // Passing I to a user function
448  if ($this->mconf['IProcFunc']) {
449  $this->I = $this->userProcess('IProcFunc', $this->I);
450  }
451  // Putting the item together.
452  // Merge parts + beforeAllWrap
453  $this->I['theItem'] = implode('', $this->I['parts']);
454  $this->I['theItem'] = $this->extProc_beforeAllWrap($this->I['theItem'], $key);
455  // wrap:
456  $this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $this->I['val']['wrap']);
457  // allWrap:
458  $allWrap = isset($this->I['val']['allWrap.']) ? $this->WMcObj->stdWrap($this->I['val']['allWrap'], $this->I['val']['allWrap.']) : $this->I['val']['allWrap'];
459  $this->I['theItem'] = $this->WMcObj->wrap($this->I['theItem'], $allWrap);
460  if ($this->I['val']['subst_elementUid']) {
461  $this->I['theItem'] = str_replace('{elementUid}', $this->I['uid'], $this->I['theItem']);
462  }
463  // allStdWrap:
464  if (is_array($this->I['val']['allStdWrap.'])) {
465  $this->I['theItem'] = $this->WMcObj->stdWrap($this->I['theItem'], $this->I['val']['allStdWrap.']);
466  }
467  $tsfe->imagesOnPage[] = $this->I['val']['output_file'];
468  $this->extProc_afterLinking($key);
469  }
470  }
471  return $this->extProc_finish();
472  }
473 
481  public function extProc_init()
482  {
483  }
484 
492  public function extProc_RO($key)
493  {
494  }
495 
503  public function extProc_beforeLinking($key)
504  {
505  }
506 
517  public function extProc_afterLinking($key)
518  {
519  // Add part to the accumulated result + fetch submenus
520  if (!$this->I['spacer']) {
521  $this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
522  }
523  $part = isset($this->I['val']['wrapItemAndSub.']) ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.']) : $this->I['val']['wrapItemAndSub'];
524  $this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
525  }
526 
536  public function extProc_beforeAllWrap($item, $key)
537  {
538  return $item;
539  }
540 
548  public function extProc_finish()
549  {
550  // stdWrap:
551  if (is_array($this->mconf['stdWrap.'])) {
552  $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
553  }
554  return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap']) . $this->WMextraScript;
555  }
556 }
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
static mkdir_deep($directory, $deepDirectory='')
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel='E_DEBUG')
static makeInstance($className,... $constructorArguments)
findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']