Location: PHPKode > scripts > Repose PHP ORM > dflydev-repose-php-e783d16/lib/repose_ProxyInstance.inc
<?php
/**
 * Repox Proxy Instance
 * @package repose
 */

require_once('repose_Uuid.php');
require_once('repose_ArrayCollection.php');

if ( ! class_exists('PROXY_TEMPLATE') ) {
    /**
     * Placeholder proxy for the proxy template class
     */
    class PROXY_TEMPLATE {}
}

/**
 * Repox Proxy Instance Class
 * @package repose
 */
class PROXY_TEMPLATE__ReposeProxy__ extends PROXY_TEMPLATE implements repose_IProxy {

    /**
     * ID
     * @var string
     */
    private $___repose_id;

    /**
     * Session
     * @var string
     */
    private $___repose_sessionId;

    /**
     * Instance cache
     * @var string
     */
    private $___repose_instanceCacheId;

    /**
     * Mapped class name
     * @var string
     */
    private $___repose_clazz;

    /**
     * Reflection properties
     * @var array
     */
    private $___repose_reflectionProperties;

    /**
     * Proxy class name
     * @var string
     */
    private $___repose_proxyClazz;

    /**
     * Data history
     * @var array
     */
    private $___repose_history;

    /**
     * Is persisted?
     * @var bool
     */
    private $___repose_isPersisted;

    /**
     * Is deleted?
     * @var bool
     */
    private $___repose_isDeleted;
    
    /**
     * Is really deleted?
     * @var bool
     */
    private $___repose_isReallyDeleted;
    
    /**
     * Are we flushing?
     * @var bool
     */
    private $___repose_isFlushing = false;

    /**
     * Constructor
     */
    public function __construct() {
        // noop
    }

    /**
     * Initialization
     * @param repose_Session $session Session
     * @param repose_InstanceCache $instanceCache Instance cache
     * @param string $proxyClazz Proxy class
     * @param string $clazz Class
     * @param array $reflectionProperties Reflection properties
     */
    public function ___repose_init($session, $instanceCache, $proxyClazz, $clazz, $reflectionProperties, $data = null, $isPersisted = false) {
        $this->___repose_id = repose_Uuid::v4();
        $this->___repose_sessionId = $session->id();
        $this->___repose_instanceCacheId = $instanceCache->id();
        $this->___repose_proxyClazz = $proxyClazz;
        $this->___repose_clazz = $clazz;
        $this->___repose_reflectionProperties = $reflectionProperties;
        $this->___repose_isPersisted = $isPersisted;
        $this->___repose_populateInstanceFromData($data);
        $this->___repose_populateHistoryFromInstance();
        $this->___repose_isDeleted = false;
        $this->___repose_isReallyDeleted = false;
        $clazz = $this->___repose_clazz;

        $primaryKey = $this->___repose_primaryKey();
        $primaryKeyProperty = $primaryKey->isComposite() ? null : $primaryKey->property();

        if ( $primaryKeyProperty !== null ) {
            $name = $primaryKeyProperty->name();
            if ( $primaryKeyProperty->generator()->shouldGenerateOnAdd() ) {
                $this->___repose_propertySetter($name, $primaryKeyProperty->generator()->generate(
                    $this->___repose_session(),
                    $this->___repose_mappedClass(),
                    $primaryKeyProperty,
                    $this
                ));
            }
        }
        
    }

    /**
     * Internal ID for this proxy instance
     * @return string
     */
    public function ___repose_id() {
        return $this->___repose_id;
    }

    /**
     * Get the session
     * @return repose_Session
     */
    public function ___repose_session() {
        return repose_Session::BY_ID($this->___repose_sessionId);
    }

    /**
     * Get the instance cache
     * @return repose_InstanceCache
     */
    public function ___repose_instanceCache() {
        return repose_InstanceCache::BY_ID($this->___repose_instanceCacheId);
    }

    /**
     * Is persisted?
     * @return bool
     */
    public function ___repose_isPersisted() {
        return $this->___repose_isPersisted;
    }

    /**
     * Is deleted?
     * @return bool
     */
    public function ___repose_isDeleted() {
        return $this->___repose_isDeleted;
    }
    
