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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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