Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/di-code-generator-fixes-rebased' of https://gith…
Browse files Browse the repository at this point in the history
…ub.com/Ocramius/zf2 into hotfix/di-generator
  • Loading branch information
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 160 deletions.
9 changes: 3 additions & 6 deletions src/Definition/CompilerDefinition.php
Expand Up @@ -92,7 +92,7 @@ public function addCodeScannerFile(FileScanner $fileScanner)
if ($this->directoryScanner == null) {
$this->directoryScanner = new DirectoryScanner();
}

$this->directoryScanner->addFileScanner($fileScanner);
}

Expand All @@ -103,8 +103,8 @@ public function addCodeScannerFile(FileScanner $fileScanner)
*/
public function compile()
{
/*
* @var $classScanner \Zend\Code\Scanner\DerivedClassScanner
/*
* @var $classScanner \Zend\Code\Scanner\DerivedClassScanner
*/
foreach ($this->directoryScanner->getClassNames() as $class) {
$this->processClass($class);
Expand Down Expand Up @@ -246,9 +246,6 @@ protected function processClass($class)
}
}
}


//var_dump($this->classes);
}

protected function processParams(&$def, Reflection\ClassReflection $rClass, Reflection\MethodReflection $rMethod)
Expand Down
9 changes: 3 additions & 6 deletions src/Definition/RuntimeDefinition.php
Expand Up @@ -52,7 +52,7 @@ public function setIntrospectionStrategy(IntrospectionStrategy $introspectionStr
{
$this->introspectionStrategy = $introspectionStrategy;
}

/**
* @return IntrospectionStrategy
*/
Expand Down Expand Up @@ -82,7 +82,7 @@ public function forceLoadClass($class)

/**
* Retrieves registered classes names
*
*
* @return array
*/
public function getClasses()
Expand All @@ -101,7 +101,7 @@ public function hasClass($class)
if ($this->explicitLookups === true) {
return (array_key_exists($class, $this->classes));
}

return class_exists($class) || interface_exists($class);
}

Expand Down Expand Up @@ -324,9 +324,6 @@ protected function processClass($class)
}
}
}


//var_dump($this->classes);
}

