|
TYPO3 API
SVNRelease
|
00001 <?php 00002 00003 /* 00004 * This file is part of SwiftMailer. 00005 * (c) 2004-2009 Chris Corbyn 00006 * 00007 * For the full copyright and license information, please view the LICENSE 00008 * file that was distributed with this source code. 00009 */ 00010 00011 //@require 'Swift/DependencyException.php'; 00012 00013 /** 00014 * Dependency Injection container. 00015 * @package Swift 00016 * @author Chris Corbyn 00017 */ 00018 class Swift_DependencyContainer 00019 { 00020 00021 /** Constant for literal value types */ 00022 const TYPE_VALUE = 0x0001; 00023 00024 /** Constant for new instance types */ 00025 const TYPE_INSTANCE = 0x0010; 00026 00027 /** Constant for shared instance types */ 00028 const TYPE_SHARED = 0x0100; 00029 00030 /** Constant for aliases */ 00031 const TYPE_ALIAS = 0x1000; 00032 00033 /** Singleton instance */ 00034 private static $_instance = null; 00035 00036 /** The data container */ 00037 private $_store = array(); 00038 00039 /** The current endpoint in the data container */ 00040 private $_endPoint; 00041 00042 /** 00043 * Constructor should not be used. 00044 * Use {@link getInstance()} instead. 00045 */ 00046 public function __construct() { } 00047 00048 /** 00049 * Returns a singleton of the DependencyContainer. 00050 * @return Swift_DependencyContainer 00051 */ 00052 public static function getInstance() 00053 { 00054 if (!isset(self::$_instance)) 00055 { 00056 self::$_instance = new self(); 00057 } 00058 return self::$_instance; 00059 } 00060 00061 /** 00062 * List the names of all items stored in the Container. 00063 * @return array 00064 */ 00065 public function listItems() 00066 { 00067 return array_keys($this->_store); 00068 } 00069 00070 /** 00071 * Test if an item is registered in this container with the given name. 00072 * @param string $itemName 00073 * @return boolean 00074 * @see register() 00075 */ 00076 public function has($itemName) 00077 { 00078 return array_key_exists($itemName, $this->_store) 00079 && isset($this->_store[$itemName]['lookupType']); 00080 } 00081 00082 /** 00083 * Lookup the item with the given $itemName. 00084 * @param string $itemName 00085 * @return mixed 00086 * @throws Swift_DependencyException If the dependency is not found 00087 * @see register() 00088 */ 00089 public function lookup($itemName) 00090 { 00091 if (!$this->has($itemName)) 00092 { 00093 throw new Swift_DependencyException( 00094 'Cannot lookup dependency "' . $itemName . '" since it is not registered.' 00095 ); 00096 } 00097 00098 switch ($this->_store[$itemName]['lookupType']) 00099 { 00100 case self::TYPE_ALIAS: 00101 return $this->_createAlias($itemName); 00102 case self::TYPE_VALUE: 00103 return $this->_getValue($itemName); 00104 case self::TYPE_INSTANCE: 00105 return $this->_createNewInstance($itemName); 00106 case self::TYPE_SHARED: 00107 return $this->_createSharedInstance($itemName); 00108 } 00109 } 00110 00111 /** 00112 * Create an array of arguments passed to the constructor of $itemName. 00113 * @param string $itemName 00114 * @return array 00115 */ 00116 public function createDependenciesFor($itemName) 00117 { 00118 $args = array(); 00119 if (isset($this->_store[$itemName]['args'])) 00120 { 00121 $args = $this->_resolveArgs($this->_store[$itemName]['args']); 00122 } 00123 return $args; 00124 } 00125 00126 /** 00127 * Register a new dependency with $itemName. 00128 * This method returns the current DependencyContainer instance because it 00129 * requires the use of the fluid interface to set the specific details for the 00130 * dependency. 00131 * 00132 * @param string $itemName 00133 * @return Swift_DependencyContainer 00134 * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() 00135 */ 00136 public function register($itemName) 00137 { 00138 $this->_store[$itemName] = array(); 00139 $this->_endPoint =& $this->_store[$itemName]; 00140 return $this; 00141 } 00142 00143 /** 00144 * Specify the previously registered item as a literal value. 00145 * {@link register()} must be called before this will work. 00146 * 00147 * @param mixed $value 00148 * @return Swift_DependencyContainer 00149 */ 00150 public function asValue($value) 00151 { 00152 $endPoint =& $this->_getEndPoint(); 00153 $endPoint['lookupType'] = self::TYPE_VALUE; 00154 $endPoint['value'] = $value; 00155 return $this; 00156 } 00157 00158 /** 00159 * Specify the previously registered item as an alias of another item. 00160 * @param string $lookup 00161 * @return Swift_DependencyContainer 00162 */ 00163 public function asAliasOf($lookup) 00164 { 00165 $endPoint =& $this->_getEndPoint(); 00166 $endPoint['lookupType'] = self::TYPE_ALIAS; 00167 $endPoint['ref'] = $lookup; 00168 return $this; 00169 } 00170 00171 /** 00172 * Specify the previously registered item as a new instance of $className. 00173 * {@link register()} must be called before this will work. 00174 * Any arguments can be set with {@link withDependencies()}, 00175 * {@link addConstructorValue()} or {@link addConstructorLookup()}. 00176 * 00177 * @param string $className 00178 * @return Swift_DependencyContainer 00179 * @see withDependencies(), addConstructorValue(), addConstructorLookup() 00180 */ 00181 public function asNewInstanceOf($className) 00182 { 00183 $endPoint =& $this->_getEndPoint(); 00184 $endPoint['lookupType'] = self::TYPE_INSTANCE; 00185 $endPoint['className'] = $className; 00186 return $this; 00187 } 00188 00189 /** 00190 * Specify the previously registered item as a shared instance of $className. 00191 * {@link register()} must be called before this will work. 00192 * @param string $className 00193 * @return Swift_DependencyContainer 00194 */ 00195 public function asSharedInstanceOf($className) 00196 { 00197 $endPoint =& $this->_getEndPoint(); 00198 $endPoint['lookupType'] = self::TYPE_SHARED; 00199 $endPoint['className'] = $className; 00200 return $this; 00201 } 00202 00203 /** 00204 * Specify a list of injected dependencies for the previously registered item. 00205 * This method takes an array of lookup names. 00206 * 00207 * @param array $lookups 00208 * @return Swift_DependencyContainer 00209 * @see addConstructorValue(), addConstructorLookup() 00210 */ 00211 public function withDependencies(array $lookups) 00212 { 00213 $endPoint =& $this->_getEndPoint(); 00214 $endPoint['args'] = array(); 00215 foreach ($lookups as $lookup) 00216 { 00217 $this->addConstructorLookup($lookup); 00218 } 00219 return $this; 00220 } 00221 00222 /** 00223 * Specify a literal (non looked up) value for the constructor of the 00224 * previously registered item. 00225 * 00226 * @param mixed $value 00227 * @return Swift_DependencyContainer 00228 * @see withDependencies(), addConstructorLookup() 00229 */ 00230 public function addConstructorValue($value) 00231 { 00232 $endPoint =& $this->_getEndPoint(); 00233 if (!isset($endPoint['args'])) 00234 { 00235 $endPoint['args'] = array(); 00236 } 00237 $endPoint['args'][] = array('type' => 'value', 'item' => $value); 00238 return $this; 00239 } 00240 00241 /** 00242 * Specify a dependency lookup for the constructor of the previously 00243 * registered item. 00244 * 00245 * @param string $lookup 00246 * @return Swift_DependencyContainer 00247 * @see withDependencies(), addConstructorValue() 00248 */ 00249 public function addConstructorLookup($lookup) 00250 { 00251 $endPoint =& $this->_getEndPoint(); 00252 if (!isset($this->_endPoint['args'])) 00253 { 00254 $endPoint['args'] = array(); 00255 } 00256 $endPoint['args'][] = array('type' => 'lookup', 'item' => $lookup); 00257 return $this; 00258 } 00259 00260 // -- Private methods 00261 00262 /** Get the literal value with $itemName */ 00263 private function _getValue($itemName) 00264 { 00265 return $this->_store[$itemName]['value']; 00266 } 00267 00268 /** Resolve an alias to another item */ 00269 private function _createAlias($itemName) 00270 { 00271 return $this->lookup($this->_store[$itemName]['ref']); 00272 } 00273 00274 /** Create a fresh instance of $itemName */ 00275 private function _createNewInstance($itemName) 00276 { 00277 $reflector = new ReflectionClass($this->_store[$itemName]['className']); 00278 if ($reflector->getConstructor()) 00279 { 00280 return $reflector->newInstanceArgs( 00281 $this->createDependenciesFor($itemName) 00282 ); 00283 } 00284 else 00285 { 00286 return $reflector->newInstance(); 00287 } 00288 } 00289 00290 /** Create and register a shared instance of $itemName */ 00291 private function _createSharedInstance($itemName) 00292 { 00293 if (!isset($this->_store[$itemName]['instance'])) 00294 { 00295 $this->_store[$itemName]['instance'] = $this->_createNewInstance($itemName); 00296 } 00297 return $this->_store[$itemName]['instance']; 00298 } 00299 00300 /** Get the current endpoint in the store */ 00301 private function &_getEndPoint() 00302 { 00303 if (!isset($this->_endPoint)) 00304 { 00305 throw new BadMethodCallException( 00306 'Component must first be registered by calling register()' 00307 ); 00308 } 00309 return $this->_endPoint; 00310 } 00311 00312 /** Get an argument list with dependencies resolved */ 00313 private function _resolveArgs(array $args) 00314 { 00315 $resolved = array(); 00316 foreach ($args as $argDefinition) 00317 { 00318 switch ($argDefinition['type']) 00319 { 00320 case 'lookup': 00321 $resolved[] = $this->_lookupRecursive($argDefinition['item']); 00322 break; 00323 case 'value': 00324 $resolved[] = $argDefinition['item']; 00325 break; 00326 } 00327 } 00328 return $resolved; 00329 } 00330 00331 /** Resolve a single dependency with an collections */ 00332 private function _lookupRecursive($item) 00333 { 00334 if (is_array($item)) 00335 { 00336 $collection = array(); 00337 foreach ($item as $k => $v) 00338 { 00339 $collection[$k] = $this->_lookupRecursive($v); 00340 } 00341 return $collection; 00342 } 00343 else 00344 { 00345 return $this->lookup($item); 00346 } 00347 } 00348 00349 }
1.8.0