    /**
     * Is really deleted?
     * @return bool
     */
    public function ___repose_isReallyDeleted() {
        return $this->___repose_isReallyDeleted;
    }
    
    /**
     * A mapped class
     * @param string $clazz Class
     * @return repose_MappedClass
     */
    public function ___repose_mappedClass($clazz = null) {
        if ( $clazz === null ) $clazz = $this->___repose_clazz;
        return $this->___repose_session()->getMappedClass($clazz);
    }

    /**
     * Get the properties for a class
     * @param string $clazz Class
     * @return array
     */
    public function ___repose_getProperties($clazz = null) {
        if ( $clazz === null ) $clazz = $this->___repose_clazz;
        return $this->___repose_session()->getProperties($clazz);
    }

    /**
     * Get a property for a class
     * @param string $clazz Class
     * @param string $name Name of property
     * @return array
     */
    public function ___repose_getProperty($clazz = null, $name) {
        if ( $clazz === null ) $clazz = $this->___repose_clazz;
        return $this->___repose_session()->getProperty($clazz, $name);
    }

    /**
     * Populate cache from current instance values
     */
    public function ___repose_populateHistoryFromInstance() {
        foreach ( $this->___repose_getProperties() as $property ) {
            $name = $property->name();
            $value = $this->___repose_propertyGetter($name);
            if ( $property->isObject() ) {
                if ( ! is_null($value) ) {
                    if ( ! $value instanceof repose_IProxy ) {
                        $value = $this->___repose_session()->add($value);
                        $this->___repose_propertySetter($name, $value);
                    }
                    $this->___repose_instanceCache()->registerRelationship($value, $this, $property);
                }
            }
            if ( $property->isCollection() and ! $value instanceof repose_ICollection ) {
                $value = new repose_ArrayCollection(
                    $this->___repose_session(),
                    $this->___repose_instanceCache(),
                    $this,
                    $property,
                    $value
                );
                $this->___repose_propertySetter($name, $value);
            }
            if ( $property->isObject() and $value and $value instanceof repose_IProxy and $value->___repose_isDeleted() ) {
                $this->___repose_history[$name] = null;
            } else {
                $this->___repose_history[$name] = $value;
            }
        }
    }

    /**
     * Populate current instance from data
     */
    public function ___repose_populateInstanceFromData($data = null) {
        if ( $data === null ) return;
        foreach ( $this->___repose_getProperties() as $property ) {
            $name = $property->name();
            $value = isset($data[$name]) ? $data[$name] : null;
            if ( $property->isObject() ) {
                if ( ! is_null($value) ) {
                    if ( ! $value instanceof repose_IProxy ) {
                        $value = $this->___repose_session()->add($value);
                    }
                    $this->___repose_instanceCache()->registerRelationship($value, $this, $property);
                }
            }
            if ( $property->isCollection() and ! $value instanceof repose_ICollection ) {
                $value = new repose_ArrayCollection(
                    $this->___repose_session(),
                    $this->___repose_instanceCache(),
                    $this,
                    $property,
                    $value
                );
            }
            if ( $property->isObject() and $value and $value instanceof repose_IProxy and $value->___repose_isDeleted() ) {
                $this->___repose_propertySetter($name, null);
            } else {
                $this->___repose_propertySetter($name, $value);
            }
        }
    }
    
    /**
     * Import a collection property?
     * @param repose_MappedClassProperty $property Property
     * @param mixed $objects
     */
    public function ___repose_mergeCollection($property, $objects) {
        echo ' aaa ' . "\n";
        $collection = $this->___repose_propertyGetter($property->name());
        if ( ! $collection instanceof repose_ICollection ) {
            $this->___repose_propertySetter($property->name(), new repose_ArrayCollection(
                $this->___repose_session(),
                $this->___repose_instanceCache(),
                $this,
                $property,
                array_merge($collection, $objects)
            ));
            
        } else {
            $collection->___repose_fakeIsQueried();
            foreach ( $objects as $object ) $collection[] = $object;
        }
        echo ' bbb ' . "\n";
    }

