* @license http://www.contenido.org/license/LIZENZ.txt * @link http://www.4fb.de * @link http://www.contenido.org * * {@internal * created 2006-10-05 * * $Id$ * }} * */ if (!defined('CON_FRAMEWORK')) { die('Illegal call'); } /** * class cTreeItem * */ class cTreeItem { /** * Sub Items for this tree item * @var array */ var $_subitems; /** * Determinates if this tree item is collapsed * @var boolean */ var $_collapsed; /** * ID for this item * @var string */ var $_id; /** * Name for this item * @var string */ var $_name; /** * Contains the level of this item * @var integer */ var $_level; /** * Contains custom entries * @var array */ var $_attributes; /** * Contains the parent of this item * @var array */ var $_parent; /** * Contains the next item * @var array */ var $_next; /** * Contains the previous item * @var array */ var $_previous; function __construct($id = "", $name = "", $collapsed = false) { $this->_id = $id; $this->_name = $name; $this->_collapsed = $collapsed; $this->_subitems = array(); $this->_parent = false; $this->_next = false; $this->_previous = false; $this->_attributes = array(); } /** * Imports a table from an array of arrays. Array format: * array( * array("id" => "Item ID", "name" => "Item name", "level" => 1, "collapsed" => true|false, "attributes" => array("attr_name" => "attr_value")) * ); * * The entries "collapsed" and "attributes" are optional! * * @param array flat_array See above * @return void * @access public */ function importTable($flat_array) { $lastobj[0] = $this->_id; $currentlevel = 1; if (!is_array($flat_array)) { return false; } foreach ($flat_array as $item) { $mitem[$item["id"]] = new cTreeItem($item["id"], $item["name"]); if ($item["level"] > $currentlevel) { $currentlevel++; } if ($item["level"] < $currentlevel) { $currentlevel = $item["level"]; } if (is_array($item["attributes"])) { $mitem[$item["id"]]->setAttributes($item["attributes"]); } if (array_key_exists("collapsed", $item)) { $mitem[$item["id"]]->setCollapsed($item["collapsed"]); } /* Set payload object */ if (array_key_exists("payload", $item)) { $mitem[$item["id"]]->setPayloadObject($item["payload"]); } if (is_object($mitem[$lastobj[$currentlevel - 1]])) { $mitem[$lastobj[$currentlevel - 1]]->addItem($mitem[$item["id"]]); } else { $this->addItemToID($lastobj[$currentlevel - 1], $mitem[$item["id"]]); } $lastobj[$currentlevel] = $item["id"]; } } // end of member function importTree function importStructuredArray($array) { $i = array(); $lastid = 1; $level = 1; $this->_flattenArray($array, $i, $lastid, $level); $this->importTable($i); } function _flattenArray($sourcearray, &$destarray, &$lastid, &$level) { if ($lastid == false) { $lastid = 1; } if ($level == false) { $level = 1; } if (!is_array($sourcearray)) { return false; } foreach ($sourcearray as $id => $item) { $lastid++; $destarray[$lastid]["id"] = $item["class"] . "." . $id; /* Name should be fetched via the meta object */ $meta = $item["object"]->getMetaObject(); if (is_object($meta)) { $destarray[$lastid]["name"] = $meta->getName(); } $destarray[$lastid]["level"] = $level; $destarray[$lastid]["payload"] = $item["object"]; if (count($item["items"]) > 0) { $level++; $this->_flattenArray($item["items"], $destarray, $lastid, $level); $level--; } } } /** * Exports a tree as an array of arrays. Array format: * array( * array("id" => "Item ID", "name" => "Item name", "level" => 1, "attributes" => array("attr_name" => "attr_value")) * ); * * @return array * @access public */ function exportTree() { /* TODO: Function can't work... work in progress... $myobj->traverse($objlist); */ } // end of member function exportTree /** * adds an item as a subitem to the current item * * @param cTreeItem item item object to add * @return void * @access public */ function addItem(&$item) { /* Update last item */ if ($lastitem = end($this->_subitems) !== false) { $this->_subitems[key($this->_subitems)]->_next = $item->_id; } $this->_subitems[count($this->_subitems)] = &$item; $item->_parent = $this->_id; $item->_previous = $lastitem->_id; } // end of member function addItem /** * adds an item to a specific ID * * @param string id ID to add the item to * @param cTreeItem item Item to add * @return void * @access public */ function addItemToID($id, &$item) { if ($this->_id == $id) { /* Update last item */ if ($lastitem = end($this->_subitems) !== false) { $this->_subitems[key($this->_subitems)]->_next = $item->_id; } $this->_subitems[count($this->_subitems)] = &$item; $item->_parent = $this->_id; $item->_previous = $lastitem->_id; return true; } else { foreach (array_keys($this->_subitems) as $key) { $result = $this->_subitems[$key]->addItemToID($id, $item); if ($result == true) { return true; } } } return false; } // end of member function addItemToID /** * moves an item to another object * * @param cTreeItem targetItem Item to move the subitem to * @param mixed itemToMove cTreeItem-Object or id of object to move * @return void * @access public */ function moveItem($targetItem, $itemToMove) { } // end of member function moveItem /** * deletes a subitem * * @param mixed item object or ID to delete * @return deleted object * @access public */ function deleteItem($id) { foreach (array_keys($this->_subitems) as $key) { if ($this->_subitems[$key]->_id == $id) { /* Fetch next item, reset to current item */ $nextitem = next($this->_subitems); $nkey = key($this->_subitems); prev($this->_subitems); $previtem = &prev($this->_subitems); $pkey = key($this->_subitems); next($this->_subitems); if ($nextitem !== false) { if ($previtem !== false) { $this->_subitems[$nkey]->_previous = $this->_subitems[$pkey]->_id; } } if ($previtem !== false) { if ($nextitem !== false) { $this->_subitems[$pkey]->_next = $this->_subitems[$nkey]->_id; } } $itemcopy = $this->_subitems[$key]; unset($this->_subitems[$key]); return ($itemcopy); } else { $this->_subitems[$key]->deleteItem($id); } } } // end of member function deleteItem /** * Retrieves a specific item by its ID. Note that this * function traverses all subitems to find the correct item. * * @param string id ID to retrieve * @return cTreeItem * @access public */ function &getItemByID($id) { if ($this->_id == $id) { return ($this); } else { foreach (array_keys($this->_subitems) as $key) { $retObj = &$this->_subitems[$key]->getItemByID($id); if ($retObj->_id == $id) { return ($retObj); } } } return false; } // end of member function getItemByID /** * sets a custom attribute for this TreeItem * * @param string attributeName * @param array attributeValue The value(s) of the attribute * @return void * @access public */ function setAttribute($attributeName, $attributeValue) { $this->_attributes[$attributeName] = $attributeValue; } // end of member function setAttribute /** * sets a bunch of attributes * * @param string attributeName * @param array attributeValue The value(s) of the attribute * @return void * @access public */ function setAttributes($aAttributeArray) { $this->_attributes = array_merge($aAttributeArray, $this->_attributes); } // end of member function setAttribute /** * returns an attribute * * @param string attributeName * @return mixed * @access public */ function getAttribute($attributeName) { if (array_key_exists($attributeName, $this->_attributes)) { return ($this->_attributes[$attributeName]); } else { return false; } } // end of member function getAttribute /** * deletes an attribute * * @param string attributeName * @return void * @access public */ function deleteAttribute($attributeName) { if (array_key_exists($attributeName, $this->_attributes)) { unset($this->_attributes[$attributeName]); return true; } else { return false; } } // end of member function deleteAttribute function hasAttribute($attributeName, $bRecursive = false) { if (array_key_exists($attributeName, $this->_attributes)) { return true; } else { if ($bRecursive == true) { if (count($this->_subitems) > 0) { foreach ($this->_subitems as $oSubitem) { $bFound = $oSubitem->hasAttribute($attributeName, true); if ($bFound == true) { return true; } } } return false; } else { return false; } } } /** * * * @param mixed expand ID of item to expand or array of item ID's to expand * @return void * @access public */ function setExpanded($id) { if (is_array($id)) { if (in_array($this->_id, $id, true)) { $this->_collapsed = false; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->setExpanded($id); } } else { if ($this->_id === $id) { $this->_collapsed = false; return true; } else { foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->setExpanded($id); } } } } // end of member function setExpanded /** * * * @param mixed collapse ID to collapse or an array with items to collapse * @return void * @access public */ function setCollapsed($id) { if (is_array($id)) { if (in_array($this->_id, $id, true)) { $this->_collapsed = true; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->setCollapsed($id); } } else { if ($this->_id === $id) { $this->_collapsed = true; return true; } else { foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->setCollapsed($id); } } } } // end of member function setCollapsed /** * * * @param int leveloffset Level offset. Ignores all expand operations below the offset. * @return void * @access public */ function expandBelowLevel($leveloffset) { if ($leveloffset > 0) { $leveloffset--; } else { $this->_collapsed = false; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->expandBelowLevel($leveloffset); } } // end of member function expandBelowLevel /** * * * @param int leveloffset Level offset. Ignores all expand operations below the offset. * @return void * @access public */ function collapseBelowLevel($leveloffset) { if ($leveloffset > 0) { $leveloffset--; } else { $this->_collapsed = true; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->collapseBelowLevel($leveloffset); } } // end of member function expandBelowLevel /** * * * @param int leveloffset Level offset. Ignores all expand operations below the offset. * @return void * @access public */ function expandBelowID($id, $found = false) { if ($found === true) { $this->_collapsed = false; } if ($this->_id == $id) { $found = true; $this->_collapsed = false; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->expandBelowID($id, $found); } } // end of member function expandBelowLevel /** * * * @param int leveloffset Level offset. Ignores all expand operations below the offset. * @return void * @access public */ function collapseBelowID($id, $found = false) { if ($found === true) { $this->_collapsed = true; } if ($this->_id == $id) { $found = true; $this->_collapsed = true; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->collapseBelowID($id, $found); } } // end of member function expandBelowLevel /** * getCollapsedList * Returns all items (as ID array) which are collapsed. * @param array $list Contains the list with all collapsed items */ function getCollapsedList(&$list) { if (!is_array($list)) { $list = array(); } if ($this->_collapsed == true) { $list[] = $this->_id; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->getCollapsedList($list); } } /** * getExpandedList * Returns all items (as ID array) which are expanded. * @param array $list Contains the list with all expanded items */ function getExpandedList(&$list) { if (!is_array($list)) { $list = array(); } if ($this->_collapsed == false && !in_array($this->_id, $list)) { $list[] = $this->_id; } foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->getExpandedList($list); } } /** * sets a payload object for later reference * * @param object payload The object to payload * @return void * @access public */ function setPayloadObject($payload) { $this->payload = $payload; } // end of member function setPayloadObject /** * unsets a payload object * * @return object * @access public */ function unsetPayloadObject() { } // end of member function unsetPayloadObject /** * traverse * traverses the tree starting from this item, and returning * all objects as $objects in a nested array. * @param object $objects all found objects * @param integer $level Level to start on */ function traverse(&$objects, $level = 0) { $objects[count($objects)] = &$this; $this->_level = $level; if ($this->_collapsed == false) { foreach (array_keys($this->_subitems) as $key) { $this->_subitems[$key]->traverse($objects, $level + 1); } } } /** * flatTraverse * traverses the tree starting from this item, and returning * all objects as $objects in a flat array. * @param object $objects all found objects * @param integer $level Level to start on */ function flatTraverse($level = 0) { $objects[] = &$this; $this->_level = $level; if ($this->_collapsed == false) { foreach (array_keys($this->_subitems) as $key) { $objects = array_merge($objects, $this->_subitems[$key]->flatTraverse($level + 1)); } } return $objects; } /** * setName * sets the Name for this item. * @param string $name New name for this item * @return none */ function setName($name) { $this->_name = $name; } } // end of cTreeItem ?>