[limb-svn] r5529 - in 3.x/trunk/limb/active_record: src tests/cases
svn at limb-project.com
svn at limb-project.com
Thu Apr 5 12:24:21 MSD 2007
Author: pachanga
Date: 2007-04-05 12:24:21 +0400 (Thu, 05 Apr 2007)
New Revision: 5529
URL: http://fisheye.limb-project.com/changelog/limb/?cs=5529
Modified:
3.x/trunk/limb/active_record/src/lmbARRecordSetDecorator.class.php
3.x/trunk/limb/active_record/src/lmbARRelationCollection.class.php
3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php
3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordSubclassingTest.class.php
Log:
-- much more robust single table inheritance support - lmbActiveRecord encodes inheritance path in 'kind' field and uses LIKE query in order to retrieve subclasses
-- lmbActiveRecord :: decodeInheritancePath($path) added, it explodes inheritance path and returns an array of classes
Modified: 3.x/trunk/limb/active_record/src/lmbARRecordSetDecorator.class.php
===================================================================
--- 3.x/trunk/limb/active_record/src/lmbARRecordSetDecorator.class.php 2007-04-04 15:08:50 UTC (rev 5528)
+++ 3.x/trunk/limb/active_record/src/lmbARRecordSetDecorator.class.php 2007-04-05 08:24:21 UTC (rev 5529)
@@ -48,8 +48,9 @@
protected function _createObject($record)
{
- if($class = $record->get(lmbActiveRecord :: getInheritanceField()))
+ if($path = $record->get(lmbActiveRecord :: getInheritanceField()))
{
+ $class = end(lmbActiveRecord :: decodeInheritancePath($path));
if(!class_exists($class))
throw new lmbException("Class '$class' not found");
return new $class;
Modified: 3.x/trunk/limb/active_record/src/lmbARRelationCollection.class.php
===================================================================
--- 3.x/trunk/limb/active_record/src/lmbARRelationCollection.class.php 2007-04-04 15:08:50 UTC (rev 5528)
+++ 3.x/trunk/limb/active_record/src/lmbARRelationCollection.class.php 2007-04-05 08:24:21 UTC (rev 5529)
@@ -78,9 +78,8 @@
$criteria = clone $this->criteria;
- $object->addClassCriteria($criteria);
-
$sort_params = array();
+ $has_class_criteria = false;
if(is_string($magic_params) || is_object($magic_params))
$criteria->addAnd($magic_params);
@@ -93,12 +92,16 @@
{
$filter_object = new $magic_params['class'];
$criteria = $filter_object->addClassCriteria($criteria);
+ $has_class_criteria = true;
}
if(isset($magic_params['sort']))
$sort_params = $magic_params['sort'];
}
+ if(!$has_class_criteria)
+ $object->addClassCriteria($criteria);
+
$rs = $this->_createDbRecordSet($criteria);
$this->_applySortParams($rs, $sort_params);
$dataset = $object->decorateRecordSet($rs);
Modified: 3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php
===================================================================
--- 3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php 2007-04-04 15:08:50 UTC (rev 5528)
+++ 3.x/trunk/limb/active_record/src/lmbActiveRecord.class.php 2007-04-05 08:24:21 UTC (rev 5529)
@@ -44,10 +44,6 @@
*/
protected $_db_table;
/**
- * @var string name of class which should be considered as a base one in single table inheritance relations
- */
- protected $_base_class;
- /**
* @var string name of class database table to store instance fields, if not set lmbActiveRecord tries to guess it
*/
protected $_db_table_name;
@@ -801,7 +797,7 @@
$fields = $this->export();
if($this->isNew() && $this->_isInheritable())
- $fields[self :: $_inheritance_field] = get_class($this);
+ $fields[self :: $_inheritance_field] = $this->_getInheritancePath();
foreach($this->_composed_of as $property => $info)
{
@@ -1186,17 +1182,33 @@
*/
function addClassCriteria($criteria)
{
- if(!$this->_isBaseClass() && $this->_isInheritable())
- return lmbSQLCriteria :: objectify($criteria)->addAnd(array(self :: $_inheritance_field . ' = ?', get_class($this)));
+ if($this->_isInheritable())
+ return lmbSQLCriteria :: objectify($criteria)->addAnd(array(self :: $_inheritance_field .
+ ' LIKE "' . $this->_getInheritancePath() . '%"'));
return $criteria;
}
- protected function _isBaseClass()
+ protected function _getInheritancePath()
{
- return ($this->_base_class && get_class($this) == $this->_base_class) ||
- (get_parent_class($this) == __CLASS__);
+ $class = get_class($this);
+ $path = "$class|";
+ while($class = get_parent_class($class))
+ {
+ if($class == __CLASS__)
+ break;
+ $path = "$class|$path";
+ }
+ return $path;
}
+
+ static function decodeInheritancePath($path)
+ {
+ $items = explode('|', $path);
+ array_pop($items);//removing last empty item
+ return $items;
+ }
+
/**
* Loads current object with data from database, overwrites any previous data, marks object dirty and unsets new status
* @param integer object id
Modified: 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordSubclassingTest.class.php
===================================================================
--- 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordSubclassingTest.class.php 2007-04-04 15:08:50 UTC (rev 5528)
+++ 3.x/trunk/limb/active_record/tests/cases/lmbActiveRecordSubclassingTest.class.php 2007-04-05 08:24:21 UTC (rev 5529)
@@ -18,13 +18,8 @@
}
class FooOneTableTestObject extends TestOneTableTypedObject{}
-class BarOneTableTestObject extends TestOneTableTypedObject{}
+class BarFooOneTableTestObject extends FooOneTableTestObject{}
-class BaseOneTableTestObject extends TestOneTableTypedObject
-{
- protected $_base_class = __CLASS__;
-}
-
class TypedLectureForTest extends lmbActiveRecord
{
protected $_db_table_name = 'lecture_for_typed_test';
@@ -33,15 +28,15 @@
}
class FooLectureForTest extends TypedLectureForTest{}
-class BarLectureForTest extends TypedLectureForTest{}
+class BarFooLectureForTest extends FooLectureForTest{}
class CourseForTestForTypedLecture extends lmbActiveRecord
{
protected $_db_table_name = 'course_for_typed_test';
protected $_has_many = array('lectures' => array('field' => 'course_id',
'class' => 'TypedLectureForTest'),
- 'bar_lectures' => array('field' => 'course_id',
- 'class' => 'BarLectureForTest'));
+ 'foo_lectures' => array('field' => 'course_id',
+ 'class' => 'FooLectureForTest'));
}
class lmbActiveRecordSubclassingTest extends UnitTestCase
@@ -61,9 +56,9 @@
function _dbCleanUp()
{
- lmbActiveRecord :: delete('TestOneTableTypedObject');
- lmbActiveRecord :: delete('CourseForTestForTypedLecture');
- lmbActiveRecord :: delete('TypedLectureForTest');
+ $this->db->delete('lecture_for_typed_test');
+ $this->db->delete('course_for_typed_test');
+ $this->db->delete('test_one_table_typed_object');
}
function testCreate()
@@ -73,26 +68,28 @@
$object1->save();
$object2 = new FooOneTableTestObject($object1->getId());
- $this->assertEqual($object2->title, $object1->title);
+ $this->assertEqual($object2->getTitle(), $object1->getTitle());
- //parents are supertypes
+ //parents are supertypes..
$object3 = new TestOneTableTypedObject($object1->getId());
+ $this->assertEqual($object3->getTitle(), $object1->getTitle());
try
{
- new BarOneTableTestObject($object1->getId());
+ //..while deeper subclasses are not
+ new BarFooOneTableTestObject($object1->getId());
$this->assertTrue(false);
}
catch(lmbARException $e){}
}
- function testParentDelete()
+ function testSupertypeDelete()
{
$foo = new FooOneTableTestObject();
$foo->setTitle('Some title');
$foo->save();
- $bar = new BarOneTableTestObject();
+ $bar = new BarFooOneTableTestObject();
$bar->setTitle('Another title');
$bar->save();
@@ -101,7 +98,7 @@
$rs = lmbActiveRecord :: find('FooOneTableTestObject');
$this->assertEqual($rs->count(), 0);
- $rs = lmbActiveRecord :: find('BarOneTableTestObject');
+ $rs = lmbActiveRecord :: find('BarFooOneTableTestObject');
$this->assertEqual($rs->count(), 0);
}
@@ -111,68 +108,42 @@
$foo->setTitle('Some title');
$foo->save();
- $bar = new BarOneTableTestObject();
+ $bar = new BarFooOneTableTestObject();
$bar->setTitle('Another title');
$bar->save();
- lmbActiveRecord :: delete('FooOneTableTestObject');
+ lmbActiveRecord :: delete('BarFooOneTableTestObject');//removing subclass
- $rs = lmbActiveRecord :: find('FooOneTableTestObject');
+ $rs = lmbActiveRecord :: find('BarFooOneTableTestObject');
$this->assertEqual($rs->count(), 0);
- $rs = lmbActiveRecord :: find('BarOneTableTestObject');
+ $rs = lmbActiveRecord :: find('FooOneTableTestObject');//supertype stays
$this->assertEqual($rs->count(), 1);
- }
- function testParentFind()
- {
- $object1 = new FooOneTableTestObject();
- $object1->setTitle('Some title');
- $object1->save();
+ lmbActiveRecord :: delete('FooOneTableTestObject');//removing supertype
- $object2 = new BarOneTableTestObject();
- $object2->setTitle('Some other title');
- $object2->save();
-
- $rs = lmbActiveRecord :: find('TestOneTableTypedObject');
- $this->assertEqual($rs->count(), 2);
- $this->assertIsA($rs->at(0), 'FooOneTableTestObject');
- $this->assertIsA($rs->at(1), 'BarOneTableTestObject');
+ $rs = lmbActiveRecord :: find('FooOneTableTestObject');
+ $this->assertEqual($rs->count(), 0);
}
- function testOverrideBaseClass()
+ function testFind()
{
$object1 = new FooOneTableTestObject();
$object1->setTitle('Some title');
$object1->save();
- $object2 = new BarOneTableTestObject();
+ $object2 = new BarFooOneTableTestObject();
$object2->setTitle('Some other title');
$object2->save();
- $rs = lmbActiveRecord :: find('BaseOneTableTestObject');
+ $rs = lmbActiveRecord :: find('FooOneTableTestObject');//supertype
$this->assertEqual($rs->count(), 2);
$this->assertIsA($rs->at(0), 'FooOneTableTestObject');
- $this->assertIsA($rs->at(1), 'BarOneTableTestObject');
- }
+ $this->assertIsA($rs->at(1), 'BarFooOneTableTestObject');
- function testTypedFind()
- {
- $object1 = new FooOneTableTestObject();
- $object1->setTitle('Some title');
- $object1->save();
-
- $object2 = new BarOneTableTestObject();
- $object2->setTitle('Some other title');
- $object2->save();
-
- $rs = lmbActiveRecord :: find('FooOneTableTestObject');
+ $rs = lmbActiveRecord :: find('BarFooOneTableTestObject');//subclass
$this->assertEqual($rs->count(), 1);
- $this->assertIsA($rs->at(0), 'FooOneTableTestObject');
-
- $rs = lmbActiveRecord :: find('BarOneTableTestObject');
- $this->assertEqual($rs->count(), 1);
- $this->assertIsA($rs->at(0), 'BarOneTableTestObject');
+ $this->assertIsA($rs->at(0), 'BarFooOneTableTestObject');
}
function testTypedRelationFind()
@@ -186,7 +157,7 @@
$lecture1->setCourse($course);
$lecture1->save();
- $lecture2 = new BarLectureForTest();
+ $lecture2 = new BarFooLectureForTest();
$lecture2->setTitle('Some other title');
$lecture2->setCourse($course);
$lecture2->save();
@@ -196,45 +167,21 @@
$course2 = new CourseForTestForTypedLecture($course->getId());
- $this->assertEqual($course2->getLectures()->count(), 2);
+ $this->assertEqual($course2->getLectures()->count(), 2);//supertype by default
$this->assertIsA($course2->getLectures()->at(0), 'FooLectureForTest');
- $this->assertIsA($course2->getLectures()->at(1), 'BarLectureForTest');
+ $this->assertIsA($course2->getLectures()->at(1), 'BarFooLectureForTest');
- $foo_lectures = $course2->getLectures()->find(array('class' => 'FooLectureForTest'));
- $this->assertEqual($foo_lectures->count(), 1);
- $this->assertIsA($foo_lectures->at(0), 'FooLectureForTest');
+ //narrowing selection but again its supertype for BarFooLectureForTest
+ $lectures = $course2->getLectures()->find(array('class' => 'FooLectureForTest'));
- $bar_lectures = $course2->getLectures()->find(array('class' => 'BarLectureForTest'));
- $this->assertEqual($bar_lectures->count(), 1);
- $this->assertIsA($bar_lectures->at(0), 'BarLectureForTest');
- }
+ $this->assertEqual($lectures->count(), 2);
+ $this->assertIsA($lectures->at(0), 'FooLectureForTest');
+ $this->assertIsA($lectures->at(1), 'BarFooLectureForTest');
- function testFilterTypedRelation()
- {
- $course = new CourseForTestForTypedLecture();
- $course->setTitle('Source1');
- $course->save();
-
- $lecture1 = new FooLectureForTest();
- $lecture1->setTitle('Some title');
- $lecture1->setCourse($course);
- $lecture1->save();
-
- $lecture2 = new BarLectureForTest();
- $lecture2->setTitle('Some other title');
- $lecture2->setCourse($course);
- $lecture2->save();
-
- $course->getLectures()->add($lecture1);
- $course->getBarLectures()->add($lecture2);
-
- $course2 = new CourseForTestForTypedLecture($course->getId());
-
- $this->assertEqual($course2->getLectures()->count(), 2);
- $this->assertEqual($course2->getBarLectures()->count(), 1);
- $this->assertIsA($course2->getBarLectures()->at(0), 'BarLectureForTest');
- $this->assertIsA($course2->getLectures()->at(0), 'FooLectureForTest');
- $this->assertIsA($course2->getLectures()->at(1), 'BarLectureForTest');
+ //narrowing more
+ $lectures = $course2->getLectures()->find(array('class' => 'BarFooLectureForTest'));
+ $this->assertEqual($lectures->count(), 1);
+ $this->assertIsA($lectures->at(0), 'BarFooLectureForTest');
}
}
More information about the limb-svn
mailing list