From 336ddc088b86a12068d25585f1e54fe217efcd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Wed, 5 Jul 2017 00:03:30 +0100 Subject: [PATCH] Scope PHP binaries --- src/Scoper/PhpScoper.php | 23 ++++++- tests/Scoper/PhpScoperTest.php | 109 ++++++++++++++++++++++++++++++--- 2 files changed, 123 insertions(+), 9 deletions(-) diff --git a/src/Scoper/PhpScoper.php b/src/Scoper/PhpScoper.php index ff55a78f..4614cd12 100644 --- a/src/Scoper/PhpScoper.php +++ b/src/Scoper/PhpScoper.php @@ -31,7 +31,11 @@ final class PhpScoper implements Scoper { /** @internal */ - const FILE_PATTERN = '/.*\.php$/'; + const FILE_PATH_PATTERN = '/.*\.php$/'; + /** @internal */ + const NOT_FILE_BINARY = '/\..+?$/'; + /** @internal */ + const PHP_BINARY = '/^#!.+?php.*\n{1,}<\?php/'; private $parser; private $decoratedScoper; @@ -51,7 +55,7 @@ public function __construct(Parser $parser, Scoper $decoratedScoper) */ public function scope(string $filePath, string $prefix): string { - if (1 !== preg_match(self::FILE_PATTERN, $filePath)) { + if (false === $this->isPhpFile($filePath)) { return $this->decoratedScoper->scope($filePath, $prefix); } @@ -67,6 +71,21 @@ public function scope(string $filePath, string $prefix): string return $prettyPrinter->prettyPrintFile($statements)."\n"; } + private function isPhpFile(string $filePath): bool + { + if (1 === preg_match(self::FILE_PATH_PATTERN, $filePath)) { + return true; + } + + if (1 === preg_match(self::NOT_FILE_BINARY, basename($filePath))) { + return false; + } + + $content = file_get_contents($filePath); + + return 1 === preg_match(self::PHP_BINARY, $content); + } + private function createTraverser(string $prefix): NodeTraverserInterface { $traverser = new NodeTraverser(); diff --git a/tests/Scoper/PhpScoperTest.php b/tests/Scoper/PhpScoperTest.php index 1d3a0c7e..c2fbb0bf 100644 --- a/tests/Scoper/PhpScoperTest.php +++ b/tests/Scoper/PhpScoperTest.php @@ -45,6 +45,16 @@ class PhpScoperTest extends TestCase */ private $tmp; + /** + * @var Scoper|ObjectProphecy + */ + private $decoratedScoperProphecy; + + /** + * @var Scoper + */ + private $decoratedScoper; + /** * @inheritdoc */ @@ -60,6 +70,9 @@ public function setUp() $this->tmp = make_tmp_dir('scoper', __CLASS__); } + $this->decoratedScoperProphecy = $this->prophesize(Scoper::class); + $this->decoratedScoper = $this->decoratedScoperProphecy->reveal(); + chdir($this->tmp); } @@ -78,32 +91,114 @@ public function test_is_a_Scoper() $this->assertTrue(is_a(PhpScoper::class, Scoper::class, true)); } + public function test_can_scope_a_PHP_file() + { + $prefix = 'Humbug'; + + $filePath = escape_path($this->tmp.'/file.php'); + + $content = <<<'PHP' +echo "Humbug!"; +PHP; + + touch($filePath); + file_put_contents($filePath, $content); + + $expected = <<<'PHP' +echo "Humbug!"; + +PHP; + + $actual = $this->scoper->scope($filePath, $prefix); + + $this->assertSame($expected, $actual); + } + public function test_does_not_scope_file_if_is_not_a_PHP_file() { $filePath = 'file.yaml'; $prefix = 'Humbug'; - /** @var Scoper|ObjectProphecy $decoratedScoperProphecy */ - $decoratedScoperProphecy = $this->prophesize(Scoper::class); - $decoratedScoperProphecy + $this->decoratedScoperProphecy + ->scope($filePath, $prefix) + ->willReturn( + $expected = 'Scoped content' + ) + ; + + $scoper = new PhpScoper( + new FakeParser(), + $this->decoratedScoper + ); + + $actual = $scoper->scope($filePath, $prefix); + + $this->assertSame($expected, $actual); + + $this->decoratedScoperProphecy->scope(Argument::cetera())->shouldHaveBeenCalledTimes(1); + } + + public function test_can_scope_PHP_binary_files() + { + $prefix = 'Humbug'; + + $filePath = escape_path($this->tmp.'/hello'); + + $content = <<<'PHP' +#!/usr/bin/env php +scoper->scope($filePath, $prefix); + + $this->assertSame($expected, $actual); + } + + public function test_does_not_scope_a_non_PHP_binary_files() + { + $prefix = 'Humbug'; + + $filePath = escape_path($this->tmp.'/hello'); + + $content = <<<'PHP' +#!/usr/bin/env bash +decoratedScoperProphecy ->scope($filePath, $prefix) ->willReturn( $expected = 'Scoped content' ) ; - /** @var Scoper $decoratedScoper */ - $decoratedScoper = $decoratedScoperProphecy->reveal(); $scoper = new PhpScoper( new FakeParser(), - $decoratedScoper + $this->decoratedScoper ); $actual = $scoper->scope($filePath, $prefix); $this->assertSame($expected, $actual); - $decoratedScoperProphecy->scope(Argument::cetera())->shouldHaveBeenCalledTimes(1); + $this->decoratedScoperProphecy->scope(Argument::cetera())->shouldHaveBeenCalledTimes(1); } public function test_cannot_scope_an_invalid_PHP_file()