Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
Björn Büttner committed Jul 14, 2023
1 parent 1b31438 commit f15ac88
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/vendor
/composer.phar
/composer.lock
28 changes: 28 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "bjoern-buettner/dependency-injector",
"description": "description",
"license": "MIT",
"authors": [
{
"name": "Björn Büttner",
"email": "email@example.com"
}
],
"require": {
"php": "^8.1",
"symfony/string": "^6.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"autoload": {
"psr-4": {
"Me\\BjoernBuettner\\DependencyInjector\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Me\\BjoernBuettner\\DependencyInjector\\": "test/"
}
}
}
106 changes: 106 additions & 0 deletions src/DependencyBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

declare(strict_types=1);

namespace Me\BjoernBuettner\DependencyInjector;

use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionParameter;
use RuntimeException;
use Symfony\Component\String\UnicodeString;

class DependencyBuilder
{
/**
* @var array<string, object>
*/
private array $cache = [];

/**
* @param array<string, mixed> $params
* @param array<string, string> $interfaces
* @param array<string, string> $factories
*/
public function __construct(
private readonly array $params = [],
private readonly array $interfaces = [],
private readonly array $factories = [],
) {
}

/**
* @throws ReflectionException
*/
private function getParamValue(ReflectionParameter $param, array $variables, string $key): mixed
{
if (isset($variables[$key])) {
return $variables[$key];
}
if ($type = $param->getType()) {
if (!$type->isBuiltin()) {
return $this->build($type->getName());
}
$envName = (new UnicodeString($param->getName()))->snake()->upper()->toString();
if (isset($_ENV[$envName])) {
return match ($param->getType()->getName()) {
'int' => (int)$_ENV[$envName],
'float' => (float)$_ENV[$envName],
'bool' => $_ENV[$envName] === 'true',
'array' => explode(',', $_ENV[$envName]),
default => (string)$_ENV[$envName],
};
}
if ($type->allowsNull()) {
return null;
}
}
if ($param->isDefaultValueAvailable()) {
return $param->getDefaultValue();
}
throw new UnresolvableParameter("Cannot resolve parameter {$param->getName()}.");
}
/**
* @throws ReflectionException
*/
public function build(string $class): object
{
if (isset($this->cache[$class])) {
return $this->cache[$class];
}
if (isset($this->factories[$class])) {
return $this->cache[$class] = $this->build($this->factories[$class])->get();
}
if (isset($this->interfaces[$class])) {
return $this->cache[$class] = $this->build($this->interfaces[$class]);
}
$rc = new ReflectionClass($class);
$constructor = $rc->getConstructor();
if (!$constructor) {
return $this->cache[$class] = $rc->newInstance();
}
$params = $constructor->getParameters();
$args = [];
foreach ($params as $param) {
$args[] = $this->getParamValue($param, $this->params, $class . '.' . $param->getName());
}
return $this->cache[$class] = $rc->newInstanceArgs($args);
}

/**
* @param array<string, string> $variables
* @throws ReflectionException
*/
public function call(string $class, string $method, array $variables = []): string
{
$object = $this->build($class);
$rm = new ReflectionMethod($object, $method);
$params = $rm->getParameters();
$args = [];
foreach ($params as $param) {
$args[] = $this->getParamValue($param, $variables, $param->getName());
}
return $rm->invokeArgs($object, $args);
}
}
10 changes: 10 additions & 0 deletions src/UnresolvableParameter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Me\BjoernBuettner\DependencyInjector;

use UnexpectedValueException;

class UnresolvableParameter extends UnexpectedValueException
{
}
10 changes: 10 additions & 0 deletions test/DependencyBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Me\BjoernBuettner\DependencyInjector;

use PHPUnit\Framework\TestCase;

class DependencyBuilderTest extends TestCase
{
}

0 comments on commit f15ac88

Please sign in to comment.