[TASK] Apply CGL compatibility (PSR-1 and PSR-2)
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / Controller / SelectImageController.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea\Controller;
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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Core\Resource\ResourceFactory;
21 use TYPO3\CMS\Core\Resource\Service\MagicImageService;
22 use TYPO3\CMS\Core\Service\DependencyOrderingService;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
25 use TYPO3\CMS\Recordlist\LinkHandler\LinkHandlerInterface;
26
27 /**
28 * Script class to select images in RTE
29 */
30 class SelectImageController extends AbstractLinkBrowserController
31 {
32 /**
33 * These file extensions are allowed in the "plain" image selection mode.
34 *
35 * @const
36 */
37 const PLAIN_MODE_IMAGE_FILE_EXTENSIONS = 'jpg,jpeg,gif,png';
38
39 /**
40 * Active with TYPO3 Element Browser: Contains the name of the form field for which this window
41 * opens - thus allows us to make references back to the main window in which the form is.
42 * Example value: "data[pages][39][bodytext]|||tt_content|"
43 * or "data[tt_content][NEW3fba56fde763d][image]|||gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai|"
44 *
45 * Values:
46 * 0: form field name reference, eg. "data[tt_content][123][image]"
47 * 1: htmlArea RTE parameters: editorNo:contentTypo3Language
48 * 2: RTE config parameters: RTEtsConfigParams
49 * 3: allowed types. Eg. "tt_content" or "gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai"
50 *
51 * $pArr = explode('|', $this->bparams);
52 * $formFieldName = $pArr[0];
53 * $allowedTablesOrFileTypes = $pArr[3];
54 *
55 * @var string
56 */
57 protected $bparams;
58
59 /**
60 * RTE configuration
61 *
62 * @var array
63 */
64 protected $RTEProperties = [];
65
66 /**
67 * Used with the Rich Text Editor.
68 * Example value: "tt_content:NEW3fba58c969f5c:bodytext:23:text:23:"
69 *
70 * @var string
71 */
72 protected $RTEtsConfigParams;
73
74 /**
75 * @var int
76 */
77 protected $editorNo;
78
79 /**
80 * TYPO3 language code of the content language
81 *
82 * @var int
83 */
84 protected $contentTypo3Language;
85
86 /**
87 * @var array
88 */
89 protected $buttonConfig = [];
90
91 /**
92 * Initialize controller
93 */
94 protected function init()
95 {
96 parent::init();
97 $this->getLanguageService()->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_dialogs.xlf');
98 }
99
100 /**
101 * @param ServerRequestInterface $request
102 */
103 protected function initVariables(ServerRequestInterface $request)
104 {
105 parent::initVariables($request);
106
107 $queryParameters = $request->getQueryParams();
108 $this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
109 $this->currentLinkParts['currentImage'] = !empty($queryParameters['fileUid']) ? $queryParameters['fileUid'] : 0;
110
111 // Process bparams
112 $pArr = explode('|', $this->bparams);
113 $pRteArr = explode(':', $pArr[1]);
114 $this->editorNo = $pRteArr[0];
115 $this->contentTypo3Language = $pRteArr[1];
116 $this->RTEtsConfigParams = $pArr[2];
117 if (!$this->editorNo) {
118 $this->editorNo = GeneralUtility::_GP('editorNo');
119 $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
120 $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
121 }
122 $pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language));
123 $pArr[2] = $this->RTEtsConfigParams;
124 $pArr[3] = $this->displayedLinkHandlerId === 'plain'
125 ? self::PLAIN_MODE_IMAGE_FILE_EXTENSIONS
126 : '';
127 $this->bparams = implode('|', $pArr);
128
129 $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
130 $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
131 $this->RTEProperties = $RTEsetup['properties'];
132
133 $thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
134 $this->buttonConfig = isset($thisConfig['buttons.']['image.'])
135 ? $thisConfig['buttons.']['image.']
136 : [];
137 }
138
139 /**
140 * Initialize hook objects implementing the interface
141 *
142 * @throws \UnexpectedValueException
143 * @return void
144 */
145 protected function initHookObjects()
146 {
147 if (
148 isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RteImageSelector']['hooks'])
149 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RteImageSelector']['hooks'])
150 ) {
151 $hooks = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies(
152 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RteImageSelector']['hooks']
153 );
154 foreach ($hooks as $key => $hook) {
155 $this->hookObjects[] = GeneralUtility::makeInstance($hook['handler']);
156 }
157 }
158 }
159
160 /**
161 * Reads the configured image handlers from page TSconfig
162 *
163 * @return array
164 * @throws \UnexpectedValueException
165 */
166 protected function getLinkHandlers()
167 {
168 $imageHandler = $this->buttonConfig['options.']['imageHandler.'];
169
170 foreach ($this->hookObjects as $hookObject) {
171 if (method_exists($hookObject, 'modifyImageHandlers')) {
172 $imageHandler = $hookObject->modifyImageHandlers($imageHandler, $this->currentLinkParts);
173 }
174 }
175
176 if (empty($imageHandler)) {
177 throw new \UnexpectedValueException('No image handlers are configured. Check page TSconfig RTE.default.buttons.image.options.imageHandler.', 1455499673);
178 }
179
180 return $imageHandler;
181 }
182
183 /**
184 * Initialize $this->currentLinkParts and $this->currentLinkHandler
185 *
186 * @return void
187 */
188 protected function initCurrentUrl()
189 {
190 if (empty($this->currentLinkParts)) {
191 return;
192 }
193
194 $orderedHandlers = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($this->linkHandlers, 'scanBefore', 'scanAfter');
195
196 // find responsible handler for current image
197 foreach ($orderedHandlers as $key => $configuration) {
198 /** @var LinkHandlerInterface $handler */
199 $handler = $configuration['handlerInstance'];
200 if ($handler->canHandleLink($this->currentLinkParts)) {
201 $this->currentLinkHandler = $handler;
202 $this->currentLinkHandlerId = $key;
203 break;
204 }
205 }
206 // reset the image reference if we have no handler for it
207 if (!$this->currentLinkHandler) {
208 $this->currentLinkParts = [];
209 }
210 }
211
212 /**
213 * Render the currently set URL
214 *
215 * @return string
216 */
217 protected function renderCurrentUrl()
218 {
219 return '<!-- Print current URL -->
220 <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
221 <tr>
222 <td>' . htmlspecialchars($this->getLanguageService()->getLL('currentImage')) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . '</td>
223 </tr>
224 </table>';
225 }
226
227 /**
228 * Get the allowed items or tabs
229 *
230 * @return string[]
231 */
232 protected function getAllowedItems()
233 {
234 $allowedItems = array_keys($this->linkHandlers);
235
236 foreach ($this->hookObjects as $hookObject) {
237 if (method_exists($hookObject, 'modifyAllowedItems')) {
238 $allowedItems = $hookObject->modifyAllowedItems($allowedItems, $this->currentLinkParts);
239 }
240 }
241
242 return $allowedItems;
243 }
244
245 /**
246 * @param array $overrides
247 *
248 * @return array Array of parameters which have to be added to URLs
249 */
250 public function getUrlParameters(array $overrides = null)
251 {
252 return [
253 'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId,
254 'bparams' => $this->bparams,
255 'editorNo' => $this->editorNo
256 ];
257 }
258
259 /**
260 * @return array
261 */
262 public function getButtonConfiguration()
263 {
264 return $this->buttonConfig;
265 }
266
267 /**
268 * @return array
269 */
270 public function getRteProperties()
271 {
272 return $this->RTEProperties;
273 }
274
275 /**
276 * Compile the final tags to be inserted into RTE
277 *
278 * @param ServerRequestInterface $request
279 * @param ResponseInterface $response
280 * @return ResponseInterface
281 */
282 public function buildImageMarkup(ServerRequestInterface $request, ResponseInterface $response)
283 {
284 $this->initVariables($request);
285 $uidList = GeneralUtility::_GP('uidList');
286 // handle ajax request for
287 $uids = explode('|', $uidList);
288 $tags = array();
289 foreach ($uids as $uid) {
290 $fileObject = ResourceFactory::getInstance()->getFileObject((int)$uid);
291 // Get default values for alt and title attributes from file properties
292 $altText = $fileObject->getProperty('alternative');
293 $titleText = $fileObject->getProperty('title');
294 if ($this->displayedLinkHandlerId === 'magic') {
295 // Create the magic image service
296 $magicImageService = GeneralUtility::makeInstance(MagicImageService::class);
297 $magicImageService->setMagicImageMaximumDimensions($this->RTEProperties['default.']);
298 // Create the magic image
299 $imageConfiguration = array(
300 'width' => GeneralUtility::_GP('cWidth'),
301 'height' => GeneralUtility::_GP('cHeight')
302 );
303 $fileObject = $magicImageService->createMagicImage($fileObject, $imageConfiguration);
304 $width = $fileObject->getProperty('width');
305 $height = $fileObject->getProperty('height');
306 } else {
307 $width = $fileObject->getProperty('width');
308 $height = $fileObject->getProperty('height');
309 if (!$width || !$height) {
310 $filePath = $fileObject->getForLocalProcessing(false);
311 $imageInfo = @getimagesize($filePath);
312 $width = $imageInfo[0];
313 $height = $imageInfo[1];
314 }
315 }
316 $imageUrl = $fileObject->getPublicUrl();
317 // If file is local, make the url absolute
318 if (strpos($imageUrl, 'http') !== 0) {
319 $imageUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . $imageUrl;
320 }
321 $tags[] = '<img src="' . htmlspecialchars($imageUrl) . '" width="' . htmlspecialchars($width) . '" height="' . htmlspecialchars($height) . '"'
322 . (isset($this->buttonConfig['properties.']['class.']['default'])
323 ? ' class="' . trim($this->buttonConfig['properties.']['class.']['default']) . '"'
324 : '')
325 . ' alt = "' . ($altText ? htmlspecialchars($altText) : '') . '"'
326 . ($titleText ? ' title="' . htmlspecialchars($titleText) . '"' : '')
327 . ' data-htmlarea-file-uid="' . (int)$uid . '" />';
328 }
329 $finalHtmlCode = implode(' ', $tags);
330
331 $response->getBody()->write(json_encode(['images' => $finalHtmlCode]));
332 return $response;
333 }
334
335 /**
336 * Return the ID of current page
337 *
338 * @return int
339 * @throws \RuntimeException
340 */
341 protected function getCurrentPageId()
342 {
343 throw new \RuntimeException('Invalid method call. This function is not supported for image handlers', 14554996791);
344 }
345 }