TYPO3 CMS  TYPO3_7-6
DataProvider.php
Go to the documentation of this file.
1 <?php
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 
19 
24 {
30  protected $nodeLimit = 0;
31 
37  protected $nodeCounter = 0;
38 
44  protected $showRootlineAboveMounts = false;
45 
51  protected $hiddenRecords = [];
52 
59 
65  public function __construct($nodeLimit = null)
66  {
67  if ($nodeLimit === null) {
68  $nodeLimit = $GLOBALS['TYPO3_CONF_VARS']['BE']['pageTree']['preloadLimit'];
69  }
70  $this->nodeLimit = abs((int)$nodeLimit);
71 
72  $this->showRootlineAboveMounts = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPathAboveMounts');
73 
74  $this->hiddenRecords = GeneralUtility::trimExplode(',', $GLOBALS['BE_USER']->getTSConfigVal('options.hideRecords.pages'));
75  $hookElements = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php']['postProcessCollections'];
76  if (is_array($hookElements)) {
77  foreach ($hookElements as $classRef) {
79  $hookObject = GeneralUtility::getUserObj($classRef);
80  if ($hookObject instanceof \TYPO3\CMS\Backend\Tree\Pagetree\CollectionProcessorInterface) {
81  $this->processCollectionHookObjects[] = $hookObject;
82  }
83  }
84  }
85  }
86 
92  public function getRoot()
93  {
95  $node = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNode::class);
96  $node->setId('root');
97  $node->setExpanded(true);
98  return $node;
99  }
100 
109  public function getNodes(\TYPO3\CMS\Backend\Tree\TreeNode $node, $mountPoint = 0, $level = 0)
110  {
112  $nodeCollection = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNodeCollection::class);
113  if ($level >= 99 || $node->getStopPageTree()) {
114  return $nodeCollection;
115  }
116  $isVirtualRootNode = false;
117  $subpages = $this->getSubpages($node->getId());
118  // check if fetching subpages the "root"-page
119  // and in case of a virtual root return the mountpoints as virtual "subpages"
120  if ((int)$node->getId() === 0) {
121  // check no temporary mountpoint is used
122  if (!(int)$GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint']) {
123  $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
124  $mountPoints = array_unique($mountPoints);
125  if (!in_array(0, $mountPoints)) {
126  // using a virtual root node
127  // so then return the mount points here as "subpages" of the first node
128  $isVirtualRootNode = true;
129  $subpages = [];
130  foreach ($mountPoints as $webMountPoint) {
131  $subpages[] = [
132  'uid' => $webMountPoint,
133  'isMountPoint' => true
134  ];
135  }
136  }
137  }
138  }
139  if (is_array($subpages) && !empty($subpages)) {
140  $lastRootline = [];
141  foreach ($subpages as $subpage) {
142  if (in_array($subpage['uid'], $this->hiddenRecords)) {
143  continue;
144  }
145  // must be calculated above getRecordWithWorkspaceOverlay,
146  // because the information is lost otherwise
147  $isMountPoint = $subpage['isMountPoint'] === true;
148  if ($isVirtualRootNode) {
149  $mountPoint = (int)$subpage['uid'];
150  }
151  $subpage = $this->getRecordWithWorkspaceOverlay($subpage['uid'], true);
152  if (!$subpage) {
153  continue;
154  }
155  $subNode = Commands::getNewNode($subpage, $mountPoint);
156  $subNode->setIsMountPoint($isMountPoint);
157  if ($isMountPoint && $this->showRootlineAboveMounts) {
158  if ($subpage['pid'] > 0) {
159  $rootline = Commands::getMountPointPath($subpage['pid']);
160  } else {
161  $rootline = Commands::getMountPointPath($subpage['uid']);
162  }
163  if ($lastRootline !== $rootline) {
164  $subNode->setReadableRootline($rootline);
165  }
166  $lastRootline = $rootline;
167  }
168  if ($this->nodeCounter < $this->nodeLimit) {
169  $childNodes = $this->getNodes($subNode, $mountPoint, $level + 1);
170  $subNode->setChildNodes($childNodes);
171  $this->nodeCounter += $childNodes->count();
172  } else {
173  $subNode->setLeaf(!$this->hasNodeSubPages($subNode->getId()));
174  }
175  if (!$GLOBALS['BE_USER']->isAdmin() && (int)$subpage['editlock'] === 1) {
176  $subNode->setLabelIsEditable(false);
177  }
178  $nodeCollection->append($subNode);
179  }
180  }
181  foreach ($this->processCollectionHookObjects as $hookObject) {
183  $hookObject->postProcessGetNodes($node, $mountPoint, $level, $nodeCollection);
184  }
185  return $nodeCollection;
186  }
187 
195  protected function getRecordWithWorkspaceOverlay($uid, $unsetMovePointers = false)
196  {
197  return BackendUtility::getRecordWSOL('pages', $uid, '*', '', true, $unsetMovePointers);
198  }
199 
208  public function getFilteredNodes(\TYPO3\CMS\Backend\Tree\TreeNode $node, $searchFilter, $mountPoint = 0)
209  {
211  $nodeCollection = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNodeCollection::class);
212  $records = $this->getSubpages(-1, $searchFilter);
213  if (!is_array($records) || empty($records)) {
214  return $nodeCollection;
215  } elseif (count($records) > 500) {
216  return $nodeCollection;
217  }
218  // check no temporary mountpoint is used
219  $mountPoints = (int)$GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint'];
220  if (!$mountPoints) {
221  $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
222  $mountPoints = array_unique($mountPoints);
223  } else {
224  $mountPoints = [$mountPoints];
225  }
226  $isNumericSearchFilter = is_numeric($searchFilter) && $searchFilter > 0;
227  $searchFilterQuoted = preg_quote($searchFilter, '/');
228  $nodeId = (int)$node->getId();
229  $processedRecordIds = [];
230  foreach ($records as $record) {
231  if ((int)$record['t3ver_wsid'] !== (int)$GLOBALS['BE_USER']->workspace && (int)$record['t3ver_wsid'] !== 0) {
232  continue;
233  }
234  $liveVersion = BackendUtility::getLiveVersionOfRecord('pages', $record['uid'], 'uid');
235  if ($liveVersion !== null) {
236  $record = $liveVersion;
237  }
238 
239  $record = Commands::getNodeRecord($record['uid'], false);
240  if ((int)$record['pid'] === -1
241  || in_array($record['uid'], $this->hiddenRecords)
242  || in_array($record['uid'], $processedRecordIds)
243  ) {
244  continue;
245  }
246  $processedRecordIds[] = $record['uid'];
247 
248  $rootline = BackendUtility::BEgetRootLine($record['uid'], '', $GLOBALS['BE_USER']->workspace != 0);
249  $rootline = array_reverse($rootline);
250  if (!in_array(0, $mountPoints, true)) {
251  $isInsideMountPoints = false;
252  foreach ($rootline as $rootlineElement) {
253  if (in_array((int)$rootlineElement['uid'], $mountPoints, true)) {
254  $isInsideMountPoints = true;
255  break;
256  }
257  }
258  if (!$isInsideMountPoints) {
259  continue;
260  }
261  }
262  $reference = $nodeCollection;
263  $inFilteredRootline = false;
264  $amountOfRootlineElements = count($rootline);
265  for ($i = 0; $i < $amountOfRootlineElements; ++$i) {
266  $rootlineElement = $rootline[$i];
267  $rootlineElement['uid'] = (int)$rootlineElement['uid'];
268  $isInWebMount = (int)$GLOBALS['BE_USER']->isInWebMount($rootlineElement['uid']);
269  if (!$isInWebMount
270  || ($rootlineElement['uid'] === (int)$mountPoints[0]
271  && $rootlineElement['uid'] !== $isInWebMount)
272  ) {
273  continue;
274  }
275  if ((int)$rootlineElement['pid'] === $nodeId
276  || $rootlineElement['uid'] === $nodeId
277  || ($rootlineElement['uid'] === $isInWebMount
278  && in_array($rootlineElement['uid'], $mountPoints, true))
279  ) {
280  $inFilteredRootline = true;
281  }
282  if (!$inFilteredRootline || $rootlineElement['uid'] === $mountPoint) {
283  continue;
284  }
285  $rootlineElement = Commands::getNodeRecord($rootlineElement['uid'], false);
286  $ident = (int)$rootlineElement['sorting'] . (int)$rootlineElement['uid'];
287  if ($reference && $reference->offsetExists($ident)) {
289  $refNode = $reference->offsetGet($ident);
290  $refNode->setExpanded(true);
291  $refNode->setLeaf(false);
292  $reference = $refNode->getChildNodes();
293  if ($reference == null) {
294  $reference = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNodeCollection::class);
295  $refNode->setChildNodes($reference);
296  }
297  } else {
298  $refNode = Commands::getNewNode($rootlineElement, $mountPoint);
299  $replacement = '<span class="typo3-pagetree-filteringTree-highlight">$1</span>';
300  if ($isNumericSearchFilter && (int)$rootlineElement['uid'] === (int)$searchFilter) {
301  $text = str_replace('$1', $refNode->getText(), $replacement);
302  } else {
303  $text = preg_replace('/(' . $searchFilterQuoted . ')/iu', $replacement, $refNode->getText());
304  }
305  $refNode->setText($text, $refNode->getTextSourceField(), $refNode->getPrefix(), $refNode->getSuffix());
307  $childCollection = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNodeCollection::class);
308  if ($i + 1 >= $amountOfRootlineElements) {
309  $childNodes = $this->getNodes($refNode, $mountPoint);
310  foreach ($childNodes as $childNode) {
312  $childRecord = $childNode->getRecord();
313  $childIdent = (int)$childRecord['sorting'] . (int)$childRecord['uid'];
314  $childCollection->offsetSet($childIdent, $childNode);
315  }
316  $refNode->setChildNodes($childNodes);
317  }
318  $refNode->setChildNodes($childCollection);
319  $reference->offsetSet($ident, $refNode);
320  $reference->ksort();
321  $reference = $childCollection;
322  }
323  }
324  }
325  foreach ($this->processCollectionHookObjects as $hookObject) {
327  $hookObject->postProcessFilteredNodes($node, $searchFilter, $mountPoint, $nodeCollection);
328  }
329  return $nodeCollection;
330  }
331 
340  public function getTreeMounts($searchFilter = '')
341  {
343  $nodeCollection = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\Pagetree\PagetreeNodeCollection::class);
344  $isTemporaryMountPoint = false;
345  $rootNodeIsVirtual = false;
346  $mountPoints = (int)$GLOBALS['BE_USER']->uc['pageTree_temporaryMountPoint'];
347  if (!$mountPoints) {
348  $mountPoints = array_map('intval', $GLOBALS['BE_USER']->returnWebmounts());
349  $mountPoints = array_unique($mountPoints);
350  if (!in_array(0, $mountPoints)) {
351  $rootNodeIsVirtual = true;
352  // use a virtual root
353  // the real mountpoints will be fetched in getNodes() then
354  // since those will be the "subpages" of the virtual root
355  $mountPoints = [0];
356  }
357  } else {
358  $isTemporaryMountPoint = true;
359  $mountPoints = [$mountPoints];
360  }
361  if (empty($mountPoints)) {
362  return $nodeCollection;
363  }
364 
365  foreach ($mountPoints as $mountPoint) {
366  if ($mountPoint === 0) {
367  $sitename = 'TYPO3';
368  if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] !== '') {
369  $sitename = $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
370  }
371  $record = [
372  'uid' => 0,
373  'title' => $sitename
374  ];
375  $subNode = Commands::getNewNode($record);
376  $subNode->setLabelIsEditable(false);
377  if ($rootNodeIsVirtual) {
378  $subNode->setType('virtual_root');
379  $subNode->setIsDropTarget(false);
380  } else {
381  $subNode->setType('pages_root');
382  $subNode->setIsDropTarget(true);
383  }
384  } else {
385  if (in_array($mountPoint, $this->hiddenRecords)) {
386  continue;
387  }
388  $record = $this->getRecordWithWorkspaceOverlay($mountPoint);
389  if (!$record) {
390  continue;
391  }
392  $subNode = Commands::getNewNode($record, $mountPoint);
393  if ($this->showRootlineAboveMounts && !$isTemporaryMountPoint) {
394  $rootline = Commands::getMountPointPath($record['uid']);
395  $subNode->setReadableRootline($rootline);
396  }
397  }
398  if (count($mountPoints) <= 1) {
399  $subNode->setExpanded(true);
400  $subNode->setCls('typo3-pagetree-node-notExpandable');
401  }
402  $subNode->setIsMountPoint(true);
403  $subNode->setDraggable(false);
404  if ($searchFilter === '') {
405  $childNodes = $this->getNodes($subNode, $mountPoint);
406  } else {
407  $childNodes = $this->getFilteredNodes($subNode, $searchFilter, $mountPoint);
408  $subNode->setExpanded(true);
409  }
410  $subNode->setChildNodes($childNodes);
411  $nodeCollection->append($subNode);
412  }
413  foreach ($this->processCollectionHookObjects as $hookObject) {
415  $hookObject->postProcessGetTreeMounts($searchFilter, $nodeCollection);
416  }
417  return $nodeCollection;
418  }
419 
427  protected function getWhereClause($id, $searchFilter = '')
428  {
429  $where = $GLOBALS['BE_USER']->getPagePermsClause(1) . BackendUtility::deleteClause('pages') . BackendUtility::versioningPlaceholderClause('pages');
430  if (is_numeric($id) && $id >= 0) {
431  $where .= ' AND pid= ' . $GLOBALS['TYPO3_DB']->fullQuoteStr((int)$id, 'pages');
432  }
433 
434  $excludedDoktypes = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.excludeDoktypes');
435  if (!empty($excludedDoktypes)) {
436  $excludedDoktypes = $GLOBALS['TYPO3_DB']->fullQuoteArray(GeneralUtility::intExplode(',', $excludedDoktypes), 'pages');
437  $where .= ' AND doktype NOT IN (' . implode(',', $excludedDoktypes) . ')';
438  }
439 
440  if ($searchFilter !== '') {
441  if (is_numeric($searchFilter) && $searchFilter > 0) {
442  $searchWhere .= 'uid = ' . (int)$searchFilter . ' OR ';
443  }
444  $searchFilter = $GLOBALS['TYPO3_DB']->fullQuoteStr('%' . $searchFilter . '%', 'pages');
445  $useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle');
446  $useAlias = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.searchInAlias');
447 
448  $searchWhereAlias = '';
449  if ($useAlias) {
450  $searchWhereAlias = ' OR alias LIKE ' . $searchFilter;
451  }
452 
453  if ($useNavTitle) {
454  $searchWhere .= '(nav_title LIKE ' . $searchFilter .
455  ' OR (nav_title = "" AND title LIKE ' . $searchFilter . ')' . $searchWhereAlias . ')';
456  } else {
457  $searchWhere .= 'title LIKE ' . $searchFilter . $searchWhereAlias;
458  }
459 
460  $where .= ' AND (' . $searchWhere . ')';
461  }
462  return $where;
463  }
464 
472  protected function getSubpages($id, $searchFilter = '')
473  {
474  $where = $this->getWhereClause($id, $searchFilter);
475  return $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,t3ver_wsid', 'pages', $where, '', 'sorting', '', 'uid');
476  }
477 
484  protected function hasNodeSubPages($id)
485  {
486  $where = $this->getWhereClause($id);
487  $subpage = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid', 'pages', $where, '', 'sorting', '', 'uid');
488  $returnValue = true;
489  if (!$subpage['uid']) {
490  $returnValue = false;
491  }
492  return $returnValue;
493  }
494 }
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
getRecordWithWorkspaceOverlay($uid, $unsetMovePointers=false)
getNodes(\TYPO3\CMS\Backend\Tree\TreeNode $node)
static getNodeRecord($nodeId, $unsetMovePointers=true)
Definition: Commands.php:278
static BEgetRootLine($uid, $clause='', $workspaceOL=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
$uid
Definition: server.php:38
static getLiveVersionOfRecord($table, $uid, $fields=' *')
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static getRecordWSOL($table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
static deleteClause($table, $tableAlias='')