e49ed7954a237cc3798d5fd612dd94f16c1be6b4
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / File / FileUploadController.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\ModuleTemplate;
21 use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
22 use TYPO3\CMS\Core\Http\HtmlResponse;
23 use TYPO3\CMS\Core\Imaging\Icon;
24 use TYPO3\CMS\Core\Localization\LanguageService;
25 use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException;
26 use TYPO3\CMS\Core\Resource\ResourceFactory;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28
29 /**
30 * Script Class for display up to 10 upload fields
31 * @internal This class is a specific Backend controller implementation and is not considered part of the Public TYPO3 API.
32 */
33 class FileUploadController
34 {
35 use PublicPropertyDeprecationTrait;
36
37 /**
38 * @var array
39 */
40 protected $deprecatedPublicProperties = [
41 'title' => 'Using $title of class FileUploadController from outside is discouraged as this variable is only used for internal storage.',
42 'target' => 'Using $target of class FileUploadController from outside is discouraged as this variable is only used for internal storage.',
43 'returnUrl' => 'Using $returnUrl of class FileUploadController from outside is discouraged as this variable is only used for internal storage.',
44 'content' => 'Using $content of class FileUploadController from outside is discouraged as this variable is only used for internal storage.',
45 ];
46
47 /**
48 * Name of the filemount
49 *
50 * @var string
51 */
52 protected $title;
53
54 /**
55 * Set with the target path inputted in &target
56 *
57 * @var string
58 */
59 protected $target;
60
61 /**
62 * Return URL of list module.
63 *
64 * @var string
65 */
66 protected $returnUrl;
67
68 /**
69 * Accumulating content
70 *
71 * @var string
72 */
73 protected $content;
74
75 /**
76 * The folder object which is the target directory for the upload
77 *
78 * @var \TYPO3\CMS\Core\Resource\Folder $folderObject
79 */
80 protected $folderObject;
81
82 /**
83 * ModuleTemplate object
84 *
85 * @var ModuleTemplate
86 */
87 protected $moduleTemplate;
88
89 /**
90 * Constructor
91 */
92 public function __construct()
93 {
94 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
95 $this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_misc.xlf');
96
97 // @deprecated since TYPO3 v9, will be moved out of __construct() in TYPO3 v10.0
98 $this->init($GLOBALS['TYPO3_REQUEST']);
99 }
100
101 /**
102 * Processes the request, currently everything is handled and put together via "renderContent()"
103 *
104 * @param ServerRequestInterface $request the current request
105 * @return ResponseInterface the response with the content
106 */
107 public function mainAction(ServerRequestInterface $request): ResponseInterface
108 {
109 $this->renderContent();
110 return new HtmlResponse($this->moduleTemplate->renderContent());
111 }
112
113 /**
114 * Main function, rendering the upload file form fields
115 *
116 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0
117 */
118 public function main()
119 {
120 trigger_error('FileUploadController->main() will be replaced by protected method renderContent() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
121 $this->renderContent();
122 }
123
124 /**
125 * This function renders the upload form
126 *
127 * @return string The HTML form as a string, ready for outputting
128 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0
129 */
130 public function renderUploadForm()
131 {
132 trigger_error('FileUploadController->renderUploadForm() will be replaced by protected method renderUploadFormInternal() in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
133 return $this->renderUploadFormInternal();
134 }
135
136 /**
137 * Initialize
138 *
139 * @param ServerRequestInterface $request
140 * @throws InsufficientFolderAccessPermissionsException
141 */
142 protected function init(ServerRequestInterface $request): void
143 {
144 $parsedBody = $request->getParsedBody();
145 $queryParams = $request->getQueryParams();
146
147 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
148 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
149 // Initialize GPvars:
150 $this->target = $parsedBody['target'] ?? $queryParams['target'] ?? null;
151 $this->returnUrl = GeneralUtility::sanitizeLocalUrl($parsedBody['returnUrl'] ?? $queryParams['returnUrl'] ?? '');
152 if (!$this->returnUrl) {
153 $this->returnUrl = (string)$uriBuilder->buildUriFromRoute('file_list', [
154 'id' => rawurlencode($this->target)
155 ]);
156 }
157 // Create the folder object
158 if ($this->target) {
159 $this->folderObject = ResourceFactory::getInstance()
160 ->retrieveFileOrFolderObject($this->target);
161 }
162 if ($this->folderObject->getStorage()->getUid() === 0) {
163 throw new InsufficientFolderAccessPermissionsException(
164 'You are not allowed to access folders outside your storages',
165 1375889834
166 );
167 }
168
169 // Cleaning and checking target directory
170 if (!$this->folderObject) {
171 $title = $this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:paramError');
172 $message = $this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:targetNoDir');
173 throw new \RuntimeException($title . ': ' . $message, 1294586843);
174 }
175
176 // Setting up the context sensitive menu
177 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
178
179 // building pathInfo for metaInformation
180 $pathInfo = [
181 'combined_identifier' => $this->folderObject->getCombinedIdentifier(),
182 ];
183 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pathInfo);
184 }
185
186 /**
187 * Render module content
188 */
189 protected function renderContent(): void
190 {
191 $lang = $this->getLanguageService();
192 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
193 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
194
195 // set page title
196 $this->moduleTemplate->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_upload.php.pagetitle'));
197
198 $pageContent = '<form action="'
199 . htmlspecialchars((string)$uriBuilder->buildUriFromRoute('tce_file'))
200 . '" method="post" id="FileUploadController" name="editform" enctype="multipart/form-data">';
201 // Make page header:
202 $pageContent .= '<h1>' . $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_upload.php.pagetitle') . '</h1>';
203 $pageContent .= $this->renderUploadFormInternal();
204
205 // Header Buttons
206 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
207
208 // csh button
209 $cshButton = $buttonBar->makeHelpButton()
210 ->setModuleName('xMOD_csh_corebe')
211 ->setFieldName('file_upload');
212 $buttonBar->addButton($cshButton);
213
214 // back button
215 if ($this->returnUrl) {
216 $backButton = $buttonBar->makeLinkButton()
217 ->setHref($this->returnUrl)
218 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
219 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-back', Icon::SIZE_SMALL));
220 $buttonBar->addButton($backButton);
221 }
222
223 $pageContent .= '</form>';
224 $this->content .= '<div>' . $pageContent . '</div>';
225 $this->moduleTemplate->setContent($this->content);
226 }
227
228 /**
229 * This function renders the upload form
230 *
231 * @return string The HTML form as a string, ready for outputting
232 */
233 protected function renderUploadFormInternal(): string
234 {
235 // Make checkbox for "overwrite"
236 $content = '
237 <div id="c-override">
238 <p class="checkbox"><label for="overwriteExistingFiles"><input type="checkbox" name="overwriteExistingFiles" id="overwriteExistingFiles" value="replace" /> ' . htmlspecialchars($this->getLanguageService()->getLL('overwriteExistingFiles')) . '</label></p>
239 <p>' . htmlspecialchars($this->getLanguageService()->getLL('uploadMultipleFilesInfo')) . '</p>
240 </div>
241 ';
242 // Produce the number of upload-fields needed:
243 $content .= '
244 <div id="c-upload">
245 ';
246 // Adding 'size="50" ' for the sake of Mozilla!
247 $content .= '
248 <input type="file" multiple="multiple" name="upload_1[]" />
249 <input type="hidden" name="data[upload][1][target]" value="' . htmlspecialchars($this->folderObject->getCombinedIdentifier()) . '" />
250 <input type="hidden" name="data[upload][1][data]" value="1" /><br />
251 ';
252 $content .= '
253 </div>
254 ';
255 // Submit button:
256 $content .= '
257 <div id="c-submit">
258 <input type="hidden" name="data[upload][1][redirect]" value="' . $this->returnUrl . '" /><br />
259 <input class="btn btn-default" type="submit" value="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_upload.php.submit')) . '" />
260 </div>
261 ';
262
263 return $content;
264 }
265
266 /**
267 * @return LanguageService
268 */
269 protected function getLanguageService(): LanguageService
270 {
271 return $GLOBALS['LANG'];
272 }
273 }