/** * Retrieve a new instance of a class * * Forces retrieval of a discrete instance of the given class, using the * constructor parameters provided. * * @param mixed $name Class name or service alias * @param array $params Parameters to pass to the constructor * @param bool $isShared * @return object|null */ public function newInstance($name, array $params = array(), $isShared = true) { // localize dependencies $definitions = $this->definitions; $instanceManager = $this->instanceManager(); if ($instanceManager->hasAlias($name)) { $class = $instanceManager->getClassFromAlias($name); $alias = $name; } else { $class = $name; $alias = null; } array_push($this->instanceContext, array('NEW', $class, $alias)); if (!$definitions->hasClass($class)) { $aliasMsg = $alias ? '(specified by alias ' . $alias . ') ' : ''; throw new Exception\ClassNotFoundException('Class ' . $aliasMsg . $class . ' could not be located in provided definitions.'); } $instantiator = $definitions->getInstantiator($class); $injectionMethods = $definitions->getMethods($class); $supertypeInjectionMethods = array(); foreach ($definitions->getClassSupertypes($class) as $supertype) { $supertypeInjectionMethods[$supertype] = $definitions->getMethods($supertype); } if ($instantiator === '__construct') { $instance = $this->createInstanceViaConstructor($class, $params, $alias); if (array_key_exists('__construct', $injectionMethods)) { unset($injectionMethods['__construct']); } } elseif (is_callable($instantiator, false)) { $instance = $this->createInstanceViaCallback($instantiator, $params, $alias); } else { if (is_array($instantiator)) { $msg = sprintf('Invalid instantiator: %s::%s() is not callable.', isset($instantiator[0]) ? $instantiator[0] : 'NoClassGiven', isset($instantiator[1]) ? $instantiator[1] : 'NoMethodGiven'); } else { $msg = sprintf('Invalid instantiator of type "%s" for "%s".', gettype($instantiator), $name); } throw new Exception\RuntimeException($msg); } if ($isShared) { if ($params) { $this->instanceManager->addSharedInstanceWithParameters($instance, $name, $params); } else { $this->instanceManager->addSharedInstance($instance, $name); } } $this->handleInjectDependencies($instance, $class, $injectionMethods, $supertypeInjectionMethods, $params, $alias); array_pop($this->instanceContext); return $instance; }
/** * Retrieve a new instance of a class * * Forces retrieval of a discrete instance of the given class, using the * constructor parameters provided. * * @param mixed $name Class name or service alias * @param array $params Parameters to pass to the constructor * @param bool $isShared * @return object|null */ public function newInstance($name, array $params = array(), $isShared = true) { // localize dependencies (this also will serve as poka-yoke) $definitions = $this->definitions; $instanceManager = $this->instanceManager(); if ($instanceManager->hasAlias($name)) { $class = $instanceManager->getClassFromAlias($name); $alias = $name; } else { $class = $name; $alias = null; } array_push($this->instanceContext, array('NEW', $class, $alias)); if (!$definitions->hasClass($class)) { $aliasMsg = $alias ? '(specified by alias ' . $alias . ') ' : ''; throw new Exception\ClassNotFoundException('Class ' . $aliasMsg . $class . ' could not be located in provided definition.'); } $instantiator = $definitions->getInstantiator($class); $injectionMethods = $definitions->getMethods($class); if ($instantiator === '__construct') { $object = $this->createInstanceViaConstructor($class, $params, $alias); if (array_key_exists('__construct', $injectionMethods)) { unset($injectionMethods['__construct']); } } elseif (is_callable($instantiator)) { $object = $this->createInstanceViaCallback($instantiator, $params, $alias); } else { throw new Exception\RuntimeException('Invalid instantiator'); } if ($isShared) { if ($params) { $this->instanceManager->addSharedInstanceWithParameters($object, $name, $params); } else { $this->instanceManager->addSharedInstance($object, $name); } } if ($injectionMethods) { foreach ($injectionMethods as $injectionMethod => $methodIsRequired) { if ($injectionMethod !== '__construct') { $this->handleInjectionMethodForObject($object, $injectionMethod, $params, $alias, $methodIsRequired); } } $instanceConfiguration = $instanceManager->getConfiguration($name); if ($instanceConfiguration['injections']) { $objectsToInject = array(); foreach ($instanceConfiguration['injections'] as $classAliasToInject) { $objectsToInject[] = $this->get($classAliasToInject, $params); } if ($objectsToInject) { // @todo this needs to be optimized foreach ($objectsToInject as $objectToInject) { foreach ($injectionMethods as $injectionMethod => $methodIsRequired) { if ($methodParams = $definitions->getMethodParameters($class, $injectionMethod)) { foreach ($methodParams as $methodParam) { if ($this->isSubclassOf(get_class($objectToInject), $methodParam[1])) { $callParams = $this->resolveMethodParameters(get_class($object), $injectionMethod, array($methodParam[0] => $objectToInject), false, $alias, true); if ($callParams) { call_user_func_array(array($object, $injectionMethod), $callParams); } continue 3; } } } } } } } } array_pop($this->instanceContext); return $object; }
/** * Retrieve a new instance of a class * * Forces retrieval of a discrete instance of the given class, using the * constructor parameters provided. * * @param mixed $name Class name or service alias * @param array $params Parameters to pass to the constructor * @param bool $isShared * @return object|null */ public function newInstance($name, array $params = array(), $isShared = true) { // localize dependencies (this also will serve as poka-yoke) $definitions = $this->definitions; $instanceManager = $this->instanceManager(); if ($instanceManager->hasAlias($name)) { $class = $instanceManager->getClassFromAlias($name); $alias = $name; } else { $class = $name; $alias = null; } array_push($this->instanceContext, array('NEW', $class, $alias)); if (!$definitions->hasClass($class)) { $aliasMsg = $alias ? '(specified by alias ' . $alias . ') ' : ''; throw new Exception\ClassNotFoundException('Class ' . $aliasMsg . $class . ' could not be located in provided definitions.'); } $instantiator = $definitions->getInstantiator($class); $injectionMethods = $definitions->getMethods($class); $supertypeInjectionMethods = array(); foreach ($definitions->getClassSupertypes($class) as $supertype) { $supertypeInjectionMethods[$supertype] = $definitions->getMethods($supertype); } if ($instantiator === '__construct') { $instance = $this->createInstanceViaConstructor($class, $params, $alias); if (array_key_exists('__construct', $injectionMethods)) { unset($injectionMethods['__construct']); } } elseif (is_callable($instantiator, false)) { $instance = $this->createInstanceViaCallback($instantiator, $params, $alias); } else { if (is_array($instantiator)) { $msg = sprintf('Invalid instantiator: %s::%s() is not callable.', isset($instantiator[0]) ? $instantiator[0] : 'NoClassGiven', isset($instantiator[1]) ? $instantiator[1] : 'NoMethodGiven'); } else { $msg = 'Invalid instantiator'; } throw new \RuntimeException($msg); } if ($isShared) { if ($params) { $this->instanceManager->addSharedInstanceWithParameters($instance, $name, $params); } else { $this->instanceManager->addSharedInstance($instance, $name); } } if ($injectionMethods || $supertypeInjectionMethods) { foreach ($injectionMethods as $injectionMethod => $methodIsRequired) { if ($injectionMethod !== '__construct') { $this->handleInjectionMethodForInstance($instance, $injectionMethod, $params, $alias, $methodIsRequired); } } foreach ($supertypeInjectionMethods as $supertype => $supertypeInjectionMethod) { foreach ($supertypeInjectionMethod as $injectionMethod => $methodIsRequired) { if ($injectionMethod !== '__construct') { $this->handleInjectionMethodForInstance($instance, $injectionMethod, $params, $alias, $methodIsRequired, $supertype); } } } $instanceConfiguration = $instanceManager->getConfiguration($name); if ($instanceConfiguration['injections']) { $objectsToInject = $methodsToCall = array(); foreach ($instanceConfiguration['injections'] as $injectName => $injectValue) { if (is_int($injectName) && is_string($injectValue)) { $objectsToInject[] = $this->get($injectValue, $params); } elseif (is_string($injectName) && is_array($injectValue)) { if (is_string(key($injectValue))) { $methodsToCall[] = array('method' => $injectName, 'args' => $injectValue); } else { foreach ($injectValue as $methodCallArgs) { $methodsToCall[] = array('method' => $injectName, 'args' => $methodCallArgs); } } } elseif (is_object($injectValue)) { $objectsToInject[] = $injectValue; } elseif (is_int($injectName) && is_array($injectValue)) { // @todo must find method name somehow throw new Exception\RuntimeException('An injection was provided with a keyed index and an array of data, try using' . ' the name of a particular method as a key for your injection data.'); } } if ($objectsToInject) { foreach ($objectsToInject as $objectToInject) { foreach ($injectionMethods as $injectionMethod => $methodIsRequired) { $methodParams = $definitions->getMethodParameters($class, $injectionMethod); if ($methodParams) { foreach ($methodParams as $methodParam) { if (get_class($objectToInject) == $methodParam[1] || $this->isSubclassOf(get_class($objectToInject), $methodParam[1])) { $callParams = $this->resolveMethodParameters(get_class($instance), $injectionMethod, array($methodParam[0] => $objectToInject), false, $alias, true); if ($callParams) { call_user_func_array(array($instance, $injectionMethod), $callParams); } continue 3; } } } } } } if ($methodsToCall) { foreach ($methodsToCall as $methodInfo) { $callParams = $this->resolveMethodParameters(get_class($instance), $methodInfo['method'], $methodInfo['args'], false, $alias, true); call_user_func_array(array($instance, $methodInfo['method']), $callParams); } } } } array_pop($this->instanceContext); return $instance; }