83f142acba9ec7a588c50788c546fc31b05c465f
[Packages/TYPO3.CMS.git] / t3lib / tree / tca / class.t3lib_tree_tca_databasetreedataprovider.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Steffen Ritter <info@steffen-ritter.net>
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 * TCA tree data provider
30 *
31 * @author Steffen Ritter <info@steffen-ritter.net>
32 * @package TYPO3
33 * @subpackage t3lib_tree
34 */
35
36 class t3lib_tree_Tca_DatabaseTreeDataProvider extends t3lib_tree_Tca_AbstractTcaTreeDataProvider {
37
38 const MODE_CHILDREN = 1;
39 const MODE_PARENT = 2;
40
41 /**
42 * @var string
43 */
44 protected $tableName = '';
45
46 /**
47 * @var string
48 */
49 protected $treeId = '';
50
51 /**
52 * @var string
53 */
54 protected $labelField = '';
55
56 /**
57 * @var string
58 *
59 */
60 protected $tableWhere = '';
61
62 /**
63 * @var int
64 */
65 protected $lookupMode = t3lib_tree_tca_DatabaseTreeDataProvider::MODE_CHILDREN;
66
67 /**
68 * @var string
69 */
70 protected $lookupField = '';
71
72 /**
73 * @var int
74 */
75 protected $rootUid = 0;
76
77 /**
78 * @var array
79 */
80 protected $idCache = array();
81
82
83 /**
84 * Stores TCA-Configuration of the LookUpField in tableName
85 *
86 * @var array
87 */
88 protected $columnConfiguration;
89
90 /**
91 * node sort values (the orderings from foreign_Table_where evaluation)
92 *
93 * @var array
94 */
95 protected $nodeSortValues = array();
96
97 /**
98 * @var array TCEforms compiled TSConfig array
99 */
100 protected $generatedTSConfig = array();
101
102 /**
103 * Sets the label field
104 *
105 * @param string $labelField
106 * @return void
107 */
108 public function setLabelField($labelField) {
109 $this->labelField = $labelField;
110 }
111
112 /**
113 * Gets the label field
114 *
115 * @return string
116 */
117 public function getLabelField() {
118 return $this->labelField;
119 }
120
121 /**
122 * Sets the table name
123 *
124 * @param string $tableName
125 * @return void
126 */
127 public function setTableName($tableName) {
128 $this->tableName = $tableName;
129 }
130
131 /**
132 * Gets the table name
133 *
134 * @return string
135 */
136 public function getTableName() {
137 return $this->tableName;
138 }
139
140 /**
141 * Sets the lookup field
142 *
143 * @param string $lookupField
144 * @return void
145 */
146 public function setLookupField($lookupField) {
147 $this->lookupField = $lookupField;
148 }
149
150 /**
151 * Gets the lookup field
152 *
153 * @return string
154 */
155 public function getLookupField() {
156 return $this->lookupField;
157 }
158
159 /**
160 * Sets the lookup mode
161 *
162 * @param int $lookupMode
163 * @return void
164 */
165 public function setLookupMode($lookupMode) {
166 $this->lookupMode = $lookupMode;
167 }
168
169 /**
170 * Gets the lookup mode
171 *
172 * @return int
173 */
174 public function getLookupMode() {
175 return $this->lookupMode;
176 }
177
178
179 /**
180 * Gets the nodes
181 *
182 * @param t3lib_tree_Node $node
183 * @return t3lib_tree_NodeCollection
184 */
185 public function getNodes(t3lib_tree_Node $node) {
186
187 }
188
189 /**
190 * Gets the root node
191 *
192 * @return t3lib_tree_tca_DatabaseNode
193 */
194 public function getRoot() {
195 return $this->buildRepresentationForNode($this->treeData);
196 }
197
198 /**
199 * Sets the root uid
200 *
201 * @param $rootUid
202 * @return void
203 */
204 public function setRootUid($rootUid) {
205 $this->rootUid = $rootUid;
206 }
207
208 /**
209 * Gets the root uid
210 *
211 * @return int
212 */
213 public function getRootUid() {
214 return $this->rootUid;
215 }
216
217 /**
218 * Sets the tableWhere clause
219 *
220 * @param string $tableWhere
221 * @return void
222 */
223 public function setTableWhere(string $tableWhere) {
224 $this->tableWhere = $tableWhere;
225 }
226
227 /**
228 * Gets the tableWhere clause
229 *
230 * @return string
231 */
232 public function getTableWhere() {
233 return $this->tableWhere;
234 }
235
236 /**
237 * Builds a complete node including childs
238 *
239 * @param t3lib_tree_Node $basicNode
240 * @param null|t3lib_tree_tca_DatabaseNode $parent
241 * @param int $level
242 * @return A|object
243 */
244 protected function buildRepresentationForNode(t3lib_tree_Node $basicNode, t3lib_tree_tca_DatabaseNode $parent = NULL, $level = 0) {
245 $node = t3lib_div::makeInstance('t3lib_tree_tca_DatabaseNode');
246 $row = array();
247 if ($basicNode->getId() == 0) {
248 $node->setSelected(FALSE);
249 $node->setExpanded(TRUE);
250 $node->setLabel($GLOBALS['LANG']->sL($GLOBALS['TCA'][$this->tableName]['ctrl']['title']));
251 } else {
252 $row = t3lib_BEfunc::getRecordWSOL($this->tableName, $basicNode->getId(), '*', '', FALSE);
253 if ($this->getLabelField() !== '') {
254 $node->setLabel($row[$this->getLabelField()]);
255 } else {
256 $node->setLabel($basicNode->getId());
257 }
258 $node->setSelected(t3lib_div::inList($this->getSelectedList(), $basicNode->getId()));
259 $node->setExpanded($this->isExpanded($basicNode));
260 }
261 $node->setSelectable(!t3lib_div::inList($this->getNonSelectableLevelList(), $level));
262 $node->setSortValue($this->nodeSortValues[$node->getId()]);
263 $node->setIcon(t3lib_iconWorks::mapRecordTypeToSpriteIconClass($this->tableName, $row));
264 $node->setId($basicNode->getId());
265 $node->setParentNode($parent);
266 if ($basicNode->hasChildNodes()) {
267 $node->setHasChildren(TRUE);
268
269 $childNodes = t3lib_div::makeInstance('t3lib_tree_SortedNodeCollection');
270 foreach ($basicNode->getChildNodes() as $child) {
271 $childNodes->append($this->buildRepresentationForNode($child, $node, $level + 1));
272 }
273 $node->setChildNodes($childNodes);
274 }
275
276 return $node;
277 }
278
279 /**
280 * Init the tree data
281 *
282 * @return void
283 */
284 public function initializeTreeData() {
285 parent::initializeTreeData();
286 $this->nodeSortValues = array_flip($this->itemWhiteList);
287
288 $this->columnConfiguration = $GLOBALS['TCA'][$this->getTableName()]['columns'][$this->getLookupField()]['config'];
289 if (isset($this->columnConfiguration['foreign_table']) && $this->columnConfiguration['foreign_table'] != $this->getTableName()) {
290 throw new InvalidArgumentException(
291 'TCA Tree configuration is invalid: tree for different node-Tables is not implemented yet',
292 '1290944650'
293 );
294 }
295
296 $this->treeData = t3lib_div::makeInstance('t3lib_tree_Node');
297 $this->treeData->setId($this->getRootUid());
298 $this->treeData->setParentNode(NULL);
299 $childNodes = $this->getChildrenOf($this->treeData, 0);
300 if ($childNodes !== NULL) {
301 $this->treeData->setChildNodes($childNodes);
302 }
303 }
304
305 /**
306 * Gets node children
307 *
308 * @param t3lib_tree_Node $node
309 * @param $level
310 * @return A|null|object
311 */
312 protected function getChildrenOf(t3lib_tree_Node $node, $level) {
313 $nodeData = NULL;
314 if ($node->getId() !== 0) {
315 $nodeData = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
316 '*',
317 $this->tableName,
318 'uid=' . $node->getId()
319 );
320 }
321 if ($nodeData == NULL) {
322 $nodeData = array(
323 'uid' => 0,
324 $this->getLookupField() => '',
325 );
326 }
327 $storage = NULL;
328 $children = $this->getRelatedRecords($nodeData);
329 if (count($children)) {
330 $storage = t3lib_div::makeInstance('t3lib_tree_NodeCollection');
331 foreach ($children as $child) {
332 $node = t3lib_div::makeInstance('t3lib_tree_Node');
333 ;
334 $node->setId($child);
335 if ($level <= $this->levelMaximum) {
336 $children = $this->getChildrenOf($node, $level + 1);
337 if ($children !== NULL) {
338 $node->setChildNodes($children);
339 }
340 }
341 $storage->append($node);
342 }
343 }
344
345 return $storage;
346 }
347
348 /**
349 * Gets related records depending on TCA configuration
350 *
351 * @param $row
352 * @return array
353 */
354 protected function getRelatedRecords(array $row) {
355 if ($this->getLookupMode() == t3lib_tree_tca_DatabaseTreeDataProvider::MODE_PARENT) {
356 $children = $this->getChildrenUidsFromParentRelation($row);
357 } else {
358 $children = $this->getChildrenUidsFromChildrenRelation($row);
359 }
360
361 $allowedArray = array();
362 foreach ($children as $child) {
363 if (!in_array($child, $this->idCache) && in_array($child, $this->itemWhiteList)) {
364 $allowedArray[] = $child;
365 }
366 }
367
368 $this->idCache = array_merge($this->idCache, $allowedArray);
369
370 return $allowedArray;
371 }
372
373 /**
374 * Gets related records depending on TCA configuration
375 *
376 * @param $row
377 * @return array
378 */
379 protected function getChildrenUidsFromParentRelation(array $row) {
380 $relatedUids = array();
381 $uid = $row['uid'];
382
383 switch ((string) $this->columnConfiguration['type']) {
384 case 'inline':
385 case 'select':
386 if ($this->columnConfiguration['MM']) {
387 $dbGroup = t3lib_div::makeInstance('t3lib_loadDBGroup');
388 // dummy field for setting "look from other site"
389 $this->columnConfiguration['MM_oppositeField'] = 'children';
390
391 $dbGroup->start(
392 $row[$this->getLookupField()],
393 $this->getTableName(),
394 $this->columnConfiguration['MM'],
395 $uid,
396 $this->getTableName(),
397 $this->columnConfiguration
398 );
399
400 $relatedUids = $dbGroup->tableArray[$this->getTableName()];
401 } elseif ($this->columnConfiguration['foreign_field']) {
402 $relatedUids = $this->listFieldQuery($this->columnConfiguration['foreign_field'], $uid);
403 } else {
404 $relatedUids = $this->listFieldQuery($this->getLookupField(), $uid);
405 }
406 break;
407 default:
408 $relatedUids = $this->listFieldQuery($this->getLookupField(), $uid);
409 }
410
411 return $relatedUids;
412 }
413
414 /**
415 * Gets related children records depending on TCA configuration
416 *
417 * @param $row
418 * @return array
419 */
420 protected function getChildrenUidsFromChildrenRelation(array $row) {
421 $relatedUids = array();
422 $uid = $row['uid'];
423 $value = $row[$this->getLookupField()];
424
425 switch ((string) $this->columnConfiguration['type']) {
426 case 'inline':
427 case 'select':
428 if ($this->columnConfiguration['MM']) {
429 $dbGroup = t3lib_div::makeInstance('t3lib_loadDBGroup');
430 $dbGroup->start(
431 $value,
432 $this->getTableName(),
433 $this->columnConfiguration['MM'],
434 $uid,
435 $this->getTableName(),
436 $this->columnConfiguration
437 );
438
439 $relatedUids = $dbGroup->tableArray[$this->getTableName()];
440 } elseif ($this->columnConfiguration['foreign_field']) {
441 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
442 'uid',
443 $this->getTableName(),
444 $this->columnConfiguration['foreign_field'] . '=' . intval($uid)
445 );
446 foreach ($records as $record) {
447 $relatedUids[] = $record['uid'];
448 }
449 } else {
450 $relatedUids = t3lib_div::intExplode(',', $value, TRUE);
451 }
452 break;
453 default:
454 $relatedUids = t3lib_div::intExplode(',', $value, TRUE);
455 }
456
457 return $relatedUids;
458 }
459
460 /**
461 * Queries the table for an field which might contain a list.
462 *
463 * @param string $fieldName the name of the field to be queried
464 * @param int $queryId the uid to search for
465 *
466 * @return int[] all uids found
467 */
468 protected function listFieldQuery($fieldName, $queryId) {
469 $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
470 'uid',
471 $this->getTableName(),
472 $GLOBALS['TYPO3_DB']->listQuery($fieldName, intval($queryId), $this->getTableName())
473 . (intval($queryId) == 0 ? (' OR ' . $fieldName . ' = \'\'') : '')
474 );
475 $uidArray = array();
476 foreach ($records as $record) {
477 $uidArray[] = $record['uid'];
478 }
479 return $uidArray;
480 }
481 }
482
483 ?>