Removoing magic number indicies
[isso.git] / api.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Iris Studios Shared Object Framework [#]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 Datamanger API
24 * api.php
25 *
26 * @package ISSO
27 */
28
29 if (!defined('REQ_YES'))
30 {
31 /**
32 * Yes, required
33 */
34 define('REQ_YES', 1);
35
36 /**
37 * No, not required
38 */
39 define('REQ_NO', 0);
40
41 /**
42 * Auto-increasing value
43 */
44 define('REQ_AUTO', -1);
45
46 /**
47 * Set by a cusotm set_*() function
48 */
49 define('REQ_SET', 2);
50
51 /**
52 * Index for cleaning type
53 */
54 define('F_TYPE', 0);
55
56 /**
57 * Index for requirement type
58 */
59 define('F_REQ', 1);
60
61 /**
62 * Index for verification type
63 */
64 define('F_VERIFY', 2);
65 }
66
67 /**
68 * Abstract API
69 *
70 * Abstract class that is used as an API base for most common database interaction
71 * schemes. Creates a simple structure that holds data and can update, delete, and
72 * insert.
73 *
74 * @author Iris Studios, Inc.
75 * @copyright Copyright ©2002 - [#]year[#], Iris Studios, Inc.
76 * @version $Revision$
77 * @package ISSO
78 *
79 */
80 class API
81 {
82 /**
83 * Registry object
84 * @var object
85 */
86 var $registry = null;
87
88 /**
89 * Fields: used for verification and sanitization
90 * NAME => array(TYPE, REQUIRED, VERIFY METHOD (:self for self-named method))
91 * @var array
92 */
93 var $fields = array();
94
95 /**
96 * Values array: sanitized and verified field values
97 * @var array
98 */
99 var $values = array();
100
101 /**
102 * Fields that were manually set with set(), not by using set_existing()
103 * @var array
104 */
105 var $setfields = array();
106
107 /**
108 * WHERE condition
109 * @var string
110 */
111 var $condition = '';
112
113 /**
114 * The object table row; a fetched row that represents this instance
115 * @var array
116 */
117 var $objdata = array();
118
119 /**
120 * Insert ID from the insert() command
121 * @var integer
122 */
123 var $insertid = 0;
124
125 /**
126 * Constructor: cannot instantiate class directly
127 */
128 function API(&$registry)
129 {
130 if (!is_subclass_of($this, 'API'))
131 {
132 trigger_error('Cannot instantiate the API module directly', E_USER_ERROR);
133 }
134
135 if (!is_object($registry))
136 {
137 trigger_error('The passed registry is not an object', E_USER_ERROR);
138 }
139
140 $this->registry =& $registry;
141 }
142
143 /**
144 * Sets a value, sanitizes it, and verifies it
145 *
146 * @param string Field name
147 * @param mixed Value
148 * @param bool Do clean?
149 * @param bool Do verify?
150 */
151 function set($field, $value, $doclean = true, $doverify = true)
152 {
153 if (!isset($this->fields["$field"]))
154 {
155 trigger_error('Field `' . $field . '` is not valid', E_USER_WARNING);
156 return;
157 }
158
159 $this->values["$field"] = ($doclean ? $this->registry->clean($value, $this->fields["$field"][F_TYPE]) : $value);
160
161 $this->setfields[] = $field;
162
163 if (isset($this->fields["$field"][F_VERIFY]) AND $doverify)
164 {
165 if ($this->fields["$field"][F_VERIFY] == ':self')
166 {
167 $verify = $this->{"verify_$field"}($field);
168 }
169 else
170 {
171 $verify = $this->{$this->fields["$field"][F_VERIFY]}($field);
172 }
173
174 if (!$verify)
175 {
176 // <ERR:CVT>
177 trigger_error('Validation of `' . $field . '` failed', E_USER_ERROR);
178 }
179 }
180 }
181
182 /**
183 * Sets the condition to use in the WHERE clause; if not passed, then it calculates it
184 * from the REQ_AUTO field
185 *
186 * @param string WHERE conditional bit
187 */
188 function set_condition($condition = '')
189 {
190 if ($condition != '')
191 {
192 $this->condition = $condition;
193 }
194 else
195 {
196 foreach ($this->fields AS $name => $options)
197 {
198 if ($options[F_REQ] == REQ_AUTO)
199 {
200 if (!$this->values["$name"])
201 {
202 trigger_error('Cannot determine condition from the REQ_AUTO field because it is not set', E_USER_WARNING);
203 continue;
204 }
205
206 $this->condition = "$name = " . (($options[F_TYPE] == TYPE_NOCLEAN OR $options[F_TYPE] == TYPE_STR) ? "'" . $this->values["$name"] . "'" : $this->values["$name"]);
207 }
208 }
209
210 if ($this->condition == '')
211 {
212 trigger_error('No REQ_AUTO fields are present and therefore the condition cannot be created', E_USER_WARNING);
213 }
214 }
215 }
216
217 /**
218 * Sets existing data into $values where it's not already present
219 */
220 function set_existing()
221 {
222 static $run;
223 if ($run)
224 {
225 return;
226 }
227
228 $this->fetch();
229
230 foreach ($this->objdata AS $field => $value)
231 {
232 if (!isset($this->values["$field"]))
233 {
234 $this->values["$field"] = $value;
235 }
236 }
237
238 $run = true;
239 }
240
241 /**
242 * Fetches a record based on the condition
243 */
244 function fetch()
245 {
246 if ($this->condition == '')
247 {
248 trigger_error('Condition is empty: cannot fetch', E_USER_ERROR);
249 }
250
251 $actmethod = (method_exists($this, 'pre_fetch') ? $this->pre_fetch() : '');
252
253 $result = $this->registry->modules['db_mysql']->query_first("SELECT * FROM {$this->prefix}{$this->table} WHERE {$this->condition}");
254 if (!$result)
255 {
256 // <ERR:CVT>
257 trigger_error('No record was returned', E_USER_ERROR);
258 return;
259 }
260
261 $actmethod = (method_exists($this, 'post_fetch') ? $this->post_fetch() : '');
262
263 $this->objdata = $result;
264 }
265
266 /**
267 * Inserts a record in the database
268 */
269 function insert()
270 {
271 $this->verify();
272
273 $actmethod = (method_exists($this, 'pre_insert') ? $this->pre_insert() : '');
274
275 foreach ($this->setfields AS $field)
276 {
277 $fields[] = $field;
278 $values[] = (($this->fields["$field"][F_TYPE] == TYPE_NOCLEAN OR $this->fields["$field"][F_TYPE] == TYPE_STR) ? "'" . $this->values["$field"] . "'" : $this->values["$field"]);
279 }
280
281 $this->registry->modules['db_mysql']->query("INSERT INTO {$this->prefix}{$this->table} (" . implode(',', $fields) . ") VALUES (" . implode(',', $values) . ")");
282 $this->insertid = $this->registry->modules['db_mysql']->insert_id();
283
284 $actmethod = (method_exists($this, 'post_insert') ? $this->post_insert() : '');
285 }
286
287 /**
288 * Updates a record in the database using the data in $vaues
289 */
290 function update()
291 {
292 if ($this->condition == '')
293 {
294 trigger_error('Condition is empty: cannot fetch', E_USER_ERROR);
295 }
296
297 $actmethod = (method_exists($this, 'pre_update') ? $this->pre_update() : '');
298
299 foreach ($this->setfields AS $field)
300 {
301 $updates[] = "$field = " . (($this->fields["$field"][F_TYPE] == TYPE_NOCLEAN OR $this->fields["$field"][F_TYPE] == TYPE_STR) ? "'" . $this->values["$field"] . "'" : $this->values["$field"]);
302 }
303 $updates = implode(', ', $updates);
304
305 $this->registry->modules['db_mysql']->query("UPDATE {$this->prefix}{$this->table} SET $updates WHERE {$this->condition}");
306
307 $actmethod = (method_exists($this, 'post_update') ? $this->post_update() : '');
308 }
309
310 /**
311 * Deletes a record
312 */
313 function delete()
314 {
315 if ($this->condition == '')
316 {
317 trigger_error('Condition is empty: cannot fetch', E_USER_ERROR);
318 }
319
320 $this->set_existing();
321
322 $actmethod = (method_exists($this, 'pre_delete') ? $this->pre_delete() : '');
323
324 $this->registry->modules['db_mysql']->query("DELETE FROM {$this->prefix}{$this->table} WHERE {$this->condition}");
325
326 $actmethod = (method_exists($this, 'post_delete') ? $this->post_delete() : '');
327 }
328
329 /**
330 * Verifies that all required fields are set
331 */
332 function verify()
333 {
334 foreach ($this->fields AS $name => $options)
335 {
336 if ($options[F_REQ] == REQ_YES)
337 {
338 if (!isset($this->values["$name"]))
339 {
340 // <ERR:CVT>
341 trigger_error('Field `' . $name . '` was not set', E_USER_ERROR);
342 }
343 }
344 else if ($options[F_REQ] == REQ_SET)
345 {
346 $this->{"set_$name"}();
347 }
348 }
349 }
350
351 /**
352 * Verify field: not a zero value
353 */
354 function verify_nozero($field)
355 {
356 if ($this->values["$field"] == 0)
357 {
358 return false;
359 }
360
361 return true;
362 }
363
364 /**
365 * Verify field: not empty
366 */
367 function verify_noempty($field)
368 {
369 if (empty($this->values["$field"]))
370 {
371 return false;
372 }
373
374 return true;
375 }
376 }
377
378 /*=====================================================================*\
379 || ###################################################################
380 || # $HeadURL$
381 || # $Id$
382 || ###################################################################
383 \*=====================================================================*/
384 ?>