mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API Remove Object class
API DataObjectSchema::manyManyComponent() return array is now associative array
This commit is contained in:
parent
7e2f8d1f2d
commit
fba8e2c245
@ -30,6 +30,7 @@ guide developers in preparing existing 3.x code for compatibility with 4.0
|
||||
arrangement of templates, as well as other references to classes via string literals or configuration.
|
||||
Automatic upgrading tools have been developed to cope with the bulk of these changes (see
|
||||
[upgrading notes](#upgrading)).
|
||||
* Object class has been removed.
|
||||
* Asset storage has been abstracted, and a new concept of `DBFile` references via database column references
|
||||
now exists in addition to references via the existing `File` dataobject. File security and protected files
|
||||
are now a core feature.
|
||||
@ -161,6 +162,90 @@ Note also that `$_FILE_TO_URL_MAPPING` has been removed and replaced with `SS_BA
|
||||
|
||||
See [Environment Management docs](/getting-started/environment_management/) for full details.
|
||||
|
||||
#### Replace usages of Object class
|
||||
|
||||
Object has been superseded by a trio of traits which replace components of this legacy class:
|
||||
|
||||
- Injectable: Provides `MyClass::create()` and `MyClass::singleton()`
|
||||
- Configurable: Provides `MyClass::config()`
|
||||
- Extensible: Provides all methods related to extensions (E.g. add_extension()). Note:
|
||||
All classes which use this trait MUST invoke `constructExtensions()` in its constructor.
|
||||
|
||||
In particular specific Object class usages should be replaced as below:
|
||||
|
||||
|
||||
Upgrade subclasses
|
||||
|
||||
|
||||
:::php
|
||||
// old
|
||||
class MyClass extends Object {}
|
||||
// new
|
||||
class MyClass {
|
||||
use Extensible;
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
public function __construct() {
|
||||
// Only needed if using Extensible trait
|
||||
$this->constructExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
References to $this->class
|
||||
|
||||
|
||||
:::php
|
||||
// old
|
||||
$obj->class
|
||||
$this->class;
|
||||
// new
|
||||
get_class($obj);
|
||||
static::class;
|
||||
|
||||
|
||||
Upgrade parse_class_spec()
|
||||
|
||||
|
||||
:::php
|
||||
// old
|
||||
$spec = Object::parse_class_spec($spec);
|
||||
// new
|
||||
$spec = ClassInfo::parse_class_spec($spec);
|
||||
|
||||
|
||||
Upgrade create_from_string()
|
||||
|
||||
|
||||
:::php
|
||||
// old
|
||||
$obj = Object::create_from_string('Varchar(100)');
|
||||
// new
|
||||
$obj = Injector::inst()->create('Varchar(100)');
|
||||
|
||||
|
||||
Extensions
|
||||
|
||||
|
||||
:::php
|
||||
// old
|
||||
Object::add_extension('File', 'Versioned');
|
||||
$has = Object::has_extension('File', 'Versioned');
|
||||
$extensions = Object::get_extensions('File');
|
||||
// new
|
||||
File::add_extension(Versioned::class);
|
||||
$has = File::has_extension(Versioned::class)
|
||||
$extensions = File::get_extensions();
|
||||
|
||||
// new (alternate form)
|
||||
// Note: The class the extension method is called on MUST be a parent class
|
||||
// of the first argument.
|
||||
DataObject::add_extension(File::class, Versioned::class); // alternate
|
||||
$has = DataObject::has_extension(File::class, Versioned::class); // alternate
|
||||
$extensions = DataObject::get_extensions(File::class);
|
||||
|
||||
|
||||
#### Compatibility with the new front-end building tools
|
||||
|
||||
If you are using Requirements from 3.x then your scripts should continue to work as they did before.
|
||||
@ -1203,6 +1288,10 @@ After (`mysite/_config/config.yml`):
|
||||
* Introduced new ModuleLoader manifest, which allows modules to be found via composer name.
|
||||
E.g. `$cms = ModuleLoader::inst()->getManifest()->getModule('silverstripe/cms')`
|
||||
* `ClassManifest::getOwnerModule()` now returns a `Module` object instance.
|
||||
* `Object` class has been removed.
|
||||
* `parse_class_spec` moved to `ClassInfo`
|
||||
* `create_from_spec` functionality removed, but now supportede by `Injector` natively.
|
||||
* `Injectable`, `Extensible` and `Configurable` traits added to support other methods.
|
||||
* Certain methods have been moved from `Controller` to `RequestHandler`:
|
||||
* `Link`
|
||||
* `redirect`
|
||||
|
@ -32,7 +32,7 @@ abstract class CliController extends Controller
|
||||
|
||||
public function index()
|
||||
{
|
||||
foreach (ClassInfo::subclassesFor($this->class) as $subclass) {
|
||||
foreach (ClassInfo::subclassesFor(static::class) as $subclass) {
|
||||
echo $subclass . "\n";
|
||||
/** @var CliController $task */
|
||||
$task = Injector::inst()->create($subclass);
|
||||
|
@ -3,7 +3,8 @@
|
||||
namespace SilverStripe\Control;
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* The content negotiator performs "text/html" or "application/xhtml+xml" switching. It does this through
|
||||
@ -31,8 +32,10 @@ use SilverStripe\Core\Object;
|
||||
* Some developers might know what they're doing and don't want ContentNegotiator messing with their
|
||||
* HTML4 doctypes, but still find it useful to have self-closing tags removed.
|
||||
*/
|
||||
class ContentNegotiator extends Object
|
||||
class ContentNegotiator
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @config
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace SilverStripe\Control;
|
||||
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Dev\Debug;
|
||||
use SilverStripe\ORM\DataModel;
|
||||
@ -122,8 +121,9 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
|
||||
$this->baseInitCalled = false;
|
||||
$this->init();
|
||||
if (!$this->baseInitCalled) {
|
||||
$class = static::class;
|
||||
user_error(
|
||||
"init() method on class '$this->class' doesn't call Controller::init()."
|
||||
"init() method on class '{$class}' doesn't call Controller::init()."
|
||||
. "Make sure that you have parent::init() included.",
|
||||
E_USER_WARNING
|
||||
);
|
||||
@ -231,18 +231,22 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
|
||||
{
|
||||
if ($response instanceof HTTPResponse) {
|
||||
if (isset($_REQUEST['debug_request'])) {
|
||||
$class = static::class;
|
||||
Debug::message(
|
||||
"Request handler returned HTTPResponse object to $this->class controller;"
|
||||
"Request handler returned HTTPResponse object to {$class} controller;"
|
||||
. "returning it without modification."
|
||||
);
|
||||
}
|
||||
$this->setResponse($response);
|
||||
} else {
|
||||
if ($response instanceof Object && $response->hasMethod('getViewer')) {
|
||||
// Could be Controller, or ViewableData_Customised controller wrapper
|
||||
if (ClassInfo::hasMethod($response, 'getViewer')) {
|
||||
if (isset($_REQUEST['debug_request'])) {
|
||||
$class = static::class;
|
||||
$responseClass = get_class($response);
|
||||
Debug::message(
|
||||
"Request handler $response->class object to $this->class controller;"
|
||||
. "rendering with template returned by $response->class::getViewer()"
|
||||
"Request handler {$responseClass} object to {$class} controller;"
|
||||
. "rendering with template returned by {$responseClass}::getViewer()"
|
||||
);
|
||||
}
|
||||
$response = $response->getViewer($this->getAction())->process($response);
|
||||
@ -399,14 +403,14 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
|
||||
// Add action-specific templates for inheritance chain
|
||||
$templates = array();
|
||||
if ($action && $action != 'index') {
|
||||
$parentClass = $this->class;
|
||||
$parentClass = static::class;
|
||||
while ($parentClass != __CLASS__) {
|
||||
$templates[] = strtok($parentClass, '_') . '_' . $action;
|
||||
$parentClass = get_parent_class($parentClass);
|
||||
}
|
||||
}
|
||||
// Add controller templates for inheritance chain
|
||||
$parentClass = $this->class;
|
||||
$parentClass = static::class;
|
||||
while ($parentClass != __CLASS__) {
|
||||
$templates[] = strtok($parentClass, '_');
|
||||
$parentClass = get_parent_class($parentClass);
|
||||
@ -469,7 +473,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
|
||||
return $definingClass;
|
||||
}
|
||||
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
while ($class != 'SilverStripe\\Control\\RequestHandler') {
|
||||
$templateName = strtok($class, '_') . '_' . $action;
|
||||
if (SSViewer::hasTemplate($templateName)) {
|
||||
@ -496,7 +500,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
|
||||
return true;
|
||||
}
|
||||
|
||||
$parentClass = $this->class;
|
||||
$parentClass = static::class;
|
||||
$templates = array();
|
||||
|
||||
while ($parentClass != __CLASS__) {
|
||||
@ -614,8 +618,9 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
|
||||
if ($this === self::$controller_stack[0]) {
|
||||
array_shift(self::$controller_stack);
|
||||
} else {
|
||||
$class = static::class;
|
||||
user_error(
|
||||
"popCurrent called on $this->class controller, but it wasn't at the top of the stack",
|
||||
"popCurrent called on {$class} controller, but it wasn't at the top of the stack",
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
|
@ -573,7 +573,8 @@ class Email extends ViewableData
|
||||
{
|
||||
$this->render();
|
||||
|
||||
return "<h2>Email template {$this->class}:</h2>\n" . '<pre>' . $this->getSwiftMessage()->toString() . '</pre>';
|
||||
$class = static::class;
|
||||
return "<h2>Email template {$class}:</h2>\n" . '<pre>' . $this->getSwiftMessage()->toString() . '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -272,7 +272,7 @@ class RSSFeed extends ViewableData
|
||||
*/
|
||||
public function getTemplates()
|
||||
{
|
||||
$templates = SSViewer::get_templates_by_class(get_class($this), '', __CLASS__);
|
||||
$templates = SSViewer::get_templates_by_class(static::class, '', __CLASS__);
|
||||
// Prefer any custom template
|
||||
if ($this->getTemplate()) {
|
||||
array_unshift($templates, $this->getTemplate());
|
||||
|
@ -130,7 +130,7 @@ class RSSFeed_Entry extends ViewableData
|
||||
}
|
||||
|
||||
throw new BadMethodCallException(
|
||||
$this->failover->class .
|
||||
get_class($this->failover) .
|
||||
" object has neither an AbsoluteLink nor a Link method." .
|
||||
" Can't put a link in the RSS feed",
|
||||
E_USER_WARNING
|
||||
|
@ -5,7 +5,6 @@ namespace SilverStripe\Control;
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\Debug;
|
||||
use SilverStripe\ORM\DataModel;
|
||||
use SilverStripe\Security\Security;
|
||||
@ -164,7 +163,7 @@ class RequestHandler extends ViewableData
|
||||
{
|
||||
// $handlerClass is used to step up the class hierarchy to implement url_handlers inheritance
|
||||
if ($this->brokenOnConstruct) {
|
||||
$handlerClass = get_class($this);
|
||||
$handlerClass = static::class;
|
||||
throw new BadMethodCallException(
|
||||
"parent::__construct() needs to be called on {$handlerClass}::__construct()"
|
||||
);
|
||||
@ -205,7 +204,7 @@ class RequestHandler extends ViewableData
|
||||
user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR);
|
||||
}
|
||||
|
||||
$classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this);
|
||||
$classMessage = Director::isLive() ? 'on this handler' : 'on class '.static::class;
|
||||
|
||||
try {
|
||||
if (!$this->hasAction($action)) {
|
||||
@ -263,7 +262,7 @@ class RequestHandler extends ViewableData
|
||||
*/
|
||||
protected function findAction($request)
|
||||
{
|
||||
$handlerClass = ($this->class) ? $this->class : get_class($this);
|
||||
$handlerClass = static::class;
|
||||
|
||||
// We stop after RequestHandler; in other words, at ViewableData
|
||||
while ($handlerClass && $handlerClass != ViewableData::class) {
|
||||
@ -272,14 +271,18 @@ class RequestHandler extends ViewableData
|
||||
if ($urlHandlers) {
|
||||
foreach ($urlHandlers as $rule => $action) {
|
||||
if (isset($_REQUEST['debug_request'])) {
|
||||
Debug::message("Testing '$rule' with '" . $request->remaining() . "' on $this->class");
|
||||
$class = static::class;
|
||||
$remaining = $request->remaining();
|
||||
Debug::message("Testing '{$rule}' with '{$remaining}' on {$class}");
|
||||
}
|
||||
|
||||
if ($request->match($rule, true)) {
|
||||
if (isset($_REQUEST['debug_request'])) {
|
||||
$class = static::class;
|
||||
$latestParams = var_export($request->latestParams(), true);
|
||||
Debug::message(
|
||||
"Rule '$rule' matched to action '$action' on $this->class. ".
|
||||
"Latest request params: " . var_export($request->latestParams(), true)
|
||||
"Rule '{$rule}' matched to action '{$action}' on {$class}. ".
|
||||
"Latest request params: {$latestParams}"
|
||||
);
|
||||
}
|
||||
|
||||
@ -304,7 +307,7 @@ class RequestHandler extends ViewableData
|
||||
*/
|
||||
protected function handleAction($request, $action)
|
||||
{
|
||||
$classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this);
|
||||
$classMessage = Director::isLive() ? 'on this handler' : 'on class '.static::class;
|
||||
|
||||
if (!$this->hasMethod($action)) {
|
||||
return new HTTPResponse("Action '$action' isn't available $classMessage.", 404);
|
||||
@ -469,7 +472,7 @@ class RequestHandler extends ViewableData
|
||||
$isAllowed = true;
|
||||
} elseif (substr($test, 0, 2) == '->') {
|
||||
// Determined by custom method with "->" prefix
|
||||
list($method, $arguments) = Object::parse_class_spec(substr($test, 2));
|
||||
list($method, $arguments) = ClassInfo::parse_class_spec(substr($test, 2));
|
||||
$isAllowed = call_user_func_array(array($this, $method), $arguments);
|
||||
} else {
|
||||
// Value is a permission code to check the current member against
|
||||
@ -564,7 +567,7 @@ class RequestHandler extends ViewableData
|
||||
|
||||
// no link defined by default
|
||||
trigger_error(
|
||||
'Request handler '.get_class($this). ' does not have a url_segment defined. '.
|
||||
'Request handler '.static::class. ' does not have a url_segment defined. '.
|
||||
'Relying on this link may be an application error',
|
||||
E_USER_WARNING
|
||||
);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Manifest\ClassLoader;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
@ -43,14 +44,26 @@ class ClassInfo
|
||||
|
||||
/**
|
||||
* Cache for {@link hasTable()}
|
||||
*
|
||||
* @internal
|
||||
* @var array
|
||||
*/
|
||||
private static $_cache_all_tables = array();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @var array Cache for {@link ancestry()}.
|
||||
*/
|
||||
private static $_cache_ancestry = array();
|
||||
|
||||
/**
|
||||
* Cache for parse_class_spec
|
||||
*
|
||||
* @internal
|
||||
* @var array
|
||||
*/
|
||||
private static $_cache_parse = [];
|
||||
|
||||
/**
|
||||
* @todo Move this to SS_Database or DB
|
||||
*
|
||||
@ -358,4 +371,148 @@ class ClassInfo
|
||||
}
|
||||
return method_exists($object, 'hasMethod') && $object->hasMethod($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a class-spec, such as "Versioned('Stage','Live')", as passed to create_from_string().
|
||||
* Returns a 2-element array, with classname and arguments
|
||||
*
|
||||
* @param string $classSpec
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function parse_class_spec($classSpec)
|
||||
{
|
||||
if (isset(static::$_cache_parse[$classSpec])) {
|
||||
return static::$_cache_parse[$classSpec];
|
||||
}
|
||||
|
||||
$tokens = token_get_all("<?php $classSpec");
|
||||
$class = null;
|
||||
$args = array();
|
||||
|
||||
// Keep track of the current bucket that we're putting data into
|
||||
$bucket = &$args;
|
||||
$bucketStack = array();
|
||||
$hadNamespace = false;
|
||||
$currentKey = null;
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
// $forceResult used to allow null result to be detected
|
||||
$result = $forceResult = null;
|
||||
$tokenName = is_array($token) ? $token[0] : $token;
|
||||
|
||||
// Get the class name
|
||||
if ($class === null && is_array($token) && $token[0] === T_STRING) {
|
||||
$class = $token[1];
|
||||
} elseif (is_array($token) && $token[0] === T_NS_SEPARATOR) {
|
||||
$class .= $token[1];
|
||||
$hadNamespace = true;
|
||||
} elseif ($hadNamespace && is_array($token) && $token[0] === T_STRING) {
|
||||
$class .= $token[1];
|
||||
$hadNamespace = false;
|
||||
// Get arguments
|
||||
} elseif (is_array($token)) {
|
||||
switch ($token[0]) {
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
$argString = $token[1];
|
||||
switch ($argString[0]) {
|
||||
case '"':
|
||||
$result = stripcslashes(substr($argString, 1, -1));
|
||||
break;
|
||||
case "'":
|
||||
$result = str_replace(array("\\\\", "\\'"), array("\\", "'"), substr($argString, 1, -1));
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Bad T_CONSTANT_ENCAPSED_STRING arg $argString");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_DNUMBER:
|
||||
$result = (double)$token[1];
|
||||
break;
|
||||
|
||||
case T_LNUMBER:
|
||||
$result = (int)$token[1];
|
||||
break;
|
||||
|
||||
case T_DOUBLE_ARROW:
|
||||
// We've encountered an associative array (the array itself has already been
|
||||
// added to the bucket), so the previous item added to the bucket is the key
|
||||
end($bucket);
|
||||
$currentKey = current($bucket);
|
||||
array_pop($bucket);
|
||||
break;
|
||||
|
||||
case T_STRING:
|
||||
switch ($token[1]) {
|
||||
case 'true':
|
||||
$result = true;
|
||||
|
||||
break;
|
||||
case 'false':
|
||||
$result = false;
|
||||
|
||||
break;
|
||||
case 'null':
|
||||
$result = null;
|
||||
$forceResult = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Bad T_STRING arg '{$token[1]}'");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_ARRAY:
|
||||
$result = array();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ($tokenName === '[') {
|
||||
$result = array();
|
||||
} elseif (($tokenName === ')' || $tokenName === ']') && ! empty($bucketStack)) {
|
||||
// Store the bucket we're currently working on
|
||||
$oldBucket = $bucket;
|
||||
// Fetch the key for the bucket at the top of the stack
|
||||
end($bucketStack);
|
||||
$key = key($bucketStack);
|
||||
reset($bucketStack);
|
||||
// Re-instate the bucket from the top of the stack
|
||||
$bucket = &$bucketStack[$key];
|
||||
// Add our saved, "nested" bucket to the bucket we just popped off the stack
|
||||
$bucket[$key] = $oldBucket;
|
||||
// Remove the bucket we just popped off the stack
|
||||
array_pop($bucketStack);
|
||||
}
|
||||
}
|
||||
|
||||
// If we've got something to add to the bucket, add it
|
||||
if ($result !== null || $forceResult) {
|
||||
if ($currentKey) {
|
||||
$bucket[$currentKey] = $result;
|
||||
$currentKey = null;
|
||||
} else {
|
||||
$bucket[] = $result;
|
||||
}
|
||||
|
||||
// If we've just pushed an array, that becomes our new bucket
|
||||
if ($result === array()) {
|
||||
// Fetch the key that the array was pushed to
|
||||
end($bucket);
|
||||
$key = key($bucket);
|
||||
reset($bucket);
|
||||
// Store reference to "old" bucket in the stack
|
||||
$bucketStack[$key] = &$bucket;
|
||||
// Set the active bucket to be our newly-pushed, empty array
|
||||
$bucket = &$bucket[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = [$class, $args];
|
||||
static::$_cache_parse[$classSpec] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ use SilverStripe\Config\MergeStrategy\Priority;
|
||||
use SilverStripe\Config\Middleware\Middleware;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class ExtensionMiddleware implements Middleware
|
||||
{
|
||||
@ -52,7 +51,7 @@ class ExtensionMiddleware implements Middleware
|
||||
|
||||
$extensions = $classConfig['extensions'];
|
||||
foreach ($extensions as $extension) {
|
||||
list($extensionClass, $extensionArgs) = Object::parse_class_spec($extension);
|
||||
list($extensionClass, $extensionArgs) = ClassInfo::parse_class_spec($extension);
|
||||
if (!class_exists($extensionClass)) {
|
||||
throw new InvalidArgumentException("$class references nonexistent $extensionClass in 'extensions'");
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ trait CustomMethods
|
||||
{
|
||||
// If the method cache was cleared by an an Object::add_extension() / Object::remove_extension()
|
||||
// call, then we should rebuild it.
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
if (!array_key_exists($class, self::$extra_methods)) {
|
||||
$this->defineMethods();
|
||||
}
|
||||
@ -151,12 +151,12 @@ trait CustomMethods
|
||||
/**
|
||||
* Get meta-data details on a named method
|
||||
*
|
||||
* @param array $method
|
||||
* @param string $method
|
||||
* @return array List of custom method details, if defined for this method
|
||||
*/
|
||||
protected function getExtraMethodConfig($method)
|
||||
{
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
if (isset(self::$extra_methods[$class][strtolower($method)])) {
|
||||
return self::$extra_methods[$class][strtolower($method)];
|
||||
}
|
||||
@ -171,7 +171,7 @@ trait CustomMethods
|
||||
*/
|
||||
public function allMethodNames($custom = false)
|
||||
{
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
if (!isset(self::$built_in_methods[$class])) {
|
||||
self::$built_in_methods[$class] = array_map('strtolower', get_class_methods($this));
|
||||
}
|
||||
@ -198,10 +198,11 @@ trait CustomMethods
|
||||
$extension->clearOwner();
|
||||
}
|
||||
} else {
|
||||
if (!isset(self::$built_in_methods[$extension->class])) {
|
||||
self::$built_in_methods[$extension->class] = array_map('strtolower', get_class_methods($extension));
|
||||
$class = get_class($extension);
|
||||
if (!isset(self::$built_in_methods[$class])) {
|
||||
self::$built_in_methods[$class] = array_map('strtolower', get_class_methods($extension));
|
||||
}
|
||||
$methods = self::$built_in_methods[$extension->class];
|
||||
$methods = self::$built_in_methods[$class];
|
||||
}
|
||||
|
||||
return $methods;
|
||||
@ -216,7 +217,7 @@ trait CustomMethods
|
||||
*/
|
||||
protected function addMethodsFrom($property, $index = null)
|
||||
{
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
$extension = ($index !== null) ? $this->{$property}[$index] : $this->$property;
|
||||
|
||||
if (!$extension) {
|
||||
@ -253,7 +254,7 @@ trait CustomMethods
|
||||
protected function removeMethodsFrom($property, $index = null)
|
||||
{
|
||||
$extension = ($index !== null) ? $this->{$property}[$index] : $this->$property;
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
|
||||
if (!$extension) {
|
||||
throw new InvalidArgumentException(
|
||||
@ -286,7 +287,7 @@ trait CustomMethods
|
||||
*/
|
||||
protected function addWrapperMethod($method, $wrap)
|
||||
{
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
self::$extra_methods[$class][strtolower($method)] = array (
|
||||
'wrap' => $wrap,
|
||||
'method' => $method
|
||||
|
@ -3,8 +3,10 @@
|
||||
namespace SilverStripe\Core;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Control\RequestHandler;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\View\ViewableData;
|
||||
|
||||
/**
|
||||
* Allows an object to have extensions applied to it.
|
||||
@ -46,9 +48,8 @@ trait Extensible
|
||||
* @var array
|
||||
*/
|
||||
private static $unextendable_classes = array(
|
||||
'SilverStripe\\Core\\Object',
|
||||
'SilverStripe\\View\\ViewableData',
|
||||
'SilverStripe\\Control\\RequestHandler'
|
||||
ViewableData::class,
|
||||
RequestHandler::class,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -110,7 +111,7 @@ trait Extensible
|
||||
|
||||
protected function constructExtensions()
|
||||
{
|
||||
$class = get_class($this);
|
||||
$class = static::class;
|
||||
|
||||
// Register this trait as a method source
|
||||
$this->registerExtraMethodCallback('defineExtensionMethods', function () {
|
||||
@ -126,9 +127,9 @@ trait Extensible
|
||||
|
||||
if ($extensions) {
|
||||
foreach ($extensions as $extension) {
|
||||
$instance = Object::create_from_string($extension);
|
||||
$instance = Injector::inst()->create($extension);
|
||||
$instance->setOwner(null, $class);
|
||||
$this->extension_instances[$instance->class] = $instance;
|
||||
$this->extension_instances[get_class($instance)] = $instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,7 +178,7 @@ trait Extensible
|
||||
*/
|
||||
public static function add_extension($classOrExtension, $extension = null)
|
||||
{
|
||||
if (func_num_args() > 1) {
|
||||
if ($extension) {
|
||||
$class = $classOrExtension;
|
||||
} else {
|
||||
$class = get_called_class();
|
||||
@ -285,14 +286,18 @@ trait Extensible
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $class If omitted, will get extensions for the current class
|
||||
* @param bool $includeArgumentString Include the argument string in the return array,
|
||||
* FALSE would return array("Versioned"), TRUE returns array("Versioned('Stage','Live')").
|
||||
* @return array Numeric array of either {@link DataExtension} class names,
|
||||
* or eval'ed class name strings with constructor arguments.
|
||||
*/
|
||||
public static function get_extensions($class, $includeArgumentString = false)
|
||||
public static function get_extensions($class = null, $includeArgumentString = false)
|
||||
{
|
||||
if (!$class) {
|
||||
$class = get_called_class();
|
||||
}
|
||||
|
||||
$extensions = Config::forClass($class)->get('extensions', Config::EXCLUDE_EXTRA_SOURCES);
|
||||
if (empty($extensions)) {
|
||||
return array();
|
||||
@ -315,9 +320,15 @@ trait Extensible
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get extra config sources for this class
|
||||
*
|
||||
* @param string $class Name of class. If left null will return for the current class
|
||||
* @return array|null
|
||||
*/
|
||||
public static function get_extra_config_sources($class = null)
|
||||
{
|
||||
if ($class === null) {
|
||||
if (!$class) {
|
||||
$class = get_called_class();
|
||||
}
|
||||
|
||||
@ -340,7 +351,7 @@ trait Extensible
|
||||
$sources = array();
|
||||
|
||||
foreach ($extensions as $extension) {
|
||||
list($extensionClass, $extensionArgs) = Object::parse_class_spec($extension);
|
||||
list($extensionClass, $extensionArgs) = ClassInfo::parse_class_spec($extension);
|
||||
$sources[] = $extensionClass;
|
||||
|
||||
if (!class_exists($extensionClass)) {
|
||||
@ -367,16 +378,16 @@ trait Extensible
|
||||
* Return TRUE if a class has a specified extension.
|
||||
* This supports backwards-compatible format (static Object::has_extension($requiredExtension))
|
||||
* and new format ($object->has_extension($class, $requiredExtension))
|
||||
* @param string $classOrExtension if 1 argument supplied, the class name of the extension to
|
||||
* check for; if 2 supplied, the class name to test
|
||||
* @param string $requiredExtension used only if 2 arguments supplied
|
||||
* @param string $classOrExtension Class to check extension for, or the extension name to check
|
||||
* if the second argument is null.
|
||||
* @param string $requiredExtension If the first argument is the parent class, this is the extension to check.
|
||||
* If left null, the first parameter will be treated as the extension.
|
||||
* @param boolean $strict if the extension has to match the required extension and not be a subclass
|
||||
* @return bool Flag if the extension exists
|
||||
*/
|
||||
public static function has_extension($classOrExtension, $requiredExtension = null, $strict = false)
|
||||
{
|
||||
//BC support
|
||||
if (func_num_args() > 1) {
|
||||
if ($requiredExtension) {
|
||||
$class = $classOrExtension;
|
||||
} else {
|
||||
$class = get_called_class();
|
||||
@ -500,6 +511,7 @@ trait Extensible
|
||||
if ($this->hasExtension($extension)) {
|
||||
return $this->extension_instances[$extension];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,6 @@ use SilverStripe\ORM\DataObject;
|
||||
*/
|
||||
abstract class Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* This is used by extensions designed to be applied to controllers.
|
||||
* It works the same way as {@link Controller::$allowed_actions}.
|
||||
@ -45,13 +44,6 @@ abstract class Extension
|
||||
*/
|
||||
private $ownerStack = [];
|
||||
|
||||
public $class;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->class = get_class($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this extension is added to a particular class
|
||||
*
|
||||
@ -67,7 +59,7 @@ abstract class Extension
|
||||
/**
|
||||
* Set the owner of this extension.
|
||||
*
|
||||
* @param Object $owner The owner object,
|
||||
* @param object $owner The owner object,
|
||||
* @param string $ownerBaseClass The base class that the extension is applied to; this may be
|
||||
* the class of owner, or it may be a parent. For example, if Versioned was applied to SiteTree,
|
||||
* and then a Page object was instantiated, $owner would be a Page object, but $ownerBaseClass
|
||||
|
@ -20,22 +20,13 @@ trait Injectable
|
||||
* $list = DataList::create('SiteTree');
|
||||
* $list = SiteTree::get();
|
||||
*
|
||||
* @param string $classOrArgument The first argument, or class name (if called directly
|
||||
* on Object).
|
||||
* @param mixed $argument,... arguments to pass to the constructor
|
||||
* @param array $args
|
||||
* @return static
|
||||
*/
|
||||
public static function create($classOrArgument = null, $argument = null)
|
||||
public static function create(...$args)
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
// Class to create should be the calling class if not Object,
|
||||
// otherwise the first parameter
|
||||
// Class to create should be the calling class
|
||||
$class = get_called_class();
|
||||
if ($class == 'SilverStripe\\Core\\Object') {
|
||||
$class = array_shift($args);
|
||||
}
|
||||
|
||||
return Injector::inst()->createWithArgs($class, $args);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace SilverStripe\Core\Injector;
|
||||
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use ReflectionProperty;
|
||||
use ArrayObject;
|
||||
@ -828,7 +829,7 @@ class Injector implements ContainerInterface
|
||||
*/
|
||||
public function getServiceName($name)
|
||||
{
|
||||
// common case, get it over with first
|
||||
// common case, get it overwith first
|
||||
if (isset($this->specs[$name])) {
|
||||
return $name;
|
||||
}
|
||||
@ -902,7 +903,7 @@ class Injector implements ContainerInterface
|
||||
* if this object is to be created from scratch (with $asSingleton = false)
|
||||
* @return mixed Instance of the specified object
|
||||
*/
|
||||
public function get($name, $asSingleton = true, $constructorArgs = null)
|
||||
public function get($name, $asSingleton = true, $constructorArgs = [])
|
||||
{
|
||||
$object = $this->getNamedService($name, $asSingleton, $constructorArgs);
|
||||
|
||||
@ -921,8 +922,11 @@ class Injector implements ContainerInterface
|
||||
* @param array $constructorArgs
|
||||
* @return mixed|null Instance of the specified object (if it exists)
|
||||
*/
|
||||
protected function getNamedService($name, $asSingleton = true, $constructorArgs = null)
|
||||
protected function getNamedService($name, $asSingleton = true, $constructorArgs = [])
|
||||
{
|
||||
// Normalise service / args
|
||||
list($name, $constructorArgs) = $this->normaliseArguments($name, $constructorArgs);
|
||||
|
||||
// reassign the name as it might actually be a compound name
|
||||
if ($serviceName = $this->getServiceName($name)) {
|
||||
// check to see what the type of bean is. If it's a prototype,
|
||||
@ -974,6 +978,28 @@ class Injector implements ContainerInterface
|
||||
return $this->instantiate($spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect service references with constructor arguments included.
|
||||
* These will be split out of the service name reference and appended
|
||||
* to the $args
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $args
|
||||
* @return array Two items with name and new args
|
||||
*/
|
||||
protected function normaliseArguments($name, $args = [])
|
||||
{
|
||||
if (strstr($name, '(')) {
|
||||
list($name, $extraArgs) = ClassInfo::parse_class_spec($name);
|
||||
if ($args) {
|
||||
$args = array_merge($args, $extraArgs);
|
||||
} else {
|
||||
$args = $extraArgs;
|
||||
}
|
||||
}
|
||||
return [ $name, $args ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to return an item directly
|
||||
*
|
||||
@ -999,7 +1025,7 @@ class Injector implements ContainerInterface
|
||||
{
|
||||
$constructorArgs = func_get_args();
|
||||
array_shift($constructorArgs);
|
||||
return $this->get($name, false, count($constructorArgs) ? $constructorArgs : null);
|
||||
return $this->createWithArgs($name, $constructorArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,324 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Core;
|
||||
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* A base class for all SilverStripe objects to inherit from.
|
||||
*
|
||||
* This class provides a number of pattern implementations, as well as methods and fixes to add extra psuedo-static
|
||||
* and method functionality to PHP.
|
||||
*
|
||||
* See {@link Extension} on how to implement a custom multiple
|
||||
* inheritance for object instances based on PHP5 method call overloading.
|
||||
*
|
||||
* @todo Create instance-specific removeExtension() which removes an extension from $extension_instances,
|
||||
* but not from static $extensions, and clears everything added through defineMethods(), mainly $extra_methods.
|
||||
*/
|
||||
abstract class Object
|
||||
{
|
||||
use Extensible;
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @var string the class name
|
||||
*/
|
||||
public $class;
|
||||
|
||||
private static $_cache_inst_args = array();
|
||||
|
||||
/**
|
||||
* Create an object from a string representation. It treats it as a PHP constructor without the
|
||||
* 'new' keyword. It also manages to construct the object without the use of eval().
|
||||
*
|
||||
* Construction itself is done with Object::create(), so that Object::useCustomClass() calls
|
||||
* are respected.
|
||||
*
|
||||
* `Object::create_from_string("Versioned('Stage','Live')")` will return the result of
|
||||
* `Versioned::create('Stage', 'Live);`
|
||||
*
|
||||
* It is designed for simple, cloneable objects. The first time this method is called for a given
|
||||
* string it is cached, and clones of that object are returned.
|
||||
*
|
||||
* If you pass the $firstArg argument, this will be prepended to the constructor arguments. It's
|
||||
* impossible to pass null as the firstArg argument.
|
||||
*
|
||||
* `Object::create_from_string("Varchar(50)", "MyField")` will return the result of
|
||||
* `Varchar::create('MyField', '50');`
|
||||
*
|
||||
* Arguments are always strings, although this is a quirk of the current implementation rather
|
||||
* than something that can be relied upon.
|
||||
*
|
||||
* @param string $classSpec
|
||||
* @param mixed $firstArg
|
||||
* @return object
|
||||
*/
|
||||
public static function create_from_string($classSpec, $firstArg = null)
|
||||
{
|
||||
if (!isset(self::$_cache_inst_args[$classSpec.$firstArg])) {
|
||||
// an $extension value can contain parameters as a string,
|
||||
// e.g. "Versioned('Stage','Live')"
|
||||
if (strpos($classSpec, '(') === false) {
|
||||
if ($firstArg === null) {
|
||||
self::$_cache_inst_args[$classSpec.$firstArg] = Object::create($classSpec);
|
||||
} else {
|
||||
self::$_cache_inst_args[$classSpec.$firstArg] = Object::create($classSpec, $firstArg);
|
||||
}
|
||||
} else {
|
||||
list($class, $args) = self::parse_class_spec($classSpec);
|
||||
|
||||
if ($firstArg !== null) {
|
||||
array_unshift($args, $firstArg);
|
||||
}
|
||||
array_unshift($args, $class);
|
||||
|
||||
self::$_cache_inst_args[$classSpec.$firstArg] = call_user_func_array(array('SilverStripe\\Core\\Object','create'), $args);
|
||||
}
|
||||
}
|
||||
|
||||
return clone self::$_cache_inst_args[$classSpec.$firstArg];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a class-spec, such as "Versioned('Stage','Live')", as passed to create_from_string().
|
||||
* Returns a 2-element array, with classname and arguments
|
||||
*
|
||||
* @param string $classSpec
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function parse_class_spec($classSpec)
|
||||
{
|
||||
$tokens = token_get_all("<?php $classSpec");
|
||||
$class = null;
|
||||
$args = array();
|
||||
|
||||
// Keep track of the current bucket that we're putting data into
|
||||
$bucket = &$args;
|
||||
$bucketStack = array();
|
||||
$hadNamespace = false;
|
||||
$currentKey = null;
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
// $forceResult used to allow null result to be detected
|
||||
$result = $forceResult = null;
|
||||
$tokenName = is_array($token) ? $token[0] : $token;
|
||||
|
||||
// Get the class name
|
||||
if ($class === null && is_array($token) && $token[0] === T_STRING) {
|
||||
$class = $token[1];
|
||||
} elseif (is_array($token) && $token[0] === T_NS_SEPARATOR) {
|
||||
$class .= $token[1];
|
||||
$hadNamespace = true;
|
||||
} elseif ($hadNamespace && is_array($token) && $token[0] === T_STRING) {
|
||||
$class .= $token[1];
|
||||
$hadNamespace = false;
|
||||
// Get arguments
|
||||
} elseif (is_array($token)) {
|
||||
switch ($token[0]) {
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
$argString = $token[1];
|
||||
switch ($argString[0]) {
|
||||
case '"':
|
||||
$result = stripcslashes(substr($argString, 1, -1));
|
||||
break;
|
||||
case "'":
|
||||
$result = str_replace(array("\\\\", "\\'"), array("\\", "'"), substr($argString, 1, -1));
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Bad T_CONSTANT_ENCAPSED_STRING arg $argString");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_DNUMBER:
|
||||
$result = (double)$token[1];
|
||||
break;
|
||||
|
||||
case T_LNUMBER:
|
||||
$result = (int)$token[1];
|
||||
break;
|
||||
|
||||
case T_DOUBLE_ARROW:
|
||||
// We've encountered an associative array (the array itself has already been
|
||||
// added to the bucket), so the previous item added to the bucket is the key
|
||||
end($bucket);
|
||||
$currentKey = current($bucket);
|
||||
array_pop($bucket);
|
||||
break;
|
||||
|
||||
case T_STRING:
|
||||
switch ($token[1]) {
|
||||
case 'true':
|
||||
$result = true;
|
||||
|
||||
break;
|
||||
case 'false':
|
||||
$result = false;
|
||||
|
||||
break;
|
||||
case 'null':
|
||||
$result = null;
|
||||
$forceResult = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Bad T_STRING arg '{$token[1]}'");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case T_ARRAY:
|
||||
$result = array();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ($tokenName === '[') {
|
||||
$result = array();
|
||||
} elseif (($tokenName === ')' || $tokenName === ']') && ! empty($bucketStack)) {
|
||||
// Store the bucket we're currently working on
|
||||
$oldBucket = $bucket;
|
||||
// Fetch the key for the bucket at the top of the stack
|
||||
end($bucketStack);
|
||||
$key = key($bucketStack);
|
||||
reset($bucketStack);
|
||||
// Re-instate the bucket from the top of the stack
|
||||
$bucket = &$bucketStack[$key];
|
||||
// Add our saved, "nested" bucket to the bucket we just popped off the stack
|
||||
$bucket[$key] = $oldBucket;
|
||||
// Remove the bucket we just popped off the stack
|
||||
array_pop($bucketStack);
|
||||
}
|
||||
}
|
||||
|
||||
// If we've got something to add to the bucket, add it
|
||||
if ($result !== null || $forceResult) {
|
||||
if ($currentKey) {
|
||||
$bucket[$currentKey] = $result;
|
||||
$currentKey = null;
|
||||
} else {
|
||||
$bucket[] = $result;
|
||||
}
|
||||
|
||||
// If we've just pushed an array, that becomes our new bucket
|
||||
if ($result === array()) {
|
||||
// Fetch the key that the array was pushed to
|
||||
end($bucket);
|
||||
$key = key($bucket);
|
||||
reset($bucket);
|
||||
// Store reference to "old" bucket in the stack
|
||||
$bucketStack[$key] = &$bucket;
|
||||
// Set the active bucket to be our newly-pushed, empty array
|
||||
$bucket = &$bucket[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array($class, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a static property of a class, even in that property is declared protected (but not private),
|
||||
* without any inheritance, merging or parent lookup if it doesn't exist on the given class.
|
||||
*
|
||||
* @param string $class The class to get the static from
|
||||
* @param string $name The property to get from the class
|
||||
* @param mixed $default The value to return if property doesn't exist on class
|
||||
* @return mixed The value of the static property $name on class $class,
|
||||
* or $default if that property is not defined
|
||||
*/
|
||||
public static function static_lookup($class, $name, $default = null)
|
||||
{
|
||||
if (is_subclass_of($class, 'SilverStripe\\Core\\Object')) {
|
||||
if (isset($class::$$name)) {
|
||||
$parent = get_parent_class($class);
|
||||
if (!$parent || !isset($parent::$$name) || $parent::$$name !== $class::$$name) {
|
||||
return $class::$$name;
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
} else {
|
||||
// TODO: This gets set once, then not updated, so any changes to statics after this is called the first
|
||||
// time for any class won't be exposed
|
||||
static $static_properties = array();
|
||||
|
||||
if (!isset($static_properties[$class])) {
|
||||
$reflection = new ReflectionClass($class);
|
||||
$static_properties[$class] = $reflection->getStaticProperties();
|
||||
}
|
||||
|
||||
if (isset($static_properties[$class][$name])) {
|
||||
$value = $static_properties[$class][$name];
|
||||
|
||||
$parent = get_parent_class($class);
|
||||
if (!$parent) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (!isset($static_properties[$parent])) {
|
||||
$reflection = new ReflectionClass($parent);
|
||||
$static_properties[$parent] = $reflection->getStaticProperties();
|
||||
}
|
||||
|
||||
if (!isset($static_properties[$parent][$name]) || $static_properties[$parent][$name] !== $value) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->class = get_class($this);
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return true if this object "exists" i.e. has a sensible value
|
||||
*
|
||||
* This method should be overriden in subclasses to provide more context about the classes state. For example, a
|
||||
* {@link DataObject} class could return false when it is deleted from the database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string this classes parent class
|
||||
*/
|
||||
public function parentClass()
|
||||
{
|
||||
return get_parent_class($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this class is an instance of a specific class, or has that class as one of its parents
|
||||
*
|
||||
* @param string $class
|
||||
* @return bool
|
||||
*/
|
||||
public function is_a($class)
|
||||
{
|
||||
return $this instanceof $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the class name
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
}
|
@ -3,7 +3,9 @@
|
||||
namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* Interface for a generic build task. Does not support dependencies. This will simply
|
||||
@ -12,8 +14,16 @@ use SilverStripe\Core\Object;
|
||||
* To disable the task (in the case of potentially destructive updates or deletes), declare
|
||||
* the $Disabled property on the subclass.
|
||||
*/
|
||||
abstract class BuildTask extends Object
|
||||
abstract class BuildTask
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
use Extensible;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom url segment (to follow dev/tasks/)
|
||||
@ -63,7 +73,7 @@ abstract class BuildTask extends Object
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return ($this->title) ? $this->title : $this->class;
|
||||
return $this->title ?: static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,7 +200,8 @@ abstract class BulkLoader extends ViewableData
|
||||
*/
|
||||
public function Title()
|
||||
{
|
||||
return ($title = $this->stat('title')) ? $title : $this->class;
|
||||
$title = $this->stat('title');
|
||||
return $title ?: static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\View\ArrayData;
|
||||
@ -15,8 +15,9 @@ use SilverStripe\View\ArrayData;
|
||||
*
|
||||
* @author Ingo Schommer, Silverstripe Ltd. (<firstname>@silverstripe.com)
|
||||
*/
|
||||
class BulkLoader_Result extends Object
|
||||
class BulkLoader_Result
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* Stores a map of ID and ClassNames
|
||||
@ -139,7 +140,7 @@ class BulkLoader_Result extends Object
|
||||
{
|
||||
$this->created[] = $this->lastChange = array(
|
||||
'ID' => $obj->ID,
|
||||
'ClassName' => $obj->class,
|
||||
'ClassName' => get_class($obj),
|
||||
'Message' => $message
|
||||
);
|
||||
$this->lastChange['ChangeType'] = 'created';
|
||||
@ -153,7 +154,7 @@ class BulkLoader_Result extends Object
|
||||
{
|
||||
$this->updated[] = $this->lastChange = array(
|
||||
'ID' => $obj->ID,
|
||||
'ClassName' => $obj->class,
|
||||
'ClassName' => get_class($obj),
|
||||
'Message' => $message
|
||||
);
|
||||
$this->lastChange['ChangeType'] = 'updated';
|
||||
|
@ -2,13 +2,11 @@
|
||||
|
||||
namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
/**
|
||||
* Class to facilitate command-line output.
|
||||
* Support less-trivial output stuff such as colours (on xterm-color)
|
||||
*/
|
||||
class CLI extends Object
|
||||
class CLI
|
||||
{
|
||||
/**
|
||||
* Returns true if the current STDOUT supports the use of colour control codes.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SimpleXMLElement;
|
||||
use tidy;
|
||||
use Exception;
|
||||
@ -22,8 +22,10 @@ use Exception;
|
||||
* Caution: Doesn't fully support HTML elements like <header>
|
||||
* due to them being declared illegal by the "tidy" preprocessing step.
|
||||
*/
|
||||
class CSSContentParser extends Object
|
||||
class CSSContentParser
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
protected $simpleXML = null;
|
||||
|
||||
public function __construct($content)
|
||||
@ -59,8 +61,6 @@ class CSSContentParser extends Object
|
||||
throw new Exception('CSSContentParser::__construct(): Could not parse content.'
|
||||
. ' Please check the PHP extension tidy is installed.');
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use Iterator;
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
@ -31,8 +31,9 @@ use SilverStripe\Control\Director;
|
||||
* }
|
||||
* </code>
|
||||
*/
|
||||
class CSVParser extends Object implements Iterator
|
||||
class CSVParser implements Iterator
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @var string $filename
|
||||
@ -117,8 +118,6 @@ class CSVParser extends Object implements Iterator
|
||||
$this->filename = $filename;
|
||||
$this->delimiter = $delimiter;
|
||||
$this->enclosure = $enclosure;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,7 +180,7 @@ class CsvBulkLoader extends BulkLoader
|
||||
*/
|
||||
protected function processChunk($filepath, $preview = false)
|
||||
{
|
||||
$results = new BulkLoader_Result();
|
||||
$results = BulkLoader_Result::create();
|
||||
|
||||
$csv = new CSVParser(
|
||||
$filepath,
|
||||
|
@ -5,15 +5,18 @@ namespace SilverStripe\Dev;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* A basic HTML wrapper for stylish rendering of a developement info view.
|
||||
* Used to output error messages, and test results.
|
||||
*/
|
||||
class DebugView extends Object
|
||||
class DebugView
|
||||
{
|
||||
use Configurable;
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* Column size to wrap long strings to
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Assets\File;
|
||||
use SilverStripe\ORM\DataModel;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
@ -85,8 +86,8 @@ class FixtureBlueprint
|
||||
// which they are imported doesnt guarantee valid relations until after the import is complete.
|
||||
// Also disable filesystem manipulations
|
||||
Config::nest();
|
||||
Config::inst()->update('SilverStripe\\ORM\\DataObject', 'validation_enabled', false);
|
||||
Config::inst()->update('SilverStripe\\Assets\\File', 'update_filesystem', false);
|
||||
Config::modify()->set(DataObject::class, 'validation_enabled', false);
|
||||
Config::modify()->set(File::class, 'update_filesystem', false);
|
||||
|
||||
$this->invokeCallbacks('beforeCreate', array($identifier, &$data, &$fixtures));
|
||||
|
||||
@ -132,10 +133,10 @@ class FixtureBlueprint
|
||||
if ($data) {
|
||||
foreach ($data as $fieldName => $fieldVal) {
|
||||
if ($schema->manyManyComponent($class, $fieldName)
|
||||
|| $schema->hasManyComponent($class, $fieldName)
|
||||
|| $schema->hasOneComponent($class, $fieldName)
|
||||
) {
|
||||
continue;
|
||||
|| $schema->hasManyComponent($class, $fieldName)
|
||||
|| $schema->hasOneComponent($class, $fieldName)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->setValue($obj, $fieldName, $fieldVal, $fixtures);
|
||||
|
@ -83,7 +83,7 @@ class FunctionalTest extends SapphireTest
|
||||
protected function setUp()
|
||||
{
|
||||
// Skip calling FunctionalTest directly.
|
||||
if (get_class($this) == __CLASS__) {
|
||||
if (static::class == __CLASS__) {
|
||||
$this->markTestSkipped(sprintf('Skipping %s ', get_class($this)));
|
||||
}
|
||||
|
||||
|
@ -111,13 +111,14 @@ class SapphireTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
protected $requireDefaultRecordsFrom = array();
|
||||
|
||||
|
||||
/**
|
||||
* A list of extensions that can't be applied during the execution of this run. If they are
|
||||
* applied, they will be temporarily removed and a database migration called.
|
||||
*
|
||||
* The keys of the are the classes that the extensions can't be applied the extensions to, and
|
||||
* the values are an array of illegal extensions on that class.
|
||||
*
|
||||
* Set a class to `*` to remove all extensions (unadvised)
|
||||
*/
|
||||
protected static $illegal_extensions = [];
|
||||
|
||||
@ -242,7 +243,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
// We cannot run the tests on this abstract class.
|
||||
if (get_class($this) == __CLASS__) {
|
||||
if (static::class == __CLASS__) {
|
||||
$this->markTestSkipped(sprintf('Skipping %s ', get_class($this)));
|
||||
return;
|
||||
}
|
||||
@ -357,6 +358,9 @@ class SapphireTest extends PHPUnit_Framework_TestCase
|
||||
if (!class_exists($class)) {
|
||||
continue;
|
||||
}
|
||||
if ($extensions === '*') {
|
||||
$extensions = $class::get_extensions();
|
||||
}
|
||||
foreach ($extensions as $extension) {
|
||||
if (!class_exists($extension) || !$class::has_extension($extension)) {
|
||||
continue;
|
||||
|
@ -4,7 +4,7 @@ namespace SilverStripe\Dev;
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
use InvalidArgumentException;
|
||||
|
||||
@ -68,8 +68,9 @@ use InvalidArgumentException;
|
||||
* ErrorCode: 404
|
||||
* </code>
|
||||
*/
|
||||
class YamlFixture extends Object
|
||||
class YamlFixture
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* Absolute path to the .yml fixture file
|
||||
@ -104,8 +105,6 @@ class YamlFixture extends Object
|
||||
|
||||
$this->fixtureFile = $fixture;
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,9 +246,14 @@ class CompositeField extends FormField
|
||||
if ($name) {
|
||||
$formName = (isset($this->form)) ? $this->form->FormName() : '(unknown form)';
|
||||
if (isset($list[$name])) {
|
||||
user_error("collateDataFields() I noticed that a field called '$name' appears twice in"
|
||||
. " your form: '{$formName}'. One is a '{$field->class}' and the other is a"
|
||||
. " '{$list[$name]->class}'", E_USER_ERROR);
|
||||
$fieldClass = get_class($field);
|
||||
$otherFieldClass = $list[$name]->class;
|
||||
user_error(
|
||||
"collateDataFields() I noticed that a field called '$name' appears twice in"
|
||||
. " your form: '{$formName}'. One is a '{$fieldClass}' and the other is a"
|
||||
. " '{$otherFieldClass}'",
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
$list[$name] = $field;
|
||||
}
|
||||
@ -509,7 +514,8 @@ class CompositeField extends FormField
|
||||
|
||||
public function debug()
|
||||
{
|
||||
$result = "$this->class ($this->name) <ul>";
|
||||
$class = static::class;
|
||||
$result = "$class ($this->name) <ul>";
|
||||
foreach ($this->children as $child) {
|
||||
$result .= "<li>" . Debug::text($child) . " </li>";
|
||||
}
|
||||
|
@ -347,8 +347,12 @@ class FieldList extends ArrayList
|
||||
$withName = $parentPointer instanceof FormField
|
||||
? " named '{$parentPointer->getName()}'"
|
||||
: null;
|
||||
user_error("FieldList::addFieldToTab() Tried to add a tab to object"
|
||||
. " '{$parentPointer->class}'{$withName} - '$part' didn't exist.", E_USER_ERROR);
|
||||
$parentPointerClass = get_class($parentPointer);
|
||||
user_error(
|
||||
"FieldList::addFieldToTab() Tried to add a tab to object"
|
||||
. " '{$parentPointerClass}'{$withName} - '{$part}' didn't exist.",
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,8 +383,9 @@ class FieldList extends ArrayList
|
||||
if ($child instanceof CompositeField) {
|
||||
return $child->fieldByName($remainder);
|
||||
} else {
|
||||
$childClass = get_class($child);
|
||||
user_error(
|
||||
"Trying to get field '$remainder' from non-composite field $child->class.$name",
|
||||
"Trying to get field '{$remainder}' from non-composite field {$childClass}.{$name}",
|
||||
E_USER_WARNING
|
||||
);
|
||||
return null;
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
namespace SilverStripe\Forms;
|
||||
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
use SilverStripe\Assets\File;
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
/**
|
||||
* Represents a file type which can be added to a form.
|
||||
@ -104,15 +104,15 @@ class FileField extends FormField implements FileHandleField
|
||||
$objectClass = DataObject::getSchema()->hasOneComponent(get_class($record), $this->name);
|
||||
if ($objectClass === File::class || empty($objectClass)) {
|
||||
// Create object of the appropriate file class
|
||||
$file = Object::create($fileClass);
|
||||
$file = Injector::inst()->create($fileClass);
|
||||
} else {
|
||||
// try to create a file matching the relation
|
||||
$file = Object::create($objectClass);
|
||||
$file = Injector::inst()->create($objectClass);
|
||||
}
|
||||
} elseif ($record instanceof File) {
|
||||
$file = $record;
|
||||
} else {
|
||||
$file = Object::create($fileClass);
|
||||
$file = Injector::inst()->create($fileClass);
|
||||
}
|
||||
|
||||
$this->upload->loadIntoFile($_FILES[$this->name], $file, $this->getFolderName());
|
||||
|
@ -6,7 +6,7 @@ use Exception;
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Assets\File;
|
||||
use SilverStripe\Assets\Storage\AssetContainer;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
@ -308,7 +308,7 @@ trait FileUploadReceiver
|
||||
);
|
||||
}
|
||||
// Create new object explicitly. Otherwise rely on Upload::load to choose the class.
|
||||
$fileObject = Object::create($relationClass);
|
||||
$fileObject = Injector::inst()->create($relationClass);
|
||||
if (! ($fileObject instanceof DataObject) || !($fileObject instanceof AssetContainer)) {
|
||||
throw new InvalidArgumentException("Invalid asset container $relationClass");
|
||||
}
|
||||
|
@ -942,7 +942,7 @@ class Form extends ViewableData implements HasRequestHandler
|
||||
*/
|
||||
public function getTemplates()
|
||||
{
|
||||
$templates = SSViewer::get_templates_by_class(get_class($this), '', __CLASS__);
|
||||
$templates = SSViewer::get_templates_by_class(static::class, '', __CLASS__);
|
||||
// Prefer any custom template
|
||||
if ($this->getTemplate()) {
|
||||
array_unshift($templates, $this->getTemplate());
|
||||
@ -1702,7 +1702,8 @@ class Form extends ViewableData implements HasRequestHandler
|
||||
|
||||
public function debug()
|
||||
{
|
||||
$result = "<h3>$this->class</h3><ul>";
|
||||
$class = static::class;
|
||||
$result = "<h3>$class</h3><ul>";
|
||||
foreach ($this->fields as $field) {
|
||||
$result .= "<li>$field" . $field->debug() . "</li>";
|
||||
}
|
||||
|
@ -1140,7 +1140,7 @@ class FormField extends RequestHandler
|
||||
*/
|
||||
protected function _templates($customTemplate = null, $customTemplateSuffix = null)
|
||||
{
|
||||
$templates = SSViewer::get_templates_by_class(get_class($this), $customTemplateSuffix, __CLASS__);
|
||||
$templates = SSViewer::get_templates_by_class(static::class, $customTemplateSuffix, __CLASS__);
|
||||
// Prefer any custom template
|
||||
if ($customTemplate) {
|
||||
// Prioritise direct template
|
||||
@ -1278,7 +1278,7 @@ class FormField extends RequestHandler
|
||||
*/
|
||||
public function performDisabledTransformation()
|
||||
{
|
||||
$disabledClassName = $this->class . '_Disabled';
|
||||
$disabledClassName = static::class . '_Disabled';
|
||||
|
||||
if (ClassInfo::exists($disabledClassName)) {
|
||||
$clone = $this->castedCopy($disabledClassName);
|
||||
@ -1310,7 +1310,7 @@ class FormField extends RequestHandler
|
||||
{
|
||||
$patten = '/' . strtolower($class) . '/i';
|
||||
|
||||
$subject = strtolower($this->class . ' ' . $this->extraClass());
|
||||
$subject = strtolower(static::class . ' ' . $this->extraClass());
|
||||
|
||||
return preg_match($patten, $subject);
|
||||
}
|
||||
@ -1377,7 +1377,7 @@ class FormField extends RequestHandler
|
||||
{
|
||||
return sprintf(
|
||||
'%s (%s: %s : <span style="color:red;">%s</span>) = %s',
|
||||
$this->class,
|
||||
static::class,
|
||||
$this->name,
|
||||
$this->title,
|
||||
$this->message,
|
||||
@ -1435,12 +1435,13 @@ class FormField extends RequestHandler
|
||||
*/
|
||||
public function rootFieldList()
|
||||
{
|
||||
if (is_object($this->containerFieldList)) {
|
||||
if ($this->containerFieldList) {
|
||||
return $this->containerFieldList->rootFieldList();
|
||||
}
|
||||
|
||||
$class = static::class;
|
||||
user_error(
|
||||
"rootFieldList() called on $this->class object without a containerFieldList",
|
||||
"rootFieldList() called on {$class} object without a containerFieldList",
|
||||
E_USER_ERROR
|
||||
);
|
||||
|
||||
|
@ -258,7 +258,7 @@ class FormRequestHandler extends RequestHandler
|
||||
if ($legacyActions) {
|
||||
throw new BadMethodCallException(
|
||||
"allowed_actions are not valid on Form class " . get_class($this->form) .
|
||||
". Implement these in subclasses of " . get_class($this) . " instead"
|
||||
". Implement these in subclasses of " . static::class . " instead"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace SilverStripe\Forms;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
@ -11,8 +12,9 @@ use SilverStripe\ORM\DataObject;
|
||||
* @uses DBField::scaffoldFormField()
|
||||
* @uses DataObject::fieldLabels()
|
||||
*/
|
||||
class FormScaffolder extends Object
|
||||
class FormScaffolder
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @var DataObject $obj The object defining the fields to be scaffolded
|
||||
@ -58,7 +60,6 @@ class FormScaffolder extends Object
|
||||
public function __construct($obj)
|
||||
{
|
||||
$this->obj = $obj;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,7 +152,7 @@ class FormScaffolder extends Object
|
||||
? $this->fieldClasses[$relationship]
|
||||
: 'SilverStripe\\Forms\\GridField\\GridField';
|
||||
/** @var GridField $grid */
|
||||
$grid = Object::create(
|
||||
$grid = Injector::inst()->create(
|
||||
$fieldClass,
|
||||
$relationship,
|
||||
$this->obj->fieldLabel($relationship),
|
||||
@ -181,7 +182,7 @@ class FormScaffolder extends Object
|
||||
: 'SilverStripe\\Forms\\GridField\\GridField';
|
||||
|
||||
/** @var GridField $grid */
|
||||
$grid = Object::create(
|
||||
$grid = Injector::inst()->create(
|
||||
$fieldClass,
|
||||
$relationship,
|
||||
$this->obj->fieldLabel($relationship),
|
||||
|
@ -2,9 +2,11 @@
|
||||
|
||||
namespace SilverStripe\Forms;
|
||||
|
||||
use BadMethodCallException;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\Debug;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* This class represents "transformations" of a form - such as making it printable or making it readonly.
|
||||
@ -18,8 +20,17 @@ use SilverStripe\Dev\Debug;
|
||||
*
|
||||
* To actually perform the transformation, call $form->transform(new MyTransformation());
|
||||
*/
|
||||
class FormTransformation extends Object
|
||||
class FormTransformation
|
||||
{
|
||||
use Configurable;
|
||||
use Injectable;
|
||||
use Extensible;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
public function transform(FormField $field)
|
||||
{
|
||||
// Look for a performXXTransformation() method on the field itself.
|
||||
@ -34,13 +45,13 @@ class FormTransformation extends Object
|
||||
function ($name) {
|
||||
return ClassInfo::shortName($name);
|
||||
},
|
||||
array_values(ClassInfo::ancestry($this->class))
|
||||
array_values(ClassInfo::ancestry($this))
|
||||
));
|
||||
$fieldClasses = array_reverse(array_map(
|
||||
function ($name) {
|
||||
return ClassInfo::shortName($name);
|
||||
},
|
||||
array_values(ClassInfo::ancestry($field->class))
|
||||
array_values(ClassInfo::ancestry($field))
|
||||
));
|
||||
|
||||
$len = max(sizeof($transNames), sizeof($fieldClasses));
|
||||
@ -64,6 +75,8 @@ class FormTransformation extends Object
|
||||
}
|
||||
}
|
||||
|
||||
throw new \BadMethodCallException("FormTransformation:: Can't perform '$this->class' on '$field->class'");
|
||||
$class = static::class;
|
||||
$fieldClass = get_class($field);
|
||||
throw new BadMethodCallException("FormTransformation:: Can't perform '{$class}' on '{$fieldClass}'");
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
namespace SilverStripe\Forms\GridField;
|
||||
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
/**
|
||||
* Encapsulates a collection of components following the
|
||||
@ -22,22 +24,21 @@ use SilverStripe\Core\Object;
|
||||
* - {@link GridFieldConfig_RecordEditor}
|
||||
* - {@link GridFieldConfig_RelationEditor}
|
||||
*/
|
||||
class GridFieldConfig extends Object
|
||||
class GridFieldConfig
|
||||
{
|
||||
use Injectable;
|
||||
use Extensible;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @var ArrayList
|
||||
*/
|
||||
protected $components = null;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->components = new ArrayList();
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,16 +3,17 @@
|
||||
namespace SilverStripe\Forms\GridField;
|
||||
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
use SilverStripe\Control\RequestHandler;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\ORM\DataModel;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\Validator;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use Closure;
|
||||
use SilverStripe\ORM\Filterable;
|
||||
|
||||
/**
|
||||
* Provides view and edit forms at GridField-specific URLs.
|
||||
@ -91,7 +92,7 @@ class GridFieldDetailForm implements GridField_URLHandler
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @param HTTPRequest $request
|
||||
* @return GridFieldDetailForm_ItemRequest
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
public function handleItem($gridField, $request)
|
||||
{
|
||||
@ -102,21 +103,18 @@ class GridFieldDetailForm implements GridField_URLHandler
|
||||
|
||||
/** @var DataObject $record */
|
||||
if (is_numeric($request->param('ID'))) {
|
||||
$record = $gridField->getList()->byID($request->param("ID"));
|
||||
/** @var Filterable $dataList */
|
||||
$dataList = $gridField->getList();
|
||||
$record = $dataList->byID($request->param("ID"));
|
||||
} else {
|
||||
$record = Object::create($gridField->getModelClass());
|
||||
$record = Injector::inst()->create($gridField->getModelClass());
|
||||
}
|
||||
|
||||
$handler = $this->getItemRequestHandler($gridField, $record, $requestHandler);
|
||||
|
||||
// if no validator has been set on the GridField and the record has a
|
||||
// CMS validator, use that.
|
||||
if (!$this->getValidator()
|
||||
&& (
|
||||
method_exists($record, 'getCMSValidator')
|
||||
|| $record instanceof Object && $record->hasMethod('getCMSValidator')
|
||||
)
|
||||
) {
|
||||
if (!$this->getValidator() && ClassInfo::hasMethod($record, 'getCMSValidator')) {
|
||||
$this->setValidator($record->getCMSValidator());
|
||||
}
|
||||
|
||||
@ -236,8 +234,8 @@ class GridFieldDetailForm implements GridField_URLHandler
|
||||
{
|
||||
if ($this->itemRequestClass) {
|
||||
return $this->itemRequestClass;
|
||||
} elseif (ClassInfo::exists(get_class($this) . "_ItemRequest")) {
|
||||
return get_class($this) . "_ItemRequest";
|
||||
} elseif (ClassInfo::exists(static::class . "_ItemRequest")) {
|
||||
return static::class . "_ItemRequest";
|
||||
} else {
|
||||
return __CLASS__ . '_ItemRequest';
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
} else {
|
||||
if ($this->throwExceptionOnBadDataType) {
|
||||
throw new LogicException(
|
||||
get_class($this) . " expects an SS_Filterable list to be passed to the GridField."
|
||||
static::class . " expects an SS_Filterable list to be passed to the GridField."
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
@ -2,10 +2,11 @@
|
||||
|
||||
namespace SilverStripe\Forms\GridField;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Forms\FormField;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\Hierarchy\Hierarchy;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\View\SSViewer;
|
||||
|
||||
@ -14,8 +15,9 @@ use SilverStripe\View\SSViewer;
|
||||
* hierarchical data. Requires the managed record to have a "getParent()"
|
||||
* method or has_one relationship called "Parent".
|
||||
*/
|
||||
class GridFieldLevelup extends Object implements GridField_HTMLProvider
|
||||
class GridFieldLevelup implements GridField_HTMLProvider
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @var integer - the record id of the level up to
|
||||
@ -40,12 +42,15 @@ class GridFieldLevelup extends Object implements GridField_HTMLProvider
|
||||
*/
|
||||
public function __construct($currentID)
|
||||
{
|
||||
parent::__construct();
|
||||
if ($currentID && is_numeric($currentID)) {
|
||||
$this->currentID = $currentID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GridField $gridField
|
||||
* @return array|null
|
||||
*/
|
||||
public function getHTMLFragments($gridField)
|
||||
{
|
||||
$modelClass = $gridField->getModelClass();
|
||||
@ -55,6 +60,7 @@ class GridFieldLevelup extends Object implements GridField_HTMLProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var DataObject|Hierarchy $modelObj */
|
||||
$modelObj = DataObject::get_by_id($modelClass, $this->currentID);
|
||||
|
||||
$parent = null;
|
||||
|
@ -51,7 +51,7 @@ class GridFieldPageCount implements GridField_HTMLProvider
|
||||
|
||||
if (!$paginator && GridFieldPageCount::config()->uninherited('require_paginator')) {
|
||||
throw new LogicException(
|
||||
get_class($this) . " relies on a GridFieldPaginator to be added " .
|
||||
static::class . " relies on a GridFieldPaginator to be added " .
|
||||
"to the same GridField, but none are present."
|
||||
);
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
||||
} else {
|
||||
if ($this->throwExceptionOnBadDataType) {
|
||||
throw new LogicException(
|
||||
get_class($this) . " expects an SS_Limitable list to be passed to the GridField."
|
||||
static::class . " expects an SS_Limitable list to be passed to the GridField."
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
@ -75,7 +75,7 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
||||
} else {
|
||||
if ($this->throwExceptionOnBadDataType) {
|
||||
throw new LogicException(
|
||||
get_class($this) . " expects an SS_Sortable list to be passed to the GridField."
|
||||
static::class . " expects an SS_Sortable list to be passed to the GridField."
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
@ -47,7 +47,7 @@ class HTMLEditorField_Toolbar extends RequestHandler
|
||||
*/
|
||||
public function getTemplateViewFile()
|
||||
{
|
||||
return SSViewer::get_templates_by_class(get_class($this), '_viewfile', __CLASS__);
|
||||
return SSViewer::get_templates_by_class(static::class, '_viewfile', __CLASS__);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,7 +185,7 @@ class HTMLEditorField_Toolbar extends RequestHandler
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds and returns the external link form
|
||||
*
|
||||
@ -200,7 +200,7 @@ class HTMLEditorField_Toolbar extends RequestHandler
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds and returns the external link form
|
||||
*
|
||||
@ -210,13 +210,13 @@ class HTMLEditorField_Toolbar extends RequestHandler
|
||||
{
|
||||
/** @var EditorEmailLinkFormFactory $factory */
|
||||
$factory = Injector::inst()->get(EditorEmailLinkFormFactory::class);
|
||||
|
||||
|
||||
if ($factory) {
|
||||
return $factory->getForm($this->controller, "{$this->name}/EditorEmailLink");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the folder ID to filter files by for the "from cms" tab
|
||||
*
|
||||
|
@ -170,7 +170,7 @@ class NullableField extends FormField
|
||||
{
|
||||
$result = sprintf(
|
||||
'%s (%s: $s : <span style="color: red">%s</span>) = ',
|
||||
$this->class,
|
||||
static::class,
|
||||
$this->name,
|
||||
$this->title,
|
||||
$this->message
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace SilverStripe\Forms;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\ORM\ValidationResult;
|
||||
|
||||
/**
|
||||
@ -10,13 +12,16 @@ use SilverStripe\ORM\ValidationResult;
|
||||
* fields. It relies on javascript for client-side validation, and marking fields after server-side
|
||||
* validation. It acts as a visitor to individual form fields.
|
||||
*/
|
||||
abstract class Validator extends Object
|
||||
abstract class Validator
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
use Extensible;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->resetResult();
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,7 +118,7 @@ class ArrayList extends ViewableData implements SS_List, Filterable, Sortable, L
|
||||
|
||||
public function debug()
|
||||
{
|
||||
$val = "<h2>" . $this->class . "</h2><ul>";
|
||||
$val = "<h2>" . static::class . "</h2><ul>";
|
||||
foreach ($this->toNestedArray() as $item) {
|
||||
$val .= "<li style=\"list-style-type: disc; margin-left: 20px\">" . Debug::text($item) . "</li>";
|
||||
}
|
||||
|
@ -73,8 +73,8 @@ abstract class DBConnector
|
||||
public function isQueryMutable($sql)
|
||||
{
|
||||
$operations = array_merge(
|
||||
Config::inst()->get(get_class($this), 'write_operations'),
|
||||
Config::inst()->get(get_class($this), 'ddl_operations')
|
||||
Config::inst()->get(static::class, 'write_operations'),
|
||||
Config::inst()->get(static::class, 'ddl_operations')
|
||||
);
|
||||
return $this->isQueryType($sql, $operations);
|
||||
}
|
||||
@ -87,7 +87,7 @@ abstract class DBConnector
|
||||
*/
|
||||
public function isQueryDDL($sql)
|
||||
{
|
||||
$operations = Config::inst()->get(get_class($this), 'ddl_operations');
|
||||
$operations = Config::inst()->get(static::class, 'ddl_operations');
|
||||
return $this->isQueryType($sql, $operations);
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ abstract class DBConnector
|
||||
*/
|
||||
public function isQueryWrite($sql)
|
||||
{
|
||||
$operations = Config::inst()->get(get_class($this), 'write_operations');
|
||||
$operations = Config::inst()->get(static::class, 'write_operations');
|
||||
return $this->isQueryType($sql, $operations);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ namespace SilverStripe\ORM\Connect;
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\FieldType\DBPrimaryKey;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use Exception;
|
||||
@ -389,7 +389,7 @@ abstract class DBSchemaManager
|
||||
}
|
||||
|
||||
/** @var DBField $fieldObj */
|
||||
$fieldObj = Object::create_from_string($fieldSpec, $fieldName);
|
||||
$fieldObj = Injector::inst()->create($fieldSpec, $fieldName);
|
||||
$fieldObj->setArrayValue($arrayValue);
|
||||
|
||||
$fieldObj->setTable($table);
|
||||
|
@ -777,7 +777,7 @@ abstract class Database
|
||||
public function selectDatabase($name, $create = false, $errorLevel = E_USER_ERROR)
|
||||
{
|
||||
// In case our live environment is locked down, we can bypass a SHOW DATABASE check
|
||||
$canConnect = Config::inst()->get(get_class($this), 'optimistic_connect')
|
||||
$canConnect = Config::inst()->get(static::class, 'optimistic_connect')
|
||||
|| $this->schemaManager->databaseExists($name);
|
||||
if ($canConnect) {
|
||||
return $this->connector->selectDatabase($name);
|
||||
|
@ -165,7 +165,7 @@ abstract class DataExtension extends Extension
|
||||
*/
|
||||
public function updateSummaryFields(&$fields)
|
||||
{
|
||||
$summary_fields = Config::inst()->get($this->class, 'summary_fields');
|
||||
$summary_fields = Config::inst()->get(static::class, 'summary_fields');
|
||||
if ($summary_fields) {
|
||||
// if summary_fields were passed in numeric array,
|
||||
// convert to an associative array
|
||||
@ -188,7 +188,7 @@ abstract class DataExtension extends Extension
|
||||
*/
|
||||
public function updateFieldLabels(&$labels)
|
||||
{
|
||||
$field_labels = Config::inst()->get($this->class, 'field_labels');
|
||||
$field_labels = Config::inst()->get(static::class, 'field_labels');
|
||||
if ($field_labels) {
|
||||
$labels = array_merge($labels, $field_labels);
|
||||
}
|
||||
|
@ -750,8 +750,7 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li
|
||||
|
||||
public function debug()
|
||||
{
|
||||
$val = "<h2>" . $this->class . "</h2><ul>";
|
||||
|
||||
$val = "<h2>" . static::class . "</h2><ul>";
|
||||
foreach ($this->toNestedArray() as $item) {
|
||||
$val .= "<li style=\"list-style-type: disc; margin-left: 20px\">" . Debug::text($item) . "</li>";
|
||||
}
|
||||
@ -1072,7 +1071,7 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li
|
||||
/**
|
||||
* Remove every element in this DataList matching the given $filter.
|
||||
*
|
||||
* @param string $filter - a sql type where filter
|
||||
* @param string|array $filter - a sql type where filter
|
||||
* @return $this
|
||||
*/
|
||||
public function removeByFilter($filter)
|
||||
|
@ -4,7 +4,6 @@ namespace SilverStripe\ORM;
|
||||
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Resettable;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
@ -30,6 +29,7 @@ use LogicException;
|
||||
use InvalidArgumentException;
|
||||
use BadMethodCallException;
|
||||
use Exception;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* A single database record & abstract class for the data-access-model.
|
||||
@ -306,7 +306,11 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_array($record) && !is_a($record, "stdClass")) {
|
||||
if ($record instanceof stdClass) {
|
||||
$record = (array)$record;
|
||||
}
|
||||
|
||||
if (!is_array($record)) {
|
||||
if (is_object($record)) {
|
||||
$passed = "an object of type '".get_class($record)."'";
|
||||
} else {
|
||||
@ -321,10 +325,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$record = null;
|
||||
}
|
||||
|
||||
if (is_a($record, "stdClass")) {
|
||||
$record = (array)$record;
|
||||
}
|
||||
|
||||
// Set $this->record to $record, but ignore NULLs
|
||||
$this->record = array();
|
||||
foreach ($record as $k => $v) {
|
||||
@ -517,7 +517,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->class = $className;
|
||||
$this->setField("ClassName", $className);
|
||||
$this->setField('RecordClassName', $className);
|
||||
return $this;
|
||||
@ -568,20 +567,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
{
|
||||
parent::defineMethods();
|
||||
|
||||
// Define the extra db fields - this is only necessary for extensions added in the
|
||||
// class definition. Object::add_extension() will call this at definition time for
|
||||
// those objects, which is a better mechanism. Perhaps extensions defined inside the
|
||||
// class def can somehow be applied at definiton time also?
|
||||
if ($this->extension_instances) {
|
||||
foreach ($this->extension_instances as $i => $instance) {
|
||||
if (!$instance->class) {
|
||||
$class = get_class($instance);
|
||||
user_error("DataObject::defineMethods(): Please ensure {$class}::__construct() calls"
|
||||
. " parent::__construct()", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (static::class === self::class) {
|
||||
return;
|
||||
}
|
||||
@ -815,11 +800,12 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
*/
|
||||
public function update($data)
|
||||
{
|
||||
foreach ($data as $k => $v) {
|
||||
foreach ($data as $key => $value) {
|
||||
// Implement dot syntax for updates
|
||||
if (strpos($k, '.') !== false) {
|
||||
$relations = explode('.', $k);
|
||||
if (strpos($key, '.') !== false) {
|
||||
$relations = explode('.', $key);
|
||||
$fieldName = array_pop($relations);
|
||||
/** @var static $relObj */
|
||||
$relObj = $this;
|
||||
$relation = null;
|
||||
foreach ($relations as $i => $relation) {
|
||||
@ -829,7 +815,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$parentObj = $relObj;
|
||||
$relObj = $relObj->$relation();
|
||||
// If the intermediate relationship objects have been created, then write them
|
||||
if ($i<sizeof($relation)-1 && !$relObj->ID || (!$relObj->ID && $parentObj != $this)) {
|
||||
if ($i<sizeof($relation)-1 && !$relObj->ID || (!$relObj->ID && $parentObj !== $this)) {
|
||||
$relObj->write();
|
||||
$relatedFieldName = $relation."ID";
|
||||
$parentObj->$relatedFieldName = $relObj->ID;
|
||||
@ -848,16 +834,17 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
}
|
||||
|
||||
if ($relObj) {
|
||||
$relObj->$fieldName = $v;
|
||||
$relObj->$fieldName = $value;
|
||||
$relObj->write();
|
||||
$relatedFieldName = $relation."ID";
|
||||
$this->$relatedFieldName = $relObj->ID;
|
||||
$relObj->flushCache();
|
||||
} else {
|
||||
user_error("Couldn't follow dot syntax '$k' on '$this->class' object", E_USER_WARNING);
|
||||
$class = static::class;
|
||||
user_error("Couldn't follow dot syntax '{$key}' on '{$class}' object", E_USER_WARNING);
|
||||
}
|
||||
} else {
|
||||
$this->$k = $v;
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
@ -949,6 +936,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
if ($includeRelations) {
|
||||
if ($manyMany = $this->manyMany()) {
|
||||
foreach ($manyMany as $relationship => $class) {
|
||||
/** @var DataObject $leftComponents */
|
||||
$leftComponents = $leftObj->getManyManyComponents($relationship);
|
||||
$rightComponents = $rightObj->getManyManyComponents($relationship);
|
||||
if ($rightComponents && $rightComponents->exists()) {
|
||||
@ -1110,7 +1098,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
|
||||
if ($defaults && !is_array($defaults)) {
|
||||
user_error(
|
||||
"Bad '$this->class' defaults given: " . var_export($defaults, true),
|
||||
"Bad '" . static::class . "' defaults given: " . var_export($defaults, true),
|
||||
E_USER_WARNING
|
||||
);
|
||||
$defaults = null;
|
||||
@ -1181,7 +1169,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$this->brokenOnWrite = true;
|
||||
$this->onBeforeWrite();
|
||||
if ($this->brokenOnWrite) {
|
||||
user_error("$this->class has a broken onBeforeWrite() function."
|
||||
user_error(static::class . " has a broken onBeforeWrite() function."
|
||||
. " Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
@ -1251,7 +1239,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
= empty($this->record['Created'])
|
||||
? $now
|
||||
: $this->record['Created'];
|
||||
$manipulation[$table]['fields']['ClassName'] = $this->class;
|
||||
$manipulation[$table]['fields']['ClassName'] = static::class;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1434,7 +1422,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$this->brokenOnDelete = true;
|
||||
$this->onBeforeDelete();
|
||||
if ($this->brokenOnDelete) {
|
||||
user_error("$this->class has a broken onBeforeDelete() function."
|
||||
user_error(static::class . " has a broken onBeforeDelete() function."
|
||||
. " Make sure that you call parent::onBeforeDelete().", E_USER_ERROR);
|
||||
}
|
||||
|
||||
@ -1447,7 +1435,10 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
// - move the details of the delete code in the DataQuery system
|
||||
// - update the code to just delete the base table, and rely on cascading deletes in the DB to do the rest
|
||||
// obviously, that means getting requireTable() to configure cascading deletes ;-)
|
||||
$srcQuery = DataList::create($this->class, $this->model)->where("ID = $this->ID")->dataQuery()->query();
|
||||
$srcQuery = DataList::create(static::class, $this->model)
|
||||
->filter('ID', $this->ID)
|
||||
->dataQuery()
|
||||
->query();
|
||||
foreach ($srcQuery->queriedTables() as $table) {
|
||||
$delete = new SQLDelete("\"$table\"", array('"ID"' => $this->ID));
|
||||
$delete->execute();
|
||||
@ -1538,7 +1529,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
if ($polymorphic) {
|
||||
$filter = array(
|
||||
"{$joinField}ID" => $joinID,
|
||||
"{$joinField}Class" => $this->class
|
||||
"{$joinField}Class" => static::class,
|
||||
);
|
||||
} else {
|
||||
$filter = array(
|
||||
@ -1557,7 +1548,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$component = $this->model->$class->newObject();
|
||||
if ($polymorphic) {
|
||||
$component->{$joinField.'ID'} = $this->ID;
|
||||
$component->{$joinField.'Class'} = $this->class;
|
||||
$component->{$joinField.'Class'} = static::class;
|
||||
} else {
|
||||
$component->$joinField = $this->ID;
|
||||
}
|
||||
@ -1588,7 +1579,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
"DataObject::getComponents(): Unknown 1-to-many component '%s' on class '%s'",
|
||||
$componentName,
|
||||
$this->class
|
||||
static::class
|
||||
));
|
||||
}
|
||||
|
||||
@ -1596,7 +1587,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
if (!$this->ID) {
|
||||
if (!isset($this->unsavedRelations[$componentName])) {
|
||||
$this->unsavedRelations[$componentName] =
|
||||
new UnsavedRelationList($this->class, $componentName, $componentClass);
|
||||
new UnsavedRelationList(static::class, $componentName, $componentClass);
|
||||
}
|
||||
return $this->unsavedRelations[$componentName];
|
||||
}
|
||||
@ -1605,7 +1596,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$joinField = $schema->getRemoteJoinField(static::class, $componentName, 'has_many', $polymorphic);
|
||||
/** @var HasManyList $result */
|
||||
if ($polymorphic) {
|
||||
$result = PolymorphicHasManyList::create($componentClass, $joinField, $this->class);
|
||||
$result = PolymorphicHasManyList::create($componentClass, $joinField, get_class($this));
|
||||
} else {
|
||||
$result = HasManyList::create($componentClass, $joinField);
|
||||
}
|
||||
@ -1630,11 +1621,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
// Parse many_many
|
||||
$manyManyComponent = $this->getSchema()->manyManyComponent(static::class, $relationName);
|
||||
if ($manyManyComponent) {
|
||||
list(
|
||||
$relationClass, $parentClass, $componentClass,
|
||||
$parentField, $childField, $tableOrClass
|
||||
) = $manyManyComponent;
|
||||
return $componentClass;
|
||||
return $manyManyComponent['childClass'];
|
||||
}
|
||||
|
||||
// Go through all relationship configuration fields.
|
||||
@ -1772,18 +1759,17 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
case 'many_many':
|
||||
case 'belongs_many_many': {
|
||||
// Get components and extra fields from parent
|
||||
list($relationClass, $componentClass, $parentClass, $componentField, $parentField, $table)
|
||||
= $remote->getSchema()->manyManyComponent($remoteClass, $remoteRelation);
|
||||
$manyMany = $remote->getSchema()->manyManyComponent($remoteClass, $remoteRelation);
|
||||
$extraFields = $schema->manyManyExtraFieldsForComponent($remoteClass, $remoteRelation) ?: array();
|
||||
|
||||
// Reverse parent and component fields and create an inverse ManyManyList
|
||||
/** @var RelationList $result */
|
||||
$result = Injector::inst()->create(
|
||||
$relationClass,
|
||||
$componentClass,
|
||||
$table,
|
||||
$componentField,
|
||||
$parentField,
|
||||
$manyMany['relationClass'],
|
||||
$manyMany['parentClass'], // Substitute parent class for dataClass
|
||||
$manyMany['join'],
|
||||
$manyMany['parentField'], // Reversed parent / child field
|
||||
$manyMany['childField'], // Reversed parent / child field
|
||||
$extraFields
|
||||
);
|
||||
if ($this->model) {
|
||||
@ -1816,18 +1802,15 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
"DataObject::getComponents(): Unknown many-to-many component '%s' on class '%s'",
|
||||
$componentName,
|
||||
$this->class
|
||||
static::class
|
||||
));
|
||||
}
|
||||
|
||||
list($relationClass, $parentClass, $componentClass, $parentField, $componentField, $tableOrClass)
|
||||
= $manyManyComponent;
|
||||
|
||||
// If we haven't been written yet, we can't save these relations, so use a list that handles this case
|
||||
if (!$this->ID) {
|
||||
if (!isset($this->unsavedRelations[$componentName])) {
|
||||
$this->unsavedRelations[$componentName] =
|
||||
new UnsavedRelationList($parentClass, $componentName, $componentClass);
|
||||
new UnsavedRelationList($manyManyComponent['parentClass'], $componentName, $manyManyComponent['childClass']);
|
||||
}
|
||||
return $this->unsavedRelations[$componentName];
|
||||
}
|
||||
@ -1835,11 +1818,11 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$extraFields = $schema->manyManyExtraFieldsForComponent(static::class, $componentName) ?: array();
|
||||
/** @var RelationList $result */
|
||||
$result = Injector::inst()->create(
|
||||
$relationClass,
|
||||
$componentClass,
|
||||
$tableOrClass,
|
||||
$componentField,
|
||||
$parentField,
|
||||
$manyManyComponent['relationClass'],
|
||||
$manyManyComponent['childClass'],
|
||||
$manyManyComponent['join'],
|
||||
$manyManyComponent['childField'],
|
||||
$manyManyComponent['parentField'],
|
||||
$extraFields
|
||||
);
|
||||
|
||||
@ -1968,7 +1951,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
public function getDefaultSearchContext()
|
||||
{
|
||||
return new SearchContext(
|
||||
$this->class,
|
||||
static::class,
|
||||
$this->scaffoldSearchFields(),
|
||||
$this->defaultSearchFilters()
|
||||
);
|
||||
@ -2069,7 +2052,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
(array)$_params
|
||||
);
|
||||
|
||||
$fs = new FormScaffolder($this);
|
||||
$fs = FormScaffolder::create($this);
|
||||
$fs->tabbed = $params['tabbed'];
|
||||
$fs->includeRelations = $params['includeRelations'];
|
||||
$fs->restrictFields = $params['restrictFields'];
|
||||
@ -2634,7 +2617,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
*/
|
||||
public function debug()
|
||||
{
|
||||
$val = "<h3>Database record: $this->class</h3>\n<ul>\n";
|
||||
$class = static::class;
|
||||
$val = "<h3>Database record: {$class}</h3>\n<ul>\n";
|
||||
if ($this->record) {
|
||||
foreach ($this->record as $fieldName => $fieldVal) {
|
||||
$val .= "\t<li>$fieldName: " . Debug::text($fieldVal) . "</li>\n";
|
||||
@ -2680,7 +2664,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
list($class, $spec) = explode('.', $helper);
|
||||
/** @var DBField $obj */
|
||||
$table = $schema->tableName($class);
|
||||
$obj = Object::create_from_string($spec, $fieldName);
|
||||
$obj = Injector::inst()->create($spec, $fieldName);
|
||||
$obj->setTable($table);
|
||||
$obj->setValue($value, $this, false);
|
||||
return $obj;
|
||||
@ -2712,6 +2696,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
if (method_exists($component, $relation)) {
|
||||
$component = $component->$relation();
|
||||
} else {
|
||||
/** @var DataList $component */
|
||||
$component = $component->relation($relation);
|
||||
}
|
||||
} else {
|
||||
@ -2749,6 +2734,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$component = $component->$relation();
|
||||
} elseif ($component instanceof SS_List) {
|
||||
// Select adjacent relation from DataList
|
||||
/** @var DataList $component */
|
||||
$component = $component->relation($relation);
|
||||
} elseif ($component instanceof DataObject
|
||||
&& ($dbObject = $component->dbObject($relation))
|
||||
@ -2914,12 +2900,12 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
*/
|
||||
public function flushCache($persistent = true)
|
||||
{
|
||||
if ($this->class == self::class) {
|
||||
if (static::class == self::class) {
|
||||
self::$_cache_get_one = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
$classes = ClassInfo::ancestry($this->class);
|
||||
$classes = ClassInfo::ancestry(static::class);
|
||||
foreach ($classes as $class) {
|
||||
if (isset(self::$_cache_get_one[$class])) {
|
||||
unset(self::$_cache_get_one[$class]);
|
||||
@ -3139,10 +3125,9 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
foreach ($manyMany as $component => $spec) {
|
||||
// Get many_many spec
|
||||
$manyManyComponent = $schema->manyManyComponent(static::class, $component);
|
||||
list(
|
||||
$relationClass, $parentClass, $componentClass,
|
||||
$parentField, $childField, $tableOrClass
|
||||
) = $manyManyComponent;
|
||||
$parentField = $manyManyComponent['parentField'];
|
||||
$childField = $manyManyComponent['childField'];
|
||||
$tableOrClass = $manyManyComponent['join'];
|
||||
|
||||
// Skip if backed by actual class
|
||||
if (class_exists($tableOrClass)) {
|
||||
@ -3184,9 +3169,9 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
$defaultRecords = $this->config()->uninherited('default_records');
|
||||
|
||||
if (!empty($defaultRecords)) {
|
||||
$hasData = DataObject::get_one($this->class);
|
||||
$hasData = DataObject::get_one(static::class);
|
||||
if (!$hasData) {
|
||||
$className = $this->class;
|
||||
$className = static::class;
|
||||
foreach ($defaultRecords as $record) {
|
||||
$obj = $this->model->$className->newObject($record);
|
||||
$obj->write();
|
||||
@ -3308,14 +3293,14 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
||||
*/
|
||||
public function fieldLabels($includerelations = true)
|
||||
{
|
||||
$cacheKey = $this->class . '_' . $includerelations;
|
||||
$cacheKey = static::class . '_' . $includerelations;
|
||||
|
||||
if (!isset(self::$_cache_field_labels[$cacheKey])) {
|
||||
$customLabels = $this->stat('field_labels');
|
||||
$autoLabels = array();
|
||||
|
||||
// get all translated static properties as defined in i18nCollectStatics()
|
||||
$ancestry = ClassInfo::ancestry($this->class);
|
||||
$ancestry = ClassInfo::ancestry(static::class);
|
||||
$ancestry = array_reverse($ancestry);
|
||||
if ($ancestry) {
|
||||
foreach ($ancestry as $ancestorClass) {
|
||||
|
@ -5,10 +5,10 @@ namespace SilverStripe\ORM;
|
||||
use Exception;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\FieldType\DBComposite;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Object;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
|
||||
@ -438,7 +438,7 @@ class DataObjectSchema
|
||||
|
||||
// Merge composite fields into DB
|
||||
foreach ($compositeFields as $fieldName => $fieldSpec) {
|
||||
$fieldObj = Object::create_from_string($fieldSpec, $fieldName);
|
||||
$fieldObj = Injector::inst()->create($fieldSpec, $fieldName);
|
||||
$fieldObj->setTable($class);
|
||||
$nestedFields = $fieldObj->compositeDatabaseFields();
|
||||
foreach ($nestedFields as $nestedName => $nestedSpec) {
|
||||
@ -498,7 +498,7 @@ class DataObjectSchema
|
||||
}
|
||||
|
||||
// Find regular field
|
||||
while ($candidateClass) {
|
||||
while ($candidateClass && $candidateClass !== DataObject::class) {
|
||||
$fields = $this->databaseFields($candidateClass, false);
|
||||
if (isset($fields[$fieldName])) {
|
||||
return $candidateClass;
|
||||
@ -533,9 +533,9 @@ class DataObjectSchema
|
||||
$classes = ClassInfo::ancestry($class);
|
||||
foreach ($classes as $parentClass) {
|
||||
// Check if the component is defined in many_many on this class
|
||||
$manyMany = Config::inst()->get($parentClass, 'many_many', Config::UNINHERITED);
|
||||
if (isset($manyMany[$component])) {
|
||||
return $this->parseManyManyComponent($parentClass, $component, $manyMany[$component]);
|
||||
$otherManyMany = Config::inst()->get($parentClass, 'many_many', Config::UNINHERITED);
|
||||
if (isset($otherManyMany[$component])) {
|
||||
return $this->parseManyManyComponent($parentClass, $component, $otherManyMany[$component]);
|
||||
}
|
||||
|
||||
// Check if the component is defined in belongs_many_many on this class
|
||||
@ -545,13 +545,22 @@ class DataObjectSchema
|
||||
}
|
||||
|
||||
// Extract class and relation name from dot-notation
|
||||
list($childClass, $relationName)
|
||||
= $this->parseBelongsManyManyComponent($parentClass, $component, $belongsManyMany[$component]);
|
||||
$belongs = $this->parseBelongsManyManyComponent(
|
||||
$parentClass,
|
||||
$component,
|
||||
$belongsManyMany[$component]
|
||||
);
|
||||
|
||||
// Build inverse relationship from other many_many, and swap parent/child
|
||||
list($relationClass, $childClass, $parentClass, $childField, $parentField, $joinTable)
|
||||
= $this->manyManyComponent($childClass, $relationName);
|
||||
return [$relationClass, $parentClass, $childClass, $parentField, $childField, $joinTable];
|
||||
$otherManyMany = $this->manyManyComponent($belongs['childClass'], $belongs['relationName']);
|
||||
return [
|
||||
'relationClass' => $otherManyMany['relationClass'],
|
||||
'parentClass' => $otherManyMany['childClass'],
|
||||
'childClass' => $otherManyMany['parentClass'],
|
||||
'parentField' => $otherManyMany['childField'],
|
||||
'childField' => $otherManyMany['parentField'],
|
||||
'join' => $otherManyMany['join'],
|
||||
];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -596,7 +605,10 @@ class DataObjectSchema
|
||||
}
|
||||
|
||||
// Return relatios
|
||||
return array($childClass, $relationName);
|
||||
return [
|
||||
'childClass' => $childClass,
|
||||
'relationName' => $relationName
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -619,12 +631,12 @@ class DataObjectSchema
|
||||
$belongsManyMany = Config::inst()->get($class, 'belongs_many_many', Config::UNINHERITED);
|
||||
if (isset($belongsManyMany[$component])) {
|
||||
// Reverse relationship and find extrafields from child class
|
||||
list($childClass, $relationName) = $this->parseBelongsManyManyComponent(
|
||||
$belongs = $this->parseBelongsManyManyComponent(
|
||||
$class,
|
||||
$component,
|
||||
$belongsManyMany[$component]
|
||||
);
|
||||
return $this->manyManyExtraFieldsForComponent($childClass, $relationName);
|
||||
return $this->manyManyExtraFieldsForComponent($belongs['childClass'], $belongs['relationName']);
|
||||
}
|
||||
$class = get_parent_class($class);
|
||||
}
|
||||
@ -717,12 +729,12 @@ class DataObjectSchema
|
||||
$parentClass = $this->checkManyManyFieldClass($parentClass, $component, $joinClass, $specification, 'from');
|
||||
$joinChildClass = $this->checkManyManyFieldClass($parentClass, $component, $joinClass, $specification, 'to');
|
||||
return [
|
||||
ManyManyThroughList::class,
|
||||
$parentClass,
|
||||
$joinChildClass,
|
||||
$specification['from'] . 'ID',
|
||||
$specification['to'] . 'ID',
|
||||
$joinClass,
|
||||
'relationClass' => ManyManyThroughList::class,
|
||||
'parentClass' => $parentClass,
|
||||
'childClass' => $joinChildClass,
|
||||
'parentField' => $specification['from'] . 'ID',
|
||||
'childField' => $specification['to'] . 'ID',
|
||||
'join' => $joinClass,
|
||||
];
|
||||
}
|
||||
|
||||
@ -740,12 +752,12 @@ class DataObjectSchema
|
||||
}
|
||||
$joinTable = "{$classTable}_{$component}";
|
||||
return [
|
||||
ManyManyList::class,
|
||||
$parentClass,
|
||||
$specification,
|
||||
$parentField,
|
||||
$childField,
|
||||
$joinTable,
|
||||
'relationClass' => ManyManyList::class,
|
||||
'parentClass' => $parentClass,
|
||||
'childClass' => $specification,
|
||||
'parentField' => $parentField,
|
||||
'childField' => $childField,
|
||||
'join' => $joinTable,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ namespace SilverStripe\ORM;
|
||||
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\Connect\Query;
|
||||
use SilverStripe\ORM\Queries\SQLConditionGroup;
|
||||
@ -452,8 +451,8 @@ class DataQuery
|
||||
*/
|
||||
public function max($field)
|
||||
{
|
||||
$table = ClassInfo::table_for_object_field($this->dataClass, $field);
|
||||
if (!$table || $table === 'DataObject') {
|
||||
$table = DataObject::getSchema()->tableForField($this->dataClass, $field);
|
||||
if (!$table) {
|
||||
return $this->aggregate("MAX(\"$field\")");
|
||||
}
|
||||
return $this->aggregate("MAX(\"$table\".\"$field\")");
|
||||
@ -468,8 +467,8 @@ class DataQuery
|
||||
*/
|
||||
public function min($field)
|
||||
{
|
||||
$table = ClassInfo::table_for_object_field($this->dataClass, $field);
|
||||
if (!$table || $table === 'DataObject') {
|
||||
$table = DataObject::getSchema()->tableForField($this->dataClass, $field);
|
||||
if (!$table) {
|
||||
return $this->aggregate("MIN(\"$field\")");
|
||||
}
|
||||
return $this->aggregate("MIN(\"$table\".\"$field\")");
|
||||
@ -484,8 +483,8 @@ class DataQuery
|
||||
*/
|
||||
public function avg($field)
|
||||
{
|
||||
$table = ClassInfo::table_for_object_field($this->dataClass, $field);
|
||||
if (!$table || $table === 'DataObject') {
|
||||
$table = DataObject::getSchema()->tableForField($this->dataClass, $field);
|
||||
if (!$table) {
|
||||
return $this->aggregate("AVG(\"$field\")");
|
||||
}
|
||||
return $this->aggregate("AVG(\"$table\".\"$field\")");
|
||||
@ -500,8 +499,8 @@ class DataQuery
|
||||
*/
|
||||
public function sum($field)
|
||||
{
|
||||
$table = ClassInfo::table_for_object_field($this->dataClass, $field);
|
||||
if (!$table || $table === 'DataObject') {
|
||||
$table = DataObject::getSchema()->tableForField($this->dataClass, $field);
|
||||
if (!$table) {
|
||||
return $this->aggregate("SUM(\"$field\")");
|
||||
}
|
||||
return $this->aggregate("SUM(\"$table\".\"$field\")");
|
||||
@ -569,7 +568,7 @@ class DataQuery
|
||||
foreach ($compositeFields as $k => $v) {
|
||||
if ((is_null($columns) || in_array($k, $columns)) && $v) {
|
||||
$tableName = $schema->tableName($tableClass);
|
||||
$dbO = Object::create_from_string($v, $k);
|
||||
$dbO = Injector::inst()->create($v, $k);
|
||||
$dbO->setTable($tableName);
|
||||
$dbO->addToQuery($query);
|
||||
}
|
||||
@ -799,18 +798,15 @@ class DataQuery
|
||||
if ($linearOnly) {
|
||||
throw new InvalidArgumentException("$rel is not a linear relation on model $modelClass");
|
||||
}
|
||||
// Join via many_many
|
||||
list($relationClass, $parentClass, $componentClass, $parentField, $componentField, $relationTable)
|
||||
= $component;
|
||||
$this->joinManyManyRelationship(
|
||||
$relationClass,
|
||||
$parentClass,
|
||||
$componentClass,
|
||||
$parentField,
|
||||
$componentField,
|
||||
$relationTable
|
||||
$component['relationClass'],
|
||||
$component['parentClass'],
|
||||
$component['childClass'],
|
||||
$component['parentField'],
|
||||
$component['childField'],
|
||||
$component['join']
|
||||
);
|
||||
$modelClass = $componentClass;
|
||||
$modelClass = $component['childClass'];
|
||||
} else {
|
||||
throw new InvalidArgumentException("$rel is not a relation on model $modelClass");
|
||||
}
|
||||
@ -1073,7 +1069,7 @@ class DataQuery
|
||||
* It's expected that the $key will be namespaced, e.g, 'Versioned.stage' instead of just 'stage'.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param string|array $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setQueryParam($key, $value)
|
||||
|
@ -49,7 +49,8 @@ class DBBoolean extends DBField
|
||||
if ($fieldName) {
|
||||
$dataObject->$fieldName = ($this->value) ? 1 : 0;
|
||||
} else {
|
||||
user_error("DBField::saveInto() Called on a nameless '$this->class' object", E_USER_ERROR);
|
||||
$class = static::class;
|
||||
user_error("DBField::saveInto() Called on a nameless '$class' object", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\ORM\FieldType;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\ORM\Queries\SQLSelect;
|
||||
@ -145,6 +145,7 @@ abstract class DBComposite extends DBField
|
||||
* @param mixed $value
|
||||
* @param mixed $record Parent object to this field, which could be a DataObject, record array, or other
|
||||
* @param bool $markChanged
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($value, $record = null, $markChanged = true)
|
||||
{
|
||||
@ -172,6 +173,7 @@ abstract class DBComposite extends DBField
|
||||
$this->setField($field, $record[$key]);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,7 +279,7 @@ abstract class DBComposite extends DBField
|
||||
$key = $this->getName() . $field;
|
||||
$spec = $fields[$field];
|
||||
/** @var DBField $fieldObject */
|
||||
$fieldObject = Object::create_from_string($spec, $key);
|
||||
$fieldObject = Injector::inst()->create($spec, $key);
|
||||
$fieldObject->setValue($this->getField($field), null, false);
|
||||
return $fieldObject;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ class DBDecimal extends DBField
|
||||
if ($fieldName) {
|
||||
$dataObject->$fieldName = (float)preg_replace('/[^0-9.\-\+]/', '', $this->value);
|
||||
} else {
|
||||
user_error("DBField::saveInto() Called on a nameless '" . get_class($this) . "' object", E_USER_ERROR);
|
||||
user_error("DBField::saveInto() Called on a nameless '" . static::class . "' object", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace SilverStripe\ORM\FieldType;
|
||||
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Forms\FormField;
|
||||
use SilverStripe\Forms\TextField;
|
||||
@ -132,9 +131,8 @@ abstract class DBField extends ViewableData
|
||||
public static function create_field($className, $value, $name = null, $object = null)
|
||||
{
|
||||
/** @var DBField $dbField */
|
||||
$dbField = Object::create($className, $name, $object);
|
||||
$dbField = Injector::inst()->create($className, $name, $object);
|
||||
$dbField->setValue($value, null, false);
|
||||
|
||||
return $dbField;
|
||||
}
|
||||
|
||||
@ -449,7 +447,7 @@ abstract class DBField extends ViewableData
|
||||
$fieldName = $this->name;
|
||||
if (empty($fieldName)) {
|
||||
throw new \BadMethodCallException(
|
||||
"DBField::saveInto() Called on a nameless '" . get_class($this) . "' object"
|
||||
"DBField::saveInto() Called on a nameless '" . static::class . "' object"
|
||||
);
|
||||
}
|
||||
$dataObject->$fieldName = $this->value;
|
||||
|
@ -71,7 +71,7 @@ class DBPolymorphicForeignKey extends DBComposite
|
||||
if ($value instanceof DataObject) {
|
||||
$value = array(
|
||||
'ID' => $value->ID,
|
||||
'Class' => $value->class
|
||||
'Class' => get_class($value),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\ORM\Filters;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataQuery;
|
||||
use InvalidArgumentException;
|
||||
@ -23,8 +23,9 @@ use SilverStripe\ORM\FieldType\DBField;
|
||||
* class: EndsWithFilter
|
||||
* </code>
|
||||
*/
|
||||
abstract class SearchFilter extends Object
|
||||
abstract class SearchFilter
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @var string Classname of the inspected {@link DataObject}
|
||||
@ -79,7 +80,6 @@ abstract class SearchFilter extends Object
|
||||
*/
|
||||
public function __construct($fullName = null, $value = false, array $modifiers = array())
|
||||
{
|
||||
parent::__construct();
|
||||
$this->fullName = $fullName;
|
||||
|
||||
// sets $this->name and $this->relation
|
||||
@ -178,7 +178,7 @@ abstract class SearchFilter extends Object
|
||||
$unsupported = array_diff($modifiers, $allowed);
|
||||
if ($unsupported) {
|
||||
throw new InvalidArgumentException(
|
||||
get_class($this) . ' does not accept ' . implode(', ', $unsupported) . ' as modifiers'
|
||||
static::class . ' does not accept ' . implode(', ', $unsupported) . ' as modifiers'
|
||||
);
|
||||
}
|
||||
|
||||
@ -258,11 +258,11 @@ abstract class SearchFilter extends Object
|
||||
// Ensure that we're dealing with a DataObject.
|
||||
if (!is_subclass_of($this->model, DataObject::class)) {
|
||||
throw new InvalidArgumentException(
|
||||
"Model supplied to " . get_class($this) . " should be an instance of DataObject."
|
||||
"Model supplied to " . static::class . " should be an instance of DataObject."
|
||||
);
|
||||
}
|
||||
$schema = DataObject::getSchema();
|
||||
|
||||
|
||||
if ($this->aggregate) {
|
||||
$column = $this->aggregate['column'];
|
||||
$function = $this->aggregate['function'];
|
||||
@ -309,7 +309,7 @@ abstract class SearchFilter extends Object
|
||||
{
|
||||
// SRM: This code finds the table where the field named $this->name lives
|
||||
// Todo: move to somewhere more appropriate, such as DataMapper, the magical class-to-be?
|
||||
|
||||
|
||||
if ($this->aggregate) {
|
||||
return intval($this->value);
|
||||
}
|
||||
@ -330,7 +330,7 @@ abstract class SearchFilter extends Object
|
||||
{
|
||||
$schema = DataObject::getSchema();
|
||||
$baseTable = $schema->baseDataTable($query->dataClass());
|
||||
|
||||
|
||||
return $query
|
||||
->having($having)
|
||||
->groupby("\"{$baseTable}\".\"ID\"");
|
||||
@ -371,7 +371,7 @@ abstract class SearchFilter extends Object
|
||||
*/
|
||||
protected function applyMany(DataQuery $query)
|
||||
{
|
||||
throw new InvalidArgumentException(get_class($this) . " can't be used to filter by a list of items.");
|
||||
throw new InvalidArgumentException(static::class . " can't be used to filter by a list of items.");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -409,7 +409,7 @@ abstract class SearchFilter extends Object
|
||||
*/
|
||||
protected function excludeMany(DataQuery $query)
|
||||
{
|
||||
throw new InvalidArgumentException(get_class($this) . " can't be used to filter by a list of items.");
|
||||
throw new InvalidArgumentException(static::class . " can't be used to filter by a list of items.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,10 +122,10 @@ class Hierarchy extends DataExtension
|
||||
// Hierarchy is looping.
|
||||
$validationResult->addError(
|
||||
_t(
|
||||
'SilverStripe\\ORM\\Hierarchy\\Hierarchy.InfiniteLoopNotAllowed',
|
||||
__CLASS__ . '.InfiniteLoopNotAllowed',
|
||||
'Infinite loop found within the "{type}" hierarchy. Please change the parent to resolve this',
|
||||
'First argument is the class that makes up the hierarchy.',
|
||||
array('type' => $owner->class)
|
||||
array('type' => get_class($owner))
|
||||
),
|
||||
'bad',
|
||||
'INFINITE_LOOP'
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace SilverStripe\ORM;
|
||||
|
||||
use BadMethodCallException;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\Queries\SQLSelect;
|
||||
use SilverStripe\ORM\Queries\SQLDelete;
|
||||
use SilverStripe\ORM\FieldType\DBComposite;
|
||||
@ -100,7 +100,7 @@ class ManyManyList extends RelationList
|
||||
$finalized = array();
|
||||
|
||||
foreach ($this->extraFields as $field => $spec) {
|
||||
$obj = Object::create_from_string($spec);
|
||||
$obj = Injector::inst()->create($spec);
|
||||
|
||||
if ($obj instanceof DBComposite) {
|
||||
$this->_compositeExtraFields[$field] = array();
|
||||
@ -146,7 +146,7 @@ class ManyManyList extends RelationList
|
||||
}
|
||||
}
|
||||
|
||||
$obj = Object::create_from_string($this->extraFields[$fieldName], $fieldName);
|
||||
$obj = Injector::inst()->create($this->extraFields[$fieldName], $fieldName);
|
||||
$obj->setValue($value, null, false);
|
||||
$add[$fieldName] = $obj;
|
||||
}
|
||||
@ -281,7 +281,7 @@ class ManyManyList extends RelationList
|
||||
foreach ($this->extraFields as $fieldName => $fieldSpec) {
|
||||
// Skip fields without an assignment
|
||||
if (array_key_exists($fieldName, $extraFields)) {
|
||||
$fieldObject = Object::create_from_string($fieldSpec, $fieldName);
|
||||
$fieldObject = Injector::inst()->create($fieldSpec, $fieldName);
|
||||
$fieldObject->setValue($extraFields[$fieldName]);
|
||||
$fieldObject->writeToManipulation($manipulation[$this->joinTable]);
|
||||
}
|
||||
|
@ -98,8 +98,6 @@ class FulltextSearchable extends DataExtension
|
||||
} else {
|
||||
$this->searchFields = $searchFields;
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public static function get_extra_config($class, $extensionClass, $args)
|
||||
|
@ -4,7 +4,7 @@ namespace SilverStripe\ORM\Search;
|
||||
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\FormField;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
@ -34,8 +34,9 @@ use Exception;
|
||||
*
|
||||
* @see http://doc.silverstripe.com/doku.php?id=searchcontext
|
||||
*/
|
||||
class SearchContext extends Object
|
||||
class SearchContext
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* DataObject subclass to which search parameters relate to.
|
||||
@ -85,8 +86,6 @@ class SearchContext extends Object
|
||||
$this->modelClass = $modelClass;
|
||||
$this->fields = ($fields) ? $fields : new FieldList();
|
||||
$this->filters = ($filters) ? $filters : array();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,6 +135,7 @@ class SearchContext extends Object
|
||||
public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null)
|
||||
{
|
||||
/** DataList $query */
|
||||
$query = null;
|
||||
if ($existingQuery) {
|
||||
if (!($existingQuery instanceof DataList)) {
|
||||
throw new InvalidArgumentException("existingQuery must be DataList");
|
||||
@ -158,6 +158,7 @@ class SearchContext extends Object
|
||||
$query = $query->limit($limit);
|
||||
}
|
||||
|
||||
/** @var DataList $query */
|
||||
$query = $query->sort($sort);
|
||||
|
||||
// hack to work with $searchParems when it's an Object
|
||||
|
@ -51,7 +51,7 @@ class UnsavedRelationList extends ArrayList implements Relation
|
||||
/**
|
||||
* Create a new UnsavedRelationList
|
||||
*
|
||||
* @param array $baseClass
|
||||
* @param string $baseClass
|
||||
* @param string $relationName
|
||||
* @param string $dataClass The DataObject class used in the relation
|
||||
*/
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
namespace SilverStripe\Security;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\Forms\Form;
|
||||
|
||||
/**
|
||||
@ -15,8 +16,16 @@ use SilverStripe\Forms\Form;
|
||||
*
|
||||
* @author Markus Lanthaler <markus@silverstripe.com>
|
||||
*/
|
||||
abstract class Authenticator extends Object
|
||||
abstract class Authenticator
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
use Extensible;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* This variable holds all authenticators that should be used
|
||||
@ -78,7 +87,7 @@ abstract class Authenticator extends Object
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a given authenticator is registered
|
||||
*
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace SilverStripe\Security;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\ORM\ValidationResult;
|
||||
|
||||
/**
|
||||
@ -17,9 +18,15 @@ use SilverStripe\ORM\ValidationResult;
|
||||
* Member::set_password_validator($pwdValidator);
|
||||
* </code>
|
||||
*/
|
||||
class PasswordValidator extends Object
|
||||
class PasswordValidator
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @var array
|
||||
*/
|
||||
private static $character_strength_tests = array(
|
||||
'lowercase' => '/[a-z]/',
|
||||
'uppercase' => '/[A-Z]/',
|
||||
|
@ -879,7 +879,7 @@ class Security extends Controller implements TemplateGlobalProvider
|
||||
*/
|
||||
public function getTemplatesFor($action)
|
||||
{
|
||||
$templates = SSViewer::get_templates_by_class(get_class($this), "_{$action}", __CLASS__);
|
||||
$templates = SSViewer::get_templates_by_class(static::class, "_{$action}", __CLASS__);
|
||||
return array_merge(
|
||||
$templates,
|
||||
[
|
||||
|
@ -3,7 +3,8 @@
|
||||
namespace SilverStripe\Security;
|
||||
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
@ -34,8 +35,10 @@ use SilverStripe\View\TemplateGlobalProvider;
|
||||
*
|
||||
* @todo Make token name form specific for additional forgery protection.
|
||||
*/
|
||||
class SecurityToken extends Object implements TemplateGlobalProvider
|
||||
class SecurityToken implements TemplateGlobalProvider
|
||||
{
|
||||
use Configurable;
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -63,7 +66,6 @@ class SecurityToken extends Object implements TemplateGlobalProvider
|
||||
public function __construct($name = null)
|
||||
{
|
||||
$this->name = ($name) ? $name : self::get_default_name();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,13 +2,16 @@
|
||||
|
||||
namespace SilverStripe\View\Parsers;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* Base class for HTML cleaning implementations.
|
||||
*/
|
||||
abstract class HTMLCleaner extends Object
|
||||
abstract class HTMLCleaner
|
||||
{
|
||||
use Configurable;
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
@ -27,7 +30,6 @@ abstract class HTMLCleaner extends Object
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
{
|
||||
parent::__construct();
|
||||
if ($config) {
|
||||
$config = array_merge($this->defaultConfig, $config);
|
||||
} else {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\View\Parsers;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* Format a SQL Query for better readable output in HTML or Plaintext.
|
||||
@ -12,8 +12,9 @@ use SilverStripe\Core\Object;
|
||||
*
|
||||
* @author Ingo Schommer, Silverstripe Ltd. (<firstname>@silverstripe.com)
|
||||
*/
|
||||
class SQLFormatter extends Object
|
||||
class SQLFormatter
|
||||
{
|
||||
use Injectable;
|
||||
|
||||
protected static $newline_before_tokens = array(
|
||||
'SELECT',
|
||||
|
@ -3,7 +3,9 @@
|
||||
namespace SilverStripe\View\Parsers;
|
||||
|
||||
use DOMNodeList;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use InvalidArgumentException;
|
||||
use DOMElement;
|
||||
@ -16,8 +18,16 @@ use DOMElement;
|
||||
*
|
||||
* @see http://doc.silverstripe.org/framework/en/reference/shortcodes
|
||||
*/
|
||||
class ShortcodeParser extends Object
|
||||
class ShortcodeParser
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
use Extensible;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
public function img_shortcode($attrs)
|
||||
{
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace SilverStripe\View\Parsers;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* Support class for converting unicode strings into a suitable 7-bit ASCII equivalent.
|
||||
@ -14,8 +15,11 @@ use SilverStripe\Core\Object;
|
||||
* $ascii = $tr->toASCII($unicode);
|
||||
* </code>
|
||||
*/
|
||||
class Transliterator extends Object
|
||||
class Transliterator
|
||||
{
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @var boolean Allow the use of iconv() to perform transliteration. Set to false to disable.
|
||||
@ -53,11 +57,11 @@ class Transliterator extends Object
|
||||
'Õ'=>'O', 'Ö'=>'Oe', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'Ue', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'ss',
|
||||
'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'ae', 'å'=>'a', 'æ'=>'ae', 'ç'=>'c', 'è'=>'e', 'é'=>'e',
|
||||
'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o',
|
||||
'ô'=>'o', 'õ'=>'o', 'ö'=>'oe', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ü'=>'ue', 'ý'=>'y', 'ý'=>'y',
|
||||
'ô'=>'o', 'õ'=>'o', 'ö'=>'oe', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ü'=>'ue', 'ý'=>'y',
|
||||
'þ'=>'b', 'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r',
|
||||
'Ā'=>'A', 'ā'=>'a', 'Ē'=>'E', 'ē'=>'e', 'Ī'=>'I', 'ī'=>'i', 'Ō'=>'O', 'ō'=>'o', 'Ū'=>'U', 'ū'=>'u',
|
||||
'œ'=>'oe', 'ß'=>'ss', 'ij'=>'ij', 'ą'=>'a','ę'=>'e', 'ė'=>'e', 'į'=>'i','ų'=>'u','ū'=>'u', 'Ą'=>'A',
|
||||
'Ę'=>'E', 'Ė'=>'E', 'Į'=>'I','Ų'=>'U','Ū'=>'U',
|
||||
'œ'=>'oe', 'ij'=>'ij', 'ą'=>'a','ę'=>'e', 'ė'=>'e', 'į'=>'i', 'ų'=>'u', 'Ą'=>'A',
|
||||
'Ę'=>'E', 'Ė'=>'E', 'Į'=>'I','Ų'=>'U',
|
||||
"ľ"=>"l", "Ľ"=>"L", "ť"=>"t", "Ť"=>"T", "ů"=>"u", "Ů"=>"U",
|
||||
'ł'=>'l', 'Ł'=>'L', 'ń'=>'n', 'Ń'=>'N', 'ś'=>'s', 'Ś'=>'S', 'ź'=>'z', 'Ź'=>'Z', 'ż'=>'z', 'Ż'=>'Z',
|
||||
'а'=>"a",'б'=>"b",'в'=>"v",'г'=>"g",'д'=>"d",'е'=>"e",'ё'=>"yo",'ж'=>"zh",'з'=>"z",'и'=>"i",
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace SilverStripe\View\Parsers;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
|
||||
/**
|
||||
* Filter certain characters from "URL segments" (also called "slugs"), for nicer (more SEO-friendly) URLs.
|
||||
@ -14,8 +15,10 @@ use SilverStripe\Core\Object;
|
||||
*
|
||||
* See {@link FileNameFilter} for similar implementation for filesystem-based URLs.
|
||||
*/
|
||||
class URLSegmentFilter extends Object
|
||||
class URLSegmentFilter
|
||||
{
|
||||
use Configurable;
|
||||
use Injectable;
|
||||
|
||||
/**
|
||||
* @config
|
||||
|
@ -313,7 +313,7 @@ class SSViewer implements Flushable
|
||||
/**
|
||||
* Returns true if at least one of the listed templates exists.
|
||||
*
|
||||
* @param array $templates
|
||||
* @param array|string $templates
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
|
@ -5,7 +5,6 @@ namespace SilverStripe\View;
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
/**
|
||||
* This extends SSViewer_Scope to mix in data on top of what the item provides. This can be "global"
|
||||
@ -304,7 +303,7 @@ class SSViewer_DataPresenter extends SSViewer_Scope
|
||||
if ($val) {
|
||||
$obj = $val['obj'];
|
||||
if ($name === 'hasValue') {
|
||||
$res = $obj instanceof Object
|
||||
$res = $obj instanceof ViewableData
|
||||
? $obj->exists()
|
||||
: (bool)$obj;
|
||||
} else {
|
||||
|
@ -2,7 +2,10 @@
|
||||
|
||||
namespace SilverStripe\View;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use Exception;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\ORM\ArrayLib;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||
@ -23,8 +26,13 @@ use ArrayIterator;
|
||||
* is provided and automatically escaped by ViewableData. Any class that needs to be available to a view (controllers,
|
||||
* {@link DataObject}s, page controls) should inherit from this class.
|
||||
*/
|
||||
class ViewableData extends Object implements IteratorAggregate
|
||||
class ViewableData implements IteratorAggregate
|
||||
{
|
||||
use Extensible {
|
||||
defineMethods as extensibleDefineMethods;
|
||||
}
|
||||
use Injectable;
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* An array of objects to cast certain fields to. This is set up as an array in the format:
|
||||
@ -75,6 +83,11 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
*/
|
||||
private $objCache = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructExtensions();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// FIELD GETTERS & SETTERS -----------------------------------------------------------------------------------------
|
||||
@ -218,11 +231,12 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
$this->addMethodsFrom('failover');
|
||||
|
||||
if (isset($_REQUEST['debugfailover'])) {
|
||||
Debug::message("$this->class created with a failover class of {$this->failover->class}");
|
||||
$class = static::class;
|
||||
$failoverClass = get_class($this->failover);
|
||||
Debug::message("$class created with a failover class of {$failoverClass}");
|
||||
}
|
||||
}
|
||||
|
||||
parent::defineMethods();
|
||||
$this->extensibleDefineMethods();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,6 +263,27 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this object "exists" i.e. has a sensible value
|
||||
*
|
||||
* This method should be overriden in subclasses to provide more context about the classes state. For example, a
|
||||
* {@link DataObject} class could return false when it is deleted from the database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exists()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the class name
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ViewableData
|
||||
*/
|
||||
@ -273,6 +308,7 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
*
|
||||
* @param string $field
|
||||
* @return string Casting helper As a constructor pattern, and may include arguments.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function castingHelper($field)
|
||||
{
|
||||
@ -295,7 +331,7 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
// Fall back to default_cast
|
||||
$default = $this->config()->get('default_cast');
|
||||
if (empty($default)) {
|
||||
throw new \Exception("No default_cast");
|
||||
throw new Exception("No default_cast");
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
@ -448,7 +484,7 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
if (!is_object($value)) {
|
||||
// Force cast
|
||||
$castingHelper = $this->castingHelper($fieldName);
|
||||
$valueObject = Object::create_from_string($castingHelper, $fieldName);
|
||||
$valueObject = Injector::inst()->create($castingHelper, $fieldName);
|
||||
$valueObject->setValue($value, $this);
|
||||
$value = $valueObject;
|
||||
}
|
||||
@ -564,7 +600,7 @@ class ViewableData extends Object implements IteratorAggregate
|
||||
public function CSSClasses($stopAtClass = self::class)
|
||||
{
|
||||
$classes = array();
|
||||
$classAncestry = array_reverse(ClassInfo::ancestry($this->class));
|
||||
$classAncestry = array_reverse(ClassInfo::ancestry(static::class));
|
||||
$stopClasses = ClassInfo::ancestry($stopAtClass);
|
||||
|
||||
foreach ($classAncestry as $class) {
|
||||
|
@ -42,15 +42,16 @@ class ViewableData_Debugger extends ViewableData
|
||||
public function forTemplate($field = null)
|
||||
{
|
||||
// debugging info for a specific field
|
||||
$class = get_class($this->object);
|
||||
if ($field) {
|
||||
return "<b>Debugging Information for {$this->class}->{$field}</b><br/>" .
|
||||
($this->object->hasMethod($field) ? "Has method '$field'<br/>" : null) .
|
||||
($this->object->hasField($field) ? "Has field '$field'<br/>" : null);
|
||||
return "<b>Debugging Information for {$class}->{$field}</b><br/>" .
|
||||
($this->object->hasMethod($field) ? "Has method '$field'<br/>" : null) .
|
||||
($this->object->hasField($field) ? "Has field '$field'<br/>" : null);
|
||||
}
|
||||
|
||||
// debugging information for the entire class
|
||||
$reflector = new ReflectionObject($this->object);
|
||||
$debug = "<b>Debugging Information: all methods available in '{$this->object->class}'</b><br/><ul>";
|
||||
$debug = "<b>Debugging Information: all methods available in '{$class}'</b><br/><ul>";
|
||||
|
||||
foreach ($this->object->allMethodNames() as $method) {
|
||||
// check that the method is public
|
||||
@ -74,7 +75,7 @@ class ViewableData_Debugger extends ViewableData
|
||||
$debug .= '</ul>';
|
||||
|
||||
if ($this->object->hasMethod('toMap')) {
|
||||
$debug .= "<b>Debugging Information: all fields available in '{$this->object->class}'</b><br/><ul>";
|
||||
$debug .= "<b>Debugging Information: all fields available in '{$class}'</b><br/><ul>";
|
||||
|
||||
foreach ($this->object->toMap() as $field => $value) {
|
||||
$debug .= "<li>\$$field</li>";
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use ReflectionException;
|
||||
use SilverStripe\Core\Tests\ClassInfoTest\BaseClass;
|
||||
use SilverStripe\Core\Tests\ClassInfoTest\BaseDataClass;
|
||||
use SilverStripe\Core\Tests\ClassInfoTest\ChildClass;
|
||||
@ -39,8 +39,8 @@ class ClassInfoTest extends SapphireTest
|
||||
|
||||
public function testExists()
|
||||
{
|
||||
$this->assertTrue(ClassInfo::exists('SilverStripe\\Core\\Object'));
|
||||
$this->assertTrue(ClassInfo::exists('SilverStripe\\Core\\object'));
|
||||
$this->assertTrue(ClassInfo::exists(ClassInfo::class));
|
||||
$this->assertTrue(ClassInfo::exists('SilverStripe\\Core\\classinfo'));
|
||||
$this->assertTrue(ClassInfo::exists('SilverStripe\\Core\\Tests\\ClassInfoTest'));
|
||||
$this->assertTrue(ClassInfo::exists('SilverStripe\\Core\\Tests\\CLASSINFOTEST'));
|
||||
$this->assertTrue(ClassInfo::exists('stdClass'));
|
||||
@ -89,7 +89,8 @@ class ClassInfoTest extends SapphireTest
|
||||
|
||||
public function testNonClassName()
|
||||
{
|
||||
$this->setExpectedException('ReflectionException', 'Class IAmAClassThatDoesNotExist does not exist');
|
||||
$this->expectException(ReflectionException::class);
|
||||
$this->expectExceptionMessage('Class IAmAClassThatDoesNotExist does not exist');
|
||||
$this->assertEquals('IAmAClassThatDoesNotExist', ClassInfo::class_name('IAmAClassThatDoesNotExist'));
|
||||
}
|
||||
|
||||
@ -117,15 +118,12 @@ class ClassInfoTest extends SapphireTest
|
||||
public function testAncestry()
|
||||
{
|
||||
$ancestry = ClassInfo::ancestry(ChildClass::class);
|
||||
$expect = ArrayLib::valuekey(
|
||||
array(
|
||||
Object::class,
|
||||
$expect = ArrayLib::valuekey([
|
||||
ViewableData::class,
|
||||
DataObject::class,
|
||||
BaseClass::class,
|
||||
ChildClass::class,
|
||||
)
|
||||
);
|
||||
]);
|
||||
$this->assertEquals($expect, $ancestry);
|
||||
|
||||
ClassInfo::reset_db_cache();
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace SilverStripe\Core\Tests\Config;
|
||||
|
||||
use SilverStripe\Config\MergeStrategy\Priority;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
@ -260,21 +259,6 @@ class ConfigTest extends SapphireTest
|
||||
);
|
||||
}
|
||||
|
||||
public function testStaticLookup()
|
||||
{
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesFoo::class, 'foo'), 1);
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesFoo::class, 'bar'), null);
|
||||
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesBar::class, 'foo'), null);
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesBar::class, 'bar'), 2);
|
||||
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesFooAndBar::class, 'foo'), 3);
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesFooAndBar::class, 'bar'), 3);
|
||||
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesFooDoesntExtendObject::class, 'foo'), 4);
|
||||
$this->assertEquals(Object::static_lookup(ConfigTest\DefinesFooDoesntExtendObject::class, 'bar'), null);
|
||||
}
|
||||
|
||||
public function testForClass()
|
||||
{
|
||||
$config = ConfigTest\DefinesFoo::config();
|
||||
|
11
tests/php/Core/Config/ConfigTest/BaseObject.php
Normal file
11
tests/php/Core/Config/ConfigTest/BaseObject.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Core\Tests\Config\ConfigTest;
|
||||
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class BaseObject implements TestOnly
|
||||
{
|
||||
use Configurable;
|
||||
}
|
@ -2,10 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\Config\ConfigTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class DefinesFoo extends Object implements TestOnly
|
||||
class DefinesFoo extends BaseObject
|
||||
{
|
||||
protected static $foo = 1;
|
||||
|
||||
|
@ -2,10 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\Config\ConfigTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class TestNest extends Object implements TestOnly
|
||||
class TestNest extends BaseObject
|
||||
{
|
||||
/**
|
||||
* @config
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\Injector\InjectorTest;
|
||||
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Injector\InjectionCreator;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
/**
|
||||
* An example object creator that uses the SilverStripe class(arguments) mechanism for
|
||||
@ -11,8 +13,11 @@ use SilverStripe\Core\Object;
|
||||
*
|
||||
* @see https://github.com/silverstripe/sapphire
|
||||
*/
|
||||
class SSObjectCreator extends InjectionCreator
|
||||
class SSObjectCreator extends InjectionCreator implements TestOnly
|
||||
{
|
||||
/**
|
||||
* @var Injector
|
||||
*/
|
||||
private $injector;
|
||||
|
||||
public function __construct($injector)
|
||||
@ -25,7 +30,7 @@ class SSObjectCreator extends InjectionCreator
|
||||
if (strpos($class, '(') === false) {
|
||||
return parent::create($class, $params);
|
||||
} else {
|
||||
list($class, $params) = Object::parse_class_spec($class);
|
||||
list($class, $params) = ClassInfo::parse_class_spec($class);
|
||||
$params = $this->injector->convertServiceProperty($params);
|
||||
return parent::create($class, $params);
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ class ClassManifestTest extends SapphireTest
|
||||
*/
|
||||
public function testManifestWarnsAboutDuplicateClasses()
|
||||
{
|
||||
$this->setExpectedException(Exception::class);
|
||||
$this->expectException(Exception::class);
|
||||
new ClassManifest(dirname(__FILE__) . '/fixtures/classmanifest_duplicates', false);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use SilverStripe\Control\HTTPRequest as Request, SilverStripe\Control\HTTPRespon
|
||||
/** @skipUpgrade */
|
||||
use silverstripe\test\ClassA;
|
||||
/** @skipUpgrade */
|
||||
use \SilverStripe\Core\Object;
|
||||
use \SilverStripe\Core\ClassInfo;
|
||||
|
||||
/** @skipUpgrade */
|
||||
class ClassI extends ModelAdmin implements P {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Tests\ObjectTest\ExtendTest1;
|
||||
use SilverStripe\Core\Tests\ObjectTest\ExtendTest2;
|
||||
@ -52,7 +52,7 @@ class ObjectTest extends SapphireTest
|
||||
foreach ($trueMethods as $method) {
|
||||
$methodU = strtoupper($method);
|
||||
$methodL = strtoupper($method);
|
||||
$this->assertTrue($obj->hasMethod($method), "Test that obj#$i has method $method ($obj->class)");
|
||||
$this->assertTrue($obj->hasMethod($method), "Test that obj#$i has method $method");
|
||||
$this->assertTrue($obj->hasMethod($methodU), "Test that obj#$i has method $methodU");
|
||||
$this->assertTrue($obj->hasMethod($methodL), "Test that obj#$i has method $methodL");
|
||||
|
||||
@ -73,32 +73,21 @@ class ObjectTest extends SapphireTest
|
||||
|
||||
public function testSingletonCreation()
|
||||
{
|
||||
$myObject = singleton(MyObject::class);
|
||||
$this->assertEquals(
|
||||
$myObject->class,
|
||||
$myObject = MyObject::singleton();
|
||||
$this->assertInstanceOf(
|
||||
MyObject::class,
|
||||
$myObject,
|
||||
'singletons are creating a correct class instance'
|
||||
);
|
||||
$this->assertEquals(
|
||||
get_class($myObject),
|
||||
MyObject::class,
|
||||
'singletons are creating a correct class instance'
|
||||
);
|
||||
|
||||
$mySubObject = singleton(MySubObject::class);
|
||||
$this->assertEquals(
|
||||
$mySubObject->class,
|
||||
MySubObject::class,
|
||||
'singletons are creating a correct subclass instance'
|
||||
);
|
||||
$this->assertEquals(
|
||||
get_class($mySubObject),
|
||||
$mySubObject = MySubObject::singleton();
|
||||
$this->assertInstanceOf(
|
||||
MySubObject::class,
|
||||
$mySubObject,
|
||||
'singletons are creating a correct subclass instance'
|
||||
);
|
||||
|
||||
$myFirstObject = singleton(MyObject::class);
|
||||
$mySecondObject = singleton(MyObject::class);
|
||||
$myFirstObject = MyObject::singleton();
|
||||
$mySecondObject = MyObject::singleton();
|
||||
$this->assertTrue(
|
||||
$myFirstObject === $mySecondObject,
|
||||
'singletons are using the same object on subsequent calls'
|
||||
@ -182,14 +171,14 @@ class ObjectTest extends SapphireTest
|
||||
'SilverStripe\\Core\\Tests\\oBjEcTTEST\\EXTENDTest1',
|
||||
"SilverStripe\\Core\\Tests\\ObjectTest\\ExtendTest2",
|
||||
),
|
||||
Object::get_extensions(ExtensionTest::class)
|
||||
ExtensionTest::get_extensions()
|
||||
);
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'SilverStripe\\Core\\Tests\\oBjEcTTEST\\EXTENDTest1',
|
||||
"SilverStripe\\Core\\Tests\\ObjectTest\\ExtendTest2('FOO', 'BAR')",
|
||||
),
|
||||
Object::get_extensions(ExtensionTest::class, true)
|
||||
ExtensionTest::get_extensions(null, true)
|
||||
);
|
||||
$inst = new ExtensionTest();
|
||||
$extensions = $inst->getExtensionInstances();
|
||||
@ -336,7 +325,7 @@ class ObjectTest extends SapphireTest
|
||||
|
||||
ObjectTest\ExtensionRemoveTest::remove_extension(ExtendTest2::class);
|
||||
$this->assertFalse(
|
||||
Object::has_extension(ExtensionRemoveTest::class, ExtendTest2::class),
|
||||
ExtensionRemoveTest::has_extension(ExtendTest2::class),
|
||||
"Extension added through \$add_extension() are detected as removed in has_extension()"
|
||||
);
|
||||
|
||||
@ -347,14 +336,9 @@ class ObjectTest extends SapphireTest
|
||||
);
|
||||
}
|
||||
|
||||
public function testParentClass()
|
||||
{
|
||||
$this->assertEquals(ObjectTest\MyObject::create()->parentClass(), 'SilverStripe\\Core\\Object');
|
||||
}
|
||||
|
||||
public function testIsA()
|
||||
{
|
||||
$this->assertTrue(ObjectTest\MyObject::create() instanceof Object);
|
||||
$this->assertTrue(ObjectTest\MyObject::create() instanceof ObjectTest\BaseObject);
|
||||
$this->assertTrue(ObjectTest\MyObject::create() instanceof ObjectTest\MyObject);
|
||||
}
|
||||
|
||||
@ -369,30 +353,6 @@ class ObjectTest extends SapphireTest
|
||||
$this->assertTrue($obj->getExtensionInstance(TestExtension::class) instanceof ObjectTest\TestExtension);
|
||||
}
|
||||
|
||||
public function testCacheToFile()
|
||||
{
|
||||
$this->markTestIncomplete();
|
||||
/*
|
||||
// This doesn't run properly on our build slave.
|
||||
$obj = new ObjectTest_CacheTest();
|
||||
|
||||
$obj->clearCache('cacheMethod');
|
||||
$obj->clearCache('cacheMethod', null, array(true));
|
||||
$obj->clearCache('incNumber');
|
||||
|
||||
$this->assertEquals('noarg', $obj->cacheToFile('cacheMethod', -1));
|
||||
$this->assertEquals('hasarg', $obj->cacheToFile('cacheMethod', -1, null, array(true)));
|
||||
$this->assertEquals('hasarg', $obj->cacheToFile('cacheMethod', 3600, null, array(true)));
|
||||
|
||||
// -1 lifetime will ensure that the cache isn't read - number incremented
|
||||
$this->assertEquals(1, $obj->cacheToFile('incNumber', -1));
|
||||
// -1 lifetime will ensure that the cache isn't read - number incremented
|
||||
$this->assertEquals(2, $obj->cacheToFile('incNumber', -1));
|
||||
// Number shouldn't be incremented now because we're using the cached version
|
||||
$this->assertEquals(2, $obj->cacheToFile('incNumber'));
|
||||
*/
|
||||
}
|
||||
|
||||
public function testExtend()
|
||||
{
|
||||
$object = new ObjectTest\ExtendTest();
|
||||
@ -434,52 +394,52 @@ class ObjectTest extends SapphireTest
|
||||
// Simple case
|
||||
$this->assertEquals(
|
||||
array(Versioned::class,array('Stage', 'Live')),
|
||||
Object::parse_class_spec("SilverStripe\\Versioned\\Versioned('Stage','Live')")
|
||||
ClassInfo::parse_class_spec("SilverStripe\\Versioned\\Versioned('Stage','Live')")
|
||||
);
|
||||
// String with commas
|
||||
$this->assertEquals(
|
||||
array(Versioned::class,array('Stage,Live', 'Stage')),
|
||||
Object::parse_class_spec("SilverStripe\\Versioned\\Versioned('Stage,Live','Stage')")
|
||||
ClassInfo::parse_class_spec("SilverStripe\\Versioned\\Versioned('Stage,Live','Stage')")
|
||||
);
|
||||
// String with quotes
|
||||
$this->assertEquals(
|
||||
array(Versioned::class,array('Stage\'Stage,Live\'Live', 'Live')),
|
||||
Object::parse_class_spec("SilverStripe\\Versioned\\Versioned('Stage\\'Stage,Live\\'Live','Live')")
|
||||
ClassInfo::parse_class_spec("SilverStripe\\Versioned\\Versioned('Stage\\'Stage,Live\\'Live','Live')")
|
||||
);
|
||||
|
||||
// True, false and null values
|
||||
$this->assertEquals(
|
||||
array('ClassName', array('string', true, array('string', false))),
|
||||
Object::parse_class_spec('ClassName("string", true, array("string", false))')
|
||||
ClassInfo::parse_class_spec('ClassName("string", true, array("string", false))')
|
||||
);
|
||||
$this->assertEquals(
|
||||
array('ClassName', array(true, false, null)),
|
||||
Object::parse_class_spec('ClassName(true, false, null)')
|
||||
ClassInfo::parse_class_spec('ClassName(true, false, null)')
|
||||
);
|
||||
|
||||
// Array
|
||||
$this->assertEquals(
|
||||
array('Enum',array(array('Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted')),
|
||||
Object::parse_class_spec("Enum(array('Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted')")
|
||||
ClassInfo::parse_class_spec("Enum(array('Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted')")
|
||||
);
|
||||
// Nested array
|
||||
$this->assertEquals(
|
||||
array('Enum',array(array('Accepted', 'Pending', 'Declined', array('UnsubmittedA','UnsubmittedB')),
|
||||
'Unsubmitted')),
|
||||
Object::parse_class_spec(
|
||||
ClassInfo::parse_class_spec(
|
||||
"Enum(array('Accepted', 'Pending', 'Declined', array('UnsubmittedA','UnsubmittedB')), 'Unsubmitted')"
|
||||
)
|
||||
);
|
||||
// 5.4 Shorthand Array
|
||||
$this->assertEquals(
|
||||
array('Enum',array(array('Accepted', 'Pending', 'Declined', 'Unsubmitted'), 'Unsubmitted')),
|
||||
Object::parse_class_spec("Enum(['Accepted', 'Pending', 'Declined', 'Unsubmitted'], 'Unsubmitted')")
|
||||
ClassInfo::parse_class_spec("Enum(['Accepted', 'Pending', 'Declined', 'Unsubmitted'], 'Unsubmitted')")
|
||||
);
|
||||
// 5.4 Nested shorthand array
|
||||
$this->assertEquals(
|
||||
array('Enum',array(array('Accepted', 'Pending', 'Declined', array('UnsubmittedA','UnsubmittedB')),
|
||||
'Unsubmitted')),
|
||||
Object::parse_class_spec(
|
||||
ClassInfo::parse_class_spec(
|
||||
"Enum(['Accepted', 'Pending', 'Declined', ['UnsubmittedA','UnsubmittedB']], 'Unsubmitted')"
|
||||
)
|
||||
);
|
||||
@ -487,33 +447,33 @@ class ObjectTest extends SapphireTest
|
||||
// Associative array
|
||||
$this->assertEquals(
|
||||
array('Varchar', array(255, array('nullifyEmpty' => false))),
|
||||
Object::parse_class_spec("Varchar(255, array('nullifyEmpty' => false))")
|
||||
ClassInfo::parse_class_spec("Varchar(255, array('nullifyEmpty' => false))")
|
||||
);
|
||||
// Nested associative array
|
||||
$this->assertEquals(
|
||||
array('Test', array('string', array('nested' => array('foo' => 'bar')))),
|
||||
Object::parse_class_spec("Test('string', array('nested' => array('foo' => 'bar')))")
|
||||
ClassInfo::parse_class_spec("Test('string', array('nested' => array('foo' => 'bar')))")
|
||||
);
|
||||
// 5.4 shorthand associative array
|
||||
$this->assertEquals(
|
||||
array('Varchar', array(255, array('nullifyEmpty' => false))),
|
||||
Object::parse_class_spec("Varchar(255, ['nullifyEmpty' => false])")
|
||||
ClassInfo::parse_class_spec("Varchar(255, ['nullifyEmpty' => false])")
|
||||
);
|
||||
// 5.4 shorthand nested associative array
|
||||
$this->assertEquals(
|
||||
array('Test', array('string', array('nested' => array('foo' => 'bar')))),
|
||||
Object::parse_class_spec("Test('string', ['nested' => ['foo' => 'bar']])")
|
||||
ClassInfo::parse_class_spec("Test('string', ['nested' => ['foo' => 'bar']])")
|
||||
);
|
||||
|
||||
// Namespaced class
|
||||
$this->assertEquals(
|
||||
array('Test\MyClass', array()),
|
||||
Object::parse_class_spec('Test\MyClass')
|
||||
ClassInfo::parse_class_spec('Test\MyClass')
|
||||
);
|
||||
// Fully qualified namespaced class
|
||||
$this->assertEquals(
|
||||
array('\Test\MyClass', array()),
|
||||
Object::parse_class_spec('\Test\MyClass')
|
||||
ClassInfo::parse_class_spec('\Test\MyClass')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
20
tests/php/Core/ObjectTest/BaseObject.php
Normal file
20
tests/php/Core/ObjectTest/BaseObject.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use SilverStripe\Core\Extensible;
|
||||
use SilverStripe\Core\Injector\Injectable;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class BaseObject implements TestOnly
|
||||
{
|
||||
use Extensible;
|
||||
use Configurable;
|
||||
use Injectable;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructExtensions();
|
||||
}
|
||||
}
|
@ -2,11 +2,8 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class CacheTest extends Object
|
||||
class CacheTest extends BaseObject
|
||||
{
|
||||
|
||||
public $count = 0;
|
||||
|
||||
public function cacheMethod($arg1 = null)
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class CreateTest extends Object
|
||||
class CreateTest extends BaseObject
|
||||
{
|
||||
public $constructArguments;
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class CreateTest2 extends Object
|
||||
class CreateTest2 extends BaseObject
|
||||
{
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class CreateTest3 extends Object
|
||||
class CreateTest3 extends BaseObject
|
||||
{
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class ExtendTest extends Object
|
||||
class ExtendTest extends BaseObject
|
||||
{
|
||||
private static $extensions = array(
|
||||
ExtendTest1::class,
|
||||
|
@ -3,8 +3,9 @@
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class ExtendTest1 extends Extension
|
||||
class ExtendTest1 extends Extension implements TestOnly
|
||||
{
|
||||
public function extendableMethod(&$argument = null)
|
||||
{
|
||||
|
@ -3,9 +3,17 @@
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class ExtendTest2 extends Extension
|
||||
class ExtendTest2 extends Extension implements TestOnly
|
||||
{
|
||||
protected $constructorArgs = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructorArgs = func_get_args();
|
||||
}
|
||||
|
||||
public function extendableMethod($argument = null)
|
||||
{
|
||||
$args = implode(',', array_filter(func_get_args()));
|
||||
|
@ -3,9 +3,17 @@
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class ExtendTest3 extends Extension
|
||||
class ExtendTest3 extends Extension implements TestOnly
|
||||
{
|
||||
protected $constructorArgs = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructorArgs = func_get_args();
|
||||
}
|
||||
|
||||
public function extendableMethod($argument = null)
|
||||
{
|
||||
return "ExtendTest3($argument)";
|
||||
|
@ -2,10 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class Extending extends Object implements TestOnly
|
||||
class Extending extends BaseObject
|
||||
{
|
||||
|
||||
private static $extensions = array(
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class ExtensionRemoveTest extends Object
|
||||
class ExtensionRemoveTest extends BaseObject
|
||||
{
|
||||
private static $extensions = array(
|
||||
ExtendTest1::class,
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class ExtensionTest extends Object
|
||||
class ExtensionTest extends BaseObject
|
||||
{
|
||||
private static $extensions = array(
|
||||
'SilverStripe\\Core\\Tests\\oBjEcTTEST\\EXTENDTest1',
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class ExtensionTest2 extends Object
|
||||
class ExtensionTest2 extends BaseObject
|
||||
{
|
||||
private static $extensions = [
|
||||
TestExtension::class,
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class ExtensionTest3 extends Object
|
||||
class ExtensionTest3 extends BaseObject
|
||||
{
|
||||
}
|
||||
|
@ -2,14 +2,12 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class MyObject extends Object
|
||||
class MyObject extends BaseObject
|
||||
{
|
||||
public $title = 'my object';
|
||||
/**
|
||||
* @config
|
||||
*/
|
||||
* @config
|
||||
*/
|
||||
private static $mystaticProperty = "MyObject";
|
||||
static $mystaticArray = array('one');
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class T1A extends Object
|
||||
class T1A extends BaseObject
|
||||
{
|
||||
public function testMethod()
|
||||
{
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class T1B extends Object
|
||||
class T1B extends BaseObject
|
||||
{
|
||||
public function someMethod()
|
||||
{
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class T1C extends Object
|
||||
class T1C extends BaseObject
|
||||
{
|
||||
public function t1cMethod()
|
||||
{
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class T2 extends Object
|
||||
class T2 extends BaseObject
|
||||
{
|
||||
protected $failover;
|
||||
protected $failoverArr = array();
|
||||
|
@ -3,7 +3,8 @@
|
||||
namespace SilverStripe\Core\Tests\ObjectTest;
|
||||
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class TestExtension extends Extension
|
||||
class TestExtension extends Extension implements TestOnly
|
||||
{
|
||||
}
|
||||
|
@ -37,14 +37,10 @@ class TestController extends Controller implements TestOnly
|
||||
$field->getConfig()->addComponent(new GridFieldAddNewButton('toolbar-header-right'));
|
||||
$field->getConfig()->addComponent(new GridFieldViewButton());
|
||||
$field->getConfig()->addComponent(new GridFieldEditButton());
|
||||
/**
|
||||
* @skipUpgrade
|
||||
*/
|
||||
/** @skipUpgrade */
|
||||
$field->getConfig()->addComponent($gridFieldForm = new GridFieldDetailForm($this, 'Form'));
|
||||
$field->getConfig()->addComponent(new GridFieldEditButton());
|
||||
/**
|
||||
* @skipUpgrade
|
||||
*/
|
||||
/** @skipUpgrade */
|
||||
return new Form($this, 'Form', new FieldList($field), new FieldList());
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,11 @@
|
||||
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\Tests\DBHTMLTextTest\TestShortcode;
|
||||
@ -217,26 +218,24 @@ class DBHTMLTextTest extends SapphireTest
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
/**
|
||||
* @var DBHTMLText $field
|
||||
*/
|
||||
$field = Object::create_from_string("HTMLFragment(['whitelist' => 'link'])", 'MyField');
|
||||
/** @var DBHTMLText $field */
|
||||
$field = Injector::inst()->create("HTMLFragment(['whitelist' => 'link'])", 'MyField');
|
||||
$this->assertEquals(['link'], $field->getWhitelist());
|
||||
$field = Object::create_from_string("HTMLFragment(['whitelist' => 'link,a'])", 'MyField');
|
||||
$field = Injector::inst()->create("HTMLFragment(['whitelist' => 'link,a'])", 'MyField');
|
||||
$this->assertEquals(['link', 'a'], $field->getWhitelist());
|
||||
$field = Object::create_from_string("HTMLFragment(['whitelist' => ['link', 'a']])", 'MyField');
|
||||
$field = Injector::inst()->create("HTMLFragment(['whitelist' => ['link', 'a']])", 'MyField');
|
||||
$this->assertEquals(['link', 'a'], $field->getWhitelist());
|
||||
$field = Object::create_from_string("HTMLFragment", 'MyField');
|
||||
$field = Injector::inst()->create("HTMLFragment", 'MyField');
|
||||
$this->assertEmpty($field->getWhitelist());
|
||||
|
||||
// Test shortcodes
|
||||
$field = Object::create_from_string("HTMLFragment(['shortcodes' => true])", 'MyField');
|
||||
$field = Injector::inst()->create("HTMLFragment(['shortcodes' => true])", 'MyField');
|
||||
$this->assertEquals(true, $field->getProcessShortcodes());
|
||||
$field = Object::create_from_string("HTMLFragment(['shortcodes' => false])", 'MyField');
|
||||
$field = Injector::inst()->create("HTMLFragment(['shortcodes' => false])", 'MyField');
|
||||
$this->assertEquals(false, $field->getProcessShortcodes());
|
||||
|
||||
// Mix options
|
||||
$field = Object::create_from_string("HTMLFragment(['shortcodes' => true, 'whitelist' => ['a'])", 'MyField');
|
||||
$field = Injector::inst()->create("HTMLFragment(['shortcodes' => true, 'whitelist' => ['a'])", 'MyField');
|
||||
$this->assertEquals(true, $field->getProcessShortcodes());
|
||||
$this->assertEquals(['a'], $field->getWhitelist());
|
||||
}
|
||||
@ -553,7 +552,7 @@ class DBHTMLTextTest extends SapphireTest
|
||||
$field->Plain()
|
||||
);
|
||||
Config::nest();
|
||||
Config::inst()->update('SilverStripe\\Control\\Director', 'alternate_base_url', 'http://example.com/');
|
||||
Director::config()->set('alternate_base_url', 'http://example.com/');
|
||||
$this->assertEquals(
|
||||
'<p>Replaced short code with this. <a href="http://example.com/home">home</a></p>',
|
||||
$field->AbsoluteLinks()
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\FieldType\DBString;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
@ -24,10 +24,8 @@ class DBStringTest extends SapphireTest
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
/**
|
||||
* @var DBString $dbField
|
||||
*/
|
||||
$dbField = Object::create_from_string(
|
||||
/** @var DBString $dbField */
|
||||
$dbField = Injector::inst()->create(
|
||||
DBStringTest\MyStringField::class."(['default' => 'Here is my default text'])",
|
||||
'Myfield'
|
||||
);
|
||||
@ -42,9 +40,11 @@ class DBStringTest extends SapphireTest
|
||||
*/
|
||||
public function testLowerCase()
|
||||
{
|
||||
/** @var MyStringField $field */
|
||||
$field = DBField::create_field(MyStringField::class, 'This is a TEST!');
|
||||
$this->assertEquals(
|
||||
'this is a test!',
|
||||
DBField::create_field(MyStringField::class, 'This is a TEST!')->LowerCase()
|
||||
$field->LowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
@ -53,9 +53,11 @@ class DBStringTest extends SapphireTest
|
||||
*/
|
||||
public function testUpperCase()
|
||||
{
|
||||
/** @var MyStringField $field */
|
||||
$field = DBField::create_field(MyStringField::class, 'This is a TEST!');
|
||||
$this->assertEquals(
|
||||
'THIS IS A TEST!',
|
||||
DBField::create_field(MyStringField::class, 'This is a TEST!')->UpperCase()
|
||||
$field->UpperCase()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\DataObjectSchema;
|
||||
@ -139,7 +139,7 @@ class DataObjectSchemaTest extends SapphireTest
|
||||
);
|
||||
|
||||
$this->assertNull(
|
||||
$schema->tableForField(Object::class, 'Title')
|
||||
$schema->tableForField(ClassInfo::class, 'Title')
|
||||
);
|
||||
|
||||
// Test fixed fields
|
||||
|
@ -619,17 +619,17 @@ class DataObjectTest extends SapphireTest
|
||||
|
||||
// Set the favourite team for fan1
|
||||
$fan1->setField('FavouriteID', $team1->ID);
|
||||
$fan1->setField('FavouriteClass', $team1->class);
|
||||
$fan1->setField('FavouriteClass', get_class($team1));
|
||||
|
||||
$this->assertEquals($team1->ID, $fan1->Favourite()->ID, 'The team is assigned to fan 1');
|
||||
$this->assertInstanceOf($team1->class, $fan1->Favourite(), 'The team is assigned to fan 1');
|
||||
$this->assertInstanceOf(get_class($team1), $fan1->Favourite(), 'The team is assigned to fan 1');
|
||||
$this->assertEquals(
|
||||
$team1->ID,
|
||||
$fan1->getComponent('Favourite')->ID,
|
||||
'The team exists through the component getter'
|
||||
);
|
||||
$this->assertInstanceOf(
|
||||
$team1->class,
|
||||
get_class($team1),
|
||||
$fan1->getComponent('Favourite'),
|
||||
'The team exists through the component getter'
|
||||
);
|
||||
@ -847,10 +847,10 @@ class DataObjectTest extends SapphireTest
|
||||
// Test for polymorphic has_one relations
|
||||
$fan = $this->objFromFixture(DataObjectTest\Fan::class, 'fan1');
|
||||
$fan->FavouriteID = $team->ID;
|
||||
$fan->FavouriteClass = $team->class;
|
||||
$fan->FavouriteClass = DataObjectTest\Team::class;
|
||||
$this->assertNotNull($fan->Favourite());
|
||||
$this->assertEquals($team->ID, $fan->Favourite()->ID);
|
||||
$this->assertInstanceOf($team->class, $fan->Favourite());
|
||||
$this->assertInstanceOf(DataObjectTest\Team::class, $fan->Favourite());
|
||||
}
|
||||
|
||||
public function testFieldNamesThatMatchMethodNamesWork()
|
||||
@ -1434,26 +1434,25 @@ class DataObjectTest extends SapphireTest
|
||||
$equipmentSuppliers = $team->EquipmentSuppliers();
|
||||
|
||||
// Check that DataObject::many_many() works as expected
|
||||
list($relationClass, $class, $targetClass, $parentField, $childField, $joinTable)
|
||||
= DataObject::getSchema()->manyManyComponent(DataObjectTest\Team::class, 'Sponsors');
|
||||
$this->assertEquals(ManyManyList::class, $relationClass);
|
||||
$manyManyComponent = DataObject::getSchema()->manyManyComponent(DataObjectTest\Team::class, 'Sponsors');
|
||||
$this->assertEquals(ManyManyList::class, $manyManyComponent['relationClass']);
|
||||
$this->assertEquals(
|
||||
DataObjectTest\Team::class,
|
||||
$class,
|
||||
$manyManyComponent['parentClass'],
|
||||
'DataObject::many_many() didn\'t find the correct base class'
|
||||
);
|
||||
$this->assertEquals(
|
||||
DataObjectTest\EquipmentCompany::class,
|
||||
$targetClass,
|
||||
$manyManyComponent['childClass'],
|
||||
'DataObject::many_many() didn\'t find the correct target class for the relation'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'DataObjectTest_EquipmentCompany_SponsoredTeams',
|
||||
$joinTable,
|
||||
$manyManyComponent['join'],
|
||||
'DataObject::many_many() didn\'t find the correct relation table'
|
||||
);
|
||||
$this->assertEquals('DataObjectTest_TeamID', $parentField);
|
||||
$this->assertEquals('DataObjectTest_EquipmentCompanyID', $childField);
|
||||
$this->assertEquals('DataObjectTest_TeamID', $manyManyComponent['parentField']);
|
||||
$this->assertEquals('DataObjectTest_EquipmentCompanyID', $manyManyComponent['childField']);
|
||||
|
||||
// Check that ManyManyList still works
|
||||
$this->assertEquals(2, $sponsors->count(), 'Rows are missing from relation');
|
||||
@ -1918,11 +1917,15 @@ class DataObjectTest extends SapphireTest
|
||||
|
||||
// Test belongs_to assignment
|
||||
$company->OwnerID = $ceo->ID;
|
||||
$company->OwnerClass = $ceo->class;
|
||||
$company->OwnerClass = DataObjectTest\CEO::class;
|
||||
$company->write();
|
||||
|
||||
$this->assertEquals($company->ID, $ceo->CompanyOwned()->ID, 'belongs_to returns the right results.');
|
||||
$this->assertEquals($company->class, $ceo->CompanyOwned()->class, 'belongs_to returns the right results.');
|
||||
$this->assertInstanceOf(
|
||||
DataObjectTest\Company::class,
|
||||
$ceo->CompanyOwned(),
|
||||
'belongs_to returns the right results.'
|
||||
);
|
||||
|
||||
// Test automatic creation of class where no assigment exists
|
||||
$ceo = new DataObjectTest\CEO();
|
||||
|
@ -2,11 +2,7 @@
|
||||
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class ManyManyListExtensionTest extends SapphireTest
|
||||
{
|
||||
@ -26,9 +22,10 @@ class ManyManyListExtensionTest extends SapphireTest
|
||||
// This extends ManyManyListTest_Secondary with the secondary extension that adds the relationship back
|
||||
// to the primary. The instance from the fixture is ManyManyListTest_SecondarySub, deliberately a sub-class of
|
||||
// the extended class.
|
||||
Object::add_extension(ManyManyListTest\Secondary::class, ManyManyListTest\IndirectSecondaryExtension::class);
|
||||
ManyManyListTest\Secondary::add_extension(ManyManyListTest\IndirectSecondaryExtension::class);
|
||||
|
||||
// Test from the primary (not extended) to the secondary (which is extended)
|
||||
/** @var ManyManyListTest\IndirectPrimary $primary */
|
||||
$primary = $this->objFromFixture(ManyManyListTest\IndirectPrimary::class, 'manymany_extra_primary');
|
||||
$secondaries = $primary->Secondary();
|
||||
$extraFields = $secondaries->getExtraFields();
|
||||
@ -37,6 +34,7 @@ class ManyManyListExtensionTest extends SapphireTest
|
||||
$this->assertTrue(isset($extraFields['DocumentSort']), 'has DocumentSort');
|
||||
|
||||
// Test from the secondary (which is extended) to the primary (not extended)
|
||||
/** @var ManyManyListTest\SecondarySub|ManyManyListTest\IndirectSecondaryExtension $secondary */
|
||||
$secondary = $this->objFromFixture(ManyManyListTest\SecondarySub::class, 'manymany_extra_secondary');
|
||||
|
||||
$primaries = $secondary->Primary();
|
||||
|
@ -4,11 +4,14 @@ namespace SilverStripe\ORM\Tests\ManyManyListTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
|
||||
/**
|
||||
* A data object that implements the primary side of a many_many (where the extra fields are
|
||||
* defined.) The many-many refers to ManyManyListTest_Secondary rather than ManyManyListTest_SecondarySub
|
||||
* by design, because we're trying to test that a subclass instance picks up the extra fields of it's parent.
|
||||
*
|
||||
* @method ManyManyList Secondary()
|
||||
*/
|
||||
class IndirectPrimary extends DataObject implements TestOnly
|
||||
{
|
||||
|
@ -4,10 +4,13 @@ namespace SilverStripe\ORM\Tests\ManyManyListTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
|
||||
/**
|
||||
* An extension that is applied to ManyManyListTest_Secondary that
|
||||
* implements the other side of the many-many relationship.
|
||||
*
|
||||
* @method ManyManyList Primary()
|
||||
*/
|
||||
class IndirectSecondaryExtension extends DataExtension implements TestOnly
|
||||
{
|
||||
|
@ -160,12 +160,12 @@ class ManyManyThroughListTest extends SapphireTest
|
||||
// Parent components
|
||||
$this->assertEquals(
|
||||
[
|
||||
ManyManyThroughList::class,
|
||||
ManyManyThroughListTest\TestObject::class,
|
||||
ManyManyThroughListTest\Item::class,
|
||||
'ParentID',
|
||||
'ChildID',
|
||||
ManyManyThroughListTest\JoinObject::class
|
||||
'relationClass' => ManyManyThroughList::class,
|
||||
'parentClass' => ManyManyThroughListTest\TestObject::class,
|
||||
'childClass' => ManyManyThroughListTest\Item::class,
|
||||
'parentField' => 'ParentID',
|
||||
'childField' => 'ChildID',
|
||||
'join' => ManyManyThroughListTest\JoinObject::class
|
||||
],
|
||||
$schema->manyManyComponent(ManyManyThroughListTest\TestObject::class, 'Items')
|
||||
);
|
||||
@ -173,12 +173,12 @@ class ManyManyThroughListTest extends SapphireTest
|
||||
// Belongs_many_many is the same, but with parent/child substituted
|
||||
$this->assertEquals(
|
||||
[
|
||||
ManyManyThroughList::class,
|
||||
ManyManyThroughListTest\Item::class,
|
||||
ManyManyThroughListTest\TestObject::class,
|
||||
'ChildID',
|
||||
'ParentID',
|
||||
ManyManyThroughListTest\JoinObject::class
|
||||
'relationClass' => ManyManyThroughList::class,
|
||||
'parentClass' => ManyManyThroughListTest\Item::class,
|
||||
'childClass' => ManyManyThroughListTest\TestObject::class,
|
||||
'parentField' => 'ChildID',
|
||||
'childField' => 'ParentID',
|
||||
'join' => ManyManyThroughListTest\JoinObject::class
|
||||
],
|
||||
$schema->manyManyComponent(ManyManyThroughListTest\Item::class, 'Objects')
|
||||
);
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace SilverStripe\Security\Tests;
|
||||
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
use SilverStripe\Control\Cookie;
|
||||
use SilverStripe\i18n\i18n;
|
||||
@ -27,14 +26,9 @@ class MemberTest extends FunctionalTest
|
||||
|
||||
protected $orig = array();
|
||||
|
||||
protected static $illegal_extensions = array(
|
||||
Member::class => array(
|
||||
// TODO Coupling with modules, this should be resolved by automatically
|
||||
// removing all applied extensions before a unit test
|
||||
'ForumRole',
|
||||
'OpenIDAuthenticatedRole'
|
||||
)
|
||||
);
|
||||
protected static $illegal_extensions = [
|
||||
Member::class => '*',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -537,7 +531,6 @@ class MemberTest extends FunctionalTest
|
||||
*/
|
||||
public function testCanManipulateOwnRecord()
|
||||
{
|
||||
$extensions = $this->removeExtensions(Object::get_extensions(Member::class));
|
||||
$member = $this->objFromFixture(Member::class, 'test');
|
||||
$member2 = $this->objFromFixture(Member::class, 'staffmember');
|
||||
|
||||
@ -560,13 +553,11 @@ class MemberTest extends FunctionalTest
|
||||
$this->assertFalse($member->canDelete());
|
||||
$this->assertFalse($member->canEdit());
|
||||
|
||||
$this->addExtensions($extensions);
|
||||
$this->session()->inst_set('loggedInAs', null);
|
||||
}
|
||||
|
||||
public function testAuthorisedMembersCanManipulateOthersRecords()
|
||||
{
|
||||
$extensions = $this->removeExtensions(Object::get_extensions(Member::class));
|
||||
$member = $this->objFromFixture(Member::class, 'test');
|
||||
$member2 = $this->objFromFixture(Member::class, 'staffmember');
|
||||
|
||||
@ -575,14 +566,10 @@ class MemberTest extends FunctionalTest
|
||||
$this->assertTrue($member2->canView());
|
||||
$this->assertTrue($member2->canDelete());
|
||||
$this->assertTrue($member2->canEdit());
|
||||
|
||||
$this->addExtensions($extensions);
|
||||
$this->session()->inst_set('loggedInAs', null);
|
||||
}
|
||||
|
||||
public function testExtendedCan()
|
||||
{
|
||||
$extensions = $this->removeExtensions(Object::get_extensions(Member::class));
|
||||
$member = $this->objFromFixture(Member::class, 'test');
|
||||
|
||||
/* Normal behaviour is that you can't view a member unless canView() on an extension returns true */
|
||||
@ -617,7 +604,6 @@ class MemberTest extends FunctionalTest
|
||||
$this->assertTrue($member4->canEdit());
|
||||
|
||||
Member::remove_extension(MemberTest\EditingAllowedDeletingDeniedExtension::class);
|
||||
$this->addExtensions($extensions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,6 @@ class TestPasswordValidator extends PasswordValidator
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->minLength(7);
|
||||
$this->checkHistoricalPasswords(6);
|
||||
$this->characterStrength(3, array('lowercase', 'uppercase', 'digits', 'punctuation'));
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class i18nOtherModule extends Object
|
||||
class i18nOtherModule
|
||||
{
|
||||
public function mymethod()
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class i18nTestModule extends DataObject implements TestOnly
|
||||
@ -20,7 +19,7 @@ class i18nTestModule extends DataObject implements TestOnly
|
||||
);
|
||||
}
|
||||
}
|
||||
class i18nTestModule_Addition extends Object
|
||||
class i18nTestModule_Addition
|
||||
{
|
||||
public function myAdditionalMethod()
|
||||
{
|
||||
|
@ -1,13 +1,9 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Core\Object;
|
||||
|
||||
class i18nTestSubModule extends Object
|
||||
class i18nTestSubModule
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
_t('i18nTestModule.OTHERENTITY', 'Other Entity');
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user