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

Source for file MDBsimple.php

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

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