/[cvs]/nfo/php/libs/net.php.pear/Tree/Memory/DBsimple.php
ViewVC logotype

Annotation of /nfo/php/libs/net.php.pear/Tree/Memory/DBsimple.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Thu Feb 27 16:49:59 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
+ initial commit, from PEAR

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

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed