From 33f722d86ec4d2b5b6696c385505898ba58d91d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 6 Aug 2019 15:47:21 +0200 Subject: [PATCH] [ProxyManagerBridge] Polyfill for unmaintained version --- composer.json | 3 +- .../LazyProxy/PhpDumper/ProxyDumper.php | 4 + .../Legacy/ProxiedMethodReturnExpression.php | 73 +++++++++++++++++++ .../LazyProxy/PhpDumper/ProxyDumperTest.php | 15 ++++ src/Symfony/Bridge/ProxyManager/composer.json | 1 + 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bridge/ProxyManager/Legacy/ProxiedMethodReturnExpression.php diff --git a/composer.json b/composer.json index 919941f984d6..fe465e81e155 100644 --- a/composer.json +++ b/composer.json @@ -123,7 +123,8 @@ "Symfony\\Component\\": "src/Symfony/Component/" }, "classmap": [ - "src/Symfony/Component/Intl/Resources/stubs" + "src/Symfony/Component/Intl/Resources/stubs", + "src/Symfony/Bridge/ProxyManager/Legacy/ProxiedMethodReturnExpression.php" ], "exclude-from-classmap": [ "**/Tests/" diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 7acc1c65420b..d9cd210263cc 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -112,6 +112,10 @@ public function getProxyCode(Definition $definition) ); } + if (version_compare(self::getProxyManagerVersion(), '2.5', '<')) { + $code = str_replace(' \Closure::bind(function ', ' \Closure::bind(static function ', $code); + } + return $code; } diff --git a/src/Symfony/Bridge/ProxyManager/Legacy/ProxiedMethodReturnExpression.php b/src/Symfony/Bridge/ProxyManager/Legacy/ProxiedMethodReturnExpression.php new file mode 100644 index 000000000000..e3d98d800301 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/Legacy/ProxiedMethodReturnExpression.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ProxyManager\Generator\Util; + +use Composer\Autoload\ClassLoader; +use ProxyManager\Version; + +if (class_exists(Version::class) && version_compare(\defined(Version::class.'::VERSION') ? Version::VERSION : Version::getVersion(), '2.5', '<')) { + /** + * Utility class to generate return expressions in method, given a method signature. + * + * This is required since return expressions may be forbidden by the method signature (void). + * + * @author Marco Pivetta + * @license MIT + * + * @see https://github.com/Ocramius/ProxyManager + */ + final class ProxiedMethodReturnExpression + { + public static function generate(string $returnedValueExpression, ?\ReflectionMethod $originalMethod): string + { + $originalReturnType = null === $originalMethod ? null : $originalMethod->getReturnType(); + + $originalReturnTypeName = null === $originalReturnType ? null : $originalReturnType->getName(); + + if ('void' === $originalReturnTypeName) { + return $returnedValueExpression.";\nreturn;"; + } + + return 'return '.$returnedValueExpression.';'; + } + } +} else { + // Fallback to the original class by unregistering this file from composer class loader + $getComposerClassLoader = static function ($functionLoader) use (&$getComposerClassLoader) { + if (\is_array($functionLoader)) { + $functionLoader = $functionLoader[0]; + } + if (!\is_object($functionLoader)) { + return; + } + if ($functionLoader instanceof ClassLoader) { + return $functionLoader; + } + if ($functionLoader instanceof \Symfony\Component\Debug\DebugClassLoader) { + return $getComposerClassLoader($functionLoader->getClassLoader()); + } + if ($functionLoader instanceof \Symfony\Component\ErrorHandler\DebugClassLoader) { + return $getComposerClassLoader($functionLoader->getClassLoader()); + } + }; + + $classLoader = null; + $functions = spl_autoload_functions(); + while (null === $classLoader && $functions) { + $classLoader = $getComposerClassLoader(array_shift($functions)); + } + $getComposerClassLoader = null; + + if (null !== $classLoader) { + $classLoader->addClassMap([ProxiedMethodReturnExpression::class => null]); + $classLoader->loadClass(ProxiedMethodReturnExpression::class); + } +} diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 5328c9ae1227..e3e40fdbcfbc 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\ProxyManager\Tests\LazyProxy\PhpDumper; use PHPUnit\Framework\TestCase; +use ProxyManager\Version; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -63,6 +64,20 @@ public function testGetProxyCode() ); } + public function testStaticBinding() + { + if (!class_exists(Version::class) || version_compare(\defined(Version::class.'::VERSION') ? Version::VERSION : Version::getVersion(), '2.1', '<')) { + $this->markTestSkipped('ProxyManager prior to version 2.1 does not support static binding'); + } + + $definition = new Definition(__CLASS__); + $definition->setLazy(true); + + $code = $this->dumper->getProxyCode($definition); + + $this->assertStringContainsString('\Closure::bind(static function (\PHPUnit\Framework\TestCase $instance) {', $code); + } + public function testDeterministicProxyCode() { $definition = new Definition(__CLASS__); diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 7e34cd90b513..4adc5c063f89 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -25,6 +25,7 @@ }, "autoload": { "psr-4": { "Symfony\\Bridge\\ProxyManager\\": "" }, + "classmap": [ "Legacy/ProxiedMethodReturnExpression.php" ], "exclude-from-classmap": [ "/Tests/" ]