Skip to content

Commit

Permalink
Updated 'ServiceFactory' to allow pre-made objects in the config.
Browse files Browse the repository at this point in the history
  • Loading branch information
danbettles committed Sep 28, 2022
1 parent d04d614 commit 1e41706
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 18 deletions.
28 changes: 15 additions & 13 deletions src/ServiceFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
namespace DanBettles\Marigold;

use Closure;
use InvalidArgumentException;
use OutOfBoundsException;
use RangeException;

use function array_key_exists;
use function class_exists;
Expand Down Expand Up @@ -49,9 +49,9 @@ public function contains(string $id): bool
* Gets a service by its ID.
*
* @throws OutOfBoundsException If the service does not exist.
* @throws RangeException If the service class does not exist.
* @throws RangeException If the factory for the service does not return an object.
* @throws RangeException If the config for the service is invalid.
* @throws InvalidArgumentException If the service class does not exist.
* @throws InvalidArgumentException If the factory for the service does not return an object.
* @throws InvalidArgumentException If the config for the service is invalid.
*/
public function get(string $id): object
{
Expand All @@ -60,24 +60,26 @@ public function get(string $id): object
}

if (!array_key_exists($id, $this->services)) {
$classNameOrClosure = $this->getConfig()[$id];
$resolvesToObject = $this->getConfig()[$id];

$service = null;

if (is_string($classNameOrClosure)) {
if (!class_exists($classNameOrClosure)) {
throw new RangeException("The class for service `{$id}`, `{$classNameOrClosure}`, does not exist.");
if (is_string($resolvesToObject)) {
if (!class_exists($resolvesToObject)) {
throw new InvalidArgumentException("The class for service `{$id}`, `{$resolvesToObject}`, does not exist.");
}

$service = new $classNameOrClosure();
} elseif ($classNameOrClosure instanceof Closure) {
$service = $classNameOrClosure();
$service = new $resolvesToObject();
} elseif ($resolvesToObject instanceof Closure) {
$service = $resolvesToObject();

if (!is_object($service)) {
throw new RangeException("The factory for service `{$id}` does not return an object.");
throw new InvalidArgumentException("The factory for service `{$id}` does not return an object.");
}
} elseif (is_object($resolvesToObject)) {
$service = $resolvesToObject;
} else {
throw new RangeException("The config for service `{$id}` is invalid: it must be a class-name or a closure.");
throw new InvalidArgumentException("The config for service `{$id}` is invalid: it must be a class-name, closure, or an object.");
}

$this->services[$id] = $service;
Expand Down
17 changes: 12 additions & 5 deletions tests/src/ServiceFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use Closure;
use DanBettles\Marigold\AbstractTestCase;
use DanBettles\Marigold\ServiceFactory;
use InvalidArgumentException;
use OutOfBoundsException;
use RangeException;
use stdClass;

class ServiceFactoryTest extends AbstractTestCase
Expand Down Expand Up @@ -44,6 +44,13 @@ public function providesConfig(): array
],
'foo',
],
[
stdClass::class,
[
'foo' => new stdClass(),
],
'foo',
],
];
}

Expand Down Expand Up @@ -80,7 +87,7 @@ public function testGetThrowsAnExceptionIfAServiceClassDoesNotExist(): void
/** @phpstan-var class-string */
$nonExistentClassName = __CLASS__ . '\\NonExistent';

$this->expectException(RangeException::class);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("The class for service `class_name`, `{$nonExistentClassName}`, does not exist.");

(new ServiceFactory([
Expand All @@ -92,7 +99,7 @@ public function testGetThrowsAnExceptionIfAServiceClassDoesNotExist(): void

public function testGetThrowsAnExceptionIfAServiceFactoryClosureDoesNotReturnAnObject(): void
{
$this->expectException(RangeException::class);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('The factory for service `closure` does not return an object.');

(new ServiceFactory([
Expand Down Expand Up @@ -137,8 +144,8 @@ public function testGetThrowsAnExceptionIfAServiceConfigurationDoesNotResolveToA
array $invalidConfig,
string $id
): void {
$this->expectException(RangeException::class);
$this->expectExceptionMessage("The config for service `{$id}` is invalid: it must be a class-name or a closure.");
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("The config for service `{$id}` is invalid: it must be a class-name, closure, or an object.");

(new ServiceFactory($invalidConfig))->get($id);
}
Expand Down

0 comments on commit 1e41706

Please sign in to comment.