    /**
     * Is we dirty?
     * @return bool
     */
    public function ___repose_isDirty() {
        foreach ( $this->___repose_getProperties() as $property ) {
            if ( $property->isCollection() ) continue;
            $name = $property->name();
            $value = isset($this->___repose_history[$name]) ?
                $this->___repose_history[$name] : null;
            $vTest = $this->___repose_propertyGetter($name);
            if ( $value !== $vTest ) return true;
        }
        return false;
    }

    /**
     * Flush relationships
     */
    public function ___repose_flushRelationships() {
        foreach ( $this->___repose_getProperties() as $property ) {
            if ( $property->isObject() ) {
                $name = $property->name();
                $value = $this->___repose_propertyGetter($name);
                if ( $value !== null ) {
                    if ( ! $value instanceof repose_IProxy ) {
                        $value = $this->___repose_session()->add($value);
                        $this->___repose_propertySetter($name, $value);
                    }
                    if ( ! $value->___repose_isPersisted() ) {
                        //$value->___repose_persist();
                    } elseif ( $value->___repose_isDirty() ) {
                        $value->___repose_flush();
                    }
                }
            }
        }
    }

    /**
     * Flush
     */
    public function ___repose_flush() {

        // Avoid deep recursion.
        if ( $this->___repose_isFlushing ) return;

        // Set so if a related object tries to flush us again,
        // we can skip that step.
        $this->___repose_isFlushing = true;

        // Try to recursively flush our relationships.
        $this->___repose_flushRelationships();

        // Did we flush?
        $didFlush = true;

        if ( $this->___repose_isDeleted ) {
            if ( $this->___repose_isPersisted ) {
                // Delete this proxy from our engine.
                $newId = $this->___repose_session()->engine()->delete($this->___repose_session(), $this);
                $this->___repose_isPersisted = false;
            }
            $this->___repose_isReallyDeleted = true;
        } elseif ( ! $this->___repose_isPersisted ) {

            //
            // If we have never been persisted, we should attempt
            // to do so now. 
            //

            $clazz = $this->___repose_clazz;
            $primaryKey = $this->___repose_session()->getPrimaryKey($this->___repose_clazz);
            $primaryKeyProperty = $primaryKey->isComposite() ? null : $primaryKey->property();

            if ( $primaryKeyProperty !== null ) {
                $name = $primaryKeyProperty->name();
                if ( $primaryKeyProperty->generator()->shouldGenerateBeforePersist() ) {
                    $this->___repose_propertySetter($name, $primaryKeyProperty->generator()->generate(
                        $this->___repose_session(),
                        $this->___repose_mappedClass(),
                        $primaryKeyProperty,
                        $this
                    ));
                }
            }
            
            // Persist this proxy in our engine.
            $newId = $this->___repose_session()->engine()->persist($this->___repose_session(), $this);

            if ( $primaryKeyProperty !== null ) {
                $name = $primaryKeyProperty->name();
                if ( $primaryKeyProperty->generator()->shouldGenerateAfterPersist() ) {
                    $this->___repose_propertySetter($name, $primaryKeyProperty->generator()->generate(
                        $this->___repose_session(),
                        $this->___repose_mappedClass(),
                        $primaryKeyProperty,
                        $this,
                        $newId
                    ));
                }
            }

            // And now we know...
            $this->___repose_isPersisted = true;

        } elseif ( $this->___repose_isDirty() ) {

            //
            // If we have been persisted, we should update
            // the proxy in the engine.
            //

            $this->___repose_session()->engine()->update($this->___repose_session(), $this);

        } else {
            // Nothing to flush!
            $didFlush = false;
        }

        if ( $didFlush ) {

            // Capture the primary keys from our history and current state.
            $oldPk = $this->___repose_serializedPrimaryKey('history');
            $newPk = $this->___repose_serializedPrimaryKey('current');

            // Sync history from our current state.
            $this->___repose_populateHistoryFromInstance();

            // Move things around as needed inside of the identity map
            // based on our old and new primary keys.
            $this->___repose_instanceCache()->updateIdentityMap(
                $this->___repose_id,
                $this->___repose_clazz,
                $oldPk,
                $newPk
            );

        }

        // We are no longer flushing.
        $this->___repose_isFlushing = false;

    }

