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

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