c7ffde487e81b612da1db2a740db10675ddb4d32
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / File / ReplaceFileController.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\Template\DocumentTemplate;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Backend\Utility\IconUtility;
20 use TYPO3\CMS\Core\Imaging\Icon;
21 use TYPO3\CMS\Core\Imaging\IconFactory;
22 use TYPO3\CMS\Core\Resource\Exception\InsufficientFileAccessPermissionsException;
23 use TYPO3\CMS\Core\Resource\Folder;
24 use TYPO3\CMS\Core\Resource\ResourceFactory;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Lang\LanguageService;
27 use Psr\Http\Message\ResponseInterface;
28 use Psr\Http\Message\ServerRequestInterface;
29 use TYPO3\CMS\Core\Http\Response;
30
31 /**
32 * Script Class for the rename-file form
33 */
34 class ReplaceFileController implements \TYPO3\CMS\Core\Http\ControllerInterface {
35
36 /**
37 * Document template object
38 *
39 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
40 */
41 public $doc;
42
43 /**
44 * Name of the filemount
45 *
46 * @var string
47 */
48 public $title;
49
50 /**
51 * sys_file uid
52 *
53 * @var int
54 */
55 public $uid;
56
57 /**
58 * The file or folder object that should be renamed
59 *
60 * @var \TYPO3\CMS\Core\Resource\ResourceInterface $fileOrFolderObject
61 */
62 protected $fileOrFolderObject;
63
64 /**
65 * Return URL of list module.
66 *
67 * @var string
68 */
69 public $returnUrl;
70
71 /**
72 * Accumulating content
73 *
74 * @var string
75 */
76 public $content;
77
78 /**
79 * Constructor
80 */
81 public function __construct() {
82 $GLOBALS['SOBE'] = $this;
83 $this->init();
84 }
85
86 /**
87 * Init
88 *
89 * @return void
90 * @throws \RuntimeException
91 * @throws InsufficientFileAccessPermissionsException
92 */
93 protected function init() {
94 // Initialize GPvars:
95 $this->uid = (int) GeneralUtility::_GP('uid');
96
97 $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
98 // Cleaning and checking uid
99 if ($this->uid > 0) {
100 $this->fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject('file:' . $this->uid);
101 }
102 if (!$this->fileOrFolderObject) {
103 $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:paramError', TRUE);
104 $message = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:targetNoDir', TRUE);
105 throw new \RuntimeException($title . ': ' . $message, 1436895930);
106 }
107 if ($this->fileOrFolderObject->getStorage()->getUid() === 0) {
108 throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1436895931);
109 }
110
111 // If a folder should be renamed, AND the returnURL should go to the old directory name, the redirect is forced
112 // so the redirect will NOT end in an error message
113 // this case only happens if you select the folder itself in the foldertree and then use the clickmenu to
114 // rename the folder
115 if ($this->fileOrFolderObject instanceof Folder) {
116 $parsedUrl = parse_url($this->returnUrl);
117 $queryParts = GeneralUtility::explodeUrl2Array(urldecode($parsedUrl['query']));
118 if ($queryParts['id'] === $this->fileOrFolderObject->getCombinedIdentifier()) {
119 $this->returnUrl = str_replace(urlencode($queryParts['id']), urlencode($this->fileOrFolderObject->getStorage()->getRootLevelFolder()->getCombinedIdentifier()), $this->returnUrl);
120 }
121 }
122 // Setting icon and title
123 $icon = IconUtility::getSpriteIcon('apps-filetree-root');
124 $this->title = $icon . htmlspecialchars($this->fileOrFolderObject->getStorage()->getName()) . ': ' . htmlspecialchars($this->fileOrFolderObject->getIdentifier());
125 // Setting template object
126 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
127 $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/file_replace.html');
128 $this->doc->JScode = $this->doc->wrapScriptTags('
129 function backToList() {
130 top.goToModule("file_FilelistList");
131 }
132 ');
133 }
134
135 /**
136 * Main function, rendering the content of the rename form
137 *
138 * @return void
139 */
140 public function main() {
141 // Make page header:
142 $this->content = $this->doc->startPage($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_replace.php.pagetitle'));
143 $pageContent = $this->doc->header($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_replace.php.pagetitle'));
144 $pageContent .= $this->doc->spacer(5);
145 $pageContent .= $this->doc->divider(5);
146
147 $code = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file')) . '" role="form" method="post" name="editform" enctype="multipart/form-data">';
148
149 // Making the formfields for renaming:
150 $code .= '
151 <div class="form-group">
152 <input type="checkbox" value="1" id="keepFilename" name="file[replace][1][keepFilename]"> <label for="keepFilename">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_replace.php.keepfiletitle') . '</label>
153 </div>
154
155 <div class="form-group">
156 <label for="file_replace">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_replace.php.selectfile') . '</label>
157 <div class="input-group col-xs-6">
158 <input type="text" name="fakefile" id="fakefile" class="form-control input-xlarge" readonly>
159 <a class="input-group-addon btn btn-primary" onclick="TYPO3.jQuery(\'#file_replace\').click();">' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_replace.php.browse') . '</a>
160 </div>
161 <input class="form-control" type="file" id="file_replace" multiple="false" name="replace_1" style="visibility: hidden;" />
162 </div>
163
164 <script>
165 TYPO3.jQuery(\'#file_replace\').change(function(){
166 TYPO3.jQuery(\'#fakefile\').val(TYPO3.jQuery(this).val());
167 });
168 </script>
169
170 <input type="hidden" name="overwriteExistingFiles" value="replace" />
171 <input type="hidden" name="file[replace][1][data]" value="1" />
172 <input type="hidden" name="file[replace][1][uid]" value="' . $this->uid . '" />
173 ';
174 // Making submit button:
175 $code .= '
176 <div class="form-group">
177 <input class="btn btn-primary" type="submit" value="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_replace.php.submit', TRUE) . '" />
178 <input class="btn btn-danger" type="submit" value="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.cancel', TRUE) . '" onclick="backToList(); return false;" />
179 <input type="hidden" name="redirect" value="' . htmlspecialchars($this->returnUrl) . '" />
180 </div>
181 ';
182 $code .= '</form>';
183 // Add the HTML as a section:
184 $pageContent .= $code;
185 $docHeaderButtons = array(
186 'back' => ''
187 );
188 $docHeaderButtons['csh'] = BackendUtility::cshItem('xMOD_csh_corebe', 'file_rename');
189 // Back
190 if ($this->returnUrl) {
191 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
192 $docHeaderButtons['back'] = '<a href="' . htmlspecialchars(GeneralUtility::linkThisUrl($this->returnUrl))
193 . '" class="typo3-goBack" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.goBack', TRUE) . '">'
194 . $iconFactory->getIcon('actions-view-go-back', Icon::SIZE_SMALL)
195 . '</a>';
196 }
197 // Add the HTML as a section:
198 $markerArray = array(
199 'CSH' => $docHeaderButtons['csh'],
200 'FUNC_MENU' => BackendUtility::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']),
201 'CONTENT' => $pageContent,
202 'PATH' => $this->title
203 );
204 $this->content .= $this->doc->moduleBody(array(), $docHeaderButtons, $markerArray);
205 $this->content .= $this->doc->endPage();
206 $this->content = $this->doc->insertStylesAndJS($this->content);
207 }
208
209 /**
210 * Processes the request, currently everything is handled and put together via "main()"
211 *
212 * @param ServerRequestInterface $request The request object
213 * @return ResponseInterface $response The response, created by the controller
214 */
215 public function processRequest(ServerRequestInterface $request) {
216 $this->main();
217 /** @var Response $response */
218 $response = GeneralUtility::makeInstance(Response::class);
219 $response->getBody()->write($this->content);
220 return $response;
221 }
222
223 /**
224 * Outputting the accumulated content to screen
225 *
226 * @return void
227 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use the processRequest() method instead
228 */
229 public function printContent() {
230 GeneralUtility::logDeprecatedFunction();
231 echo $this->content;
232 }
233
234 /**
235 * @return LanguageService
236 */
237 protected function getLanguageService() {
238 return $GLOBALS['LANG'];
239 }
240 }