[BUGFIX] Fix exceptions from BE Routing change
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Tree / Pagetree / ExtdirectTreeCommands.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tree\Pagetree;
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\Controller\UserSettingsController;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Commands for the Page tree
24 */
25 class ExtdirectTreeCommands
26 {
27 /**
28 * Visibly the page
29 *
30 * @param \stdClass $nodeData
31 * @return array
32 */
33 public function visiblyNode($nodeData)
34 {
35 /** @var $node PagetreeNode */
36 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
37 try {
38 Commands::visiblyNode($node);
39 $newNode = Commands::getNode($node->getId());
40 $newNode->setLeaf($node->isLeafNode());
41 $returnValue = $newNode->toArray();
42 } catch (\Exception $exception) {
43 $returnValue = [
44 'success' => false,
45 'error' => $exception->getMessage()
46 ];
47 }
48 return $returnValue;
49 }
50
51 /**
52 * Hide the page
53 *
54 * @param \stdClass $nodeData
55 * @return array
56 */
57 public function disableNode($nodeData)
58 {
59 /** @var $node PagetreeNode */
60 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
61 try {
62 Commands::disableNode($node);
63 $newNode = Commands::getNode($node->getId());
64 $newNode->setLeaf($node->isLeafNode());
65 $returnValue = $newNode->toArray();
66 } catch (\Exception $exception) {
67 $returnValue = [
68 'success' => false,
69 'message' => $exception->getMessage()
70 ];
71 }
72 return $returnValue;
73 }
74
75 /**
76 * Delete the page
77 *
78 * @param \stdClass $nodeData
79 * @return array
80 */
81 public function deleteNode($nodeData)
82 {
83 /** @var $node PagetreeNode */
84 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
85 try {
86 Commands::deleteNode($node);
87 $returnValue = [];
88 if (static::getBackendUser()->workspace) {
89 $record = BackendUtility::getRecordWSOL('pages', $node->getId(), '*', '', true, true);
90 if ($record['_ORIG_uid']) {
91 $newNode = Commands::getNewNode($record);
92 $returnValue = $newNode->toArray();
93 }
94 }
95 } catch (\Exception $exception) {
96 $returnValue = [
97 'success' => false,
98 'message' => $exception->getMessage()
99 ];
100 }
101 return $returnValue;
102 }
103
104 /**
105 * Restore the page
106 *
107 * @param \stdClass $nodeData
108 * @param int $destination
109 * @return array
110 */
111 public function restoreNode($nodeData, $destination)
112 {
113 /** @var $node PagetreeNode */
114 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
115 try {
116 Commands::restoreNode($node, $destination);
117 $newNode = Commands::getNode($node->getId());
118 $returnValue = $newNode->toArray();
119 } catch (\Exception $exception) {
120 $returnValue = [
121 'success' => false,
122 'message' => $exception->getMessage()
123 ];
124 }
125 return $returnValue;
126 }
127
128 /**
129 * Updates the given field with a new text value, may be used to inline update
130 * the title field in the new page tree
131 *
132 * @param \stdClass $nodeData
133 * @param string $updatedLabel
134 * @return array
135 */
136 public function updateLabel($nodeData, $updatedLabel)
137 {
138 if ($updatedLabel === '') {
139 return [];
140 }
141 /** @var $node PagetreeNode */
142 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
143 try {
144 Commands::updateNodeLabel($node, $updatedLabel);
145 $shortendedText = GeneralUtility::fixed_lgd_cs($updatedLabel, (int)static::getBackendUser()->uc['titleLen']);
146 $returnValue = [
147 'editableText' => $updatedLabel,
148 'updatedText' => htmlspecialchars($shortendedText)
149 ];
150 } catch (\Exception $exception) {
151 $returnValue = [
152 'success' => false,
153 'message' => $exception->getMessage()
154 ];
155 }
156 return $returnValue;
157 }
158
159 /**
160 * Clear cache of the page
161 *
162 * @param \stdClass $nodeData
163 */
164 public static function clearCacheOfPage($nodeData)
165 {
166 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
167
168 $permissionClause = static::getBackendUser()->getPagePermsClause(1);
169 $access = BackendUtility::readPageAccess($node->getId(), $permissionClause);
170 if ($access) {
171 $dataHandler = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
172 $dataHandler->start([], []);
173 $dataHandler->clear_cacheCmd($node->getId());
174 }
175 }
176
177 /**
178 * Sets a temporary mount point
179 *
180 * @param \stdClass $nodeData
181 * @return array
182 */
183 public static function setTemporaryMountPoint($nodeData)
184 {
185 /** @var $node PagetreeNode */
186 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
187 static::getBackendUser()->uc['pageTree_temporaryMountPoint'] = $node->getId();
188 static::getBackendUser()->writeUC(static::getBackendUser()->uc);
189 return Commands::getMountPointPath();
190 }
191
192 /**
193 * Moves the source node directly as the first child of the destination node
194 *
195 * @param \stdClass $nodeData
196 * @param int $destination
197 * @return array
198 */
199 public function moveNodeToFirstChildOfDestination($nodeData, $destination)
200 {
201 /** @var $node PagetreeNode */
202 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
203 try {
204 Commands::moveNode($node, $destination);
205 $newNode = Commands::getNode($node->getId(), false);
206 $newNode->setLeaf($node->isLeafNode());
207 $returnValue = $newNode->toArray();
208 } catch (\Exception $exception) {
209 $returnValue = [
210 'success' => false,
211 'message' => $exception->getMessage()
212 ];
213 }
214 return $returnValue;
215 }
216
217 /**
218 * Moves the source node directly after the destination node
219 *
220 * @param \stdClass $nodeData
221 * @param int $destination
222 * @return array
223 */
224 public function moveNodeAfterDestination($nodeData, $destination)
225 {
226 /** @var $node PagetreeNode */
227 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
228 try {
229 Commands::moveNode($node, -$destination);
230 $newNode = Commands::getNode($node->getId(), false);
231 $newNode->setLeaf($node->isLeafNode());
232 $returnValue = $newNode->toArray();
233 } catch (\Exception $exception) {
234 $returnValue = [
235 'success' => false,
236 'message' => $exception->getMessage()
237 ];
238 }
239 return $returnValue;
240 }
241
242 /**
243 * Copies the source node directly as the first child of the destination node and
244 * returns the created node.
245 *
246 * @param \stdClass $nodeData
247 * @param int $destination
248 * @return array
249 */
250 public function copyNodeToFirstChildOfDestination($nodeData, $destination)
251 {
252 /** @var $node PagetreeNode */
253 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
254 try {
255 $newPageId = Commands::copyNode($node, $destination);
256 $newNode = Commands::getNode($newPageId);
257 $newNode->setLeaf($node->isLeafNode());
258 $returnValue = $newNode->toArray();
259 } catch (\Exception $exception) {
260 $returnValue = [
261 'success' => false,
262 'message' => $exception->getMessage()
263 ];
264 }
265 return $returnValue;
266 }
267
268 /**
269 * Copies the source node directly after the destination node and returns the
270 * created node.
271 *
272 * @param \stdClass $nodeData
273 * @param int $destination
274 * @return array
275 */
276 public function copyNodeAfterDestination($nodeData, $destination)
277 {
278 /** @var $node PagetreeNode */
279 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
280 try {
281 $newPageId = Commands::copyNode($node, -$destination);
282 $newNode = Commands::getNode($newPageId);
283 $newNode->setLeaf($node->isLeafNode());
284 $returnValue = $newNode->toArray();
285 } catch (\Exception $exception) {
286 $returnValue = [
287 'success' => false,
288 'message' => $exception->getMessage()
289 ];
290 }
291 return $returnValue;
292 }
293
294 /**
295 * Inserts a new node as the first child node of the destination node and returns the created node.
296 *
297 * @param \stdClass $parentNodeData
298 * @param int $pageType
299 * @return array
300 */
301 public function insertNodeToFirstChildOfDestination($parentNodeData, $pageType)
302 {
303 /** @var $parentNode PagetreeNode */
304 $parentNode = GeneralUtility::makeInstance(PagetreeNode::class, (array)$parentNodeData);
305 try {
306 $newPageId = Commands::createNode($parentNode, $parentNode->getId(), $pageType);
307 $returnValue = Commands::getNode($newPageId)->toArray();
308 } catch (\Exception $exception) {
309 $returnValue = [
310 'success' => false,
311 'message' => $exception->getMessage()
312 ];
313 }
314 return $returnValue;
315 }
316
317 /**
318 * Inserts a new node directly after the destination node and returns the created node.
319 *
320 * @param \stdClass $parentNodeData
321 * @param int $destination
322 * @param int $pageType
323 * @return array
324 */
325 public function insertNodeAfterDestination($parentNodeData, $destination, $pageType)
326 {
327 /** @var $parentNode PagetreeNode */
328 $parentNode = GeneralUtility::makeInstance(PagetreeNode::class, (array)$parentNodeData);
329 try {
330 $newPageId = Commands::createNode($parentNode, -$destination, $pageType);
331 $returnValue = Commands::getNode($newPageId)->toArray();
332 } catch (\Exception $exception) {
333 $returnValue = [
334 'success' => false,
335 'message' => $exception->getMessage()
336 ];
337 }
338 return $returnValue;
339 }
340
341 /**
342 * Returns the view link of a given node
343 *
344 * @param \stdClass $nodeData
345 * @return string
346 */
347 public static function getViewLink($nodeData)
348 {
349 /** @var $node PagetreeNode */
350 $node = GeneralUtility::makeInstance(PagetreeNode::class, (array)$nodeData);
351 $javascriptLink = BackendUtility::viewOnClick($node->getId());
352 $extractedLink = '';
353 if (preg_match('/window\\.open\\(\'([^\']+)\'/i', $javascriptLink, $match)) {
354 // Clean JSON-serialized ampersands ('&')
355 // @see GeneralUtility::quoteJSvalue()
356 $extractedLink = json_decode('"' . trim($match[1], '"') . '"', JSON_HEX_AMP);
357 }
358 return $extractedLink;
359 }
360
361 /**
362 * Adds the rootline of a given node to the tree expansion state and adds the node
363 * itself as the current selected page. This leads to the expansion and selection of
364 * the node in the tree after a refresh.
365 *
366 * @static
367 * @param string $stateId
368 * @param int $nodeId
369 * @return array
370 */
371 public static function addRootlineOfNodeToStateHash($stateId, $nodeId)
372 {
373 $mountPoints = array_map('intval', static::getBackendUser()->returnWebmounts());
374 if (empty($mountPoints)) {
375 $mountPoints = [0];
376 }
377 if (!empty(static::getBackendUser()->uc['pageTree_temporaryMountPoint'])) {
378 $mountPoints[] = (int)static::getBackendUser()->uc['pageTree_temporaryMountPoint'];
379 }
380 $mountPoints = array_unique($mountPoints);
381 /** @var $userSettingsController UserSettingsController */
382 $userSettingsController = GeneralUtility::makeInstance(UserSettingsController::class);
383 $state = $userSettingsController->process('get', 'BackendComponents.States.' . $stateId);
384 if (empty($state)) {
385 $state = new \stdClass();
386 $state->stateHash = new \stdClass();
387 }
388 $state->stateHash = (object)$state->stateHash;
389 $rootline = BackendUtility::BEgetRootLine($nodeId, '', (int)static::getBackendUser()->workspace !== 0);
390 $rootlineIds = [];
391 foreach ($rootline as $pageData) {
392 $rootlineIds[] = (int)$pageData['uid'];
393 }
394 foreach ($mountPoints as $mountPoint) {
395 if (!in_array($mountPoint, $rootlineIds, true)) {
396 continue;
397 }
398 $isFirstNode = true;
399 foreach ($rootline as $pageData) {
400 $node = Commands::getNewNode($pageData, $mountPoint);
401 if ($isFirstNode) {
402 $isFirstNode = false;
403 $state->stateHash->lastSelectedNode = $node->calculateNodeId();
404 } else {
405 $state->stateHash->{$node->calculateNodeId('')} = 1;
406 }
407 }
408 }
409 $userSettingsController->process('set', 'BackendComponents.States.' . $stateId, $state);
410 return (array)$state->stateHash;
411 }
412
413 /**
414 * Gets the path steps for a given page.
415 * This methods considers multiple mount points,
416 * thus the returned array is multidimensional, e.g.
417 *
418 * array(
419 * array('p0', 'p1', 'p13', 'p44'),
420 * array('p0', 'p13-1', 'p44-1'),
421 * )
422 *
423 * @param int $pageId
424 * @return array
425 */
426 public static function getNodePaths($pageId)
427 {
428 $pagePaths = [];
429 $mountPoints = array_map('intval', static::getBackendUser()->returnWebmounts());
430 if (empty($mountPoints)) {
431 $mountPoints = [0];
432 }
433 $mountPoints[] = (int)static::getBackendUser()->uc['pageTree_temporaryMountPoint'];
434 $mountPoints = array_unique($mountPoints);
435 $rootLine = BackendUtility::BEgetRootLine($pageId, '', (int)static::getBackendUser()->workspace !== 0);
436 $rootLineIds = [];
437 foreach ($rootLine as $rootLineLevel) {
438 $rootLineIds[] = (int)$rootLineLevel['uid'];
439 }
440 foreach ($mountPoints as $mountPoint) {
441 $pagePath = [];
442 if (!in_array($mountPoint, $rootLineIds, true)) {
443 continue;
444 }
445 foreach ($rootLine as $rootLineLevel) {
446 $node = Commands::getNewNode($rootLineLevel, $mountPoint);
447 array_unshift($pagePath, $node->calculateNodeId());
448 // Break if mount-point has been reached
449 if ($mountPoint === (int)$rootLineLevel['uid']) {
450 break;
451 }
452 }
453 // Attach valid partial root-lines
454 if (!empty($pagePath)) {
455 if ($mountPoint !== 0) {
456 array_unshift($pagePath, Commands::getNewNode(['uid' => 0])->calculateNodeId());
457 }
458 $pagePaths[] = $pagePath;
459 }
460 }
461 return $pagePaths;
462 }
463
464 /**
465 * @return BackendUserAuthentication
466 */
467 protected static function getBackendUser()
468 {
469 return $GLOBALS['BE_USER'];
470 }
471 }