Skip to content

Commit

Permalink
Add auto declarer interface to allow mixing auto dependencies and man…
Browse files Browse the repository at this point in the history
…ual dependencies
  • Loading branch information
Ivan Vegner committed Aug 2, 2017
1 parent 073e6fa commit 5262831
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 38 deletions.
9 changes: 9 additions & 0 deletions src/AutoDeclarerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace SD\DependencyInjection;

interface AutoDeclarerInterface {
/**
* @return string[]
**/
public function autoDeclareDependencies();
}
4 changes: 2 additions & 2 deletions src/AutoDeclareTrait.php → src/AutoDeclarerTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace SD\DependencyInjection;

trait AutoDeclareTrait {
trait AutoDeclarerTrait {
private $prefixAutoDeclare = 'autoDeclare';

/**
* @return string[]
**/
public function declareDependencies() {
public function autoDeclareDependencies() {
$class = new \ReflectionClass($this);
$deps = [];
foreach ($class->getDefaultProperties () as $name => $value) {
Expand Down
24 changes: 15 additions & 9 deletions src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public function __construct(array $config = [], $selfName = '') {
}

public function connect(ProviderInterface $provider) {
$this->initializers[$provider->getName()] = function () use ($provider) {
$this->initializers[$provider->getServiceName()] = function () use ($provider) {
$this->inject($provider);
return $provider->provide();
};
Expand Down Expand Up @@ -55,9 +55,7 @@ public function inject($consumer) {
$parameters = $this->getParameterValues(new \ReflectionFunction($consumer));
return $consumer(...$parameters);
} else {
if ($consumer instanceof DeclarerInterface) {
$consumer = $this->injectDeclared($consumer);
}
$consumer = $this->injectDeclarer($consumer);
return $consumer;
}
}
Expand All @@ -83,14 +81,22 @@ private function produceRecursive($initializer, array $names) {
} else {
$instance = $initializer;
}
if ($instance instanceof DeclarerInterface) {
$instance = $this->injectDeclared($instance);
}
$instance = $this->injectDeclarer($instance);
return $instance;
}

private function injectDeclared(DeclarerInterface $object) {
foreach ($object->declareDependencies() as $name) {
private function injectDeclarer($object) {
if ($object instanceof AutoDeclarerInterface) {
$object = $this->injectByNames($object, $object->autoDeclareDependencies());
}
if ($object instanceof DeclarerInterface) {
$object = $this->injectByNames($object, $object->declareDependencies());
}
return $object;
}

private function injectByNames($object, array $names) {
foreach ($names as $name) {
$setter = 'set' . implode('', array_map('ucfirst', explode('_', $name)));
if (!method_exists($object, $setter)) {
throw new Exception("Object declared $name dependency, but setter method $setter was not found");
Expand Down
2 changes: 1 addition & 1 deletion src/ProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
namespace SD\DependencyInjection;

interface ProviderInterface {
public function getName(): string;
public function getServiceName(): string;
public function provide();
}
15 changes: 0 additions & 15 deletions tests/AutoDeclareService.php

This file was deleted.

15 changes: 15 additions & 0 deletions tests/AutoDeclarerService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
namespace tests;

use SD\DependencyInjection\AutoDeclarerTrait;
use SD\DependencyInjection\AutoDeclarerInterface;
use SD\DependencyInjection\ContainerAwareTrait;

class AutoDeclarerService implements AutoDeclarerInterface {
use AutoDeclarerTrait;
use ContainerAwareTrait;

public function getContainer() {
return $this->container;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
namespace tests;

use PHPUnit\Framework\TestCase;
use SD\DependencyInjection\AutoDeclareTrait;
use SD\DependencyInjection\AutoDeclarerTrait;
use SD\DependencyInjection\Container;

class AutoDeclareTraitTest extends TestCase {
class AutoDeclarerTraitTest extends TestCase {
public function testDeclareDependencies() {
$container = new Container([], 'container');
$service = $container->produce(AutoDeclareService::class);
$service = $container->produce(AutoDeclarerService::class);
$this->assertEquals($container, $service->getContainer(), 'Must inject container with auto declare');
}
}
2 changes: 1 addition & 1 deletion tests/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function testConnect() {
);
$provider = new LegacyProvider();
$container->connect($provider);
$service = $container->get($provider->getName());
$service = $container->get($provider->getServiceName());
$this->assertInstanceOf(LegacyService::class, $service, 'Must return instance of LegacyService');
$this->assertEquals($name, $service->getName(), 'Must inject name from config');
$this->assertEquals($container, $service->getContainer(), 'Must inject container by setter');
Expand Down
13 changes: 6 additions & 7 deletions tests/LegacyProvider.php
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
<?php
namespace tests;

use SD\DependencyInjection\AutoDeclareTrait;
use SD\DependencyInjection\AutoDeclarerInterface;
use SD\DependencyInjection\AutoDeclarerTrait;
use SD\DependencyInjection\ContainerAwareTrait;
use SD\DependencyInjection\DeclarerInterface;
use SD\DependencyInjection\ProviderInterface;

class LegacyProvider implements DeclarerInterface, ProviderInterface {
use AutoDeclareTrait {
declareDependencies as autoDeclareDependencies;
}
class LegacyProvider implements AutoDeclarerInterface, DeclarerInterface, ProviderInterface {
use AutoDeclarerTrait;
use ContainerAwareTrait;

private $name;

public function declareDependencies() {
return array_merge($this->autoDeclareDependencies(), ['name']);
return ['name'];
}

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

public function getName(): string {
public function getServiceName(): string {
return 'helloWorld';
}

Expand Down

0 comments on commit 5262831

Please sign in to comment.