[TASK] Deprecate ExtensionManagementUtility::extRelPath
[Packages/TYPO3.CMS.git] / typo3 / sysext / t3editor / Classes / Form / Element / T3editorElement.php
1 <?php
2 namespace TYPO3\CMS\T3editor\Form\Element;
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\Backend\Form\Element\AbstractFormElement;
18 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
19 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Core\Utility\MathUtility;
22 use TYPO3\CMS\Core\Utility\PathUtility;
23 use TYPO3\CMS\Lang\LanguageService;
24 use TYPO3\CMS\T3editor\T3editor;
25
26 /**
27 * t3editor FormEngine widget
28 */
29 class T3editorElement extends AbstractFormElement
30 {
31 const MODE_CSS = 'css';
32 const MODE_HTML = 'html';
33 const MODE_JAVASCRIPT = 'javascript';
34 const MODE_MIXED = 'mixed';
35 const MODE_PHP = 'php';
36 const MODE_SPARQL = 'sparql';
37 const MODE_TYPOSCRIPT = 'typoscript';
38 const MODE_XML = 'xml';
39
40 /**
41 * @var array
42 */
43 protected $allowedModes = [
44 self::MODE_CSS,
45 self::MODE_HTML,
46 self::MODE_JAVASCRIPT,
47 self::MODE_MIXED,
48 self::MODE_PHP,
49 self::MODE_SPARQL,
50 self::MODE_TYPOSCRIPT,
51 self::MODE_XML,
52 ];
53
54 /**
55 * @var array
56 */
57 protected $resultArray;
58
59 /**
60 * @var string
61 */
62 protected $mode = '';
63
64 /**
65 * Counts the editors on the current page
66 *
67 * @var int
68 */
69 protected $editorCounter = 0;
70
71 /**
72 * Relative path to EXT:t3editor
73 *
74 * @var string
75 */
76 protected $extPath = '';
77
78 /**
79 * @var string
80 */
81 protected $codemirrorPath = 'Resources/Public/JavaScript/Contrib/codemirror/js/';
82
83 /**
84 * RequireJS modules loaded for code completion
85 *
86 * @var array
87 */
88 protected $codeCompletionComponents = ['TsRef', 'CompletionResult', 'TsParser', 'TsCodeCompletion'];
89
90 /**
91 * Render t3editor element
92 *
93 * @return array As defined in initializeResultArray() of AbstractNode
94 */
95 public function render()
96 {
97 $this->getLanguageService()->includeLLFile('EXT:t3editor/Resources/Private/Language/locallang.xlf');
98 $this->extPath = PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('t3editor'));
99 $this->codemirrorPath = $this->extPath . $this->codemirrorPath;
100
101 $this->resultArray = $this->initializeResultArray();
102
103 $parameterArray = $this->data['parameterArray'];
104
105 $rows = MathUtility::forceIntegerInRange($parameterArray['fieldConf']['config']['rows'] ?: 10, 1, 40);
106 $this->setMode(isset($parameterArray['fieldConf']['config']['format']) ? $parameterArray['fieldConf']['config']['format'] : T3editor::MODE_MIXED);
107
108 $attributes = [];
109 $attributes['rows'] = $rows;
110 $attributes['wrap'] = 'off';
111 $attributes['style'] = 'width:100%;';
112 $attributes['onchange'] = GeneralUtility::quoteJSvalue($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']);
113
114 $attributeString = '';
115 foreach ($attributes as $param => $value) {
116 $attributeString .= $param . '="' . htmlspecialchars($value) . '" ';
117 }
118
119 $this->resultArray['html'] = $this->getHTMLCodeForEditor(
120 $parameterArray['itemFormElName'],
121 'text-monospace enable-tab',
122 $parameterArray['itemFormElValue'],
123 $attributeString,
124 $this->data['tableName'] . ' > ' . $this->data['fieldName'],
125 ['target' => 0]
126 );
127 $this->resultArray['additionalJavaScriptPost'][] = 'require(["TYPO3/CMS/T3editor/T3editor"], function(T3editor) {T3editor.findAndInitializeEditors();});';
128
129 $this->initJavascriptCode();
130 return $this->resultArray;
131 }
132
133 /**
134 * Sets the type of code to edit, use one of the predefined constants
135 *
136 * @param string $mode Expects one of the predefined constants
137 * @throws \InvalidArgumentException
138 */
139 public function setMode($mode)
140 {
141 if (!in_array($mode, $this->allowedModes, true)) {
142 throw new \InvalidArgumentException($mode . 'is not allowed', 1438352574);
143 }
144 $this->mode = $mode;
145 }
146
147 /**
148 * Get mode
149 *
150 * @return string
151 */
152 public function getMode()
153 {
154 return $this->mode;
155 }
156
157 /**
158 * Init the JavaScript code (header part) for editor
159 */
160 protected function initJavascriptCode()
161 {
162 $this->resultArray['stylesheetFiles'][] = 'EXT:t3editor/Resources/Public/Css/t3editor.css';
163 if ($this->mode === self::MODE_TYPOSCRIPT) {
164 foreach ($this->codeCompletionComponents as $codeCompletionComponent) {
165 $this->resultArray['requireJsModules'][] = 'TYPO3/CMS/T3editor/Plugins/CodeCompletion/' . $codeCompletionComponent;
166 }
167 }
168 }
169
170 /**
171 * Generates HTML with code editor
172 *
173 * @param string $name Name attribute of HTML tag
174 * @param string $class Class attribute of HTML tag
175 * @param string $content Content of the editor
176 * @param string $additionalParams Any additional editor parameters
177 * @param string $alt Alt attribute
178 * @param array $hiddenfields
179 * @return string Generated HTML code for editor
180 */
181 protected function getHTMLCodeForEditor($name, $class = '', $content = '', $additionalParams = '', $alt = '', array $hiddenfields = [])
182 {
183 $code = [];
184 $attributes = [];
185 $attributes['class'] = $class . ' t3editor';
186 $attributes['alt'] = $alt;
187 $attributes['id'] = 't3editor_' . $this->editorCounter;
188 $attributes['name'] = $name;
189 $attributes['data-labels'] = json_encode($this->getLanguageService()->getLabelsWithPrefix('js.', 'label_'));
190 $attributes['data-instance-number'] = $this->editorCounter;
191 $attributes['data-editor-path'] = $this->extPath;
192 $attributes['data-codemirror-path'] = $this->codemirrorPath;
193 $attributes['data-ajaxsavetype'] = ''; // no ajax save in FormEngine at the moment
194 $attributes['data-parserfile'] = $this->getParserfileByMode($this->mode);
195 $attributes['data-stylesheet'] = $this->getStylesheetByMode($this->mode);
196
197 $attributesString = '';
198 foreach ($attributes as $attribute => $value) {
199 $attributesString .= $attribute . '="' . htmlspecialchars($value) . '" ';
200 }
201 $attributesString .= $additionalParams;
202
203 $code[] = '<div class="t3editor">';
204 $code[] = ' <div class="t3e_wrap">';
205 $code[] = str_replace([CR, LF], '', file_get_contents(GeneralUtility::getFileAbsFileName('EXT:t3editor/Resources/Private/Templates/t3editor.html')));
206 $code[] = ' </div>';
207 $code[] = ' <textarea ' . $attributesString . '>' . htmlspecialchars($content) . '</textarea>';
208 $code[] = '</div>';
209
210 if (!empty($hiddenfields)) {
211 foreach ($hiddenfields as $name => $value) {
212 $code[] = '<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />';
213 }
214 }
215 $this->editorCounter++;
216 return implode(LF, $code);
217 }
218
219 /**
220 * Determine the correct parser js file for given mode
221 *
222 * @param string $mode
223 * @return string Parser file name
224 */
225 protected function getParserfileByMode($mode)
226 {
227 $parserfile = [];
228 switch ($mode) {
229 case self::MODE_TYPOSCRIPT:
230 $relPath = '../../../parse_typoscript/';
231 $parserfile = [$relPath . 'tokenizetyposcript.js', $relPath . 'parsetyposcript.js'];
232 break;
233 case self::MODE_JAVASCRIPT:
234 $parserfile = ['tokenizejavascript.js', 'parsejavascript.js'];
235 break;
236 case self::MODE_CSS:
237 $parserfile = ['parsecss.js'];
238 break;
239 case self::MODE_XML:
240 $parserfile = ['parsexml.js'];
241 break;
242 case self::MODE_SPARQL:
243 $parserfile = ['parsesparql.js'];
244 break;
245 case self::MODE_HTML:
246 $parserfile = ['tokenizejavascript.js', 'parsejavascript.js', 'parsecss.js', 'parsexml.js', 'parsehtmlmixed.js'];
247 break;
248 case self::MODE_PHP:
249 case self::MODE_MIXED:
250 $parserfile = ['tokenizejavascript.js', 'parsejavascript.js', 'parsecss.js', 'parsexml.js', '../contrib/php/js/tokenizephp.js', '../contrib/php/js/parsephp.js', '../contrib/php/js/parsephphtmlmixed.js'];
251 break;
252 }
253 return json_encode($parserfile);
254 }
255
256 /**
257 * Determine the correct css file for given mode
258 *
259 * @param string $mode
260 * @return string css file name
261 */
262 protected function getStylesheetByMode($mode)
263 {
264 switch ($mode) {
265 case self::MODE_TYPOSCRIPT:
266 $stylesheet = [$this->extPath . 'Resources/Public/Css/t3editor_typoscript_colors.css'];
267 break;
268 case self::MODE_JAVASCRIPT:
269 $stylesheet = [$this->codemirrorPath . '../css/jscolors.css'];
270 break;
271 case self::MODE_CSS:
272 $stylesheet = [$this->codemirrorPath . '../css/csscolors.css'];
273 break;
274 case self::MODE_XML:
275 $stylesheet = [$this->codemirrorPath . '../css/xmlcolors.css'];
276 break;
277 case self::MODE_HTML:
278 $stylesheet = [$this->codemirrorPath . '../css/xmlcolors.css', $this->codemirrorPath . '../css/jscolors.css', $this->codemirrorPath . '../css/csscolors.css'];
279 break;
280 case self::MODE_SPARQL:
281 $stylesheet = [$this->codemirrorPath . '../css/sparqlcolors.css'];
282 break;
283 case self::MODE_PHP:
284 $stylesheet = [$this->codemirrorPath . '../contrib/php/css/phpcolors.css'];
285 break;
286 case self::MODE_MIXED:
287 $stylesheet = [$this->codemirrorPath . '../css/xmlcolors.css', $this->codemirrorPath . '../css/jscolors.css', $this->codemirrorPath . '../css/csscolors.css', $this->codemirrorPath . '../contrib/php/css/phpcolors.css'];
288 break;
289 default:
290 $stylesheet = [];
291 }
292 $stylesheet[] = $this->extPath . 'Resources/Public/Css/t3editor_inner.css';
293 return json_encode($stylesheet);
294 }
295
296 /**
297 * @return LanguageService
298 */
299 protected function getLanguageService()
300 {
301 return $GLOBALS['LANG'];
302 }
303
304 /**
305 * @return BackendUserAuthentication
306 */
307 protected function getBackendUserAuthentication()
308 {
309 return $GLOBALS['BE_USER'];
310 }
311 }