FIX Allow passing objects to InjectionCreator::create()

Co-authored-by: Nate Devereux <nate@daveclark.co.nz>
This commit is contained in:
Steve Boyd 2022-10-19 18:04:48 +13:00
parent 0b80643210
commit e3a6cad8a8
2 changed files with 43 additions and 2 deletions

View File

@ -2,18 +2,36 @@
namespace SilverStripe\Core\Injector; namespace SilverStripe\Core\Injector;
use InvalidArgumentException;
/** /**
* A class for creating new objects by the injector. * A class for creating new objects by the injector.
*/ */
class InjectionCreator implements Factory 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 = []) 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"); throw new InjectorNotFoundException("Class {$class} does not exist");
} }
// Ensure there are no string keys as they cannot be unpacked with the `...` operator // 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); return new $class(...$values);
} }
} }

View File

@ -1065,4 +1065,27 @@ class InjectorTest extends SapphireTest
Injector::unnest(); Injector::unnest();
$this->nestingLevel--; $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());
}
} }