diff --git a/lib/Doctrine/Record/Filter.php b/lib/Doctrine/Record/Filter.php new file mode 100644 index 000000000..35fe861bb --- /dev/null +++ b/lib/Doctrine/Record/Filter.php @@ -0,0 +1,233 @@ +. + */ + +/** + * Doctrine_Record_Filter + * Filters and prepares the record data + * + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @package Doctrine + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision: 1298 $ + */ +class Doctrine_Record_Filter +{ + /** + * @var Doctrine_Record $_record the record object this filter belongs to + */ + protected $_record; + /** + * constructor + * + * @param Doctrine_Record $_record the record object this filter belongs to + */ + public function __construct(Doctrine_Record $record) + { + $this->_record = $record; + } + /** + * getRecord + * + * @return Doctrine_Record $_record the record object this filter belongs to + */ + public function getRecord() + { + return $this->_record; + } + /** + * cleanData + * this method does several things to records internal data + * + * 1. It unserializes array and object typed columns + * 2. Uncompresses gzip typed columns + * 3. Gets the appropriate enum values for enum typed columns + * 4. Initializes special null object pointer for null values (for fast column existence checking purposes) + * + * + * example: + * + * $data = array("name"=>"John","lastname"=> null, "id" => 1,"unknown" => "unknown"); + * $names = array("name", "lastname", "id"); + * $data after operation: + * $data = array("name"=>"John","lastname" => Object(Doctrine_Null)); + * + * here column 'id' is removed since its auto-incremented primary key (read-only) + * + * @throws Doctrine_Record_Exception if unserialization of array/object typed column fails or + * if uncompression of gzip typed column fails + * + * @return integer + */ + public function cleanData() + { + $tmp = $this->_data; + + $this->_data = array(); + + $count = 0; + + foreach ($this->_table->getColumnNames() as $name) { + $type = $this->_table->getTypeOf($name); + + if ( ! isset($tmp[$name])) { + $this->_data[$name] = self::$null; + } else { + switch ($type) { + case 'array': + case 'object': + if ($tmp[$name] !== self::$null) { + if (is_string($tmp[$name])) { + $value = unserialize($tmp[$name]); + + if ($value === false) + throw new Doctrine_Record_Exception('Unserialization of ' . $name . ' failed.'); + } else { + $value = $tmp[$name]; + } + $this->_data[$name] = $value; + } + break; + case 'gzip': + if ($tmp[$name] !== self::$null) { + $value = gzuncompress($tmp[$name]); + + if ($value === false) + throw new Doctrine_Record_Exception('Uncompressing of ' . $name . ' failed.'); + + $this->_data[$name] = $value; + } + break; + case 'enum': + $this->_data[$name] = $this->_table->enumValue($name, $tmp[$name]); + break; + default: + $this->_data[$name] = $tmp[$name]; + } + $count++; + } + } + + return $count; + } + /** + * prepareIdentifiers + * prepares identifiers for later use + * + * @param boolean $exists whether or not this record exists in persistent data store + * @return void + */ + private function prepareIdentifiers($exists = true) + { + switch ($this->_table->getIdentifierType()) { + case Doctrine_Identifier::AUTO_INCREMENT: + case Doctrine_Identifier::SEQUENCE: + $name = $this->_table->getIdentifier(); + + if ($exists) { + if (isset($this->_data[$name]) && $this->_data[$name] !== self::$null) { + $this->_id[$name] = $this->_data[$name]; + } + } + + unset($this->_data[$name]); + + break; + case Doctrine_Identifier::NORMAL: + $this->_id = array(); + $name = $this->_table->getIdentifier(); + + if (isset($this->_data[$name]) && $this->_data[$name] !== self::$null) { + $this->_id[$name] = $this->_data[$name]; + } + break; + case Doctrine_Identifier::COMPOSITE: + $names = $this->_table->getIdentifier(); + + foreach ($names as $name) { + if ($this->_data[$name] === self::$null) { + $this->_id[$name] = null; + } else { + $this->_id[$name] = $this->_data[$name]; + } + } + break; + } + } + /** + * getPrepared + * + * returns an array of modified fields and values with data preparation + * adds column aggregation inheritance and converts Records into primary key values + * + * @param array $array + * @return array + */ + public function getPrepared(array $array = array()) { + $a = array(); + + if (empty($array)) { + $array = $this->_modified; + } + foreach ($array as $k => $v) { + $type = $this->_table->getTypeOf($v); + + if ($this->_data[$v] === self::$null) { + $a[$v] = null; + continue; + } + + switch ($type) { + case 'array': + case 'object': + $a[$v] = serialize($this->_data[$v]); + break; + case 'gzip': + $a[$v] = gzcompress($this->_data[$v],5); + break; + case 'boolean': + $a[$v] = $this->getTable()->getConnection()->convertBooleans($this->_data[$v]); + break; + case 'enum': + $a[$v] = $this->_table->enumIndex($v,$this->_data[$v]); + break; + default: + if ($this->_data[$v] instanceof Doctrine_Record) + $this->_data[$v] = $this->_data[$v]->getIncremented(); + + $a[$v] = $this->_data[$v]; + } + } + $map = $this->_table->inheritanceMap; + foreach ($map as $k => $v) { + $old = $this->get($k, false); + + if ((string) $old !== (string) $v || $old === null) { + $a[$k] = $v; + $this->_data[$k] = $v; + } + } + + return $a; + } +}