protected function processParams(&$def, Reflection\ClassReflection $rClass, Reflection\MethodReflection $rMethod)
Expand Down
26 changes: 21 additions & 5 deletions src/Di.php
Expand Up @@ -229,7 +229,7 @@ public function newInstance($name, array $params = array(), $isShared = true)
public function injectDependencies($instance, array $params = array())
{
$definitions = $this->definitions();
$class = get_class($instance);
$class = $this->getClass($instance);
$injectionMethods = array(
$class => ($definitions->hasClass($class)) ? $definitions->getMethods($class) : array()
);
Expand Down Expand Up @@ -300,7 +300,8 @@ protected function handleInjectDependencies($instance, $injectionMethods, $param
$methodParams = $definitions->getMethodParameters($type, $typeInjectionMethod);
if ($methodParams) {
foreach ($methodParams as $methodParam) {
if (get_class($objectToInject) == $methodParam[1] || $this->isSubclassOf(get_class($objectToInject), $methodParam[1])) {
$objectToInjectClass = $this->getClass($objectToInject);
if ($objectToInjectClass == $methodParam[1] || $this->isSubclassOf($objectToInjectClass, $methodParam[1])) {
if ($this->resolveAndCallInjectionMethodForInstance($instance, $typeInjectionMethod, array($methodParam[0] => $objectToInject), $instanceAlias, true, $type)) {
$calledMethods[$typeInjectionMethod] = true;
}
Expand All @@ -315,7 +316,7 @@ protected function handleInjectDependencies($instance, $injectionMethods, $param
}
if ($methodsToCall) {
foreach ($methodsToCall as $methodInfo) {
$this->resolveAndCallInjectionMethodForInstance($instance, $methodInfo['method'], $methodInfo['args'], $instanceAlias, true, get_class($instance));
$this->resolveAndCallInjectionMethodForInstance($instance, $methodInfo['method'], $methodInfo['args'], $instanceAlias, true, $instanceClass);
}
}
}
Expand Down Expand Up @@ -375,7 +376,7 @@ protected function createInstanceViaCallback($callback, $params, $alias)
}

if (is_array($callback)) {
$class = (is_object($callback[0])) ? get_class($callback[0]) : $callback[0];
$class = (is_object($callback[0])) ? $this->getClass($callback[0]) : $callback[0];
$method = $callback[1];
} elseif (is_string($callback) && strpos($callback, '::') !== false) {
list($class, $method) = explode('::', $callback, 2);
Expand All @@ -402,7 +403,7 @@ protected function createInstanceViaCallback($callback, $params, $alias)
*/
protected function resolveAndCallInjectionMethodForInstance($instance, $method, $params, $alias, $methodIsRequired, $methodClass = null)
{
$methodClass = ($methodClass) ?: get_class($instance);
$methodClass = ($methodClass) ?: $this->getClass($instance);
$callParameters = $this->resolveMethodParameters($methodClass, $method, $params, $alias, $methodIsRequired);
if ($callParameters == false) {
return false;
Expand Down Expand Up @@ -657,6 +658,21 @@ protected function resolveMethodParameters($class, $method, array $callTimeUserP
return $resolvedParams; // return ordered list of parameters
}

/**
* Utility method used to retrieve the class of a particular instance. This is here to allow extending classes to
* override how class names are resolved
*
* @internal this method is used by the ServiceLocator\DependencyInjectorProxy class to interact with instances
* and is a hack to be used internally until a major refactor does not split the `resolveMethodParameters`. Do not
* rely on its functionality.
* @param Object $instance
* @return string
*/
protected function getClass($instance)
{
return get_class($instance);
}

/**
* @see https://bugs.php.net/bug.php?id=53727
*
Expand Down
149 changes: 67 additions & 82 deletions src/ServiceLocator/DependencyInjectorProxy.php
Expand Up @@ -5,6 +5,9 @@
use Zend\Di\Di;
use Zend\Di\Exception;

/**
* Proxy used to analyze how instances are created by a given Di.
*/
class DependencyInjectorProxy extends Di
{
/**
Expand All @@ -22,10 +25,6 @@ public function __construct(Di $di)
$this->instanceManager = $di->instanceManager();
}

/**
* Methods with functionality overrides
*/

/**
* Override, as we want it to use the functionality defined in the proxy
*
Expand All @@ -35,19 +34,27 @@ public function __construct(Di $di)
*/
public function get($name, array $params = array())
{
$im = $this->instanceManager();
return parent::get($name, $params);
}
/**
* {@inheritDoc}
*/
public function newInstance($name, array $params = array(), $isShared = true)
{
$instance = parent::newInstance($name, $params, $isShared);

if ($params) {
$fastHash = $im->hasSharedInstanceWithParameters($name, $params, true);
if ($fastHash) {
return $im->getSharedInstanceWithParameters(null, array(), $fastHash);
}
} else {
if ($im->hasSharedInstance($name, $params)) {
return $im->getSharedInstance($name, $params);
if ($instance instanceof GeneratorInstance) {
/* @var $instance GeneratorInstance */
$instance->setShared($isShared);

// When a callback is used, we don't know instance the class name.
// That's why we assume $name as the instance alias
if (null === $instance->getName()) {
$instance->setAlias($name);
}
}
return $this->newInstance($name, $params);

return $instance;
}

/**
Expand All @@ -63,122 +70,100 @@ public function get($name, array $params = array())
public function createInstanceViaConstructor($class, $params, $alias = null)
{
$callParameters = array();

if ($this->di->definitions->hasMethod($class, '__construct')
&& (count($this->di->definitions->getMethodParameters($class, '__construct')) > 0)
) {
$callParameters = $this->resolveMethodParameters(
$class, '__construct', $params, true, $alias, true
);
$callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, true, true);
$callParameters = $callParameters ?: array();
}
return new GeneratorInstance($class, '__construct', $callParameters);

return new GeneratorInstance($class, $alias, '__construct', $callParameters);
}

/**
* Override instance creation via callback
*
* @param callback $callback
* @param null|array $params
* @param callback $callback
* @param null|array $params
* @param null|string $alias
* @return GeneratorInstance
* @throws Exception\InvalidCallbackException
*/
public function createInstanceViaCallback($callback, $params, $alias = null)
public function createInstanceViaCallback($callback, $params, $alias)
{
if (is_string($callback)) {
$callback = explode('::', $callback);
}

if (!is_callable($callback)) {
throw new Exception\InvalidCallbackException('An invalid constructor callback was provided');
}

if (!is_array($callback) || is_object($callback[0])) {
throw new Exception\InvalidCallbackException('For purposes of service locator generation, constructor callbacks must refer to static methods only');
throw new Exception\InvalidCallbackException(
'For purposes of service locator generation, constructor callbacks must refer to static methods only'
);
}

$class = $callback[0];
$method = $callback[1];

$callParameters = array();
if ($this->di->definitions->hasMethod($class, $method)) {
$callParameters = $this->resolveMethodParameters($class, $method, $params, true, $alias, true);
$callParameters = $this->resolveMethodParameters($class, $method, $params, $alias, true, true);
}

return new GeneratorInstance(null, $callback, $callParameters);
$callParameters = $callParameters ?: array();

return new GeneratorInstance(null, $alias, $callback, $callParameters);
}

/**
* Retrieve metadata for injectible methods
*
* @param string $class
* @param string $method
* @param array $params
* @param string $alias
* @return array
* {@inheritDoc}
*/
public function handleInjectionMethodForObject($class, $method, $params, $alias, $isRequired)
{
$callParameters = $this->resolveMethodParameters($class, $method, $params, false, $alias, $isRequired);
return array(
'method' => $method,
'params' => $callParameters,
'params' => $this->resolveMethodParameters($class, $method, $params, $alias, $isRequired),
);
}

/**
* Override new instance creation
*
* @param string $name
* @param array $params
* @param bool $isShared
* @return GeneratorInstance
* @throws Exception\ClassNotFoundException
* @throws Exception\RuntimeException
* {@inheritDoc}
*/
public function newInstance($name, array $params = array(), $isShared = true)
protected function resolveAndCallInjectionMethodForInstance($instance, $method, $params, $alias, $methodIsRequired, $methodClass = null)
{
$definition = $this->definitions();
$instanceManager = $this->instanceManager();

if ($instanceManager->hasAlias($name)) {
$class = $instanceManager->getClassFromAlias($name);
$alias = $name;
} else {
$class = $name;
$alias = null;
if (!$instance instanceof GeneratorInstance) {
return parent::resolveAndCallInjectionMethodForInstance($instance, $method, $params, $alias, $methodIsRequired, $methodClass);
}

if (!$definition->hasClass($class)) {
$aliasMsg = ($alias) ? '(specified by alias ' . $alias . ') ' : '';
throw new Exception\ClassNotFoundException(
'Class ' . $aliasMsg . $class . ' could not be located in provided definitions.'
);
}
/* @var $instance GeneratorInstance */
$methodClass = $instance->getClass();
$callParameters = $this->resolveMethodParameters($methodClass, $method, $params, $alias, $methodIsRequired);

$instantiator = $definition->getInstantiator($class);
$injectionMethods = $definition->getMethods($class);

if ($instantiator === '__construct') {
$object = $this->createInstanceViaConstructor($class, $params, $alias);
if (in_array('__construct', $injectionMethods)) {
unset($injectionMethods[array_search('__construct', $injectionMethods)]);
}
} elseif (is_callable($instantiator)) {
$object = $this->createInstanceViaCallback($instantiator, $params, $alias);
$object->setName($class);
} else {
throw new Exception\RuntimeException('Invalid instantiator');
if ($callParameters === false) {
$instance->addMethod(array(
'method' => $method,
'params' => $callParameters,
));
return true;
}

if ($injectionMethods) {
foreach ($injectionMethods as $injectionMethod) {
$methodMetadata[] = $this->handleInjectionMethodForObject($class, $injectionMethod, $params, $alias);
}
}
return false;
}

if ($isShared) {
if ($params) {
$instanceManager->addSharedInstanceWithParameters($object, $name, $params);
} else {
$instanceManager->addSharedInstance($object, $name);
}
/**
* {@inheritDoc}
*/
protected function getClass($instance)
{
if ($instance instanceof GeneratorInstance) {
/* @var $instance GeneratorInstance */
return $instance->getClass();
}

return $object;
return parent::getClass($instance);
}
}

0 comments on commit c18caa3

Please sign in to comment.