/[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.2 - (hide annotations)
Wed Jul 7 02:49:21 2004 UTC (20 years, 2 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -1 lines
updated to Tree-0.2.4

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

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