[TASK] Fix CGL errors
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / File / EditFileController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\File;
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\Module\AbstractModule;
18 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
19 use TYPO3\CMS\Backend\Template\DocumentTemplate;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Core\Imaging\Icon;
22 use TYPO3\CMS\Core\Imaging\IconFactory;
23 use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException;
24 use TYPO3\CMS\Core\Resource\ResourceFactory;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use Psr\Http\Message\ResponseInterface;
27 use Psr\Http\Message\ServerRequestInterface;
28
29 /**
30 * Script Class for rendering the file editing screen
31 */
32 class EditFileController extends AbstractModule
33 {
34 /**
35 * Module content accumulated.
36 *
37 * @var string
38 */
39 public $content;
40
41 /**
42 * @var string
43 */
44 public $title;
45
46 /**
47 * Document template object
48 *
49 * @var DocumentTemplate
50 */
51 public $doc;
52
53 /**
54 * Original input target
55 *
56 * @var string
57 */
58 public $origTarget;
59
60 /**
61 * The original target, but validated.
62 *
63 * @var string
64 */
65 public $target;
66
67 /**
68 * Return URL of list module.
69 *
70 * @var string
71 */
72 public $returnUrl;
73
74 /**
75 * the file that is being edited on
76 *
77 * @var \TYPO3\CMS\Core\Resource\AbstractFile
78 */
79 protected $fileObject;
80
81 /**
82 * Constructor
83 */
84 public function __construct()
85 {
86 parent::__construct();
87 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
88 $GLOBALS['SOBE'] = $this;
89 $this->init();
90 }
91
92 /**
93 * Initialize script class
94 *
95 * @throws InsufficientFileAccessPermissionsException
96 * @throws \InvalidArgumentException
97 * @throws \RuntimeException
98 */
99 protected function init()
100 {
101 // Setting target, which must be a file reference to a file within the mounts.
102 $this->target = ($this->origTarget = ($fileIdentifier = GeneralUtility::_GP('target')));
103 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
104 // create the file object
105 if ($fileIdentifier) {
106 $this->fileObject = ResourceFactory::getInstance()
107 ->retrieveFileOrFolderObject($fileIdentifier);
108 }
109 // Cleaning and checking target directory
110 if (!$this->fileObject) {
111 $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:paramError', true);
112 $message = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:targetNoDir', true);
113 throw new \RuntimeException($title . ': ' . $message, 1294586841);
114 }
115 if ($this->fileObject->getStorage()->getUid() === 0) {
116 throw new InsufficientFileAccessPermissionsException(
117 'You are not allowed to access files outside your storages',
118 1375889832
119 );
120 }
121
122 // Setting the title and the icon
123 $icon = $this->iconFactory->getIcon('apps-filetree-root', Icon::SIZE_SMALL)->render();
124 $this->title = $icon
125 . htmlspecialchars(
126 $this->fileObject->getStorage()->getName()
127 ) . ': ' . htmlspecialchars(
128 $this->fileObject->getIdentifier()
129 );
130
131 // Setting template object
132 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
133 $this->moduleTemplate->addJavaScriptCode(
134 'FileEditBackToList',
135 'function backToList() {
136 top.goToModule("file_FilelistList");
137 }'
138 );
139 }
140
141 /**
142 * Main function, redering the actual content of the editing page
143 *
144 * @return void
145 */
146 public function main()
147 {
148 $this->getButtons();
149 // Hook before compiling the output
150 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'])) {
151 $preOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'];
152 if (is_array($preOutputProcessingHook)) {
153 $hookParameters = array(
154 'content' => &$this->content,
155 'target' => &$this->target
156 );
157 foreach ($preOutputProcessingHook as $hookFunction) {
158 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
159 }
160 }
161 }
162
163 $pageContent = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file')) . '" method="post" id="EditFileController" name="editform">';
164 $pageContent .= '<h1>'
165 . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.pagetitle')
166 . ' ' . htmlspecialchars($this->fileObject->getName()) . '</h1>';
167
168 $code = '';
169 $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'];
170 try {
171 if (!$extList || !GeneralUtility::inList($extList, $this->fileObject->getExtension())) {
172 throw new \Exception('Files with that extension are not editable.');
173 }
174
175 // Read file content to edit:
176 $fileContent = $this->fileObject->getContents();
177
178 // Making the formfields
179 $hValue = BackendUtility::getModuleUrl('file_edit', array(
180 'target' => $this->origTarget,
181 'returnUrl' => $this->returnUrl
182 ));
183 $code .= '
184 <div id="c-edit">
185 <textarea rows="30" name="file[editfile][0][data]" wrap="off" class="text-monospace t3js-enable-tab">' . htmlspecialchars($fileContent) . '</textarea>
186 <input type="hidden" name="file[editfile][0][target]" value="' . $this->fileObject->getUid() . '" />
187 <input type="hidden" name="redirect" value="' . htmlspecialchars($hValue) . '" />
188 </div>
189 <br />';
190 } catch (\Exception $e) {
191 $code .= sprintf(
192 $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.coundNot'),
193 $extList
194 );
195 }
196
197 // Ending of section and outputting editing form:
198 $pageContent .= $code;
199
200 // Hook after compiling the output
201 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'])) {
202 $postOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'];
203 if (is_array($postOutputProcessingHook)) {
204 $hookParameters = array(
205 'pageContent' => &$pageContent,
206 'target' => &$this->target
207 );
208 foreach ($postOutputProcessingHook as $hookFunction) {
209 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
210 }
211 }
212 }
213 $pageContent .= '</form>';
214 $this->content = $pageContent;
215
216 $this->moduleTemplate->setContent($this->content);
217 }
218
219 /**
220 * Processes the request, currently everything is handled and put together via "main()"
221 *
222 * @param ServerRequestInterface $request the current request
223 * @param ResponseInterface $response
224 * @return ResponseInterface the response with the content
225 */
226 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
227 {
228 $this->main();
229
230 $response->getBody()->write($this->moduleTemplate->renderContent());
231 return $response;
232 }
233
234 /**
235 * Builds the buttons for the docheader and returns them as an array
236 *
237 * @return array
238 */
239 public function getButtons()
240 {
241 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
242
243 $lang = $this->getLanguageService();
244 // CSH button
245 $helpButton = $buttonBar->makeHelpButton()
246 ->setFieldName('file_edit')
247 ->setModuleName('xMOD_csh_corebe');
248 $buttonBar->addButton($helpButton);
249
250 // Save button
251 $saveButton = $buttonBar->makeInputButton()
252 ->setName('_save')
253 ->setValue('1')
254 ->setOnClick('document.editform.submit();')
255 ->setTitle($lang->makeEntities($lang->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.submit', true)))
256 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL));
257
258 // Save and Close button
259 $saveAndCloseButton = $buttonBar->makeInputButton()
260 ->setName('_saveandclose')
261 ->setValue('1')
262 ->setOnClick(
263 'document.editform.redirect.value='
264 . GeneralUtility::quoteJSvalue($this->returnUrl)
265 . '; document.editform.submit();'
266 )
267 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.saveAndClose', true))
268 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
269 'actions-document-save-close',
270 Icon::SIZE_SMALL
271 ));
272
273 $splitButton = $buttonBar->makeSplitButton()
274 ->addItem($saveButton)
275 ->addItem($saveAndCloseButton);
276 $buttonBar->addButton($splitButton, ButtonBar::BUTTON_POSITION_LEFT, 20);
277
278 // Cancel button
279 $closeButton = $buttonBar->makeLinkButton()
280 ->setHref('#')
281 ->setOnClick('backToList(); return false;')
282 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.cancel', true))
283 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL));
284 $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 10);
285
286 // Make shortcut:
287 $shortButton = $buttonBar->makeShortcutButton()
288 ->setModuleName('file_edit')
289 ->setGetVariables(['target']);
290 $buttonBar->addButton($shortButton);
291 }
292
293 /**
294 * Returns LanguageService
295 *
296 * @return \TYPO3\CMS\Lang\LanguageService
297 */
298 protected function getLanguageService()
299 {
300 return $GLOBALS['LANG'];
301 }
302
303 /**
304 * Returns the current BE user.
305 *
306 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
307 */
308 protected function getBackendUser()
309 {
310 return $GLOBALS['BE_USER'];
311 }
312 }