.. _api: ========== Baobab API ========== Copyright and License --------------------- Copyright 2010-2011 Riccardo Attilio Galli http://www.sideralis.org Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Exceptions ---------- .. class:: sp_Error Root exception. Each exception thrown in a Sideralis Programs library derive from this class .. class:: sp_MySQL_Error Exception holding informations about errors occurred when using mysql :param $conn_or_msg: database connection object or an exception message :type $conn_or_msg: mysqli or string :param $err_code: mysql error code :type $err_code: int .. class:: BaobabNode($id,$lft,$rgt,$parentId[,$fields=NULL]) Node of a Baobab tree :param $id: the node id :type $id: int :param $lft: the node left bound :type $lft: int :param $rgt: the node right bound :type $rgt: int :param $parentId: the parent's node id, if any :type $parentId: int or NULL :param $fields_values: additional fields of the node (mapping fieldName => value) :type $fields_values: array or NULL **Attributes**: **id** int, node id **lft** int, left value **rgt** int, right value **parentNode** int, the parent node id **fields_values** array, additional fields of the node **children** array, instances of BaobabNode children of the current node .. note:: this class doesn't have database interaction, its purpose is just to have a runtime representation of a Baobab tree. The data inserted is supposed to be valid in his tree (e.g. $this->lft cant' be -1 or major of any node right value) .. method:: appendChild($child) Add a node as last sibling of the node's children. :param $child: append a node to the list of this node children :type $child: :class:`BaobabNode` .. method:: stringify([$fields=NULL[,$diveInto=TRUE[,$indentChar=" "[,$indentLevel=0]]]]) Return a representation of the tree as a string. :param $fields: what node fields include in the output. id, lft and rgt are always included. :type $fields: array :param $diveInto: wheter to continue with node's children or not :type $diveInto: boolean :param $indentChar: character to use to indent :type $indentChar: string :param $indentLevel: how deep we are indenting :type $indentLevel: int :return: tree or node representation :rtype: string .. note:: $indentLevel is meant for internal use only. .. todo:: $fields is currently unused .. method:: isRightmost() Check if the node is rightmost between his siblings. :return: whether if the node is the rightmost or not :rtype: boolean .. note: root node is considered to be rightmost .. method:: isLeftmost() Check if the node is leftmost between his siblings. :return: whether if the node is the leftmost or not :rtype: boolean .. note: root node is considered to be leftmost Baobab ------ .. class:: Baobab($db,$forest_name[,$tree_id=NULL]) This class lets you create, populate search and destroy a tree stored using the Nested Set Model described by Joe Celko. :param $db: mysqli database connection in object oriented style :type $db: an instance of mysqli_connect :param $forest_name: name of the forest, will be used to create an homonymous table that will hold the data. :type $forest_name: string :param $tree_id: id of the tree (to create a new tree it must be NULL or an unused tree_id number). If there is only a tree in the table, you can load it with -1; A new tree created using NULL has $tree_id = 0 until an appendChild occurs. :type $tree_id: int or NULL **Attributes**: **tree_id** int, id of the tree (0 means it's new with no nodes added yet) .. method:: build() Apply the database schema :return: TRUE if any table was added, FALSE if the build was skipped (e.g. if the tree yet exists calling build will do nothing and return FALSE). :rtype: boolean .. note:: This is automatically called while instantiating the class. If the version of the library didn't change in the meantime, nothing happens, otherwise it will throw an exception to inform you to use :class:`Baobab:upgrade()` .. staticmethod:: upgrade($db[,$untilVersion=NULL]) Upgrade the database schema of all the trees to reflect the current library's version. :param $db: mysqli database connection object :type $db: mysqli :param $untilVersion: version at which stop (or NULL to update to last version) :type $untilVersion: string or NULL .. warning:: To avoid any possible data loss you should backup your database's tables first. .. warning:: For each release read release notes and check what's going to happen when you upgrade your database (see sql/upgrade/* files). Eventually stop with $untilVersion at a certain point to apply needed tweaks. .. method:: destroy() Remove every table, procedure or view that were created via :class:`Baobab.build` for the current tree name :param $removeDataTable: unless this value is TRUE, avoid to delete the table that holds the tree data :type $removeDataTable: boolean .. method:: clean() Delete all the records about this tree. Other trees in the same table will be unaffected. .. staticmethod:: cleanAll($db,$forest_name) Delete all the records in $forest_name :param $db: mysqli database connection in object oriented style :type $db: an instance of mysqli_connect :param $forest_name: name of the forest, equals to the name of the table holding the data :type $forest_name: string .. method:: getRoot() Return the id of the first node of the tree. :return: id of the root, or NULL if empty :rtype: int or NULL .. method:: getParent($id_node) Return the id of the node's parent. :return: id of the parent, or NULL if node is root :rtype: int or NULL .. method:: getSize([$id_node=NULL]) Retrieve the number of nodes of the subtree starting at $id_node (or at tree root if $id_node is NULL). :param $id_node: id of the node to count from (or NULL to count from root) :type $id_node: int or NULL :return: the number of nodes in the selected subtree :rtype: int .. method:: getDescendants([$id_node=NULL]) Retrieve all the descendants of a node :param $id_node: id of the node whose descendants we're searching for, or NULL to start from the tree root. :type $id_node: int or NULL :return: the ids of node's descendants, in ascending order :rtype: array .. method:: getLeaves([$id_node=NULL]) Find the leaves of a subtree. :param $id_node: id of a node or NULL to start from the tree root :type $id_node: int or NULL :return: the ids of the leaves, ordered from left to right :rtype: array .. method:: getLevels() Find at what level of the tree each node is. :param $id_node: id of a node or NULL to start from the tree root :type $id_node: int or NULL :return: associative arrays with id => number, level => number, unordered :rtype: array .. note:: tree root is at level 0 .. method:: getPath($id_node[,$fields=NULL[,$squash=FALSE]]) Find all the nodes between tree root and a node. :param $id_node: id of the node used to calculate the path to :type $id_node: int :param $fields: if not NULL, a string with a Baobab tree field name or an array of field names :type $fields: mixed :param $squash: if TRUE the method will return an array with just the values of the first field in $fields (if $fields is empty it will default to "id" ) :type $squash: boolean :return: sequence of associative arrays mapping for each node fieldName => value, where field names are the one present in $fields plus the field "id" (unless $squash was set), ordered from root to $id_node :rtype: array Example (considering a tree with two nodes with a field 'name'): .. code-block:: none php> $tree->getPath(2, array("name")) array([0] => array([id] => 1, [name] => 'rootName'), array([id] => 2, [name] => 'secondNodeName'])) php> join("/", $tree->getPath(2, "name", TRUE)) "rootName/secondNodeName" .. method:: getFirstNChildren($id_parent[,$howMany=NULL[,$fromLeftToRight=TRUE]]) Find the first n node's children starting from left or right. :param $id_parent: id of the parent node :type $id_parent: int :param $howMany: maximum number of children to retrieve (NULL means all) :type $howMany: int or NULL :param $fromLeftToRight: what order the children must follow :type $fromLeftToRight: boolean :return: ids of the children nodes, ordered from left to right :rtype: array .. method:: getChildren($id_parent) Find all node's children :param $id_parent: id of the parent node :type $id_parent: int :return: ids of the children nodes, ordered from left to right :rtype: array .. method:: getFirstChild($id_parent) Find the leftmost child of a node :param $id_parent: id of the parent node :type $id_parent: int :return: id of the leftmost child node, or 0 if not found :rtype: int .. method:: getLastChild($id_parent) Find the rightmost child of a node :param $id_parent: id of the parent node :type $id_parent: int :return: id of the rightmost child node, or 0 if not found :rtype: int .. method:: getChildAtIndex($id_parent, $index) Find the nth child of a parent node :param $id_parent: id of the parent node :type $id_parent: int :param $index: position between his siblings (0 is first). Negative indexes are allowed (-1 is the last sibling). :type $index: int :return: id of the nth child node :rtype: int .. method:: getTree([$className="BaobabNode"[,$appendChild="appendChild"]]) Create a tree from the database data. It's possible to use a default tree or use custom classes/functions (it must extends the class :class:`BaobabNode`) :param $className: name of the class holding a node's information :type $className: string :param $appendChild: method of $className to call to append a node :type $appendChild: string :return: a node instance :rtype: instance of $className .. method:: deleteNode($id_node[,$close_gaps=True]) Delete a node and all of his children. If $close_gaps is TRUE, mantains the Modified Preorder Tree consistent closing gaps. :param $id_node: id of the node to drop :type $id_node: int :param $close_gaps: whether to close the gaps in the tree or not (default TRUE) :type $close_gaps: boolean .. warning:: If the gaps are not closed, you can't use most of the API. Usually you want to avoid closing gaps when you're deleting different subtrees and want to update the numbering just once (see :class:`Baobab.closeGaps`) .. method:: closeGaps Update right and left values of each node to ensure there are no gaps in the tree. .. warning:: This is a really slow function, use it only if needed (e.g. to delete multiple subtrees and close gaps just once) .. method:: getTreeHeight() Calculate the height of the tree :return: the height of the tree :rtype: int .. note:: A tree with one node has height 1. .. method:: updateNode($id_node,$fields_values) Update data associeted to a node :param $id_node: id of the node to update :type $id_node: int :param $fields_values: mapping fields => values to update (only supported types are string, int, float, boolean) :type $fields_values: array .. method:: getNodeData($id_node[,$fields=NULL]) Retrieve informations about a node. :param $id_node: id of the node :type $id_node: int :param $fields: fields' names to read values from :type $fields: array :return: the informations found :rtype: array .. method:: appendChild([$id_parent=NULL[,$fields_values=NULL]]) Create and append a node as last child of a parent node. If no parent is given, the new node will become the root node. :param $id_parent: id of the parent node :type $id_parent: int or NULL :param $fields_values: mapping fields => values to assign to the new node :type $fields_values: array or NULL :return: id of new node :rtype: int .. method:: insertAfter($id_sibling[,$fields_values=NULL]) Create a new node and insert it as the next sibling of the node chosen (which can not be root) :param $id_sibling: id of a node in the tree (can not be root) :type $id_sibling: int :param $fields_values: mapping fields => values to assign to the new node :type $fields_values: array or NULL :return: id of the new node :rtype: int .. method:: insertBefore($id_sibling[,$fields_values=NULL]) Create a new node and insert it as the previous sibling of the node chosen (which can not be root) :param $id_sibling: id of a node in the tree (can not be root) :type $id_sibling: int :param $fields_values: mapping fields => values to assign to the new node :type $fields_values: array or NULL :return: id of the new node :rtype: int .. method:: insertChildAtIndex($id_parent,$index[,$fields_values=NULL]) Create a new node and insert it as the nth child of the parent node chosen :param $id_parent: id of a node in the tree :type $id_parent: int :param $index: new child position between his siblings (0 is first). You cannot insert a child as last sibling. Negative indexes are allowed (-1 is the position before the last sibling). :type $index: int :param $fields_values: mapping fields => values to assign to the new node :type $fields_values: array or NULL :return: id of the new node :rtype: int .. method:: moveAfter($id_to_move,$reference_node) Move a node and all of his children as right sibling of another node. :param $id_to_move: id of a node in the tree :type $id_to_move: int :param $reference_node: the node that will become the left sibling of $id_to_move :type $reference_node: int .. warning: Moving a subtree after/before root or as a child of hisself will throw a sp_Error exception .. method:: moveBefore($id_to_move,$reference_node) Move a node and all of his children as left sibling of another node. :param $id_to_move: id of a node in the tree :type $id_to_move: int :param $reference_node: the node that will become the left sibling of $id_to_move :type $reference_node: int .. warning: Moving a subtree after/before root or as a child of hisself will throw a sp_Error exception .. method:: moveNodeAtIndex($id_to_move,$id_parent,$index) Move a node as nth child of another node. :param $id_to_move: id of a node in the tree :type $id_to_move: int :param $id_parent: id of a node that will become $id_to_move's parent :type $id_parent: int :param $index: new child position between his siblings (0 is first). Negative indexes are allowed (-1 is the position before the last sibling). :type $index: int .. warning: Moving a subtree after/before root or as a child of hisself will throw a sp_Error exception .. staticmethod:: import($db,$forest_name,$data) Load data about a single tree (as generated by the export method). :param $db: mysqli database connection in object oriented style :type $db: an instance of mysqli_connect :param $forest_name: name of the forest, equals to the name of the table holding the data :type $forest_name: string :param $data: data to import :type $data: string (JSON) or array :return: an array of Baobab tree instances :rtype: array $data JSON format is like the following .. code-block:: json [ { "tree_id": 6, //optional, it could also be one of the fields, or none at all "fields" : ["id", "lft", "rgt"], "values" : [1,1,4,[ [2,2,3,[]] ]] } // more could follow ... ] .. note:: If "id" field is used and the nodes values are not NULL, mustn't exist in the table a record with that same value. .. note:: If "tree_id" is used (as attribute or field) and not NULL, mustn't exist in the table records belonging to that same tree. .. staticmethod:: export($db,$forest_name[,$fields=NULL[,$tree_id=NULL]]) Create a JSON dump of one or more trees :param $db: mysqli database connection in object oriented style :type $db: an instance of mysqli_connect :param $forest_name: name of the forest, equals to the name of the table holding the data :type $forest_name: string :param $fields: optional, the fields to be exported :type $fields: array :param $tree_id: optional, a single tree_id to be exported, or an array of them. If NULL all the trees in the table will be exported; :type $tree_id: array or int :return: a dump of the trees in JSON format :rtype: string .. note:: if 'tree_id' is passed as field, it will not appear in the field list because redundat (it will be present once in the tree_id attribute) Example of an exported tree .. code-block:: json [ { "tree_id": 6, "fields" : ["id", "lft", "rgt"], // tree_id is stripped if requested via fields because redundant "values" : [1,1,4,[ [2,2,3,[]] ]] } // more could follow ... ]