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.2 2007/08/11 21:34:27 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.  
  141.         // Account for the fact the by default MDB2 lower cases field names
  142.         foreach ($res as $index => $value{
  143.             $res[$index]['parentId'$res[$index]['parentid'];
  144.             unset$res[$index]['parentid');
  145.         }
  146.  
  147.         // if the db-column names need to be mapped to different names
  148.         // FIXXME somehow we should be able to do this in the query, but I dont know
  149.         // how to select only those columns, use "as" on them and select the rest,
  150.         //without getting those columns again :-(
  151.         if ($map{
  152.             foreach ($res as $id => $aResult// map each result
  153.                 foreach ($map as $key => $columnName{
  154.                     $res[$id][$key$res[$id][$columnName];
  155.                     unset($res[$id][$columnName]);
  156.                 }
  157.             }
  158.         }
  159.  
  160.         return $res;
  161.     }
  162.  
  163.     // }}}
  164.     // {{{ add()
  165.  
  166.     /**
  167.      * adds _one_ new element in the tree under the given parent
  168.      * the values' keys given have to match the db-columns, because the
  169.      * value gets inserted in the db directly
  170.      * to add an entire node containing children and so on see 'addNode()'
  171.      *
  172.      * to be compatible with the MDB2nested, u can also give the parent and previd
  173.      * as the second and third parameter
  174.      *
  175.      * @see addNode
  176.      * @access public
  177.      * @param array $newValues this array contains the values that shall be inserted in the db-table
  178.      *                          the key for each element is the name of the column
  179.      * @return mixed either boolean false on failure or the id of the inserted row
  180.      */
  181.     function add($newValues$parentId = 0)
  182.     {
  183.         // FIXXME use $this->dbh->tableInfo to check which columns exist
  184.         // so only data for which a column exist is inserted
  185.         if ($parentId{
  186.             $newValues['parentId'$parentId;
  187.         }
  188.         $newData = array();
  189.         foreach ($newValues as $key => $value{
  190.             // quote the values, as needed for the insert
  191.             $newData[$this->_getColName($key)$this->_quote($value);
  192.         }
  193.         // use sequences to create a new id in the db-table
  194.         $nextId $this->dbh->nextId($this->table);
  195.         $query sprintf("INSERT INTO %s (%s,%s) VALUES (%s,%s)",
  196.                          $this->table ,
  197.                          $this->_getColName('id'),
  198.                          implode(','array_keys($newData)) ,
  199.                          $nextId,
  200.                          implode(','$newData));
  201.         if (MDB2::isError($res $this->dbh->exec($query))) {
  202.             // TODO raise PEAR error
  203.             printf("ERROR - Tree::add - %s - %s<br />"MDB2::errorMessage($res)$query);
  204.             return false;
  205.         }
  206.  
  207.         return $nextId;
  208.     }
  209.  
  210.     // }}}
  211.     // {{{ remove()
  212.  
  213.     /**
  214.      * removes the given node
  215.      *
  216.      * @access public
  217.      * @param  mixed $id the id of the node to be removed, or an array of id's to be removed
  218.      * @return boolean true on success
  219.      */
  220.     function remove($id)
  221.     {
  222.         // if the one to remove has children, get their id's to remove them too
  223.         if ($this->hasChildren($id)) {
  224.             $id $this->walk(array('_remove'$this)$id'array');
  225.         }
  226.         $idColumnName 'id';
  227.         $map $this->getOption('columnNameMaps');
  228.         if (isset($map['id'])) // if there are maps given
  229.                 $idColumnName $map['id'];
  230.         }
  231.  
  232.         $whereClause = "WHERE $idColumnName=$id";
  233.         if (is_array($id)) {
  234.             $whereClause = "WHERE $idColumnName in (" . implode(','$id')';
  235.         }
  236.  
  237.         $query = "DELETE FROM {$this->table$whereClause";
  238.         // print('<br />'.$query);
  239.         if (MDB2::isError($res = $this->dbh->exec($query))) {
  240.             // TODO raise PEAR error
  241.             printf("ERROR - Tree::remove - %s - %s<br>", MDB2::errormessage($res), $query);
  242.             return false;
  243.         }
  244.         // TODO if remove succeeded set prevId of the following element properly
  245.         return true;
  246.     }
  247.  
  248.     // }}}
  249.     // {{{ move()
  250.     /**
  251.      * move an entry under a given parent or behind a given entry
  252.      *
  253.      * @version 2001/10/10
  254.      * @access public
  255.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  256.      * @param integer $idToMove the id of the element that shall be moved
  257.      * @param integer $newParentId the id of the element which will be the new parent
  258.      * @param integer $newPrevId if prevId is given the element with the id idToMove
  259.      *                                        shall be moved _behind_ the element with id=prevId
  260.      *                                        if it is 0 it will be put at the beginning
  261.      *                                        if no prevId is in the DB it can be 0 too and won't bother
  262.      *                                        since it is not written in the DB anyway
  263.      * @return boolean true for success
  264.      */
  265.     function move($idToMove, $newParentId, $newPrevId = 0)
  266.     {
  267.         $idColumnName = 'id';
  268.         $parentIdColumnName = 'parentId';
  269.         $map = $this->getOption('columnNameMaps');
  270.         if (isset($map['id'])) {
  271.             $idColumnName = $map['id'];
  272.         }
  273.         if (isset($map['parentId'])) {
  274.             $parentIdColumnName = $map['parentId'];
  275.         }
  276.         // FIXXME todo: previous stuff
  277.         // set the parent in the DB
  278.         $query = "UPDATE $this->table SET $parentIdColumnName=$newParentId WHERE $idColumnName=$idToMove";
  279.         // print($query);
  280.         if (MDB2::isError($res = $this->dbh->exec($query))) {
  281.             // TODO raise PEAR error
  282.             printf("ERROR - Tree::move - %s - %s<br>", MDB2::errorMessage($res), $query);
  283.             return false;
  284.         }
  285.         // FIXXME update the prevId's of the elements where the element was moved away from and moved in
  286.         return true;
  287.     }
  288.  
  289.     // }}}
  290.     // {{{ update()
  291.     /**
  292.      * update an element in the DB
  293.      *
  294.      * @version 2002/01/17
  295.      * @access public
  296.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  297.      * @param array $newData all the new data, the key 'id' is used to
  298.                              build the 'WHERE id=' clause and all the other
  299.      *                       elements are the data to fill in the DB
  300.      * @return boolean true for success
  301.      */
  302.     function update($id, $newData)
  303.     {
  304.         // FIXXME check $this->dbh->tableInfo to see if all the columns that shall be updated
  305.         // really exist, this will also extract nextId etc. if given before writing it in the DB
  306.         // in case they dont exist in the DB
  307.         $setData = array();
  308.         foreach ($newData as $key => $value) { // quote the values, as needed for the insert
  309.             $setData[] = $this->_getColName($key'=' $this->_quote($value);
  310.         }
  311.  
  312.         $query = sprintf('UPDATE %s SET %s WHERE %s=%s',
  313.                          $this->table,
  314.                          implode(','$setData),
  315.                          $this->_getColName('id'),
  316.                          $id
  317.                 );
  318.         if (MDB2::isError($res $this->dbh->exec($query))) {
  319.             // FIXXME raise PEAR error
  320.             printf("ERROR - Tree::update - %s - %s<br>", MDB2::errormessage($res), $query);
  321.             return false;
  322.         }
  323.  
  324.         return true;
  325.     }
  326.  
  327.     // }}}
  328.     // {{{ _prepareResults()
  329.     /**
  330.      * prepare multiple results
  331.      *
  332.      * @see _prepareResult
  333.      * @access private
  334.      * @version 2002/03/03
  335.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  336.      */
  337.     function _prepareResults($results)
  338.     {
  339.         $newResults = array();
  340.         foreach ($results as $aResult) {
  341.             $newResults[] = $this->_prepareResult($aResult);
  342.         }
  343.         return $newResults;
  344.     }
  345.  
  346.     // }}}
  347.     // {{{ _prepareResult()
  348.     /**
  349.      * map back the index names to get what is expected
  350.      *
  351.      * @access private
  352.      * @version 2002/03/03
  353.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  354.      */
  355.     function _prepareResult($result)
  356.     {
  357.         $map = $this->getOption('columnNameMaps');
  358.  
  359.         if ($map{
  360.             foreach ($map as $key => $columnName) {
  361.                 $result[$key] = $result[$columnName];
  362.                 unset($result[$columnName]);
  363.             }
  364.         }
  365.         return $result;
  366.     }
  367.  
  368.     // }}}
  369.     // {{{ _getColName()
  370.     /**
  371.      * this method retreives the real column name, as used in the DB
  372.      *    since the internal names are fixed, to be portable between different
  373.      *    DB-column namings, we map the internal name to the real column name here
  374.      *
  375.      * @access private
  376.      * @version 2002/03/02
  377.      * @author Wolfram Kriesing <wolfram@kriesing.de>
  378.      */
  379.     function _getColName($internalName)
  380.     {
  381.         if ($map = $this->getOption('columnNameMaps')) {
  382.             if (isset($map[$internalName])) {
  383.                 return $map[$internalName];
  384.             }
  385.         }
  386.         return $internalName;
  387.     }
  388.  
  389.     // }}}
  390.     // {{{ _quoteArray()
  391.     /**
  392.      * quotes all the data in this array
  393.      *
  394.      * @param array $data Array to quote
  395.      */
  396.     function _quoteArray($data)
  397.     {
  398.         foreach ($data as $key => $val) {
  399.             $data[$key] = $this->_quote($val);
  400.         }
  401.         return $data;
  402.     }
  403.  
  404.     // }}}
  405.     // {{{ _quote()
  406.     /**
  407.      * quotes all the data in this var (can be any type except object)
  408.      * @param mixed $data data to quote
  409.      */
  410.     function _quote($data)
  411.     {
  412.         switch(gettype($data)) {
  413.             case 'array':
  414.                 return $this->_quoteArray($data);
  415.                 break;
  416.             case 'boolean':
  417.                 return $this->dbh->quote($data);
  418.                 break;
  419.             case 'double':
  420.                 return $this->dbh->quote($data);
  421.                 break;
  422.             case 'integer':
  423.                 return $this->dbh->quote($data);
  424.                 break;
  425.             case 'string':  //if 'string' or 'unknown', quote as text
  426.             default:
  427.                 return $this->dbh->quote($data);
  428.         }
  429.     }
  430.  
  431.     // }}}
  432. }

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