TYPO3 CMS  TYPO3_7-6
DatabaseTreeDataProvider.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 
21 
26 {
27  const SIGNAL_PostProcessTreeData = 'PostProcessTreeData';
28  const MODE_CHILDREN = 1;
29  const MODE_PARENT = 2;
30 
34  protected $tableName = '';
35 
39  protected $treeId = '';
40 
44  protected $labelField = '';
45 
49  protected $tableWhere = '';
50 
54  protected $lookupMode = self::MODE_CHILDREN;
55 
59  protected $lookupField = '';
60 
64  protected $rootUid = 0;
65 
69  protected $idCache = [];
70 
77 
83  protected $nodeSortValues = [];
84 
88  protected $generatedTSConfig = [];
89 
94 
101  public function setLabelField($labelField)
102  {
103  $this->labelField = $labelField;
104  }
105 
111  public function getLabelField()
112  {
113  return $this->labelField;
114  }
115 
122  public function setTableName($tableName)
123  {
124  $this->tableName = $tableName;
125  }
126 
132  public function getTableName()
133  {
134  return $this->tableName;
135  }
136 
143  public function setLookupField($lookupField)
144  {
145  $this->lookupField = $lookupField;
146  }
147 
153  public function getLookupField()
154  {
155  return $this->lookupField;
156  }
157 
164  public function setLookupMode($lookupMode)
165  {
166  $this->lookupMode = $lookupMode;
167  }
168 
174  public function getLookupMode()
175  {
176  return $this->lookupMode;
177  }
178 
185  public function getNodes(\TYPO3\CMS\Backend\Tree\TreeNode $node)
186  {
187  }
188 
194  public function getRoot()
195  {
196  return $this->buildRepresentationForNode($this->treeData);
197  }
198 
205  public function setRootUid($rootUid)
206  {
207  $this->rootUid = $rootUid;
208  }
209 
215  public function getRootUid()
216  {
217  return $this->rootUid;
218  }
219 
226  public function setTableWhere($tableWhere)
227  {
228  $this->tableWhere = $tableWhere;
229  }
230 
236  public function getTableWhere()
237  {
238  return $this->tableWhere;
239  }
240 
249  protected function buildRepresentationForNode(\TYPO3\CMS\Backend\Tree\TreeNode $basicNode, DatabaseTreeNode $parent = null, $level = 0)
250  {
252  $node = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode::class);
253  $row = [];
254  if ($basicNode->getId() == 0) {
255  $node->setSelected(false);
256  $node->setExpanded(true);
257  $node->setLabel($GLOBALS['LANG']->sL($GLOBALS['TCA'][$this->tableName]['ctrl']['title']));
258  } else {
259  $row = BackendUtility::getRecordWSOL($this->tableName, $basicNode->getId(), '*', '', false);
260  $node->setLabel(BackendUtility::getRecordTitle($this->tableName, $row) ?: $basicNode->getId());
261  $node->setSelected(GeneralUtility::inList($this->getSelectedList(), $basicNode->getId()));
262  $node->setExpanded($this->isExpanded($basicNode));
263  }
264  $node->setId($basicNode->getId());
265  $node->setSelectable(!GeneralUtility::inList($this->getNonSelectableLevelList(), $level) && !in_array($basicNode->getId(), $this->getItemUnselectableList()));
266  $node->setSortValue($this->nodeSortValues[$basicNode->getId()]);
267  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
268  $node->setIcon($iconFactory->getIconForRecord($this->tableName, $row, Icon::SIZE_SMALL)->render());
269  $node->setParentNode($parent);
270  if ($basicNode->hasChildNodes()) {
271  $node->setHasChildren(true);
273  $childNodes = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\SortedTreeNodeCollection::class);
274  foreach ($basicNode->getChildNodes() as $child) {
275  $childNodes->append($this->buildRepresentationForNode($child, $node, $level + 1));
276  }
277  $node->setChildNodes($childNodes);
278  }
279  return $node;
280  }
281 
287  public function initializeTreeData()
288  {
289  parent::initializeTreeData();
290  $this->nodeSortValues = array_flip($this->itemWhiteList);
291  $this->columnConfiguration = $GLOBALS['TCA'][$this->getTableName()]['columns'][$this->getLookupField()]['config'];
292  if (isset($this->columnConfiguration['foreign_table']) && $this->columnConfiguration['foreign_table'] != $this->getTableName()) {
293  throw new \InvalidArgumentException('TCA Tree configuration is invalid: tree for different node-Tables is not implemented yet', 1290944650);
294  }
295  $this->treeData = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\TreeNode::class);
296  $this->loadTreeData();
298  }
299 
305  protected function loadTreeData()
306  {
307  $this->treeData->setId($this->getRootUid());
308  $this->treeData->setParentNode(null);
309  if ($this->levelMaximum >= 1) {
310  $childNodes = $this->getChildrenOf($this->treeData, 1);
311  if ($childNodes !== null) {
312  $this->treeData->setChildNodes($childNodes);
313  }
314  }
315  }
316 
324  protected function getChildrenOf(\TYPO3\CMS\Backend\Tree\TreeNode $node, $level)
325  {
326  $nodeData = null;
327  if ($node->getId() !== 0) {
328  $nodeData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->tableName, 'uid=' . $node->getId());
329  }
330  if ($nodeData == null) {
331  $nodeData = [
332  'uid' => 0,
333  $this->getLookupField() => ''
334  ];
335  }
336  $storage = null;
337  $children = $this->getRelatedRecords($nodeData);
338  if (!empty($children)) {
340  $storage = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\TreeNodeCollection::class);
341  foreach ($children as $child) {
342  $node = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\TreeNode::class);
343  $node->setId($child);
344  if ($level < $this->levelMaximum) {
345  $children = $this->getChildrenOf($node, $level + 1);
346  if ($children !== null) {
347  $node->setChildNodes($children);
348  }
349  }
350  $storage->append($node);
351  }
352  }
353  return $storage;
354  }
355 
362  protected function getRelatedRecords(array $row)
363  {
364  if ($this->getLookupMode() == self::MODE_PARENT) {
365  $children = $this->getChildrenUidsFromParentRelation($row);
366  } else {
367  $children = $this->getChildrenUidsFromChildrenRelation($row);
368  }
369  $allowedArray = [];
370  foreach ($children as $child) {
371  if (!in_array($child, $this->idCache) && in_array($child, $this->itemWhiteList)) {
372  $allowedArray[] = $child;
373  }
374  }
375  $this->idCache = array_merge($this->idCache, $allowedArray);
376  return $allowedArray;
377  }
378 
385  protected function getChildrenUidsFromParentRelation(array $row)
386  {
387  $uid = $row['uid'];
388  switch ((string)$this->columnConfiguration['type']) {
389  case 'inline':
390 
391  case 'select':
392  if ($this->columnConfiguration['MM']) {
394  $dbGroup = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\RelationHandler::class);
395  // Dummy field for setting "look from other site"
396  $this->columnConfiguration['MM_oppositeField'] = 'children';
397  $dbGroup->start($row[$this->getLookupField()], $this->getTableName(), $this->columnConfiguration['MM'], $uid, $this->getTableName(), $this->columnConfiguration);
398  $relatedUids = $dbGroup->tableArray[$this->getTableName()];
399  } elseif ($this->columnConfiguration['foreign_field']) {
400  $relatedUids = $this->listFieldQuery($this->columnConfiguration['foreign_field'], $uid);
401  } else {
402  $relatedUids = $this->listFieldQuery($this->getLookupField(), $uid);
403  }
404  break;
405  default:
406  $relatedUids = $this->listFieldQuery($this->getLookupField(), $uid);
407  }
408  return $relatedUids;
409  }
410 
417  protected function getChildrenUidsFromChildrenRelation(array $row)
418  {
419  $relatedUids = [];
420  $uid = $row['uid'];
421  $value = $row[$this->getLookupField()];
422  switch ((string)$this->columnConfiguration['type']) {
423  case 'inline':
424 
425  case 'select':
426  if ($this->columnConfiguration['MM']) {
428  $dbGroup = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\RelationHandler::class);
429  $dbGroup->start($value, $this->getTableName(), $this->columnConfiguration['MM'], $uid, $this->getTableName(), $this->columnConfiguration);
430  $relatedUids = $dbGroup->tableArray[$this->getTableName()];
431  } elseif ($this->columnConfiguration['foreign_field']) {
432  $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', $this->getTableName(), $this->columnConfiguration['foreign_field'] . '=' . (int)$uid);
433  foreach ($records as $record) {
434  $relatedUids[] = $record['uid'];
435  }
436  } else {
437  $relatedUids = GeneralUtility::intExplode(',', $value, true);
438  }
439  break;
440  default:
441  $relatedUids = GeneralUtility::intExplode(',', $value, true);
442  }
443  return $relatedUids;
444  }
445 
453  protected function listFieldQuery($fieldName, $queryId)
454  {
455  $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', $this->getTableName(), $GLOBALS['TYPO3_DB']->listQuery($fieldName, (int)$queryId, $this->getTableName()) . ((int)$queryId === 0 ? ' OR CAST(' . $fieldName . ' AS CHAR) = \'\'' : ''));
456  $uidArray = [];
457  if (!empty($records)) {
458  foreach ($records as $record) {
459  $uidArray[] = $record['uid'];
460  }
461  }
462  return $uidArray;
463  }
464 
470  protected function emitPostProcessTreeDataSignal()
471  {
472  $this->getSignalSlotDispatcher()->dispatch(\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeDataProvider::class,
473  self::SIGNAL_PostProcessTreeData,
474  [$this, $this->treeData]
475  );
477  }
478 
487  {
488  $deprecatedSlots = $this->getSignalSlotDispatcher()->getSlots(
489  'TYPO3\\CMS\\Core\\Tree\\TableConfiguration\\TableConfiguration\\DatabaseTreeDataProvider',
490  self::SIGNAL_PostProcessTreeData
491  );
492  if (!empty($deprecatedSlots)) {
493  foreach ($deprecatedSlots as $slotInformation) {
494  $slotClassNameOrObject = $slotInformation['object'] ? get_class($slotInformation['object']) : $slotInformation['class'];
496  'Signal "TYPO3\\CMS\\Core\\Tree\\TableConfiguration\\TableConfiguration\\DatabaseTreeDataProvider" ' .
497  'is deprecated but used by "' . $slotClassNameOrObject . '". ' .
498  'Please update signal name to "' . __CLASS__ . '".'
499  );
500  }
501  $this->getSignalSlotDispatcher()->dispatch(
502  'TYPO3\\CMS\\Core\\Tree\\TableConfiguration\\TableConfiguration\\DatabaseTreeDataProvider',
503  self::SIGNAL_PostProcessTreeData,
504  [$this, $this->treeData]
505  );
506  }
507  }
508 
514  protected function getSignalSlotDispatcher()
515  {
516  if (!isset($this->signalSlotDispatcher)) {
517  $this->signalSlotDispatcher = $this->getObjectManager()->get(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
518  }
520  }
521 
527  protected function getObjectManager()
528  {
529  return GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
530  }
531 }
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
$uid
Definition: server.php:38
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)