2006-05-30 12:42:10 +04:00
< ? php
2006-08-24 20:34:05 +04:00
/*
2006-07-26 21:09:00 +04:00
* $Id $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL . For more information , see
* < http :// www . phpdoctrine . com >.
*/
2006-09-22 01:09:58 +04:00
Doctrine :: autoload ( 'Doctrine_Access' );
2006-05-30 12:42:10 +04:00
/**
* Doctrine_Record
2006-07-26 21:09:00 +04:00
* All record classes should inherit this super class
*
* @ author Konsta Vesterinen
* @ license LGPL
* @ package Doctrine
2006-05-30 12:42:10 +04:00
*/
2006-08-24 20:34:05 +04:00
2006-06-05 13:57:53 +04:00
abstract class Doctrine_Record extends Doctrine_Access implements Countable , IteratorAggregate , Serializable {
2006-05-30 12:42:10 +04:00
/**
* STATE CONSTANTS
*/
/**
* DIRTY STATE
* a Doctrine_Record is in dirty state when its properties are changed
*/
const STATE_DIRTY = 1 ;
/**
* TDIRTY STATE
* a Doctrine_Record is in transient dirty state when it is created and some of its fields are modified
* but it is NOT yet persisted into database
*/
const STATE_TDIRTY = 2 ;
/**
* CLEAN STATE
* a Doctrine_Record is in clean state when all of its properties are loaded from the database
* and none of its properties are changed
*/
const STATE_CLEAN = 3 ;
/**
* PROXY STATE
* a Doctrine_Record is in proxy state when its properties are not fully loaded
*/
const STATE_PROXY = 4 ;
/**
* NEW TCLEAN
* a Doctrine_Record is in transient clean state when it is created and none of its fields are modified
*/
const STATE_TCLEAN = 5 ;
/**
* DELETED STATE
* a Doctrine_Record turns into deleted state when it is deleted
*/
const STATE_DELETED = 6 ;
/**
2006-06-03 13:10:43 +04:00
* CALLBACK CONSTANTS
2006-05-30 12:42:10 +04:00
*/
2006-06-03 13:10:43 +04:00
/**
* RAW CALLBACK
*
* when using a raw callback and the property if a record is changed using this callback the
* record state remains untouched
*/
const CALLBACK_RAW = 1 ;
/**
* STATE - WISE CALLBACK
*
* state - wise callback means that when callback is used and the property is changed the
* record state is also updated
*/
const CALLBACK_STATEWISE = 2 ;
2006-05-30 12:42:10 +04:00
/**
* @ var object Doctrine_Table $table the factory that created this data access object
*/
protected $table ;
/**
2006-07-10 13:18:09 +04:00
* @ var integer $id the primary keys of this object
2006-05-30 12:42:10 +04:00
*/
2006-07-22 03:22:15 +04:00
protected $id = array ();
2006-05-30 12:42:10 +04:00
/**
* @ var array $data the record data
*/
2006-07-22 03:22:15 +04:00
protected $data = array ();
2006-05-30 12:42:10 +04:00
/**
* @ var integer $state the state of this record
* @ see STATE_ * constants
*/
2006-06-01 15:58:05 +04:00
protected $state ;
/**
* @ var array $modified an array containing properties that have been modified
*/
2006-07-22 03:22:15 +04:00
protected $modified = array ();
2006-05-30 12:42:10 +04:00
/**
* @ var array $collections the collections this record is in
*/
2006-07-22 03:22:15 +04:00
private $collections = array ();
2006-05-30 12:42:10 +04:00
/**
2006-07-22 03:22:15 +04:00
* @ var array $references an array containing all the references
2006-05-30 12:42:10 +04:00
*/
2006-07-22 03:22:15 +04:00
private $references = array ();
2006-05-30 12:42:10 +04:00
/**
2006-07-22 03:22:15 +04:00
* @ var array $originals an array containing all the original references
2006-05-30 12:42:10 +04:00
*/
2006-07-22 03:22:15 +04:00
private $originals = array ();
/**
* @ var array $filters
*/
private $filters = array ();
2006-05-30 12:42:10 +04:00
/**
* @ var integer $index this index is used for creating object identifiers
*/
2006-07-22 03:22:15 +04:00
private static $index = 1 ;
2006-05-30 12:42:10 +04:00
/**
2006-06-08 14:20:30 +04:00
* @ var Doctrine_Null $null a Doctrine_Null object used for extremely fast
2006-06-07 13:07:38 +04:00
* null value testing
2006-05-30 12:42:10 +04:00
*/
private static $null ;
/**
* @ var integer $oid object identifier
*/
private $oid ;
/**
* constructor
* @ param Doctrine_Table $table a Doctrine_Table object
2006-08-22 03:19:15 +04:00
* @ throws Doctrine_Connection_Exception if object is created using the new operator and there are no
* open connections
2006-05-30 12:42:10 +04:00
*/
public function __construct ( $table = null ) {
if ( isset ( $table ) && $table instanceof Doctrine_Table ) {
$this -> table = $table ;
$exists = ( ! $this -> table -> isNewEntry ());
} else {
2006-08-22 03:19:15 +04:00
$this -> table = Doctrine_Manager :: getInstance () -> getCurrentConnection () -> getTable ( get_class ( $this ));
2006-05-30 12:42:10 +04:00
$exists = false ;
}
2006-08-22 03:19:15 +04:00
// Check if the current connection has the records table in its registry
2006-05-30 12:42:10 +04:00
// If not this is record is only used for creating table definition and setting up
// relations.
2006-08-22 03:19:15 +04:00
if ( $this -> table -> getConnection () -> hasTable ( $this -> table -> getComponentName ())) {
2006-05-30 12:42:10 +04:00
$this -> oid = self :: $index ;
2006-07-22 04:58:07 +04:00
2006-05-30 12:42:10 +04:00
self :: $index ++ ;
$keys = $this -> table -> getPrimaryKeys ();
if ( ! $exists ) {
// listen the onPreCreate event
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onPreCreate ( $this );
} else {
// listen the onPreLoad event
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onPreLoad ( $this );
}
// get the data array
$this -> data = $this -> table -> getData ();
2006-06-05 14:24:14 +04:00
2006-05-30 12:42:10 +04:00
// get the column count
$count = count ( $this -> data );
// clean data array
2006-06-01 15:58:05 +04:00
$this -> cleanData ();
2006-05-30 12:42:10 +04:00
$this -> prepareIdentifiers ( $exists );
if ( ! $exists ) {
2006-06-08 14:20:30 +04:00
2006-06-01 15:58:05 +04:00
if ( $count > 0 )
2006-05-30 12:42:10 +04:00
$this -> state = Doctrine_Record :: STATE_TDIRTY ;
else
$this -> state = Doctrine_Record :: STATE_TCLEAN ;
2006-09-16 00:56:25 +04:00
// set the default values for this record
$this -> setDefaultValues ();
2006-05-30 12:42:10 +04:00
// listen the onCreate event
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onCreate ( $this );
} else {
$this -> state = Doctrine_Record :: STATE_CLEAN ;
if ( $count < $this -> table -> getColumnCount ()) {
$this -> state = Doctrine_Record :: STATE_PROXY ;
}
// listen the onLoad event
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onLoad ( $this );
}
2006-06-20 01:31:22 +04:00
2006-06-30 03:04:39 +04:00
$repository = $this -> table -> getRepository ();
$repository -> add ( $this );
2006-05-30 12:42:10 +04:00
}
}
/**
* initNullObject
2006-06-01 15:58:05 +04:00
*
* @ param Doctrine_Null $null
2006-05-30 12:42:10 +04:00
*/
public static function initNullObject ( Doctrine_Null $null ) {
self :: $null = $null ;
}
2006-06-01 15:58:05 +04:00
/**
* @ return Doctrine_Null
*/
public static function getNullObject () {
return self :: $null ;
}
2006-07-22 04:58:07 +04:00
/**
2006-05-30 12:42:10 +04:00
* setUp
2006-09-22 01:09:58 +04:00
* this method is used for setting up relations and attributes
* it should be implemented by child classes
*
* @ return void
2006-05-30 12:42:10 +04:00
*/
public function setUp () { }
/**
2006-09-22 01:09:58 +04:00
* getOID
2006-05-30 12:42:10 +04:00
* return the object identifier
*
* @ return integer
*/
public function getOID () {
return $this -> oid ;
}
2006-09-16 00:56:25 +04:00
/**
* setDefaultValues
* sets the default values
*
* @ param boolean $overwrite whether or not to overwrite the already set values
* @ return boolean
*/
public function setDefaultValues ( $overwrite = false ) {
if ( ! $this -> table -> hasDefaultValues ())
return false ;
foreach ( $this -> data as $column => $value ) {
$default = $this -> table -> getDefaultValueOf ( $column );
if ( $default === null )
$default = self :: $null ;
2006-09-17 19:44:10 +04:00
if ( $value === self :: $null || $overwrite ) {
2006-09-16 00:56:25 +04:00
$this -> data [ $column ] = $default ;
2006-09-17 19:44:10 +04:00
$this -> modified [] = $column ;
$this -> state = Doctrine_Record :: STATE_TDIRTY ;
}
2006-09-16 00:56:25 +04:00
}
}
2006-05-30 12:42:10 +04:00
/**
* cleanData
* modifies data array
* example :
*
2006-06-07 13:07:38 +04:00
* $data = array ( " name " => " John " , " lastname " => null , " id " => 1 , " unknown " => " unknown " );
* $names = array ( " name " , " lastname " , " id " );
2006-05-30 12:42:10 +04:00
* $data after operation :
2006-06-07 13:07:38 +04:00
* $data = array ( " name " => " John " , " lastname " => Object ( Doctrine_Null ));
*
2006-07-22 04:58:07 +04:00
* here column 'id' is removed since its auto - incremented primary key ( protected )
2006-06-18 02:46:03 +04:00
*
* @ return integer
2006-05-30 12:42:10 +04:00
*/
2006-09-20 19:46:25 +04:00
private function cleanData ( $debug = false ) {
2006-09-03 23:20:02 +04:00
$tmp = $this -> data ;
2006-06-01 15:58:05 +04:00
2006-05-30 12:42:10 +04:00
$this -> data = array ();
2006-07-22 04:58:07 +04:00
2006-06-08 14:20:30 +04:00
$count = 0 ;
2006-05-30 12:42:10 +04:00
foreach ( $this -> table -> getColumnNames () as $name ) {
2006-06-07 13:07:38 +04:00
$type = $this -> table -> getTypeOf ( $name );
2006-09-17 19:44:10 +04:00
if ( ! isset ( $tmp [ $name ])) {
$this -> data [ $name ] = self :: $null ;
2006-05-30 12:42:10 +04:00
} else {
2006-06-07 13:07:38 +04:00
switch ( $type ) :
2006-06-03 13:10:43 +04:00
case " array " :
case " object " :
2006-07-31 01:37:07 +04:00
2006-09-17 19:44:10 +04:00
if ( $tmp [ $name ] !== self :: $null ) {
if ( is_string ( $tmp [ $name ])) {
$value = unserialize ( $tmp [ $name ]);
2006-07-31 01:37:54 +04:00
2006-08-25 21:17:55 +04:00
if ( $value === false )
2006-09-03 23:20:02 +04:00
throw new Doctrine_Record_Exception ( " Unserialization of $name failed. " . var_dump ( $tmp [ $lower ], true ));
2006-08-25 21:17:55 +04:00
} else
2006-09-17 19:44:10 +04:00
$value = $tmp [ $name ];
2006-08-26 00:13:37 +04:00
2006-07-31 01:37:07 +04:00
$this -> data [ $name ] = $value ;
}
2006-06-18 02:46:03 +04:00
break ;
2006-09-20 19:46:25 +04:00
case " gzip " :
if ( $tmp [ $name ] !== self :: $null ) {
$value = gzuncompress ( $tmp [ $name ]);
2006-09-17 19:44:10 +04:00
2006-09-20 19:46:25 +04:00
if ( $value === false )
throw new Doctrine_Record_Exception ( " Uncompressing of $name failed. " );
$this -> data [ $name ] = $value ;
}
break ;
case " enum " :
2006-09-17 19:44:10 +04:00
$this -> data [ $name ] = $this -> table -> enumValue ( $name , $tmp [ $name ]);
2006-06-03 13:10:43 +04:00
break ;
default :
2006-09-17 19:44:10 +04:00
$this -> data [ $name ] = $tmp [ $name ];
2006-06-03 13:10:43 +04:00
endswitch ;
2006-06-18 02:46:03 +04:00
$count ++ ;
2006-05-30 12:42:10 +04:00
}
}
2006-07-31 01:37:07 +04:00
2006-09-20 19:46:25 +04:00
2006-06-08 14:20:30 +04:00
return $count ;
2006-05-30 12:42:10 +04:00
}
/**
2006-06-07 13:07:38 +04:00
* prepares identifiers for later use
2006-05-30 12:42:10 +04:00
*
2006-06-07 13:07:38 +04:00
* @ param boolean $exists whether or not this record exists in persistent data store
2006-05-30 12:42:10 +04:00
* @ return void
*/
private function prepareIdentifiers ( $exists = true ) {
switch ( $this -> table -> getIdentifierType ()) :
case Doctrine_Identifier :: AUTO_INCREMENT :
case Doctrine_Identifier :: SEQUENCE :
2006-06-03 13:10:43 +04:00
$name = $this -> table -> getIdentifier ();
if ( $exists ) {
2006-06-05 13:57:53 +04:00
if ( isset ( $this -> data [ $name ]) && $this -> data [ $name ] !== self :: $null )
2006-07-10 13:18:09 +04:00
$this -> id [ $name ] = $this -> data [ $name ];
2006-05-30 12:42:10 +04:00
}
2006-06-05 13:57:53 +04:00
2006-06-03 13:10:43 +04:00
unset ( $this -> data [ $name ]);
2006-05-30 12:42:10 +04:00
break ;
2006-07-27 22:31:18 +04:00
case Doctrine_Identifier :: NORMAL :
$this -> id = array ();
$name = $this -> table -> getIdentifier ();
2006-08-24 20:34:05 +04:00
2006-07-27 22:31:18 +04:00
if ( isset ( $this -> data [ $name ]) && $this -> data [ $name ] !== self :: $null )
$this -> id [ $name ] = $this -> data [ $name ];
break ;
2006-05-30 12:42:10 +04:00
case Doctrine_Identifier :: COMPOSITE :
$names = $this -> table -> getIdentifier ();
2006-07-27 22:31:18 +04:00
2006-05-30 12:42:10 +04:00
foreach ( $names as $name ) {
if ( $this -> data [ $name ] === self :: $null )
$this -> id [ $name ] = null ;
2006-07-22 04:58:07 +04:00
else
2006-05-30 12:42:10 +04:00
$this -> id [ $name ] = $this -> data [ $name ];
}
break ;
endswitch ;
}
/**
* this method is automatically called when this Doctrine_Record is serialized
*
* @ return array
*/
2006-06-05 13:57:53 +04:00
public function serialize () {
2006-05-30 12:42:10 +04:00
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onSleep ( $this );
2006-06-05 13:57:53 +04:00
$vars = get_object_vars ( $this );
2006-07-22 04:58:07 +04:00
2006-06-05 13:57:53 +04:00
unset ( $vars [ 'references' ]);
unset ( $vars [ 'collections' ]);
unset ( $vars [ 'originals' ]);
unset ( $vars [ 'table' ]);
2006-07-10 13:18:09 +04:00
$name = $this -> table -> getIdentifier ();
$this -> data = array_merge ( $this -> data , $this -> id );
2006-05-30 12:42:10 +04:00
2006-06-03 13:10:43 +04:00
foreach ( $this -> data as $k => $v ) {
2006-05-30 12:42:10 +04:00
if ( $v instanceof Doctrine_Record )
2006-06-05 23:44:31 +04:00
unset ( $vars [ 'data' ][ $k ]);
2006-06-03 13:10:43 +04:00
elseif ( $v === self :: $null ) {
2006-06-05 23:44:31 +04:00
unset ( $vars [ 'data' ][ $k ]);
2006-06-03 13:10:43 +04:00
} else {
switch ( $this -> table -> getTypeOf ( $k )) :
case " array " :
case " object " :
2006-06-05 23:44:31 +04:00
$vars [ 'data' ][ $k ] = serialize ( $vars [ 'data' ][ $k ]);
2006-06-03 13:10:43 +04:00
break ;
endswitch ;
}
2006-05-30 12:42:10 +04:00
}
2006-06-05 13:57:53 +04:00
return serialize ( $vars );
2006-05-30 12:42:10 +04:00
}
/**
* unseralize
* this method is automatically called everytime a Doctrine_Record object is unserialized
*
* @ return void
*/
2006-06-05 13:57:53 +04:00
public function unserialize ( $serialized ) {
2006-05-30 12:42:10 +04:00
$manager = Doctrine_Manager :: getInstance ();
2006-08-22 03:19:15 +04:00
$connection = $manager -> getCurrentConnection ();
2006-05-30 12:42:10 +04:00
$this -> oid = self :: $index ;
self :: $index ++ ;
2006-08-22 03:19:15 +04:00
$this -> table = $connection -> getTable ( get_class ( $this ));
2006-07-22 04:58:07 +04:00
2006-06-05 13:57:53 +04:00
$array = unserialize ( $serialized );
foreach ( $array as $name => $values ) {
$this -> $name = $values ;
}
2006-05-30 12:42:10 +04:00
$this -> table -> getRepository () -> add ( $this );
$this -> cleanData ();
2006-06-03 13:10:43 +04:00
$exists = true ;
2006-05-30 12:42:10 +04:00
2006-06-03 13:10:43 +04:00
if ( $this -> state == Doctrine_Record :: STATE_TDIRTY ||
$this -> state == Doctrine_Record :: STATE_TCLEAN )
$exists = false ;
$this -> prepareIdentifiers ( $exists );
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onWakeUp ( $this );
2006-05-30 12:42:10 +04:00
}
2006-06-05 13:57:53 +04:00
2006-05-30 12:42:10 +04:00
/**
* addCollection
* @ param Doctrine_Collection $collection
* @ param mixed $key
*/
final public function addCollection ( Doctrine_Collection $collection , $key = null ) {
if ( $key !== null ) {
2006-07-22 04:58:07 +04:00
if ( isset ( $this -> collections [ $key ]))
2006-05-30 12:42:10 +04:00
throw InvalidKeyException ();
$this -> collections [ $key ] = $collection ;
} else {
$this -> collections [] = $collection ;
}
}
/**
* getCollection
* @ param integer $key
* @ return Doctrine_Collection
*/
final public function getCollection ( $key ) {
return $this -> collections [ $key ];
}
/**
* hasCollections
* whether or not this record is part of a collection
*
* @ return boolean
*/
final public function hasCollections () {
return ( ! empty ( $this -> collections ));
}
/**
* getState
* returns the current state of the object
*
* @ see Doctrine_Record :: STATE_ * constants
* @ return integer
*/
final public function getState () {
return $this -> state ;
}
/**
2006-07-22 04:58:07 +04:00
* refresh
2006-05-30 12:42:10 +04:00
* refresh internal data from the database
*
* @ return boolean
*/
final public function refresh () {
2006-09-17 21:59:04 +04:00
$id = $this -> obtainIdentifier ();
2006-05-30 12:42:10 +04:00
if ( ! is_array ( $id ))
$id = array ( $id );
if ( empty ( $id ))
return false ;
$id = array_values ( $id );
2006-06-25 22:34:53 +04:00
$query = $this -> table -> getQuery () . " WHERE " . implode ( " = ? AND " , $this -> table -> getPrimaryKeys ()) . " = ? " ;
2006-09-16 00:56:25 +04:00
$stmt = $this -> table -> getConnection () -> execute ( $query , $id );
$this -> data = $stmt -> fetch ( PDO :: FETCH_ASSOC );
2006-05-30 12:42:10 +04:00
2006-09-03 23:20:02 +04:00
if ( ! $this -> data )
throw new Doctrine_Record_Exception ( 'Failed to refresh. Record does not exist anymore' );
2006-09-06 02:09:07 +04:00
2006-09-03 23:20:02 +04:00
$this -> data = array_change_key_case ( $this -> data , CASE_LOWER );
2006-05-30 12:42:10 +04:00
$this -> modified = array ();
2006-09-20 19:46:25 +04:00
$this -> cleanData ( true );
2006-05-30 12:42:10 +04:00
$this -> prepareIdentifiers ();
$this -> state = Doctrine_Record :: STATE_CLEAN ;
2006-05-31 02:14:50 +04:00
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onLoad ( $this );
2006-05-30 12:42:10 +04:00
return true ;
}
/**
* factoryRefresh
2006-06-18 02:46:03 +04:00
* refreshes the data from outer source ( Doctrine_Table )
*
2006-05-30 12:42:10 +04:00
* @ throws Doctrine_Exception
* @ return void
*/
final public function factoryRefresh () {
2006-07-31 01:37:07 +04:00
$this -> data = $this -> table -> getData ();
2006-07-10 13:18:09 +04:00
$old = $this -> id ;
$this -> cleanData ();
2006-05-30 12:42:10 +04:00
$this -> prepareIdentifiers ();
2006-07-10 13:18:09 +04:00
if ( $this -> id != $old )
2006-08-08 00:58:09 +04:00
throw new Doctrine_Record_Exception ( " The refreshed primary key doesn't match the one in the record memory. " , Doctrine :: ERR_REFRESH );
2006-05-30 12:42:10 +04:00
$this -> state = Doctrine_Record :: STATE_CLEAN ;
$this -> modified = array ();
2006-05-31 02:14:50 +04:00
$this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onLoad ( $this );
2006-05-30 12:42:10 +04:00
}
/**
* return the factory that created this data access object
* @ return object Doctrine_Table a Doctrine_Table object
*/
final public function getTable () {
return $this -> table ;
}
/**
* return all the internal data
* @ return array an array containing all the properties
*/
final public function getData () {
return $this -> data ;
}
2006-06-01 15:58:05 +04:00
/**
* rawGet
* returns the value of a property , if the property is not yet loaded
* this method does NOT load it
*
* @ param $name name of the property
* @ return mixed
*/
public function rawGet ( $name ) {
if ( ! isset ( $this -> data [ $name ]))
throw new InvalidKeyException ();
2006-07-22 04:58:07 +04:00
2006-09-12 14:15:58 +04:00
if ( $this -> data [ $name ] === self :: $null )
2006-06-01 15:58:05 +04:00
return null ;
return $this -> data [ $name ];
}
2006-09-12 14:15:58 +04:00
/**
* load
* loads all the unitialized properties from the database
*
* @ return boolean
*/
public function load () {
// only load the data from database if the Doctrine_Record is in proxy state
if ( $this -> state == Doctrine_Record :: STATE_PROXY ) {
if ( ! empty ( $this -> collections )) {
// delegate the loading operation to collections in which this record resides
foreach ( $this -> collections as $collection ) {
$collection -> load ( $this );
2006-09-13 01:36:36 +04:00
2006-09-12 14:15:58 +04:00
}
} else {
2006-09-13 01:36:36 +04:00
2006-09-12 14:15:58 +04:00
$this -> refresh ();
}
$this -> state = Doctrine_Record :: STATE_CLEAN ;
return true ;
}
return false ;
}
2006-05-30 12:42:10 +04:00
/**
* get
2006-07-22 04:58:07 +04:00
* returns a value of a property or a related component
2006-05-30 12:42:10 +04:00
*
2006-09-12 14:15:58 +04:00
* @ param mixed $name name of the property or related component
* @ param boolean $invoke whether or not to invoke the onGetProperty listener
* @ throws Doctrine_Exception
2006-05-30 12:42:10 +04:00
* @ return mixed
*/
2006-09-12 14:15:58 +04:00
public function get ( $name , $invoke = true ) {
$listener = $this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER );
$value = self :: $null ;
2006-09-17 19:44:10 +04:00
$lower = strtolower ( $name );
2006-09-12 14:15:58 +04:00
2006-09-17 19:44:10 +04:00
if ( isset ( $this -> data [ $lower ])) {
2006-05-30 12:42:10 +04:00
// check if the property is null (= it is the Doctrine_Null object located in self::$null)
2006-09-17 19:44:10 +04:00
if ( $this -> data [ $lower ] === self :: $null ) {
2006-09-12 14:15:58 +04:00
$this -> load ();
2006-09-13 01:36:36 +04:00
}
2006-09-17 19:44:10 +04:00
if ( $this -> data [ $lower ] === self :: $null )
2006-09-13 01:36:36 +04:00
$value = null ;
else
2006-09-17 19:44:10 +04:00
$value = $this -> data [ $lower ];
2006-05-30 12:42:10 +04:00
2006-09-13 01:36:36 +04:00
}
2006-07-22 04:58:07 +04:00
2006-06-05 13:57:53 +04:00
2006-09-12 14:15:58 +04:00
if ( $value !== self :: $null ) {
2006-09-13 01:36:36 +04:00
if ( $invoke && $name !== $this -> table -> getIdentifier ()) {
2006-09-12 14:15:58 +04:00
return $this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onGetProperty ( $this , $name , $value );
} else
return $value ;
}
2006-05-30 12:42:10 +04:00
2006-09-13 01:36:36 +04:00
2006-09-17 19:44:10 +04:00
if ( isset ( $this -> id [ $lower ]))
return $this -> id [ $lower ];
2006-09-13 01:36:36 +04:00
if ( $name === $this -> table -> getIdentifier ())
return null ;
2006-05-30 12:42:10 +04:00
if ( ! isset ( $this -> references [ $name ]))
2006-09-12 14:15:58 +04:00
$this -> loadReference ( $name );
2006-05-30 12:42:10 +04:00
return $this -> references [ $name ];
}
2006-06-09 02:11:36 +04:00
/**
* internalSet
2006-06-12 12:44:08 +04:00
*
* @ param mixed $name
* @ param mixed $value
2006-06-09 02:11:36 +04:00
*/
final public function internalSet ( $name , $value ) {
2006-08-26 00:13:37 +04:00
if ( $value === null )
$value = self :: $null ;
2006-06-09 02:11:36 +04:00
$this -> data [ $name ] = $value ;
}
2006-05-30 12:42:10 +04:00
/**
* rawSet
* doctrine uses this function internally , not recommended for developers
*
2006-09-06 02:09:07 +04:00
* rawSet () works in very same same way as set () with an exception that
2006-09-03 23:20:02 +04:00
* 1. it cannot be used for setting references
* 2. it cannot load uninitialized fields
*
2006-05-30 12:42:10 +04:00
* @ param mixed $name name of the property or reference
* @ param mixed $value value of the property or reference
*/
final public function rawSet ( $name , $value ) {
if ( $value instanceof Doctrine_Record )
2006-07-10 13:18:09 +04:00
$id = $value -> getIncremented ();
2006-05-30 12:42:10 +04:00
2006-07-10 13:18:09 +04:00
if ( isset ( $id ))
2006-05-30 12:42:10 +04:00
$value = $id ;
2006-06-01 15:58:05 +04:00
2006-05-30 12:42:10 +04:00
if ( isset ( $this -> data [ $name ])) {
if ( $this -> data [ $name ] === self :: $null ) {
if ( $this -> data [ $name ] !== $value ) {
switch ( $this -> state ) :
case Doctrine_Record :: STATE_CLEAN :
$this -> state = Doctrine_Record :: STATE_DIRTY ;
break ;
case Doctrine_Record :: STATE_TCLEAN :
$this -> state = Doctrine_Record :: STATE_TDIRTY ;
endswitch ;
}
}
if ( $this -> state == Doctrine_Record :: STATE_TCLEAN )
$this -> state = Doctrine_Record :: STATE_TDIRTY ;
2006-08-26 00:13:37 +04:00
if ( $value === null )
$value = self :: $null ;
2006-05-30 12:42:10 +04:00
$this -> data [ $name ] = $value ;
2006-06-03 13:10:43 +04:00
$this -> modified [] = $name ;
2006-05-30 12:42:10 +04:00
}
}
2006-07-27 21:51:19 +04:00
2006-05-30 12:42:10 +04:00
/**
* set
* method for altering properties and Doctrine_Record references
*
* @ param mixed $name name of the property or reference
* @ param mixed $value value of the property or reference
* @ throws InvalidKeyException
* @ throws InvalidTypeException
* @ return void
*/
public function set ( $name , $value ) {
2006-09-17 19:44:10 +04:00
$lower = strtolower ( $name );
if ( isset ( $this -> data [ $lower ])) {
2006-05-30 12:42:10 +04:00
if ( $value instanceof Doctrine_Record ) {
2006-07-10 13:18:09 +04:00
$id = $value -> getIncremented ();
2006-07-22 04:58:07 +04:00
2006-07-10 13:18:09 +04:00
if ( $id !== null )
$value = $id ;
2006-05-30 12:42:10 +04:00
}
2006-07-22 04:58:07 +04:00
2006-09-17 19:44:10 +04:00
$old = $this -> get ( $lower , false );
2006-05-30 12:42:10 +04:00
if ( $old !== $value ) {
2006-09-12 14:15:58 +04:00
// invoke the onPreSetProperty listener
2006-09-21 16:15:48 +04:00
$value = $this -> table -> getAttribute ( Doctrine :: ATTR_LISTENER ) -> onSetProperty ( $this , $name , $value );
2006-09-12 14:15:58 +04:00
2006-08-26 00:13:37 +04:00
if ( $value === null )
$value = self :: $null ;
2006-09-17 19:44:10 +04:00
$this -> data [ $lower ] = $value ;
$this -> modified [] = $lower ;
2006-05-30 12:42:10 +04:00
switch ( $this -> state ) :
case Doctrine_Record :: STATE_CLEAN :
case Doctrine_Record :: STATE_PROXY :
$this -> state = Doctrine_Record :: STATE_DIRTY ;
break ;
case Doctrine_Record :: STATE_TCLEAN :
$this -> state = Doctrine_Record :: STATE_TDIRTY ;
break ;
endswitch ;
}
} else {
// if not found, throws InvalidKeyException
2006-08-31 13:04:14 +04:00
$fk = $this -> table -> getRelation ( $name );
2006-05-30 12:42:10 +04:00
// one-to-many or one-to-one relation
2006-06-05 13:57:53 +04:00
if ( $fk instanceof Doctrine_ForeignKey ||
2006-05-30 12:42:10 +04:00
$fk instanceof Doctrine_LocalKey ) {
switch ( $fk -> getType ()) :
case Doctrine_Relation :: MANY_COMPOSITE :
case Doctrine_Relation :: MANY_AGGREGATE :
// one-to-many relation found
if ( ! ( $value instanceof Doctrine_Collection ))
2006-08-08 00:58:09 +04:00
throw new Doctrine_Record_Exception ( " Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references. " );
2006-05-30 12:42:10 +04:00
$value -> setReference ( $this , $fk );
break ;
case Doctrine_Relation :: ONE_COMPOSITE :
case Doctrine_Relation :: ONE_AGGREGATE :
// one-to-one relation found
if ( ! ( $value instanceof Doctrine_Record ))
2006-08-08 00:58:09 +04:00
throw new Doctrine_Record_Exception ( " Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record when setting one-to-one references. " );
2006-05-30 12:42:10 +04:00
if ( $fk -> getLocal () == $this -> table -> getIdentifier ()) {
$this -> references [ $name ] -> set ( $fk -> getForeign (), $this );
} else {
$this -> set ( $fk -> getLocal (), $value );
}
break ;
endswitch ;
} elseif ( $fk instanceof Doctrine_Association ) {
// join table relation found
if ( ! ( $value instanceof Doctrine_Collection ))
2006-08-08 00:58:09 +04:00
throw new Doctrine_Record_Exception ( " Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references. " );
2006-05-30 12:42:10 +04:00
}
$this -> references [ $name ] = $value ;
}
}
/**
2006-09-13 13:40:22 +04:00
* contains
2006-05-30 12:42:10 +04:00
*
* @ param string $name
* @ return boolean
*/
2006-09-13 13:40:22 +04:00
public function contains ( $name ) {
2006-05-30 12:42:10 +04:00
if ( isset ( $this -> data [ $name ]))
return true ;
if ( isset ( $this -> references [ $name ]))
return true ;
return false ;
}
/**
* @ param string $name
* @ return void
*/
public function __unset ( $name ) {
if ( isset ( $this -> data [ $name ]))
$this -> data [ $name ] = array ();
// todo: what to do with references ?
}
/**
* applies the changes made to this object into database
* this method is smart enough to know if any changes are made
* and whether to use INSERT or UPDATE statement
*
* this method also saves the related composites
*
* @ return void
*/
2006-09-22 23:23:57 +04:00
final public function save ( Doctrine_Connection $conn = null ) {
if ( $conn == null ) {
$conn = $this -> table -> getConnection ();
}
$conn -> beginTransaction ();
2006-05-30 12:42:10 +04:00
2006-09-22 23:23:57 +04:00
$saveLater = $conn -> saveRelated ( $this );
2006-05-30 12:42:10 +04:00
2006-09-22 23:23:57 +04:00
$conn -> save ( $this );
2006-05-30 12:42:10 +04:00
foreach ( $saveLater as $fk ) {
$table = $fk -> getTable ();
$alias = $this -> table -> getAlias ( $table -> getComponentName ());
if ( isset ( $this -> references [ $alias ])) {
$obj = $this -> references [ $alias ];
$obj -> save ();
}
}
// save the MANY-TO-MANY associations
$this -> saveAssociations ();
2006-07-22 04:58:07 +04:00
2006-09-22 23:23:57 +04:00
$conn -> commit ();
2006-05-30 12:42:10 +04:00
}
/**
* returns an array of modified fields and associated values
* @ return array
*/
final public function getModified () {
$a = array ();
2006-06-20 01:31:22 +04:00
foreach ( $this -> modified as $k => $v ) {
2006-05-30 12:42:10 +04:00
$a [ $v ] = $this -> data [ $v ];
}
return $a ;
}
/**
* returns an array of modified fields and values with data preparation
* adds column aggregation inheritance and converts Records into primary key values
*
* @ return array
*/
2006-06-20 01:31:22 +04:00
final public function getPrepared ( array $array = array ()) {
2006-05-30 12:42:10 +04:00
$a = array ();
2006-06-20 01:31:22 +04:00
if ( empty ( $array ))
$array = $this -> modified ;
foreach ( $array as $k => $v ) {
2006-06-03 13:10:43 +04:00
$type = $this -> table -> getTypeOf ( $v );
2006-06-07 13:07:38 +04:00
2006-09-04 10:23:38 +04:00
switch ( $type ) {
case 'array' :
case 'object' :
$a [ $v ] = serialize ( $this -> data [ $v ]);
2006-09-20 19:46:25 +04:00
break ;
case 'gzip' :
$a [ $v ] = gzcompress ( $this -> data [ $v ], 5 );
break ;
2006-09-04 10:27:27 +04:00
case 'enum' :
2006-09-04 10:23:38 +04:00
$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 ();
2006-06-03 13:10:43 +04:00
2006-09-06 02:09:07 +04:00
2006-09-04 10:23:38 +04:00
if ( $this -> data [ $v ] === self :: $null )
$a [ $v ] = null ;
else
$a [ $v ] = $this -> data [ $v ];
}
2006-05-30 12:42:10 +04:00
}
2006-06-09 02:11:36 +04:00
foreach ( $this -> table -> getInheritanceMap () as $k => $v ) {
$old = $this -> get ( $k );
if (( string ) $old !== ( string ) $v || $old === null ) {
$a [ $k ] = $v ;
$this -> data [ $k ] = $v ;
}
}
2006-05-30 12:42:10 +04:00
return $a ;
}
/**
* this class implements countable interface
* @ return integer the number of columns
*/
public function count () {
return count ( $this -> data );
}
2006-08-24 20:34:05 +04:00
/**
* alias for count ()
*/
public function getColumnCount () {
return $this -> count ();
}
2006-09-08 01:28:47 +04:00
/**
* toArray
* returns record as an array
*
* @ return array
*/
public function toArray () {
$a = array ();
foreach ( $this as $column => $value ) {
$a [ $column ] = $value ;
}
if ( $this -> table -> getIdentifierType () == Doctrine_Identifier :: AUTO_INCREMENT ) {
$i = $this -> table -> getIdentifier ();
$a [ $i ] = $this -> getIncremented ();
}
return $a ;
}
2006-08-24 20:34:05 +04:00
/**
* checks if record has data
* @ return boolean
*/
2006-08-25 19:21:23 +04:00
public function exists () {
2006-09-06 02:09:07 +04:00
return ( $this -> state !== Doctrine_Record :: STATE_TCLEAN &&
2006-08-25 19:21:23 +04:00
$this -> state !== Doctrine_Record :: STATE_TDIRTY );
2006-08-24 20:34:05 +04:00
}
/**
* method for checking existence of properties and Doctrine_Record references
* @ param mixed $name name of the property or reference
* @ return boolean
*/
public function hasRelation ( $name ) {
if ( isset ( $this -> data [ $name ]) || isset ( $this -> id [ $name ]))
return true ;
2006-09-06 02:09:07 +04:00
return $this -> table -> hasRelation ( $name );
2006-08-24 20:34:05 +04:00
}
2006-05-30 12:42:10 +04:00
/**
* getIterator
2006-06-01 15:58:05 +04:00
* @ return Doctrine_Record_Iterator a Doctrine_Record_Iterator that iterates through the data
2006-05-30 12:42:10 +04:00
*/
public function getIterator () {
2006-06-01 15:58:05 +04:00
return new Doctrine_Record_Iterator ( $this );
2006-05-30 12:42:10 +04:00
}
/**
* saveAssociations
* save the associations of many - to - many relations
* this method also deletes associations that do not exist anymore
* @ return void
*/
final public function saveAssociations () {
2006-08-31 13:04:14 +04:00
foreach ( $this -> table -> getRelations () as $fk ) :
2006-05-30 12:42:10 +04:00
$table = $fk -> getTable ();
$name = $table -> getComponentName ();
$alias = $this -> table -> getAlias ( $name );
if ( $fk instanceof Doctrine_Association ) {
switch ( $fk -> getType ()) :
case Doctrine_Relation :: MANY_COMPOSITE :
break ;
case Doctrine_Relation :: MANY_AGGREGATE :
$asf = $fk -> getAssociationFactory ();
if ( isset ( $this -> references [ $alias ])) {
$new = $this -> references [ $alias ];
if ( ! isset ( $this -> originals [ $alias ])) {
$this -> loadReference ( $alias );
}
2006-07-10 22:10:54 +04:00
$r = Doctrine_Relation :: getDeleteOperations ( $this -> originals [ $alias ], $new );
2006-05-30 12:42:10 +04:00
2006-07-10 22:10:54 +04:00
foreach ( $r as $record ) {
2006-05-30 12:42:10 +04:00
$query = " DELETE FROM " . $asf -> getTableName () . " WHERE " . $fk -> getForeign () . " = ? "
2006-06-25 22:34:53 +04:00
. " AND " . $fk -> getLocal () . " = ? " ;
2006-08-22 03:19:15 +04:00
$this -> table -> getConnection () -> execute ( $query , array ( $record -> getIncremented (), $this -> getIncremented ()));
2006-05-30 12:42:10 +04:00
}
2006-07-22 04:58:07 +04:00
2006-07-10 22:10:54 +04:00
$r = Doctrine_Relation :: getInsertOperations ( $this -> originals [ $alias ], $new );
foreach ( $r as $record ) {
2006-05-30 12:42:10 +04:00
$reldao = $asf -> create ();
$reldao -> set ( $fk -> getForeign (), $record );
$reldao -> set ( $fk -> getLocal (), $this );
$reldao -> save ();
2006-07-10 13:18:09 +04:00
2006-07-22 04:58:07 +04:00
}
2006-05-30 12:42:10 +04:00
$this -> originals [ $alias ] = clone $this -> references [ $alias ];
}
break ;
endswitch ;
2006-07-22 04:58:07 +04:00
} elseif ( $fk instanceof Doctrine_ForeignKey ||
2006-05-30 12:42:10 +04:00
$fk instanceof Doctrine_LocalKey ) {
2006-07-10 13:18:09 +04:00
2006-05-30 12:42:10 +04:00
switch ( $fk -> getType ()) :
case Doctrine_Relation :: ONE_COMPOSITE :
2006-09-17 21:59:04 +04:00
if ( isset ( $this -> originals [ $alias ]) && $this -> originals [ $alias ] -> obtainIdentifier () != $this -> references [ $alias ] -> obtainIdentifier ())
2006-05-30 12:42:10 +04:00
$this -> originals [ $alias ] -> delete ();
2006-07-22 04:58:07 +04:00
2006-05-30 12:42:10 +04:00
break ;
case Doctrine_Relation :: MANY_COMPOSITE :
if ( isset ( $this -> references [ $alias ])) {
$new = $this -> references [ $alias ];
if ( ! isset ( $this -> originals [ $alias ]))
$this -> loadReference ( $alias );
2006-07-10 22:10:54 +04:00
$r = Doctrine_Relation :: getDeleteOperations ( $this -> originals [ $alias ], $new );
2006-05-30 12:42:10 +04:00
2006-07-10 22:10:54 +04:00
foreach ( $r as $record ) {
2006-05-30 12:42:10 +04:00
$record -> delete ();
}
2006-07-22 04:58:07 +04:00
2006-05-30 12:42:10 +04:00
$this -> originals [ $alias ] = clone $this -> references [ $alias ];
}
break ;
endswitch ;
}
endforeach ;
}
/**
* getOriginals
*/
final public function getOriginals ( $name ) {
if ( ! isset ( $this -> originals [ $name ]))
throw new InvalidKeyException ();
return $this -> originals [ $name ];
}
/**
* deletes this data access object and all the related composites
* this operation is isolated by a transaction
*
* this event can be listened by the onPreDelete and onDelete listeners
*
* @ return boolean true on success , false on failure
*/
2006-09-22 23:23:57 +04:00
public function delete ( Doctrine_Connection $conn = null ) {
if ( $conn == null ) {
$conn = $this -> table -> getConnection ();
}
return $conn -> delete ( $this );
2006-05-30 12:42:10 +04:00
}
/**
* returns a copy of this object
* @ return DAO
*/
public function copy () {
return $this -> table -> create ( $this -> data );
}
/**
* @ param integer $id
* @ return void
*/
2006-09-17 21:59:04 +04:00
final public function assignIdentifier ( $id = false ) {
2006-05-30 12:42:10 +04:00
if ( $id === false ) {
2006-07-10 13:18:09 +04:00
$this -> id = array ();
2006-05-30 12:42:10 +04:00
$this -> cleanData ();
$this -> state = Doctrine_Record :: STATE_TCLEAN ;
$this -> modified = array ();
} elseif ( $id === true ) {
$this -> prepareIdentifiers ( false );
$this -> state = Doctrine_Record :: STATE_CLEAN ;
$this -> modified = array ();
} else {
2006-06-05 13:57:53 +04:00
$name = $this -> table -> getIdentifier ();
2006-07-22 04:58:07 +04:00
2006-07-10 13:18:09 +04:00
$this -> id [ $name ] = $id ;
2006-06-05 13:57:53 +04:00
$this -> state = Doctrine_Record :: STATE_CLEAN ;
$this -> modified = array ();
2006-05-30 12:42:10 +04:00
}
}
/**
2006-07-10 13:18:09 +04:00
* returns the primary keys of this object
*
* @ return array
2006-05-30 12:42:10 +04:00
*/
2006-09-17 21:59:04 +04:00
final public function obtainIdentifier () {
2006-05-30 12:42:10 +04:00
return $this -> id ;
}
2006-07-10 13:18:09 +04:00
/**
* returns the value of autoincremented primary key of this object ( if any )
*
* @ return integer
*/
final public function getIncremented () {
$id = current ( $this -> id );
if ( $id === false )
return null ;
2006-07-22 04:58:07 +04:00
2006-07-10 13:18:09 +04:00
return $id ;
}
2006-05-30 12:42:10 +04:00
/**
* getLast
* this method is used internally be Doctrine_Query
* it is needed to provide compatibility between
* records and collections
*
* @ return Doctrine_Record
*/
public function getLast () {
return $this ;
}
/**
* hasRefence
* @ param string $name
* @ return boolean
*/
public function hasReference ( $name ) {
return isset ( $this -> references [ $name ]);
}
2006-09-20 13:35:29 +04:00
/**
* obtainReference
*
* @ param string $name
*/
public function obtainReference ( $name ) {
if ( isset ( $this -> references [ $name ]))
return $this -> references [ $name ];
throw new Doctrine_Record_Exception ( " Unknown reference $name " );
}
2006-05-30 12:42:10 +04:00
/**
* initalizes a one - to - one relation
*
* @ param Doctrine_Record $record
* @ param Doctrine_Relation $connector
* @ return void
*/
2006-06-27 01:18:19 +04:00
public function initSingleReference ( Doctrine_Record $record , Doctrine_Relation $connector ) {
$alias = $connector -> getAlias ();
$this -> references [ $alias ] = $record ;
2006-05-30 12:42:10 +04:00
}
/**
* initalizes a one - to - many / many - to - many relation
*
* @ param Doctrine_Collection $coll
* @ param Doctrine_Relation $connector
* @ return void
*/
public function initReference ( Doctrine_Collection $coll , Doctrine_Relation $connector ) {
2006-06-26 22:55:42 +04:00
$alias = $connector -> getAlias ();
2006-07-22 04:58:07 +04:00
2006-06-08 14:20:30 +04:00
if ( ! ( $connector instanceof Doctrine_Association ))
$coll -> setReference ( $this , $connector );
2006-06-26 22:55:42 +04:00
$this -> references [ $alias ] = $coll ;
$this -> originals [ $alias ] = clone $coll ;
2006-05-30 12:42:10 +04:00
}
/**
* addReference
* @ param Doctrine_Record $record
* @ param mixed $key
* @ return void
*/
2006-06-26 22:55:42 +04:00
public function addReference ( Doctrine_Record $record , Doctrine_Relation $connector , $key = null ) {
$alias = $connector -> getAlias ();
2006-05-30 12:42:10 +04:00
2006-08-22 02:04:13 +04:00
$this -> references [ $alias ] -> internalAdd ( $record , $key );
$this -> originals [ $alias ] -> internalAdd ( $record , $key );
2006-05-30 12:42:10 +04:00
}
/**
* getReferences
* @ return array all references
*/
public function getReferences () {
return $this -> references ;
}
/**
2006-07-27 21:51:19 +04:00
* setRelated
*
* @ param string $alias
* @ param Doctrine_Access $coll
*/
final public function setRelated ( $alias , Doctrine_Access $coll ) {
$this -> references [ $alias ] = $coll ;
$this -> originals [ $alias ] = $coll ;
}
/**
* loadReference
* loads a related component
*
2006-05-30 12:42:10 +04:00
* @ throws InvalidKeyException
2006-07-27 21:51:19 +04:00
* @ param string $name
2006-05-30 12:42:10 +04:00
* @ return void
*/
final public function loadReference ( $name ) {
2006-06-25 22:34:53 +04:00
2006-08-31 13:04:14 +04:00
$fk = $this -> table -> getRelation ( $name );
2006-05-30 12:42:10 +04:00
$table = $fk -> getTable ();
$local = $fk -> getLocal ();
$foreign = $fk -> getForeign ();
$graph = $table -> getQueryObject ();
$type = $fk -> getType ();
switch ( $this -> getState ()) :
case Doctrine_Record :: STATE_TDIRTY :
case Doctrine_Record :: STATE_TCLEAN :
if ( $type == Doctrine_Relation :: ONE_COMPOSITE ||
$type == Doctrine_Relation :: ONE_AGGREGATE ) {
// ONE-TO-ONE
$this -> references [ $name ] = $table -> create ();
if ( $fk instanceof Doctrine_ForeignKey ) {
$this -> references [ $name ] -> set ( $fk -> getForeign (), $this );
} else {
$this -> set ( $fk -> getLocal (), $this -> references [ $name ]);
}
} else {
$this -> references [ $name ] = new Doctrine_Collection ( $table );
if ( $fk instanceof Doctrine_ForeignKey ) {
// ONE-TO-MANY
$this -> references [ $name ] -> setReference ( $this , $fk );
}
$this -> originals [ $name ] = new Doctrine_Collection ( $table );
}
break ;
case Doctrine_Record :: STATE_DIRTY :
case Doctrine_Record :: STATE_CLEAN :
case Doctrine_Record :: STATE_PROXY :
switch ( $fk -> getType ()) :
case Doctrine_Relation :: ONE_COMPOSITE :
case Doctrine_Relation :: ONE_AGGREGATE :
// ONE-TO-ONE
$id = $this -> get ( $local );
if ( $fk instanceof Doctrine_LocalKey ) {
if ( empty ( $id )) {
$this -> references [ $name ] = $table -> create ();
$this -> set ( $fk -> getLocal (), $this -> references [ $name ]);
} else {
2006-06-07 00:37:56 +04:00
$record = $table -> find ( $id );
2006-07-22 04:58:07 +04:00
if ( $record !== false )
2006-06-07 00:37:56 +04:00
$this -> references [ $name ] = $record ;
else
2006-06-03 13:10:43 +04:00
$this -> references [ $name ] = $table -> create ();
2006-07-22 04:58:07 +04:00
2006-06-03 13:10:43 +04:00
//$this->set($fk->getLocal(),$this->references[$name]);
2006-06-07 00:37:56 +04:00
2006-05-30 12:42:10 +04:00
}
} elseif ( $fk instanceof Doctrine_ForeignKey ) {
if ( empty ( $id )) {
$this -> references [ $name ] = $table -> create ();
$this -> references [ $name ] -> set ( $fk -> getForeign (), $this );
} else {
$dql = " FROM " . $table -> getComponentName () . " WHERE " . $table -> getComponentName () . " . " . $fk -> getForeign () . " = ? " ;
$coll = $graph -> query ( $dql , array ( $id ));
$this -> references [ $name ] = $coll [ 0 ];
$this -> references [ $name ] -> set ( $fk -> getForeign (), $this );
}
}
break ;
default :
2006-08-16 01:33:41 +04:00
$query = $fk -> getRelationDql ( 1 );
2006-05-30 12:42:10 +04:00
// ONE-TO-MANY
if ( $fk instanceof Doctrine_ForeignKey ) {
$id = $this -> get ( $local );
2006-08-16 01:33:41 +04:00
$coll = $graph -> query ( $query , array ( $id ));
$coll -> setReference ( $this , $fk );
2006-09-12 01:46:01 +04:00
} elseif ( $fk instanceof Doctrine_Association_Self ) {
$id = $this -> getIncremented ();
$q = new Doctrine_RawSql ();
$assocTable = $fk -> getAssociationFactory () -> getTableName ();
$tableName = $this -> getTable () -> getTableName ();
$identifier = $this -> getTable () -> getIdentifier ();
$sub = " SELECT " . $fk -> getForeign () .
" FROM " . $assocTable .
" WHERE " . $fk -> getLocal () .
" = ? " ;
$sub2 = " SELECT " . $fk -> getLocal () .
" FROM " . $assocTable .
" WHERE " . $fk -> getForeign () .
" = ? " ;
$q -> select ( '{' . $tableName . '.*}, {' . $assocTable . '.*}' )
-> from ( $tableName . ' INNER JOIN ' . $assocTable . ' ON ' .
$tableName . '.' . $identifier . ' = ' . $assocTable . '.' . $fk -> getLocal () . ' OR ' .
$tableName . '.' . $identifier . ' = ' . $assocTable . '.' . $fk -> getForeign ()
)
-> where ( $tableName . '.' . $identifier . ' IN (' . $sub . ') OR ' .
$tableName . '.' . $identifier . ' IN (' . $sub2 . ')'
);
$q -> addComponent ( $tableName , $this -> table -> getComponentName ());
$q -> addComponent ( $assocTable , $this -> table -> getComponentName () . '.' . $fk -> getAssociationFactory () -> getComponentName ());
$coll = $q -> execute ( array ( $id , $id ));
2006-07-22 04:58:07 +04:00
} elseif ( $fk instanceof Doctrine_Association ) {
2006-08-16 01:33:41 +04:00
$id = $this -> getIncremented ();
$coll = $graph -> query ( $query , array ( $id ));
2006-05-30 12:42:10 +04:00
}
2006-08-16 01:33:41 +04:00
$this -> references [ $name ] = $coll ;
$this -> originals [ $name ] = clone $coll ;
2006-05-30 12:42:10 +04:00
endswitch ;
break ;
endswitch ;
}
2006-07-22 03:22:15 +04:00
/**
* filterRelated
* lazy initializes a new filter instance for given related component
*
2006-07-27 21:51:19 +04:00
* @ param $componentAlias alias of the related component
2006-07-22 03:22:15 +04:00
* @ return Doctrine_Filter
*/
2006-07-27 21:51:19 +04:00
final public function filterRelated ( $componentAlias ) {
if ( ! isset ( $this -> filters [ $componentAlias ])) {
$this -> filters [ $componentAlias ] = new Doctrine_Filter ( $componentAlias );
2006-07-22 03:22:15 +04:00
}
2006-07-27 21:51:19 +04:00
return $this -> filters [ $componentAlias ];
2006-07-22 03:22:15 +04:00
}
2006-05-30 12:42:10 +04:00
/**
* binds One - to - One composite relation
*
* @ param string $objTableName
* @ param string $fkField
* @ return void
*/
final public function ownsOne ( $componentName , $foreignKey , $localKey = null ) {
$this -> table -> bind ( $componentName , $foreignKey , Doctrine_Relation :: ONE_COMPOSITE , $localKey );
}
/**
* binds One - to - Many composite relation
*
* @ param string $objTableName
* @ param string $fkField
* @ return void
*/
final public function ownsMany ( $componentName , $foreignKey , $localKey = null ) {
$this -> table -> bind ( $componentName , $foreignKey , Doctrine_Relation :: MANY_COMPOSITE , $localKey );
}
/**
* binds One - to - One aggregate relation
*
* @ param string $objTableName
* @ param string $fkField
* @ return void
*/
final public function hasOne ( $componentName , $foreignKey , $localKey = null ) {
$this -> table -> bind ( $componentName , $foreignKey , Doctrine_Relation :: ONE_AGGREGATE , $localKey );
}
/**
* binds One - to - Many aggregate relation
*
* @ param string $objTableName
* @ param string $fkField
* @ return void
*/
final public function hasMany ( $componentName , $foreignKey , $localKey = null ) {
$this -> table -> bind ( $componentName , $foreignKey , Doctrine_Relation :: MANY_AGGREGATE , $localKey );
}
/**
* setPrimaryKey
* @ param mixed $key
*/
final public function setPrimaryKey ( $key ) {
$this -> table -> setPrimaryKey ( $key );
}
/**
* hasColumn
* sets a column definition
*
* @ param string $name
* @ param string $type
* @ param integer $length
* @ param mixed $options
* @ return void
*/
2006-09-24 13:52:04 +04:00
final public function hasColumn ( $name , $type , $length = 2147483647 , $options = " " ) {
2006-05-30 12:42:10 +04:00
$this -> table -> setColumn ( $name , $type , $length , $options );
}
2006-08-25 21:13:21 +04:00
/**
* countRelated
2006-08-26 03:50:55 +04:00
*
2006-08-30 00:37:55 +04:00
* @ param string $name the name of the related component
2006-08-26 03:50:55 +04:00
* @ return integer
2006-08-25 21:13:21 +04:00
*/
public function countRelated ( $name ) {
2006-08-31 13:04:14 +04:00
$rel = $this -> table -> getRelation ( $name );
2006-08-26 03:50:55 +04:00
$componentName = $rel -> getTable () -> getComponentName ();
$alias = $rel -> getTable () -> getAlias ( get_class ( $this ));
$query = new Doctrine_Query ();
$query -> from ( $componentName . '(' . 'COUNT(1)' . ')' ) -> where ( $componentName . '.' . $alias . '.' . $this -> getTable () -> getIdentifier () . ' = ?' );
$array = $query -> execute ( array ( $this -> getIncremented ()));
return $array [ 0 ][ 'COUNT(1)' ];
2006-08-25 21:13:21 +04:00
}
2006-08-07 00:55:54 +04:00
/**
* merge
2006-09-09 03:20:51 +04:00
* merges this record with an array of values
2006-08-07 00:55:54 +04:00
*
* @ param array $values
*/
public function merge ( array $values ) {
foreach ( $this -> table -> getColumnNames () as $value ) {
try {
2006-08-20 22:52:07 +04:00
if ( isset ( $values [ $value ]))
$this -> set ( $value , $values [ $value ]);
2006-08-07 00:55:54 +04:00
} catch ( Exception $e ) { }
}
}
2006-05-31 02:47:01 +04:00
/**
* __call
* @ param string $m
* @ param array $a
*/
public function __call ( $m , $a ) {
2006-08-16 01:33:41 +04:00
if ( method_exists ( $this -> table , $m ))
return call_user_func_array ( array ( $this -> table , $m ), $a );
2006-05-31 02:47:01 +04:00
if ( ! function_exists ( $m ))
2006-05-31 12:46:44 +04:00
throw new Doctrine_Record_Exception ( " unknown callback ' $m ' " );
2006-06-01 15:58:05 +04:00
2006-05-31 02:47:01 +04:00
if ( isset ( $a [ 0 ])) {
$column = $a [ 0 ];
2006-05-31 12:46:44 +04:00
$a [ 0 ] = $this -> get ( $column );
2006-06-03 13:10:43 +04:00
$newvalue = call_user_func_array ( $m , $a );
2006-08-24 20:34:05 +04:00
2006-08-16 01:33:41 +04:00
$this -> data [ $column ] = $newvalue ;
2006-05-31 02:47:01 +04:00
}
return $this ;
}
2006-05-30 12:42:10 +04:00
/**
* returns a string representation of this object
*/
public function __toString () {
return Doctrine_Lib :: getRecordAsString ( $this );
}
}
2006-09-04 02:46:30 +04:00