From 6b31d2a028e506289b4ebe4feffdc569e81dd36b Mon Sep 17 00:00:00 2001 From: Andy Raines Date: Fri, 9 Dec 2016 12:15:36 +0000 Subject: [PATCH 1/3] [Console] fixed BC issue with static closures Static closures were unable to be used in Command::setCode since #14431. This change fixes the BC break and ensures static closures can still be used. --- .../Component/Console/Command/Command.php | 3 ++- .../Console/Tests/Command/CommandTest.php | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index aadc60cdffec3..a519489f6cef4 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -283,7 +283,8 @@ public function setCode($code) if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { - $code = \Closure::bind($code, $this); + // Cannot bind static closures for PHP<7.0 so it may fail + $code = @\Closure::bind($code, $this); } } diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index ff0c8d4791f57..e64d498720be8 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -335,6 +335,29 @@ public function testSetCodeBindToClosure($previouslyBound, $expected) $this->assertEquals('interact called'.PHP_EOL.$expected.PHP_EOL, $tester->getDisplay()); } + public function testSetCodeWithStaticClosure() + { + $command = new \TestCommand(); + $command->setCode(self::createClosure()); + $tester = new CommandTester($command); + $tester->execute(array()); + + if (version_compare(phpversion(), '7.0.0', '<')) { + // Cannot bind static closures in PHP 5 + $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay()); + } else { + // Can bind static closures in PHP 7 + $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay()); + } + } + + private static function createClosure() + { + return function (InputInterface $input, OutputInterface $output) { + $output->writeln(isset($this) ? 'bound' : 'not bound'); + }; + } + public function testSetCodeWithNonClosureCallable() { $command = new \TestCommand(); From bffae93f1640a3f6d40f95560f29d620babaf5e9 Mon Sep 17 00:00:00 2001 From: Andy Raines Date: Fri, 9 Dec 2016 18:23:25 +0000 Subject: [PATCH 2/3] Use PHP_VERSION_ID instead of phpversion() --- src/Symfony/Component/Console/Tests/Command/CommandTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index e64d498720be8..4378847369a75 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -342,7 +342,7 @@ public function testSetCodeWithStaticClosure() $tester = new CommandTester($command); $tester->execute(array()); - if (version_compare(phpversion(), '7.0.0', '<')) { + if (PHP_VERSION_ID < 70000) { // Cannot bind static closures in PHP 5 $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay()); } else { From a0d010825cc37ea078de946be9f0d5d86c30a9d2 Mon Sep 17 00:00:00 2001 From: Andy Raines Date: Tue, 13 Dec 2016 12:36:44 +0000 Subject: [PATCH 3/3] Clarify fix --- src/Symfony/Component/Console/Command/Command.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index a519489f6cef4..bbac86a5a293e 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -283,8 +283,15 @@ public function setCode($code) if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { - // Cannot bind static closures for PHP<7.0 so it may fail - $code = @\Closure::bind($code, $this); + if (PHP_VERSION_ID < 70000) { + // Bug in PHP5: https://bugs.php.net/bug.php?id=64761 + // This means that we cannot bind static closures and therefore we must + // ignore any errors here. There is no way to test if the closure is + // bindable. + $code = @\Closure::bind($code, $this); + } else { + $code = \Closure::bind($code, $this); + } } }