Skip to content
This repository has been archived by the owner on Jul 28, 2023. It is now read-only.
/ container Public archive
generated from spaceonfire/skeleton

Commit

Permalink
Merge pull request #3 from spaceonfire/definition-tags
Browse files Browse the repository at this point in the history
feat: support definition tags
  • Loading branch information
tntrex authored Sep 23, 2020
2 parents dca148e + 6b8041d commit 9d33910
Show file tree
Hide file tree
Showing 19 changed files with 414 additions and 24 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip
- Nothing
-->

## [2.1.0] - 2020-09-23
### Added
- Support definition tags

## [2.0.1] - 2020-06-21
### Fixed
- Resolve definition in `Container` class using parent container
Expand Down
25 changes: 23 additions & 2 deletions src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace spaceonfire\Container;

use InvalidArgumentException;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Container\Argument\ArgumentResolver;
use spaceonfire\Container\Argument\ResolverInterface;
use spaceonfire\Container\Definition\DefinitionAggregate;
Expand Down Expand Up @@ -45,7 +46,7 @@ final class Container implements ContainerWithServiceProvidersInterface, Contain

/**
* Container constructor.
* @param DefinitionAggregateInterface $definitions
* @param DefinitionAggregateInterface|null $definitions
* @param ServiceProviderAggregateInterface|null $providers
*/
public function __construct(
Expand Down Expand Up @@ -127,7 +128,7 @@ public function get($id, array $arguments = [])
if ($this->providers->provides($id)) {
$this->providers->register($id);

if (!$this->definitions->hasDefinition($id)) {
if (!$this->definitions->hasDefinition($id) || $this->definitions->hasTag($id)) {
throw new ContainerException(sprintf('Service provider lied about providing (%s) service', $id));
}

Expand All @@ -152,4 +153,24 @@ public function invoke(callable $callable, array $arguments = [])
{
return ($this->callableInvoker)($callable, $arguments);
}

/**
* @inheritDoc
*/
public function hasTagged(string $tag): bool
{
return $this->definitions->hasTag($tag);
}

/**
* @inheritDoc
*/
public function getTagged(string $tag): CollectionInterface
{
if ($this->providers->provides($tag)) {
$this->providers->register($tag);
}

return $this->definitions->resolveTagged($tag, $this->getContainer());
}
}
7 changes: 2 additions & 5 deletions src/ContainerAwareTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ trait ContainerAwareTrait
protected $container;

/**
* Set a container
* @param ContainerInterface $container
* @return $this|ContainerAwareInterface
* @inheritDoc
*/
public function setContainer(ContainerInterface $container): ContainerAwareInterface
{
Expand All @@ -23,8 +21,7 @@ public function setContainer(ContainerInterface $container): ContainerAwareInter
}

/**
* Get the container
* @return ContainerInterface
* @inheritDoc
*/
public function getContainer(): ContainerInterface
{
Expand Down
34 changes: 34 additions & 0 deletions src/ContainerChain.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace spaceonfire\Container;

use Psr\Container\ContainerInterface as PsrContainerInterface;
use spaceonfire\Collection\Collection;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Container\Definition\DefinitionInterface;
use spaceonfire\Container\Exception\ContainerException;
use spaceonfire\Container\Exception\NotFoundException;
Expand Down Expand Up @@ -185,4 +187,36 @@ public function addServiceProvider($provider): ContainerWithServiceProvidersInte

throw new ContainerException('No container provided with support of service providers');
}

/**
* @inheritDoc
*/
public function hasTagged(string $tag): bool
{
foreach ($this->chain as $container) {
if ($container instanceof ContainerInterface && $container->hasTagged($tag)) {
return true;
}
}

return false;
}

/**
* @inheritDoc
*/
public function getTagged(string $tag): CollectionInterface
{
$result = new Collection();

foreach ($this->chain as $container) {
if (!$container instanceof ContainerInterface) {
continue;
}

$result = $result->merge($container->getTagged($tag));
}

return $result;
}
}
13 changes: 13 additions & 0 deletions src/ContainerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace spaceonfire\Container;

use Psr\Container\ContainerInterface as PsrContainerInterface;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Container\Definition\DefinitionInterface;

interface ContainerInterface extends PsrContainerInterface
Expand Down Expand Up @@ -47,4 +48,16 @@ public function add(string $id, $concrete = null, bool $shared = false): Definit
* @return DefinitionInterface
*/
public function share(string $id, $concrete = null): DefinitionInterface;

/**
* @param string $tag
* @return bool
*/
public function hasTagged(string $tag): bool;

/**
* @param string $tag
* @return mixed[]|CollectionInterface
*/
public function getTagged(string $tag): CollectionInterface;
}
29 changes: 29 additions & 0 deletions src/Definition/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ final class Definition implements DefinitionInterface
* @var array[]
*/
private $methods = [];
/**
* @var array<string,string>
*/
private $tags = [];
/**
* @var object|null
*/
Expand Down Expand Up @@ -152,4 +156,29 @@ public function resolve(ContainerInterface $container)

return $this->resolved = $resolved;
}