    /**
     * Derive the actual data store value for a property
     * @param repose_MappedClassProperty $property Property
     * @param mixed $value Current value
     */
    protected function derivePropertyValue($property, $value = null) {
        if ( $property->isObject() ) {
            return $value;
        } elseif ( $property->isCollection() ) {
            return $value;
        } else {
            return $value;
        }
    }

    /**
     * Current data
     * @return array
     */
    public function ___repose_currentData() {
        $data = array();
        foreach ( $this->___repose_getProperties() as $property ) {
            $name = $property->name();
            $value = $this->___repose_propertyGetter($name);
            if ( isset($value) ) {
                if ( ! $property->isCollection() ) {
                    $data[$name] = $this->derivePropertyValue(
                        $property,
                        $value
                    );
                }
            }
        }
        return $data;
    }

    /**
     * Changed data
     * @return array
     */
    public function ___repose_changedData() {
        $data = array();
        foreach ( $this->___repose_getProperties() as $property ) {
            $name = $property->name();
            if ( ! $property->isCollection() ) {
                $value = $this->___repose_propertyGetter($name);
                if ( ! isset($this->___repose_history[$name]) or $value != $this->___repose_history[$name] ) {
                    $data[$name] = $this->derivePropertyValue(
                        $property,
                        $value
                    );
                }
            }
        }
        return $data;
    }

    /**
     * Primary key data
     * @param string $which Which data? 'current' or 'history'
     */
    public function ___repose_primaryKeyData($which = 'current') {
        $data = array();
        $clazz = $this->___repose_clazz;
        foreach ( $this->___repose_session()->getPrimaryKey($clazz)->properties() as $property ) {
            $name = $property->name();
            switch($which) {
                case 'current':
                    $value = $this->___repose_propertyGetter($name);
                    if ( isset($value) ) $data[$name] = $value;
                    break;
                case 'history':
                    if ( isset($this->___repose_history[$name]) ) {
                        $data[$name] = $this->___repose_history[$name];
                    }
                    break;
            }
        }
        return $data;
    }

    /**
     * Primary key
     * @return repose_MappedClassPrimaryKey
     */
    public function ___repose_primaryKey() {
        return $this->___repose_session()->getPrimaryKey($this->___repose_clazz);
    }

    /**
     * Primary key value
     * @param string $which Which data? 'current' or 'history'
     */
    public function ___repose_primaryKeyValue($which = 'current') {
        $data = $this->___repose_primaryKeyData($which);
        foreach ( $data as $key => $value ) { return $value; }
        return NULL;
    }

    /**
     * Serialized primary key data
     * @param string $which Which data? 'current' or 'history'
     */
    public function ___repose_serializedPrimaryKey($which = 'current') {
        return $this->___repose_session()->serializePrimaryKey(
            $this->___repose_primaryKeyData($which),
            $this->___repose_id
        );
    }

    /**
     * Delete
     */
    public function ___repose_delete() {
        $this->___repose_isDeleted = true;
        $this->___repose_instanceCache()->pruneRelationship($this);
    }

    /**
     * Get a property
     * @param string $name Property name
     * @return mixed
     */
    public function ___repose_propertyGetter($name) {
        $reflectionProperty = $this->___repose_reflectionProperties[$name];
        return $reflectionProperty->getValue($this);
    }

    /**
     * Set a property
     * @param string $name Property name
     * @param mixed $value Value
     */
    public function ___repose_propertySetter($name, $value = null) {
        $reflectionProperty = $this->___repose_reflectionProperties[$name];
        return $reflectionProperty->setValue($this, $value);
    }

    /**
     * Destroy
     */
    public function destroy() {
        //$this->session = null;
        //$this->instanceCache = null;
    }

    /**
     * Instance Cache by ID
     * @param string $id Instance Cache ID
     * @return repose_Session
     */
    static public function SESSION($id) {
        if ( isset(self::$CACHE[$id]) ) return self::$CACHE[$id];
        return null;
    }

}

?>
Return current item: Repose PHP ORM