Skip to content

Commit e93a4a0

Browse files
authored
Check requirements when running from a PHAR (#116)
An issue one may come across when running a PHAR, as opposed to when you install a tool via Composer, is that no check whatsoever is run. By leveraging [symfony/requirements-checker](https://github.com/symfony/requirements-checker/), a check is now run when running the PHAR. The check is run _before anything_. The output is the following when checks are passing in very verbose mode (`-vv` or `-vvv`): ![screen shot 2017-10-07 at 12 30 23](https://user-images.githubusercontent.com/5175937/31354701-3cc2cb9c-ad2f-11e7-8787-92c8c9a96b5e.png) If the very verbose mode is not given, nothing is displayed unless an error occurs. If the checks don't pass, regardless of the verbosity specified, the errors will be printed: ![screen shot 2017-10-07 at 12 28 00](https://user-images.githubusercontent.com/5175937/31354704-3ff9b65e-ad2f-11e7-906c-4dce9104113f.png)
1 parent 866a9a3 commit e93a4a0

File tree

9 files changed

+492
-16
lines changed

9 files changed

+492
-16
lines changed

.styleci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ disabled:
1111
finder:
1212
exclude:
1313
- 'fixtures'
14+
not-path:
15+
- 'src/check.php'
16+
- 'src/Autoload/Requirements.php'

bin/php-scoper

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22
<?php
33

44
/*
5-
* This file is part of the webmozart/php-scoper package.
5+
* This file is part of the humbug/php-scoper package.
66
*
7-
* (c) Bernhard Schussek <[email protected]>
7+
* Copyright (c) 2017 Théo FIDRY <[email protected]>,
8+
* Pádraic Brady <[email protected]>
89
*
910
* For the full copyright and license information, please view the LICENSE
1011
* file that was distributed with this source code.
1112
*/
1213

1314
namespace Humbug\PhpScoper;
1415

15-
$autoload = (function () {
16+
use RuntimeException;
17+
18+
$findAutoload = function () {
1619
if (file_exists($autoload = __DIR__.'/../../../autoload.php')) {
1720
// Is installed via composer
1821
return $autoload;
@@ -23,15 +26,51 @@ $autoload = (function () {
2326
return $autoload;
2427
}
2528

26-
return __DIR__.'/../vendor/autoload.php';
27-
})();
29+
if (file_exists($autoload = __DIR__.'/../vendor/autoload.php')) {
30+
// Is installed locally
31+
return $autoload;
32+
}
33+
34+
throw new RuntimeException('Unable to find the Composer or PHP-Scoper autoloader.');
35+
};
2836

29-
require_once $autoload;
37+
$autoload = $findAutoload();
3038

39+
require $autoload;
40+
41+
// Exposes the finder used by PHP-Scoper PHAR to allow its usage in the configuration file.
3142
if (false === class_exists('Isolated\Symfony\Component\Finder\Finder')) {
3243
class_alias('Symfony\Component\Finder\Finder', 'Isolated\Symfony\Component\Finder\Finder');
3344
}
3445

46+
$isVeryVerbose = array_reduce(
47+
$argv,
48+
/**
49+
* @param bool $isVeryVerbose
50+
* @param string $param
51+
*
52+
* @return bool
53+
*/
54+
function ($isVeryVerbose, $arg) {
55+
return $isVeryVerbose || '-vv' === $arg || '-vvv' === $arg;
56+
},
57+
false
58+
);
59+
60+
if ('phar:' === substr(__FILE__, 0, 5)) {
61+
$checkPassed = check_requirements(__DIR__.'/../composer.json', $isVeryVerbose);
62+
63+
if (false === $checkPassed) {
64+
exit(1);
65+
}
66+
}
67+
68+
require __DIR__.'/../src/functions.php';
69+
70+
if (file_exists(__DIR__.'/../tests/functions.php')) {
71+
require __DIR__.'/../tests/functions.php';
72+
}
73+
3574
$app = create_application();
3675

3776
$app->run();

box.json.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"vendor-bin"
1717
],
1818
"in": "vendor"
19+
},
20+
{
21+
"name": "composer.json",
22+
"in": "."
1923
}
2024
],
2125
"compression": "GZ",

composer.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919

2020
"require": {
2121
"php": "^7.1",
22+
"composer/semver": "^1.4",
2223
"nikic/php-parser": "^3.0",
2324
"ocramius/package-versions": "^1.1",
2425
"padraic/phar-updater": "^1.0",
2526
"symfony/console": "^3.2",
2627
"symfony/filesystem": "^3.2",
27-
"symfony/finder": "^3.2"
28+
"symfony/finder": "^3.2",
29+
"symfony/requirements-checker": "^1.0"
2830
},
2931
"require-dev": {
3032
"bamarni/composer-bin-plugin": "^1.1",
@@ -37,16 +39,13 @@
3739
"Humbug\\PhpScoper\\": "src/"
3840
},
3941
"files": [
40-
"src/functions.php"
42+
"src/check.php"
4143
]
4244
},
4345
"autoload-dev": {
4446
"psr-4": {
4547
"Humbug\\PhpScoper\\": "tests/"
46-
},
47-
"files": [
48-
"tests/functions.php"
49-
]
48+
}
5049
},
5150

