[BUGFIX] Add missing int-cast for checking uid zero
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Tree / Pagetree / Commands.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\Utility\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\MathUtility;
21 use TYPO3\CMS\Core\Versioning\VersionState;
22
23 /**
24 * Page Tree and Context Menu Commands
25 *
26 * @author Stefan Galinski <stefan.galinski@gmail.com>
27 */
28 class Commands {
29
30 /**
31 * @var bool|null
32 */
33 static protected $useNavTitle = NULL;
34
35 /**
36 * @var bool|null
37 */
38 static protected $addIdAsPrefix = NULL;
39
40 /**
41 * @var bool|null
42 */
43 static protected $addDomainName = NULL;
44
45 /**
46 * @var array|null
47 */
48 static protected $backgroundColors = NULL;
49
50 /**
51 * @var int|null
52 */
53 static protected $titleLength = NULL;
54
55 /**
56 * Visibly the page
57 *
58 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node
59 * @return void
60 */
61 static public function visiblyNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node) {
62 $data['pages'][$node->getWorkspaceId()]['hidden'] = 0;
63 self::processTceCmdAndDataMap(array(), $data);
64 }
65
66 /**
67 * Hide the page
68 *
69 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node
70 * @return void
71 */
72 static public function disableNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node) {
73 $data['pages'][$node->getWorkspaceId()]['hidden'] = 1;
74 self::processTceCmdAndDataMap(array(), $data);
75 }
76
77 /**
78 * Delete the page
79 *
80 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node
81 * @return void
82 */
83 static public function deleteNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node) {
84 $cmd['pages'][$node->getId()]['delete'] = 1;
85 self::processTceCmdAndDataMap($cmd);
86 }
87
88 /**
89 * Restore the page
90 *
91 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node
92 * @param int $targetId
93 * @return void
94 */
95 static public function restoreNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node, $targetId) {
96 $cmd['pages'][$node->getId()]['undelete'] = 1;
97 self::processTceCmdAndDataMap($cmd);
98 if ($node->getId() !== $targetId) {
99 self::moveNode($node, $targetId);
100 }
101 }
102
103 /**
104 * Updates the node label
105 *
106 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node
107 * @param string $updatedLabel
108 * @return void
109 */
110 static public function updateNodeLabel(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $node, $updatedLabel) {
111 if ($GLOBALS['BE_USER']->checkLanguageAccess(0)) {
112 $data['pages'][$node->getWorkspaceId()][$node->getTextSourceField()] = $updatedLabel;
113 self::processTceCmdAndDataMap(array(), $data);
114 } else {
115 throw new \RuntimeException(implode(LF, array('Editing title of page id \'' . $node->getWorkspaceId() . '\' failed. Editing default language is not allowed.')), 1365513336);
116 }
117 }
118
119 /**
120 * Copies a page and returns the id of the new page
121 *
122 * Node: Use a negative target id to specify a sibling target else the parent is used
123 *
124 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $sourceNode
125 * @param int $targetId
126 * @return int
127 */
128 static public function copyNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $sourceNode, $targetId) {
129 $cmd['pages'][$sourceNode->getId()]['copy'] = $targetId;
130 $returnValue = self::processTceCmdAndDataMap($cmd);
131 return $returnValue['pages'][$sourceNode->getId()];
132 }
133
134 /**
135 * Moves a page
136 *
137 * Node: Use a negative target id to specify a sibling target else the parent is used
138 *
139 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $sourceNode
140 * @param int $targetId
141 * @return void
142 */
143 static public function moveNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $sourceNode, $targetId) {
144 $cmd['pages'][$sourceNode->getId()]['move'] = $targetId;
145 self::processTceCmdAndDataMap($cmd);
146 }
147
148 /**
149 * Creates a page of the given doktype and returns the id of the created page
150 *
151 * @param \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $parentNode
152 * @param int $targetId
153 * @param int $pageType
154 * @return int
155 */
156 static public function createNode(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode $parentNode, $targetId, $pageType) {
157 $placeholder = 'NEW12345';
158 $pid = (int)$parentNode->getWorkspaceId();
159 $targetId = (int)$targetId;
160
161 // Use page TsConfig as default page initialization
162 $pageTs = BackendUtility::getPagesTSconfig($pid);
163 if (array_key_exists('TCAdefaults.', $pageTs) && array_key_exists('pages.', $pageTs['TCAdefaults.'])) {
164 $data['pages'][$placeholder] = $pageTs['TCAdefaults.']['pages.'];
165 } else {
166 $data['pages'][$placeholder] = array();
167 }
168
169 $data['pages'][$placeholder]['pid'] = $pid;
170 $data['pages'][$placeholder]['doktype'] = $pageType;
171 $data['pages'][$placeholder]['title'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:tree.defaultPageTitle', TRUE);
172 $newPageId = self::processTceCmdAndDataMap(array(), $data);
173 $node = self::getNode($newPageId[$placeholder]);
174 if ($pid !== $targetId) {
175 self::moveNode($node, $targetId);
176 }
177
178 return $newPageId[$placeholder];
179 }
180
181 /**
182 * Process TCEMAIN commands and data maps
183 *
184 * Command Map:
185 * Used for moving, recover, remove and some more operations.
186 *
187 * Data Map:
188 * Used for creating and updating records,
189 *
190 * This API contains all necessary access checks.
191 *
192 * @param array $cmd
193 * @param array $data
194 * @return array
195 * @throws \RuntimeException if an error happened while the TCE processing
196 */
197 static protected function processTceCmdAndDataMap(array $cmd, array $data = array()) {
198 /** @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */
199 $tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
200 $tce->stripslashes_values = 0;
201 $tce->start($data, $cmd);
202 $tce->copyTree = MathUtility::forceIntegerInRange($GLOBALS['BE_USER']->uc['copyLevels'], 0, 100);
203 if (count($cmd)) {
204 $tce->process_cmdmap();
205 $returnValues = $tce->copyMappingArray_merged;
206 } elseif (count($data)) {
207 $tce->process_datamap();
208 $returnValues = $tce->substNEWwithIDs;
209 } else {
210 $returnValues = array();
211 }
212 // check errors
213 if (count($tce->errorLog)) {
214 throw new \RuntimeException(implode(LF, $tce->errorLog), 1333754629);
215 }
216 return $returnValues;
217 }
218
219 /**
220 * Returns a node from the given node id
221 *
222 * @param int $nodeId
223 * @param bool $unsetMovePointers
224 * @return \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode
225 */
226 static public function getNode($nodeId, $unsetMovePointers = TRUE) {
227 $record = self::getNodeRecord($nodeId, $unsetMovePointers);
228 return self::getNewNode($record);
229 }
230
231 /**
232 * Returns the mount point path for a temporary mount or the given id
233 *
234 * @param int $uid
235 * @return string
236 */
237 static public function getMountPointPath($uid = -1) {
238 if ($uid === -1) {
239 $uid = (int)$GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint'];
240 }
241 if ($uid <= 0) {
242 return '';
243 }
244 if (self::$useNavTitle === NULL) {
245 self::$useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle');
246 }
247 $rootline = array_reverse(BackendUtility::BEgetRootLine($uid));
248 array_shift($rootline);
249 $path = array();
250 foreach ($rootline as $rootlineElement) {
251 $record = self::getNodeRecord($rootlineElement['uid']);
252 $text = $record['title'];
253 if (self::$useNavTitle && trim($record['nav_title']) !== '') {
254 $text = $record['nav_title'];
255 }
256 $path[] = htmlspecialchars($text);
257 }
258 return '/' . implode('/', $path);
259 }
260
261 /**
262 * Returns a node record from a given id
263 *
264 * @param int $nodeId
265 * @param bool $unsetMovePointers
266 * @return array
267 */
268 static public function getNodeRecord($nodeId, $unsetMovePointers = TRUE) {
269 $record = BackendUtility::getRecordWSOL('pages', $nodeId, '*', '', TRUE, $unsetMovePointers);
270 return $record;
271 }
272
273 /**
274 * Returns the first configured domain name for a page
275 *
276 * @param int $uid
277 * @return string
278 */
279 static public function getDomainName($uid) {
280 $whereClause = 'pid=' . (int)$uid . BackendUtility::deleteClause('sys_domain') . BackendUtility::BEenableFields('sys_domain');
281 $domain = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('domainName', 'sys_domain', $whereClause, '', 'sorting');
282 return is_array($domain) ? htmlspecialchars($domain['domainName']) : '';
283 }
284
285 /**
286 * Creates a node with the given record information
287 *
288 * @param array $record
289 * @param int $mountPoint
290 * @return \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode
291 */
292 static public function getNewNode($record, $mountPoint = 0) {
293 if (self::$titleLength === NULL) {
294 self::$useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle');
295 self::$addIdAsPrefix = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPageIdWithTitle');
296 self::$addDomainName = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showDomainNameWithTitle');
297 self::$backgroundColors = $GLOBALS['BE_USER']->getTSConfigProp('options.pageTree.backgroundColor');
298 self::$titleLength = (int)$GLOBALS['BE_USER']->uc['titleLen'];
299 }
300 /** @var $subNode \TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode */
301 $subNode = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode::class);
302 $subNode->setRecord($record);
303 $subNode->setCls($record['_CSSCLASS']);
304 $subNode->setType('pages');
305 $subNode->setId($record['uid']);
306 $subNode->setMountPoint($mountPoint);
307 $subNode->setWorkspaceId($record['_ORIG_uid'] ?: $record['uid']);
308 $subNode->setBackgroundColor(self::$backgroundColors[$record['uid']]);
309 $field = 'title';
310 $text = $record['title'];
311 if (self::$useNavTitle && trim($record['nav_title']) !== '') {
312 $field = 'nav_title';
313 $text = $record['nav_title'];
314 }
315 if (trim($text) === '') {
316 $visibleText = '[' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.no_title', TRUE) . ']';
317 } else {
318 $visibleText = $text;
319 }
320 $visibleText = GeneralUtility::fixed_lgd_cs($visibleText, self::$titleLength);
321 $suffix = '';
322 if (self::$addDomainName) {
323 $domain = self::getDomainName($record['uid']);
324 $suffix = $domain !== '' ? ' [' . $domain . ']' : '';
325 }
326 $qtip = str_replace(' - ', '<br />', htmlspecialchars(BackendUtility::titleAttribForPages($record, '', FALSE)));
327 $prefix = '';
328 $lockInfo = BackendUtility::isRecordLocked('pages', $record['uid']);
329 if (is_array($lockInfo)) {
330 $qtip .= '<br />' . htmlspecialchars($lockInfo['msg']);
331 $prefix .= IconUtility::getSpriteIcon('status-warning-in-use', array(
332 'class' => 'typo3-pagetree-status'
333 ));
334 }
335 // Call stats information hook
336 $stat = '';
337 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) {
338 $_params = array('pages', $record['uid']);
339 $fakeThis = NULL;
340 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) {
341 $stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $fakeThis);
342 }
343 }
344 $prefix .= htmlspecialchars(self::$addIdAsPrefix ? '[' . $record['uid'] . '] ' : '');
345 $subNode->setEditableText($text);
346 $subNode->setText(htmlspecialchars($visibleText), $field, $prefix, htmlspecialchars($suffix) . $stat);
347 $subNode->setQTip($qtip);
348 if ((int)$record['uid'] !== 0) {
349 $spriteIconCode = IconUtility::getSpriteIconForRecord('pages', $record);
350 } else {
351 $spriteIconCode = IconUtility::getSpriteIcon('apps-pagetree-root');
352 }
353 $subNode->setSpriteIconCode($spriteIconCode);
354 if (
355 !$subNode->canCreateNewPages()
356 || VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)
357 ) {
358 $subNode->setIsDropTarget(FALSE);
359 }
360 if (
361 !$subNode->canBeEdited()
362 || !$subNode->canBeRemoved()
363 || VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)
364 ) {
365 $subNode->setDraggable(FALSE);
366 }
367 return $subNode;
368 }
369
370 }