Skip to content

Commit 8d63d9b

Browse files
authored
Fix the whitelisting of classes (#263)
A change has been made in the whitelist behaviour in order to support the whitelisting of global classes: instead of blindly applying aliases with their `class_alias()` statements in the `scoper-autoload.php`, the whitelisted classes found are recorded and the `scoper-autoload.php` will contain all the `class_alias()` statements necessary. However the Scoper autoload dumper was not updated to reflect on that new API
1 parent 85c65e6 commit 8d63d9b

File tree

7 files changed

+253
-56
lines changed

7 files changed

+253
-56
lines changed

Makefile

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,23 @@ PHPSCOPER=bin/php-scoper.phar
5555
.PHONY: e2e_004
5656
e2e_004: ## Run end-to-end tests for the fixture set 004 — Source code case
5757
e2e_004: bin/php-scoper.phar
58-
$(PHPBIN) $(BOX) compile --working-dir fixtures/set004
58+
$(PHPBIN) $(BOX) compile --no-parallel --working-dir fixtures/set004
5959

6060
php build/set004/bin/greet.phar > build/set004/output
6161
diff fixtures/set004/expected-output build/set004/output
6262

6363
.PHONY: e2e_005
6464
e2e_005: ## Run end-to-end tests for the fixture set 005 — Third-party code case
6565
e2e_005: bin/php-scoper.phar fixtures/set005/vendor
66-
$(PHPBIN) $(BOX) compile --working-dir fixtures/set005
66+
$(PHPBIN) $(BOX) compile --no-parallel --working-dir fixtures/set005
6767

6868
php build/set005/bin/greet.phar > build/set005/output
6969
diff fixtures/set005/expected-output build/set005/output
7070

7171
.PHONY: e2e_011
7272
e2e_011: ## Run end-to-end tests for the fixture set 011 — Whitelist case
7373
e2e_011: bin/php-scoper.phar fixtures/set011/vendor
74-
$(PHPBIN) $(BOX) compile --working-dir fixtures/set011
74+
$(PHPBIN) $(BOX) compile --no-parallel --working-dir fixtures/set011
7575
cp -R fixtures/set011/tests/ build/set011/tests/
7676

7777
php build/set011/bin/greet.phar > build/set011/output
@@ -88,15 +88,15 @@ e2e_013: bin/php-scoper.phar
8888
.PHONY: e2e_014
8989
e2e_014: ## Run end-to-end tests for the fixture set 014 — Source code case with PSR-0
9090
e2e_014: bin/php-scoper.phar
91-
$(PHPBIN) $(BOX) compile --working-dir fixtures/set014
91+
$(PHPBIN) $(BOX) compile --no-parallel --working-dir fixtures/set014
9292

9393
php build/set014/bin/greet.phar > build/set014/output
9494
diff fixtures/set014/expected-output build/set014/output
9595

9696
.PHONY: e2e_015
9797
e2e_015: ## Run end-to-end tests for the fixture set 015 — Third-party code case with PSR-0
9898
e2e_015: bin/php-scoper.phar fixtures/set015/vendor
99-
$(PHPBIN) $(BOX) compile --working-dir fixtures/set015
99+
$(PHPBIN) $(BOX) compile --no-parallel --working-dir fixtures/set015
100100

101101
php build/set015/bin/greet.phar > build/set015/output
102102
diff fixtures/set015/expected-output build/set015/output
@@ -205,7 +205,7 @@ e2e_021: bin/php-scoper.phar fixtures/set021-composer/vendor
205205
.PHONY: e2e_022
206206
e2e_022: ## Run end-to-end tests for the fixture set 022 — Whitelist the project code with namespace whitelisting
207207
e2e_022: bin/php-scoper.phar fixtures/set022/vendor
208-
$(PHPBIN) $(BOX) compile --working-dir fixtures/set022
208+
$(PHPBIN) $(BOX) compile --no-parallel --working-dir fixtures/set022
209209
cp -R fixtures/set022/tests/ build/set022/tests/
210210

211211
php build/set022/bin/greet.phar > build/set022/output
@@ -318,7 +318,7 @@ fixtures/set005/vendor: fixtures/set005/composer.lock
318318
composer --working-dir=fixtures/set005 install
319319
touch $@
320320

321-
fixtures/set011/vendor: fixtures/set011/vendor
321+
fixtures/set011/vendor:
322322
composer --working-dir=fixtures/set011 dump-autoload
323323
touch $@
324324

box.json.dist

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
{
2-
"chmod": "0755",
3-
42
"algorithm": "OPENSSL",
53
"key": ".travis/php-scoper-private.pem",
64

specs/new/global-scope-single-part.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,12 @@
2929
'payload' => <<<'PHP'
3030
<?php
3131
32-
class Foo {}
33-
3432
new Foo();
3533
----
3634
<?php
3735
3836
namespace Humbug;
3937
40-
class Foo
41-
{
42-
}
4338
new \Humbug\Foo();
4439

4540
PHP
@@ -64,17 +59,12 @@ class Foo
6459
'payload' => <<<'PHP'
6560
<?php
6661
67-
class Foo {}
68-
6962
new \Foo();
7063
----
7164
<?php
7265
7366
namespace Humbug;
7467
75-
class Foo
76-
{
77-
}
7868
new \Humbug\Foo();
7969

8070
PHP

src/Autoload/ScoperAutoloadGenerator.php

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Humbug\PhpScoper\Whitelist;
1818
use PhpParser\Node\Name\FullyQualified;
1919
use const PHP_EOL;
20+
use function array_column;
2021
use function array_map;
2122
use function array_unshift;
2223
use function sprintf;
@@ -39,8 +40,22 @@ public function dump(string $prefix): string
3940

4041
$hasNamespacedFunctions = $this->hasNamespacedFunctions($whitelistedFunctions);
4142

42-
$statements = implode(PHP_EOL, $this->createClassAliasStatements($prefix, $hasNamespacedFunctions)).PHP_EOL.PHP_EOL;
43-
$statements .= implode(PHP_EOL, $this->createFunctionAliasStatements($whitelistedFunctions, $hasNamespacedFunctions));
43+
$statements = implode(
44+
PHP_EOL,
45+
$this->createClassAliasStatements(
46+
$this->whitelist->getRecordedWhitelistedClasses(),
47+
$hasNamespacedFunctions)
48+
)
49+
.PHP_EOL
50+
.PHP_EOL
51+
;
52+
$statements .= implode(
53+
PHP_EOL,
54+
$this->createFunctionAliasStatements(
55+
$whitelistedFunctions,
56+
$hasNamespacedFunctions
57+
)
58+
);
4459

4560
if ($hasNamespacedFunctions) {
4661
$dump = <<<PHP
@@ -82,17 +97,19 @@ public function dump(string $prefix): string
8297
/**
8398
* @return string[]
8499
*/
85-
private function createClassAliasStatements(string $prefix, bool $hasNamespacedFunctions): array
100+
private function createClassAliasStatements(array $whitelistedClasses, bool $hasNamespacedFunctions): array
86101
{
87102
$statements = array_map(
88-
function (string $whitelistedElement) use ($prefix): string {
103+
function (string $prefixedClass): string {
89104
return sprintf(
90-
'class_exists(\'%s\%s\');',
91-
$prefix,
92-
$whitelistedElement
105+
'class_exists(\'%s\');',
106+
$prefixedClass
93107
);
94108
},
95-
$this->whitelist->getClassWhitelistArray()
109+
array_column(
110+
$whitelistedClasses,
111+
1
112+
)
96113
);
97114

98115
if ([] === $statements) {

src/Configuration.php

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@
1919
use Iterator;
2020
use RuntimeException;
2121
use SplFileInfo;
22+
use Symfony\Component\Filesystem\Filesystem;
2223
use Symfony\Component\Finder\Finder;
2324
use const DIRECTORY_SEPARATOR;
2425
use function dirname;
26+
use function file_exists;
2527
use function gettype;
28+
use function in_array;
2629
use function is_array;
2730
use function is_bool;
31+
use function is_file;
32+
use function is_link;
2833
use function is_string;
34+
use function readlink;
2935
use function realpath;
36+
use function sprintf;
3037

3138
/**
3239
* @final
@@ -72,6 +79,36 @@ public static function load(string $path = null, array $paths = []): self
7279
if (null === $path) {
7380
$config = [];
7481
} else {
82+
if (false === (new Filesystem())->isAbsolutePath($path)) {
83+
throw new InvalidArgumentException(
84+
sprintf(
85+
'Expected the path of the configuration file to load to be an absolute path, got "%s" '
86+
.'instead',
87+
$path
88+
)
89+
);
90+
}
91+
92+
if (false === file_exists($path)) {
93+
throw new InvalidArgumentException(
94+
sprintf(
95+
'Expected the path of the configuration file to exists but the file "%s" could not be '
96+
.'found',
97+
$path
98+
)
99+
);
100+
}
101+
102+
if (false === is_file($path) && false === (is_link($path) && is_file(readlink($path)))) {
103+
throw new InvalidArgumentException(
104+
sprintf(
105+
'Expected the path of the configuration file to be a file but "%s" appears to be a '
106+
.'directory.',
107+
$path
108+
)
109+
);
110+
}
111+
75112
$config = include $path;
76113

77114
if (false === is_array($config)) {
@@ -162,7 +199,7 @@ public function withPrefix(?string $prefix): self
162199
);
163200
}
164201

165-
public function getPath(): string
202+
public function getPath(): ?string
166203
{
167204
return $this->path;
168205
}
@@ -208,7 +245,7 @@ private static function validateConfigKeys(array $config): void
208245

209246
private static function validateConfigKey(string $key): void
210247
{
211-
if (false === in_array($key, self::KEYWORDS)) {
248+
if (false === in_array($key, self::KEYWORDS, true)) {
212249
throw new InvalidArgumentException(
213250
sprintf(
214251
'Invalid configuration key value "%s" found.',
@@ -360,7 +397,7 @@ private static function retrieveWhitelistedFiles(string $dirPath, array $config)
360397
return [];
361398
}
362399

363-
$whitelistedFiles = $config[self::WHITELIST_KEYWORD];
400+
$whitelistedFiles = $config[self::WHITELISTED_FILES_KEYWORD];
364401

365402
if (false === is_array($whitelistedFiles)) {
366403
throw new InvalidArgumentException(
@@ -372,7 +409,7 @@ private static function retrieveWhitelistedFiles(string $dirPath, array $config)
372409
}
373410

374411
foreach ($whitelistedFiles as $index => $file) {
375-
if (is_string($file)) {
412+
if (false === is_string($file)) {
376413
throw new InvalidArgumentException(
377414
sprintf(
378415
'Expected whitelisted files to be an array of string, the "%d" element is not.',
@@ -381,7 +418,7 @@ private static function retrieveWhitelistedFiles(string $dirPath, array $config)
381418
);
382419
}
383420

384-
if ('' !== $file && DIRECTORY_SEPARATOR !== $file[0]) {
421+
if (false === (new Filesystem())->isAbsolutePath($file)) {
385422
$file = $dirPath.DIRECTORY_SEPARATOR.$file;
386423
}
387424

0 commit comments

Comments
 (0)