5251
"config": {

composer.lock

Lines changed: 111 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpunit.xml.dist

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ file that was distributed with this source code.
1111

1212
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1313
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.0/phpunit.xsd"
14-
backupGlobals="false"
15-
bootstrap="vendor/autoload.php"
14+
bootstrap="tests/autoload.php"
1615
colors="true"
1716
>
1817
<testsuites>
19-
<testsuite name="Webmozart PHP-Scoper Test Suite">
18+
<testsuite name="PHP-Scoper Test Suite">
2019
<directory suffix="Test.php">./tests/</directory>
2120
</testsuite>
2221
</testsuites>

src/Autoload/Requirements.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the humbug/php-scoper package.
5+
*
6+
* Copyright (c) 2017 Théo FIDRY <[email protected]>,
7+
* Pádraic Brady <[email protected]>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace Humbug\PhpScoper\Autoload;
14+
15+
use Composer\Semver\Semver;
16+
use Symfony\Requirements\RequirementCollection;
17+
18+
/**
19+
* Collect the list of requirements for running the project. Code in this file must be PHP 5.3+ compatible as is used
20+
* to know if PHP-Scoper can be run or not.
21+
*/
22+
final class Requirements extends RequirementCollection
23+
{
24+
public function __construct($composerJson)
25+
{
26+
$composerConfig = $this->readComposer($composerJson);
27+
28+
$this->addPhpVersionRequirement($composerConfig);
29+
$this->addExtensionRequirements($composerConfig);
30+
}
31+
32+
private function readComposer($composerJson)
33+
{
34+
$composer = json_decode(file_get_contents($composerJson), true);
35+
36+
return $composer['require'];
37+
}
38+
39+
private function addPhpVersionRequirement(array $composerConfig)
40+
{
41+
$installedPhpVersion = phpversion();
42+
$requiredPhpVersion = $composerConfig['php'];
43+
44+
$this->addRequirement(
45+
Semver::satisfies(phpversion(), $requiredPhpVersion),
46+
sprintf(
47+
'PHP version must satisfies "%s" ("%s" installed)',
48+
$requiredPhpVersion,
49+
$installedPhpVersion
50+
),
51+
''
52+
);
53+
}
54+
55+
private function addExtensionRequirements(array $composerConfig)
56+
{
57+
foreach ($composerConfig as $package => $constraint) {
58+
if (preg_match('/^ext-(?<extension>.+)$/', $package, $matches)) {
59+
$this->addExtensionRequirement($matches['extension']);
60+
}
61+
}
62+
}
63+
64+
/**
65+
* @param string $extension Extension name, e.g. `iconv`.
66+
*/
67+
private function addExtensionRequirement($extension)
68+
{
69+
$this->addRequirement(
70+
extension_loaded($extension),
71+
sprintf(
72+
'The extension "%s" must be enabled.',
73+
$extension
74+
),
75+
''
76+
);
77+
}
78+
}

0 commit comments

Comments
 (0)