Skip to content

Commit

Permalink
move factories into theirs own container
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondřej Ešler committed Jul 10, 2020
1 parent c27c1bb commit c7a9bc2
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 21 deletions.
37 changes: 18 additions & 19 deletions src/ServiceContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,26 @@

namespace IW;

use IW\ServiceContainer\AliasFactory;
use IW\ServiceContainer\CallableFactory;
use IW\ServiceContainer\ClassnameFactory;
use IW\ServiceContainer\EmptyResultFromFactory;
use IW\ServiceContainer\FactoryContainer;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Throwable;

class ServiceContainer implements ContainerInterface
{
/** @var callable[] */
private $factories = [];
/** @var FactoryContainer */
private $factories;

/** @var mixed[] */
private $instances = [];

public function __construct()
{
$this->factories = new FactoryContainer();
}

/**
* Sets an alias for a dependency, it's useful for binding implementations
* to a interface. Container will resolve alias as late as possible.
Expand All @@ -40,7 +43,7 @@ class ServiceContainer implements ContainerInterface
*/
public function alias(string $alias, string $id): void
{
$this->factories[$alias] = new AliasFactory($id);
$this->factories->alias($alias, $id);
}

/**
Expand All @@ -55,32 +58,27 @@ public function alias(string $alias, string $id): void
*/
public function bind(string $id, callable $factory): void
{
$this->factories[$id] = new CallableFactory($factory);
$this->factories->bind($id, $factory);
}

public function factory(string $id): callable
{
if (isset($this->factories[$id])) {
return $this->factories[$id];
}

return $this->factories[$id] = new ClassnameFactory($id);
return $this->factories->get($id);
}

/**
* Finds an entry of the container by its identifier and returns it.
*
* @template T
* @param class-string<T> $id Identifier of the entry to look for.
*
* @return mixed Entry.
* @return T
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
* @throws ContainerExceptionInterface Error while retrieving the entry.
*
* @return T
* @template T
*/
public function get($id) // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
public function get($id) // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint,SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint,Generic.Files.LineLength.TooLong
{
if (isset($this->instances[$id])) {
return $this->instances[$id]; // try load a singleton if saved
Expand Down Expand Up @@ -110,7 +108,7 @@ public function has($id) // phpcs:ignore SlevomatCodingStandard.TypeHints.Parame
}

// a factory exists
if (isset($this->factories[$id])) {
if ($this->factories->has($id)) {
return true;
}

Expand All @@ -137,12 +135,13 @@ public function singleton(string $id)
/**
* Makes a new instance of a service. Dependencies are resolved from the container.
*
* @template T
* @param class-string<T> $id ID of entry we want to create new instance of
*
* @return T
*
* @template T
*/
public function make(string $id)
public function make(string $id) // phpcs:ignore SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint,Generic.Files.LineLength.TooLong
{
$instance = $this->factory($id)($this);

Expand Down
35 changes: 35 additions & 0 deletions src/ServiceContainer/FactoryContainer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace IW\ServiceContainer;

final class FactoryContainer
{
/** @var ServiceFactory[] */
private $factories = [];

public function alias(string $alias, string $id): void
{
$this->factories[$alias] = new AliasFactory($id);
}

public function bind(string $id, callable $factory): void
{
$this->factories[$id] = new CallableFactory($factory);
}

public function get(string $id): ServiceFactory
{
if (isset($this->factories[$id])) {
return $this->factories[$id];
}

return $this->factories[$id] = new ClassnameFactory($id);
}

public function has(string $id): bool
{
return isset($this->factories[$id]);
}
}
4 changes: 2 additions & 2 deletions tests/ServiceContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function testBindingCustomFactory(): void
*/
public function testHasMethod(string $id, bool $has): void
{
$container = $this->createPartialMock(ServiceContainer::class, ['make']);
$container = $this->createTestProxy(ServiceContainer::class, ['make']);
$container->expects($this->never())->method('make');

if ($has) {
Expand All @@ -131,7 +131,7 @@ public function testHasASingleton(): void

public function testHasAFactory(): void
{
$container = $this->createPartialMock(ServiceContainer::class, ['make', 'factory']);
$container = $this->createTestProxy(ServiceContainer::class, ['make', 'factory']);
$container->expects($this->never())->method('make');
$container->expects($this->never())->method('factory');

Expand Down

0 comments on commit c7a9bc2

Please sign in to comment.