TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
GraphicalMenuContentObject.php
Go to the documentation of this file.
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 
20 
25 {
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 
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  $gifCreator->createTempSubDir('menu/');
240  $gifFileName = $gifCreator->fileName('menu/');
241  }
242  $this->result[$resKey][$key] = $conf[$key];
243  // Generation of image file:
244  // File exists
245  if (file_exists($gifFileName)) {
246  $info = @getimagesize($gifFileName);
247  $this->result[$resKey][$key]['output_w'] = (int)$info[0];
248  $this->result[$resKey][$key]['output_h'] = (int)$info[1];
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  $this->WMsubmenuObjSuffixes = $this->tmpl->splitConfArray(['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 
481  public function extProc_init()
482  {
483  }
484 
493  public function extProc_RO($key)
494  {
495  }
496 
505  public function extProc_beforeLinking($key)
506  {
507  }
508 
520  public function extProc_afterLinking($key)
521  {
522  // Add part to the accumulated result + fetch submenus
523  if (!$this->I['spacer']) {
524  $this->I['theItem'] .= $this->subMenu($this->I['uid'], $this->WMsubmenuObjSuffixes[$key]['sOSuffix']);
525  }
526  $part = isset($this->I['val']['wrapItemAndSub.']) ? $this->WMcObj->stdWrap($this->I['val']['wrapItemAndSub'], $this->I['val']['wrapItemAndSub.']) : $this->I['val']['wrapItemAndSub'];
527  $this->WMresult .= $part ? $this->WMcObj->wrap($this->I['theItem'], $part) : $this->I['theItem'];
528  }
529 
539  public function extProc_beforeAllWrap($item, $key)
540  {
541  return $item;
542  }
543 
551  public function extProc_finish()
552  {
553  // stdWrap:
554  if (is_array($this->mconf['stdWrap.'])) {
555  $this->WMresult = $this->WMcObj->stdWrap($this->WMresult, $this->mconf['stdWrap.']);
556  }
557  return $this->WMcObj->wrap($this->WMresult, $this->mconf['wrap']) . $this->WMextraScript;
558  }
559 }
findLargestDims($conf, $items, $Hobjs, $Wobjs, $minDim, $maxDim)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
debug($variable= '', $name= '*variable *', $line= '*line *', $file= '*file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)