Skip to content

Instantly share code, notes, and snippets.

@StanAngeloff
Created February 1, 2015 13:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StanAngeloff/94f994ee3de17b4836ae to your computer and use it in GitHub Desktop.
Save StanAngeloff/94f994ee3de17b4836ae to your computer and use it in GitHub Desktop.
<?php
/**
* (c) PSP UK Group Ltd. <hello@psp-group.co.uk>
*
* 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