[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