[BUGFIX] Remove early return in PageTreeDataProvider
[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 * Process collection hook objects
59 *
60 * @var array<t3lib_tree_pagetree_interfaces_collectionprocessor>
61 */
62 protected $processCollectionHookObjects = array();
63
64 /**
65 * Constructor
66 *
67 * @param int $nodeLimit (optional)
68 */
69 public function __construct($nodeLimit = NULL) {
70 if ($nodeLimit === NULL) {
71 $nodeLimit = $GLOBALS['TYPO3_CONF_VARS']['BE']['pageTree']['preloadLimit'];
72 }
73 $this->nodeLimit = abs(intval($nodeLimit));
74
75 $this->hiddenRecords = t3lib_div::trimExplode(
76 ',',
77 $GLOBALS['BE_USER']->getTSConfigVal('options.hideRecords.pages')
78 );
79
80 $hookElements = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php']['postProcessCollections'];
81 if (is_array($hookElements)) {
82 foreach ($hookElements as $classRef) {
83 /** @var $hookObject t3lib_tree_pagetree_interfaces_collectionprocessor */
84 $hookObject = t3lib_div::getUserObj($classRef);
85 if ($hookObject instanceof t3lib_tree_pagetree_interfaces_collectionprocessor) {
86 $this->processCollectionHookObjects[] = $hookObject;
87 }
88 }
89 }
90 }
91
92 /**
93 * Returns the root node
94 *
95 * @return t3lib_tree_Node
96 */
97 public function getRoot() {
98 /** @var $node t3lib_tree_pagetree_Node */
99 $node = t3lib_div::makeInstance('t3lib_tree_pagetree_Node');
100 $node->setId('root');
101 $node->setExpanded(TRUE);
102
103 return $node;
104 }
105
106 /**
107 * Fetches the sub-nodes of the given node
108 *
109 * @param t3lib_tree_Node $node
110 * @param int $mountPoint
111 * @param int $level internally used variable as a recursion limiter
112 * @return t3lib_tree_NodeCollection
113 */
114 public function getNodes(t3lib_tree_Node $node, $mountPoint = 0, $level = 0) {
115 /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */
116 $nodeCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
117
118 if ($level >= 99) {
119 return $nodeCollection;
120 }
121
122 $subpages = $this->getSubpages($node->getId());
123 if (is_array($subpages) && count($subpages) > 0) {
124
125 foreach ($subpages as $subpage) {
126 if (in_array($subpage['uid'], $this->hiddenRecords)) {
127 continue;
128 }
129
130 $subpage = t3lib_befunc::getRecordWSOL('pages', $subpage['uid'], '*', '', TRUE, TRUE);
131 if (!$subpage) {
132 continue;
133 }
134
135 $subNode = t3lib_tree_pagetree_Commands::getNewNode($subpage, $mountPoint);
136 if ($this->nodeCounter < $this->nodeLimit) {
137 $childNodes = $this->getNodes($subNode, $mountPoint, $level + 1);
138 $subNode->setChildNodes($childNodes);
139 $this->nodeCounter += $childNodes->count();
140 } else {
141 $subNode->setLeaf(!$this->hasNodeSubPages($subNode->getId()));
142 }
143
144 $nodeCollection->append($subNode);
145 }
146 }
147
148
149 foreach ($this->processCollectionHookObjects as $hookObject) {
150 /** @var $hookObject t3lib_tree_pagetree_interfaces_collectionprocessor */
151 $hookObject->postProcessGetNodes($node, $mountPoint, $level, $nodeCollection);
152 }
153
154 return $nodeCollection;
155 }
156
157 /**
158 * Returns a node collection of filtered nodes
159 *
160 * @param t3lib_tree_Node $node
161 * @param string $searchFilter
162 * @param int $mountPoint
163 * @return void
164 */
165 public function getFilteredNodes(t3lib_tree_Node $node, $searchFilter, $mountPoint = 0) {
166 /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */
167 $nodeCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
168
169 $records = $this->getSubpages(-1, $searchFilter);
170 if (!is_array($records) || !count($records)) {
171 return $nodeCollection;
172 } elseif (count($records) > 500) {
173 return $nodeCollection;
174 }
175
176 $isNumericSearchFilter = (is_numeric($searchFilter) && $searchFilter > 0);
177 $nodeId = intval($node->getId());
178 foreach ($records as $record) {
179 $record = t3lib_tree_pagetree_Commands::getNodeRecord($record['uid']);
180 if (intval($record['pid']) === -1 || in_array($record['uid'], $this->hiddenRecords)) {
181 continue;
182 }
183
184 $rootline = t3lib_BEfunc::BEgetRootLine($record['uid'], ' AND uid != ' . $nodeId);
185 $rootline = array_reverse($rootline);
186 if ($nodeId === 0) {
187 array_shift($rootline);
188 }
189 $reference = $nodeCollection;
190
191 $inFilteredRootline = FALSE;
192 $amountOfRootlineElements = count($rootline);
193 for ($i = 0; $i < $amountOfRootlineElements; ++$i) {
194 $rootlineElement = $rootline[$i];
195 if (intval($rootlineElement['pid']) === $nodeId) {
196 $inFilteredRootline = TRUE;
197 }
198
199 if (!$inFilteredRootline) {
200 continue;
201 }
202
203 $rootlineElement = t3lib_tree_pagetree_Commands::getNodeRecord($rootlineElement['uid']);
204 $ident = intval($rootlineElement['sorting']) . intval($rootlineElement['uid']);
205 if ($reference && $reference->offsetExists($ident)) {
206 /** @var $refNode t3lib_tree_pagetree_Node */
207 $refNode = $reference->offsetGet($ident);
208 $refNode->setExpanded(TRUE);
209 $refNode->setLeaf(FALSE);
210
211 $reference = $refNode->getChildNodes();
212 if ($reference == NULL) {
213 $reference = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
214 $refNode->setChildNodes($reference);
215 }
216 } else {
217 $refNode = t3lib_tree_pagetree_Commands::getNewNode($rootlineElement, $mountPoint);
218 $replacement = '<span class="typo3-pagetree-filteringTree-highlight">$1</span>';
219 if ($isNumericSearchFilter && intval($rootlineElement['uid']) === intval($searchFilter)) {
220 $text = str_replace('$1', $refNode->getText(), $replacement);
221 } else {
222 $text = preg_replace('/(' . $searchFilter . ')/i', $replacement, $refNode->getText());
223 }
224
225 $refNode->setText(
226 $text,
227 $refNode->getTextSourceField(),
228 $refNode->getPrefix(),
229 $refNode->getSuffix()
230 );
231
232 /** @var $childCollection t3lib_tree_pagetree_NodeCollection */
233 $childCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
234
235 if (($i +1) >= $amountOfRootlineElements) {
236 $childNodes = $this->getNodes($refNode, $mountPoint);
237 foreach ($childNodes as $childNode) {
238 /** @var $childNode t3lib_tree_pagetree_Node */
239 $childRecord = $childNode->getRecord();
240 $childIdent = intval($childRecord['sorting']) . intval($childRecord['uid']);
241 $childCollection->offsetSet($childIdent, $childNode);
242 }
243 $refNode->setChildNodes($childNodes);
244 }
245
246 $refNode->setChildNodes($childCollection);
247 $reference->offsetSet($ident, $refNode);
248 $reference->ksort();
249
250 $reference = $childCollection;
251 }
252 }
253 }
254
255 foreach ($this->processCollectionHookObjects as $hookObject) {
256 /** @var $hookObject t3lib_tree_pagetree_interfaces_collectionprocessor */
257 $hookObject->postProcessFilteredNodes($node, $searchFilter, $mountPoint, $nodeCollection);
258 }
259
260 return $nodeCollection;
261 }
262
263 /**
264 * Returns the page tree mounts for the current user
265 *
266 * Note: If you add the search filter parameter, the nodes will be filtered by this string.
267 *
268 * @param string $searchFilter
269 * @return array
270 */
271 public function getTreeMounts($searchFilter = '') {
272 /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */
273 $nodeCollection = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection');
274
275 $isTemporaryMountPoint = FALSE;
276 $mountPoints = intval($GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint']);
277 if (!$mountPoints) {
278 $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
279 $mountPoints = array_unique($mountPoints);
280 } else {
281 $isTemporaryMountPoint = TRUE;
282 $mountPoints = array($mountPoints);
283 }
284
285 if (!count($mountPoints)) {
286 return $nodeCollection;
287 }
288
289 $showRootlineAboveMounts = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPathAboveMounts');
290 foreach ($mountPoints as $mountPoint) {
291 if ($mountPoint === 0) {
292 $sitename = 'TYPO3';
293 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] !== '') {
294 $sitename = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
295 }
296
297 $record = array(
298 'uid' => 0,
299 'title' => $sitename,
300 );
301 $subNode = t3lib_tree_pagetree_Commands::getNewNode($record);
302 $subNode->setLabelIsEditable(FALSE);
303 $subNode->setType('pages_root');
304 } else {
305 if (in_array($mountPoint, $this->hiddenRecords)) {
306 continue;
307 }
308
309 $record = t3lib_BEfunc::getRecordWSOL('pages', $mountPoint, '*', '', TRUE);
310 if (!$record) {
311 continue;
312 }
313
314 $subNode = t3lib_tree_pagetree_Commands::getNewNode($record, $mountPoint);
315 if ($showRootlineAboveMounts && !$isTemporaryMountPoint) {
316 $rootline = t3lib_tree_pagetree_Commands::getMountPointPath($record['uid']);
317 $subNode->setReadableRootline($rootline);
318 }
319 }
320
321 if (count($mountPoints) <= 1) {
322 $subNode->setExpanded(TRUE);
323 $subNode->setCls('typo3-pagetree-node-notExpandable');
324 }
325
326 $subNode->setIsMountPoint(TRUE);
327 $subNode->setDraggable(FALSE);
328 $subNode->setIsDropTarget(FALSE);
329
330 if ($searchFilter === '') {
331 $childNodes = $this->getNodes($subNode, $mountPoint);
332 } else {
333 $childNodes = $this->getFilteredNodes($subNode, $searchFilter, $mountPoint);
334 $subNode->setExpanded(TRUE);
335 }
336
337 $subNode->setChildNodes($childNodes);
338 $nodeCollection->append($subNode);
339 }
340
341 foreach ($this->processCollectionHookObjects as $hookObject) {
342 /** @var $hookObject t3lib_tree_pagetree_interfaces_collectionprocessor */
343 $hookObject->postProcessGetTreeMounts($searchFilter, $nodeCollection);
344 }
345
346 return $nodeCollection;
347 }
348
349 /**
350 * Returns the where clause for fetching pages
351 *
352 * @param int $id
353 * @param string $searchFilter
354 * @return string
355 */
356 protected function getWhereClause($id, $searchFilter = '') {
357 $where = $GLOBALS['BE_USER']->getPagePermsClause(1) .
358 t3lib_BEfunc::deleteClause('pages') .
359 t3lib_BEfunc::versioningPlaceholderClause('pages');
360
361 if (is_numeric($id) && $id >= 0) {
362 $where .= ' AND pid= ' . $GLOBALS['TYPO3_DB']->fullQuoteStr(intval($id), 'pages');
363 }
364
365 if ($searchFilter !== '') {
366 if (is_numeric($searchFilter) && $searchFilter > 0) {
367 $seachWhere .= 'uid = ' . intval($searchFilter) . ' OR ';
368 }
369
370 $searchFilter = $GLOBALS['TYPO3_DB']->fullQuoteStr('%' . $searchFilter . '%', 'pages');
371 $useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle');
372
373 if ($useNavTitle) {
374 $seachWhere .= '(nav_title LIKE ' . $searchFilter .
375 ' OR (nav_title = "" && title LIKE ' . $searchFilter . '))';
376 } else {
377 $seachWhere .= 'title LIKE ' . $searchFilter;
378 }
379
380 $where .= ' AND (' . $seachWhere . ')';
381 }
382
383 return $where;
384 }
385
386 /**
387 * Returns all sub-pages of a given id
388 *
389 * @param int $id
390 * @param string $searchFilter
391 * @return array
392 */
393 protected function getSubpages($id, $searchFilter = '') {
394 $where = $this->getWhereClause($id, $searchFilter);
395 $subpages = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
396 'uid', 'pages', $where, '', 'sorting', '', 'uid'
397 );
398
399 return $subpages;
400 }
401
402 /**
403 * Returns TRUE if the node has child's
404 *
405 * @param int $id
406 * @return bool
407 */
408 protected function hasNodeSubPages($id) {
409 $where = $this->getWhereClause($id);
410 $subpage = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
411 'uid', 'pages', $where, '', 'sorting', '', 'uid'
412 );
413
414 $returnValue = TRUE;
415 if (!$subpage['uid']) {
416 $returnValue = FALSE;
417 }
418
419 return $returnValue;
420 }
421 }
422
423 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php'])) {
424 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php']);
425 }
426
427 ?>