2012-04-20 00:08:17 +02:00
< ? php
2016-06-15 06:03:16 +02:00
2016-10-14 03:30:05 +02:00
namespace SilverStripe\ORM\Tests ;
2016-06-15 06:03:16 +02:00
use SilverStripe\ORM\DB ;
use SilverStripe\ORM\DataList ;
use SilverStripe\ORM\DataObject ;
2016-10-14 03:30:05 +02:00
use SilverStripe\ORM\Tests\DataObjectTest\SubTeam ;
use SilverStripe\ORM\Tests\DataObjectTest\Team ;
2016-08-19 00:51:35 +02:00
use SilverStripe\Dev\SapphireTest ;
2012-04-20 00:08:17 +02:00
2016-12-16 05:34:21 +01:00
class DataObjectLazyLoadingTest extends SapphireTest
{
2020-04-20 19:58:09 +02:00
protected static $fixture_file = [
2016-12-16 05:34:21 +01:00
'DataObjectTest.yml' ,
2020-04-20 19:58:09 +02:00
];
2016-12-16 05:34:21 +01:00
2017-06-22 12:50:45 +02:00
public static function getExtraDataObjects ()
2016-12-16 05:34:21 +01:00
{
return array_merge (
DataObjectTest :: $extra_data_objects ,
2017-03-21 04:22:23 +01:00
ManyManyListTest :: $extra_data_objects
2016-12-16 05:34:21 +01:00
);
}
public function testQueriedColumnsID ()
{
$db = DB :: get_conn ();
$playerList = new DataList ( SubTeam :: class );
2020-04-20 19:58:09 +02:00
$playerList = $playerList -> setQueriedColumns ([ 'ID' ]);
2018-01-16 19:39:30 +01:00
$expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' . '"DataObjectTest_Team"."Created", "DataObjectTest_Team"."ID", CASE WHEN ' . '"DataObjectTest_Team"."ClassName" IS NOT NULL THEN "DataObjectTest_Team"."ClassName" ELSE ' . $db -> quoteString ( Team :: class ) . ' END AS "RecordClassName", "DataObjectTest_Team"."Title" ' . 'FROM "DataObjectTest_Team" ' . 'LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = "DataObjectTest_Team"."ID" ' . 'WHERE ("DataObjectTest_Team"."ClassName" IN (?))' . ' ORDER BY "DataObjectTest_Team"."Title" ASC' ;
2016-12-16 05:34:21 +01:00
$this -> assertSQLEquals ( $expected , $playerList -> sql ( $parameters ));
}
public function testQueriedColumnsFromBaseTableAndSubTable ()
{
$db = DB :: get_conn ();
$playerList = new DataList ( SubTeam :: class );
2020-04-20 19:58:09 +02:00
$playerList = $playerList -> setQueriedColumns ([ 'Title' , 'SubclassDatabaseField' ]);
2018-01-16 19:39:30 +01:00
$expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' . '"DataObjectTest_Team"."Created", "DataObjectTest_Team"."Title", ' . '"DataObjectTest_SubTeam"."SubclassDatabaseField", "DataObjectTest_Team"."ID", CASE WHEN ' . '"DataObjectTest_Team"."ClassName" IS NOT NULL THEN "DataObjectTest_Team"."ClassName" ELSE ' . $db -> quoteString ( Team :: class ) . ' END AS "RecordClassName" FROM "DataObjectTest_Team" ' . 'LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = "DataObjectTest_Team"."ID" WHERE ' . '("DataObjectTest_Team"."ClassName" IN (?)) ' . 'ORDER BY "DataObjectTest_Team"."Title" ASC' ;
2016-12-16 05:34:21 +01:00
$this -> assertSQLEquals ( $expected , $playerList -> sql ( $parameters ));
}
public function testQueriedColumnsFromBaseTable ()
{
$db = DB :: get_conn ();
$playerList = new DataList ( SubTeam :: class );
2020-04-20 19:58:09 +02:00
$playerList = $playerList -> setQueriedColumns ([ 'Title' ]);
2018-01-16 19:39:30 +01:00
$expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' . '"DataObjectTest_Team"."Created", "DataObjectTest_Team"."Title", "DataObjectTest_Team"."ID", ' . 'CASE WHEN "DataObjectTest_Team"."ClassName" IS NOT NULL THEN "DataObjectTest_Team"."ClassName" ELSE ' . $db -> quoteString ( Team :: class ) . ' END AS "RecordClassName" FROM "DataObjectTest_Team" ' . 'LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = "DataObjectTest_Team"."ID" WHERE ' . '("DataObjectTest_Team"."ClassName" IN (?)) ' . 'ORDER BY "DataObjectTest_Team"."Title" ASC' ;
2016-12-16 05:34:21 +01:00
$this -> assertSQLEquals ( $expected , $playerList -> sql ( $parameters ));
}
public function testQueriedColumnsFromSubTable ()
{
$db = DB :: get_conn ();
$playerList = new DataList ( SubTeam :: class );
2020-04-20 19:58:09 +02:00
$playerList = $playerList -> setQueriedColumns ([ 'SubclassDatabaseField' ]);
2018-01-16 19:39:30 +01:00
$expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' . '"DataObjectTest_Team"."Created", "DataObjectTest_SubTeam"."SubclassDatabaseField", ' . '"DataObjectTest_Team"."ID", CASE WHEN "DataObjectTest_Team"."ClassName" IS NOT NULL THEN ' . '"DataObjectTest_Team"."ClassName" ELSE ' . $db -> quoteString ( Team :: class ) . ' END ' . 'AS "RecordClassName", "DataObjectTest_Team"."Title" ' . 'FROM "DataObjectTest_Team" LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = ' . '"DataObjectTest_Team"."ID" WHERE ("DataObjectTest_Team"."ClassName" IN (?)) ' . 'ORDER BY "DataObjectTest_Team"."Title" ASC' ;
2016-12-16 05:34:21 +01:00
$this -> assertSQLEquals ( $expected , $playerList -> sql ( $parameters ));
}
public function testNoSpecificColumnNamesBaseDataObjectQuery ()
{
// This queries all columns from base table
$playerList = new DataList ( Team :: class );
// Shouldn't be a left join in here.
$this -> assertEquals (
0 ,
preg_match (
$this -> normaliseSQL (
'/SELECT DISTINCT "DataObjectTest_Team"."ID" .* LEFT JOIN .* FROM "DataObjectTest_Team"/'
2022-04-14 03:12:59 +02:00
) ? ? '' ,
$this -> normaliseSQL ( $playerList -> sql ( $parameters )) ? ? ''
2016-12-16 05:34:21 +01:00
)
);
}
public function testNoSpecificColumnNamesSubclassDataObjectQuery ()
{
// This queries all columns from base table and subtable
$playerList = new DataList ( SubTeam :: class );
// Should be a left join.
$this -> assertEquals (
1 ,
preg_match (
2022-04-14 03:12:59 +02:00
$this -> normaliseSQL ( '/SELECT DISTINCT .* LEFT JOIN .* /' ) ? ? '' ,
$this -> normaliseSQL ( $playerList -> sql ( $parameters )) ? ? ''
2016-12-16 05:34:21 +01:00
)
);
}
public function testLazyLoadedFieldsHasField ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
// TODO Fix hasField() to exclude *_Lazy
// $this->assertFalse($subteam1Lazy->hasField('SubclassDatabaseField_Lazy'));
$this -> assertTrue ( $subteam1Lazy -> hasField ( 'SubclassDatabaseField' ));
}
public function testLazyLoadedFieldsGetField ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$this -> assertEquals (
$subteam1 -> getField ( 'SubclassDatabaseField' ),
$subteam1Lazy -> getField ( 'SubclassDatabaseField' )
);
}
2017-02-07 12:57:49 +01:00
public function testDBObjectLazyLoadedFields ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$subteam1DO = $subteam1 -> dbObject ( 'SubclassDatabaseField' );
$subteam1LazyDO = $subteam1Lazy -> dbObject ( 'SubclassDatabaseField' );
$this -> assertEquals (
$subteam1DO -> getValue (),
$subteam1LazyDO -> getValue ()
);
}
2016-12-16 05:34:21 +01:00
public function testLazyLoadedFieldsSetField ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$subteam1ID = $subteam1 -> ID ;
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
// Updated lazyloaded field
$subteam1Lazy -> SubclassDatabaseField = 'Changed' ;
$subteam1Lazy -> write ();
// Reload from database
DataObject :: flush_and_destroy_cache ();
$subteam1Reloaded = DataObject :: get_by_id ( SubTeam :: class , $subteam1ID );
$this -> assertEquals (
'Changed' ,
$subteam1Reloaded -> getField ( 'SubclassDatabaseField' )
);
}
public function testLazyLoadedFieldsWriteWithUnloadedFields ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$subteam1ID = $subteam1 -> ID ;
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
// Updated lazyloaded field
$subteam1Lazy -> Title = 'Changed' ;
$subteam1Lazy -> write ();
// Reload from database
DataObject :: flush_and_destroy_cache ();
$subteam1Reloaded = DataObject :: get_by_id ( SubTeam :: class , $subteam1ID );
$this -> assertEquals (
'Subclassed 1' ,
$subteam1Reloaded -> getField ( 'SubclassDatabaseField' )
);
}
public function testLazyLoadedFieldsWriteNullFields ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$subteam1ID = $subteam1 -> ID ;
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
// Updated lazyloaded field
$subteam1Lazy -> SubclassDatabaseField = null ;
$subteam1Lazy -> write ();
// Reload from database
DataObject :: flush_and_destroy_cache ();
$subteam1Reloaded = DataObject :: get_by_id ( SubTeam :: class , $subteam1ID );
$this -> assertEquals (
null ,
$subteam1Reloaded -> getField ( 'SubclassDatabaseField' )
);
}
public function testLazyLoadedFieldsGetChangedFields ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
// Updated lazyloaded field
$subteam1Lazy -> SubclassDatabaseField = 'Changed' ;
$this -> assertEquals (
2020-04-20 19:58:09 +02:00
[ 'SubclassDatabaseField' => [
2016-12-16 05:34:21 +01:00
'before' => 'Subclassed 1' ,
'after' => 'Changed' ,
'level' => 2
2020-04-20 19:58:09 +02:00
]],
2016-12-16 05:34:21 +01:00
$subteam1Lazy -> getChangedFields ()
);
}
public function testLazyLoadedFieldsHasOneRelation ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$parentTeam = $this -> objFromFixture ( Team :: class , 'team1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$parentTeamLazy = $subteam1Lazy -> ParentTeam ();
$this -> assertInstanceOf ( Team :: class , $parentTeamLazy );
$this -> assertEquals ( $parentTeam -> ID , $parentTeamLazy -> ID );
}
public function testLazyLoadedFieldsToMap ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$parentTeam = $this -> objFromFixture ( Team :: class , 'team1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$mapLazy = $subteam1Lazy -> toMap ();
$this -> assertArrayHasKey ( 'SubclassDatabaseField' , $mapLazy );
$this -> assertEquals ( 'Subclassed 1' , $mapLazy [ 'SubclassDatabaseField' ]);
}
public function testLazyLoadedFieldsIsEmpty ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$parentTeam = $this -> objFromFixture ( Team :: class , 'team1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$subteam1Lazy -> Title = '' ;
$subteam1Lazy -> DecoratedDatabaseField = '' ;
$subteam1Lazy -> ParentTeamID = 0 ;
// Leave $subteam1Lazy->SubclassDatabaseField intact
$this -> assertFalse ( $subteam1Lazy -> isEmpty ());
}
public function testLazyLoadedFieldsDuplicate ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$parentTeam = $this -> objFromFixture ( Team :: class , 'team1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$subteam1LazyDup = $subteam1Lazy -> duplicate ();
$this -> assertEquals ( 'Subclassed 1' , $subteam1LazyDup -> SubclassDatabaseField );
}
public function testLazyLoadedFieldsGetAllFields ()
{
$subteam1 = $this -> objFromFixture ( SubTeam :: class , 'subteam1' );
$parentTeam = $this -> objFromFixture ( Team :: class , 'team1' );
$teams = DataObject :: get ( Team :: class ); // query parent class
$subteam1Lazy = $teams -> find ( 'ID' , $subteam1 -> ID );
$this -> assertArrayNotHasKey ( 'SubclassDatabaseField_Lazy' , $subteam1Lazy -> toMap ());
$this -> assertArrayHasKey ( 'SubclassDatabaseField' , $subteam1Lazy -> toMap ());
}
2012-04-20 00:08:17 +02:00
}