summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php20
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php12
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php10
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php17
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php2
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php3
-rw-r--r--framework/Data/ActiveRecord/TActiveRecord.php173
-rw-r--r--framework/Data/ActiveRecord/TActiveRecordManager.php24
-rw-r--r--framework/Data/ActiveRecord/TActiveRecordStateRegistry.php243
-rw-r--r--framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js4
-rw-r--r--tests/simple_unit/ActiveRecord/ForeignKeyTestCase.php1
-rw-r--r--tests/simple_unit/ActiveRecord/MultipleForeignKeyTestCase.php17
13 files changed, 183 insertions, 344 deletions
diff --git a/.gitattributes b/.gitattributes
index e4e7fdb3..0c8dc975 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2028,7 +2028,6 @@ framework/Data/ActiveRecord/TActiveRecordConfig.php -text
framework/Data/ActiveRecord/TActiveRecordCriteria.php -text
framework/Data/ActiveRecord/TActiveRecordGateway.php -text
framework/Data/ActiveRecord/TActiveRecordManager.php -text
-framework/Data/ActiveRecord/TActiveRecordStateRegistry.php -text
framework/Data/Common/IbmDb2/TIbmColumnMetaData.php -text
framework/Data/Common/IbmDb2/TIbmMetaData.php -text
framework/Data/Common/IbmDb2/TIbmMetaDataInspector.php -text
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php b/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php
index c030f2d2..565070c1 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordBelongsTo.php
@@ -123,20 +123,16 @@ class TActiveRecordBelongsTo extends TActiveRecordRelation
{
$obj = $this->getContext()->getSourceRecord();
$fkObject = $obj->getColumnValue($this->getContext()->getProperty());
- $registry = $fkObject->getRecordManager()->getObjectStateRegistry();
- if($registry->shouldPersistObject($fkObject))
+ if($fkObject!==null)
{
- if($fkObject!==null)
- {
- $fkObject->save();
- $source = $this->getSourceRecord();
- $fkeys = $this->findForeignKeys($source, $fkObject);
- foreach($fkeys as $srcKey => $fKey)
- $source->setColumnValue($srcKey, $fkObject->getColumnValue($fKey));
- return true;
- }
+ $fkObject->save();
+ $source = $this->getSourceRecord();
+ $fkeys = $this->findForeignKeys($source, $fkObject);
+ foreach($fkeys as $srcKey => $fKey)
+ $source->setColumnValue($srcKey, $fkObject->getColumnValue($fKey));
+ return true;
}
- return true;
+ return false;
}
}
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php
index f7426862..382d9789 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasMany.php
@@ -88,7 +88,7 @@ class TActiveRecordHasMany extends TActiveRecordRelation
/**
* @return array foreign key field names as key and object properties as value.
* @since 3.1.2
- */
+ */
public function getRelationForeignKeys()
{
$fkObject = $this->getContext()->getForeignRecordFinder();
@@ -107,16 +107,12 @@ class TActiveRecordHasMany extends TActiveRecordRelation
if(($total = count($fkObjects))> 0)
{
$source = $this->getSourceRecord();
- $registry = $source->getRecordManager()->getObjectStateRegistry();
$fkeys = $this->findForeignKeys($fkObjects[0], $source);
for($i=0;$i<$total;$i++)
{
- if($registry->shouldPersistObject($fkObjects[$i]))
- {
- foreach($fkeys as $fKey => $srcKey)
- $fkObjects[$i]->setColumnValue($fKey, $source->getColumnValue($srcKey));
- $success = $fkObjects[$i]->save() && $success;
- }
+ foreach($fkeys as $fKey => $srcKey)
+ $fkObjects[$i]->setColumnValue($fKey, $source->getColumnValue($srcKey));
+ $success = $fkObjects[$i]->save() && $success;
}
}
return $success;
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php
index 564d3d22..bcda962c 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php
@@ -189,7 +189,6 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation
{
$criteria = $this->getCriteria();
$finder = $this->getContext()->getForeignRecordFinder();
- $registry = $finder->getRecordManager()->getObjectStateRegistry();
$type = get_class($finder);
$command = $this->createCommand($criteria, $foreignKeys,$indexValues,$sourceKeys);
$srcProps = array_keys($sourceKeys);
@@ -201,7 +200,6 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation
unset($row[$column]);
$obj = $this->createFkObject($type,$row,$foreignKeys);
$collections[$hash][] = $obj;
- $registry->registerClean($obj);
}
$this->setResultCollection($results, $collections, array_values($sourceKeys));
}
@@ -214,7 +212,7 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation
*/
protected function createFkObject($type,$row,$foreignKeys)
{
- $obj = new $type($row);
+ $obj = TActiveRecord::createRecordInstance($type, $row, TActiveRecord::STATE_LOADED);
if(count($this->_association_columns) > 0)
{
$i=0;
@@ -309,13 +307,9 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation
if(($total = count($fkObjects))> 0)
{
$source = $this->getSourceRecord();
- $registry = $source->getRecordManager()->getObjectStateRegistry();
$builder = $this->getAssociationTableCommandBuilder();
for($i=0;$i<$total;$i++)
- {
- if($registry->shouldPersistObject($fkObjects[$i]))
- $success = $fkObjects[$i]->save() && $success;
- }
+ $success = $fkObjects[$i]->save() && $success;
return $this->updateAssociationTable($obj, $fkObjects, $builder) && $success;
}
return $success;
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php
index e5a36659..49119965 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php
@@ -100,7 +100,7 @@ class TActiveRecordHasOne extends TActiveRecordRelation
$fkObjects = $this->findForeignObjects($fields,$indexValues);
$this->populateResult($results,$properties,$fkObjects,$fields);
}
-
+
/**
* @return array foreign key field names as key and object properties as value.
* @since 3.1.2
@@ -135,16 +135,11 @@ class TActiveRecordHasOne extends TActiveRecordRelation
public function updateAssociatedRecords()
{
$fkObject = $this->getContext()->getPropertyValue();
- $registry = $fkObject->getRecordManager()->getObjectStateRegistry();
- if($registry->shouldPersistObject($fkObject))
- {
- $source = $this->getSourceRecord();
- $fkeys = $this->findForeignKeys($fkObject, $source);
- foreach($fkeys as $fKey => $srcKey)
- $fkObject->setColumnValue($fKey, $source->getColumnValue($srcKey));
- return $fkObject->save();
- }
- return true;
+ $source = $this->getSourceRecord();
+ $fkeys = $this->findForeignKeys($fkObject, $source);
+ foreach($fkeys as $fKey => $srcKey)
+ $fkObject->setColumnValue($fKey, $source->getColumnValue($srcKey));
+ return $fkObject->save();
}
}
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
index 5bde4898..63e182ca 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
@@ -162,7 +162,7 @@ abstract class TActiveRecordRelation
$ids=array();
foreach($properties as $property)
$ids[] = is_object($obj) ? $obj->getColumnValue($property) : $obj[$property];
- return sprintf('%x',crc32(serialize($ids)));
+ return serialize($ids);
}
/**
diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php b/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php
index 8bc4362f..d6f86a9a 100644
--- a/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php
+++ b/framework/Data/ActiveRecord/Relations/TActiveRecordRelationContext.php
@@ -182,8 +182,9 @@ class TActiveRecordRelationContext
public function updateAssociatedRecords($updateBelongsTo=false)
{
$success=true;
- foreach($this->_record->getRelations() as $property=>$relation)
+ foreach($this->_record->getRelations() as $data)
{
+ list($property, $relation) = $data;
$belongsTo = $relation[0]==TActiveRecord::BELONGS_TO;
if(($updateBelongsTo && $belongsTo) || (!$updateBelongsTo && !$belongsTo))
{
diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php
index f5d73582..4bbee046 100644
--- a/framework/Data/ActiveRecord/TActiveRecord.php
+++ b/framework/Data/ActiveRecord/TActiveRecord.php
@@ -108,6 +108,27 @@ Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelationContext');
* fetched in a lazy way, which avoids unnecessary overhead if the foreign objects are not accessed
* at all.
*
+ * Since v3.1.2, new events OnInsert, OnUpdate and OnDelete are available.
+ * The event OnInsert, OnUpdate and OnDelete methods are executed before
+ * inserting, updating, and deleting the current record, respectively. You may override
+ * these methods; a TActiveRecordChangeEventParameter parameter is passed to these methods.
+ * The property {@link TActiveRecordChangeEventParameter::setIsValid IsValid} of the parameter
+ * can be set to false to prevent the change action to be executed. This can be used,
+ * for example, to validate the record before the action is executed. For example,
+ * in the following the password property is hashed before a new record is inserted.
+ * <code>
+ * class UserRecord extends TActiveRecord
+ * {
+ * function OnInsert($param)
+ * {
+ * //parent method should be called to raise the event
+ * parent::OnInsert($param);
+ * $this->nounce = md5(time());
+ * $this->password = md5($this->password.$this->nounce);
+ * }
+ * }
+ * </code>
+ *
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id$
* @package System.Data.ActiveRecord
@@ -120,6 +141,16 @@ abstract class TActiveRecord extends TComponent
const HAS_MANY='HAS_MANY';
const MANY_TO_MANY='MANY_TO_MANY';
+ const STATE_NEW=0;
+ const STATE_LOADED=1;
+ const STATE_DELETED=2;
+
+ /**
+ * @var integer object state: 0 = new, 1 = loaded, 2 = deleted.
+ * @since 3.1.2
+ */
+ private $_objectState=0;
+
/**
* This static variable defines the column mapping.
* The keys are physical column names as defined in database,
@@ -177,11 +208,12 @@ abstract class TActiveRecord extends TComponent
*/
public function __construct($data=array(), $connection=null)
{
- $this->copyFrom($data);
if($connection!==null)
- $this->_connection=$connection;
+ $this->setDbConnection($connection);
$this->setupColumnMapping();
$this->setupRelations();
+ if(!empty($data)) //$data may be an object
+ $this->copyFrom($data);
}
/**
@@ -242,7 +274,7 @@ abstract class TActiveRecord extends TComponent
$class=new ReflectionClass($className);
$relations=array();
foreach($class->getStaticPropertyValue('RELATIONS') as $key=>$value)
- $relations[strtolower($key)]=$value;
+ $relations[strtolower($key)]=array($key,$value);
self::$_relations[$className]=$relations;
}
}
@@ -258,7 +290,7 @@ abstract class TActiveRecord extends TComponent
if(!is_array($data))
throw new TActiveRecordException('ar_must_copy_from_array_or_object', get_class($this));
foreach($data as $name=>$value)
- $this->$name = $value;
+ $this->setColumnValue($name,$value);
return $this;
}
@@ -270,11 +302,7 @@ abstract class TActiveRecord extends TComponent
public function getDbConnection()
{
if($this->_connection===null)
- {
- $this->setDbConnection(self::getRecordManager()->getDbConnection());
- if($this->_connection===null) //check it
- throw new TActiveRecordException('ar_invalid_db_connection',get_class($this));
- }
+ return self::getRecordManager()->getDbConnection();
return $this->_connection;
}
@@ -367,19 +395,31 @@ abstract class TActiveRecord extends TComponent
}
/**
- * Commit changes to the record, may insert, update or delete depending
- * on the record state given in TObjectStateRegistery.
+ * Commit changes to the record: insert, update or delete depending on the object state.
* @return boolean true if changes were made.
*/
protected function commitChanges()
{
- $registry = $this->getRecordManager()->getObjectStateRegistry();
$gateway = $this->getRecordGateway();
if(!$this->_readOnly)
$this->_readOnly = $gateway->getRecordTableInfo($this)->getIsView();
if($this->_readOnly)
throw new TActiveRecordException('ar_readonly_exception',get_class($this));
- return $registry->commit($this,$gateway);
+ $param = new TActiveRecordChangeEventParameter();
+ switch($this->_objectState)
+ {
+ case self::STATE_NEW:
+ $this->onInsert($param);
+ return $param->getIsValid() ? $gateway->insert($this) : false;
+ case self::STATE_LOADED:
+ $this->onUpdate($param);
+ return $param->getIsValid() ? $gateway->update($this) : false;
+ case self::STATE_DELETED:
+ $this->onDelete($param);
+ return $param->getIsValid() ? $gateway->delete($this) : false;
+ default:
+ throw new TActiveRecordException('ar_invalid_state', get_class($this));
+ }
}
/**
@@ -389,8 +429,7 @@ abstract class TActiveRecord extends TComponent
*/
public function delete()
{
- $registry = $this->getRecordManager()->getObjectStateRegistry();
- $registry->registerRemoved($this);
+ $this->_objectState = self::STATE_DELETED;
return $this->commitChanges();
}
@@ -456,19 +495,22 @@ abstract class TActiveRecord extends TComponent
{
if(empty($data))
return null;
- //create and populate the object
+ $obj = self::createRecordInstance($type, $data, self::STATE_LOADED);
+ return $obj;
+ }
+
+ /**
+ * Create an instance of ActiveRecord class given by $type.
+ * This static method should only be used internally within core ActiveRecord classes.
+ */
+ public static function createRecordInstance($type, $data=array(), $state=self::STATE_NEW)
+ {
$obj = Prado::createComponent($type);
- $tableInfo = $this->getRecordGateway()->getRecordTableInfo($obj);
- foreach($data as $name=>$value)
- $obj->setColumnValue($name,$value);
- /*
- foreach($tableInfo->getColumns()->getKeys() as $name)
- {
- if(isset($data[$name]))
- $obj->setColumnValue($name,$data[$name]);
- }*/
- $obj->_readOnly = $tableInfo->getIsView();
- $this->getRecordManager()->getObjectStateRegistry()->registerClean($obj);
+ $obj->_objectState=$state;
+ $tableInfo = $obj->getRecordGateway()->getRecordTableInfo($obj);
+ $obj->_readOnly=$tableInfo->getIsView();
+ if(!empty($data))
+ $obj->copyFrom($data);
return $obj;
}
@@ -642,9 +684,9 @@ abstract class TActiveRecord extends TComponent
* @param array method call arguments.
* @return TActiveRecordRelation, null if the context or the handler doesn't exist
*/
- protected function getRelationHandler($property,$args=array())
+ protected function getRelationHandler($name,$args=array())
{
- if(($context=$this->getRelationContext($property)) !== null)
+ if(($context=$this->getRelationContext($name)) !== null)
{
$criteria = $this->getCriteria(count($args)>0 ? $args[0] : null, array_slice($args,1));
return $context->getRelationHandler($criteria);
@@ -662,10 +704,10 @@ abstract class TActiveRecord extends TComponent
* the active record relationships for given property, null if invalid relationship
* @since 3.1.2
*/
- protected function getRelationContext($property)
+ protected function getRelationContext($name)
{
- if(($relation=$this->getRelation($property))!==null)
- return new TActiveRecordRelationContext($this,strtolower($property),$relation);
+ if(list($property, $relation) = $this->getRelation($name))
+ return new TActiveRecordRelationContext($this,$property,$relation);
else
return null;
}
@@ -825,6 +867,36 @@ abstract class TActiveRecord extends TComponent
}
/**
+ * Raised before the record attempt to insert its data into the database.
+ * To prevent the insert operation, set the TActiveRecordChangeEventParameter::IsValid parameter to false.
+ * @param TActiveRecordChangeEventParameter event parameter to be passed to the event handlers
+ */
+ public function onInsert($param)
+ {
+ $this->raiseEvent('OnInsert', $this, $param);
+ }
+
+ /**
+ * Raised before the record attempt to delete its data from the database.
+ * To prevent the insert operation, set the TActiveRecordChangeEventParameter::IsValid parameter to false.
+ * @param TActiveRecordChangeEventParameter event parameter to be passed to the event handlers
+ */
+ public function onDelete($param)
+ {
+ $this->raiseEvent('OnDelete', $this, $param);
+ }
+
+ /**
+ * Raised before the record attempt to update its data in the database.
+ * To prevent the insert operation, set the TActiveRecordChangeEventParameter::IsValid parameter to false.
+ * @param TActiveRecordChangeEventParameter event parameter to be passed to the event handlers
+ */
+ public function onUpdate($param)
+ {
+ $this->raiseEvent('OnUpdate', $this, $param);
+ }
+
+ /**
* Retrieves the column value according to column name.
* This method is used internally.
* @param string the column name (as defined in database schema)
@@ -885,4 +957,41 @@ abstract class TActiveRecord extends TComponent
return isset(self::$_relations[get_class($this)][strtolower($property)]);
}
}
+
+/**
+ * TActiveRecordChangeEventParameter class
+ *
+ * TActiveRecordChangeEventParameter encapsulates the parameter data for
+ * ActiveRecord change commit events that are broadcasted. The following change events
+ * may be raise: {@link TActiveRecord::OnInsert}, {@link TActiveRecord::OnUpdate} and
+ * {@link TActiveRecord::OnDelete}. The {@link setIsValid IsValid} parameter can
+ * be set to false to prevent the requested change event to be performed.
+ *
+ * @author Wei Zhuo<weizhuo@gmail.com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord
+ * @since 3.1.2
+ */
+
+class TActiveRecordChangeEventParameter extends TEventParameter
+{
+ private $_isValid=true;
+
+ /**
+ * @return boolean whether the event should be performed.
+ */
+ public function getIsValid()
+ {
+ return $this->_isValid;
+ }
+
+ /**
+ * @param boolean set to false to prevent the event.
+ */
+ public function setIsValid($value)
+ {
+ $this->_isValid = TPropertyValue::ensureBoolean($value);
+ }
+}
+
?> \ No newline at end of file
diff --git a/framework/Data/ActiveRecord/TActiveRecordManager.php b/framework/Data/ActiveRecord/TActiveRecordManager.php
index ab6fe88d..3790773d 100644
--- a/framework/Data/ActiveRecord/TActiveRecordManager.php
+++ b/framework/Data/ActiveRecord/TActiveRecordManager.php
@@ -14,11 +14,10 @@ Prado::using('System.Data.TDbConnection');
Prado::using('System.Data.ActiveRecord.TActiveRecord');
Prado::using('System.Data.ActiveRecord.Exceptions.TActiveRecordException');
Prado::using('System.Data.ActiveRecord.TActiveRecordGateway');
-Prado::using('System.Data.ActiveRecord.TActiveRecordStateRegistry');
/**
- * TActiveRecordManager provides the default DB connection, default object state
- * registry, default active record gateway, and table meta data inspector.
+ * TActiveRecordManager provides the default DB connection,
+ * default active record gateway, and table meta data inspector.
*
* The default connection can be set as follows:
* <code>
@@ -38,7 +37,6 @@ Prado::using('System.Data.ActiveRecord.TActiveRecordStateRegistry');
*/
class TActiveRecordManager extends TComponent
{
- private $_objectRegistry;
private $_gateway;
private $_meta=array();
private $_connection;
@@ -91,24 +89,6 @@ class TActiveRecordManager extends TComponent
}
/**
- * @return TActiveRecordStateRegistry record object registry.
- */
- public function getObjectStateRegistry()
- {
- if(is_null($this->_objectRegistry))
- $this->_objectRegistry = $this->createObjectStateRegistry();
- return $this->_objectRegistry;
- }
-
- /**
- * @return TActiveRecordStateRegistry default object registry.
- */
- protected function createObjectStateRegistry()
- {
- return new TActiveRecordStateRegistry();
- }
-
- /**
* @return TActiveRecordGateway record gateway.
*/
public function getRecordGateway()
diff --git a/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php b/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php
deleted file mode 100644
index 7a285274..00000000
--- a/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php
+++ /dev/null
@@ -1,243 +0,0 @@
-<?php
-/**
- * TActiveRecordStateRegistry class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2007 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Data.ActiveRecord
- */
-
-/**
- * Active record Unit of Work class and Identity Map.
- *
- * Maintains a list of objects affected by a business transaction and
- * coordinates the writing out of changes and the resolution of concurrency problems.
- *
- * This registry keeps track of everything you do during a business transaction
- * that can affect the database. When you're done, it figures out everything that
- * needs to be done to alter the database as a result of your work.
- *
- * The object can only be in one of the four states: "new", "clean", "dirty" or "removed".
- * A "new" object is one that is created not by loading the record from database.
- * A "clean" object is one that is created by loading the record from datase.
- * A "dirty" object is one that is marked as dirty or a "clean" object that has
- * its internal state altered (done by using == object comparision).
- * A "removed" object is one that is marked for deletion.
- *
- * See the "Active Record Object States.png" in the docs directory for state
- * transition diagram.
- *
- * @author Wei Zhuo <weizho[at]gmail[dot]com>
- * @version $Id$
- * @package System.Data.ActiveRecord
- * @since 3.1
- */
-class TActiveRecordStateRegistry
-{
- private $_cleanObjects=array();
- private $_removedObjects;
- //private $_cachedObjects=array();
- /**
- * Initialize the registry.
- */
- public function __construct()
- {
- $this->_removedObjects = new TList;
- }
-
- /**
- * @return string hash of the data.
- */
- protected function getObjectDataKey($data)
- {
- return sprintf('%x',crc32(serialize($data)));
- }
-
- /**
- * Ensure that object is not null.
- */
- protected function assertNotNull($obj)
- {
- if(is_null($obj))
- throw new TActiveRecordException('ar_object_must_not_be_null');
- }
-
- /**
- * Register the object for deletion, when the object invokes its delete() method
- * the corresponding row in the database is deleted.
- * @param TActiveRecord existing active record.
- * @throws TActiveRecordException if object is null.
- */
- public function registerRemoved($obj)
- {
- $this->assertNotNull($obj);
- $found=false;
- foreach($this->_cleanObjects as $i=>$cache)
- {
- if($cache[0]===$obj)
- {
- unset($this->_cleanObjects[$i]);
- $found=true;
- }
- }
- if(!$found)
- throw new TActiveRecordException('ar_object_must_be_retrieved_before_delete');
- if(!$this->_removedObjects->contains($obj))
- $this->_removedObjects->add($obj);
- }
-
- /**
- * Register a clean object attached to a specific data that was used to
- * populate the object. This acts as an object cache.
- * @param TActiveRecord new clean object.
- */
- public function registerClean($obj)
- {
- $this->removeCleanOrDirty($obj);
- if($this->isRemovedObject($obj))
- throw new TActiveRecordException('ar_object_marked_for_removal');
- $this->_cleanObjects[] = array($obj, clone($obj));
- }
-
- /**
- * Remove the object from dirty state.
- * @param TActiveRecord object to remove.
- */
- protected function removeDirty($obj)
- {
- $this->assertNotNull($obj);
- foreach($this->_cleanObjects as $i=>$cache)
- if($cache[0]===$obj && $obj != $cache[1])
- unset($this->_cleanObjects[$i]);
- }
-
- /**
- * Remove object from clean state.
- * @param TActiveRecord object to remove.
- */
- protected function removeClean($obj)
- {
- $this->assertNotNull($obj);
- foreach($this->_cleanObjects as $i=>$cache)
- if($cache[0]===$obj && $obj == $cache[1])
- unset($this->_cleanObjects[$i]);
- }
-
- /**
- * Remove object from dirty and clean state.
- * @param TActiveRecord object to remove.
- */
- protected function removeCleanOrDirty($obj)
- {
- $this->assertNotNull($obj);
- foreach($this->_cleanObjects as $i=>$cache)
- if($cache[0]===$obj)
- unset($this->_cleanObjects[$i]);
- }
-
- /**
- * Remove object from removed state.
- * @param TActiveRecord object to remove.
- */
- protected function removeRemovedObject($obj)
- {
- $this->_removedObjects->remove($obj);
- }
-
- /**
- * Test whether an object is dirty or has been modified.
- * @param TActiveRecord object to test.
- * @return boolean true if the object is dirty, false otherwise.
- */
- public function isDirtyObject($obj)
- {
- foreach($this->_cleanObjects as $cache)
- if($cache[0] === $obj)
- return $obj != $cache[1];
- return false;
- }
-
- /**
- * Test whether an object is in the clean state.
- * @param TActiveRecord object to test.
- * @return boolean true if object is clean, false otherwise.
- */
- public function isCleanObject($obj)
- {
- foreach($this->_cleanObjects as $cache)
- if($cache[0] === $obj)
- return $obj == $cache[1];
- return false;
- }
-
- /**
- * Test whether an object is a new instance.
- * @param TActiveRecord object to test.
- * @return boolean true if object is newly created, false otherwise.
- */
- public function isNewObject($obj)
- {
- if($this->isRemovedObject($obj)) return false;
- foreach($this->_cleanObjects as $cache)
- if($cache[0] === $obj)
- return false;
- return true;
- }
-
- /**
- * @param TActiveRecord object to test.
- * @return boolean true if object is dirty or is new.
- */
- public function shouldPersistObject($obj)
- {
- return $this->isDirtyObject($obj) || $this->isNewObject($obj);
- }
-
- /**
- * Test whether an object is marked for deletion.
- * @param TActiveRecord object to test.
- * @return boolean true if object is marked for deletion, false otherwise.
- */
- public function isRemovedObject($obj)
- {
- return $this->_removedObjects->contains($obj);
- }
-
- /**
- * Commit the object to database:
- * * a new record is inserted if the object is new, object becomes clean.
- * * the record is updated if the object is dirty, object becomes clean.
- * * the record is deleted if the object is marked for removal.
- *
- * @param TActiveRecord record object.
- * @param TActiveRecordGateway database gateway
- * @return boolean true if commit was successful, false otherwise.
- */
- public function commit($record,$gateway)
- {
- $rowsAffected=false;
-
- if($this->isRemovedObject($record))
- {
- $rowsAffected = $gateway->delete($record);
- if($rowsAffected)
- $this->removeRemovedObject($record);
- }
- else
- {
- if($this->isDirtyObject($record))
- $rowsAffected = $gateway->update($record);
- else if($this->isNewObject($record))
- $rowsAffected = $gateway->insert($record);
-
- if($rowsAffected)
- $this->registerClean($record);
- }
- return (boolean)$rowsAffected;
- }
-}
-
-?> \ No newline at end of file
diff --git a/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js b/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js
index 8f480d3d..87b8ddde 100644
--- a/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js
+++ b/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js
@@ -283,7 +283,7 @@ Prado.WebUI.TInPlaceTextBox = Base.extend(
}
}
},
-
+
setReadOnly : function(id, value)
{
var textbox = Prado.WebUI.TInPlaceTextBox.textboxes[id];
@@ -291,5 +291,5 @@ Prado.WebUI.TInPlaceTextBox = Base.extend(
{
textbox.readOnly=value;
}
- },
+ }
}); \ No newline at end of file
diff --git a/tests/simple_unit/ActiveRecord/ForeignKeyTestCase.php b/tests/simple_unit/ActiveRecord/ForeignKeyTestCase.php
index 2e4bee2d..d8017aeb 100644
--- a/tests/simple_unit/ActiveRecord/ForeignKeyTestCase.php
+++ b/tests/simple_unit/ActiveRecord/ForeignKeyTestCase.php
@@ -159,7 +159,6 @@ class ForeignKeyTestCase extends UnitTestCase
function test_self_reference_fk()
{
$item = ItemRecord::finder()->withRelated_Items()->findByPk(1);
-
$this->assertNotNull($item);
$this->assertEqual($item->name, "Professional Work Attire");
diff --git a/tests/simple_unit/ActiveRecord/MultipleForeignKeyTestCase.php b/tests/simple_unit/ActiveRecord/MultipleForeignKeyTestCase.php
index 16036b9f..77408631 100644
--- a/tests/simple_unit/ActiveRecord/MultipleForeignKeyTestCase.php
+++ b/tests/simple_unit/ActiveRecord/MultipleForeignKeyTestCase.php
@@ -32,7 +32,7 @@ class Table1 extends MultipleFKSqliteRecord
public $fk3;
public $object1;
- public $object2;
+ //public $object2; //commented out for testing __get/__set
public $object3;
public static $RELATIONS = array
@@ -57,7 +57,7 @@ class Table2 extends MultipleFKSqliteRecord
public $field1;
private $_state1;
- public $state2;
+ //public $state2; //commented out for testing __get/__set
public $state3;
public static $RELATIONS = array
@@ -174,6 +174,19 @@ class MultipleForeignKeyTestCase extends UnitTestCase
$this->assertEqual($obj->parent_category->cat_id, 1);
}
+
+ function testLazyLoadingGetterSetter_hasMany()
+ {
+ $arr = Table2::finder()->findByPk(2);
+
+ $this->assertNotNull($arr->state2); //lazy load
+ $this->assertEqual(count($arr->state2), 1);
+ $this->assertEqual($arr->state2[0]->id, "1");
+ $this->assertNotNull($arr->state2[0]->object2);
+ $this->assertEqual($arr->state2[0]->object2->id, "2");
+
+ $this->assertNotIdentical($arr, $arr->state2[0]->object2);
+ }
}
?> \ No newline at end of file