array(TYPE, REQUIRED, VERIFY METHOD (:self for self-named method)) * @var array */ var $fields = array(); /** * Values array: sanitized and verified field values * @var array */ var $values = array(); /** * Fields that were manually set with set(), not by using set_existing() * @var array */ var $setfields = array(); /** * WHERE condition * @var string */ var $condition = ''; /** * The object table row; a fetched row that represents this instance * @var array */ var $objdata = array(); /** * Insert ID from the insert() command * @var integer */ var $insertid = 0; /** * Pre- and post-action method stoppers * @var array */ var $norunners = array(); /** * Constructor: cannot instantiate class directly */ function __construct(&$registry) { if (!is_subclass_of($this, 'API')) { trigger_error('Cannot instantiate the API module directly', E_USER_ERROR); } if (!is_object($registry)) { trigger_error('The passed registry is not an object', E_USER_ERROR); } $this->registry =& $registry; } /** * (PHP 4) Constructor */ function API(&$registry) { $this->__construct($registry); } /** * Constructs an error for the error handler to receive * * @param string Error message */ function error($message) { call_user_func(APIError(), $message); } /** * Sets a value, sanitizes it, and verifies it * * @access public * * @param string Field name * @param mixed Value * @param bool Do clean? * @param bool Do verify? */ function set($field, $value, $doclean = true, $doverify = true) { if (!isset($this->fields["$field"])) { trigger_error('Field `' . $field . '` is not valid', E_USER_WARNING); return; } $this->values["$field"] = ($doclean ? $this->registry->clean($value, $this->fields["$field"][F_TYPE]) : $value); $this->setfields["$field"] = $field; if (isset($this->fields["$field"][F_VERIFY]) AND $doverify) { if ($this->fields["$field"][F_VERIFY] == ':self') { $verify = $this->{"verify_$field"}($field); } else { $verify = $this->{$this->fields["$field"][F_VERIFY]}($field); } if (!$verify) { $this->error(sprintf($this->registry->modules['localize']->string('Validation of %1$s failed'), $field)); } } } /** * Sets the condition to use in the WHERE clause; if not passed, then it calculates it * from the REQ_AUTO field * * @access public * * @param string WHERE conditional bit */ function set_condition($condition = '') { if ($condition != '') { $this->condition = $condition; } else { foreach ($this->fields AS $name => $options) { if ($options[F_REQ] == REQ_AUTO) { if (!$this->values["$name"]) { trigger_error('Cannot determine condition from the REQ_AUTO field because it is not set', E_USER_WARNING); continue; } $this->condition = "$name = " . (($options[F_TYPE] == TYPE_NOCLEAN OR $options[F_TYPE] == TYPE_STR OR $options[F_TYPE] == TYPE_STRUN) ? "'" . $this->values["$name"] . "'" : $this->values["$name"]); } } if ($this->condition == '') { trigger_error('No REQ_AUTO fields are present and therefore the condition cannot be created', E_USER_WARNING); } } } /** * Sets existing data into $values where it's not already present * * @access public */ function set_existing() { static $run; if ($run) { return; } $this->fetch(); foreach ($this->objdata AS $field => $value) { if (!isset($this->values["$field"])) { $this->values["$field"] = $value; } } $run = true; } /** * Fetches a record based on the condition * * @access public */ function fetch() { if ($this->condition == '') { trigger_error('Condition is empty: cannot fetch', E_USER_ERROR); } $this->run_action_method('pre_fetch'); $result = $this->registry->modules['db_mysql']->query_first("SELECT * FROM {$this->prefix}{$this->table} WHERE {$this->condition}"); if (!$result) { $this->error($this->registry->modules['localize']->string('No records were returned')); return; } $this->run_action_method('post_fetch'); $this->objdata = $result; } /** * Inserts a record in the database * * @access public */ function insert() { $this->verify(); $this->run_action_method('pre_insert'); foreach ($this->setfields AS $field) { $fields[] = $field; $values[] = (($this->fields["$field"][F_TYPE] == TYPE_NOCLEAN OR $this->fields["$field"][F_TYPE] == TYPE_STR OR $this->fields["$field"][F_TYPE] == TYPE_STRUN) ? "'" . $this->values["$field"] . "'" : $this->values["$field"]); } $this->registry->modules['db_mysql']->query("INSERT INTO {$this->prefix}{$this->table} (" . implode(',', $fields) . ") VALUES (" . implode(',', $values) . ")"); $this->insertid = $this->registry->modules['db_mysql']->insert_id(); $this->run_action_method('post_insert'); } /** * Updates a record in the database using the data in $vaues * * @access public */ function update() { if ($this->condition == '') { trigger_error('Condition is empty: cannot fetch', E_USER_ERROR); } $this->run_action_method('pre_update'); foreach ($this->setfields AS $field) { $updates[] = "$field = " . (($this->fields["$field"][F_TYPE] == TYPE_NOCLEAN OR $this->fields["$field"][F_TYPE] == TYPE_STR OR $this->fields["$field"][F_TYPE] == TYPE_STRUN) ? "'" . $this->values["$field"] . "'" : $this->values["$field"]); } $updates = implode(', ', $updates); $this->registry->modules['db_mysql']->query("UPDATE {$this->prefix}{$this->table} SET $updates WHERE {$this->condition}"); $this->run_action_method('post_update'); } /** * Deletes a record * * @access public */ function delete() { if ($this->condition == '') { trigger_error('Condition is empty: cannot fetch', E_USER_ERROR); } $this->set_existing(); $this->run_action_method('pre_delete'); $this->registry->modules['db_mysql']->query("DELETE FROM {$this->prefix}{$this->table} WHERE {$this->condition}"); $this->run_action_method('post_delete'); } /** * Verifies that all required fields are set * * @access private */ function verify() { foreach ($this->fields AS $name => $options) { if ($options[F_REQ] == REQ_YES) { if (!isset($this->values["$name"])) { $this->error(sprintf($this->registry->modules['localize']->string('Required field %1$s was not set'), $name)); } } else if ($options[F_REQ] == REQ_SET) { $this->{"set_$name"}(); } } } /** * Runs a pre- or post-action method for database commands * * @access private * * @param string Action to run */ function run_action_method($method) { if (in_array($method, $this->norunners)) { return; } $actmethod = (method_exists($this, $method) ? $this->$method() : ''); } /** * Verify field: not a zero value * * @access protected */ function verify_nozero($field) { if ($this->values["$field"] == 0) { return false; } return true; } /** * Verify field: not empty * * @access protected */ function verify_noempty($field) { if (empty($this->values["$field"])) { return false; } return true; } } /** * Setter and getter method for the API error reporting * system. Passing a name will cause the set, no arguments * will cause the get. * * @access public * * @param mixed Method name in callable form * * @return mixed Method name in callable form */ function APIError($new = null) { static $caller; if ($new !== null) { $caller = $new; } return $caller; } /*=====================================================================*\ || ################################################################### || # $HeadURL$ || # $Id$ || ################################################################### \*=====================================================================*/ ?>