[BUGFIX] Drag&Drop inside the root page of the pagetree isn't possible
[Packages/TYPO3.CMS.git] / t3lib / tree / pagetree / class.t3lib_tree_pagetree_dataprovider.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010-2011 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * Abstract Tree Data Provider
30 *
31 * @author Stefan Galinski <stefan.galinski@gmail.com>
32 * @package TYPO3
33 * @subpackage t3lib
34 */
35 class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider {
36 /**
37 * Node limit that should be loaded for this request per mount
38 *
39 * @var int
40 */
41 protected $nodeLimit = 0;
42
43 /**
44 * Current amount of nodes
45 *
46 * @var int
47 */
48 protected $nodeCounter = 0;
49
50 /**
51 * Hidden Records
52 *
53 * @var array
54 */
55 protected $hiddenRecords = array();
56
57 /**
58 * Constructor
59 *
60 * @param int $nodeLimit (optional)
61 */
62 public function __construct($nodeLimit = NULL) {
63 if ($nodeLimit === NULL) {
64 $nodeLimit = $GLOBALS['TYPO3_CONF_VARS']['BE']['pageTree']['preloadLimit'];
65 }
66 $this->nodeLimit = abs(intval($nodeLimit));
67
68 $this->hiddenRecords = t3lib_div::trimExplode(
69 ',',
70 $GLOBALS['BE_USER']->getTSConfigVal('options.hideRecords.pages')
71 );
72 }
73
74 /**
75 * Returns the root node
76 *
77 * @return t3lib_tree_Node
78 */
79 public function getRoot() {
80 /** @var $node t3lib_tree_pagetree_Node */
81 $node = t3lib_div::makeInstance('t3lib_tree_pagetree_Node');
82 $node->setId('root');
83 $node->setExpanded(true);
84
85 return $node;
86 }
87
88 /**
89 * Fetches the sub-nodes of the given node
90 *
91 * @param t3lib_tree_Node $node
92 * @param int $mountPoint
93 * @param int $level internally used variable as a recursion limiter
94 * @return t3lib_tree_NodeCollection
95 */
96 public function getNodes(t3lib_tree_Node $node, $mountPoint = 0, $level = 0) {
97 /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */
98 $nodeCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
99
100 if ($level >= 99) {
101 return $nodeCollection;
102 }
103
104 $subpages = $this->getSubpages($node->getId());
105 if (!is_array($subpages) || !count($subpages)) {
106 return $nodeCollection;
107 }
108
109 foreach ($subpages as $subpage) {
110 if (in_array($subpage['uid'], $this->hiddenRecords)) {
111 continue;
112 }
113
114 // must be calculated above getRecordWSOL, because the information is lost otherwise
115 $isMountPoint = ($subpage['isMountPoint'] === TRUE);
116
117 $subpage = t3lib_befunc::getRecordWSOL('pages', $subpage['uid'], '*', '', TRUE, TRUE);
118 if (!$subpage) {
119 continue;
120 }
121
122 $subNode = t3lib_tree_pagetree_Commands::getNewNode($subpage, $mountPoint);
123 $subNode->setIsMountPoint($isMountPoint);
124 if ($this->nodeCounter < $this->nodeLimit) {
125 $childNodes = $this->getNodes($subNode, $mountPoint, $level + 1);
126 $subNode->setChildNodes($childNodes);
127 $this->nodeCounter += $childNodes->count();
128 } else {
129 $subNode->setLeaf(!$this->hasNodeSubPages($subNode->getId()));
130 }
131
132 $nodeCollection->append($subNode);
133 }
134
135 return $nodeCollection;
136 }
137
138 /**
139 * Returns a node collection of filtered nodes
140 *
141 * @param t3lib_tree_Node $node
142 * @param string $searchFilter
143 * @param int $mountPoint
144 * @return void
145 */
146 public function getFilteredNodes(t3lib_tree_Node $node, $searchFilter, $mountPoint = 0) {
147 /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */
148 $nodeCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
149
150 $records = $this->getSubpages(-1, $searchFilter);
151 if (!is_array($records) || !count($records)) {
152 return $nodeCollection;
153 } elseif (count($records) > 500) {
154 return $nodeCollection;
155 }
156
157 $isNumericSearchFilter = (is_numeric($searchFilter) && $searchFilter > 0);
158 $nodeId = intval($node->getId());
159 foreach ($records as $record) {
160 $record = t3lib_tree_pagetree_Commands::getNodeRecord($record['uid']);
161 if (intval($record['pid']) === -1 || in_array($record['uid'], $this->hiddenRecords)) {
162 continue;
163 }
164
165 $rootline = t3lib_BEfunc::BEgetRootLine($record['uid'], ' AND uid != ' . $nodeId);
166 $rootline = array_reverse($rootline);
167 if ($nodeId === 0) {
168 array_shift($rootline);
169 }
170 $reference = $nodeCollection;
171
172 $inFilteredRootline = FALSE;
173 $amountOfRootlineElements = count($rootline);
174 for ($i = 0; $i < $amountOfRootlineElements; ++$i) {
175 $rootlineElement = $rootline[$i];
176 if (intval($rootlineElement['pid']) === $nodeId) {
177 $inFilteredRootline = TRUE;
178 }
179
180 if (!$inFilteredRootline) {
181 continue;
182 }
183
184 $rootlineElement = t3lib_tree_pagetree_Commands::getNodeRecord($rootlineElement['uid']);
185 $ident = intval($rootlineElement['sorting']) . intval($rootlineElement['uid']);
186 if ($reference && $reference->offsetExists($ident)) {
187 /** @var $refNode t3lib_tree_pagetree_Node */
188 $refNode = $reference->offsetGet($ident);
189 $refNode->setExpanded(TRUE);
190 $refNode->setLeaf(FALSE);
191
192 $reference = $refNode->getChildNodes();
193 if ($reference == NULL) {
194 $reference = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
195 $refNode->setChildNodes($reference);
196 }
197 } else {
198 $refNode = t3lib_tree_pagetree_Commands::getNewNode($rootlineElement, $mountPoint);
199 $replacement = '<span class="typo3-pagetree-filteringTree-highlight">$1</span>';
200 if ($isNumericSearchFilter && intval($rootlineElement['uid']) === intval($searchFilter)) {
201 $text = str_replace('$1', $refNode->getText(), $replacement);
202 } else {
203 $text = preg_replace('/(' . $searchFilter . ')/i', $replacement, $refNode->getText());
204 }
205
206 $refNode->setText(
207 $text,
208 $refNode->getTextSourceField(),
209 $refNode->getPrefix(),
210 $refNode->getSuffix()
211 );
212
213 /** @var $childCollection t3lib_tree_pagetree_NodeCollection */
214 $childCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
215
216 if (($i +1) >= $amountOfRootlineElements) {
217 $childNodes = $this->getNodes($refNode, $mountPoint);
218 foreach ($childNodes as $childNode) {
219 /** @var $childNode t3lib_tree_pagetree_Node */
220 $childRecord = $childNode->getRecord();
221 $childIdent = intval($childRecord['sorting']) . intval($childRecord['uid']);
222 $childCollection->offsetSet($childIdent, $childNode);
223 }
224 $refNode->setChildNodes($childNodes);
225 }
226
227 $refNode->setChildNodes($childCollection);
228 $reference->offsetSet($ident, $refNode);
229 $reference->ksort();
230
231 $reference = $childCollection;
232 }
233 }
234 }
235
236 return $nodeCollection;
237 }
238
239 /**
240 * Returns the page tree mounts for the current user
241 *
242 * Note: If you add the search filter parameter, the nodes will be filtered by this string.
243 *
244 * @param string $searchFilter
245 * @return array
246 */
247 public function getTreeMounts($searchFilter = '') {
248 /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */
249 $nodeCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
250
251 $isTemporaryMountPoint = FALSE;
252 $mountPoints = intval($GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint']);
253 if (!$mountPoints) {
254 $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
255 $mountPoints = array_unique($mountPoints);
256 } else {
257 $isTemporaryMountPoint = TRUE;
258 $mountPoints = array($mountPoints);
259 }
260
261 if (!count($mountPoints)) {
262 return $nodeCollection;
263 }
264
265 $showRootlineAboveMounts = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPathAboveMounts');
266 foreach ($mountPoints as $mountPoint) {
267 if ($mountPoint === 0) {
268 $sitename = 'TYPO3';
269 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] !== '') {
270 $sitename = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
271 }
272
273 $record = array(
274 'uid' => 0,
275 'title' => $sitename,
276 );
277 $subNode = t3lib_tree_pagetree_Commands::getNewNode($record);
278 $subNode->setLabelIsEditable(FALSE);
279 $subNode->setType('pages_root');
280 } else {
281 if (in_array($mountPoint, $this->hiddenRecords)) {
282 continue;
283 }
284
285 $record = t3lib_BEfunc::getRecordWSOL('pages', $mountPoint, '*', '', TRUE);
286 if (!$record) {
287 continue;
288 }
289
290 $subNode = t3lib_tree_pagetree_Commands::getNewNode($record, $mountPoint);
291 if ($showRootlineAboveMounts && !$isTemporaryMountPoint) {
292 $rootline = t3lib_tree_pagetree_Commands::getMountPointPath($record['uid']);
293 $subNode->setReadableRootline($rootline);
294 }
295 }
296
297 if (count($mountPoints) <= 1) {
298 $subNode->setExpanded(TRUE);
299 $subNode->setCls('typo3-pagetree-node-notExpandable');
300 }
301
302 $subNode->setIsMountPoint(TRUE);
303 $subNode->setDraggable(FALSE);
304
305 if ($searchFilter === '') {
306 $childNodes = $this->getNodes($subNode, $mountPoint);
307 } else {
308 $childNodes = $this->getFilteredNodes($subNode, $searchFilter, $mountPoint);
309 $subNode->setExpanded(TRUE);
310 }
311
312 $subNode->setChildNodes($childNodes);
313 $nodeCollection->append($subNode);
314 }
315
316 return $nodeCollection;
317 }
318
319 /**
320 * Returns the where clause for fetching pages
321 *
322 * @param int $id
323 * @param string $searchFilter
324 * @return string
325 */
326 protected function getWhereClause($id, $searchFilter = '') {
327 $where = $GLOBALS['BE_USER']->getPagePermsClause(1) .
328 t3lib_BEfunc::deleteClause('pages') .
329 t3lib_BEfunc::versioningPlaceholderClause('pages');
330
331 if (is_numeric($id) && $id >= 0) {
332 $where .= ' AND pid= ' . $GLOBALS['TYPO3_DB']->fullQuoteStr(intval($id), 'pages');
333 }
334
335 if ($searchFilter !== '') {
336 if (is_numeric($searchFilter) && $searchFilter > 0) {
337 $seachWhere .= 'uid = ' . intval($searchFilter) . ' OR ';
338 }
339
340 $searchFilter = $GLOBALS['TYPO3_DB']->fullQuoteStr('%' . $searchFilter . '%', 'pages');
341 $useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle');
342
343 if ($useNavTitle) {
344 $seachWhere .= '(nav_title LIKE ' . $searchFilter .
345 ' OR (nav_title = "" && title LIKE ' . $searchFilter . '))';
346 } else {
347 $seachWhere .= 'title LIKE ' . $searchFilter;
348 }
349
350 $where .= ' AND (' . $seachWhere . ')';
351 }
352
353 return $where;
354 }
355
356 /**
357 * Returns all sub-pages of a given id
358 *
359 * @param int $id
360 * @param string $searchFilter
361 * @return array
362 */
363 protected function getSubpages($id, $searchFilter = '') {
364 $where = $this->getWhereClause($id, $searchFilter);
365 $subpages = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
366 'uid', 'pages', $where, '', 'sorting', '', 'uid'
367 );
368
369 return $subpages;
370 }
371
372 /**
373 * Returns true if the node has child's
374 *
375 * @param int $id
376 * @return bool
377 */
378 protected function hasNodeSubPages($id) {
379 $where = $this->getWhereClause($id);
380 $subpage = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
381 'uid', 'pages', $where, '', 'sorting', '', 'uid'
382 );
383
384 $returnValue = TRUE;
385 if (!$subpage['uid']) {
386 $returnValue = FALSE;
387 }
388
389 return $returnValue;
390 }
391 }
392
393 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php'])) {
394 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php']);
395 }
396
397 ?>