<?php 
/** 
 * This file contains the DBColumn class. 
 *  
 * @author Gonzalo Chumillas <[email protected]> 
 * @package database 
 */ 
 
require_once dirname(__DIR__) . "/database/exceptions/column-not-editable-db-exception.php"; 
require_once dirname(__DIR__) . "/database/db-query.php"; 
require_once dirname(__DIR__) . "/database/db-table.php"; 
 
/** 
 * class DBColumn 
 * @package database 
 */ 
class DBColumn {    
    /** 
     * Query object. 
     * @var DBColumn 
     */ 
    private $query; 
     
    /** 
     * Column table. 
     * @var DBTable 
     */ 
    private $table = NULL; 
     
    /** 
     * Column name. 
     * @var string 
     */ 
    private $name = ""; 
     
    /** 
     * Column aliases. 
     * @var array[string] 
     */ 
    private $aliases = array(); 
     
    /** 
     * Column value. 
     * @var string 
     */ 
    private $value = ""; 
     
    /** 
     * Column default value. 
     * @var string 
     */ 
    private $default_value = ""; 
     
    /** 
     * Column links. 
     * @var array[DBColumn] 
     */ 
    private $links = array(); 
     
    /** 
     * Has value changed? 
     * @var boolean 
     */ 
    private $has_changed = FALSE; 
     
    /** 
     * Has a default value? 
     * @var boolean 
     */ 
    private $has_default_value = FALSE; 
     
    /** 
     * Is accessible? 
     * @var boolean 
     */ 
    private $accessible = FALSE; 
     
    /** 
     * @param DBQuery $query 
     * @param String $table Table alias. 
     * @param String $name Column name. 
     */ 
    public function __construct($query, $table, $name) { 
        $this->query = $query; 
        $this->name = $name; 
         
        if (!util::isEmpty($table)) { 
            $this->table = $this->query->registerTable($table); 
            $this->table->registerColumn($this); 
        } 
    } 
     
    public function reset() { 
        $this->value = ""; 
        $this->has_changed = FALSE; 
    } 
     
    /** 
     * Gets the column table. 
     * @return DBTable 
     */ 
    public function getTable() { 
        return $this->table; 
    } 
     
    /** 
     * Gets column name. 
     * @return string 
     */ 
    public function getName() { 
        return $this->name; 
    } 
     
    /** 
     * Gets full name of the column. 
     * The full name is composed by the 'table alias' and the 'column name' separated by a dot. 
     * For example: table.field It identifies the column in the query in a unique way. 
     * @return string 
     */ 
    public function getFullName() { 
        $ret = ""; 
         
        if ($this->isComputed()) { 
            if (count($this->aliases) > 0) { 
                // first alias 
                $ret = $this->aliases[0]; 
            } else { 
                // column position 
                $columns = $this->query->getColumns(); 
                $ret = "" . array_search($this, $columns, TRUE); 
            } 
        } else { 
            // table alias 
            $table_alias = $this->table->getAlias(); 
            if (preg_match("/\W+/", $table_alias)) { 
                $table_alias = "`$table_alias`"; 
            } 
             
            // column name 
            $column_name = $this->name; 
            if (preg_match("/\W+/", $column_name)) { 
                $column_name = "`$column_name`"; 
            } 
             
            $ret = "$table_alias.$column_name"; 
        } 
         
        return $ret; 
    } 
     
    /** 
     * Gets value. 
     * @return string 
     */ 
    public function getValue() { 
        $ret = ""; 
         
        if ($this->hasValue()) { 
            $ret = $this->value; 
        } else 
        if ($this->hasOriginalValue()) { 
            $ret = $this->getOriginalValue(); 
        } 
         
        return $ret; 
    } 
     
    /** 
     * Sets column value. 
     * @param string $value 
     * @throws ColumnNotEditableDBException if the column is not editable. 
     */ 
    public function setValue($value, &$stack = array()) { 
        if ($this->isComputed()) { 
            throw new ColumnNotEditableDBException($this, ColumnNotEditableDBException::COMPUTED); 
        } 
         
        $table = $this->table; 
        $pk = $table->getPrimaryKey(); 
        $this->value = $value; 
        $this->has_changed = TRUE; 
        array_push($stack, $this); 
         
        if ($pk == NULL) { 
            $column = $this->getFullName(); 
            $table = $this->table->getAlias(); 
            throw new ColumnNotEditableDBException($this, ColumnNotEditableDBException::PK_MISSING); 
        } else { 
            $pk_value = $pk->getOriginalValue(); 
             
            if (util::isEmpty($pk_value) && !$pk->isEditable()) { 
                throw new ColumnNotEditableDBException($this, ColumnNotEditableDBException::PK_NOT_EDITABLE); 
            } 
        } 
         
        foreach ($this->links as $link) { 
            if (array_search($link, $stack, TRUE) === FALSE) { 
                if (!$link->isEditable()) { 
                    throw new ColumnNotEditableDBException($this, ColumnNotEditableDBException::LINK_NOT_EDITABLE); 
                } 
                 
                $link->setValue($value, $stack); 
            } 
        } 
    } 
     
