From 419f0815c85a40639ac82c1ce05c80186a64dc55 Mon Sep 17 00:00:00 2001 From: wei <> Date: Tue, 1 May 2007 03:19:30 +0000 Subject: remove identity map in active record. --- HISTORY | 1 + UPGRADE | 2 +- .../Relations/TActiveRecordHasManyAssociation.php | 17 ++--- framework/Data/ActiveRecord/TActiveRecord.php | 80 ++++++++++++---------- .../ActiveRecord/TActiveRecordStateRegistry.php | 33 +-------- .../UI/WebControls/TRegularExpressionValidator.php | 22 +++++- .../ActiveRecord/UserRecordTestCase.php | 7 +- 7 files changed, 77 insertions(+), 85 deletions(-) diff --git a/HISTORY b/HISTORY index 4e413d25..996b994d 100644 --- a/HISTORY +++ b/HISTORY @@ -3,6 +3,7 @@ Version 3.1.0 RC To be released BUG: Ticket#605 - TDatePicker don't works in 3.1.b on linux server (Wei) BUG: Ticket#606 - TColorPicker bug in Full mode (Wei) ENH: Add javascript references for "slider" and "dragdrop" for TClientScript::PradoScripts (Wei) +ENH: Added PatternModifiers property to TRegularExpressionValidator (Wei) CHG:
tags are used instead of when TDataList.RepeatLayout is Raw (Qiang) CHG: changed comment tag to (Qiang) diff --git a/UPGRADE b/UPGRADE index 6e12c56f..f18cb74f 100644 --- a/UPGRADE +++ b/UPGRADE @@ -17,7 +17,7 @@ Upgrading from v3.1b - Comment tag (introduced in v3.1a) is changed to - When TDataList.RepeatLayout is Raw, the items will render
instead of - +- TActiveRecord finder methods will always return a new object instance (identity mapping was removed). Upgrading from v3.1a --------------------- diff --git a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php index bb2cc583..456848fe 100644 --- a/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php +++ b/framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php @@ -73,6 +73,8 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation { $criteria = $this->getContext()->getCriteria(); $finder = $this->getContext()->getForeignRecordFinder(); + $registry = $finder->getRecordManager()->getObjectStateRegistry(); + $type = get_class($finder); $command = $this->createCommand($criteria, $foreignKeys,$indexValues,$sourceKeys); $srcProps = array_keys($sourceKeys); $collections=array(); @@ -81,22 +83,13 @@ class TActiveRecordHasManyAssociation extends TActiveRecordRelation $hash = $this->getObjectHash($row, $srcProps); foreach($srcProps as $column) unset($row[$column]); - $collections[$hash][] = $this->populateObject($finder, $row); + $obj = new $type($row); + $collections[$hash][] = $obj; + $registry->registerClean($obj); } $this->setResultCollection($results, $collections, array_values($sourceKeys)); } - - protected function populateObject($finder, $data) - { - $registry = $finder->getRecordManager()->getObjectStateRegistry(); - if(!is_null($obj = $registry->getCachedInstance($data, false))) - return $obj; - $gateway = $finder->getRecordManager()->getRecordGateway(); - $type = get_class($finder); - $obj = new $type($data); - return $registry->addCachedInstance($data,$obj); - } /** * @param TSqlCriteria diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php index 2ff3f1d4..cb3a1ebe 100644 --- a/framework/Data/ActiveRecord/TActiveRecord.php +++ b/framework/Data/ActiveRecord/TActiveRecord.php @@ -150,6 +150,35 @@ abstract class TActiveRecord extends TComponent $this->_connection=$connection; } + /** + * Compare two records using their primary key values (all column values if + * table does not defined primary keys). The default uses simple == for + * comparison of their values. Set $strict=true for identity comparison. + * @param TActiveRecord another record to compare with. + * @param boolean true to perform strict identity comparison + * @return boolean true if $record equals, false otherwise. + */ + public function equals(TActiveRecord $record, $strict=false) + { + $thisClass=__CLASS__; + if(!($record instanceof $thisClass)) + return false; + $tableInfo = $this->getRecordGateway()->getRecordTableInfo($this); + $pks = $tableInfo->getPrimaryKeys(); + $properties = count($pks) > 0 ? $pks : $tableInfo->getColumns()->getKeys(); + $equals=true; + foreach($properties as $prop) + { + if($strict) + $equals = $equals && $this->{$prop} === $record->{$prop}; + else + $equals = $equals && $this->{$prop} == $record->{$prop}; + if(!$equals) + return false; + } + return $equals; + } + /** * Returns the instance of a active record finder for a particular class. * The finder objects are static instances for each ActiveRecord class. @@ -210,7 +239,7 @@ abstract class TActiveRecord extends TComponent protected function commitChanges() { $registry = $this->getRecordManager()->getObjectStateRegistry(); - $gateway = $this->getRecordManager()->getRecordGateway(); + $gateway = $this->getRecordGateway(); if(!$this->_readOnly) $this->_readOnly = $gateway->getRecordTableInfo($this)->getIsView(); if($this->_readOnly) @@ -257,8 +286,7 @@ abstract class TActiveRecord extends TComponent { if(func_num_args() > 1) $keys = func_get_args(); - $gateway = $this->getRecordManager()->getRecordGateway(); - return $gateway->deleteRecordsByPk($this,(array)$keys); + return $this->getRecordGateway()->deleteRecordsByPk($this,(array)$keys); } @@ -272,8 +300,7 @@ abstract class TActiveRecord extends TComponent { $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; $criteria = $this->getCriteria($criteria,$parameters, $args); - $gateway = $this->getRecordManager()->getRecordGateway(); - return $gateway->deleteRecordsByCriteria($this, $criteria); + return $this->getRecordGateway()->deleteRecordsByCriteria($this, $criteria); } /** @@ -284,28 +311,19 @@ abstract class TActiveRecord extends TComponent */ protected function populateObject($type, $data) { - if(empty($data)) return null; - $registry = $this->getRecordManager()->getObjectStateRegistry(); - - //try the cache (the cache object must be clean) - if(!is_null($obj = $registry->getCachedInstance($data))) - return $obj; - - $gateway = $this->getRecordManager()->getRecordGateway(); - + if(empty($data)) + return null; //create and populate the object $obj = Prado::createComponent($type); - $tableInfo = $gateway->getRecordTableInfo($obj); + $tableInfo = $this->getRecordGateway()->getRecordTableInfo($obj); foreach($tableInfo->getColumns()->getKeys() as $name) { if(isset($data[$name])) $obj->{$name} = $data[$name]; } - $obj->_readOnly = $tableInfo->getIsView(); - - //cache it - return $registry->addCachedInstance($data,$obj); + $this->getRecordManager()->getObjectStateRegistry()->registerClean($obj); + return $obj; } /** @@ -341,8 +359,7 @@ abstract class TActiveRecord extends TComponent { $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; $criteria = $this->getCriteria($criteria,$parameters, $args); - $gateway = $this->getRecordManager()->getRecordGateway(); - $data = $gateway->findRecordsByCriteria($this,$criteria); + $data = $this->getRecordGateway()->findRecordsByCriteria($this,$criteria); return $this->populateObject(get_class($this), $data); } @@ -358,8 +375,7 @@ abstract class TActiveRecord extends TComponent $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; if($criteria!==null) $criteria = $this->getCriteria($criteria,$parameters, $args); - $gateway = $this->getRecordManager()->getRecordGateway(); - $result = $gateway->findRecordsByCriteria($this,$criteria,true); + $result = $this->getRecordGateway()->findRecordsByCriteria($this,$criteria,true); return $this->collectObjects($result); } @@ -379,8 +395,7 @@ abstract class TActiveRecord extends TComponent { if(func_num_args() > 1) $keys = func_get_args(); - $gateway = $this->getRecordManager()->getRecordGateway(); - $data = $gateway->findRecordByPK($this,$keys); + $data = $this->getRecordGateway()->findRecordByPK($this,$keys); return $this->populateObject(get_class($this), $data); } @@ -405,8 +420,7 @@ abstract class TActiveRecord extends TComponent { if(func_num_args() > 1) $keys = func_get_args(); - $gateway = $this->getRecordManager()->getRecordGateway(); - $result = $gateway->findRecordsByPks($this,(array)$keys); + $result = $this->getRecordGateway()->findRecordsByPks($this,(array)$keys); return $this->collectObjects($result); } @@ -422,8 +436,7 @@ abstract class TActiveRecord extends TComponent { $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; $criteria = $this->getCriteria($sql,$parameters, $args); - $gateway = $this->getRecordManager()->getRecordGateway(); - $result = $gateway->findRecordsBySql($this,$criteria); + $result = $this->getRecordGateway()->findRecordsBySql($this,$criteria); return $this->collectObjects($result); } @@ -441,8 +454,7 @@ abstract class TActiveRecord extends TComponent */ public function findAllByIndex($criteria,$fields,$values) { - $gateway = $this->getRecordManager()->getRecordGateway(); - $result = $gateway->findRecordsByIndex($this,$criteria,$fields,$values); + $result = $this->getRecordGateway()->findRecordsByIndex($this,$criteria,$fields,$values); return $this->collectObjects($result); } @@ -457,8 +469,7 @@ abstract class TActiveRecord extends TComponent $args = func_num_args() > 1 ? array_slice(func_get_args(),1) : null; if($criteria!==null) $criteria = $this->getCriteria($criteria,$parameters, $args); - $gateway = $this->getRecordManager()->getRecordGateway(); - return $gateway->countRecords($this,$criteria); + return $this->getRecordGateway()->countRecords($this,$criteria); } /** @@ -521,8 +532,7 @@ abstract class TActiveRecord extends TComponent else return null;//throw new TActiveRecordException('ar_invalid_finder_method',$method); - $gateway = $this->getRecordManager()->getRecordGateway(); - $criteria = $gateway->getCommand($this)->createCriteriaFromString($method, $condition, $args); + $criteria = $this->getRecordGateway()->getCommand($this)->createCriteriaFromString($method, $condition, $args); if($delete) return $this->deleteAll($criteria); else diff --git a/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php b/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php index 691090dc..d6f24961 100644 --- a/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php +++ b/framework/Data/ActiveRecord/TActiveRecordStateRegistry.php @@ -39,7 +39,7 @@ class TActiveRecordStateRegistry { private $_cleanObjects=array(); private $_removedObjects; - private $_cachedObjects=array(); + //private $_cachedObjects=array(); /** * Initialize the registry. */ @@ -48,37 +48,6 @@ class TActiveRecordStateRegistry $this->_removedObjects = new TList; } - /** - * Get the cached object for given type and row data. The cached object - * must also be clean. - * @param mixed row data fetched - * @return TActiveRecord cached object if found, null otherwise. - */ - public function getCachedInstance($data,$mustBeClean=true) - { - $key = $this->getObjectDataKey($data); - if(isset($this->_cachedObjects[$key])) - { - $obj = $this->_cachedObjects[$key]; - if(!($mustBeClean && !$this->getIsCleanObject($obj))) - return $obj; - } - } - - /** - * Cache the object that corresponding to the fetched row data. - * @param mixed row data fetched. - * @param TActiveRecord object to be cached. - * @return TActiveRecord cached object. - */ - public function addCachedInstance($data,$obj) - { - $key = $this->getObjectDataKey($data); - $this->registerClean($obj); - $this->_cachedObjects[$key]=$obj; - return $obj; - } - /** * @return string hash of the data. */ diff --git a/framework/Web/UI/WebControls/TRegularExpressionValidator.php b/framework/Web/UI/WebControls/TRegularExpressionValidator.php index c4f7ceac..2f65d6b6 100644 --- a/framework/Web/UI/WebControls/TRegularExpressionValidator.php +++ b/framework/Web/UI/WebControls/TRegularExpressionValidator.php @@ -87,11 +87,31 @@ class TRegularExpressionValidator extends TBaseValidator if(($value=$this->getValidationValue($this->getValidationTarget()))==='') return true; if(($expression=$this->getRegularExpression())!=='') - return preg_match("/^$expression\$/",$value); + { + $mods = $this->getPatternModifiers(); + return preg_match("/^$expression\$/{$mods}",$value); + } else return true; } + /** + * @param string pattern modifiers, + * see http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php + */ + public function setPatternModifiers($value) + { + $this->setViewState('PatternModifiers', $value); + } + + /** + * @return string pattern modifiers, no modifiers by default. + */ + public function getPatternModifiers() + { + return $this->getViewState('PatternModifiers', ''); + } + /** * Returns an array of javascript validator options. * @return array javascript validator options. diff --git a/tests/simple_unit/ActiveRecord/UserRecordTestCase.php b/tests/simple_unit/ActiveRecord/UserRecordTestCase.php index 483dc42f..057455f7 100644 --- a/tests/simple_unit/ActiveRecord/UserRecordTestCase.php +++ b/tests/simple_unit/ActiveRecord/UserRecordTestCase.php @@ -1,5 +1,4 @@ -assertNotNull($user1); } - function test_same_data_returns_same_object() + function test_same_data_returns_different_instance() { $user1 = UserRecord::finder()->findByPk('admin'); $this->assertNotNull($user1); $user2 = UserRecord::finder()->findByPk('admin'); - $this->assertTrue($user1===$user2); + $this->assertFalse($user1===$user2); } function testFindByPk_returns_null() -- cgit v1.2.3