Skip to content

Commit

Permalink
add compile to Resolver, add newCompiledInstance and configureCompile…
Browse files Browse the repository at this point in the history
…dInstance to ContainerBuilder
  • Loading branch information
frederikbosch committed May 17, 2024
1 parent 1b3e22c commit 80e4914
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 3 deletions.
56 changes: 53 additions & 3 deletions src/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/
namespace Aura\Di;

use Aura\Di\Injection\InjectionFactory;
use Aura\Di\Resolver\AutoResolver;
use Aura\Di\Resolver\Reflector;
use Aura\Di\Resolver\Resolver;
Expand Down Expand Up @@ -77,8 +76,6 @@ protected function newResolver(bool $autoResolve = false): Resolver
*
* @return Container
*
* @throws Exception\SetterMethodNotFound
*
*/
public function newConfiguredInstance(
array $configClasses = [],
Expand All @@ -94,6 +91,59 @@ public function newConfiguredInstance(
return $di;
}

/**
*
* Creates a new Container, applies ContainerConfig classes to define()
* services, locks the container and compiles all classes into blueprints.
* A compiled container is ready to serialize.
*
* @param array $configClasses A list of ContainerConfig classes to
* instantiate and invoke for configuring the Container.
*
* @param array $extraCompileClasses A list of classes that should also be compiled, e.g. a list of classes that
* might contain container annotations.
*
* @param bool $autoResolve Use the auto-resolver?
*
* @return Container
*/
public function newCompiledInstance(
array $configClasses = [],
array $extraCompileClasses = [],
bool $autoResolve = false,
): Container {
$resolver = $this->newResolver($autoResolve);
$di = new Container($resolver);
$collection = $this->newConfigCollection($configClasses);

$collection->define($di);
$di->lock();
$resolver->compile($extraCompileClasses);

return $di;
}

/**
*
* Creates a new Container, applies ContainerConfig classes to define()
* services, locks the container, and applies the ContainerConfig instances
* to modify() services.
*
* @param Container $compiledContainer The container that has been compiled in an earlier step.
*
* @param array $configClasses A list of ContainerConfig classes to
* instantiate and invoke for configuring the Container.
*
* @return Container
*/
public function configureCompiledInstance(
Container $compiledContainer,
array $configClasses = [],
): Container {
$this->newConfigCollection($configClasses)->modify($compiledContainer);
return $compiledContainer;
}

/**
*
* Creates a new ContainerConfig for a collection of
Expand Down
18 changes: 18 additions & 0 deletions src/Resolver/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,24 @@ public function resolve(Blueprint $blueprint, array $contextualBlueprints = []):
return $resolved;
}

public function compile(array $extraClasses = []): void
{
$classes = \array_unique([
...\array_keys($this->params),
...\array_keys($this->setters),
...\array_keys($this->mutations),
...$extraClasses,
]);

foreach ($classes as $class) {
$this->getUnified($class);
}

$this->params = [];
$this->setters = [];
$this->mutations = [];
}

/**
*
* Returns the unified constructor params and setters for a class.
Expand Down
37 changes: 37 additions & 0 deletions tests/ContainerBuilderTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<?php
namespace Aura\Di;

use Aura\Di\Fake\FakeConstructAttributeClass;
use Aura\Di\Fake\FakeInterfaceClass1;
use Aura\Di\Fake\FakeInterfaceClass2;
use Aura\Di\Fake\FakeParentClass;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -156,4 +159,38 @@ public function testSerializeAndUnserializeLazyCallable()
$this->expectException(\Exception::class);
serialize($di);
}

public function testCompilationSerialization()
{
$config_classes = [
new \Aura\Di\Fake\FakeLibraryConfig,
new \Aura\Di\Fake\FakeProjectConfig,
new \Aura\Di\Fake\FakeCompilationTestConfig(),
];

$extra_classes = [
FakeConstructAttributeClass::class
];

$di = $this->builder->newCompiledInstance($config_classes, $extra_classes);
$serialized = \serialize($di);
$di = \unserialize($serialized);
$di = $this->builder->configureCompiledInstance($di, $config_classes);

$this->assertInstanceOf('Aura\Di\Container', $di);

$expect = 'zim';
$actual = $di->get('library_service');
$this->assertSame($expect, $actual->foo);

$expect = 'gir';
$actual = $di->get('project_service');
$this->assertSame($expect, $actual->baz);

$actual = $di->newInstance(FakeConstructAttributeClass::class);
$this->assertInstanceOf(FakeInterfaceClass1::class, $actual->getFakeService());
$this->assertInstanceOf(FakeInterfaceClass1::class, $actual->getFakeServiceGet());
$this->assertInstanceOf(FakeInterfaceClass2::class, $actual->getFakeInstance());
$this->assertSame('value', $actual->getString());
}
}
19 changes: 19 additions & 0 deletions tests/Fake/FakeCompilationTestConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
namespace Aura\Di\Fake;

use Aura\Di\Container;
use Aura\Di\ContainerConfig;

class FakeCompilationTestConfig extends ContainerConfig
{
public function define(Container $di): void
{
parent::define($di);
$fakeService = new FakeInterfaceClass1();
$fakeServiceGet = new FakeInterfaceClass1();
$fakeService->setFoo($fakeServiceGet);

$di->set('fake.service', $fakeService);
$di->values['fake.value'] = 'value';
}
}
20 changes: 20 additions & 0 deletions tests/Resolver/ResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,24 @@ public function testOverwriteAttribute()
$actual = $this->resolver->resolve(new Blueprint('Aura\Di\Fake\FakeConstructAttributeClass'));
$this->assertSame($fakeService2, $actual->getFakeService());
}

public function testCompile()
{
$fakeService = new FakeInterfaceClass1();
$fakeService2 = new FakeInterfaceClass2();
$fakeServiceGet = new FakeInterfaceClass1();
$fakeService->setFoo($fakeServiceGet);

$this->resolver->setService('fake.service', $fakeService);
$this->resolver->setService('fake.service2', $fakeService2);
$this->resolver->values['fake.value'] = 'value';
$this->resolver->params['Aura\Di\Fake\FakeConstructAttributeClass']['fakeService'] = new LazyGet('fake.service2');
$this->resolver->compile();

$actual = $this->resolver->resolve(new Blueprint('Aura\Di\Fake\FakeConstructAttributeClass'));
$this->assertSame($fakeService2, $actual->getFakeService());
$this->assertSame($fakeServiceGet, $actual->getFakeServiceGet());
$this->assertInstanceOf('Aura\Di\Fake\FakeInterfaceClass2', $actual->getFakeInstance());
$this->assertSame('value', $actual->getString());
}
}

0 comments on commit 80e4914

Please sign in to comment.