/** * Extract Dependencies. * * @param string|array|object|callable $class - name of the class to make * @param string $method - class method to call * * @return callable|string * @throws ContainerAbstractNotFound */ protected function extract_dependencies($class, $method = NULL) { // collect the request attributes $attributes = $this->current_request->attributes->all(); // this will return an empty array if none are found $route_parameters = $this->route_parameters(); // create a reflection based on the format of `$class` and `$method`. $reflection = $this->getReflection($class, $method); # locate the method arguments $arguments = $reflection->getParameters(); # build an argument list to pass to the closure/method # this will contain instantiated dependencies. # more or less $arg_list = []; foreach ($arguments as $key => $arg) { # determine and retrieve the class of the argument, if it exists. $dependency_class = $arg->getClass() === NULL ? NULL : $arg->getClass()->name; # found in the container? if ($this->container->has($dependency_class)) { $arg_list[] = $this->container[$dependency_class]; # Forge::get($dependency_class); continue; } # use the default value if it exists if ($arg->isDefaultValueAvailable()) { $arg_list[] = $arg->getDefaultValue(); continue; } # how about a valid class name? if (class_exists($dependency_class)) { # a class exists as an argument but was not found in the Forge, # so instantiate the class with dependencies $arg_list[] = $this->invokeClassMethod($dependency_class, '__construct'); # new $dependency_class; // next continue; } # we didn't find it in the containers, so look in the request if (array_key_exists($arg->name, $route_parameters)) { $arg_list[] = $route_parameters[$arg->name]; continue; } # throw if no argument reference was found. throw new ContainerAbstractNotFound($arg->name, 'The ' . class_basename($this) . " was unable to resolve a dependency for: ({$dependency_class} \${$arg->name} )", E_USER_ERROR); } # return an array containing the reflection and the list of qualified argument instances return compact('reflection', 'arg_list'); }
/** * Apply and register `Application` settings. * * @throws CannotAddNonexistentClass */ private function bootSettings() { // contextual use for routes and di $app = $this; // load the local environment date_default_timezone_set($this['timezone']); mb_internal_encoding($this['mb_internal_encoding']); setlocale(LC_ALL, $this['locale']); $this['nine.container'] = $this->container; # Forge::getInstance(); $this['nine.events'] = function () { return $this->events; }; // For DI, associate the Pimple\Container with this instance of F9\Application. $this->container->add([\Pimple\Container::class, Application::class], function () use($app) { return $this; }); // set native dependencies $this->container->has('config') ?: $this->container->add([get_class($this->config), 'config'], $this->config); $this->container->add([self::class, 'app'], $this); }
/** * @param array $paths * @param ContainerInterface|Forge $container * * @return array */ private function registerClasses(array $paths, $container) { // we'll start by loading the configuration into the Forge Container $container->add(ContainerInterface::class, function () { return Forge::getInstance(); }); $container->add([Scope::class, 'context'], function () { return new Scope(); }); $container->add('environment', function () use($container) { return $container['GlobalScope']; }); $container->singleton([GlobalScope::class, 'GlobalScope'], $global_scope = new GlobalScope($this)); $container->singleton([Paths::class, 'Paths'], new Paths($paths)); $container->singleton([Config::class, 'Config'], $config = Config::createFromFolder(\CONFIG)); $container->singleton([Events::class, 'Events'], $events = Events::getInstance()); $container->add('paths', function () use($container) { return $container['Paths']; }); $container->add('config', function () use($container) { return $container['Config']; }); return [$global_scope, $config, $events]; }
/** * @param Container $app */ public function register(Container $app) { $app['invoke_with_dependencies'] = $app->protect(function ($class, $method, $execute = NULL) { return $this->injector->invokeClassMethod($class, $method, TRUE); }); }