[!!!][TASK] Fluidification of EditFileController
[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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Module\AbstractModule;
20 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
21 use TYPO3\CMS\Backend\Template\DocumentTemplate;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Imaging\Icon;
24 use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException;
25 use TYPO3\CMS\Core\Resource\ResourceFactory;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Fluid\View\StandaloneView;
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 $GLOBALS['SOBE'] = $this;
88 $this->init();
89 }
90
91 /**
92 * Initialize script class
93 *
94 * @throws InsufficientFileAccessPermissionsException
95 * @throws \InvalidArgumentException
96 * @throws \RuntimeException
97 */
98 protected function init()
99 {
100 // Setting target, which must be a file reference to a file within the mounts.
101 $this->target = ($this->origTarget = ($fileIdentifier = GeneralUtility::_GP('target')));
102 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
103 // create the file object
104 if ($fileIdentifier) {
105 $this->fileObject = ResourceFactory::getInstance()
106 ->retrieveFileOrFolderObject($fileIdentifier);
107 }
108 // Cleaning and checking target directory
109 if (!$this->fileObject) {
110 $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:paramError');
111 $message = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:targetNoDir');
112 throw new \RuntimeException($title . ': ' . $message, 1294586841);
113 }
114 if ($this->fileObject->getStorage()->getUid() === 0) {
115 throw new InsufficientFileAccessPermissionsException(
116 'You are not allowed to access files outside your storages',
117 1375889832
118 );
119 }
120
121 // Setting the title and the icon
122 $icon = $this->moduleTemplate->getIconFactory()->getIcon('apps-filetree-root', Icon::SIZE_SMALL)->render();
123 $this->title = $icon
124 . htmlspecialchars(
125 $this->fileObject->getStorage()->getName()
126 ) . ': ' . htmlspecialchars(
127 $this->fileObject->getIdentifier()
128 );
129
130 // Setting template object
131 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
132 $this->moduleTemplate->addJavaScriptCode(
133 'FileEditBackToList',
134 'function backToList() {
135 top.goToModule("file_FilelistList");
136 }'
137 );
138 }
139
140 /**
141 * Main function, redering the actual content of the editing page
142 *
143 * @return void
144 */
145 public function main()
146 {
147 $this->getButtons();
148 // Hook: before compiling the output
149 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'])) {
150 $preOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'];
151 if (is_array($preOutputProcessingHook)) {
152 $hookParameters = [
153 'content' => &$this->content,
154 'target' => &$this->target
155 ];
156 foreach ($preOutputProcessingHook as $hookFunction) {
157 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
158 }
159 }
160 }
161
162 $assigns = [];
163 $assigns['moduleUrlTceFile'] = BackendUtility::getModuleUrl('tce_file');
164 $assigns['fileName'] = $this->fileObject->getName();
165
166 $extList = $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext'];
167 try {
168 if (!$extList || !GeneralUtility::inList($extList, $this->fileObject->getExtension())) {
169 throw new \Exception('Files with that extension are not editable.', 1476050135);
170 }
171
172 // Read file content to edit:
173 $fileContent = $this->fileObject->getContents();
174
175 // Making the formfields
176 $hValue = BackendUtility::getModuleUrl('file_edit', [
177 'target' => $this->origTarget,
178 'returnUrl' => $this->returnUrl
179 ]);
180 $assigns['uid'] = $this->fileObject->getUid();
181 $assigns['fileContent'] = $fileContent;
182 $assigns['hValue'] = $hValue;
183 } catch (\Exception $e) {
184 $assigns['extList'] = $extList;
185 }
186
187 // Rendering of the output via fluid
188 $view = GeneralUtility::makeInstance(StandaloneView::class);
189 $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]);
190 $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]);
191 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
192 'EXT:backend/Resources/Private/Templates/File/EditFile.html'
193 ));
194 $view->assignMultiple($assigns);
195 $pageContent = $view->render();
196
197 // Hook: after compiling the output
198 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'])) {
199 $postOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'];
200 if (is_array($postOutputProcessingHook)) {
201 $hookParameters = [
202 'pageContent' => &$pageContent,
203 'target' => &$this->target
204 ];
205 foreach ($postOutputProcessingHook as $hookFunction) {
206 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
207 }
208 }
209 }
210
211 $this->content .= $pageContent;
212 $this->moduleTemplate->setContent($this->content);
213 }
214
215 /**
216 * Processes the request, currently everything is handled and put together via "main()"
217 *
218 * @param ServerRequestInterface $request the current request
219 * @param ResponseInterface $response
220 * @return ResponseInterface the response with the content
221 */
222 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
223 {
224 $this->main();
225
226 $response->getBody()->write($this->moduleTemplate->renderContent());
227 return $response;
228 }
229
230 /**
231 * Builds the buttons for the docheader and returns them as an array
232 *
233 * @return array
234 */
235 public function getButtons()
236 {
237 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
238
239 $lang = $this->getLanguageService();
240 // CSH button
241 $helpButton = $buttonBar->makeHelpButton()
242 ->setFieldName('file_edit')
243 ->setModuleName('xMOD_csh_corebe');
244 $buttonBar->addButton($helpButton);
245
246 // Save button
247 $saveButton = $buttonBar->makeInputButton()
248 ->setName('_save')
249 ->setValue('1')
250 ->setOnClick('document.editform.submit();')
251 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.submit'))
252 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL));
253
254 // Save and Close button
255 $saveAndCloseButton = $buttonBar->makeInputButton()
256 ->setName('_saveandclose')
257 ->setValue('1')
258 ->setOnClick(
259 'document.editform.redirect.value='
260 . GeneralUtility::quoteJSvalue($this->returnUrl)
261 . '; document.editform.submit();'
262 )
263 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.saveAndClose'))
264 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
265 'actions-document-save-close',
266 Icon::SIZE_SMALL
267 ));
268
269 $splitButton = $buttonBar->makeSplitButton()
270 ->addItem($saveButton)
271 ->addItem($saveAndCloseButton);
272 $buttonBar->addButton($splitButton, ButtonBar::BUTTON_POSITION_LEFT, 20);
273
274 // Cancel button
275 $closeButton = $buttonBar->makeLinkButton()
276 ->setHref('#')
277 ->setOnClick('backToList(); return false;')
278 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.cancel'))
279 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL));
280 $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 10);
281
282 // Make shortcut:
283 $shortButton = $buttonBar->makeShortcutButton()
284 ->setModuleName('file_edit')
285 ->setGetVariables(['target']);
286 $buttonBar->addButton($shortButton);
287 }
288
289 /**
290 * Returns LanguageService
291 *
292 * @return \TYPO3\CMS\Lang\LanguageService
293 */
294 protected function getLanguageService()
295 {
296 return $GLOBALS['LANG'];
297 }
298
299 /**
300 * Returns the current BE user.
301 *
302 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
303 */
304 protected function getBackendUser()
305 {
306 return $GLOBALS['BE_USER'];
307 }
308 }