/**
* @inheritDoc
*/
public function addTag(string $tag): DefinitionInterface
{
$this->tags[$tag] = $tag;
return $this;
}

/**
* @inheritDoc
*/
public function hasTag(string $tag): bool
{
return array_key_exists($tag, $this->tags);
}

/**
* @inheritDoc
*/
public function getTags(): array
{
return array_keys($this->tags);
}
}
39 changes: 39 additions & 0 deletions src/Definition/DefinitionAggregate.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace spaceonfire\Container\Definition;

use spaceonfire\Collection\AbstractCollectionDecorator;
use spaceonfire\Collection\Collection;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Collection\IndexedCollection;
use spaceonfire\Collection\TypedCollection;
Expand All @@ -18,6 +19,10 @@ final class DefinitionAggregate extends AbstractCollectionDecorator implements D
* @var DefinitionFactoryInterface
*/
private $definitionFactory;
/**
* @var array<string,string>
*/
private $tags = [];

/**
* DefinitionAggregate constructor.
Expand Down Expand Up @@ -115,4 +120,38 @@ public function resolve(string $id, ContainerInterface $container)
{
return $this->getDefinition($id)->resolve($container);
}

/**
* @inheritDoc
*/
public function hasTag(string $tag): bool
{
if (array_key_exists($tag, $this->tags)) {
return true;
}

/** @var DefinitionInterface $definition */
foreach ($this->getIterator() as $definition) {
if ($definition->hasTag($tag)) {
$this->tags[$tag] = $tag;
return true;
}
}

return false;
}

/**
* @inheritDoc
*/
public function resolveTagged(string $tag, ContainerInterface $container): CollectionInterface
{
return (new Collection($this->getIterator()))
->filter(static function (DefinitionInterface $definition) use ($tag) {
return $definition->hasTag($tag);
})
->map(static function (DefinitionInterface $definition) use ($container) {
return $definition->resolve($container);
});
}
}
16 changes: 16 additions & 0 deletions src/Definition/DefinitionAggregateInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace spaceonfire\Container\Definition;

use IteratorAggregate;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Container\ContainerInterface;

interface DefinitionAggregateInterface extends IteratorAggregate
Expand Down Expand Up @@ -46,4 +47,19 @@ public function makeDefinition(string $abstract, $concrete, bool $shared = false
* @return mixed
*/
public function resolve(string $id, ContainerInterface $container);

/**
* Checks whether tag exists as definition.
* @param string $tag
* @return bool
*/
public function hasTag(string $tag): bool;

/**
* Resolve and build a collection of concrete values by given tag.
* @param string $tag
* @param ContainerInterface $container
* @return mixed[]|CollectionInterface
*/
public function resolveTagged(string $tag, ContainerInterface $container): CollectionInterface;
}
24 changes: 22 additions & 2 deletions src/Definition/DefinitionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ public function addArgument(Argument $argument): self;
public function addArguments(array $arguments): self;

/**
* Add a method to be invoked
* Add a method to be invoked.
* @param string $method
* @param array<string,mixed> $arguments
* @return $this
*/
public function addMethodCall(string $method, array $arguments = []): self;

/**
* Add multiple methods to be invoked
* Add multiple methods to be invoked.
* @param array<string,array<string,mixed>> $methods
* @return $this
*/
Expand All @@ -62,4 +62,24 @@ public function addMethodCalls(array $methods = []): self;
* @return mixed
*/
public function resolve(ContainerInterface $container);

/**
* Add a tag to the definition.
* @param string $tag
* @return $this
*/
public function addTag(string $tag): self;

/**
* Does the definition have a tag?
* @param string $tag
* @return bool
*/
public function hasTag(string $tag): bool;

/**
* Returns tags of the definition.
* @return string[]
*/
public function getTags(): array;
}
20 changes: 20 additions & 0 deletions src/Definition/DefinitionTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace spaceonfire\Container\Definition;

/**
* List of common definitions tags. Use these constants to prevent collision that can be caused by typos in tag names.
* Feel free to suggest tag names of your choice.
* @package spaceonfire\Container\Definition
*/
final class DefinitionTag
{
/**
* Mark symfony/console commands
* @var string
* @see https://symfony.com/doc/current/reference/dic_tags.html#console-command
*/
public const CONSOLE_COMMAND = 'console.command';
}
18 changes: 18 additions & 0 deletions src/ReflectionContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace spaceonfire\Container;

use BadMethodCallException;
use spaceonfire\Collection\Collection;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Container\Argument\ArgumentResolver;
use spaceonfire\Container\Argument\ResolverInterface;
use spaceonfire\Container\Definition\DefinitionInterface;
Expand Down Expand Up @@ -97,4 +99,20 @@ public function share(string $id, $concrete = null): DefinitionInterface
{
throw new BadMethodCallException('ReflectionContainer does not support definitions');
}

/**
* @inheritDoc
*/
public function hasTagged(string $tag): bool
{
return false;
}

/**
* @inheritDoc
*/
public function getTagged(string $tag): CollectionInterface
{
return new Collection();
}
}
Loading

0 comments on commit 9d33910

Please sign in to comment.