2 namespace TYPO3\CMS\Core\Tree\TableConfiguration
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Backend\Utility\BackendUtility
;
18 use TYPO3\CMS\Core\Imaging\Icon
;
19 use TYPO3\CMS\Core\Imaging\IconFactory
;
20 use TYPO3\CMS\Core\Utility\GeneralUtility
;
23 * TCA tree data provider
25 class DatabaseTreeDataProvider
extends AbstractTableConfigurationTreeDataProvider
27 const SIGNAL_PostProcessTreeData
= 'PostProcessTreeData';
28 const MODE_CHILDREN
= 1;
29 const MODE_PARENT
= 2;
34 protected $tableName = '';
39 protected $treeId = '';
44 protected $labelField = '';
49 protected $tableWhere = '';
54 protected $lookupMode = self
::MODE_CHILDREN
;
59 protected $lookupField = '';
64 protected $rootUid = 0;
69 protected $idCache = array();
72 * Stores TCA-Configuration of the LookUpField in tableName
76 protected $columnConfiguration;
79 * node sort values (the orderings from foreign_Table_where evaluation)
83 protected $nodeSortValues = array();
86 * @var array TCEforms compiled TSConfig array
88 protected $generatedTSConfig = array();
91 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
93 protected $signalSlotDispatcher;
96 * Sets the label field
98 * @param string $labelField
101 public function setLabelField($labelField)
103 $this->labelField
= $labelField;
107 * Gets the label field
111 public function getLabelField()
113 return $this->labelField
;
117 * Sets the table name
119 * @param string $tableName
122 public function setTableName($tableName)
124 $this->tableName
= $tableName;
128 * Gets the table name
132 public function getTableName()
134 return $this->tableName
;
138 * Sets the lookup field
140 * @param string $lookupField
143 public function setLookupField($lookupField)
145 $this->lookupField
= $lookupField;
149 * Gets the lookup field
153 public function getLookupField()
155 return $this->lookupField
;
159 * Sets the lookup mode
161 * @param int $lookupMode
164 public function setLookupMode($lookupMode)
166 $this->lookupMode
= $lookupMode;
170 * Gets the lookup mode
174 public function getLookupMode()
176 return $this->lookupMode
;
182 * @param \TYPO3\CMS\Backend\Tree\TreeNode $node
183 * @return \TYPO3\CMS\Backend\Tree\TreeNodeCollection
185 public function getNodes(\TYPO3\CMS\Backend\Tree\TreeNode
$node)
192 * @return \TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode
194 public function getRoot()
196 return $this->buildRepresentationForNode($this->treeData
);
202 * @param int $rootUid
205 public function setRootUid($rootUid)
207 $this->rootUid
= $rootUid;
215 public function getRootUid()
217 return $this->rootUid
;
221 * Sets the tableWhere clause
223 * @param string $tableWhere
226 public function setTableWhere($tableWhere)
228 $this->tableWhere
= $tableWhere;
232 * Gets the tableWhere clause
236 public function getTableWhere()
238 return $this->tableWhere
;
242 * Builds a complete node including childs
244 * @param \TYPO3\CMS\Backend\Tree\TreeNode $basicNode
245 * @param NULL|\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode $parent
247 * @return \TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode Node object
249 protected function buildRepresentationForNode(\TYPO3\CMS\Backend\Tree\TreeNode
$basicNode, DatabaseTreeNode
$parent = null, $level = 0)
251 /** @var $node \TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode */
252 $node = GeneralUtility
::makeInstance(\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeNode
::class);
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']));
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));
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
));
269 $node->setParentNode($parent);
270 if ($basicNode->hasChildNodes()) {
271 $node->setHasChildren(true);
272 /** @var $childNodes \TYPO3\CMS\Backend\Tree\SortedTreeNodeCollection */
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));
277 $node->setChildNodes($childNodes);
287 public function initializeTreeData()
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);
295 $this->treeData
= GeneralUtility
::makeInstance(\TYPO3\CMS\Backend\Tree\TreeNode
::class);
296 $this->loadTreeData();
297 $this->emitPostProcessTreeDataSignal();
301 * Loads the tree data (all possible children)
305 protected function loadTreeData()
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);
320 * @param \TYPO3\CMS\Backend\Tree\TreeNode $node
322 * @return NULL|\TYPO3\CMS\Backend\Tree\TreeNodeCollection
324 protected function getChildrenOf(\TYPO3\CMS\Backend\Tree\TreeNode
$node, $level)
327 if ($node->getId() !== 0) {
328 $nodeData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->tableName
, 'uid=' . $node->getId());
330 if ($nodeData == null) {
333 $this->getLookupField() => ''
337 $children = $this->getRelatedRecords($nodeData);
338 if (!empty($children)) {
339 /** @var $storage \TYPO3\CMS\Backend\Tree\TreeNodeCollection */
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);
350 $storage->append($node);
357 * Gets related records depending on TCA configuration
362 protected function getRelatedRecords(array $row)
364 if ($this->getLookupMode() == DatabaseTreeDataProvider
::MODE_PARENT
) {
365 $children = $this->getChildrenUidsFromParentRelation($row);
367 $children = $this->getChildrenUidsFromChildrenRelation($row);
369 $allowedArray = array();
370 foreach ($children as $child) {
371 if (!in_array($child, $this->idCache
) && in_array($child, $this->itemWhiteList
)) {
372 $allowedArray[] = $child;
375 $this->idCache
= array_merge($this->idCache
, $allowedArray);
376 return $allowedArray;
380 * Gets related records depending on TCA configuration
385 protected function getChildrenUidsFromParentRelation(array $row)
388 switch ((string)$this->columnConfiguration
['type']) {
392 if ($this->columnConfiguration
['MM']) {
393 /** @var $dbGroup \TYPO3\CMS\Core\Database\RelationHandler */
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);
402 $relatedUids = $this->listFieldQuery($this->getLookupField(), $uid);
406 $relatedUids = $this->listFieldQuery($this->getLookupField(), $uid);
412 * Gets related children records depending on TCA configuration
417 protected function getChildrenUidsFromChildrenRelation(array $row)
419 $relatedUids = array();
421 $value = $row[$this->getLookupField()];
422 switch ((string)$this->columnConfiguration
['type']) {
426 if ($this->columnConfiguration
['MM']) {
427 /** @var $dbGroup \TYPO3\CMS\Core\Database\RelationHandler */
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'];
437 $relatedUids = GeneralUtility
::intExplode(',', $value, true);
441 $relatedUids = GeneralUtility
::intExplode(',', $value, true);
447 * Queries the table for an field which might contain a list.
449 * @param string $fieldName the name of the field to be queried
450 * @param int $queryId the uid to search for
451 * @return int[] all uids found
453 protected function listFieldQuery($fieldName, $queryId)
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) = \'\'' : ''));
457 foreach ($records as $record) {
458 $uidArray[] = $record['uid'];
464 * Emits the post processing tree data signal.
468 protected function emitPostProcessTreeDataSignal()
470 $this->getSignalSlotDispatcher()->dispatch(\TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeDataProvider
::class,
471 self
::SIGNAL_PostProcessTreeData
,
472 array($this, $this->treeData
)
477 * Get the SignalSlot dispatcher
479 * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
481 protected function getSignalSlotDispatcher()
483 if (!isset($this->signalSlotDispatcher
)) {
484 $this->signalSlotDispatcher
= $this->getObjectManager()->get(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher
::class);
486 return $this->signalSlotDispatcher
;
490 * Get the ObjectManager
492 * @return \TYPO3\CMS\Extbase\Object\ObjectManager
494 protected function getObjectManager()
496 return GeneralUtility
::makeInstance(\TYPO3\CMS\Extbase\
Object\ObjectManager
::class);