summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwei <>2007-05-01 03:19:30 +0000
committerwei <>2007-05-01 03:19:30 +0000
commit419f0815c85a40639ac82c1ce05c80186a64dc55 (patch)
treee875e519451b617a822bece75e24d23d3b93236e
parent595a0acc2554da4c4c52f065dc76893c241f2624 (diff)
remove identity map in active record.
-rw-r--r--HISTORY1
-rw-r--r--UPGRADE2
-rw-r--r--framework/Data/ActiveRecord/Relations/TActiveRecordHasManyAssociation.php17
-rw-r--r--framework/Data/ActiveRecord/TActiveRecord.php80
-rw-r--r--framework/Data/ActiveRecord/TActiveRecordStateRegistry.php33
-rw-r--r--framework/Web/UI/WebControls/TRegularExpressionValidator.php22
-rw-r--r--tests/simple_unit/ActiveRecord/UserRecordTestCase.php7
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: <div> tags are used instead of <span> 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 <div> instead of <span>
-
+- 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
@@ -151,6 +151,35 @@ abstract class TActiveRecord extends TComponent
}
/**
+ * 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.
* This means that event handlers bound to these finder instances are class wide.
@@ -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.
*/
@@ -49,37 +49,6 @@ class TActiveRecordStateRegistry
}
/**
- * 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.
*/
protected function getObjectDataKey($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,12 +87,32 @@ 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 @@
-<?php
-
+<?php
Prado::using('System.Data.ActiveRecord.TActiveRecord');
require_once(dirname(__FILE__).'/records/UserRecord.php');
@@ -17,13 +16,13 @@ class UserRecordTestCase extends UnitTestCase
$this->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()