Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/container/src/GenericContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ final class GenericContainer implements Container
{
use HasInstance;

/** @var array<class-string<DynamicInitializer>, DynamicInitializer> */
private array $resolvedDynamicInitializers = [];

public function __construct(
/** @var ArrayIterator<array-key, mixed> $definitions */
private(set) ArrayIterator $definitions = new ArrayIterator(),
Expand Down Expand Up @@ -81,6 +84,7 @@ public function setInitializers(array $initializers): self
public function setDynamicInitializers(array $dynamicInitializers): self
{
$this->dynamicInitializers = new ArrayIterator($dynamicInitializers);
$this->resolvedDynamicInitializers = [];

return $this;
}
Expand Down Expand Up @@ -330,6 +334,7 @@ public function removeInitializer(ClassReflector|string $initializerClass): Cont
);

unset($this->dynamicInitializers[$index]);
unset($this->resolvedDynamicInitializers[$initializerClass->getName()]);

return $this;
}
Expand Down Expand Up @@ -444,8 +449,11 @@ private function initializerForClass(ClassReflector $target, null|string|UnitEnu
// Loop through the registered initializers to see if
// we have something to handle this class.
foreach ($this->dynamicInitializers as $initializerClass) {
/** @var DynamicInitializer $initializer */
$initializer = $this->resolve($initializerClass);
if (! isset($this->resolvedDynamicInitializers[$initializerClass])) {
$this->resolvedDynamicInitializers[$initializerClass] = $this->resolve($initializerClass);
}

$initializer = $this->resolvedDynamicInitializers[$initializerClass];

if (! $initializer->canInitialize(class: $target, tag: $tag)) {
continue;
Expand Down Expand Up @@ -719,6 +727,7 @@ public function addResettable(string|ClassReflector $resettableClass): Container
public function reset(): self
{
$this->resolvedSingletons = new ArrayIterator();
$this->resolvedDynamicInitializers = [];

foreach ($this->resettables as $resettableClass) {
/** @var Resettable $resettable */
Expand Down
14 changes: 14 additions & 0 deletions packages/container/tests/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use Tempest\Container\Tests\Fixtures\ContainerObjectDInitializer;
use Tempest\Container\Tests\Fixtures\ContainerObjectE;
use Tempest\Container\Tests\Fixtures\ContainerObjectEInitializer;
use Tempest\Container\Tests\Fixtures\CountingDynamicInitializer;
use Tempest\Container\Tests\Fixtures\DecoratedClass;
use Tempest\Container\Tests\Fixtures\DecoratedInterface;
use Tempest\Container\Tests\Fixtures\DecoratorClass;
Expand Down Expand Up @@ -157,6 +158,19 @@ public function test_call_tries_to_transform_unmatched_values(): void
$this->assertSame('other', $return->id);
}

public function test_dynamic_initializer_instances_are_reused(): void
{
CountingDynamicInitializer::reset();

$container = new GenericContainer();
$container->addInitializer(CountingDynamicInitializer::class);

$container->get(ContainerObjectA::class);
$container->get(ContainerObjectA::class);

$this->assertSame(1, CountingDynamicInitializer::$instances);
}

public function test_arrays_are_automatically_created(): void
{
$container = new GenericContainer();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Tempest\Container\Tests\Fixtures;

use Tempest\Container\Container;
use Tempest\Container\DynamicInitializer;
use Tempest\Reflection\ClassReflector;
use UnitEnum;

final class CountingDynamicInitializer implements DynamicInitializer
{
public static int $instances = 0;

private bool $counted = false;

public static function reset(): void
{
self::$instances = 0;
}

public function canInitialize(ClassReflector $class, null|string|UnitEnum $tag): bool
{
if (! $this->counted) {
$this->counted = true;
self::$instances++;
}

return false;
}

public function initialize(ClassReflector $class, null|string|UnitEnum $tag, Container $container): object
{
throw new \LogicException('CountingDynamicInitializer should not initialize objects.');
}
}
Loading