Merge pull request #6927 from open-sausages/pulls/4.0/remove-object

API Remove Object class
This commit is contained in:
Chris Joe 2017-05-23 15:15:01 +12:00 committed by GitHub
commit 44981de560
124 changed files with 993 additions and 980 deletions

View File

@ -56,6 +56,9 @@ before_script:
- phpenv config-rm xdebug.ini
- echo 'memory_limit = 2048M' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
# Temporarily update to 1.5.x-dev of composer
- composer self-update --snapshot
# Install composer dependencies
- composer validate
- composer install --prefer-dist

View File

@ -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`

View File

@ -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);

View File

@ -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

View File

@ -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);
@ -396,26 +400,22 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
} elseif ($this->template) {
$templates = $this->template;
} else {
// Add action-specific templates for inheritance chain
$templates = array();
if ($action && $action != 'index') {
$parentClass = $this->class;
while ($parentClass != __CLASS__) {
$templates[] = strtok($parentClass, '_') . '_' . $action;
$parentClass = get_parent_class($parentClass);
// Build templates based on class hierarchy
$actionTemplates = [];
$classTemplates = [];
$parentClass = static::class;
while ($parentClass !== parent::class) {
// _action templates have higher priority
if ($action && $action != 'index') {
$actionTemplates[] = strtok($parentClass, '_') . '_' . $action;
}
}
// Add controller templates for inheritance chain
$parentClass = $this->class;
while ($parentClass != __CLASS__) {
$templates[] = strtok($parentClass, '_');
// class templates have lower priority
$classTemplates[] = strtok($parentClass, '_');
$parentClass = get_parent_class($parentClass);
}
$templates[] = __CLASS__;
// remove duplicates
$templates = array_unique($templates);
// Add controller templates for inheritance chain
$templates = array_unique(array_merge($actionTemplates, $classTemplates));
}
return new SSViewer($templates);
@ -469,7 +469,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 +496,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
return true;
}
$parentClass = $this->class;
$parentClass = static::class;
$templates = array();
while ($parentClass != __CLASS__) {
@ -614,8 +614,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
);
}

View File

@ -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>';
}
/**

View File

@ -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());

View File

@ -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

View File

@ -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
);

View File

@ -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;
}
}

View File

@ -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'");
}

View File

@ -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

View File

@ -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;
}
/**

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
/**

View File

@ -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;
}
}

View File

@ -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;
}
/**

View File

@ -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;
}
/**

View File

@ -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';

View File

@ -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.

View File

@ -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();
}
/**

View File

@ -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();
}
/**

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -83,8 +83,8 @@ class FunctionalTest extends SapphireTest
protected function setUp()
{
// Skip calling FunctionalTest directly.
if (get_class($this) == __CLASS__) {
$this->markTestSkipped(sprintf('Skipping %s ', get_class($this)));
if (static::class == __CLASS__) {
$this->markTestSkipped(sprintf('Skipping %s ', static::class));
}
parent::setUp();

View File

@ -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,8 +243,8 @@ class SapphireTest extends PHPUnit_Framework_TestCase
}
// We cannot run the tests on this abstract class.
if (get_class($this) == __CLASS__) {
$this->markTestSkipped(sprintf('Skipping %s ', get_class($this)));
if (static::class == __CLASS__) {
$this->markTestSkipped(sprintf('Skipping %s ', static::class));
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;
@ -559,9 +563,9 @@ class SapphireTest extends PHPUnit_Framework_TestCase
*/
protected function getCurrentAbsolutePath()
{
$filename = self::$test_class_manifest->getItemPath(get_class($this));
$filename = self::$test_class_manifest->getItemPath(static::class);
if (!$filename) {
throw new LogicException("getItemPath returned null for " . get_class($this));
throw new LogicException("getItemPath returned null for " . static::class);
}
return dirname($filename);
}

View File

@ -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();
}
/**

View File

@ -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 = get_class($list[$name]);
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) . "&nbsp;</li>";
}

View File

@ -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;

View File

@ -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());

View File

@ -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");
}

View File

@ -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>";
}

View File

@ -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
);

View File

@ -213,7 +213,7 @@ class FormRequestHandler extends RequestHandler
) {
return $this->httpError(
403,
sprintf('Action "%s" not allowed on form request handler (Class: "%s")', $funcName, get_class($this))
sprintf('Action "%s" not allowed on form request handler (Class: "%s")', $funcName, static::class)
);
}
@ -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"
);
}

View File

@ -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),

View File

@ -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}'");
}
}

View File

@ -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();
}
/**

View File

@ -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';
}

View File

@ -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;

View File

@ -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;

View File

@ -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."
);
}

View File

@ -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;

View File

@ -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;

View File

@ -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
*

View File

@ -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

View File

@ -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();
}
/**

View File

@ -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>";
}

View File

@ -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);
}

View File

@ -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;
@ -356,7 +356,7 @@ abstract class DBSchemaManager
// Check if options changed
$tableOptionsChanged = false;
// Check for DB constant on the schema class
$dbIDName = sprintf('%s::ID', get_class($this));
$dbIDName = sprintf('%s::ID', static::class);
$dbID = defined($dbIDName) ? constant($dbIDName) : null;
if ($dbID && isset($options[$dbID])) {
if (preg_match('/ENGINE=([^\s]*)/', $options[$dbID], $alteredEngineMatches)) {
@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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, static::class);
} 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) {

View File

@ -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,
];
}

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -71,7 +71,7 @@ class DBPolymorphicForeignKey extends DBComposite
if ($value instanceof DataObject) {
$value = array(
'ID' => $value->ID,
'Class' => $value->class
'Class' => get_class($value),
);
}

View File

@ -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.");
}
/**

View File

@ -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'

View File

@ -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]);
}

View File

@ -98,8 +98,6 @@ class FulltextSearchable extends DataExtension
} else {
$this->searchFields = $searchFields;
}
parent::__construct();
}
public static function get_extra_config($class, $extensionClass, $args)

View File

@ -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

View File

@ -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
*/

View File

@ -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
*

View File

@ -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]/',

View File

@ -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,
[

View File

@ -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();
}
/**

View File

@ -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 {

View File

@ -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',

View File

@ -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)
{

View File

@ -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",

View File

@ -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

View File

@ -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
*/

View File

@ -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 {

View File

@ -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) {

View File

@ -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>";

View File

@ -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();

View File

@ -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();

View 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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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')
);
}
}

View 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();
}
}

View File

@ -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)

View File

@ -2,9 +2,7 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class CreateTest extends Object
class CreateTest extends BaseObject
{
public $constructArguments;

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class CreateTest2 extends Object
class CreateTest2 extends BaseObject
{
}

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class CreateTest3 extends Object
class CreateTest3 extends BaseObject
{
}

View File

@ -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,

View File

@ -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)
{

View File

@ -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()));

View File

@ -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)";

View File

@ -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(

View File

@ -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,

View File

@ -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',

View File

@ -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,

View File

@ -2,8 +2,6 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class ExtensionTest3 extends Object
class ExtensionTest3 extends BaseObject
{
}

View File

@ -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');
}

View File

@ -2,9 +2,7 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class T1A extends Object
class T1A extends BaseObject
{
public function testMethod()
{

View File

@ -2,9 +2,7 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class T1B extends Object
class T1B extends BaseObject
{
public function someMethod()
{

View File

@ -2,9 +2,7 @@
namespace SilverStripe\Core\Tests\ObjectTest;
use SilverStripe\Core\Object;
class T1C extends Object
class T1C extends BaseObject
{
public function t1cMethod()
{

View File

@ -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();

View File

@ -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
{
}

View File

@ -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());
}
}

View File

@ -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()

View File

@ -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()
);
}

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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
{

View File

@ -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
{

View File

@ -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')
);

View File

@ -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);
}
/**

View File

@ -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'));

View File

@ -1,8 +1,6 @@
<?php
use SilverStripe\Core\Object;
class i18nOtherModule extends Object
class i18nOtherModule
{
public function mymethod()
{

View File

@ -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()
{

View File

@ -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();
}
}