Viewing file: DependencyContainer.php (9.7 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/* * This file is part of SwiftMailer. * (c) 2004-2009 Chris Corbyn * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */
/** * Dependency Injection container. * * @author Chris Corbyn */ class Swift_DependencyContainer { /** Constant for literal value types */ const TYPE_VALUE = 0x00001;
/** Constant for new instance types */ const TYPE_INSTANCE = 0x00010;
/** Constant for shared instance types */ const TYPE_SHARED = 0x00100;
/** Constant for aliases */ const TYPE_ALIAS = 0x01000;
/** Constant for arrays */ const TYPE_ARRAY = 0x10000;
/** Singleton instance */ private static $instance = null;
/** The data container */ private $store = [];
/** The current endpoint in the data container */ private $endPoint;
/** * Constructor should not be used. * * Use {@link getInstance()} instead. */ public function __construct() { }
/** * Returns a singleton of the DependencyContainer. * * @return self */ public static function getInstance() { if (!isset(self::$instance)) { self::$instance = new self(); }
return self::$instance; }
/** * List the names of all items stored in the Container. * * @return array */ public function listItems() { return array_keys($this->store); }
/** * Test if an item is registered in this container with the given name. * * @see register() * * @param string $itemName * * @return bool */ public function has($itemName) { return \array_key_exists($itemName, $this->store) && isset($this->store[$itemName]['lookupType']); }
/** * Lookup the item with the given $itemName. * * @see register() * * @param string $itemName * * @return mixed * * @throws Swift_DependencyException If the dependency is not found */ public function lookup($itemName) { if (!$this->has($itemName)) { throw new Swift_DependencyException('Cannot lookup dependency "'.$itemName.'" since it is not registered.'); }
switch ($this->store[$itemName]['lookupType']) { case self::TYPE_ALIAS: return $this->createAlias($itemName); case self::TYPE_VALUE: return $this->getValue($itemName); case self::TYPE_INSTANCE: return $this->createNewInstance($itemName); case self::TYPE_SHARED: return $this->createSharedInstance($itemName); case self::TYPE_ARRAY: return $this->createDependenciesFor($itemName); } }
/** * Create an array of arguments passed to the constructor of $itemName. * * @param string $itemName * * @return array */ public function createDependenciesFor($itemName) { $args = []; if (isset($this->store[$itemName]['args'])) { $args = $this->resolveArgs($this->store[$itemName]['args']); }
return $args; }
/** * Register a new dependency with $itemName. * * This method returns the current DependencyContainer instance because it * requires the use of the fluid interface to set the specific details for the * dependency. * * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() * * @param string $itemName * * @return $this */ public function register($itemName) { $this->store[$itemName] = []; $this->endPoint = &$this->store[$itemName];
return $this; }
/** * Specify the previously registered item as a literal value. * * {@link register()} must be called before this will work. * * @param mixed $value * * @return $this */ public function asValue($value) { $endPoint = &$this->getEndPoint(); $endPoint['lookupType'] = self::TYPE_VALUE; $endPoint['value'] = $value;
return $this; }
/** * Specify the previously registered item as an alias of another item. * * @param string $lookup * * @return $this */ public function asAliasOf($lookup) { $endPoint = &$this->getEndPoint(); $endPoint['lookupType'] = self::TYPE_ALIAS; $endPoint['ref'] = $lookup;
return $this; }
/** * Specify the previously registered item as a new instance of $className. * * {@link register()} must be called before this will work. * Any arguments can be set with {@link withDependencies()}, * {@link addConstructorValue()} or {@link addConstructorLookup()}. * * @see withDependencies(), addConstructorValue(), addConstructorLookup() * * @param string $className * * @return $this */ public function asNewInstanceOf($className) { $endPoint = &$this->getEndPoint(); $endPoint['lookupType'] = self::TYPE_INSTANCE; $endPoint['className'] = $className;
return $this; }
/** * Specify the previously registered item as a shared instance of $className. * * {@link register()} must be called before this will work. * * @param string $className * * @return $this */ public function asSharedInstanceOf($className) { $endPoint = &$this->getEndPoint(); $endPoint['lookupType'] = self::TYPE_SHARED; $endPoint['className'] = $className;
return $this; }
/** * Specify the previously registered item as array of dependencies. * * {@link register()} must be called before this will work. * * @return $this */ public function asArray() { $endPoint = &$this->getEndPoint(); $endPoint['lookupType'] = self::TYPE_ARRAY;
return $this; }
/** * Specify a list of injected dependencies for the previously registered item. * * This method takes an array of lookup names. * * @see addConstructorValue(), addConstructorLookup() * * @return $this */ public function withDependencies(array $lookups) { $endPoint = &$this->getEndPoint(); $endPoint['args'] = []; foreach ($lookups as $lookup) { $this->addConstructorLookup($lookup); }
return $this; }
/** * Specify a literal (non looked up) value for the constructor of the * previously registered item. * * @see withDependencies(), addConstructorLookup() * * @param mixed $value * * @return $this */ public function addConstructorValue($value) { $endPoint = &$this->getEndPoint(); if (!isset($endPoint['args'])) { $endPoint['args'] = []; } $endPoint['args'][] = ['type' => 'value', 'item' => $value];
return $this; }
/** * Specify a dependency lookup for the constructor of the previously * registered item. * * @see withDependencies(), addConstructorValue() * * @param string $lookup * * @return $this */ public function addConstructorLookup($lookup) { $endPoint = &$this->getEndPoint(); if (!isset($this->endPoint['args'])) { $endPoint['args'] = []; } $endPoint['args'][] = ['type' => 'lookup', 'item' => $lookup];
return $this; }
/** Get the literal value with $itemName */ private function getValue($itemName) { return $this->store[$itemName]['value']; }
/** Resolve an alias to another item */ private function createAlias($itemName) { return $this->lookup($this->store[$itemName]['ref']); }
/** Create a fresh instance of $itemName */ private function createNewInstance($itemName) { $reflector = new ReflectionClass($this->store[$itemName]['className']); if ($reflector->getConstructor()) { return $reflector->newInstanceArgs( $this->createDependenciesFor($itemName) ); }
return $reflector->newInstance(); }
/** Create and register a shared instance of $itemName */ private function createSharedInstance($itemName) { if (!isset($this->store[$itemName]['instance'])) { $this->store[$itemName]['instance'] = $this->createNewInstance($itemName); }
return $this->store[$itemName]['instance']; }
/** Get the current endpoint in the store */ private function &getEndPoint() { if (!isset($this->endPoint)) { throw new BadMethodCallException('Component must first be registered by calling register()'); }
return $this->endPoint; }
/** Get an argument list with dependencies resolved */ private function resolveArgs(array $args) { $resolved = []; foreach ($args as $argDefinition) { switch ($argDefinition['type']) { case 'lookup': $resolved[] = $this->lookupRecursive($argDefinition['item']); break; case 'value': $resolved[] = $argDefinition['item']; break; } }
return $resolved; }
/** Resolve a single dependency with an collections */ private function lookupRecursive($item) { if (\is_array($item)) { $collection = []; foreach ($item as $k => $v) { $collection[$k] = $this->lookupRecursive($v); }
return $collection; }
return $this->lookup($item); } }
|