Created
February 1, 2015 13:26
-
-
Save StanAngeloff/94f994ee3de17b4836ae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* (c) PSP UK Group Ltd. <[email protected]> | |
* | |
* For the full copyright and license information, | |
* please view the LICENSE file that was distributed with this source code. | |
*/ | |
namespace Psp\Bundle\PspFrameworkBundle\DependencyInjection\Compiler; | |
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | |
use Symfony\Component\DependencyInjection\ContainerBuilder; | |
/** | |
* A compiler pass which fixes a bug in JMS AOP where interceptors are attached to the wrong class. | |
* | |
* If a method is intercepted on a class which inherits the method from a parent class, | |
* the interceptors definition attaches it to the child class instead of the parent. E.g., | |
* | |
* class FriendlyHi { function greet() { } } | |
* class PoliteHello extends FriendlyHi { } | |
* | |
* On intercepting greet(..), the method is wrongly attached to PoliteHello instead of FriendlyHi. | |
*/ | |
final class ReplaceAbstractAopInterceptorsPass implements CompilerPassInterface | |
{ | |
# {{{ CompilerPassInterface | |
/** | |
* {@inheritdoc} | |
* | |
* @SuppressWarnings(PMD.CyclomaticComplexity) | |
* @SuppressWarnings(PMD.ElseExpression) | |
* @SuppressWarnings(PMD.LongVariableName) | |
*/ | |
public function process(ContainerBuilder $container) | |
{ | |
if (( ! $container->hasDefinition($loaderServiceName = 'jms_aop.interceptor_loader'))) { | |
return; | |
} | |
$definition = $container->getDefinition($loaderServiceName); | |
$arguments = $definition->getArguments(); | |
if (empty ($arguments[$index = 1])) { | |
return; | |
} | |
$interceptors = array(); | |
foreach ($arguments[$index] as $className => $methodInterceptors) { | |
$performMerge = false; | |
$reflectClass = null; | |
try { | |
$reflectClass = new \ReflectionClass($className); | |
} catch (\ReflectionException $exception) { | |
# Noop. | |
} | |
foreach ($methodInterceptors as $methodName => $interceptorServiceNames) { | |
try { | |
if (isset ($reflectClass)) { | |
$reflectMethod = $reflectClass->getMethod($methodName); | |
# If the class the method belongs to is different from the one recorded | |
# in the interceptor loader, use the former. | |
if (strcmp($reflectMethod->class, $className) !== 0) { | |
$className = $reflectMethod->class; | |
$performMerge = true; | |
} | |
} | |
} catch (\ReflectionException $exception) { | |
# Noop. | |
} | |
# If we updated the class name, we also wish to merge any existing services with new ones. | |
if ($performMerge && isset ($interceptors[$className][$methodName])) { | |
$interceptors[$className][$methodName] = array_values( | |
array_unique( | |
array_merge( | |
array_values($interceptors[$className][$methodName]), | |
array_values($interceptorServiceNames) | |
) | |
) | |
); | |
} else { | |
$interceptors[$className][$methodName] = $interceptorServiceNames; | |
} | |
} | |
} | |
$definition->replaceArgument($index, $interceptors); | |
} | |
# }}} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment