Merge pull request #10555 from creative-commoners/pulls/4.11/inject-objects

This commit is contained in:
Michal Kleiner 2022-10-19 21:07:48 +13:00 committed by GitHub
commit 0c207c3079
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 2 deletions

View File

@ -2,18 +2,36 @@
namespace SilverStripe\Core\Injector;
use InvalidArgumentException;
/**
* A class for creating new objects by the injector.
*/
class InjectionCreator implements Factory
{
/**
* Create a new instance of a class
*
* Passing an object for $class will result from using an anonymous class in unit testing, e.g.
* Injector::inst()->load([SomeClass::class => ['class' => new class { ... }]]);
*
* @param string|object $class - string: The FQCN of the class, object: A class instance
*/
public function create($class, array $params = [])
{
if (!class_exists($class ?? '')) {
if (is_object($class ?? '')) {
$class = get_class($class);
}
if (!is_string($class ?? '')) {
throw new InvalidArgumentException('$class parameter must be a string or an object');
}
if (!class_exists($class)) {
throw new InjectorNotFoundException("Class {$class} does not exist");
}
// Ensure there are no string keys as they cannot be unpacked with the `...` operator
$values = array_values($params ?? []);
$values = array_values($params);
return new $class(...$values);
}
}

View File

@ -1065,4 +1065,27 @@ class InjectorTest extends SapphireTest
Injector::unnest();
$this->nestingLevel--;
}
public function testAnonymousClass()
{
Injector::inst()->load([
'Some\\Project\\Class' => [
// the php anonymous class syntax will instantiate a new anonymous class object, with ('abc')
// passed to the constructor
'class' => new class ('abc') {
private string $property;
public function __construct(string $value)
{
$this->property = $value;
}
public function foo(): string
{
return $this->property;
}
}
],
]);
// assert that Injector creates a new instance of the anonymous class, with ('def') passed to the constructor
$this->assertSame('def', Injector::inst()->create('Some\\Project\\Class', 'def')->foo());
}
}