Sources for file plugins/class/activerecord.php in version 4.0 Beta 1



Click on a comment to hide it. Click here to show all comments.

/**
 * Project:     Xnyo 4: Bubbles
 * File:        plugins/class/activerecord.php
 *
 * Version:     4.0-dev
 * SVN Id:      $Id: activerecord.php 10 2007-08-01 01:02:01Z bok $
 * SVN URL:     $HeadURL:
http://svn.syd.wholesalebroadband.com.au/xnyo/trunk/plugins/class/activerecord.php $
 * Authors:     Robert Amos <bok[at]odynia.org>
 *
 * Copyright (c) 2001-2007 Robert Amos <bok[at]odynia.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/

/**
 * This class implements activerecord support in Xnyo
**/

class XnyoActiveRecord implements IteratorAggregate
{
    
// this contains the current PDOStatement object.
    
protected $statement;

    
// this contains the current XnyoDatabasePlugin object
    
protected $resource;
    
    
// this contains the last executed SQL statement
    
protected $sql;

    
// this is an array containing the results of the current view
    
protected $results = array();

    
// contains the number of elements available
    
protected $count 0;

    
// contains the current element number
    
protected $key 0;
    
    
// the parent table, if there is one
    
protected $uptable;
    
    
// all of the columns
    
public $columns = array();
    
    
// xnyo
    
private $xnyo;

    
/**
     * Get Iterator
     * 
     * This returns a XnyoActiveRecordIterator object with the current results.
     * See further down in this file
    **/
    
public function getIterator ()
    {
        return new 
XnyoActiveRecordIterator($this->results);
    }

    
/**
     * Constructor
    **/
    
public function __construct ($uptable=null)
    {
        global 
$db;
        
        
$this->xnyo $GLOBALS['xnyo_parent'];
        
        
// check to see if we have a valid database specified.
        
if (!isset($this->database) || empty($this->database))
            throw new 
XnyoError('No database specified for dbspec plugin <b>%s</b>'__CLASS__);

        
// we want to announce ourselves to the XnyoDB collector so it can establish a connection
        
if (XNYO_DEBUG$this->xnyo->d('Announcing <b>%s</b> to the XnyoDB collector object.',
get_class($this));
        
$this->resource $db->announce($this);

        
// we're being created as a reference inside another table, store that
        
if (!is_null($uptable))
            
$this->uptable $uptable;
    }
    
    
/**
     * Populate me with results of a basic query
    **/
    
public function populate ($sql=null)
    {
        
// pass the query through to the PDO object
        
if (!is_null($sql))
        {
            
$this->statement $this->resource->query($sql);

            
// store the SQL for later debug usage
            
$this->sql $sql;
        }
        elseif (!
is_object($this->statement))
            throw new 
XnyoError('Unable to populate with results of existing query because no statement
object found.'
);

        
// empty the current results
        
$this->results = array();

        
// no results?
        
if ($this->statement->rowCount() == 0)
            return 
false;

        
// for all the matching rows
        // get our child class name
        
if (class_exists(get_class($this).'Child'))
        {
            
$c = new get_class($this).'Child';
            if (
$c instanceof XnyoActiveRecordChild)
                
$class get_class($this).'Child';
            else
                throw new 
XnyoError('Attempted to use <b>%s</b> as the child row record for <b>%s</b> however it
does not extend <b>XnyoActiveRecordChild</b>.'
get_class($this).'Child'get_class($this));
        } else
            
$class 'XnyoActiveRecordChild';
        
        for (
$i 0$c $this->statement->rowCount(); $i $c$i++)
        {
            
// fetch a XnyoActiveRecordChild object with the result for this row
            
$this->results[] = $this->statement->fetchObject($class, array($this$this->xnyo));
        }

        
// total of all the results
        
$this->count count($this->results);
        return 
$this->count;
    }
    
    
/**
     * Load
     *
     * Loads the specified id into .. me
    **/
    
public function load ($id)
    {
        return 
$this->find(array('id' => $id));
    }
    
    
/**
     * Find
     *
     * Magic find method, lets you find based on anything.
    **/
    
public function find ($params=null$order=null)
    {
        
// check
        
if (is_null($params))
            
$params = array();
        else
            
$params = (array)$params;

        
// ordering on multiple fields?
        
if (is_null($order))
            
$order = array('id');
        elseif (
strpos($order',') !== false)
            
$order explode(','$order);
        else
            
$order = array($order);

        
// build the sql
        
$sql 'SELECT * FROM '.$this->table;

        
// loop over the params
        
if (count($params))
        {
            
$sql .= ' WHERE ';
            foreach (
$params as $name => $value)
            {
                if (!isset(
$this->columns[$name]))
                    throw new 
XnyoError('Unable to find based on invalid column <b>%s</b> in table <b>%s</b>.',
$name$this->table);
                if (
is_array($value) && count($value) == 2)
                    
$sql .= $name.' '.$value[0].' :'.$name.' AND ';
                else
                    
$sql .= $name.' = :'.$name.' AND ';
            }
            
$sql substr($sql0, -4);

            
// field to order by
            
foreach ($order as $o)
            {
                
$o explode(' '$o);
                if (!isset(
$this->columns[$o[0]]))
                    throw new 
XnyoError('Unable to order find results by invalid column <b>%s</b> in table
<b>%s</b>.'
$o[0], $this->table);
            }

            
$sql .= ' ORDER BY '.join(','$order);
            
            
// prepare the statement
            
$this->statement $this->resource->prepare($sql);

            
// loop the parameters.. again
            
foreach ($params as $name => $value)
            {
                
// cater for null values and columns that are not allowed to be null
                
if (is_array($value))
                    
$value $value[1];

                if (
is_null($value) || $value === '')
                {
                    
// not allowed to be null!
                    
if ($this->columns[$name]['notnull'])
                        throw new 
XnyoWarning('Unable to find rows in table <b>%s</b> where column <b>%s</b> is null
because column <b>%s</b> cannot be null.'
$this->__objs['table'], $name$name);

                    
// bind a null value
                    
$this->statement->bindValue(':'.$namenullPDO::PARAM_NULL);
                    continue;
                }

                
// bind the parameter to the sql query
                
$this->statement->bindValue(':'.$name$value,
XnyoDB::xnyoToPDOType($this->columns[$name]['type']));
            }
        } else
        {
            
// field to order by
            
foreach ($order as $o)
            {
                
$o explode(' '$o);
                if (!isset(
$this->columns[$o[0]]))
                    throw new 
XnyoError('Unable to order find results by invalid column <b>%s</b> in table
<b>%s</b>.'
$o[0], $this->table);
            }

            
$sql .= ' ORDER BY '.join(','$order);

            
// prepare to select all!
            
if (XNYO_DEBUG$this->xnyo->d('Executing query for find: <b>%s</b>'$sql);
            
$this->statement $this->resource->prepare($sql);
        }
        
        
// store the SQL for later debug usage
        
if (XNYO_DEBUG$this->xnyo->d('Executing query for find: <b>%s</b>'$sql);
        
$this->sql $sql;

        
// execute the statement and populate us with the results
        
$this->statement->execute();
        return 
$this->populate();
    }

    
/**
     * Returns the current PDO object.
     *
     * This is used by the XnyoActiveRecordChild objects to make a connection
     * back to the database.
    **/
    
public function get_resource ()
    {
        return 
$this->resource;
    }
    
    
/**
     * Retrieves the last executed SQL statement (for debugging)
    **/
    
public function get_sql ()
    {
        return 
$this->sql;
    }
    
    
/**
     * Add a empty placeholder row
    **/
    
public function add ()
    {
        
// add an empty XnyoActiveRecordChild object to the results array
        
$this->results[] = new XnyoActiveRecordChild($this$this->xnyo);

        
// point our current row at the new one
        
$this->key $this->count;

        
// update the count
        
$this->count++;

        
// is there a parent table we need to reference?
        
if (is_object($this->uptable))
        {
            
$c strtolower(get_class($this->uptable));
            
$this->results[$this->key]->$c $this->uptable->id;
        }
    }
    
    
/**
     * Clear all rows!
    **/
    
public function reset ()
    {
        unset(
$this->results);
        
$this->results = array();
        
$this->rewind();
        
$this->count 0;
    }
    
    
/**
     * Next
     * 
     * Advance us to the next row if we're not already on the last row
    **/
    
public function next ()
    {
        if ((
$this->key 1) < $this->count)
            
$this->key++;
    }

    
/**
     * Prev
     *
     * Rewinds to the previous row if we're not already on the first row
    **/
    
public function prev ()
    {
        if (
$this->key 0)
            
$this->key--;
    }

    
/**
     * Rewind
     *
     * Rewinds to the first row
    **/
    
public function rewind ()
    {
        
// take us back to the start
        
$this->key 0;
    }

    
/**
     * End
     *
     * Advances to the last row
    **/
    
public function end ()
    {
        if (
$this->count != 0)
            
$this->key $this->count 1;
    }

    
/**
     * Count
     *
     * Returns the number of result rows
    **/
    
public function count ()
    {
        return 
$this->count;
    }
    
    
/**
     * Return the row instance
    **/
    
public function current()
    {
        return 
$this->results[$this->key];
    }

    
/**
     * Accessing data at the current element
    **/
    
public function __get($var)
    {
        if (!isset(
$this->results[$this->key]) || !isset($this->results[$this->key]->$var))
            return 
null;
        return 
$this->results[$this->key]->$var;
    }

    
/**
     * Setting data at the current element
    **/
    
public function __set($var$value)
    {
        if (!isset(
$this->results[$this->key]))
            return 
false;
        return 
$this->results[$this->key]->$var $value;
    }
    
    
/**
     * Does the element exist?
    **/
    
public function __isset($var)
    {
        if (!isset(
$this->results[$this->key]))
            return 
false;
        return isset(
$this->results[$this->key]->$var);
    }

    
/**
     * Unset the element
    **/
    
public function __unset($var)
    {
        if (isset(
$this->results[$this->key]))
            unset(
$this->results[$this->key]->$var);
    }
    
    
/**
     * Export all rows
    **/
    
public function export ()
    {
        
$r = array();
        foreach (
$this->results as $var)
            
$r[] = $var->export();
        return 
$r;
    }
    
    
/**
     * Remove the column from this reference
    **/
    
public function removeColumn ($col)
    {
        if (!isset(
$this->columns) || empty($this->columns) || !isset($this->columns[$col]))
            return 
false;
        unset(
$this->columns[$col]);
        
        
// and from any results for security reasons
        
foreach ($this->results as $r)
            
$r->removeColumn($col);
    }

    
/**
     * Save Current Element
    **/
    
public function save ()
    {
        if (!isset(
$this->results[$this->key]))
            return 
false;
        return 
$this->results[$this->key]->save();
    }

    
/**
     * Save all
    **/
    
public function saveAll ()
    {
        foreach (
$this->results as $v)
            
$v->save();
    }

    
/**
     * Any other method call
    **/
    
public function __call ($func$args)
    {
        
$func strtolower($func);

        
// check to see if the method they're calling is set_<column>
        
foreach ($this->columns as $name => $value)
            if (
$func == 'set'.$name || $func == 'set_'.$name)
                
$this->results[$this->key]->$name $args[0];
    }
}

/**
 * XnyoActiveRecordIterator
 *
 * Allows you to use foreach() on the XnyoActiveRecord-based object. Each XnyoActiveRecordChild
 * object is independant of the parent one, see XnyoActiveRecordChild below.
**/
class XnyoActiveRecordIterator implements Iterator
{
    private 
$results = array();
    private 
$key 0;
    private 
$count 0;
    
    
/**
     * Store the results in an internal array
    **/
    
public function __construct ($results)
    {
        
$this->results $results;
        
$this->count count($this->results);
    }
    
    
/**
     * Rewind
     *
     * Rewinds us to the first row
    **/
    
public function rewind ()
    {
        
$this->key 0;
    }
    
    
/**
     * Valid
     *
     * Returns whether the current row exists
    **/
    
public function valid ()
    {
        return 
$this->key $this->count;
    }
    
    
/**
     * Key
     *
     * Returns the current row number
    **/
    
public function key ()
    {
        return 
$this->key;
    }
    
    
/**
     * Current
     * 
     * Returns the contents of the current row
    **/
    
public function current ()
    {
        return 
$this->results[$this->key];
    }
    
    
/**
     * Next
     * 
     * Advances to the next row
    **/
    
public function next ()
    {
        
$this->key++;
    }
}

/**
 * XnyoActiveRecordChild
 *
 * Our self-contained object representing a row
**/
class XnyoActiveRecordChild
{
    
// store data outside of the table results
    
private $__objs = array();

    public function 
__construct ($parent$xnyo)
    {
        
/**
         * Store references to the parent object so we can use
         * it to communicate with the database
        **/
        
$this->__objs['parent'] = $parent;
        
$this->__objs['xnyo'] = $xnyo;
        
$this->__objs['table'] = $parent->table;
        
$this->__objs['database'] = $parent->database;

        
// initialise the array, if its not already been done
        
if (!isset($this->__objs['result']) || !is_array($this->__objs['result']))
            
$this->__objs['result'] = array();

        
// Relationships with other tables
        
if (isset($this->__objs['parent']->has_many))
        {
            
// strtolower() all references, for ease of comparison later
            
if (is_array($this->__objs['parent']->has_many))
                foreach (
$this->__objs['parent']->has_many as $k => $v)
                    
$this->__objs['parent']->has_many[$k] = strtolower($v);
            else
                
$this->__objs['parent']->has_many strtolower($this->__objs['parent']->has_many);

            
// create the blank array
            
$this->__objs['has_many'] = array();
        }

        
// Has One
        
if (isset($this->__objs['parent']->has_one))
        {
            
// strtolower() all references, for ease of comparison later
            
if (is_array($this->__objs['parent']->has_one))
                foreach (
$this->__objs['parent']->has_one as $k => $v)
                    
$this->__objs['parent']->has_one[$k] = strtolower($v);
            else
                
$this->__objs['parent']->has_one strtolower($this->__objs['parent']->has_one);

            
// create the blank array
            
$this->__objs['has_one'] = array();
        }

        
// Belongs To
        
if (isset($this->__objs['parent']->belongs_to))
        {
            
// strtolower() all references, for ease of comparison later
            
if (is_array($this->__objs['parent']->belongs_to))
                foreach (
$this->__objs['parent']->belongs_to as $k => $v)
                    
$this->__objs['parent']->belongs_to[$k] = strtolower($v);
            else
                
$this->__objs['parent']->belongs_to strtolower($this->__objs['parent']->belongs_to);

            
// create the blank array
            
$this->__objs['belongs_to'] = array();
        }


        
// Keep a copy of the original result for comparison
        
$this->__objs['orig'] = array();

        
// populate the original result
        
$this->copy_orig();
    }

    
/**
     * Copy Orig
     *
     * Take a snapshot of what our row looks like so that we can
     * compare results later on to see if it has been modified.
    **/
    
private function copy_orig()
    {
        foreach (
$this->__objs['result'] as $name => $value)
            
$this->__objs['orig'][$name] = $value;
    }

    
/**
     * Destructor
     *
     * When the object is being destroyed, check to see if we have been
     * changed. If we have, update the database before we die.
     *
     * We don't insert new rows on destruction though, they need to be
     * saved implicitely via save()
    **/
    
public function __destruct ()
    {
        
$this->save(true);
    }

    
/**
     * Save
     *
     * Saves the row (only if it has been changed). Will auto-detect
     * whether or not a row is new and insert it if appropriate.
    **/
    
public function save ($destruct=false)
    {
        
// are we a new row?
        
if (count($this->__objs['orig']) == 0)
        {
            
// we dont insert during destruct, it needs to be implicetly saved
            
if (!$destruct)
                
$this->insert();
            return 
true;
        }

        
// Lets checks to see if any of our properties have been changed.
        
$changed = array();
        foreach (
$this->__objs['parent']->columns as $name => $value)
        {
            
// we can't change the id or the objs array, obviously
            
if ($name == 'id' || $name == 'modified' || $name == 'created')
                continue;

            
// check changed first..
            
if ($this->__objs['result'][$name] != $this->__objs['orig'][$name])
            {
                
// is this one null?
                
if ((!isset($this->__objs['result'][$name]) || $this->__objs['result'][$name] === null ||
$this->__objs['result'][$name] === '') && $this->__objs['parent']->columns[$name]['notnull'])
                {
                    
// Can't throw errors in destructors
                    
if (!$destruct)
                        throw new 
XnyoError('Unable to update row <b>%s</b> in table <b>%s</b> because column
<b>%s</b> cannot be null.'
$this->id$this->__objs['table'], $name);
                    
$this->__objs['xnyo']->storage->error->raise(new XnyoError('Unable to update row <b>%s</b> in
table <b>%s</b> because column <b>%s</b> cannot be null.'
$this->id$this->__objs['table'],
$name));
                } elseif (!isset(
$this->__objs['result'][$name]) || $this->__objs['result'][$name] === null ||
$this->__objs['result'][$name] === '')
                    
$changed[$name] = null;
                else
                    
$changed[$name] = $this->__objs['result'][$name];
            }
        }
        
        
// has anything changed?
        
if (count($changed) > 0)
            
$this->update($changed);

        
// save all our related rows too
        
if (isset($this->__objs['has_many']) && is_array($this->__objs['has_many']))
            foreach (
$this->__objs['has_many'] as $r)
                
$r->save();
        if (isset(
$this->__objs['has_one']) && is_array($this->__objs['has_one']))
            foreach (
$this->__objs['has_one'] as $r)
                
$r->save();
        if (isset(
$this->__objs['belongs_to']) && is_array($this->__objs['belongs_to']))
            foreach (
$this->__objs['belongs_to'] as $r)
                
$r->save();
    }
    
    
/**
     * Remove a column from reference
    **/
    
public function removeColumn ($col)
    {
        if (isset(
$this->__objs['result'][$col]))
            unset(
$this->__objs['result'][$col]);
        if (isset(
$this->__objs['orig'][$col]))
            unset(
$this->__objs['orig'][$col]);
    }
    
    
/**
     * Export the row using a stdClass
    **/
    
public function export ()
    {
        
$r = new stdClass;
        foreach (
$this->__objs['parent']->columns as $c => $v)
            if (!isset(
$this->__objs['result'][$c]))
                
$r->$c null;
            else
                
$r->$c $this->__objs['result'][$c];
        return 
$r;
    }

    
/**
     * Update a row
    **/
    
protected function update ($values)
    {
        
// Build up the SQL query
        
$sql 'UPDATE '.$this->__objs['table'].' SET ';

        
// show which ones have changed
        
foreach ($values as $name => $value)
            
$sql .= $name ' = :'.$name.', ';

        
// and add the modified field
        
if (isset($this->__objs['parent']->columns['modified']))
            
$sql .= 'modified = '.time().', ';

        
// trim off any extra ", "'s
        
$sql substr($sql0, -2);

        
// and append our WHERE clause.
        
$sql .= ' WHERE id = '.$this->id;

        
// get a reference to the PDO object so we can talk to the database
        
$res $this->__objs['parent']->get_resource();

        
// PDO::prepare() the query
        
$statement $res->prepare($sql);

        
// bind our parameters
        
foreach ($values as $name => $value)
        {
            if (
$value === null || $value === '')
            {
                
$statement->bindValue(':'.$namenullPDO::PARAM_NULL);
                continue;
            }
            
$statement->bindValue(':'.$name$value,
XnyoDB::xnyoToPDOType($this->__objs['parent']->columns[$name]['type']));
        }

        
// execute the query
        
if ($statement->execute())
            
// make a snapshot of the current state of the row
            
$this->copy_orig();
    }
    
    
/**
     * Insert a new row
    **/
    
protected function insert ()
    {
        
$sql 'INSERT INTO '.$this->__objs['table'].' (';
        foreach (
$this->__objs['parent']->columns as $name => $value)
        {
            if (
$name == 'id')
                continue;

            
$names[] = $name;
            
$values[] = ':'.$name;
        }
        
$sql .= join(', '$names).') VALUES ('.join(', '$values).')';

        
// get a reference to the PDO object so we can talk to the database
        
$res $this->__objs['parent']->get_resource();

        
// PDO::prepare() the query
        
$statement $res->prepare($sql);

        
// bind our parameters
        
foreach ($this->__objs['parent']->columns as $name => $value)
        {
            if (
$name == 'id')
                continue;

            
// cater for created/modified fields
            
if (($name == 'created' || $name == 'modified') &&
$this->__objs['parent']->columns[$name]['type'] == XnyoDB::INT)
            {
                
$statement->bindValue(':'.$nametime(),
XnyoDB::xnyoToPDOType($this->__objs['parent']->columns[$name]['type']));
                continue;
            }

            
// cater for null values and columns that are not allowed to be null
            
if (!isset($this->__objs['result'][$name]) || $this->__objs['result'][$name] === null ||
$this->__objs['result'][$name] == '')
            {
                
// not allowed to be null!
                
if ($this->__objs['parent']->columns[$name]['notnull'])
                    throw new 
XnyoWarning('Unable to insert row in table <b>%s</b> because column <b>%s</b> cannot
be null.'
$this->__objs['table'], $name);

                
// bind a null value
                
$statement->bindValue(':'.$namenullPDO::PARAM_NULL);
                continue;
            }

            
// bind the parameter to the sql query
            
$statement->bindValue(':'.$name$this->__objs['result'][$name],
XnyoDB::xnyoToPDOType($this->__objs['parent']->columns[$name]['type']));
        }

        
// execute the query
        
if ($statement->execute())
        {
            if (isset(
$this->__objs['parent']->columns['id']))
                
$this->id $res->lastInsertId($this->__objs['table']);
            
$this->copy_orig();
        }
    }
    

    
/**
     * Get a column from the row
    **/
    
public function __get ($var)
    {
        
// relations - has_many
        
if (isset($this->__objs['parent']->has_many))
        {
            
// is this a from a table we've loaded before?
            
if (isset($this->__objs['has_many'][$var]))
                return 
$this->__objs['has_many'][$var];

            
// is it a valid has_many?
            
if ((is_array($this->__objs['parent']->has_many) && in_array(strtolower($var),
$this->__objs['parent']->has_many)) || $this->__objs['parent']->has_many === $var)
            {

                
// yep, load up a new class for that table
                
$this->__objs['has_many'][$var] = new $var($this->__objs['parent']);

                
// populate it with all rows that have their class column as my id
                // eg. if im a 'person' object ill find all rows with person = my_id
                
$this->__objs['has_many'][$var]->find(array(strtolower(get_class($this->__objs['parent'])) =>
$this->id));

                
// return resulting object
                
return $this->__objs['has_many'][$var];
            }
        }

        
// relations - has_one
        
if (isset($this->__objs['parent']->has_one))
        {
            
// is this from a table we've loaded before?
            
if (isset($this->__objs['has_one'][$var]))
                return 
$this->__objs['has_one'][$var];

            
// is it a valid has_one?
            
if ((is_array($this->__objs['parent']->has_one) && in_array(strtolower($var),
$this->__objs['parent']->has_one)) || $this->__objs['parent']->has_one === $var)
            {
                
// yep, load up a new class for that table.
                
$this->__objs['has_one'][$var] = new $var($this->__objs['parent']);

                
// populate it with all the rows that reference me
                
$this->__objs['has_one'][$var]->find(array(strtolower(get_class($this->__objs['parent'])) =>
$this->id), null1);

                
// return the object
                
return $this->__objs['has_one'][$var];
            }
        }
        
        
// relations - belongs_to
        
if (isset($this->__objs['parent']->belongs_to))
        {
            
// is this from a table we've loaded before?
            
if (isset($this->__objs['belongs_to'][$var]))
                return 
$this->__objs['belongs_to'][$var];

            
// is it a valid belongs_to?
            
if ((is_array($this->__objs['parent']->belongs_to) && in_array(strtolower($var),
$this->__objs['parent']->belongs_to)) || $this->__objs['parent']->belongs_to === $var)
            {
                
// yep, load up a new class for that table.
                
$this->__objs['belongs_to'][$var] = new $var($this->__objs['parent']);

                
// populate it with the row i have listed for that table
                
$this->__objs['belongs_to'][$var]->load($this->__objs['result'][$var]);

                
// return the object
                
return $this->__objs['belongs_to'][$var];
            }
        }

        
// check to see if this column exists in this table
        
if (!isset($this->__objs['parent']->columns[$var]['type']) ||
!isset(
$this->__objs['result'][$var]))
            return 
null;

        
// return the column data
        
return $this->__objs['result'][$var];
    }

    
/**
     * Set a column in a row
    **/
    
public function __set ($var$value)
    {
        
// the constructor hasn't fired yet, meaning that this is a PDO::fetchObject filling contents
        
if (!isset($this->__objs['parent']))
            return 
$this->__objs['result'][$var] = $value;

        
// does this column exist?
        
if (!isset($this->__objs['parent']->columns[$var]))
            throw new 
XnyoError('Unable to set column <b>%s</b> of row in table <b>%s</b> as column does not
exist.'
$var$this->__objs['table']);
        
        
// filter it
        
$type $this->__objs['parent']->columns[$var]['type'];
        if (!
in_array($typeget_class_methods('XnyoInput')))
            throw new 
XnyoError('Unable to set column <b>%s</b> of row in table <b>%s</b> because specified
column type <b>%s</b> cannot be filtered.'
$var$this->__objs['table'], $type);
        return 
$this->__objs['result'][$var] = XnyoInput::$type($value);
    }
    
    
/**
     * Does the column exist?
    **/
    
public function __isset ($var)
    {
        return isset(
$this->__objs['parent']->columns[$var]) || $this->is_relation($var);
    }

    
/**
     * Is the variable being accessed a relationship?
    **/
    
private function is_relation ($var)
    {
        
// for niceness
        
$var strtolower($var);

        
// is it a belongs_to reference?
        
if (isset($this->__objs['parent']->belongs_to))
        {
            if (
is_array($this->__objs['parent']->belongs_to) && in_array($var,
$this->__objs['parent']->belongs_to))
                return 
true;
            if (!
is_array($this->__objs['parent']->belongs_to) && $this->__objs['parent']->belongs_to ==
$var)
                return 
true;
        }

        
// what about a has_many reference?
        
if (isset($this->__objs['parent']->has_many))
        {
            if (
is_array($this->__objs['parent']->has_many) && in_array($var,
$this->__objs['parent']->has_many))
                return 
true;
            if (!
is_array($this->__objs['parent']->has_many) && $this->__objs['parent']->has_many == $var)
                return 
true;
        }

        
// or a has_one reference?
        
if (isset($this->has_one))
        {
            if (
is_array($this->__objs['parent']->has_one) && in_array($var,
$this->__objs['parent']->has_one))
                return 
true;
            if (!
is_array($this->__objs['parent']->has_one) && $this->__objs['parent']->has_one == $var)
                return 
true;
        }
        return 
false;
    }
    
    
/**
     * Set the column to null
    **/
    
public function __unset ($var)
    {
        
$this->__objs['result'][$var] = null;
    }

    
/**
     * Any other method call
    **/
    
public function __call ($func$args)
    {
        
$func strtolower($func);

        
// check to see if the method they're calling is set_<column>
        
foreach ($this->__objs['parent']->columns as $name => $value)
            if (
$func == 'set'.$name || $func == 'set_'.$name)
                
$this->$name $args[0];
    }
}


Website is Copyright © Odynia.org 2000-2005 - Xnyo is released under a BSD license.