mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
aeccb8b8e0
API: Deprecate SS_Datetime. The DBField subclasses are have all been renamed to start with “DB” and be in the SilverStripe\Model\FieldType namespace. To keep DataObject definitions concise, the original short variations of their names are preserved as service definitions. Most of the field generation code doesn’t need to change, but where field classes are referenced directly, changes will be needed. SS_Datetime, which is commonly referenced outside the model system itself, has been preserved as a subclass of DBDatetime. This has been marked as deprecated and can be removed in SilverStripe 5. A few places that referred to $db and $casting values weren’t using the Injector to instantiate the relevant classes. This meant that the remapping we have created as part of moving classes into a namespace didn’t work.
301 lines
9.1 KiB
PHP
301 lines
9.1 KiB
PHP
<?php
|
||
/**
|
||
* See {@link SSViewerTest->testCastingHelpers()} for more tests related to casting and ViewableData behaviour,
|
||
* from a template-parsing perspective.
|
||
*
|
||
* @package framework
|
||
* @subpackage tests
|
||
*/
|
||
class ViewableDataTest extends SapphireTest {
|
||
|
||
public function testRequiresCasting() {
|
||
$caster = new ViewableDataTest_Castable();
|
||
|
||
$this->assertTrue($caster->obj('alwaysCasted') instanceof ViewableDataTest_RequiresCasting);
|
||
$this->assertTrue($caster->obj('noCastingInformation') instanceof ViewableData_Caster);
|
||
|
||
$this->assertTrue($caster->obj('alwaysCasted', null, false) instanceof ViewableDataTest_RequiresCasting);
|
||
$this->assertFalse($caster->obj('noCastingInformation', null, false) instanceof ViewableData_Caster);
|
||
}
|
||
|
||
public function testFailoverRequiresCasting() {
|
||
$caster = new ViewableDataTest_Castable();
|
||
$container = new ViewableDataTest_Container();
|
||
$container->setFailover($caster);
|
||
|
||
$this->assertTrue($container->obj('alwaysCasted') instanceof ViewableDataTest_RequiresCasting);
|
||
$this->assertTrue($caster->obj('alwaysCasted', null, false) instanceof ViewableDataTest_RequiresCasting);
|
||
|
||
/* @todo This currently fails, because the default_cast static variable is always taken from the topmost
|
||
* object, not the failover object the field actually came from. Should we fix this, or declare current
|
||
* behaviour as correct?
|
||
*
|
||
* $this->assertTrue($container->obj('noCastingInformation') instanceof ViewableData_Caster);
|
||
* $this->assertFalse($caster->obj('noCastingInformation', null, false) instanceof ViewableData_Caster);
|
||
*/
|
||
}
|
||
|
||
public function testCastingXMLVal() {
|
||
$caster = new ViewableDataTest_Castable();
|
||
|
||
$this->assertEquals('casted', $caster->XML_val('alwaysCasted'));
|
||
$this->assertEquals('noCastingInformation', $caster->XML_val('noCastingInformation'));
|
||
|
||
// test automatic escaping is only applied by casted classes
|
||
$this->assertEquals('<foo>', $caster->XML_val('unsafeXML'));
|
||
$this->assertEquals('<foo>', $caster->XML_val('castedUnsafeXML'));
|
||
}
|
||
|
||
public function testUncastedXMLVal() {
|
||
$caster = new ViewableDataTest_Castable();
|
||
$this->assertEquals($caster->XML_val('uncastedZeroValue'), 0);
|
||
}
|
||
|
||
public function testArrayCustomise() {
|
||
$viewableData = new ViewableDataTest_Castable();
|
||
$newViewableData = $viewableData->customise(array (
|
||
'test' => 'overwritten',
|
||
'alwaysCasted' => 'overwritten'
|
||
));
|
||
|
||
$this->assertEquals('test', $viewableData->XML_val('test'));
|
||
$this->assertEquals('casted', $viewableData->XML_val('alwaysCasted'));
|
||
|
||
$this->assertEquals('overwritten', $newViewableData->XML_val('test'));
|
||
$this->assertEquals('overwritten', $newViewableData->XML_val('alwaysCasted'));
|
||
|
||
$this->assertEquals('castable', $viewableData->forTemplate());
|
||
$this->assertEquals('castable', $newViewableData->forTemplate());
|
||
}
|
||
|
||
public function testObjectCustomise() {
|
||
$viewableData = new ViewableDataTest_Castable();
|
||
$newViewableData = $viewableData->customise(new ViewableDataTest_RequiresCasting());
|
||
|
||
$this->assertEquals('test', $viewableData->XML_val('test'));
|
||
$this->assertEquals('casted', $viewableData->XML_val('alwaysCasted'));
|
||
|
||
$this->assertEquals('overwritten', $newViewableData->XML_val('test'));
|
||
$this->assertEquals('casted', $newViewableData->XML_val('alwaysCasted'));
|
||
|
||
$this->assertEquals('castable', $viewableData->forTemplate());
|
||
$this->assertEquals('casted', $newViewableData->forTemplate());
|
||
}
|
||
|
||
public function testDefaultValueWrapping() {
|
||
$data = new ArrayData(array('Title' => 'SomeTitleValue'));
|
||
// this results in a cached raw string in ViewableData:
|
||
$this->assertTrue($data->hasValue('Title'));
|
||
$this->assertFalse($data->hasValue('SomethingElse'));
|
||
// this should cast the raw string to a StringField since we are
|
||
// passing true as the third argument:
|
||
$obj = $data->obj('Title', null, true);
|
||
$this->assertTrue(is_object($obj));
|
||
// and the string field should have the value of the raw string:
|
||
$this->assertEquals('SomeTitleValue', $obj->forTemplate());
|
||
}
|
||
|
||
public function testRAWVal() {
|
||
$data = new ViewableDataTest_Castable();
|
||
$data->test = 'This & This';
|
||
$this->assertEquals($data->RAW_val('test'), 'This & This');
|
||
}
|
||
|
||
public function testSQLVal() {
|
||
$data = new ViewableDataTest_Castable();
|
||
$this->assertEquals($data->SQL_val('test'), 'test');
|
||
}
|
||
|
||
public function testJSVal() {
|
||
$data = new ViewableDataTest_Castable();
|
||
$data->test = '"this is a test"';
|
||
$this->assertEquals($data->JS_val('test'), '\"this is a test\"');
|
||
}
|
||
|
||
public function testATTVal() {
|
||
$data = new ViewableDataTest_Castable();
|
||
$data->test = '"this is a test"';
|
||
$this->assertEquals($data->ATT_val('test'), '"this is a test"');
|
||
}
|
||
|
||
public function testCastingClass() {
|
||
$expected = array(
|
||
'NonExistant' => null,
|
||
'Field' => 'CastingType',
|
||
'Argument' => 'ArgumentType',
|
||
'ArrayArgument' => 'ArrayArgumentType'
|
||
);
|
||
$obj = new ViewableDataTest_CastingClass();
|
||
|
||
foreach($expected as $field => $class) {
|
||
$this->assertEquals(
|
||
$class,
|
||
$obj->castingClass($field),
|
||
"castingClass() returns correct results for ::\$$field"
|
||
);
|
||
}
|
||
}
|
||
|
||
public function testObjWithCachedStringValueReturnsValidObject() {
|
||
$obj = new ViewableDataTest_NoCastingInformation();
|
||
|
||
// Save a literal string into cache
|
||
$cache = true;
|
||
$uncastedData = $obj->obj('noCastingInformation', null, false, $cache);
|
||
|
||
// Fetch the cached string as an object
|
||
$forceReturnedObject = true;
|
||
$castedData = $obj->obj('noCastingInformation', null, $forceReturnedObject);
|
||
|
||
// Uncasted data should always be the nonempty string
|
||
$this->assertNotEmpty($uncastedData, 'Uncasted data was empty.');
|
||
$this->assertTrue(is_string($uncastedData), 'Uncasted data should be a string.');
|
||
|
||
// Casted data should be the string wrapped in a DBField-object.
|
||
$this->assertNotEmpty($castedData, 'Casted data was empty.');
|
||
$this->assertInstanceOf('SilverStripe\Model\FieldType\DBField', $castedData, 'Casted data should be instance of DBField.');
|
||
|
||
$this->assertEquals($uncastedData, $castedData->getValue(), 'Casted and uncasted strings are not equal.');
|
||
}
|
||
|
||
public function testCaching() {
|
||
$objCached = new ViewableDataTest_Cached();
|
||
$objNotCached = new ViewableDataTest_NotCached();
|
||
|
||
$objCached->Test = 'AAA';
|
||
$objNotCached->Test = 'AAA';
|
||
|
||
$this->assertEquals('AAA', $objCached->obj('Test', null, true, true));
|
||
$this->assertEquals('AAA', $objNotCached->obj('Test', null, true, true));
|
||
|
||
$objCached->Test = 'BBB';
|
||
$objNotCached->Test = 'BBB';
|
||
|
||
// Cached data must be always the same
|
||
$this->assertEquals('AAA', $objCached->obj('Test', null, true, true));
|
||
$this->assertEquals('BBB', $objNotCached->obj('Test', null, true, true));
|
||
}
|
||
|
||
public function testSetFailover() {
|
||
$failover = new ViewableData();
|
||
$container = new ViewableDataTest_Container();
|
||
$container->setFailover($failover);
|
||
|
||
$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
|
||
$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() is already defined when it shouldn’t be');
|
||
|
||
// Ensure that defined methods detected from the failover aren't cached when setting a new failover
|
||
$container->setFailover(new ViewableDataTest_Failover);
|
||
$this->assertTrue($container->hasMethod('testMethod'));
|
||
}
|
||
|
||
}
|
||
|
||
/**#@+
|
||
* @ignore
|
||
*/
|
||
class ViewableDataTest_Castable extends ViewableData {
|
||
|
||
private static $default_cast = 'ViewableData_Caster';
|
||
|
||
private static $casting = array (
|
||
'alwaysCasted' => 'ViewableDataTest_RequiresCasting',
|
||
'castedUnsafeXML' => 'ViewableData_UnescaptedCaster'
|
||
);
|
||
|
||
public $test = 'test';
|
||
|
||
public $uncastedZeroValue = 0;
|
||
|
||
public function alwaysCasted() {
|
||
return 'alwaysCasted';
|
||
}
|
||
|
||
public function noCastingInformation() {
|
||
return 'noCastingInformation';
|
||
}
|
||
|
||
public function unsafeXML() {
|
||
return '<foo>';
|
||
}
|
||
|
||
public function castedUnsafeXML() {
|
||
return $this->unsafeXML();
|
||
}
|
||
|
||
public function forTemplate() {
|
||
return 'castable';
|
||
}
|
||
}
|
||
|
||
class ViewableDataTest_RequiresCasting extends ViewableData {
|
||
|
||
public $test = 'overwritten';
|
||
|
||
public function forTemplate() {
|
||
return 'casted';
|
||
}
|
||
|
||
public function setValue() {}
|
||
|
||
}
|
||
|
||
class ViewableData_UnescaptedCaster extends ViewableData {
|
||
|
||
protected $value;
|
||
|
||
public function setValue($value) {
|
||
$this->value = $value;
|
||
}
|
||
|
||
public function forTemplate() {
|
||
return Convert::raw2xml($this->value);
|
||
}
|
||
|
||
}
|
||
|
||
class ViewableData_Caster extends ViewableData {
|
||
|
||
public function forTemplate() {
|
||
return 'casted';
|
||
}
|
||
|
||
public function setValue() {}
|
||
|
||
}
|
||
|
||
class ViewableDataTest_Container extends ViewableData {
|
||
|
||
}
|
||
|
||
class ViewableDataTest_CastingClass extends ViewableData {
|
||
private static $casting = array(
|
||
'Field' => 'CastingType',
|
||
'Argument' => 'ArgumentType(Argument)',
|
||
'ArrayArgument' => 'ArrayArgumentType(array(foo, bar))'
|
||
);
|
||
}
|
||
|
||
class ViewableDataTest_NoCastingInformation extends ViewableData {
|
||
public function noCastingInformation() {
|
||
return "No casting information";
|
||
}
|
||
}
|
||
|
||
class ViewableDataTest_Cached extends ViewableData {
|
||
public $Test;
|
||
}
|
||
|
||
class ViewableDataTest_NotCached extends ViewableData {
|
||
public $Test;
|
||
|
||
protected function objCacheGet($key) {
|
||
// Disable caching
|
||
return null;
|
||
}
|
||
}
|
||
|
||
class ViewableDataTest_Failover extends ViewableData {
|
||
public function testMethod() {}
|
||
}
|