Allow fetching of enumerated rows instead of assoc
[isso.git] / db.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # app [#]version[#]
5 || # Copyright ©2002-[#]year[#] Iris Studios, Inc.
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Abstract Database Layer
24 * db.php
25 *
26 * @package ISSO
27 */
28
29 /**
30 * Abstract Database Layer
31 *
32 * This class provides an abstract template for all RDBMS layers. All
33 * ISSO abstraction layers should inherit this class. It provides error
34 * reporting, SQL analysis, and general connection functionality.
35 *
36 * Constants:
37 * [required] ISSO_DB_LAYER - The name of the DB layer module used in the application
38 *
39 * @author Iris Studios, Inc.
40 * @copyright Copyright ©2002 - [#]year[#], Iris Studios, Inc.
41 * @version $Revision$
42 * @package ISSO
43 *
44 */
45 class DB_Abstract
46 {
47 /**
48 * Framework registry object
49 * @var object
50 * @access protected
51 */
52 var $registry = null;
53
54 /**
55 * Determines whether or not errors should be shown
56 * @var bool
57 * @access public
58 */
59 var $showerrors = true;
60
61 /**
62 * Current error number
63 * @var integer
64 * @access protected
65 */
66 var $errnum = 0;
67
68 /**
69 * Description of current error
70 * @var string
71 * @access protected
72 */
73 var $errstr = '';
74
75 /**
76 * Currend open MySQL connexion
77 * @var resource
78 * @access protected
79 */
80 var $dblink = null;
81
82 /**
83 * Current query ID
84 * @var integer
85 * @access protected
86 */
87 var $result = null;
88
89 /**
90 * Current query string
91 * @var string
92 * @access protected
93 */
94 var $querystr = '';
95
96 /**
97 * History of all executed queryies
98 * @var array
99 * @access protected
100 */
101 var $history = array();
102
103 /**
104 * Command mapping list
105 * @var array
106 * @access protected
107 */
108 var $commands = array(
109 'pconnect' => '%server %user %password %database',
110 'connect' => '%server %user %password %database',
111 'query' => '%link %query',
112 'error_num' => '%link',
113 'error_str' => '%link',
114 'escape_string' => '%link %string',
115 'fetch_assoc' => '%result',
116 'fetch_row' => '%result',
117 'fetch_object' => '%result',
118 'free_result' => '%result',
119 'insert_id' => '%link',
120 'num_rows' => '%result',
121 'affected_rows' => '%result'
122 );
123
124 // ###################################################################
125 /**
126 * Constructor
127 */
128 function __construct(&$registry)
129 {
130 $this->registry =& $registry;
131
132 // because ivars and call_user_func() are conspiring against us...
133 foreach ($this->commands AS $key => $string)
134 {
135 if (strpos($string, '$this->') !== false)
136 {
137 $this->commands["$key"] = array($this, str_replace('$this->', '', $string));
138 }
139 }
140 }
141
142 // ###################################################################
143 /**
144 * (PHP 4) Constructor
145 */
146 function DB_Abstract(&$registry)
147 {
148 $this->__construct($registry);
149 }
150
151 // ###################################################################
152 /**
153 * Initializes the class and all subclasses under a common package name
154 *
155 * @access protected
156 *
157 * @return string The package name
158 */
159 function init_as_package()
160 {
161 if (!defined('ISSO_DB_LAYER'))
162 {
163 define('ISSO_DB_LAYER', get_class($this));
164 trigger_error('ISSO_DB_LAYER was defined automatically by DB::init_as_package(). Define the constant yourself to remove this warning', E_USER_WARNING);
165 }
166
167 return 'db';
168 }
169
170 // ###################################################################
171 /**
172 * Connect to a the specified database
173 *
174 * @access public
175 *
176 * @param string Server name
177 * @param string User name
178 * @param string Password
179 * @param string Database name
180 * @param bool Use p-connect?
181 *
182 * @return bool Result of connect
183 */
184 function connect($server, $user, $password, $database, $pconnect)
185 {
186 $this->registry->check_isso_fields(get_class($this));
187
188 if ($this->dblink == false)
189 {
190 $this->dblink = call_user_func(($pconnect ? $this->commands['pconnect'] : $this->commands['connect']), $server, $user, $password, $database);
191
192 if ($this->dblink == false)
193 {
194 $this->error('DB-Link == false, cannot connect');
195 return false;
196 }
197
198 return true;
199 }
200 }
201
202 // ###################################################################
203 /**
204 * Send a query to the open database link
205 *
206 * @access public
207 *
208 * @param string Query string
209 *
210 * @return integer Result
211 */
212 function query($string)
213 {
214 $this->querystr = $string;
215 $this->result = call_user_func($this->commands['query'], $this->dblink, $string);
216 $this->history[] = $string;
217
218 if (defined('ISSO_SHOW_QUERIES_LIVE'))
219 {
220 if (constant('ISSO_SHOW_QUERIES_LIVE'))
221 {
222 print($this->querystr . '<hr />');
223 }
224 }
225
226 if (!$this->result)
227 {
228 $this->error('Invalid SQL query');
229 }
230
231 return $this->result;
232 }
233
234 // ###################################################################
235 /**
236 * Escape a string (depending on character set, if supported)
237 *
238 * @access public
239 *
240 * @param string String to be escaped
241 *
242 * @return string Escaped string
243 */
244 function escape_string($string)
245 {
246 return call_user_func($this->commands['escape_string'], $this->dblink, $string);
247 }
248
249 // ###################################################################
250 /**
251 * Fetch the query result as an array
252 *
253 * @access public
254 *
255 * @param integer Result
256 * @param bool Return an associative array?
257 *
258 * @return array A row of the query result
259 */
260 function fetch_array($result, $assoc = true)
261 {
262 return call_user_func($this->commands[ ($assoc ? 'fetch_assoc' : 'fetch_row') ], $result);
263 }
264
265 // ###################################################################
266 /**
267 * Fetch the query result as an object
268 *
269 * @access public
270 *
271 * @param integer Result
272 *
273 * @return object An object with the query result
274 */
275 function fetch_object($result)
276 {
277 return call_user_func($this->commands['fetch_object'], $result);
278 }
279
280 // ###################################################################
281 /**
282 * Send a query and return the first row of the results
283 *
284 * @access public
285 *
286 * @param string Query string
287 * @param string Result return function (in the database layer)
288 *
289 * @return mixed Results in variable formats
290 */
291 function query_first($string, $callback = 'fetch_array')
292 {
293 $resource = $this->query($string);
294 $return = $this->$callback($resource);
295 $this->free_result($resource);
296 return $return;
297 }
298
299 // ###################################################################
300 /**
301 * Free the current query result
302 *
303 * @access public
304 *
305 * @param integer Result
306 */
307 function free_result($result)
308 {
309 call_user_func($this->commands['free_result'], $result);
310 $this->result = null;
311 $this->querystr = '';
312 }
313
314 // ###################################################################
315 /**
316 * Fetch the unique ID of the record just inserted
317 *
318 * @access public
319 *
320 * @return integer Insert-ID
321 */
322 function insert_id()
323 {
324 return call_user_func($this->commands['insert_id'], $this->dblink);
325 }
326
327 // ###################################################################
328 /**
329 * Fetch the number of rows in the result
330 *
331 * @access public
332 *
333 * @param integer Result
334 *
335 * @return integer Number of rows
336 */
337 function num_rows($result)
338 {
339 return call_user_func($this->commands['num_rows'], $result);
340 }
341
342 // ###################################################################
343 /**
344 * Fetch the number of rows affected by the query
345 *
346 * @access public
347 *
348 * @param integer Result
349 *
350 * @return integer Number of affected rows
351 */
352 function affected_rows($result)
353 {
354 return call_user_func($this->commands['affected_rows'], $result);
355 }
356
357 // ###################################################################
358 /**
359 * Error wrapper for ISSO->message()
360 *
361 * @access protected
362 *
363 * @param string User defined error message
364 */
365 function error($message)
366 {
367 if ($this->showerrors)
368 {
369 if ($this->dblink)
370 {
371 $this->errnum = call_user_func($this->commands['error_num'], $this->dblink);
372 $this->errstr = call_user_func($this->commands['error_str'], $this->dblink);
373 }
374
375 $style['code'] = 'font-family: \'Courier New\', Courier, mono; font-size: 11px;';
376
377 $message_prepped = "<blockquote>\n<p>";
378 $message_prepped .= "\n\t&raquo; <strong>Query:</strong>\n<br /> <pre style=\"$style[code]\">" . htmlspecialchars($this->querystr) ."</pre>\n<br />";
379 $message_prepped .= "\n\t&raquo; <strong>Error Number:</strong> <span style=\"$style[code]\">" . $this->errnum . "</span>\n<br />";
380 $message_prepped .= "\n\t&raquo; <strong>Error Message:</strong> <span style=\"$style[code]\">" . $this->errstr . "</span>\n<br />";
381 $message_prepped .= "\n\t&raquo; <strong>Additional Notes:</strong> <span style=\"$style[code]\">" . $message . "</span>\n<br />";
382 $message_prepped .= "\n\t&raquo; <strong>File:</strong> <span style=\"$style[code]\">" . $_SERVER['PHP_SELF'] . "</span>\n";
383 $message_prepped .= "\n</p>\n</blockquote>";
384
385 $this->registry->message('Database Error in `<em>' . $this->registry->application . '</em>`', $message_prepped, 3);
386 exit;
387 }
388 }
389 }
390
391 /*=====================================================================*\
392 || ###################################################################
393 || # $HeadURL$
394 || # $Id$
395 || ###################################################################
396 \*=====================================================================*/
397 ?>