From c2863d516626b94adcfcda1de13df82828cae4a0 Mon Sep 17 00:00:00 2001 From: Ralph Schindler Date: Wed, 29 Jun 2011 10:59:01 -0500 Subject: [PATCH] Fixed Zend\Di\DependnecyInjector matching of preferred classes with is_subclass_of due to a bug in PHP: https://bugs.php.net/bug.php?id=53727 --- library/Zend/Di/DependencyInjector.php | 23 +++++++++++++++---- tests/Zend/Di/DependencyInjectorTest.php | 20 ++++++++++++++++ .../Di/TestAsset/PreferredImplClasses/A.php | 7 ++++++ .../TestAsset/PreferredImplClasses/BofA.php | 7 ++++++ .../Di/TestAsset/PreferredImplClasses/C.php | 12 ++++++++++ .../Di/TestAsset/PreferredImplClasses/D.php | 8 +++++++ 6 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 tests/Zend/Di/TestAsset/PreferredImplClasses/A.php create mode 100644 tests/Zend/Di/TestAsset/PreferredImplClasses/BofA.php create mode 100644 tests/Zend/Di/TestAsset/PreferredImplClasses/C.php create mode 100644 tests/Zend/Di/TestAsset/PreferredImplClasses/D.php diff --git a/library/Zend/Di/DependencyInjector.php b/library/Zend/Di/DependencyInjector.php index 54fa04d0f13..ccf6cc2651a 100755 --- a/library/Zend/Di/DependencyInjector.php +++ b/library/Zend/Di/DependencyInjector.php @@ -288,6 +288,20 @@ protected function handleInjectionMethodForObject($object, $method, $params, $al */ protected function resolveMethodParameters($class, $method, array $userParams, $isInstantiator, $alias) { + static $isSubclassFunc = null; + static $isSubclassFuncCache = null; + + $isSubclassFunc = function($class, $type) use (&$isSubclassFuncCache) { + /* @see https://bugs.php.net/bug.php?id=53727 */ + if ($isSubclassFuncCache === null) { + $isSubclassFuncCache = array(); + } + if (!array_key_exists($class, $isSubclassFuncCache)) { + $isSubclassFuncCache[$class] = class_parents($class, true) + class_implements($class, true); + } + return (isset($isSubclassFuncCache[$class][$type])); + }; + $resolvedParams = array(); $injectionMethodParameters = $this->definition->getInjectionMethodParameters($class, $method); @@ -296,7 +310,6 @@ protected function resolveMethodParameters($class, $method, array $userParams, $ $computedLookupParams = array(); foreach ($injectionMethodParameters as $name => $type) { - //$computedValueParams[$name] = null; // first consult user provided parameters if (isset($userParams[$name])) { @@ -326,9 +339,9 @@ protected function resolveMethodParameters($class, $method, array $userParams, $ foreach ($pInstances as $pInstance) { $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; - if ($pInstanceClass === $type || is_subclass_of($pInstanceClass, $type)) { + if ($pInstanceClass === $type || $isSubclassFunc($pInstanceClass, $type)) { $computedLookupParams[$name] = array($pInstance, $pInstanceClass); - continue; + continue 2; } } } @@ -339,9 +352,9 @@ protected function resolveMethodParameters($class, $method, array $userParams, $ foreach ($pInstances as $pInstance) { $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; - if ($pInstanceClass === $type || is_subclass_of($pInstanceClass, $type)) { + if ($pInstanceClass === $type || $isSubclassFunc($pInstanceClass, $type)) { $computedLookupParams[$name] = array($pInstance, $pInstanceClass); - continue; + continue 2; } } } diff --git a/tests/Zend/Di/DependencyInjectorTest.php b/tests/Zend/Di/DependencyInjectorTest.php index 697fdb30d47..0a6d3404d05 100755 --- a/tests/Zend/Di/DependencyInjectorTest.php +++ b/tests/Zend/Di/DependencyInjectorTest.php @@ -279,4 +279,24 @@ public function testNewInstanceThrowsExceptionWhenEnteringInMiddleOfCircularDepe $di->newInstance('ZendTest\Di\TestAsset\CircularClasses\D'); } + /** + * Fix for PHP bug in is_subclass_of + * + * @see https://bugs.php.net/bug.php?id=53727 + */ + public function testNewInstanceWillUsePreferredClassForInterfaceHints() + { + $di = new DependencyInjector(); + $di->getInstanceManager()->addPreferredInstance( + 'ZendTest\Di\TestAsset\PreferredImplClasses\A', + 'ZendTest\Di\TestAsset\PreferredImplClasses\BofA' + ); + + $c = $di->get('ZendTest\Di\TestAsset\PreferredImplClasses\C'); + $a = $c->a; + $this->assertType('ZendTest\Di\TestAsset\PreferredImplClasses\BofA', $a); + $d = $di->get('ZendTest\Di\TestAsset\PreferredImplClasses\D'); + $this->assertSame($a, $d->a); + } + } diff --git a/tests/Zend/Di/TestAsset/PreferredImplClasses/A.php b/tests/Zend/Di/TestAsset/PreferredImplClasses/A.php new file mode 100644 index 00000000000..15dd8604a60 --- /dev/null +++ b/tests/Zend/Di/TestAsset/PreferredImplClasses/A.php @@ -0,0 +1,7 @@ +a = $a; + } +} \ No newline at end of file diff --git a/tests/Zend/Di/TestAsset/PreferredImplClasses/D.php b/tests/Zend/Di/TestAsset/PreferredImplClasses/D.php new file mode 100644 index 00000000000..c5993a27932 --- /dev/null +++ b/tests/Zend/Di/TestAsset/PreferredImplClasses/D.php @@ -0,0 +1,8 @@ +