[limb-svn] r6423 - in 3.x/trunk/limb/active_record: src tests/cases
svn at limb-project.com
svn at limb-project.com
Tue Oct 16 11:49:09 MSD 2007
Author: serega
Date: 2007-10-16 11:49:09 +0400 (Tue, 16 Oct 2007)
New Revision: 6423
URL: http://fisheye.limb-project.com/changelog/limb/?cs=6423
Modified:
3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php
3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php
3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php
3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php
3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php
3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordTest.class.php
Log:
-- lmbActiveRecord refactoring due to recent lmbObject changes:
* lmbActiveRecord :: has() now properly works for all db fields and relations and always returns true if such db field or relation exists.
* lmbActiveRecord :: $_raw_value_objects() removed for simpler design.
* lmbActiveRecord :: _setDbValue() removed. lmbObject :: _setRaw() used instead.
* Note what lmbActiveRecord also throws exceptions from get('no_such_property') and getNoSuchProperty() as well as lmbObject does
Modified: 3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php
===================================================================
--- 3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php 2007-10-16 07:43:25 UTC (rev 6422)
+++ 3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php 2007-10-16 07:49:09 UTC (rev 6423)
@@ -65,6 +65,10 @@
*/
protected $_db_table_name;
/**
+ * @var array list of database table fields
+ */
+ protected $_db_table_fields = array();
+ /**
* @var boolean reflects new or loaded status of an object
*/
protected $_is_new = true;
@@ -97,6 +101,14 @@
*/
protected $_composed_of = array();
/**
+ * @var array all relations of an object
+ */
+ protected $_relations = array();
+ /**
+ * @var array all relations of an object to any other object. Like "has one", "many belongs to", "belongs_to".
+ */
+ protected $_single_object_relations = array();
+ /**
* @var boolean true during the object's saving procedure
*/
protected $_is_being_saved = false;
@@ -150,12 +162,6 @@
protected $_listeners = array();
/**
- * Note, this property is not guarded with "_" prefix since we need it to be imported/exported
- * @var array An array of attached value objects
- */
- protected $raw_value_objects = array();
-
- /**
* Constructor.
* Creates an instance of lmbActiveRecord object in different ways depending on passed argument
* <code>
@@ -174,12 +180,17 @@
$this->_defineRelations();
+ // For optimization purposes
+ $this->_relations = $this->_getAllRelations();
+ $this->_single_object_relations = $this->_getSingleObjectRelations();
+
if(is_object($conn))
$this->_db_conn = $conn;
else
$this->_db_conn = self :: getDefaultConnection();
$this->_db_meta_info = lmbToolkit :: instance()->getActiveRecordMetaInfo($this, $this->_db_conn);
+ $this->_db_table_fields = $this->_db_meta_info->getDbColumnsNames();
$this->_db_table = $this->_db_meta_info->getDbTable();
$this->_db_table_name = $this->_db_table->getTableName();
@@ -305,9 +316,8 @@
*/
function getRelationInfo($relation)
{
- $relations = $this->_getAllRelations();
- if(isset($relations[$relation]))
- return $relations[$relation];
+ if(isset($this->_relations[$relation]))
+ return $this->_relations[$relation];
}
protected function _getAllRelations()
@@ -319,6 +329,15 @@
$this->_many_belongs_to,
$this->_composed_of);
}
+
+ protected function _getSingleObjectRelations()
+ {
+ return array_merge($this->_has_one,
+ $this->_belongs_to,
+ $this->_many_belongs_to,
+ $this->_composed_of);
+ }
+
/**
* Returns all relations info for one-to-many
* @return array
@@ -466,15 +485,18 @@
protected function __call($method, $args = array())
{
- if($property = $this->_mapGetToProperty($method))
- return $this->get($property);
+ try
+ {
+ return parent :: __call($method, $args);
- if($property = $this->mapAddToProperty($method))
+ }
+ catch(lmbNoSuchMethodException $e)
{
- $this->_addToProperty($property, $args[0]);
- return;
+ if($property = $this->mapAddToProperty($method))
+ $this->_addToProperty($property, $args[0]);
+ else
+ throw $e;
}
- return parent :: __call($method, $args);
}
protected function _addToProperty($property, $value)
@@ -491,30 +513,30 @@
return in_array($property, $this->_lazy_attributes);
}
- protected function _hasLazyAttributes()
- {
- if(!$this->_lazy_attributes)
- return false;
-
- foreach($this->_lazy_attributes as $attribute)
- if(!$this->hasAttribute($attribute))
- return true;
-
- return false;
- }
-
protected function _loadLazyAttribute($property)
{
$record = $this->_db_table->selectRecordById($this->getId(), array($property));
$processed = $this->_decodeDbValues($record);
- $this->_setDbValue($property, $processed[$property]);
+ $this->_setRaw($property, $processed[$property]);
}
protected function _loadLazyAttributes()
{
foreach($this->_lazy_attributes as $attribute)
- $this->_loadLazyAttribute($attribute);
+ {
+ if(!parent :: has($attribute))
+ $this->_loadLazyAttribute($attribute);
+ }
}
+
+ function has($property)
+ {
+ return parent :: has($property)
+ || in_array($property, $this->_db_table_fields)
+ || $this->_izLazyAttribute($property)
+ || $this->_hasRelation($property);
+ }
+
/**
* Generic magic getter for any attribute
* @param string property name
@@ -522,17 +544,26 @@
*/
function get($property)
{
- if(!$this->isNew() && $this->_izLazyAttribute($property) && !$this->hasAttribute($property))
+ if(!$this->isNew() && $this->_izLazyAttribute($property) && !parent :: has($property))
$this->_loadLazyAttribute($property);
if($this->_hasValueObjectRelation($property))
return $this->_getValueObject($property);
- $value = parent :: get($property);
+ try
+ {
+ return parent :: get($property);
+ }
+ catch(lmbNoSuchPropertyException $e)
+ {
+ }
- if(isset($value))
- return $value;
+ if(in_array($property, $this->_db_table_fields))
+ return null;
+ if($this->isNew() && $this->_hasSingleObjectRelation($property))
+ return null;
+
if(!$this->isNew() && $this->_hasBelongsToRelation($property))
{
$object = $this->_loadBelongsToObject($property);
@@ -560,7 +591,8 @@
$this->_setRaw($property, $collection);
return $collection;
}
- $exists = false;
+
+ throw $e;
}
function createRelationCollection($relation, $criteria = null)
@@ -575,6 +607,16 @@
return new lmbARManyToManyCollection($relation, $this, $criteria, $this->_db_conn);
}
+ protected function _hasRelation($property)
+ {
+ return isset($this->_relations[$property]);
+ }
+
+ protected function _hasSingleObjectRelation($property)
+ {
+ return isset($this->_single_object_relations[$property]);
+ }
+
protected function _hasCollectionRelation($relation)
{
return $this->_hasOneToManyRelation($relation) ||
@@ -600,14 +642,11 @@
$collection->set($value);
}
else
+ {
parent :: set($property, $value);
- }
- protected function _setRaw($property, $value)
- {
- parent :: _setRaw($property, $value);
-
- $this->_markDirtyProperty($property);
+ $this->_markDirtyProperty($property);
+ }
}
protected function _markDirtyProperty($property)
@@ -705,7 +744,7 @@
*/
function mapFieldToProperty($field)
{
- foreach($this->_getAllRelations() as $property => $info)
+ foreach($this->_relations as $property => $info)
{
if(isset($info['field']) && $info['field'] == $field)
return $property;
@@ -783,13 +822,8 @@
$this->_many_belongs_to[$property]['can_be_null'];
}
- protected function _loadValueObject($property)
+ protected function _loadValueObject($property, $value)
{
- if(!isset($this->raw_value_objects[$this->_composed_of[$property]['field']]))
- return null;
-
- $value = $this->raw_value_objects[$this->_composed_of[$property]['field']];
-
return $this->_createValueObject($this->_composed_of[$property]['class'],
$value);
}
@@ -807,10 +841,14 @@
protected function _getValueObject($property)
{
+ if(!parent :: has($property))
+ return;
+
$value = $this->_getRaw($property);
+
if(!is_object($value))
{
- $object = $this->_loadValueObject($property);
+ $object = $this->_loadValueObject($property, $value);
$this->_setRaw($property, $object);
return $object;
}
@@ -1126,25 +1164,25 @@
protected function _getCallingClass()
{
//once PHP-5.3 LSB patch is available we'll use get_called_class
- //currently it's a quite a slow implementation and it doesn't
+ //currently it's a quite a slow implementation and it doesn't
//recognize multiline function calls
- $trace = debug_backtrace();
- $back = $trace[1];
+ $trace = debug_backtrace();
+ $back = $trace[1];
$method = $back['function'];
$fp = fopen($back['file'], 'r');
for($i=0; $i<$back['line']-1; $i++)
fgets($fp);
- $line = fgets($fp);
+ $line = fgets($fp);
fclose($fp);
if(!preg_match('~(\w+)\s*::\s*' . $method . '\s*\(~', $line, $m))
throw new lmbARException("Static calling class not found!(using multiline static method call?)");
if($m[1] == 'lmbActiveRecord')
throw new lmbARException("Found static class can't be lmbActiveRecord!");
- return $m[1];
+ return $m[1];
}
/**
@@ -1548,21 +1586,13 @@
$decoded = $this->_decodeDbValues($record);
foreach($decoded as $key => $value)
- $this->_setDbValue($key, $value);
+ $this->_setRaw($key, $value);
$this->_resetDirty();
$this->_is_new = false;
return true;
}
- protected function _setDbValue($key, $value)
- {
- if($this->_hasValueObjectRelation($key))
- $this->raw_value_objects[$key] = $value;
- else
- parent :: _setRaw($key, $value);
- }
-
protected function _decodeDbValues($record)
{
return $this->_db_meta_info->castDbValues($record);
@@ -1626,14 +1656,6 @@
$this->_is_being_destroyed = false;
}
- function remove($name)
- {
- parent :: remove($name);
-
- if(isset($this->raw_value_objects[$name]))
- unset($this->raw_value_objects[$name]);
- }
-
protected function _deleteDbRecord()
{
$this->_db_table->deleteById($this->getId());
@@ -1850,6 +1872,8 @@
function importRaw($source)
{
parent :: import($source);
+
+ $this->markDirty(true);
}
protected function _canImportProperty($property)
@@ -1908,7 +1932,7 @@
*/
function export()
{
- if(!$this->isNew() && $this->_hasLazyAttributes())
+ if(!$this->isNew() && sizeof($this->_lazy_attributes))
$this->_loadLazyAttributes();
return parent :: export();
Modified: 3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php 2007-10-16 07:43:25 UTC (rev 6422)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARAttributesLazyLoadingTest.class.php 2007-10-16 07:49:09 UTC (rev 6423)
@@ -67,15 +67,19 @@
protected function _checkLazyness($object, $annotation, $content)
{
- $this->assertTrue($object->hasAttribute('news_date'));
+ $this->assertTrue($object->has('news_date'));
- $this->assertFalse($object->hasAttribute('annotation'));
+ $this->assertFalse(array_key_exists('annotation', $object->exportRaw()));
+ $this->assertTrue($object->has('annotation'));
$this->assertEqual($object->getAnnotation(), $annotation);
- $this->assertTrue($object->hasAttribute('annotation'));
+ $this->assertTrue($object->has('annotation'));
+ $this->assertTrue(array_key_exists('annotation', $object->exportRaw()));
- $this->assertFalse($object->hasAttribute('content'));
+ $this->assertFalse(array_key_exists('content', $object->exportRaw()));
+ $this->assertTrue($object->has('content'));
$this->assertEqual($object->getContent(), $content);
- $this->assertTrue($object->hasAttribute('content'));
+ $this->assertTrue($object->has('content'));
+ $this->assertTrue(array_key_exists('content', $object->exportRaw()));
}
protected function _createActiveRecord($annotation, $content)
Modified: 3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php 2007-10-16 07:43:25 UTC (rev 6422)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbARImportTest.class.php 2007-10-16 07:49:09 UTC (rev 6423)
@@ -114,10 +114,14 @@
$object2 = new LazyTestOneTableObject($object->getId());
$object1->import($object2);
- $this->assertFalse($object1->hasAttribute('annotation'));
+ $this->assertFalse(array_key_exists('annotation', $object1->exportRaw()));
+ $this->assertTrue($object1->has('annotation'));
$this->assertEqual($object1->getAnnotation(), $annotation);
- $this->assertFalse($object1->hasAttribute('content'));
+ $this->assertTrue(array_key_exists('annotation', $object1->exportRaw()));
+ $this->assertFalse(array_key_exists('content', $object1->exportRaw()));
+ $this->assertTrue($object1->has('content'));
$this->assertEqual($object1->getContent(), $content);
+ $this->assertTrue(array_key_exists('content', $object1->exportRaw()));
}
function testImportOverwritesIdOfNewObject()
@@ -134,7 +138,6 @@
$this->assertEqual($object->getId(), 1000);
$this->assertEqual($object->getAnnotation(), 'Some annotation');
$this->assertEqual($object->getContent(), 'Some content');
- $this->assertNull($object->getJunk());
}
function testImportPreservesIdOfExistingObject()
Modified: 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php 2007-10-16 07:43:25 UTC (rev 6422)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbAROneToManyRelationsTest.class.php 2007-10-16 07:49:09 UTC (rev 6423)
@@ -92,6 +92,12 @@
$this->db->delete('lecture_for_test');
}
+ function testHas()
+ {
+ $lecture = new LectureForTest();
+ $this->assertTrue(isset($lecture['course']));
+ }
+
function testMapPropertyToField()
{
$course = new CourseForTest();
Modified: 3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php 2007-10-16 07:43:25 UTC (rev 6422)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbAROneToOneRelationsTest.class.php 2007-10-16 07:49:09 UTC (rev 6423)
@@ -74,6 +74,12 @@
$this->db->delete('social_security_for_test');
}
+ function testHas()
+ {
+ $person = new PersonForTest();
+ $this->assertTrue(isset($person['social_security']));
+ }
+
function testNewObjectReturnsNullChild()
{
$person = new PersonForTest();
Modified: 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordTest.class.php 2007-10-16 07:43:25 UTC (rev 6422)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordTest.class.php 2007-10-16 07:49:09 UTC (rev 6423)
@@ -127,6 +127,8 @@
{
$this->_cleanUp();
+ $this->conn->disconnect();
+
lmbToolkit :: restore();
}
@@ -135,6 +137,14 @@
$this->db->delete('test_one_table_object');
}
+ function testArrayAccessConsidersDbFields()
+ {
+ $object = new TestOneTableObject();
+ $this->assertTrue(isset($object['annotation']));
+ unset($object['annotation']); // Does not make any sence since db fields always available
+ $this->assertTrue(isset($object['annotation']));
+ }
+
function testSaveNewRecord()
{
$object = new TestOneTableObject();
More information about the limb-svn
mailing list