Tree
[ class tree: Tree ] [ index: Tree ] [ all elements ]

Source for file MDB2simple.php

Documentation is available at MDB2simple.php

  1. <?php
  2.  
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Wolfram Kriesing <wolfram@kriesing.de>                      |
  17. // |          Lorenzo Alberton <l.alberton@quipo.it>                      |
  18. // +----------------------------------------------------------------------+
  19.  
  20. // $Id: MDB2simple.php,v 1.1.2.1 2007/06/01 23:05:38 dufuz Exp $
  21. require_once 'Tree/OptionsMDB2.php';
  22.  
  23. /**
  24. * the MDB2 interface to the tree class
  25. *
  26. @access public
  27. @author Lorenzo Alberton <l.alberton@quipo.it>
  28. @package Tree
  29. */
  30. {
  31.     // FIXXME should actually extend Tree_Common, to use the methods provided in there...
  32.     // but we need to connect to the db here, so we extend optionsMDB2 for now, may be use
  33.     // "aggregate" function to fix that
  34.  
  35.     /**
  36.      * @access public
  37.      * @var array saves the options passed to the constructor. Valid options:
  38.      *       - order: which column to order by when reading the data from the DB,
  39.      *                this sorts the data even inside every level
  40.      *       - whereAddOn: add on for the where clause, this string is simply
  41.      *                     added behind the WHERE in the select, so you better make
  42.      *                     sure its correct SQL :-), i.e. 'uid=3'.
  43.      *                     This is needed i.e. when you are saving many trees for different
  44.      *                     user in one table where each entry has a uid (user id)
  45.      *       - columnNameMaps: the column-name maps are used for the "as" in the select
  46.      *                         queries so you can use any column name in the table and "map"
  47.      *                         it to the name that shall be used in the internal array,
  48.      *                         that is built, see the examples (in comments)
  49.      *       - columnNameMaps: array for id/parentId/prevId/name table column names
  50.      */
  51.     var $options = array('order' => '',
  52.                          'whereAddOn' => '',
  53.                          'table' => '',
  54.                          'columnNameMaps' => array(
  55.                                    /* 'id'       => 'tree_id', // use "tree_id" as "id"
  56.                                       'parentId' => 'parent_id',
  57.                                       'prevId'   => 'previous_id',
  58.                                       'name'     => 'nodeName'
  59.                                    */
  60.                         ),
  61.                     );
  62.  
  63.     /**
  64.      * @access public
  65.      * @var string the table where to read the tree data from
  66.      *              can also be set using the DSN in the constructor
  67.      */
  68.     var $table;
  69.  
  70.     /**
  71.      * @access private
  72.      * @var object $dbh    the handle to the DB-object
  73.      */
  74.     // var $dbh;
  75.  
  76.     // {{{ Tree_Memory_MDB2simple()
  77.  
  78.     /**
  79.      * set up this object
  80.      *
  81.      * @access public
  82.      * @param string $dsn this is a DSN of the for that PEAR::DB uses it
  83.      *                     only that additionally you can add parameters like ...?table=test_table
  84.      *                     to define the table it shall work on
  85.      * @param array $options additional options you can set
  86.      */
  87.     function Tree_Memory_MDB2simple($dsn$options = array())
  88.     {
  89.         $this->Tree_OptionsMDB2($dsn$options)// instanciate DB
  90.         if (is_string($options)) {
  91.             // just to be backward compatible, or to make the second paramter shorter
  92.             $this->setOption('order'$options);
  93.         }
  94.  
  95.         $this->table = $this->getOption('table');
  96.     }
  97.  
  98.     // }}}
  99.     // {{{ setup()
  100.  
  101.     /**
  102.      * retrieve all the navigation data from the db and call build to build the
  103.      * tree in the array data and structure
  104.      *
  105.      * @access public
  106.      * @return boolean true on success
  107.      */
  108.     function setup()
  109.     {
  110.         // TODO sort by prevId (parentId, prevId $addQuery) too if it exists in the table,
  111.         //      or the root might be wrong, since the prevId of the root should be 0
  112.  
  113.         $whereAddOn '';
  114.         if ($this->options['whereAddOn']{
  115.             $whereAddOn 'WHERE ' $this->getOption('whereAddOn');
  116.         }
  117.  
  118.         $orderBy '';
  119.         if ($this->options['order']{
  120.             $orderBy ',' $this->options['order'];
  121.         }
  122.  
  123.         $map $this->getOption('columnNameMaps');
  124.         if (isset($map['parentId'])) {
  125.             $orderBy $map['parentId'$orderBy;
  126.         else {
  127.             $orderBy 'parentId' $orderBy;
  128.         }
  129.         // build the query this way, that the root, which has no parent (parentId=0)
  130.         // and no previous (prevId=0) is in first place (in case prevId is given)
  131.         $query sprintf("SELECT * FROM %s %s ORDER BY %s",
  132.                          $this->table,
  133.                          $whereAddOn,
  134.                          $orderBy)//,prevId !!!!
  135.         if (MDB2::isError($res $this->dbh->queryAll($query))) {
  136.             // FIXXME remove print use debug mode instead
  137.             printf("ERROR - Tree::setup - %s - %s<br />"MDB2::errorMessage($res)$query);
  138.             return Tree::raiseError('TREE_ERROR_RAISE_ERROR'$res->getMessage());
  139.         }
  140.         // if the db-column names need to be mapped to different names
  141.         // FIXXME somehow we should be able to do this in the query, but I dont know
  142.         // how to select only those columns, use "as" on them and select the rest,
  143.         //without getting those columns again :-(
  144.         if ($map{
  145.             foreach ($res as $id => $aResult// map each result
  146.                 foreach ($map as $key => $columnName{
  147.                     $res[$id][$key$res[$id][$columnName];
  148.                     unset($res[$id][$columnName]);
  149.                 }
  150.             }
  151.         }
  152.  
  153.         return $res;
  154.     }
  155.  
  156.     // }}}
  157.     // {{{ add()
  158.  
  159.     /**
  160.      * adds _one_ new element in the tree under the given parent
  161.      * the values' keys given have to match the db-columns, because the
  162.      * value gets inserted in the db directly
  163.      * to add an entire node containing children and so on see 'addNode()'
  164.      *
  165.      * to be compatible with the MDB2nested, u can also give the parent and previd
  166.      * as the second and third parameter
  167.      *
  168.      * @see addNode
  169.      * @access public
  170.      * @param array $newValues this array contains the values that shall be inserted in the db-table
  171.      *                          the key for each element is the name of the column
  172.      * @return mixed either boolean false on failure or the id of the inserted row
  173.      */
  174.     function add($newValues$parentId = 0)
  175.     {
  176.         // FIXXME use $this->dbh->tableInfo to check which columns exist
  177.         // so only data for which a column exist is inserted
  178.         if ($parentId{
  179.             $newValues['parentId'$parentId;
  180.         }
  181.         $newData = array();
  182.         foreach ($newValues as $key => $value{
  183.             // quote the values, as needed for the insert
  184.             $newData[$this->_getColName($key)$this->_quote($value);
  185.         }
  186.         // use sequences to create a new id in the db-table
  187.         $nextId $this->dbh->nextId($this->table);
  188.         $query sprintf("INSERT INTO %s (%s,%s) VALUES (%s,%s)",
  189.                          $this->table ,
  190.                          $this->_getColName('id'),
  191.                          implode(','array_keys($newData)) ,
  192.                          $nextId,
  193.                          implode(','$newData));
  194.         if (MDB2::isError($res $this->dbh->exec($query))) {
  195.             // TODO raise PEAR error
  196.             printf("ERROR - Tree::add - %s - %s<br />"MDB2::errorMessage($res)$query);
  197.             return false;
  198.         }
  199.  
  200.         return $nextId;
  201.     }
  202.  
  203.     // }}}
  204.     // {{{ remove()
  205.  
  206.     /**
  207.      * removes the given node
  208.      *
  209.      * @access public
  210.      * @param  mixed $id the id of the node to be removed, or an array of id's to be removed
  211.      * @return boolean true on success
  212.      */
  213.     function remove($id)
  214.     {
  215.         // if the one to remove has children, get their id's to remove them too
  216.         if ($this->hasChildren($id)) {
  217.             $id $this->walk(array('_remove'$this)$id'array');
  218.         }
  219.         $idColumnName 'id';
  220.         $map $this->getOption('columnNameMaps');
  221.         if (isset($map['id'])) // if there are maps given
  222.                 $idColumnName $map['id'];
  223.         }
  224.  
  225.         $whereClause = "WHERE $idColumnName=$id";
  226.         if (is_array($id)) {
  227.             $whereClause = "WHERE $idColumnName in (" . implode(','$id')';
  228.         }
  229.  
  230.         $query = "DELETE FROM {$this->table$whereClause";
  231.         // print('<br />'.$query);
  232.         if (MDB2::isError($res = $this->dbh->exec($query))) {
  233.             // TODO raise PEAR error
  234.             printf("ERROR - Tree::remove - %s - %s<br>", MDB2::errormessage($res), $query);
  235.             return false;
  236.         }
  237.         // TODO if remove succeeded set prevId of the following element properly
  238.         return true;
  239.     }
  240.  
  241.     // }}}
  242.     // {{{ move()
  243.     /**
  244.      * move an entry under a given parent or behind a given entry
  245.      *
  246.      * @version 2001/10/10
  247.      * @access public
  248.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  249.      * @param integer $idToMove the id of the element that shall be moved
  250.      * @param integer $newParentId the id of the element which will be the new parent
  251.      * @param integer $newPrevId if prevId is given the element with the id idToMove
  252.      *                                        shall be moved _behind_ the element with id=prevId
  253.      *                                        if it is 0 it will be put at the beginning
  254.      *                                        if no prevId is in the DB it can be 0 too and won't bother
  255.      *                                        since it is not written in the DB anyway
  256.      * @return boolean true for success
  257.      */
  258.     function move($idToMove, $newParentId, $newPrevId = 0)
  259.     {
  260.         $idColumnName = 'id';
  261.         $parentIdColumnName = 'parentId';
  262.         $map = $this->getOption('columnNameMaps');
  263.         if (isset($map['id'])) {
  264.             $idColumnName = $map['id'];
  265.         }
  266.         if (isset($map['parentId'])) {
  267.             $parentIdColumnName = $map['parentId'];
  268.         }
  269.         // FIXXME todo: previous stuff
  270.         // set the parent in the DB
  271.         $query = "UPDATE $this->table SET $parentIdColumnName=$newParentId WHERE $idColumnName=$idToMove";
  272.         // print($query);
  273.         if (MDB2::isError($res = $this->dbh->exec($query))) {
  274.             // TODO raise PEAR error
  275.             printf("ERROR - Tree::move - %s - %s<br>", MDB2::errorMessage($res), $query);
  276.             return false;
  277.         }
  278.         // FIXXME update the prevId's of the elements where the element was moved away from and moved in
  279.         return true;
  280.     }
  281.  
  282.     // }}}
  283.     // {{{ update()
  284.     /**
  285.      * update an element in the DB
  286.      *
  287.      * @version 2002/01/17
  288.      * @access public
  289.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  290.      * @param array $newData all the new data, the key 'id' is used to
  291.                              build the 'WHERE id=' clause and all the other
  292.      *                       elements are the data to fill in the DB
  293.      * @return boolean true for success
  294.      */
  295.     function update($id, $newData)
  296.     {
  297.         // FIXXME check $this->dbh->tableInfo to see if all the columns that shall be updated
  298.         // really exist, this will also extract nextId etc. if given before writing it in the DB
  299.         // in case they dont exist in the DB
  300.         $setData = array();
  301.         foreach ($newData as $key => $value) { // quote the values, as needed for the insert
  302.             $setData[] = $this->_getColName($key'=' $this->_quote($value);
  303.         }
  304.  
  305.         $query = sprintf('UPDATE %s SET %s WHERE %s=%s',
  306.                          $this->table,
  307.                          implode(','$setData),
  308.                          $this->_getColName('id'),
  309.                          $id
  310.                 );
  311.         if (MDB2::isError($res $this->dbh->exec($query))) {
  312.             // FIXXME raise PEAR error
  313.             printf("ERROR - Tree::update - %s - %s<br>", MDB2::errormessage($res), $query);
  314.             return false;
  315.         }
  316.  
  317.         return true;
  318.     }
  319.  
  320.     // }}}
  321.     // {{{ _prepareResults()
  322.     /**
  323.      * prepare multiple results
  324.      *
  325.      * @see _prepareResult
  326.      * @access private
  327.      * @version 2002/03/03
  328.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  329.      */
  330.     function _prepareResults($results)
  331.     {
  332.         $newResults = array();
  333.         foreach ($results as $aResult) {
  334.             $newResults[] = $this->_prepareResult($aResult);
  335.         }
  336.         return $newResults;
  337.     }
  338.  
  339.     // }}}
  340.     // {{{ _prepareResult()
  341.     /**
  342.      * map back the index names to get what is expected
  343.      *
  344.      * @access private
  345.      * @version 2002/03/03
  346.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  347.      */
  348.     function _prepareResult($result)
  349.     {
  350.         $map = $this->getOption('columnNameMaps');
  351.  
  352.         if ($map{
  353.             foreach ($map as $key => $columnName) {
  354.                 $result[$key] = $result[$columnName];
  355.                 unset($result[$columnName]);
  356.             }
  357.         }
  358.         return $result;
  359.     }
  360.  
  361.     // }}}
  362.     // {{{ _getColName()
  363.     /**
  364.      * this method retreives the real column name, as used in the DB
  365.      *    since the internal names are fixed, to be portable between different
  366.      *    DB-column namings, we map the internal name to the real column name here
  367.      *
  368.      * @access private
  369.      * @version 2002/03/02
  370.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  371.      */
  372.     function _getColName($internalName)
  373.     {
  374.         if ($map = $this->getOption('columnNameMaps')) {
  375.             if (isset($map[$internalName])) {
  376.                 return $map[$internalName];
  377.             }
  378.         }
  379.         return $internalName;
  380.     }
  381.  
  382.     // }}}
  383.     // {{{ _quoteArray()
  384.     /**
  385.      * quotes all the data in this array
  386.      *
  387.      * @param array $data Array to quote
  388.      */
  389.     function _quoteArray($data)
  390.     {
  391.         foreach ($data as $key => $val) {
  392.             $data[$key] = $this->_quote($val);
  393.         }
  394.         return $data;
  395.     }
  396.  
  397.     // }}}
  398.     // {{{ _quote()
  399.     /**
  400.      * quotes all the data in this var (can be any type except object)
  401.      * @param mixed $data data to quote
  402.      */
  403.     function _quote($data)
  404.     {
  405.         switch(gettype($data)) {
  406.             case 'array':
  407.                 return $this->_quoteArray($data);
  408.                 break;
  409.             case 'boolean':
  410.                 return $this->dbh->getBooleanValue($data);
  411.                 break;
  412.             case 'double':
  413.                 return $this->dbh->getFloatValue($data);
  414.                 break;
  415.             case 'integer':
  416.                 return $this->dbh->getIntegerValue($data);
  417.                 break;
  418.             case 'string':  //if 'string' or 'unknown', quote as text
  419.             default:
  420.                 return $this->dbh->getTextValue($data);
  421.         }
  422.     }
  423.  
  424.     // }}}
  425. }

Documentation generated on Mon, 11 Mar 2019 15:02:14 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.