6f44386cb0ac212852df51687c9d34af0911ed5f
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / Menu / ImageMenuContentObject.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\Frontend\Imaging\GifBuilder;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Core\TypoScript\TemplateService;
20 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
21 use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
22
23 /**
24 * ImageMap based menus
25 *
26 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
27 */
28 class ImageMenuContentObject extends AbstractMenuContentObject {
29
30 /**
31 * Calls procesItemStates() so that the common configuration for the menu items are resolved into individual configuration per item.
32 * Calls makeImageMap() to generate the image map image-file
33 *
34 * @return void
35 * @see AbstractMenuContentObject::procesItemStates(), makeImageMap()
36 */
37 public function generate() {
38 $NOconf = array();
39 $splitCount = count($this->menuArr);
40 if ($splitCount) {
41 list($NOconf) = $this->procesItemStates($splitCount);
42 }
43 if (!empty($this->mconf['debugItemConf'])) {
44 echo '<h3>$NOconf:</h3>';
45 debug($NOconf);
46 }
47 $this->makeImageMap($NOconf);
48 }
49
50 /**
51 * Will traverse input array with configuration per-item and create corresponding GIF files for the menu.
52 * The data of the files are stored in $this->result
53 *
54 * @param array $conf Array with configuration for each item.
55 * @return void
56 * @access private
57 * @see generate()
58 */
59 public function makeImageMap($conf) {
60 if (!is_array($conf)) {
61 $conf = array();
62 }
63 if (is_array($this->mconf['main.'])) {
64 $gifCreator = GeneralUtility::makeInstance(GifBuilder::class);
65 $gifCreator->init();
66 $itemsConf = $conf;
67 $conf = $this->mconf['main.'];
68 if (is_array($conf)) {
69 $sKeyArray = TemplateService::sortedKeyList($conf);
70 $gifObjCount = (int)end($sKeyArray);
71 // Now we add graphical objects to the gifbuilder-setup
72 $waArr = array();
73 foreach ($itemsConf as $key => $val) {
74 if (is_array($val)) {
75 $gifObjCount++;
76 $waArr[$key]['free'] = $gifObjCount;
77 $sKeyArray = TemplateService::sortedKeyList($val);
78 foreach ($sKeyArray as $theKey) {
79 $theValue = $val[$theKey];
80 if ((int)$theKey && ($theValArr = $val[$theKey . '.'])) {
81 $cObjData = $this->menuArr[$key] ?: array();
82 $gifObjCount++;
83 if ($theValue === 'TEXT') {
84 $waArr[$key]['textNum'] = $gifObjCount;
85 $gifCreator->data = $cObjData;
86 $theValArr = $gifCreator->checkTextObj($theValArr);
87 // if this is not done it seems that imageMaps will be rendered wrong!!
88 unset($theValArr['text.']);
89 // check links
90 $LD = $this->menuTypoLink($this->menuArr[$key], $this->mconf['target'], '', '', array(), '', $this->mconf['forceTypeValue']);
91 // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
92 $this->changeLinksForAccessRestrictedPages($LD, $this->menuArr[$key], $this->mconf['target'], $this->mconf['forceTypeValue']);
93 // Overriding URL / Target if set to do so:
94 if ($this->menuArr[$key]['_OVERRIDE_HREF']) {
95 $LD['totalURL'] = $this->menuArr[$key]['_OVERRIDE_HREF'];
96 if ($this->menuArr[$key]['_OVERRIDE_TARGET']) {
97 $LD['target'] = $this->menuArr[$key]['_OVERRIDE_TARGET'];
98 }
99 }
100 // Setting target/url for Image Map:
101 if ($theValArr['imgMap.']['url'] === '') {
102 $theValArr['imgMap.']['url'] = $LD['totalURL'];
103 }
104 if ($theValArr['imgMap.']['target'] === '') {
105 $theValArr['imgMap.']['target'] = $LD['target'];
106 }
107 if (is_array($theValArr['imgMap.']['altText.'])) {
108 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
109 $cObj->start($cObjData, 'pages');
110 if (isset($theValArr['imgMap.']['altText.'])) {
111 $theValArr['imgMap.']['altText'] = $cObj->stdWrap($theValArr['imgMap.']['altText'], $theValArr['imgMap.']['altText.']);
112 }
113 unset($theValArr['imgMap.']['altText.']);
114 }
115 if (is_array($theValArr['imgMap.']['titleText.'])) {
116 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
117 $cObj->start($cObjData, 'pages');
118 if (isset($theValArr['imgMap.']['titleText.'])) {
119 $theValArr['imgMap.']['titleText'] = $cObj->stdWrap($theValArr['imgMap.']['titleText'], $theValArr['imgMap.']['titleText.']);
120 }
121 unset($theValArr['imgMap.']['titleText.']);
122 }
123 }
124 // This code goes one level in if the object is an image. If 'file' and/or 'mask' appears to be GIFBUILDER-objects, they are both searched for TEXT objects, and if a textobj is found, it's checked with the currently loaded record!!
125 if ($theValue === 'IMAGE') {
126 if ($theValArr['file'] === 'GIFBUILDER') {
127 $temp_sKeyArray = TemplateService::sortedKeyList($theValArr['file.']);
128 foreach ($temp_sKeyArray as $temp_theKey) {
129 if ($theValArr['mask.'][$temp_theKey] === 'TEXT') {
130 $gifCreator->data = $this->menuArr[$key] ?: array();
131 $theValArr['mask.'][$temp_theKey . '.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey . '.']);
132 // If this is not done it seems that imageMaps will be rendered wrong!!
133 unset($theValArr['mask.'][$temp_theKey . '.']['text.']);
134 }
135 }
136 }
137 if ($theValArr['mask'] === 'GIFBUILDER') {
138 $temp_sKeyArray = TemplateService::sortedKeyList($theValArr['mask.']);
139 foreach ($temp_sKeyArray as $temp_theKey) {
140 if ($theValArr['mask.'][$temp_theKey] === 'TEXT') {
141 $gifCreator->data = $this->menuArr[$key] ?: array();
142 $theValArr['mask.'][$temp_theKey . '.'] = $gifCreator->checkTextObj($theValArr['mask.'][$temp_theKey . '.']);
143 // if this is not done it seems that imageMaps will be rendered wrong!!
144 unset($theValArr['mask.'][$temp_theKey . '.']['text.']);
145 }
146 }
147 }
148 }
149 // Checks if disabled is set...
150 $setObjFlag = 1;
151 if ($theValArr['if.']) {
152 /** @var ContentObjectRenderer $cObj */
153 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
154 $cObj->start($cObjData, 'pages');
155 if (!empty($theValArr['if.']) && !$cObj->checkIf($theValArr['if.'])) {
156 $setObjFlag = 0;
157 }
158 unset($theValArr['if.']);
159 }
160 // Set the object!
161 if ($setObjFlag) {
162 $conf[$gifObjCount] = $theValue;
163 $conf[$gifObjCount . '.'] = $theValArr;
164 }
165 }
166 }
167 }
168 }
169 $gifCreator->start($conf, $this->getTypoScriptFrontendController()->page);
170 // calculations
171 $dConf = array();
172 foreach ($waArr as $key => $val) {
173 if ($dConf[$key] = $itemsConf[$key]['distrib']) {
174 $textBB = $gifCreator->objBB[$val['textNum']];
175 $dConf[$key] = str_replace(
176 array('textX', 'textY'),
177 array($textBB[0], $textBB[1]),
178 $dConf[$key]
179 );
180 $dConf[$key] = GeneralUtility::intExplode(',', $gifCreator->calcOffset($dConf[$key]));
181 }
182 }
183 $workArea = GeneralUtility::intExplode(',', $gifCreator->calcOffset($this->mconf['dWorkArea']));
184 foreach ($waArr as $key => $val) {
185 $index = $val['free'];
186 $gifCreator->setup[$index] = 'WORKAREA';
187 $workArea[2] = $dConf[$key][2] ?: $dConf[$key][0];
188 $workArea[3] = $dConf[$key][3] ?: $dConf[$key][1];
189 $gifCreator->setup[$index . '.']['set'] = implode(',', $workArea);
190 $workArea[0] += $dConf[$key][0];
191 $workArea[1] += $dConf[$key][1];
192 }
193 if ($this->mconf['debugRenumberedObject']) {
194 echo '<h3>Renumbered GIFBUILDER object:</h3>';
195 debug($gifCreator->setup);
196 }
197 $gifCreator->createTempSubDir('menu/');
198 $gifFileName = $gifCreator->fileName('menu/');
199 // Gets the ImageMap from the cache...
200 $cache = $this->getCache();
201 $imgHash = md5($gifFileName);
202 $imgMap = $cache->get($imgHash);
203 // File exists
204 if ($imgMap && file_exists($gifFileName)) {
205 $info = @getimagesize($gifFileName);
206 $w = $info[0];
207 $h = $info[1];
208 } else {
209 // file is generated
210 $gifCreator->make();
211 $w = $gifCreator->w;
212 $h = $gifCreator->h;
213 $gifCreator->output($gifFileName);
214 $gifCreator->destroy();
215 $imgMap = $gifCreator->map;
216 $cache->set($imgHash, $imgMap, array('ident_MENUIMAGEMAP'), 0);
217 }
218 $imgMap .= $this->mconf['imgMapExtras'];
219 $gifFileName = GraphicalFunctions::pngToGifByImagemagick($gifFileName);
220 $this->result = array('output_file' => $gifFileName, 'output_w' => $w, 'output_h' => $h, 'imgMap' => $imgMap);
221 }
222 }
223 }
224
225 /**
226 * Returns the HTML for the image map menu.
227 * If ->result is TRUE it will create the HTML for the image map menu.
228 *
229 * @return string The HTML for the menu
230 */
231 public function writeMenu() {
232 if ($this->result) {
233 $res = $this->result;
234 // shortMD5 260900
235 $menuName = 'menu_' . GeneralUtility::shortMD5($res['imgMap']);
236 $result = '<img src="' . $this->getTypoScriptFrontendController()->absRefPrefix . $res['output_file'] . '" width="' . $res['output_w'] . '" height="' . $res['output_h'] . '" usemap="#' . $menuName . '" border="0" ' . $this->mconf['params'];
237 // Adding alt attribute if not set.
238 if (!strstr($result, 'alt="')) {
239 $result .= ' alt="Menu Image Map"';
240 }
241 $result .= ' /><map name="' . $menuName . '" id="' . $menuName . '">' . $res['imgMap'] . '</map>';
242 $this->getTypoScriptFrontendController()->imagesOnPage[] = $res['output_file'];
243 return $this->WMcObj->wrap($result, $this->mconf['wrap']);
244 }
245 return '';
246 }
247
248 }