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 #6 from spaceonfire/composite-container-priority
Browse files Browse the repository at this point in the history
Composite containers priority
  • Loading branch information
tntrex authored Oct 24, 2020
2 parents 9340688 + ce81663 commit ad6c687
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 48 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.3.0] - 2020-10-24
### Added
- Added priority option for containers in `spaceonfire\Container\CompositeContainer`.

## [2.2.0] - 2020-10-22
### Deprecated
- Class `spaceonfire\Container\ContainerChain` renamed to `spaceonfire\Container\CompositeContainer`.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
"dev-master": "2.3-dev"
}
},
"config": {
Expand Down
67 changes: 55 additions & 12 deletions src/CompositeContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

namespace spaceonfire\Container;

use Generator;
use IteratorAggregate;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use spaceonfire\Collection\ArrayHelper;
use spaceonfire\Collection\Collection;
use spaceonfire\Collection\CollectionInterface;
use spaceonfire\Container\Definition\DefinitionInterface;
use spaceonfire\Container\Exception\ContainerException;
use spaceonfire\Container\Exception\NotFoundException;
use Traversable;

/**
* Class CompositeContainer
Expand All @@ -20,12 +24,14 @@
* @package spaceonfire\Container
* @final
*/
class CompositeContainer implements ContainerWithServiceProvidersInterface, ContainerAwareInterface
class CompositeContainer implements ContainerWithServiceProvidersInterface, ContainerAwareInterface, IteratorAggregate
{
use ContainerAwareTrait;

private const DEFAULT_PRIORITY = 999;

/**
* @var PsrContainerInterface[]
* @var array<int, PsrContainerInterface[]>
*/
private $containers = [];
/**
Expand All @@ -37,7 +43,7 @@ class CompositeContainer implements ContainerWithServiceProvidersInterface, Cont
* CompositeContainer constructor.
* @param PsrContainerInterface[] $containers
*/
public function __construct(iterable $containers)
public function __construct(iterable $containers = [])
{
$this->setContainer($this);
$this->addContainers($containers);
Expand All @@ -49,7 +55,7 @@ public function __construct(iterable $containers)
public function setContainer(ContainerInterface $container): ContainerAwareInterface
{
$this->container = $container;
foreach ($this->containers as $delegate) {
foreach ($this->getIterator() as $delegate) {
if ($delegate instanceof ContainerAwareInterface) {
$delegate->setContainer($container);
}
Expand Down Expand Up @@ -95,18 +101,34 @@ private function setPrimary(ContainerInterface $primary): void
*/
public function addContainers(iterable $containers): self
{
foreach ($containers as $container) {
$this->addContainer($container);
if ($containers instanceof Traversable) {
$containers = iterator_to_array($containers);
}

$isAssoc = ArrayHelper::isArrayAssoc($containers);

foreach ($containers as $priority => $container) {
if (is_int($priority)) {
// Assoc means that the keys are not in order.
// So if this is integer key we threat it as priority.
// In other way add gaps between keys
$priority = $isAssoc ? $priority : ($priority + 1) * 10;
} else {
$priority = null;
}

$this->addContainer($container, $priority ?? self::DEFAULT_PRIORITY);
}
return $this;
}

/**
* Add container to the chain
* @param PsrContainerInterface $container
* @param int $priority
* @return $this
*/
public function addContainer(PsrContainerInterface $container): self
public function addContainer(PsrContainerInterface $container, int $priority = self::DEFAULT_PRIORITY): self
{
if ($container instanceof ContainerInterface) {
$this->setPrimary($container);
Expand All @@ -116,16 +138,37 @@ public function addContainer(PsrContainerInterface $container): self
$container->setContainer($this->getContainer());
}

$this->containers[] = $container;
if (isset($this->containers[$priority])) {
$this->containers[$priority][] = $container;
} else {
$this->containers[$priority] = [$container];
}

return $this;
}

/**
* Iterates over inner containers
* @return Generator<PsrContainerInterface>
*/
public function getIterator(): Generator
{
// Sort by priority
ksort($this->containers);

foreach ($this->containers as $containers) {
foreach ($containers as $container) {
yield $container;
}
}
}

/**
* @inheritDoc
*/
public function get($id, array $arguments = [])
{
foreach ($this->containers as $container) {
foreach ($this->getIterator() as $container) {
if ($container->has($id)) {
return $container instanceof ContainerInterface
? $container->get($id, $arguments)
Expand All @@ -141,7 +184,7 @@ public function get($id, array $arguments = [])
*/
public function has($id): bool
{
foreach ($this->containers as $container) {
foreach ($this->getIterator() as $container) {
if ($container->has($id)) {
return true;
}
Expand Down Expand Up @@ -202,7 +245,7 @@ public function addServiceProvider($provider): ContainerWithServiceProvidersInte
*/
public function hasTagged(string $tag): bool
{
foreach ($this->containers as $container) {
foreach ($this->getIterator() as $container) {
if ($container instanceof ContainerInterface && $container->hasTagged($tag)) {
return true;
}
Expand All @@ -218,7 +261,7 @@ public function getTagged(string $tag): CollectionInterface
{
$result = new Collection();

foreach ($this->containers as $container) {
foreach ($this->getIterator() as $container) {
if (!$container instanceof ContainerInterface) {
continue;
}
Expand Down
Loading

0 comments on commit ad6c687

Please sign in to comment.