Skip to content

Commit

Permalink
add AnnotatedWith attribute, and AnnotatedResolverFactory that scans …
Browse files Browse the repository at this point in the history
…for attributes, allow to execute code before compilation via ContainerCompileInterface
  • Loading branch information
frederikbosch committed May 21, 2024
1 parent 80e4914 commit 9894c8e
Show file tree
Hide file tree
Showing 19 changed files with 562 additions and 54 deletions.
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
"require-dev": {
"producer/producer": "^2.3",
"phpunit/phpunit": "^9.0 || ^10.0",
"phpstan/phpstan": "^1.11.1"
"phpstan/phpstan": "^1.11.1",
"composer/class-map-generator": "^1.1"
},
"suggest": {
"composer/class-map-generator": "Required for detecting annotations"
},
"autoload-dev": {
"psr-4": {
Expand Down
31 changes: 31 additions & 0 deletions src/Attribute/AnnotatedWith.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
/**
*
* This file is part of Aura for PHP.
*
* @license http://opensource.org/licenses/MIT MIT
*
*/

namespace Aura\Di\Attribute;

use Attribute;
use Aura\Di\Injection\LazyAnnotatedWith;
use Aura\Di\Injection\LazyInterface;

#[Attribute(Attribute::TARGET_PARAMETER)]
class AnnotatedWith implements AnnotatedInjectInterface
{
private string $name;

public function __construct(string $name)
{
$this->name = $name;
}

public function inject(): LazyInterface
{
return new LazyAnnotatedWith($this->name);
}
}
16 changes: 16 additions & 0 deletions src/Attribute/DefineInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/**
*
* This file is part of Aura for PHP.
*
* @license http://opensource.org/licenses/MIT MIT
*
*/

namespace Aura\Di\Attribute;

interface DefineInterface
{
public function define(\Reflector $reflector): mixed;
}
16 changes: 16 additions & 0 deletions src/ConfigCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,22 @@ public function define(Container $di): void
}
}

/**
*
* Execute code after the Container is defined and before the Container is locked and compiled.
*
* @param Container $di The DI container.
*
*/
public function compile(Container $di): void
{
foreach ($this->configs as $config) {
if ($config instanceof ContainerCompileInterface) {
$config->compile($di);
}
}
}

/**
*
* Modify service objects for each config after the Container is locked.
Expand Down
47 changes: 31 additions & 16 deletions src/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
*/
namespace Aura\Di;

use Aura\Di\Resolver\AutoResolver;
use Aura\Di\Resolver\Reflector;
use Aura\Di\Resolver\Resolver;
use Aura\Di\Resolver\ResolverFactory;
use Aura\Di\Resolver\ResolverFactoryInterface;

/**
*
Expand All @@ -29,7 +29,25 @@ class ContainerBuilder
* @const true
*
*/
const AUTO_RESOLVE = true;
const AUTO_RESOLVE = ResolverFactoryInterface::AUTO_RESOLVE;

/**
*
* A factory to create the resolver.
*
* @var ResolverFactoryInterface
*
*/
private ResolverFactoryInterface $resolverFactory;

public function __construct(?ResolverFactoryInterface $resolverFactory = null)
{
if ($resolverFactory === null) {
$resolverFactory = new ResolverFactory();
}

$this->resolverFactory = $resolverFactory;
}

/**
*
Expand All @@ -56,11 +74,7 @@ public function newInstance(bool $autoResolve = false): Container
*/
protected function newResolver(bool $autoResolve = false): Resolver
{
if ($autoResolve) {
return new AutoResolver(new Reflector());
}

return new Resolver(new Reflector());
return $this->resolverFactory->newResolver($autoResolve);
}

/**
Expand Down Expand Up @@ -114,9 +128,11 @@ public function newCompiledInstance(
): Container {
$resolver = $this->newResolver($autoResolve);
$di = new Container($resolver);
$collection = $this->newConfigCollection($configClasses);

$collection = $this->newConfigCollection($configClasses);
$collection->define($di);
$collection->compile($di);

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

Expand All @@ -125,23 +141,22 @@ public function newCompiledInstance(

/**
*
* Creates a new Container, applies ContainerConfig classes to define()
* services, locks the container, and applies the ContainerConfig instances
* to modify() services.
* Applies the ContainerConfig instances to modify() services onto a Container that was
* compiled.
*
* @param Container $compiledContainer The container that has been compiled in an earlier step.
* @param Container $container 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,
Container $container,
array $configClasses = [],
): Container {
$this->newConfigCollection($configClasses)->modify($compiledContainer);
return $compiledContainer;
$this->newConfigCollection($configClasses)->modify($container);
return $container;
}

/**
Expand Down
29 changes: 29 additions & 0 deletions src/ContainerCompileInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
/**
*
* This file is part of Aura for PHP.
*
* @license http://opensource.org/licenses/MIT MIT
*
*/
namespace Aura\Di;

/**
*
* An interface for a set of Container configuration instructions.
*
* @package Aura.Di
*
*/
interface ContainerCompileInterface extends ContainerConfigInterface
{
/**
*
* Execute code after the Container is defined and before the Container is locked and compiled.
*
* @param Container $di The DI container.
*
*/
public function compile(Container $di): void;
}
13 changes: 12 additions & 1 deletion src/ContainerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* @package Aura.Di
*
*/
class ContainerConfig implements ContainerConfigInterface
class ContainerConfig implements ContainerCompileInterface
{
/**
*
Expand All @@ -29,6 +29,17 @@ public function define(Container $di): void
{
}

/**
*
* Execute code after the Container is defined and before the Container is locked and compiled.
*
* @param Container $di The DI container.
*
*/
public function compile(Container $di): void
{
}

/**
*
* Modify service objects after the Container is locked.
Expand Down
63 changes: 63 additions & 0 deletions src/Injection/LazyAnnotatedWith.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
/**
*
* This file is part of Aura for PHP.
*
* @license http://opensource.org/licenses/MIT MIT
*
*/
namespace Aura\Di\Injection;

use Aura\Di\Resolver\Resolver;

/**
*
* Returns a Container service when invoked.
*
* @package Aura.Di
*
*/
class LazyAnnotatedWith implements LazyInterface
{
/**
*
* The name of the class.
*
* @var string
*
*/
protected string $className;

/**
*
* Constructor.
*
* @param string $className The name to the class used for the annotation.
*
*/
public function __construct(string $className)
{
$this->className = $className;
}

/**
*
* Invokes the closure to create the instance.
*
* @return array The list of the defined annotations.
*
*/
public function __invoke(Resolver $resolver): array
{
$annotations = $resolver->annotations[$this->className] ?? [];

foreach ($annotations as $key => $val) {
if ($val instanceof LazyInterface) {
$annotations[$key] = $val($resolver);
}
}

return $annotations;
}
}
Loading

0 comments on commit 9894c8e

Please sign in to comment.