92f29e107d899d670a708a61bba255944378ab97
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / File / RenameFileController.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Backend\Controller\File;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
21 use TYPO3\CMS\Backend\Template\DocumentTemplate;
22 use TYPO3\CMS\Backend\Template\ModuleTemplate;
23 use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
24 use TYPO3\CMS\Core\Http\HtmlResponse;
25 use TYPO3\CMS\Core\Imaging\Icon;
26 use TYPO3\CMS\Core\Localization\LanguageService;
27 use TYPO3\CMS\Core\Resource\DuplicationBehavior;
28 use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException;
29 use TYPO3\CMS\Core\Resource\File;
30 use TYPO3\CMS\Core\Resource\Folder;
31 use TYPO3\CMS\Core\Utility\GeneralUtility;
32 use TYPO3\CMS\Fluid\View\StandaloneView;
33
34 /**
35 * Script Class for the rename-file form.
36 */
37 class RenameFileController
38 {
39 use PublicPropertyDeprecationTrait;
40
41 /**
42 * @var array
43 */
44 protected $deprecatedPublicProperties = [
45 'title' => 'Using $title of class RenameFileController from outside is discouraged as this variable is only used for internal storage.',
46 'target' => 'Using $target of class RenameFileController from outside is discouraged as this variable is only used for internal storage.',
47 'returnUrl' => 'Using $returnUrl of class RenameFileController from outside is discouraged as this variable is only used for internal storage.',
48 'content' => 'Using $content of class RenameFileController from outside is discouraged as this variable is only used for internal storage.',
49 ];
50
51 /**
52 * Name of the filemount
53 *
54 * @var string
55 */
56 protected $title;
57
58 /**
59 * Target path
60 *
61 * @var string
62 * @internal
63 */
64 protected $target;
65
66 /**
67 * The file or folder object that should be renamed
68 *
69 * @var File|Folder $fileOrFolderObject
70 */
71 protected $fileOrFolderObject;
72
73 /**
74 * Return URL of list module.
75 *
76 * @var string
77 */
78 protected $returnUrl;
79
80 /**
81 * Accumulating content
82 *
83 * @var string
84 * @internal
85 */
86 protected $content;
87
88 /**
89 * ModuleTemplate object
90 *
91 * @var ModuleTemplate
92 */
93 protected $moduleTemplate;
94
95 /**
96 * Constructor
97 */
98 public function __construct()
99 {
100 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
101
102 // @deprecated since v9, will be moved out of __construct() in v10
103 $this->init($GLOBALS['TYPO3_REQUEST']);
104 }
105
106 /**
107 * Processes the request, currently everything is handled and put together via "renderContent()"
108 *
109 * @return ResponseInterface the response with the content
110 */
111 public function mainAction(ServerRequestInterface $request): ResponseInterface
112 {
113 $this->renderContent();
114
115 return new HtmlResponse($this->moduleTemplate->renderContent());
116 }
117
118 /**
119 * Main function, rendering the content of the rename form
120 *
121 * @deprecated since v9, will be removed in v10
122 */
123 public function main()
124 {
125 trigger_error('Method main() will be replaced by protected method renderContent() in v10. Do not call from other extension', E_USER_DEPRECATED);
126 $this->renderContent();
127 }
128
129 /**
130 * Initialize
131 *
132 * @param ServerRequestInterface $request
133 * @throws InsufficientFileAccessPermissionsException
134 */
135 protected function init(ServerRequestInterface $request): void
136 {
137 $parsedBody = $request->getParsedBody();
138 $queryParams = $request->getQueryParams();
139
140 // Initialize GPvars:
141 $this->target = $parsedBody['target'] ?? $queryParams['target'] ?? null;
142 $this->returnUrl = GeneralUtility::sanitizeLocalUrl($parsedBody['returnUrl'] ?? $queryParams['returnUrl'] ?? '');
143 // Cleaning and checking target
144 if ($this->target) {
145 $this->fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->target);
146 }
147 if (!$this->fileOrFolderObject) {
148 $title = $this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:paramError');
149 $message = $this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:targetNoDir');
150 throw new \RuntimeException($title . ': ' . $message, 1294586844);
151 }
152 if ($this->fileOrFolderObject->getStorage()->getUid() === 0) {
153 throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1375889840);
154 }
155
156 // If a folder should be renamed, AND the returnURL should go to the old directory name, the redirect is forced
157 // so the redirect will NOT end in an error message
158 // this case only happens if you select the folder itself in the foldertree and then use the clickmenu to
159 // rename the folder
160 if ($this->fileOrFolderObject instanceof Folder) {
161 $parsedUrl = parse_url($this->returnUrl);
162 $queryParts = GeneralUtility::explodeUrl2Array(urldecode($parsedUrl['query']));
163 if ($queryParts['id'] === $this->fileOrFolderObject->getCombinedIdentifier()) {
164 $this->returnUrl = str_replace(
165 urlencode($queryParts['id']),
166 urlencode($this->fileOrFolderObject->getStorage()->getRootLevelFolder()->getCombinedIdentifier()),
167 $this->returnUrl
168 );
169 }
170 }
171
172 // building pathInfo for metaInformation
173 $pathInfo = [
174 'combined_identifier' => $this->fileOrFolderObject->getCombinedIdentifier(),
175 ];
176 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pathInfo);
177
178 // Setting up the context sensitive menu
179 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
180 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/RenameFile');
181
182 // Add javaScript
183 $this->moduleTemplate->addJavaScriptCode(
184 'RenameFileInlineJavaScript',
185 'function backToList() {top.goToModule("file_FilelistList");}'
186 );
187 }
188
189 /**
190 * Render module content
191 */
192 protected function renderContent(): void
193 {
194 $assigns = [];
195 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
196 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
197 $assigns['moduleUrlTceFile'] = (string)$uriBuilder->buildUriFromRoute('tce_file');
198 $assigns['returnUrl'] = $this->returnUrl;
199
200 if ($this->fileOrFolderObject instanceof Folder) {
201 $fileIdentifier = $this->fileOrFolderObject->getCombinedIdentifier();
202 $targetLabel = 'file_rename.php.label.target.folder';
203 } else {
204 $fileIdentifier = $this->fileOrFolderObject->getUid();
205 $targetLabel = 'file_rename.php.label.target.file';
206 $assigns['conflictMode'] = DuplicationBehavior::cast(DuplicationBehavior::RENAME);
207 $assigns['destination'] = $this->fileOrFolderObject->getParentFolder()->getCombinedIdentifier();
208 }
209
210 $assigns['fileName'] = $this->fileOrFolderObject->getName();
211 $assigns['fileIdentifier'] = $fileIdentifier;
212 $assigns['fieldLabel'] = $targetLabel;
213
214 // Create buttons
215 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
216
217 // csh button
218 $cshButton = $buttonBar->makeHelpButton()
219 ->setModuleName('xMOD_csh_corebe')
220 ->setFieldName('file_rename');
221 $buttonBar->addButton($cshButton);
222
223 // back button
224 if ($this->returnUrl) {
225 $backButton = $buttonBar->makeLinkButton()
226 ->setHref($this->returnUrl)
227 ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
228 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-close', Icon::SIZE_SMALL));
229 $buttonBar->addButton($backButton);
230 }
231
232 // Save and Close button
233 $saveAndCloseButton = $buttonBar->makeInputButton()
234 ->setName('_saveandclose')
235 ->setValue('1')
236 ->setShowLabelText(true)
237 ->setClasses('t3js-submit-file-rename')
238 ->setForm('RenameFileController')
239 ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_edit.php.saveAndClose'))
240 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save-close', Icon::SIZE_SMALL));
241
242 $buttonBar->addButton($saveAndCloseButton, ButtonBar::BUTTON_POSITION_LEFT, 20);
243
244 $this->moduleTemplate->getPageRenderer()->addInlineLanguageLabelArray([
245 'file_rename.actions.cancel' => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_rename.actions.cancel'),
246 'file_rename.actions.rename' => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_rename.actions.rename'),
247 'file_rename.actions.override' => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_rename.actions.override'),
248 'file_rename.exists.title' => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_rename.exists.title'),
249 'file_rename.exists.description' => $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_rename.exists.description'),
250 ]);
251
252 // Rendering of the output via fluid
253 $view = GeneralUtility::makeInstance(StandaloneView::class);
254 $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]);
255 $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]);
256 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
257 'EXT:backend/Resources/Private/Templates/File/RenameFile.html'
258 ));
259 $view->assignMultiple($assigns);
260 $this->content = $view->render();
261 $this->moduleTemplate->setContent($this->content);
262 }
263
264 /**
265 * @return LanguageService
266 */
267 protected function getLanguageService(): LanguageService
268 {
269 return $GLOBALS['LANG'];
270 }
271
272 /**
273 * @return DocumentTemplate
274 */
275 protected function getDocumentTemplate(): DocumentTemplate
276 {
277 return $GLOBALS['TBE_TEMPLATE'];
278 }
279 }