    /** 
     * Deletes column value. 
     */ 
    public function delValue() { 
        $this->value = ""; 
        $this->has_changed = FALSE; 
    } 
     
    /** 
     * Gets default value. 
     * @return string 
     */ 
    public function getDefaultValue() { 
        return $this->default_value; 
    } 
     
    /** 
     * Sets default value. 
     * @param string $value 
     */ 
    public function setDefaultValue($value) { 
        $this->default_value = $value; 
        $this->has_default_value = TRUE; 
    } 
     
    /** 
     * Gets original value. 
     * @return string 
     */ 
    public function getOriginalValue() { 
        return $this->query->getOriginalValue($this); 
    } 
     
    /** 
     * Sets original column value. 
     * @param string $value 
     */ 
    public function setOriginalValue($value) { 
        $this->query->setOriginalValue($this, $value); 
    } 
     
    /** 
     * Adds a column link. 
     * @param DBColumn $column 
     */ 
    public function registerLink($column) { 
        if (array_search($column, $this->links, TRUE) === FALSE) { 
            array_push($this->links, $column); 
        } 
    } 
     
    /** 
     * Is column accessible? 
     * @return boolean 
     */ 
    public function isAccessible() { 
        return $this->accessible; 
    } 
     
    /** 
     * Sets column accessibility. 
     * @param boolean $accessible 
     */ 
    public function setAccessible($accessible) { 
        $this->accessible = $accessible; 
    } 
     
    /** 
     * Is the column editable? 
     * A column is editable when: 
     *      2. it is not a constant (it hasn't a default value) 
     *      3. its parent table has primary key 
     *      4. all its linked columns are editable 
     * @param object $column 
     * @return boolean 
     */ 
    public function isEditable(&$stack = array()) { 
        $ret = !$this->isComputed() && $this->table->getPrimaryKey() != NULL; 
         
        if ($ret) { 
            array_push($stack, $this); 
             
            foreach ($this->links as $link) { 
                if (array_search($link, $stack, TRUE) === FALSE) { 
                    if (!$link->isEditable($stack)) { 
                        $ret = FALSE; 
                        break; 
                    } 
                } 
            } 
        } 
         
        return $ret; 
    } 
     
    /** 
     * Is primary key? 
     * @param boolean 
     */ 
    public function isPrimaryKey() { 
        return $this->is_primary_key; 
    } 
     
    /** 
     * Is a computed column? 
     */ 
    public function isComputed() { 
        return $this->table == NULL; 
    } 
     
    /** 
     * Marks as primary key. 
     * @param boolean $value 
     */ 
    public function setPrimaryKey($value) { 
        $this->is_primary_key = $value; 
         
        if (!$this->isComputed() && $this->is_primary_key) { 
            $this->table->setPrimaryKey($this); 
        } 
    } 
     
    /** 
     * Has changed the value? 
     * @return boolean 
     */ 
    public function hasChanged() { 
        return $this->has_changed; 
    } 
     
    /** 
     * Has a value? 
     * @return boolean 
     */ 
    public function hasValue() { 
        return $this->hasChanged(); 
    } 
     
    /** 
     * Has a default value? 
     * @return boolean 
     */ 
    public function hasDefaultValue() { 
        return $this->has_default_value; 
    } 
     
    /** 
     * Has an original value? 
     * @return boolean 
     */ 
    public function hasOriginalValue() { 
        return $this->query->hasOriginalValue($this); 
    } 
     
    /** 
     * Adds an alias. 
     * @param string $alias 
     */ 
    public function registerAlias($alias) { 
        $alias = trim($alias); 
         
        if (strlen($alias) > 0 && array_search($alias, $this->aliases) === FALSE) { 
            array_push($this->aliases, $alias); 
        } 
    } 
     
    /** 
     * Checks if it has an alias. 
     * @param string $alias 
     * @return boolean 
     */ 
    public function isAlias($alias) { 
        return array_search($alias, $this->aliases) !== FALSE; 
    } 
     
    /** 
     * String representation of the column. 
     * @return string 
     */ 
    public function __toString() { 
        return $this->getFullName(); 
    } 
} 
 
 |