[TASK] Use strict comparison for strings
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / Controller / UserElementsController.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 use Psr\Http\Message\ResponseInterface;
17 use Psr\Http\Message\ServerRequestInterface;
18 use TYPO3\CMS\Core\Configuration\Richtext;
19 use TYPO3\CMS\Core\Utility\ArrayUtility;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * User defined content for htmlArea RTE
24 */
25 class UserElementsController
26 {
27 /**
28 * @var string
29 */
30 public $content;
31
32 /**
33 * @var array
34 */
35 public $modData;
36
37 /**
38 * @var string
39 */
40 public $siteUrl;
41
42 /**
43 * document template object
44 *
45 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
46 */
47 public $doc;
48
49 /**
50 * @var string
51 */
52 public $editorNo;
53
54 /**
55 * Initialize language files
56 */
57 public function __construct()
58 {
59 $GLOBALS['LANG']->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_userelementscontroller.xlf');
60 $GLOBALS['LANG']->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_dialogs.xlf');
61
62 $this->init();
63 }
64
65 /**
66 * @return void
67 */
68 public function init()
69 {
70 $this->editorNo = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('editorNo');
71 $this->siteUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
72 $this->doc = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
73 $this->doc->bodyTagAdditions = 'onload="Init();"';
74 $this->doc->form = '
75 <form action="" id="process" name="process" method="post">
76 <input type="hidden" name="processContent" value="" />
77 <input type="hidden" name="returnUrl" value="' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI')) . '" />
78 ';
79 $JScode = '
80 var plugin = window.parent.RTEarea["' . $this->editorNo . '"].editor.getPlugin("UserElements");
81 var HTMLArea = window.parent.HTMLArea;
82 var editor = plugin.editor;
83
84 function Init() {
85 };
86 function insertHTML(content,noHide) {
87 plugin.restoreSelection();
88 editor.getSelection().insertHtml(content);
89 if(!noHide) plugin.close();
90 };
91 function wrapHTML(wrap1,wrap2,noHide) {
92 plugin.restoreSelection();
93 if(!editor.getSelection().isEmpty()) {
94 editor.getSelection().surroundHtml(wrap1,wrap2);
95 } else {
96 alert(' . GeneralUtility::quoteJSvalue($GLOBALS['LANG']->getLL('noTextSelection')) . ');
97 }
98 if(!noHide) plugin.close();
99 };
100 function processSelection(script) {
101 plugin.restoreSelection();
102 document.process.action = script;
103 document.process.processContent.value = editor.getSelection().getHtml();
104 document.process.submit();
105 };
106 function jumpToUrl(URL) {
107 var RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RTEtsConfigParams')) . '";
108 var editorNo = "&editorNo=' . rawurlencode($this->editorNo) . '";
109 theLocation = URL+RTEtsConfigParams+editorNo;
110 window.location.href = theLocation;
111 }
112 ';
113
114 // unset the default jumpToUrl() function
115 unset($this->doc->JScodeArray['jumpToUrl']);
116
117 $this->doc->JScode = GeneralUtility::wrapJS($JScode);
118 $this->modData = $GLOBALS['BE_USER']->getModuleData('user.php', 'ses');
119 if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('OC_key')) {
120 $parts = explode('|', \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('OC_key'));
121 $this->modData['openKeys'][$parts[1]] = $parts[0] === 'O' ? 1 : 0;
122 $GLOBALS['BE_USER']->pushModuleData('user.php', $this->modData);
123 }
124 }
125
126 /**
127 * Injects the request object for the current request or subrequest
128 * As this controller goes only through the main_user() method, it is rather simple for now
129 *
130 * @param ServerRequestInterface $request the current request
131 * @param ResponseInterface $response the prepared response object
132 * @return ResponseInterface the response with the content
133 */
134 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
135 {
136 $content = $this->main_user($this->modData['openKeys']);
137 $response->getBody()->write($content);
138 return $response;
139 }
140
141 /********************************
142 *
143 * Other functions
144 *
145 *********************************/
146 /**
147 * @param array $imgInfo
148 * @param int $maxW
149 * @param int $maxH
150 * @return array
151 */
152 public function calcWH($imgInfo, $maxW = 380, $maxH = 500)
153 {
154 $IW = $imgInfo[0];
155 $IH = $imgInfo[1];
156 if ($IW > $maxW) {
157 $IH = ceil($IH / $IW * $maxW);
158 $IW = $maxW;
159 }
160 if ($IH > $maxH) {
161 $IW = ceil($IW / $IH * $maxH);
162 $IH = $maxH;
163 }
164 $imgInfo[3] = 'width="' . $IW . '" height="' . $IH . '"';
165 return $imgInfo;
166 }
167
168 /**
169 * Rich Text Editor (RTE) user element selector
170 *
171 * @param array $openKeys
172 * @return string
173 */
174 public function main_user($openKeys)
175 {
176 // Starting content:
177 $content = $this->doc->startPage(htmlspecialchars($GLOBALS['LANG']->getLL('Insert Custom Element')));
178
179 // @todo: This needs refactoring to enable sane config in flex form, either transfer parts of 'config', or use data providers
180 $RTEtsConfigParts = explode(':', GeneralUtility::_GP('RTEtsConfigParams'));
181 $table = $RTEtsConfigParts[0];
182 $field = $RTEtsConfigParts[2];
183 $recordType = $RTEtsConfigParts[3];
184 $tcaConfigOfField = $GLOBALS['TCA'][$table][$field]['config'] ?? [];
185 $columnsOverridesConfigOfField = $GLOBALS['TCA'][$table]['types'][$recordType]['columnsOverrides'][$field]['config'] ?? [];
186 if (!empty($columnsOverridesConfigOfField)) {
187 ArrayUtility::mergeRecursiveWithOverrule($tcaConfigOfField, $columnsOverridesConfigOfField);
188 }
189 $richtextConfigurationProvider = GeneralUtility::makeInstance(Richtext::class);
190 $richtextConfiguration = $richtextConfigurationProvider->getConfiguration(
191 $RTEtsConfigParts[0],
192 $RTEtsConfigParts[2],
193 $RTEtsConfigParts[3],
194 $RTEtsConfigParts[4],
195 $tcaConfigOfField
196 );
197 $thisConfig = $richtextConfiguration;
198
199 if (is_array($thisConfig['userElements.'])) {
200 $categories = [];
201 foreach ($thisConfig['userElements.'] as $k => $value) {
202 $ki = (int)$k;
203 $v = $thisConfig['userElements.'][$ki . '.'];
204 if (substr($k, -1) === '.' && is_array($v)) {
205 $subcats = [];
206 $openK = $ki;
207 if ($openKeys[$openK]) {
208 $mArray = '';
209 if ($v['load'] === 'images_from_folder') {
210 $mArray = [];
211 if ($v['path'] && @is_dir((PATH_site . $v['path']))) {
212 $files = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir(PATH_site . $v['path'], 'gif,jpg,jpeg,png', 0, '');
213 if (is_array($files)) {
214 $c = 0;
215 foreach ($files as $filename) {
216 $iInfo = @getimagesize((PATH_site . $v['path'] . $filename));
217 $iInfo = $this->calcWH($iInfo, 50, 100);
218 $ks = (string)(100 + $c);
219 $mArray[$ks] = $filename;
220 $mArray[$ks . '.'] = [
221 'content' => '<img src="' . $this->siteUrl . $v['path'] . $filename . '" />',
222 '_icon' => '<img src="' . $this->siteUrl . $v['path'] . $filename . '" ' . $iInfo[3] . ' />',
223 'description' => $GLOBALS['LANG']->getLL('filesize') . ': ' . str_replace('&nbsp;', ' ', \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize(@filesize((PATH_site . $v['path'] . $filename)))) . ', ' . htmlspecialchars($GLOBALS['LANG']->getLL('pixels')) . ': ' . $iInfo[0] . 'x' . $iInfo[1]
224 ];
225 $c++;
226 }
227 }
228 }
229 }
230 if (is_array($mArray)) {
231 if ($v['merge']) {
232 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($mArray, $v);
233 $v = $mArray;
234 } else {
235 $v = $mArray;
236 }
237 }
238 foreach ($v as $k2 => $dummyValue) {
239 $k2i = (int)$k2;
240 if (substr($k2, -1) === '.' && is_array($v[$k2i . '.'])) {
241 $title = trim($v[$k2i]);
242 if (!$title) {
243 $title = '[' . htmlspecialchars($GLOBALS['LANG']->getLL('noTitle')) . ']';
244 } else {
245 $title = htmlspecialchars($GLOBALS['LANG']->sL($title));
246 }
247 $description = htmlspecialchars($GLOBALS['LANG']->sL($v[$k2i . '.']['description'])) . '<br />';
248 if (!$v[$k2i . '.']['dontInsertSiteUrl']) {
249 $v[$k2i . '.']['content'] = str_replace('###_URL###', $this->siteUrl, $v[$k2i . '.']['content']);
250 }
251 $logo = $v[$k2i . '.']['_icon'] ?: '';
252 $onClickEvent = '';
253 switch ((string)$v[$k2i . '.']['mode']) {
254 case 'wrap':
255 $wrap = explode('|', $v[$k2i . '.']['content']);
256 $onClickEvent = 'wrapHTML(' . GeneralUtility::quoteJSvalue($wrap[0]) . ',' . GeneralUtility::quoteJSvalue($wrap[1]) . ',false);';
257 break;
258 case 'processor':
259 $script = trim($v[$k2i . '.']['submitToScript']);
260 if (substr($script, 0, 4) !== 'http') {
261 $script = $this->siteUrl . $script;
262 }
263 if ($script) {
264 $onClickEvent = 'processSelection(' . GeneralUtility::quoteJSvalue($script) . ');';
265 }
266 break;
267 case 'insert':
268
269 default:
270 $onClickEvent = 'insertHTML(' . GeneralUtility::quoteJSvalue($v[$k2i . '.']['content']) . ');';
271 }
272 $A = ['<a href="#" onClick="' . $onClickEvent . 'return false;">', '</a>'];
273 $subcats[$k2i] = '<tr>
274 <td></td>
275 <td>' . $A[0] . $logo . $A[1] . '</td>
276 <td>' . $A[0] . '<strong>' . $title . '</strong><br />' . $description . $A[1] . '</td>
277 </tr>';
278 }
279 }
280 ksort($subcats);
281 }
282 $categories[$ki] = implode('', $subcats);
283 }
284 }
285 ksort($categories);
286 // Render menu of the items:
287 $lines = [];
288 foreach ($categories as $k => $v) {
289 $title = trim($thisConfig['userElements.'][$k]);
290 $openK = $k;
291 if (!$title) {
292 $title = '[' . htmlspecialchars($GLOBALS['LANG']->getLL('noTitle')) . ']';
293 } else {
294 $title = htmlspecialchars($GLOBALS['LANG']->sL($title));
295 }
296
297 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
298 $url = (string)$uriBuilder->buildUriFromRoute('rtehtmlarea_wizard_user_elements', ['OC_key' => ($openKeys[$openK] ? 'C|' : 'O|') . $openK]);
299
300 $lines[] = '<tr><td colspan="3"><a href="#" title="' . htmlspecialchars($GLOBALS['LANG']->getLL('expand')) . '" onClick="jumpToUrl(' . GeneralUtility::quoteJSvalue($url) . ');return false;"><i class="fa fa-caret-square-o-' . ($openKeys[$openK] ? 'left' : 'right') . '" title="' . htmlspecialchars($GLOBALS['LANG']->getLL('expand')) . '"></i><strong>' . $title . '</strong></a></td></tr>';
301 $lines[] = $v;
302 }
303 $content .= '<table class="table table-striped table-hover">' . implode('', $lines) . '</table>';
304 }
305 $content .= $this->doc->endPage();
306 return $content;
307 }
308 }