Added feature #16228: [Feature] TCA tree (Thanks to Steffen Ritter) - part 4 (TCA)
authorSteffen Kamper <info@sk-typo3.de>
Wed, 3 Nov 2010 15:53:56 +0000 (15:53 +0000)
committerSteffen Kamper <info@sk-typo3.de>
Wed, 3 Nov 2010 15:53:56 +0000 (15:53 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@9253 709f56b5-9817-0410-a4d7-c38de5d9e867

t3lib/class.t3lib_tceforms.php
t3lib/core_autoload.php
t3lib/tceforms/class.t3lib_tceforms_tree.php [new file with mode: 0644]
t3lib/tree/tca/class.t3lib_tree_tca_abstracttcatreedataprovider.php [new file with mode: 0644]
t3lib/tree/tca/class.t3lib_tree_tca_databasenode.php [new file with mode: 0644]
t3lib/tree/tca/class.t3lib_tree_tca_databasetreedataprovider.php [new file with mode: 0644]
t3lib/tree/tca/class.t3lib_tree_tca_dataproviderfactory.php [new file with mode: 0644]
t3lib/tree/tca/class.t3lib_tree_tca_extjsarrayrenderer.php [new file with mode: 0644]
t3lib/tree/tca/class.t3lib_tree_tca_tcatree.php [new file with mode: 0644]

index 558cd98..747f589 100644 (file)
@@ -1563,12 +1563,15 @@ class t3lib_TCEforms    {
                $maxitems = intval($config['maxitems']);
 
                        // If a SINGLE selector box...
-               if ($maxitems<=1)       {
+               if ($maxitems<=1 && $config['renderMode'] !== 'tree') {
                        $item = $this->getSingleField_typeSelect_single($table,$field,$row,$PA,$config,$selItems,$nMV_label);
                } elseif (!strcmp($config['renderMode'],'checkbox'))    {       // Checkbox renderMode
                        $item = $this->getSingleField_typeSelect_checkbox($table,$field,$row,$PA,$config,$selItems,$nMV_label);
                } elseif (!strcmp($config['renderMode'],'singlebox'))   {       // Single selector box renderMode
                        $item = $this->getSingleField_typeSelect_singlebox($table,$field,$row,$PA,$config,$selItems,$nMV_label);
+               } elseif (!strcmp($config['renderMode'],'tree')) { // Tree renderMode
+                       $treeClass = t3lib_div::makeInstance('t3lib_TCEforms_Tree');
+                       $item = $treeClass->renderField($table, $field, $row, $PA, $this);
                } else {        // Traditional multiple selector box:
                        $item = $this->getSingleField_typeSelect_multiple($table,$field,$row,$PA,$config,$selItems,$nMV_label);
                }
@@ -6435,4 +6438,4 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_tceforms.php']);
 }
 
-?>
\ No newline at end of file
+?>
index 9b3165e..4ee4550 100644 (file)
@@ -158,12 +158,20 @@ $t3libClasses = array(
        't3lib_tree_labeleditable' => PATH_t3lib . 'interfaces/tree/interface.t3lib_tree_labeleditable.php',
        't3lib_tree_renderer_abstract' => PATH_t3lib . 'tree/renderer/class.t3lib_tree_renderer_abstract.php',
        't3lib_tree_renderer_unorderedlist' => PATH_t3lib . 'tree/renderer/class.t3lib_tree_renderer_unorderedlist.php',
+       't3lib_tree_renderer_extjsjson' => PATH_t3lib . 'tree/renderer/class.t3lib_tree_renderer_extjsjson.php',
        't3lib_contextmenu_abstractcontextmenu' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_abstractcontextmenu.php',
        't3lib_contextmenu_abstractdataprovider' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_abstractdataprovider.php',
        't3lib_contextmenu_action' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_action.php',
        't3lib_contextmenu_actioncollection' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_actioncollection.php',
        't3lib_contextmenu_renderer_abstract' => PATH_t3lib . 'contextmenu/renderer/class.t3lib_contextmenu_renderer_abstract.php',
        't3lib_contextmenu_extdirect_contextmenu' => PATH_t3lib . 'contextmenu/extdirect/class.t3lib_contextmenu_extdirect_contextmenu.php',
+       't3lib_tceforms_tree' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_tree.php',
+       't3lib_tree_tca_abstracttcatreedataprovider' => PATH_t3lib . 'tree/tca/class.t3lib_tree_tca_abstracttcatreedataprovider.php',
+       't3lib_tree_tca_extjsarrayrenderer' => PATH_t3lib . 'tree/tca/class.t3lib_tree_tca_extjsarrayrenderer.php',
+       't3lib_tree_tca_databasenode' => PATH_t3lib . 'tree/tca/class.t3lib_tree_tca_databasenode.php',
+       't3lib_tree_tca_databasetreedataprovider' => PATH_t3lib . 'tree/tca/class.t3lib_tree_tca_databasetreedataprovider.php',
+       't3lib_tree_tca_dataproviderfactory' => PATH_t3lib . 'tree/tca/class.t3lib_tree_tca_dataproviderfactory.php',
+       't3lib_tree_tca_tcatree' => PATH_t3lib . 'tree/tca/class.t3lib_tree_tca_tcatree.php',
 );
 
 $tslibClasses = require(PATH_typo3 . 'sysext/cms/ext_autoload.php');
diff --git a/t3lib/tceforms/class.t3lib_tceforms_tree.php b/t3lib/tceforms/class.t3lib_tceforms_tree.php
new file mode 100644 (file)
index 0000000..1e3b130
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+*  (c) 2010 Steffen Kamper <steffen@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * TCEforms wizard for rendering an AJAX selector for records
+ *
+ * $Id: class.t3lib_tceforms_suggest.php 7905 2010-06-13 14:42:33Z ohader $
+ *
+ * @author Steffen Ritter <info@steffen-ritter.net>
+ * @author Steffen Kamper <steffen@typo3.org>
+ */
+
+class t3lib_TCEforms_Tree {
+
+       /**
+        * @param string The table name of the record
+        * @param string The field name which this element is supposed to edit
+        * @param array The record data array where the value(s) for the field can be found
+        * @param array An array with additional configuration options.
+        * @return string The HTML code for the TCEform field
+        */
+       public function renderField($table, $field, $row, &$PA, &$tceForms) {
+               $valueArray = explode(',', $row[$field]);
+               $selectedNodes = array();
+               if (count($valueArray)) {
+                       foreach ($valueArray as $selectedValue) {
+                               $temp = explode('|', $selectedValue);
+                               $selectedNodes[] = $temp[0];
+                       }
+               }
+
+               $treeDataProvider = t3lib_tree_Tca_DataProviderFactory::getDataProvider(
+                       $GLOBALS['TCA'][$table]['columns'][$field]['config'],
+                       $table,
+                       $field,
+                       $row
+               );
+               $treeDataProvider->setSelectedList(implode(',', $selectedNodes));
+               $treeDataProvider->initializeTreeData();
+
+               $treeRenderer = t3lib_div::makeInstance('t3lib_tree_Tca_ExtJsArrayRenderer');
+               $tree = t3lib_div::makeInstance('t3lib_tree_Tca_TcaTree');
+               $tree->setDataProvider($treeDataProvider);
+               $tree->setNodeRenderer($treeRenderer);
+
+               $treeData = $tree->render();
+
+               $itemArray = array();
+               if (is_array($PA['fieldConf']['config']['items'])) {
+                       foreach ($PA['fieldConf']['config']['items'] as $additionalItem) {
+                               if ($additionalItem[1] !== '--div--') {
+                                       $item = new stdClass();
+                                       $item->uid = $additionalItem[1];
+                                       $item->text = $GLOBALS['LANG']->sL($additionalItem[0]);
+                                       $item->selectable = true;
+                                       $item->leaf = true;
+                                       $item->checked = in_array($additionalItem[1], $selectedNodes);
+                                       if (file_exists(PATH_typo3 . $additionalItem[3])) {
+                                               $item->icon = $additionalItem[3];
+                                       } elseif (strlen(trim($additionalItem[3]))) {
+                                               $item->iconCls= t3lib_iconWorks::getSpriteIconClasses($additionalItem[3]);
+                                       }
+
+                                       $itemArray[] = $item;
+                               }
+                       }
+               }
+               $itemArray[] = $treeData;
+               $treeData = json_encode($itemArray);
+
+               $id = md5($PA['itemFormElName']);
+
+               if (isset($PA['fieldConf']['config']['size']) && intval($PA['fieldConf']['config']['size']) > 0 ) {
+                       $height = intval($PA['fieldConf']['config']['size']) * 20;
+               } else {
+                       $height = 280;
+               }
+               if (isset($PA['fieldConf']['config']['autoSizeMax']) && intval($PA['fieldConf']['config']['autoSizeMax']) > 0 ) {
+                       $autoSizeMax = intval($PA['fieldConf']['config']['autoSizeMax']) * 20;
+               }
+
+
+               $header = FALSE;
+               $expanded = FALSE;
+               $appearance = $PA['fieldConf']['config']['treeConfig']['appearance'];
+               if (is_array($appearance)) {
+                       $header = $appearance['showHeader'] ? TRUE : FALSE;
+                       $expanded = ($appearance['expandAll'] === TRUE);
+               }
+
+               $onChange = '';
+               if ($PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged']) {
+                       $onChange = substr($PA['fieldChangeFunc']['TBE_EDITOR_fieldChanged'], 0, -1);
+               }
+
+               /** @var $pageRenderer t3lib_PageRenderer */
+               $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
+               $pageRenderer->loadExtJs();
+               $pageRenderer->addJsFile('../t3lib/js/extjs/tree/tree.js');
+               $pageRenderer->addExtOnReadyCode('
+                       TYPO3.Components.Tree.StandardTreeItemData["' . $id . '"] = ' . $treeData . ';
+                       var tree' . $id . ' = new TYPO3.Components.Tree.StandardTree({
+                               checkChangeHandler: TYPO3.Components.Tree.TcaCheckChangeHandler,
+                               id: "' . $id . '",
+                               showHeader: ' . intval($header) . ',
+                               onChange: "' . $onChange . '",
+                               tcaMaxItems: ' . ($PA['fieldConf']['config']['maxitems'] ? intval($PA['fieldConf']['config']['maxitems']) : 99999) . ',
+                               tcaExclusiveKeys: "' . (
+                                       $PA['fieldConf']['config']['exclusiveKeys']
+                                               ? $PA['fieldConf']['config']['exclusiveKeys'] : '') . '",
+                               ucId: "' . md5($table . '|' . $field ) . '",
+                               selModel: TYPO3.Components.Tree.EmptySelectionModel
+                       });
+                       tree' . $id . '.' . ($autoSizeMax
+                                       ? 'bodyStyle = "max-height: ' . $autoSizeMax . 'px;"'
+                                       : 'height = ' . $height
+                               ) . ';
+                       tree' . $id . '.render("tree_' . $id . '");' .
+                       ($expanded ? 'tree' . $id . '.expandAll();' : '') . '
+               ');
+
+               $formField = '
+                       <div class="typo3-tceforms-tree">
+                               <input type="hidden" name="' . $PA['itemFormElName'] . '" id="treeinput' . $id . '" value="' . $row[$field] . '" />
+                       </div>
+                       <div id="tree_' . $id . '">
+
+                       </div>';
+
+               return $formField;
+       }
+}
+
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_tree.php']) {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['classes/t3lib/tceforms/class.t3lib_tceforms_tree.php']);
+}
+
+?>
diff --git a/t3lib/tree/tca/class.t3lib_tree_tca_abstracttcatreedataprovider.php b/t3lib/tree/tca/class.t3lib_tree_tca_abstracttcatreedataprovider.php
new file mode 100644 (file)
index 0000000..c682b2c
--- /dev/null
@@ -0,0 +1,201 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * An abstract TCA tree data provider
+ *
+ * @author Steffen Ritter <info@steffen-ritter.net>
+ * @package TYPO3
+ * @subpackage t3lib_tree
+ */
+abstract class t3lib_tree_Tca_AbstractTcaTreeDataProvider extends t3lib_tree_AbstractDataProvider {
+       /**
+        * @var boolean
+        */
+       protected $expandAll = FALSE;
+
+       /**
+        * @var int
+        */
+       protected $levelMaximum = 2;
+
+       /**
+        * @var t3lib_tree_AbstractNode
+        */
+       protected $treeData = NULL;
+
+       /**
+        * @var string
+        */
+       protected $nonSelectableLevelList = '0';
+
+       /**
+        * @var string
+        */
+       protected $expandedList = '';
+
+       /**
+        * @var string
+        */
+       protected $selectedList = '';
+
+       /**
+        * Sets the id of the tree
+        *
+        * @param string $treeId
+        * @return void
+        */
+       public function setTreeId($treeId) {
+               $this->treeId = $treeId;
+       }
+
+       /**
+        * Gets the id of the tree
+        * @return string
+        */
+       public function getTreeId() {
+               return $this->treeId;
+       }
+
+
+       /**
+        * Sets the expandAll
+        *
+        * @param bool $expandAll
+        * @return void
+        */
+       public function setExpandAll($expandAll) {
+               $this->expandAll = $expandAll;
+       }
+
+       /**
+        * Gets the expamdAll
+        *
+        * @return bool
+        */
+       public function getExpandAll() {
+               return $this->expandAll;
+       }
+
+       /**
+        * Sets the levelMaximum
+        *
+        * @param int $levelMaximum
+        * @return void
+        */
+       public function setLevelMaximum($levelMaximum) {
+               $this->levelMaximum = $levelMaximum;
+       }
+
+       /**
+        * Gets the levelMaximum
+        *
+        * @return int
+        */
+       public function getLevelMaximum() {
+               return $this->levelMaximum;
+       }
+
+       /**
+        * Gets the expanded state of a given node
+        *
+        * @param t3lib_tree_AbstractNode $node
+        * @return bool
+        */
+       protected function isExpanded(t3lib_tree_Node $node) {
+               return $this->getExpandAll() || t3lib_div::inList($this->expandedList, $node->getId());
+       }
+
+
+       /**
+        * Sets the list for expanded nodes
+        *
+        * @param string $expandedList
+        * @return void
+        */
+       public function setExpandedList($expandedList) {
+               $this->expandedList = $expandedList;
+       }
+
+       /**
+        * Gets the list for expanded nodes
+        *
+        * @return string
+        */
+       public function getExpandedList() {
+               return $this->expandedList;
+       }
+
+       /**
+        * Read the list for expanded nodes from user settings
+        *
+        * @return void
+        */
+       public function initializeTreeData() {
+               $this->expandedList = $GLOBALS['BE_USER']->uc['tcaTrees'][$this->treeId];
+       }
+
+       /**
+        * Sets the list for selected nodes
+        *
+        * @param  $selectedList
+        * @return void
+        */
+       public function setSelectedList($selectedList) {
+               $this->selectedList = $selectedList;
+       }
+
+       /**
+        * Gets the list for selected nodes
+        *
+        * @return string
+        */
+       public function getSelectedList() {
+               return $this->selectedList;
+       }
+
+       /**
+        * Sets the list for non selectabal tree levels
+        *
+        * @param  $nonSelectableLevelList
+        * @return void
+        */
+       public function setNonSelectableLevelList($nonSelectableLevelList) {
+               $this->nonSelectableLevelList = $nonSelectableLevelList;
+       }
+
+       /**
+        * Gets the list for non selectabal tree levels
+        *
+        * @return string
+        */
+       public function getNonSelectableLevelList() {
+               return $this->nonSelectableLevelList;
+       }
+}
+
+?>
diff --git a/t3lib/tree/tca/class.t3lib_tree_tca_databasenode.php b/t3lib/tree/tca/class.t3lib_tree_tca_databasenode.php
new file mode 100644 (file)
index 0000000..03a85a5
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Represents a node in a TCA database setup
+ *
+ * @author Steffen Ritter <info@steffen-ritter.net>
+ * @package TYPO3
+ * @subpackage t3lib_tree
+ */
+
+class t3lib_tree_Tca_DatabaseNode extends t3lib_tree_RepresentationNode {
+
+       /**
+        * @var boolean
+        */
+       protected $selectable;
+
+       /**
+        * @var boolean
+        */
+       protected $selected = FALSE;
+
+       /**
+        * @var boolean
+        */
+       protected $expanded = TRUE;
+
+       /**
+        * @var boolean
+        */
+       protected $hasChildren = FALSE;
+
+       /**
+        * @var mixed
+        */
+       private $sortValue;
+
+       /**
+        * Sets the expand state
+        *
+        * @param  $expanded
+        * @return void
+        */
+       public function setExpanded($expanded) {
+               $this->expanded = $expanded;
+       }
+
+       /**
+        * Gets the expand state
+        *
+        * @return bool
+        */
+       public function getExpanded() {
+               return $this->expanded;
+       }
+
+       /**
+        * Sets the selectable property
+        *
+        * @param  $selectable
+        * @return void
+        */
+       public function setSelectable($selectable) {
+               $this->selectable = $selectable;
+       }
+
+       /**
+        * Gets the selectable property
+        *
+        * @return bool
+        */
+       public function getSelectable() {
+               return $this->selectable;
+       }
+
+       /**
+        * Sets the select state
+        *
+        * @param  $selected
+        * @return void
+        */
+       public function setSelected($selected) {
+               $this->selected = $selected;
+       }
+
+       /**
+        * Gets the select state
+        *
+        * @return bool
+        */
+       public function getSelected() {
+               return $this->selected;
+       }
+
+       /**
+        * Gets the hasChildren property
+        *
+        * @return bool
+        */
+       public function hasChildren() {
+               return $this->hasChildren;
+       }
+
+       /**
+        * Sets the hasChildren property
+        *
+        * @param  $value
+        * @return void
+        */
+       public function setHasChildren($value) {
+               $this->hasChildren = (boolean)$value;
+       }
+
+       /**
+        * Compares with another nide, used for sorting
+        *
+        * @param  $other node object
+        * @return int
+        */
+       public function compareTo($other) {
+               if ($this->sortValue > $other->sortValue) {
+                       return 1;
+               } elseif ($this->sortValue < $other->sortValue) {
+                       return -1;
+               } else {
+                       return 0;
+               }
+       }
+
+       /**
+        * Gets the sort value
+        *
+        * @return mixed
+        */
+       public function getSortValue() {
+               return $this->sortValue;
+       }
+
+       /**
+        * Sets the sort value
+        *
+        * @param mixed $sortValue
+        * @return void
+        */
+       public function setSortValue(mixed $sortValue) {
+               $this->sortValue = $sortValue;
+       }
+
+}
+
+?>
diff --git a/t3lib/tree/tca/class.t3lib_tree_tca_databasetreedataprovider.php b/t3lib/tree/tca/class.t3lib_tree_tca_databasetreedataprovider.php
new file mode 100644 (file)
index 0000000..23d54b7
--- /dev/null
@@ -0,0 +1,358 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * TCA tree data provider
+ *
+ * @author Steffen Ritter <info@steffen-ritter.net>
+ * @package TYPO3
+ * @subpackage t3lib_tree
+ */
+
+class t3lib_tree_Tca_DatabaseTreeDataProvider extends t3lib_tree_Tca_AbstractTcaTreeDataProvider {
+
+       const MODE_CHILDREN = 1;
+       const MODE_PARENT = 2;
+
+       /**
+        * @var string
+        */
+       protected $tableName = '';
+
+       /**
+        * @var string
+        */
+       protected $treeId = '';
+
+       /**
+        * @var string
+        */
+       protected $labelField = '';
+
+       /**
+        * @var string
+        *
+        */
+       protected $tableWhere = '';
+
+       /**
+        * @var int
+        */
+       protected $lookupMode = t3lib_tree_tca_DatabaseTreeDataProvider::MODE_CHILDREN;
+
+       /**
+        * @var string
+        */
+       protected $lookupField = '';
+
+       /**
+        * @var int
+        */
+       protected $rootUid = 0;
+
+
+       /**
+        * Sets the label field
+        *
+        * @param string $labelField
+        * @return void
+        */
+       public function setLabelField($labelField) {
+               $this->labelField = $labelField;
+       }
+
+       /**
+        * Gets the label field
+        *
+        * @return string
+        */
+       public function getLabelField() {
+               return $this->labelField;
+       }
+
+       /**
+        * Sets the table name
+        *
+        * @param string $tableName
+        * @return void
+        */
+       public function setTableName($tableName) {
+               $this->tableName = $tableName;
+       }
+
+       /**
+        * Gets the table name
+        *
+        * @return string
+        */
+       public function getTableName() {
+               return $this->tableName;
+       }
+
+       /**
+        * Sets the lookup field
+        *
+        * @param string $lookupField
+        * @return void
+        */
+       public function setLookupField($lookupField) {
+               $this->lookupField = $lookupField;
+       }
+
+       /**
+        * Gets the lookup field
+        *
+        * @return string
+        */
+       public function getLookupField() {
+               return $this->lookupField;
+       }
+
+       /**
+        * Sets the lookup mode
+        *
+        * @param int $lookupMode
+        * @return void
+        */
+       public function setLookupMode($lookupMode) {
+               $this->lookupMode = $lookupMode;
+       }
+
+       /**
+        * Gets the lookup mode
+        *
+        * @return int
+        */
+       public function getLookupMode() {
+               return $this->lookupMode;
+       }
+
+
+       /**
+        * Gets the nodes
+        *
+        * @param t3lib_tree_Node $node
+        * @return t3lib_tree_NodeCollection
+        */
+       public function getNodes(t3lib_tree_Node $node) {
+
+       }
+
+       /**
+        * Gets the root node
+        *
+        * @return t3lib_tree_tca_DatabaseNode
+        */
+       public function getRoot() {
+               return $this->buildRepresentationForNode($this->treeData);
+       }
+
+       /**
+        * Sets the root uid
+        *
+        * @param  $rootUid
+        * @return void
+        */
+       public function setRootUid($rootUid) {
+               $this->rootUid = $rootUid;
+       }
+
+       /**
+        * Gets the root uid
+        *
+        * @return int
+        */
+       public function getRootUid() {
+               return $this->rootUid;
+       }
+
+       /**
+        * Sets the tableWhere clause
+        *
+        * @param string $tableWhere
+        * @return void
+        */
+       public function setTableWhere(string $tableWhere) {
+               $this->tableWhere = $tableWhere;
+       }
+
+       /**
+        * Gets the tableWhere clause
+        *
+        * @return string
+        */
+       public function getTableWhere() {
+               return $this->tableWhere;
+       }
+
+       /**
+        * Builds a complete node including childs
+        *
+        * @param t3lib_tree_Node $basicNode
+        * @param null|t3lib_tree_tca_DatabaseNode $parent
+        * @param int $level
+        * @return A|object
+        */
+       protected function buildRepresentationForNode(t3lib_tree_Node $basicNode, t3lib_tree_tca_DatabaseNode $parent = NULL, $level = 0) {
+               $node = t3lib_div::makeInstance('t3lib_tree_tca_DatabaseNode');
+               $row = array();
+               if ($basicNode->getId() == 0) {
+                       $node->setSelected(FALSE);
+                       $node->setExpanded(TRUE);
+                       $node->setLabel($GLOBALS['LANG']->sL($GLOBALS['TCA'][$this->tableName]['ctrl']['title']));
+               } else {
+                       $row = t3lib_BEfunc::getRecordWSOL($this->tableName, $basicNode->getId(), '*');
+                       if ($this->getLabelField() !== '') {
+                               $node->setLabel($row[$this->getLabelField()]);
+                       } else {
+                               $node->setLabel($basicNode->getId());
+                       }
+                       $node->setSelected(t3lib_div::inList($this->getSelectedList(), $basicNode->getId()));
+                       $node->setExpanded($this->isExpanded($basicNode));
+               }
+               $node->setSelectable(!t3lib_div::inList($this->getNonSelectableLevelList(), $level));
+               $node->setIcon(t3lib_iconWorks::mapRecordTypeToSpriteIconClass($this->tableName, $row));
+               $node->setId($basicNode->getId());
+               $node->setParentNode($parent);
+               if ($basicNode->hasChildNodes()) {
+                       $node->setHasChildren(TRUE);
+
+                       $childNodes = t3lib_div::makeInstance('t3lib_tree_NodeCollection');
+                       foreach ($basicNode->getChildNodes() as $child) {
+                               $childNodes->append($this->buildRepresentationForNode($child, $node, $level + 1));
+                       }
+                       $node->setChildNodes($childNodes);
+               }
+               return $node;
+       }
+
+       /**
+        * Init the tree data
+        *
+        * @return void
+        */
+       public function initializeTreeData() {
+               parent::initializeTreeData();
+
+               $this->treeData = t3lib_div::makeInstance('t3lib_tree_Node');
+               $this->treeData->setId($this->getRootUid());
+               $this->treeData->setParentNode(NULL);
+               $childNodes = $this->getChildrenOf($this->treeData, 0);
+               if ($childNodes !== NULL) {
+                       $this->treeData->setChildNodes($childNodes);
+               }
+       }
+
+       /**
+        * Gets node children
+        *
+        * @param t3lib_tree_Node $node
+        * @param  $level
+        * @return A|null|object
+        */
+       protected function getChildrenOf(t3lib_tree_Node $node, $level) {
+               if ($this->getLookupMode() == t3lib_tree_tca_DatabaseTreeDataProvider::MODE_CHILDREN) {
+                       $nodeData = NULL;
+                       if ($node->getId() !== 0) {
+                               $nodeData = current($GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                                       '*',
+                                       $this->tableName,
+                                       'uid=' . $node->getId()
+                               ));
+                       }
+                       if ($nodeData == NULL) {
+                               $nodeData = array('uid' => 0);
+                       }
+                       $children = $this->getRelatedRecords($nodeData);
+               } else {
+                       $childrenDB = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                               'uid',
+                               $this->tableName,
+                               $this->getLookupField() . '=' . intval($node->getId()) .  $this->getTableWhere()
+                       );
+                       $children = array();
+                       foreach ($childrenDB as $child) {
+                               $children[] = $child['uid'];
+                       }
+               }
+               if (count($children)) {
+                       $storage = t3lib_div::makeInstance('t3lib_tree_NodeCollection');
+                       foreach ($children as $child) {
+                               $node = t3lib_div::makeInstance('t3lib_tree_Node');;
+                               $node->setId($child);
+                               if ($level <= $this->levelMaximum) {
+                                       $children = $this->getChildrenOf($node, $level + 1);
+                                       if ($children !== NULL) {
+                                               $node->setChildNodes($this->getChildrenOf($node, $level + 1));
+                                       }
+                               }
+                               $storage->append($node);
+                       }
+               } else {
+                       $storage = NULL;
+               }
+               return $storage;
+       }
+
+       /**
+        * Gets related records depending on TCA configuration
+        *
+        * @param  $row
+        * @return array
+        */
+       protected function getRelatedRecords(array $row) {
+               $relatedUids = array();
+               $uid = $row['uid'];
+               $value = $row[$this->getLookupField()];
+
+               $theColConf = $GLOBALS['TCA'][$this->getTableName()]['columns'][$this->getLookupField()]['config'];
+               switch ((string)$theColConf['type']) {
+                       case 'inline':
+                       case 'select':
+                               if ($theColConf['MM']) {
+                                       $dbGroup = t3lib_div::makeInstance('t3lib_loadDBGroup');
+                                       $dbGroup->start($value, $theColConf['foreign_table'], $theColConf['MM'], $uid, $this->getLookupField(), $theColConf);
+                                       $relatedUids = $dbGroup->tableArray[$theColConf['foreign_table']];
+                               } elseif ($theColConf['foreign_table'] && $GLOBALS['TCA'][$theColConf['foreign_table']] && $theColConf['foreign_field']) {
+                                       $records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid', $theColConf['foreign_table'], $theColConf['foreign_field'] . '=' . intval($uid) . ' ' . t3lib_BEfunc::deleteClause( $theColConf['foreign_table']));
+                                       foreach ($records as $record) {
+                                               $relatedUids[] = $record['uid'];
+                                       }
+                               } else {
+                                       $relatedUids = t3lib_div::trimExplode(',', $value);
+                               }
+                               break;
+                       case 'group':
+                               $relatedUids = t3lib_div::trimExplode(',', $value, 1);
+                       break;
+               }
+               return $relatedUids;
+       }
+
+}
+
+?>
diff --git a/t3lib/tree/tca/class.t3lib_tree_tca_dataproviderfactory.php b/t3lib/tree/tca/class.t3lib_tree_tca_dataproviderfactory.php
new file mode 100644 (file)
index 0000000..6199f9d
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Builds a t3lib_tree_Tca_DatabaseTreeDataProvider object based on some TCA configuration
+ *
+ * @author Steffen Ritter <info@steffen-ritter.net>
+ * @package TYPO3
+ * @subpackage t3lib_tree
+ */
+class t3lib_tree_Tca_DataProviderFactory {
+
+       /**
+        * Gets the data provider, depending on TCA configuration
+        *
+        * @static
+        * @param array $tcaConfiguration
+        * @return t3lib_tree_Tca_DatabaseTreeDataProvider
+        * @throws InvalidArgumentException
+        */
+       public static function getDataProvider(array $tcaConfiguration, $table, $field, $currentValue) {
+               $dataProvider = NULL;
+
+               if (!isset($tcaConfiguration['internal_type'])) {
+                       $tcaConfiguration['internal_type'] = 'db';
+               }
+
+               if ($tcaConfiguration['internal_type'] == 'db') {
+                       /**
+                        * @var $dataProvider t3lib_tree_Tca_DatabaseTreeDataProvider
+                        */
+                       $dataProvider = t3lib_div::makeInstance('t3lib_tree_Tca_DatabaseTreeDataProvider');
+
+                       if (isset($tcaConfiguration['foreign_table'])) {
+                               $tableName = $tcaConfiguration['foreign_table'];
+                               $dataProvider->setTableName($tableName);
+
+                               t3lib_div::loadTCA($tableName);
+                       } else {
+                               throw new InvalidArgumentException(
+                                       'TCA Tree configuration is invalid: "foreign_table" not set',
+                                       '1288215888'
+                               );
+                       }
+
+                       if (isset($tcaConfiguration['foreign_label'])) {
+                               $dataProvider->setLabelField($tcaConfiguration['foreign_label']);
+                       } else {
+                               $dataProvider->setLabelField($GLOBALS['TCA'][$tableName]['ctrl']['label']);
+                       }
+                       $dataProvider->setTreeId(md5($table . '|' . $field));
+                       $dataProvider->setSelectedList($currentValue);
+                       if (isset($tcaConfiguration['treeConfig']) && is_array($tcaConfiguration['treeConfig'])) {
+                               $treeConfiguration = $tcaConfiguration['treeConfig'];
+
+                               if (isset($treeConfiguration['rootUid'])) {
+                                       $dataProvider->setRootUid(intval($treeConfiguration['rootUid']));
+                               }
+
+                               if (isset($treeConfiguration['appearance']['expandAll'])) {
+                                       $dataProvider->setExpandAll((boolean)$treeConfiguration['appearance']['expandAll']);
+                               }
+
+                               if (isset($treeConfiguration['appearance']['maxLevels'])) {
+                                       $dataProvider->setLevelMaximum(intval($treeConfiguration['appearance']['maxLevels']));
+                               }
+
+                               if (isset($treeConfiguration['appearance']['nonSelectableLevels'])) {
+                                       $dataProvider->setNonSelectableLevelList($treeConfiguration['appearance']['nonSelectableLevels']);
+                               } elseif (isset($treeConfiguration['rootUid'])) {
+                                       $dataProvider->setNonSelectableLevelList('');
+                               }
+
+                               if (isset($treeConfiguration['childrenField'])) {
+                                       $dataProvider->setLookupMode(t3lib_tree_tca_DatabaseTreeDataProvider::MODE_CHILDREN);
+                                       $dataProvider->setLookupField($treeConfiguration['childrenField']);
+                               } elseif (isset($treeConfiguration['parentField'])) {
+                                       $dataProvider->setLookupMode(t3lib_tree_tca_DatabaseTreeDataProvider::MODE_PARENT);
+                                       $dataProvider->setLookupField($treeConfiguration['parentField']);
+                               } else {
+                                       throw new InvalidArgumentException(
+                                               'TCA Tree configuration is invalid: neither "childrenField" nor "parentField" is set',
+                                               '1288215889'
+                                       );
+                               }
+                       } else {
+                               throw new InvalidArgumentException(
+                                       'TCA Tree configuration is invalid: "treeConfig" array is missing',
+                                       '1288215890'
+                               );
+                       }
+
+               } elseif ($tcaConfiguration['internal_type'] == 'file') {
+                               // Not implemented yet
+                       throw new InvalidArgumentException(
+                               'TCA Tree configuration is invalid: tree for "internal_type=file" not implemented yet',
+                               '1288215891'
+                       );
+               } else {
+                       throw new InvalidArgumentException(
+                               'TCA Tree configuration is invalid: tree for "internal_type=' .
+                                       $tcaConfiguration['internal_type'] .
+                                       '" not implemented yet',
+                               '1288215892'
+                       );
+               }
+               return $dataProvider;
+       }
+}
+
+?>
diff --git a/t3lib/tree/tca/class.t3lib_tree_tca_extjsarrayrenderer.php b/t3lib/tree/tca/class.t3lib_tree_tca_extjsarrayrenderer.php
new file mode 100644 (file)
index 0000000..b077c87
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Renders a tca tree array for ExtJS
+ *
+ * @author     Steffen Ritter <info@steffen-ritter.net>
+ * @package TYPO3
+ * @subpackage t3lib_tree
+ */
+
+class t3lib_tree_Tca_ExtJsArrayRenderer extends t3lib_tree_Renderer_ExtJsJson {
+
+       /**
+        * Gets the node array. If the TCA configuration has defined items,
+        * they are added to rootlevel on top of the tree
+        *
+        * @param t3lib_tree_Tca_DatabaseNode $node
+        * @return array
+        */
+       protected function getNodeArray(t3lib_tree_Tca_DatabaseNode $node) {
+               $nodeArray = parent::getNodeArray($node);
+               $nodeArray = array_merge(
+                       $nodeArray,
+                       array(
+                               'expanded' => $node->getExpanded(),
+                               'expandable' => $node->hasChildNodes(),
+                               'checked' => $node->getSelected(),
+                       )
+               );
+               if (!$node->getSelectable()) {
+                       unset ($nodeArray['checked']);
+               }
+               return $nodeArray;
+       }
+
+       /**
+        * Renders a node collection recursive or just a single instance
+        *
+        * @param t3lib_tree_NodeCollection $node
+        * @param bool $recursive
+        * @return array
+        */
+       public function renderTree(t3lib_tree_AbstractTree $tree, $recursive = TRUE) {
+               $this->recursionLevel = 0;
+               $children = $this->renderNode($tree->getRoot(), $recursive);
+
+               return $children;
+       }
+}
+
+?>
diff --git a/t3lib/tree/tca/class.t3lib_tree_tca_tcatree.php b/t3lib/tree/tca/class.t3lib_tree_tca_tcatree.php
new file mode 100644 (file)
index 0000000..4f6e1ba
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Ritter <info@steffen-ritter.net>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Class for tca tree
+ *
+ * @author     Steffen Ritter <info@steffen-ritter.net>
+ * @package TYPO3
+ * @subpackage t3lib_tree
+ */
+
+class t3lib_tree_Tca_TcaTree extends t3lib_tree_AbstractTree {
+
+       /**
+        * Returns the root node
+        *
+        * @return t3lib_tree_Node
+        */
+       public function getRoot() {
+               return $this->dataProvider->getRoot();
+       }
+
+       /**
+        * Renders a tree
+        *
+        * @return mixed
+        */
+       public function render() {
+               return $this->nodeRenderer->renderTree($this);
+       }
+}
+
+?>