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

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