From f028b39979b6ca51c0b545c733fa8c4b17993d43 Mon Sep 17 00:00:00 2001 From: Rein Van Oyen Date: Wed, 15 Jan 2020 17:02:45 +0100 Subject: [PATCH] whenAsksGive --- src/Container/Container.php | 92 ++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/src/Container/Container.php b/src/Container/Container.php index c720226..021c3b1 100644 --- a/src/Container/Container.php +++ b/src/Container/Container.php @@ -2,6 +2,7 @@ namespace Oak\Container; +use Exception; use Oak\Contracts\Container\ContainerInterface; use ReflectionClass; @@ -32,6 +33,11 @@ class Container implements ContainerInterface */ private $instances = []; + /** + * @var array + */ + private $arguments = []; + /** * Stores a implementation in the container for the given key * @@ -43,6 +49,17 @@ public function set(string $contract, $implementation) $this->contracts[$contract] = $implementation; } + /** + * Checks if the container has a value by a given contract + * + * @param string $contract + * @return bool + */ + public function has(string $contract): bool + { + return isset($this->contracts[$contract]); + } + /** * Stores a implementation in the container for the given key and also store it as a singleton * @@ -71,6 +88,7 @@ public function instance(string $contract, $instance) * Retreives a value from the container by a given contract * * @param string $contract + * @return mixed * @throws \Exception */ public function get(string $contract) @@ -95,24 +113,27 @@ public function get(string $contract) /** * @param string $contract - * @param array $arguments - * @return mixed - * @throws \Exception + * @param string $arg + * @param $value */ - public function getWith(string $contract, array $arguments) + public function whenAsksGive(string $contract, string $argument, $value) { - return $this->create($contract, $arguments); + if (! isset($this->arguments[$contract])) { + $this->arguments[$contract] = []; + } + + $this->arguments[$contract][$argument] = $value; } /** - * Checks if the container has a value by a given contract - * * @param string $contract - * @return bool + * @param array $arguments + * @return mixed + * @throws \Exception */ - public function has(string $contract): bool + public function getWith(string $contract, array $arguments) { - return isset($this->contracts[$contract]); + return $this->create($contract, $arguments); } /** @@ -135,6 +156,12 @@ private function create(string $contract, array $arguments = []) $implementation = $this->contracts[$contract]; } + // Check if we have to give this class some stored arguments + if (is_string($implementation) && isset($this->arguments[$implementation])) { + $arguments = array_merge($arguments, $this->arguments[$implementation]); + } + + // Is it callable? Call it right away and return the results if (is_callable($implementation)) { return call_user_func($implementation, $this); } @@ -156,16 +183,47 @@ private function create(string $contract, array $arguments = []) foreach ($parameters as $parameter) { - // Check if the parameter was given - if (isset($arguments[$parameter->getName()])) { - $injections[] = $arguments[$parameter->getName()]; + // Check if param is a class + if ($class = $parameter->getClass()) { + + $className = $class->name; + + // Check if it was explicitely given as an argument + if (isset($arguments[$className])) { + + // Get the explicit argument from the container + $injections[] = $this->get($arguments[$className]); + continue; + + } + + // Get the class from the container + $injections[] = $this->get($className); + continue; - } - // It's a dependency, so inject it - $class = $parameter->getClass()->name; + } else { + + $argName = $parameter->getName(); + + // Check if the argument was explicitely given + if (isset($arguments[$argName])) { + + $injections[] = $arguments[$argName]; + continue; + + } + + // Check if the argument has a default value + if($parameter->isDefaultValueAvailable()) { + + // Inject the default value + $injections[] = $parameter->getDefaultValue(); + continue; + } + } - $injections[] = $this->get($class); + throw new Exception('Could not provide argument "'.$parameter->getName().'" to '.$contract); } return $reflect->newInstanceArgs($injections);