2008-01-09 04:39:05 +01:00
< ? php
/**
2008-06-15 15:33:53 +02:00
* @ package sapphire
* @ subpackage tests
2008-01-09 04:39:05 +01:00
*/
class DataObjectTest extends SapphireTest {
static $fixture_file = 'sapphire/tests/DataObjectTest.yml' ;
/**
* Test deletion of DataObjects
* - Deleting using delete () on the DataObject
* - Deleting using DataObject :: delete_by_id ()
*/
function testDelete () {
// Test deleting using delete() on the DataObject
// Get the first page
2008-08-11 01:17:51 +02:00
$page = $this -> fixture -> objFromFixture ( 'Page' , 'page1' );
2008-01-09 04:39:05 +01:00
// Check the page exists before deleting
$this -> assertTrue ( is_object ( $page ) && $page -> exists ());
// Delete the page
$page -> delete ();
// Check that page does not exist after deleting
2008-08-11 01:17:51 +02:00
$page = $this -> fixture -> objFromFixture ( 'Page' , 'page1' );
2008-01-09 04:39:05 +01:00
$this -> assertTrue ( ! $page || ! $page -> exists ());
// Test deleting using DataObject::delete_by_id()
// Get the second page
2008-08-11 01:17:51 +02:00
$page2 = $this -> fixture -> objFromFixture ( 'Page' , 'page2' );
2008-01-09 04:39:05 +01:00
// Check the page exists before deleting
$this -> assertTrue ( is_object ( $page2 ) && $page2 -> exists ());
// Delete the page
DataObject :: delete_by_id ( 'Page' , $page2 -> ID );
// Check that page does not exist after deleting
2008-08-11 01:17:51 +02:00
$page2 = $this -> fixture -> objFromFixture ( 'Page' , 'page2' );
2008-01-09 04:39:05 +01:00
$this -> assertTrue ( ! $page2 || ! $page2 -> exists ());
}
/**
* Test methods that get DataObjects
* - DataObject :: get ()
* - All records of a DataObject
* - Filtering
* - Sorting
* - Joins
* - Limit
* - Container class
* - DataObject :: get_by_id ()
* - DataObject :: get_by_url ()
* - DataObject :: get_one ()
* - With and without caching
* - With and without ordering
*/
function testGet () {
// Test getting all records of a DataObject
$comments = DataObject :: get ( 'PageComment' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 8 , $comments -> Count ());
2008-01-09 04:39:05 +01:00
// Test WHERE clause
2008-11-24 10:31:14 +01:00
$comments = DataObject :: get ( 'PageComment' , " \" Name \" ='Bob' " );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 2 , $comments -> Count ());
2008-01-09 04:39:05 +01:00
foreach ( $comments as $comment ) {
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'Bob' , $comment -> Name );
2008-01-09 04:39:05 +01:00
}
// Test sorting
2008-11-24 10:31:14 +01:00
$comments = DataObject :: get ( 'PageComment' , '' , '"Name" ASC' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 8 , $comments -> Count ());
$this -> assertEquals ( 'Bob' , $comments -> First () -> Name );
2008-11-24 10:31:14 +01:00
$comments = DataObject :: get ( 'PageComment' , '' , '"Name" DESC' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 8 , $comments -> Count ());
$this -> assertEquals ( 'Joe' , $comments -> First () -> Name );
2008-01-09 04:39:05 +01:00
// Test join
2008-11-24 10:31:14 +01:00
$comments = DataObject :: get ( 'PageComment' , " \" SiteTree \" . \" Title \" ='First Page' " , '' , 'INNER JOIN "SiteTree" ON "PageComment"."ParentID" = "SiteTree"."ID"' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 2 , $comments -> Count ());
$this -> assertEquals ( 'Bob' , $comments -> First () -> Name );
$this -> assertEquals ( 'Bob' , $comments -> Last () -> Name );
2008-01-09 04:39:05 +01:00
// Test limit
2008-11-24 10:31:14 +01:00
$comments = DataObject :: get ( 'PageComment' , '' , '"Name" ASC' , '' , '1,2' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 2 , $comments -> Count ());
$this -> assertEquals ( 'Bob' , $comments -> First () -> Name );
$this -> assertEquals ( 'Dean' , $comments -> Last () -> Name );
2008-01-09 04:39:05 +01:00
// Test container class
$comments = DataObject :: get ( 'PageComment' , '' , '' , '' , '' , 'DataObjectSet' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'DataObjectSet' , get_class ( $comments ));
2008-01-09 04:39:05 +01:00
$comments = DataObject :: get ( 'PageComment' , '' , '' , '' , '' , 'ComponentSet' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'ComponentSet' , get_class ( $comments ));
2008-01-09 04:39:05 +01:00
// Test get_by_id()
2008-08-13 02:44:52 +02:00
$homepageID = $this -> idFromFixture ( 'Page' , 'home' );
$page = DataObject :: get_by_id ( 'Page' , $homepageID );
$this -> assertEquals ( 'Home' , $page -> Title );
2008-01-09 04:39:05 +01:00
// Test get_by_url()
2008-11-02 01:24:23 +01:00
$page = SiteTree :: get_by_url ( 'home' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( $homepageID , $page -> ID );
2008-01-09 04:39:05 +01:00
// Test get_one() without caching
2008-11-24 10:31:14 +01:00
$comment1 = DataObject :: get_one ( 'PageComment' , " \" Name \" ='Joe' " , false );
2008-01-09 04:39:05 +01:00
$comment1 -> Comment = " Something Else " ;
2008-11-24 10:31:14 +01:00
$comment2 = DataObject :: get_one ( 'PageComment' , " \" Name \" ='Joe' " , false );
2008-08-13 02:44:52 +02:00
$this -> assertNotEquals ( $comment1 -> Comment , $comment2 -> Comment );
2008-01-09 04:39:05 +01:00
// Test get_one() with caching
2008-11-24 10:31:14 +01:00
$comment1 = DataObject :: get_one ( 'PageComment' , " \" Name \" ='Jane' " , true );
2008-01-09 04:39:05 +01:00
$comment1 -> Comment = " Something Else " ;
2008-11-24 10:31:14 +01:00
$comment2 = DataObject :: get_one ( 'PageComment' , " \" Name \" ='Jane' " , true );
2008-08-13 02:44:52 +02:00
$this -> assertEquals (( string ) $comment1 -> Comment , ( string ) $comment2 -> Comment );
2008-01-09 04:39:05 +01:00
// Test get_one() with order by without caching
2008-11-24 10:31:14 +01:00
$comment = DataObject :: get_one ( 'PageComment' , '' , false , '"Name" ASC' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'Bob' , $comment -> Name );
2008-11-24 10:31:14 +01:00
$comment = DataObject :: get_one ( 'PageComment' , '' , false , '"Name" DESC' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'Joe' , $comment -> Name );
2008-01-09 04:39:05 +01:00
// Test get_one() with order by with caching
2008-11-24 10:31:14 +01:00
$comment = DataObject :: get_one ( 'PageComment' , '' , true , '"Name" ASC' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'Bob' , $comment -> Name );
2008-11-24 10:31:14 +01:00
$comment = DataObject :: get_one ( 'PageComment' , '' , true , '"Name" DESC' );
2008-08-13 02:44:52 +02:00
$this -> assertEquals ( 'Joe' , $comment -> Name );
2008-01-09 04:39:05 +01:00
}
2008-08-09 05:54:55 +02:00
/**
* Test writing of database columns which don ' t correlate to a DBField ,
* e . g . all relation fields on has_one / has_many like " ParentID " .
*
*/
function testWritePropertyWithoutDBField () {
2008-08-11 01:17:51 +02:00
$page = $this -> fixture -> objFromFixture ( 'Page' , 'page1' );
2008-08-09 05:54:55 +02:00
$page -> ParentID = 99 ;
$page -> write ();
// reload the page from the database
$savedPage = DataObject :: get_by_id ( 'Page' , $page -> ID );
$this -> assertTrue ( $savedPage -> ParentID == 99 );
}
2008-01-09 04:39:05 +01:00
/**
* Test has many relationships
* - Test getComponents () gets the ComponentSet of the other side of the relation
* - Test the IDs on the DataObjects are set correctly
*/
function testHasManyRelationships () {
2008-08-11 01:17:51 +02:00
$page = $this -> fixture -> objFromFixture ( 'Page' , 'home' );
2008-01-09 04:39:05 +01:00
// Test getComponents() gets the ComponentSet of the other side of the relation
$this -> assertTrue ( $page -> getComponents ( 'Comments' ) -> Count () == 2 );
// Test the IDs on the DataObjects are set correctly
foreach ( $page -> getComponents ( 'Comments' ) as $comment ) {
$this -> assertTrue ( $comment -> ParentID == $page -> ID );
}
}
2008-08-11 05:03:52 +02:00
/**
* @ todo Test removeMany () and addMany () on $many_many relationships
*/
function testManyManyRelationships () {
$player1 = $this -> fixture -> objFromFixture ( 'DataObjectTest_Player' , 'player1' );
$player2 = $this -> fixture -> objFromFixture ( 'DataObjectTest_Player' , 'player2' );
$team1 = $this -> fixture -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$team2 = $this -> fixture -> objFromFixture ( 'DataObjectTest_Team' , 'team2' );
// Test adding single DataObject by reference
$player1 -> Teams () -> add ( $team1 );
$player1 -> flushCache ();
$compareTeams = new ComponentSet ( $team1 );
$this -> assertEquals (
$player1 -> Teams () -> column ( 'ID' ),
$compareTeams -> column ( 'ID' ),
" Adding single record as DataObject to many_many "
);
// test removing single DataObject by reference
$player1 -> Teams () -> remove ( $team1 );
$player1 -> flushCache ();
$compareTeams = new ComponentSet ();
$this -> assertEquals (
$player1 -> Teams () -> column ( 'ID' ),
$compareTeams -> column ( 'ID' ),
" Removing single record as DataObject from many_many "
);
// test adding single DataObject by ID
$player1 -> Teams () -> add ( $team1 -> ID );
$player1 -> flushCache ();
$compareTeams = new ComponentSet ( $team1 );
$this -> assertEquals (
$player1 -> Teams () -> column ( 'ID' ),
$compareTeams -> column ( 'ID' ),
" Adding single record as ID to many_many "
);
// test removing single DataObject by ID
$player1 -> Teams () -> remove ( $team1 -> ID );
$player1 -> flushCache ();
$compareTeams = new ComponentSet ();
$this -> assertEquals (
$player1 -> Teams () -> column ( 'ID' ),
$compareTeams -> column ( 'ID' ),
" Removing single record as ID from many_many "
);
}
/**
* @ todo Extend type change tests ( e . g . '0' == NULL )
*/
function testChangedFields () {
$page = $this -> fixture -> objFromFixture ( 'Page' , 'home' );
$page -> Title = 'Home-Changed' ;
$page -> ShowInMenus = true ;
$this -> assertEquals (
$page -> getChangedFields ( false , 1 ),
array (
'Title' => array (
'before' => 'Home' ,
'after' => 'Home-Changed' ,
'level' => 2
),
'ShowInMenus' => array (
'before' => 1 ,
'after' => true ,
'level' => 1
)
),
'Changed fields are correctly detected with strict type changes (level=1)'
);
$this -> assertEquals (
$page -> getChangedFields ( false , 2 ),
array (
'Title' => array (
'before' => 'Home' ,
'after' => 'Home-Changed' ,
'level' => 2
)
),
'Changed fields are correctly detected while ignoring type changes (level=2)'
);
2008-10-08 04:00:12 +02:00
$newPage = new Page ();
$newPage -> Title = " New Page Title " ;
$this -> assertEquals (
$newPage -> getChangedFields ( false , 2 ),
array (
'Title' => array (
'before' => null ,
'after' => 'New Page Title' ,
'level' => 2
)
),
'Initialised fields are correctly detected as full changes'
);
2008-08-11 05:03:52 +02:00
}
2008-08-13 02:44:52 +02:00
function testRandomSort () {
/* If we perforn the same regularly sorted query twice, it should return the same results */
$itemsA = DataObject :: get ( " PageComment " , " " , " ID " );
foreach ( $itemsA as $item ) $keysA [] = $item -> ID ;
$itemsB = DataObject :: get ( " PageComment " , " " , " ID " );
foreach ( $itemsB as $item ) $keysB [] = $item -> ID ;
$this -> assertEquals ( $keysA , $keysB );
/* If we perform the same random query twice, it shouldn't return the same results */
$itemsA = DataObject :: get ( " PageComment " , " " , " RAND() " );
foreach ( $itemsA as $item ) $keysA [] = $item -> ID ;
$itemsB = DataObject :: get ( " PageComment " , " " , " RAND() " );
foreach ( $itemsB as $item ) $keysB [] = $item -> ID ;
$this -> assertNotEquals ( $keysA , $keysB );
}
2008-08-15 05:08:03 +02:00
function testWriteSavesToHasOneRelations () {
/* DataObject::write() should save to a has_one relationship if you set a field called (relname)ID */
$team = new DataObjectTest_Team ();
$captainID = $this -> idFromFixture ( 'DataObjectTest_Player' , 'player1' );
$team -> CaptainID = $captainID ;
$team -> write ();
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( $captainID , DB :: query ( " SELECT \" CaptainID \" FROM \" DataObjectTest_Team \" WHERE \" ID \" = $team->ID " ) -> value ());
2008-08-15 05:08:03 +02:00
/* After giving it a value, you should also be able to set it back to null */
$team -> CaptainID = '' ;
$team -> write ();
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( 0 , DB :: query ( " SELECT \" CaptainID \" FROM \" DataObjectTest_Team \" WHERE \" ID \" = $team->ID " ) -> value ());
2008-08-15 05:08:03 +02:00
/* You should also be able to save a blank to it when it's first created */
$team = new DataObjectTest_Team ();
$team -> CaptainID = '' ;
$team -> write ();
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( 0 , DB :: query ( " SELECT \" CaptainID \" FROM \" DataObjectTest_Team \" WHERE \" ID \" = $team->ID " ) -> value ());
2008-08-15 05:08:03 +02:00
/* Ditto for existing records without a value */
$existingTeam = $this -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$existingTeam -> CaptainID = '' ;
$existingTeam -> write ();
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( 0 , DB :: query ( " SELECT \" CaptainID \" FROM \" DataObjectTest_Team \" WHERE \" ID \" = $existingTeam->ID " ) -> value ());
2008-08-15 05:08:03 +02:00
}
2008-09-30 02:20:30 +02:00
2008-10-02 02:45:13 +02:00
function testCanAccessHasOneObjectsAsMethods () {
/* If you have a has_one relation 'Captain' on $obj , and you set the $obj -> CaptainID = ( ID ), then the object itself should
* be accessible as $obj -> Captain () */
$team = $this -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$captainID = $this -> idFromFixture ( 'DataObjectTest_Player' , 'captain1' );
$team -> CaptainID = $captainID ;
$this -> assertNotNull ( $team -> Captain ());
$this -> assertEquals ( $captainID , $team -> Captain () -> ID );
}
2008-10-01 02:55:25 +02:00
function testFieldNamesThatMatchMethodNamesWork () {
/* Check that a field name that corresponds to a method on DataObject will still work */
$obj = new DataObjectTest_FunnyFieldNames ();
$obj -> Data = " value1 " ;
$obj -> DbObject = " value2 " ;
$obj -> Duplicate = " value3 " ;
$obj -> write ();
$this -> assertNotNull ( $obj -> ID );
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( 'value1' , DB :: query ( " SELECT \" Data \" FROM \" DataObjectTest_FunnyFieldNames \" WHERE \" ID \" = $obj->ID " ) -> value ());
$this -> assertEquals ( 'value2' , DB :: query ( " SELECT \" DbObject \" FROM \" DataObjectTest_FunnyFieldNames \" WHERE \" ID \" = $obj->ID " ) -> value ());
$this -> assertEquals ( 'value3' , DB :: query ( " SELECT \" Duplicate \" FROM \" DataObjectTest_FunnyFieldNames \" WHERE \" ID \" = $obj->ID " ) -> value ());
2008-10-01 02:55:25 +02:00
}
2008-09-30 02:27:22 +02:00
/**
* @ todo Re - enable all test cases for field existence after behaviour has been fixed
*/
2008-09-30 02:20:30 +02:00
function testFieldExistence () {
$teamInstance = $this -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$teamSingleton = singleton ( 'DataObjectTest_Team' );
$subteamInstance = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam1' );
$subteamSingleton = singleton ( 'DataObjectTest_SubTeam' );
/* hasField() singleton checks */
$this -> assertTrue ( $teamSingleton -> hasField ( 'ID' ), 'hasField() finds built-in fields in singletons' );
$this -> assertTrue ( $teamSingleton -> hasField ( 'Title' ), 'hasField() finds custom fields in singletons' );
/* hasField() instance checks */
$this -> assertFalse ( $teamInstance -> hasField ( 'NonExistingField' ), 'hasField() doesnt find non-existing fields in instances' );
$this -> assertTrue ( $teamInstance -> hasField ( 'ID' ), 'hasField() finds built-in fields in instances' );
$this -> assertTrue ( $teamInstance -> hasField ( 'Created' ), 'hasField() finds built-in fields in instances' );
$this -> assertTrue ( $teamInstance -> hasField ( 'DatabaseField' ), 'hasField() finds custom fields in instances' );
//$this->assertFalse($teamInstance->hasField('SubclassDatabaseField'), 'hasField() doesnt find subclass fields in parentclass instances');
2008-10-09 16:38:46 +02:00
$this -> assertTrue ( $teamInstance -> hasField ( 'DynamicField' ), 'hasField() finds dynamic getters in instances' );
2008-09-30 02:20:30 +02:00
$this -> assertTrue ( $teamInstance -> hasField ( 'HasOneRelationshipID' ), 'hasField() finds foreign keys in instances' );
$this -> assertTrue ( $teamInstance -> hasField ( 'DecoratedDatabaseField' ), 'hasField() finds decorated fields in instances' );
$this -> assertTrue ( $teamInstance -> hasField ( 'DecoratedHasOneRelationshipID' ), 'hasField() finds decorated foreign keys in instances' );
//$this->assertTrue($teamInstance->hasField('DecoratedDynamicField'), 'hasField() includes decorated dynamic getters in instances');
/* hasField() subclass checks */
$this -> assertTrue ( $subteamInstance -> hasField ( 'ID' ), 'hasField() finds built-in fields in subclass instances' );
$this -> assertTrue ( $subteamInstance -> hasField ( 'Created' ), 'hasField() finds built-in fields in subclass instances' );
$this -> assertTrue ( $subteamInstance -> hasField ( 'DatabaseField' ), 'hasField() finds custom fields in subclass instances' );
$this -> assertTrue ( $subteamInstance -> hasField ( 'SubclassDatabaseField' ), 'hasField() finds custom fields in subclass instances' );
2008-10-09 16:38:46 +02:00
$this -> assertTrue ( $subteamInstance -> hasField ( 'DynamicField' ), 'hasField() finds dynamic getters in subclass instances' );
2008-09-30 02:20:30 +02:00
$this -> assertTrue ( $subteamInstance -> hasField ( 'HasOneRelationshipID' ), 'hasField() finds foreign keys in subclass instances' );
$this -> assertTrue ( $subteamInstance -> hasField ( 'DecoratedDatabaseField' ), 'hasField() finds decorated fields in subclass instances' );
$this -> assertTrue ( $subteamInstance -> hasField ( 'DecoratedHasOneRelationshipID' ), 'hasField() finds decorated foreign keys in subclass instances' );
/* hasDatabaseField() singleton checks */
//$this->assertTrue($teamSingleton->hasDatabaseField('ID'), 'hasDatabaseField() finds built-in fields in singletons');
$this -> assertTrue ( $teamSingleton -> hasDatabaseField ( 'Title' ), 'hasDatabaseField() finds custom fields in singletons' );
/* hasDatabaseField() instance checks */
$this -> assertFalse ( $teamInstance -> hasDatabaseField ( 'NonExistingField' ), 'hasDatabaseField() doesnt find non-existing fields in instances' );
//$this->assertTrue($teamInstance->hasDatabaseField('ID'), 'hasDatabaseField() finds built-in fields in instances');
$this -> assertTrue ( $teamInstance -> hasDatabaseField ( 'Created' ), 'hasDatabaseField() finds built-in fields in instances' );
$this -> assertTrue ( $teamInstance -> hasDatabaseField ( 'DatabaseField' ), 'hasDatabaseField() finds custom fields in instances' );
$this -> assertFalse ( $teamInstance -> hasDatabaseField ( 'SubclassDatabaseField' ), 'hasDatabaseField() doesnt find subclass fields in parentclass instances' );
//$this->assertFalse($teamInstance->hasDatabaseField('DynamicField'), 'hasDatabaseField() doesnt dynamic getters in instances');
$this -> assertTrue ( $teamInstance -> hasDatabaseField ( 'HasOneRelationshipID' ), 'hasDatabaseField() finds foreign keys in instances' );
$this -> assertTrue ( $teamInstance -> hasDatabaseField ( 'DecoratedDatabaseField' ), 'hasDatabaseField() finds decorated fields in instances' );
$this -> assertTrue ( $teamInstance -> hasDatabaseField ( 'DecoratedHasOneRelationshipID' ), 'hasDatabaseField() finds decorated foreign keys in instances' );
$this -> assertFalse ( $teamInstance -> hasDatabaseField ( 'DecoratedDynamicField' ), 'hasDatabaseField() doesnt include decorated dynamic getters in instances' );
/* hasDatabaseField() subclass checks */
$this -> assertTrue ( $subteamInstance -> hasField ( 'DatabaseField' ), 'hasField() finds custom fields in subclass instances' );
$this -> assertTrue ( $subteamInstance -> hasField ( 'SubclassDatabaseField' ), 'hasField() finds custom fields in subclass instances' );
}
2008-09-30 02:27:22 +02:00
/**
* @ todo Re - enable all test cases for field inheritance aggregation after behaviour has been fixed
*/
2008-09-30 02:20:30 +02:00
function testFieldInheritance () {
$teamInstance = $this -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$subteamInstance = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam1' );
$this -> assertEquals (
array_keys ( $teamInstance -> inheritedDatabaseFields ()),
array (
//'ID',
//'ClassName',
//'Created',
//'LastEdited',
'Title' ,
'DatabaseField' ,
'DecoratedDatabaseField' ,
'CaptainID' ,
'HasOneRelationshipID' ,
'DecoratedHasOneRelationshipID'
),
'inheritedDatabaseFields() contains all fields defined on instance, including base fields, decorated fields and foreign keys'
);
$this -> assertEquals (
array_keys ( $teamInstance -> databaseFields ()),
array (
//'ID',
'ClassName' ,
'Created' ,
'LastEdited' ,
'Title' ,
'DatabaseField' ,
'DecoratedDatabaseField' ,
'CaptainID' ,
'HasOneRelationshipID' ,
'DecoratedHasOneRelationshipID'
),
'databaseFields() contains only fields defined on instance, including base fields, decorated fields and foreign keys'
);
$this -> assertEquals (
array_keys ( $subteamInstance -> inheritedDatabaseFields ()),
array (
//'ID',
//'ClassName',
//'Created',
//'LastEdited',
'SubclassDatabaseField' ,
'Title' ,
'DatabaseField' ,
'DecoratedDatabaseField' ,
'CaptainID' ,
'HasOneRelationshipID' ,
'DecoratedHasOneRelationshipID' ,
),
'inheritedDatabaseFields() on subclass contains all fields defined on instance, including base fields, decorated fields and foreign keys'
);
$this -> assertEquals (
array_keys ( $subteamInstance -> databaseFields ()),
array (
'SubclassDatabaseField' ,
),
'databaseFields() on subclass contains only fields defined on instance'
);
}
2008-10-02 02:45:13 +02:00
function testDataObjectUpdate () {
/* update() calls can use the dot syntax to reference has_one relations and other methods that return objects */
$team1 = $this -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$team1 -> CaptainID = $this -> idFromFixture ( 'DataObjectTest_Player' , 'captain1' );
$team1 -> update ( array (
'DatabaseField' => 'Something' ,
'Captain.FirstName' => 'Jim' ,
'Captain.Email' => 'jim@example.com' ,
'Captain.FavouriteTeam.Title' => 'New and improved team 1' ,
));
/* Test the simple case of updating fields on the object itself */
$this -> assertEquals ( 'Something' , $team1 -> DatabaseField );
/* Setting Captain . Email and Captain . FirstName will have updated DataObjectTest_Captain . captain1 in the database . Although update ()
* doesn ' t usually write , it does write related records automatically . */
$captain1 = $this -> objFromFixture ( 'DataObjectTest_Player' , 'captain1' );
$this -> assertEquals ( 'Jim' , $captain1 -> FirstName );
$this -> assertEquals ( 'jim@example.com' , $captain1 -> Email );
/* Jim's favourite team is team 1; we need to reload the object to the the change that setting Captain.FavouriteTeam.Title made */
$reloadedTeam1 = $this -> objFromFixture ( 'DataObjectTest_Team' , 'team1' );
$this -> assertEquals ( 'New and improved team 1' , $reloadedTeam1 -> Title );
}
2008-10-08 22:42:09 +02:00
public function testDataObjectValidation () {
$validatedObject = new DataObjectTest_ValidatedObject ();
try {
$validatedObject -> write ();
// If write doesn't throw an exception, this line is executed and the test fails.
$this -> assertTrue ( false , " Validated object did not throw a ValidationException when saving with DataObject::write " );
} catch ( ValidationException $validationException ) {
// ValidationException wraps a ValidationResult. This result should be invalid
$this -> assertFalse ( $validationException -> getResult () -> valid (), " ValidationException thrown by DataObject::write contains a valid ValidationResult. The result should be invalid. " );
}
$validatedObject -> Name = " Mr. Jones " ;
try {
$validatedObject -> write ();
$this -> assertTrue ( $validatedObject -> isInDB (), " Validated object was not saved to database " );
} catch ( Exception $exception ) {
$this -> assertTrue ( false , " Validated object threw an unexpected exception of type " . get_class ( $exception ) . " from DataObject::write: " . $exception -> getMessage ());
}
}
2008-10-28 02:23:41 +01:00
public function testSubclassCreation () {
/* Creating a new object of a subclass should set the ClassName field correctly */
$obj = new DataObjectTest_SubTeam ();
$obj -> write ();
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( " DataObjectTest_SubTeam " , DB :: query ( " SELECT \" ClassName \" FROM \" DataObjectTest_Team \" WHERE \" ID \" = $obj->ID " ) -> value ());
2008-10-28 02:23:41 +01:00
}
public function testForceInsert () {
/* If you set an ID on an object and pass forceInsert = true, then the object should be correctly created */
$obj = new DataObjectTest_SubTeam ();
$obj -> ID = 1001 ;
$obj -> Title = 'asdfasdf' ;
$obj -> SubclassDatabaseField = 'asdfasdf' ;
$obj -> write ( false , true );
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( " DataObjectTest_SubTeam " , DB :: query ( " SELECT \" ClassName \" FROM \" DataObjectTest_Team \" WHERE \" ID \" = $obj->ID " ) -> value ());
2008-10-28 02:23:41 +01:00
/* Check that it actually saves to the database with the correct ID */
2008-11-24 10:31:14 +01:00
$this -> assertEquals ( " 1001 " , DB :: query ( " SELECT \" ID \" FROM \" DataObjectTest_SubTeam \" WHERE \" SubclassDatabaseField \" = 'asdfasdf' " ) -> value ());
$this -> assertEquals ( " 1001 " , DB :: query ( " SELECT \" ID \" FROM \" DataObjectTest_Team \" WHERE \" Title \" = 'asdfasdf' " ) -> value ());
2008-10-28 02:23:41 +01:00
}
2008-11-06 05:51:25 +01:00
public function TestHasOwnTable () {
/* Test DataObject::has_own_table() returns true if the object has $has_one or $db values */
$this -> assertTrue ( DataObject :: has_own_table ( " DataObjectTest_Player " ));
$this -> assertTrue ( DataObject :: has_own_table ( " DataObjectTest_Team " ));
$this -> assertTrue ( DataObject :: has_own_table ( " DataObjectTest_FunnyFieldNames " ));
/* Root DataObject that always have a table, even if they lack both $db and $has_one */
$this -> assertTrue ( DataObject :: has_own_table ( " DataObjectTest_FieldlessTable " ));
/* Subclasses without $db or $has_one don't have a table */
$this -> assertFalse ( DataObject :: has_own_table ( " DataObjectTest_FieldlessSubTable " ));
/* Return false if you don't pass it a subclass of DataObject */
$this -> assertFalse ( DataObject :: has_own_table ( " DataObject " ));
$this -> assertFalse ( DataObject :: has_own_table ( " ViewableData " ));
$this -> assertFalse ( DataObject :: has_own_table ( " ThisIsntADataObject " ));
}
2009-01-07 02:25:43 +01:00
public function testMerge () {
// test right merge of subclasses
$left = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam1' );
$right = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam2_with_player_relation' );
$leftOrigID = $left -> ID ;
$left -> merge ( $right , 'right' , false , false );
$this -> assertEquals (
$left -> Title ,
'Subteam 2' ,
'merge() with "right" priority overwrites fields with existing values on subclasses'
);
$this -> assertEquals (
$left -> ID ,
$leftOrigID ,
'merge() with "right" priority doesnt overwrite database ID'
);
// test overwriteWithEmpty flag on existing left values
$left = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam2_with_player_relation' );
$right = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam3_with_empty_fields' );
$left -> merge ( $right , 'right' , false , true );
$this -> assertEquals (
$left -> Title ,
'Subteam 3' ,
'merge() with $overwriteWithEmpty overwrites non-empty fields on left object'
);
// test overwriteWithEmpty flag on empty left values
$left = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam1' );
$right = $this -> objFromFixture ( 'DataObjectTest_SubTeam' , 'subteam2_with_player_relation' ); // $SubclassDatabaseField is empty on here
$left -> merge ( $right , 'right' , false , true );
$this -> assertEquals (
$left -> SubclassDatabaseField ,
NULL ,
'merge() with $overwriteWithEmpty overwrites empty fields on left object'
);
// @todo test "left" priority flag
// @todo test includeRelations flag
// @todo test includeRelations in combination with overwriteWithEmpty
// @todo test has_one relations
// @todo test has_many and many_many relations
}
2008-01-09 04:39:05 +01:00
}
2008-08-11 06:51:58 +02:00
class DataObjectTest_Player extends Member implements TestOnly {
2008-10-02 02:45:13 +02:00
static $has_one = array (
'FavouriteTeam' => 'DataObjectTest_Team' ,
);
static $belongs_many_many = array (
'Teams' => 'DataObjectTest_Team'
);
2008-08-11 06:51:58 +02:00
}
class DataObjectTest_Team extends DataObject implements TestOnly {
2008-08-15 05:08:03 +02:00
static $db = array (
'Title' => 'Text' ,
2008-09-30 02:20:30 +02:00
'DatabaseField' => 'Text'
2008-08-15 05:08:03 +02:00
);
static $has_one = array (
" Captain " => 'DataObjectTest_Player' ,
2008-09-30 02:20:30 +02:00
'HasOneRelationship' => 'DataObjectTest_Player' ,
2008-08-15 05:08:03 +02:00
);
static $many_many = array (
'Players' => 'DataObjectTest_Player'
);
2008-09-30 02:20:30 +02:00
function getDynamicField () {
return 'dynamicfield' ;
}
}
2008-10-01 02:55:25 +02:00
class DataObjectTest_FunnyFieldNames extends DataObject implements TestOnly {
static $db = array (
'Data' => 'Text' ,
'Duplicate' => 'Text' ,
'DbObject' => 'Text' ,
);
}
2008-09-30 02:20:30 +02:00
class DataObjectTest_SubTeam extends DataObjectTest_Team implements TestOnly {
static $db = array (
'SubclassDatabaseField' => 'Text'
);
}
2008-08-15 05:08:03 +02:00
2008-11-06 05:51:25 +01:00
class DataObjectTest_FieldlessTable extends DataObject implements TestOnly {
}
class DataObjectTest_FieldlessSubTable extends DataObjectTest_Team implements TestOnly {
}
2008-09-30 02:20:30 +02:00
class DataObjectTest_Team_Decorator extends DataObjectDecorator implements TestOnly {
2008-11-02 01:36:57 +01:00
function extraStatics () {
2008-09-30 02:20:30 +02:00
return array (
'db' => array (
'DecoratedDatabaseField' => 'Text'
),
'has_one' => array (
'DecoratedHasOneRelationship' => 'DataObjectTest_Player'
)
);
}
function getDecoratedDynamicField () {
return " decorated dynamic field " ;
}
2008-08-11 06:51:58 +02:00
}
2008-10-08 22:42:09 +02:00
class DataObjectTest_ValidatedObject extends DataObject implements TestOnly {
static $db = array (
'Name' => 'Varchar(50)'
);
protected function validate () {
if ( ! empty ( $this -> Name )) {
return new ValidationResult ();
} else {
return new ValidationResult ( false , " This object needs a name. Otherwise it will have an identity crisis! " );
}
}
}
2008-09-30 02:20:30 +02:00
DataObject :: add_extension ( 'DataObjectTest_Team' , 'DataObjectTest_Team_Decorator' );
2008-01-09 04:39:05 +01:00
?>