From 693387ce50116d8928e1676238df21fce4b06d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Fri, 24 Nov 2023 22:21:54 +0100 Subject: [PATCH] fix fixture --- fixtures/bench/with-compactors/box.json.dist | 2 +- .../bin/check-requirements.php | 24 ++ .../res/requirement-checker/src/Checker.php | 103 +++++++++ .../res/requirement-checker/src/IO.php | 128 ++++++++++ .../src/IsExtensionConflictFulfilled.php | 19 ++ .../src/IsExtensionFulfilled.php | 19 ++ .../requirement-checker/src/IsFulfilled.php | 10 + .../src/IsPhpVersionFulfilled.php | 23 ++ .../res/requirement-checker/src/Printer.php | 105 +++++++++ .../requirement-checker/src/Requirement.php | 38 +++ .../src/RequirementCollection.php | 51 ++++ .../res/requirement-checker/src/Terminal.php | 118 ++++++++++ .../bench/with-compactors/res/schema.json | 218 ++++++++++++++++++ .../bench/without-compactors/box.json.dist | 9 +- .../bin/check-requirements.php | 24 ++ .../res/requirement-checker/src/Checker.php | 103 +++++++++ .../res/requirement-checker/src/IO.php | 128 ++++++++++ .../src/IsExtensionConflictFulfilled.php | 19 ++ .../src/IsExtensionFulfilled.php | 19 ++ .../requirement-checker/src/IsFulfilled.php | 10 + .../src/IsPhpVersionFulfilled.php | 23 ++ .../res/requirement-checker/src/Printer.php | 105 +++++++++ .../requirement-checker/src/Requirement.php | 38 +++ .../src/RequirementCollection.php | 51 ++++ .../res/requirement-checker/src/Terminal.php | 118 ++++++++++ .../bench/without-compactors/res/schema.json | 218 ++++++++++++++++++ 26 files changed, 1719 insertions(+), 4 deletions(-) create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/bin/check-requirements.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/Checker.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/IO.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionFulfilled.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/IsFulfilled.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/IsPhpVersionFulfilled.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/Printer.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/Requirement.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/RequirementCollection.php create mode 100644 fixtures/bench/with-compactors/res/requirement-checker/src/Terminal.php create mode 100644 fixtures/bench/with-compactors/res/schema.json create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/bin/check-requirements.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/Checker.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/IO.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionFulfilled.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/IsFulfilled.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/IsPhpVersionFulfilled.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/Printer.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/Requirement.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/RequirementCollection.php create mode 100644 fixtures/bench/without-compactors/res/requirement-checker/src/Terminal.php create mode 100644 fixtures/bench/without-compactors/res/schema.json diff --git a/fixtures/bench/with-compactors/box.json.dist b/fixtures/bench/with-compactors/box.json.dist index 9904ada17..51419897f 100644 --- a/fixtures/bench/with-compactors/box.json.dist +++ b/fixtures/bench/with-compactors/box.json.dist @@ -4,7 +4,7 @@ "main": "box.php", "output": "../../../dist/bench/box.phar", - "directories-bin": ["../../../res/requirement-checker"], + "directories-bin": ["res"], "force-autodiscovery": true, "dump-autoload": false, diff --git a/fixtures/bench/with-compactors/res/requirement-checker/bin/check-requirements.php b/fixtures/bench/with-compactors/res/requirement-checker/bin/check-requirements.php new file mode 100644 index 000000000..43c38684f --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/bin/check-requirements.php @@ -0,0 +1,24 @@ +evaluateRequirements(); + $io = new IO(); + self::printCheck($checkPassed, new Printer($io->getVerbosity(), $io->hasColorSupport()), $requirements); + return $checkPassed; + } + public static function printCheck($checkPassed, Printer $printer, RequirementCollection $requirements) : void + { + if (\false === $checkPassed && IO::VERBOSITY_VERY_VERBOSE > $printer->getVerbosity()) { + $printer->setVerbosity(IO::VERBOSITY_VERY_VERBOSE); + } + $verbosity = IO::VERBOSITY_VERY_VERBOSE; + $iniPath = $requirements->getPhpIniPath(); + $printer->title('Box Requirements Checker', $verbosity); + $printer->printv('> Using PHP ', $verbosity); + $printer->printvln(\PHP_VERSION, $verbosity, 'green'); + if ($iniPath) { + $printer->printvln('> PHP is using the following php.ini file:', $verbosity); + $printer->printvln(' ' . $iniPath, $verbosity, 'green'); + } else { + $printer->printvln('> PHP is not using any php.ini file.', $verbosity, 'yellow'); + } + $printer->printvln('', $verbosity); + if (count($requirements) > 0) { + $printer->printvln('> Checking Box requirements:', $verbosity); + $printer->printv(' ', $verbosity); + } else { + $printer->printvln('> No requirements found.', $verbosity); + } + $errorMessages = []; + foreach ($requirements->getRequirements() as $requirement) { + if ($errorMessage = $printer->getRequirementErrorMessage($requirement)) { + if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { + $printer->printvln('✘ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'red'); + $printer->printv(' ', IO::VERBOSITY_DEBUG); + $errorMessages[] = $errorMessage; + } else { + $printer->printv('E', $verbosity, 'red'); + $errorMessages[] = $errorMessage; + } + continue; + } + if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { + $printer->printvln('✔ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'green'); + $printer->printv(' ', IO::VERBOSITY_DEBUG); + } else { + $printer->printv('.', $verbosity, 'green'); + } + } + if (IO::VERBOSITY_DEBUG !== $printer->getVerbosity() && count($requirements) > 0) { + $printer->printvln('', $verbosity); + } + if ($requirements->evaluateRequirements()) { + $printer->block('OK', 'Your system is ready to run the application.', $verbosity, 'success'); + } else { + $printer->block('ERROR', 'Your system is not ready to run the application.', $verbosity, 'error'); + $printer->title('Fix the following mandatory requirements:', $verbosity, 'red'); + foreach ($errorMessages as $errorMessage) { + $printer->printv(' * ' . $errorMessage, $verbosity); + } + } + $printer->printvln('', $verbosity); + } + private static function retrieveRequirements() : RequirementCollection + { + if (null === self::$requirementsConfig) { + self::$requirementsConfig = __DIR__ . '/../.requirements.php'; + } + $config = (require self::$requirementsConfig); + $requirements = new RequirementCollection(); + foreach ($config as $constraint) { + $requirements->addRequirement(self::createCondition($constraint['type'], $constraint['condition']), $constraint['message'], $constraint['helpMessage']); + } + return $requirements; + } + private static function createCondition($type, $condition) : IsFulfilled + { + switch ($type) { + case 'php': + return new IsPhpVersionFulfilled($condition); + case 'extension': + return new IsExtensionFulfilled($condition); + case 'extension-conflict': + return new IsExtensionConflictFulfilled($condition); + default: + throw new InvalidArgumentException(sprintf('Unknown requirement type "%s".', $type)); + } + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/IO.php b/fixtures/bench/with-compactors/res/requirement-checker/src/IO.php new file mode 100644 index 000000000..f9b3b12bf --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/IO.php @@ -0,0 +1,128 @@ +options = implode(' ', $_SERVER['argv']); + $shellVerbosity = $this->configureVerbosity(); + $this->interactive = $this->checkInteractivity($shellVerbosity); + $this->colorSupport = $this->checkColorSupport(); + } + public function isInteractive() : bool + { + return $this->interactive; + } + public function getVerbosity() : int + { + return $this->verbosity; + } + public function hasColorSupport() : bool + { + return $this->colorSupport; + } + public function hasParameter($values) : bool + { + $values = (array) $values; + foreach ($values as $value) { + $regexp = sprintf('/\\s%s\\b/', str_replace(' ', '\\s+', preg_quote($value, '/'))); + if (1 === preg_match($regexp, $this->options)) { + return \true; + } + } + return \false; + } + private function checkInteractivity(int $shellVerbosity) : bool + { + if (-1 === $shellVerbosity) { + return \false; + } + if (\true === $this->hasParameter(['--no-interaction', '-n'])) { + return \false; + } + if (function_exists('posix_isatty') && !@posix_isatty(STDOUT) && \false === getenv('SHELL_INTERACTIVE')) { + return \false; + } + return \true; + } + private function configureVerbosity() : int + { + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: + $this->verbosity = self::VERBOSITY_QUIET; + break; + case 1: + $this->verbosity = self::VERBOSITY_VERBOSE; + break; + case 2: + $this->verbosity = self::VERBOSITY_VERY_VERBOSE; + break; + case 3: + $this->verbosity = self::VERBOSITY_DEBUG; + break; + default: + $shellVerbosity = 0; + break; + } + if ($this->hasParameter(['--quiet', '-q'])) { + $this->verbosity = self::VERBOSITY_QUIET; + $shellVerbosity = -1; + } elseif ($this->hasParameter(['-vvv', '--verbose=3', '--verbose 3'])) { + $this->verbosity = self::VERBOSITY_DEBUG; + $shellVerbosity = 3; + } elseif ($this->hasParameter(['-vv', '--verbose=2', '--verbose 2'])) { + $this->verbosity = self::VERBOSITY_VERY_VERBOSE; + $shellVerbosity = 2; + } elseif ($this->hasParameter(['-v', '--verbose=1', '--verbose 1', '--verbose'])) { + $this->verbosity = self::VERBOSITY_VERBOSE; + $shellVerbosity = 1; + } + return $shellVerbosity; + } + private function checkColorSupport() : bool + { + if ($this->hasParameter(['--ansi'])) { + return \true; + } + if ($this->hasParameter(['--no-ansi'])) { + return \false; + } + if (DIRECTORY_SEPARATOR === '\\') { + return function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT) || \false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); + } + if (function_exists('stream_isatty')) { + return stream_isatty(STDOUT); + } + if (function_exists('posix_isatty')) { + return posix_isatty(STDOUT); + } + $stat = fstat(STDOUT); + return $stat ? 020000 === ($stat['mode'] & 0170000) : \false; + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php b/fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php new file mode 100644 index 000000000..a8fa58f59 --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php @@ -0,0 +1,19 @@ +conflictingExtension = $requiredExtension; + } + public function __invoke() : bool + { + return !extension_loaded($this->conflictingExtension); + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionFulfilled.php b/fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionFulfilled.php new file mode 100644 index 000000000..4e9111b2b --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/IsExtensionFulfilled.php @@ -0,0 +1,19 @@ +requiredExtension = $requiredExtension; + } + public function __invoke() : bool + { + return extension_loaded($this->requiredExtension); + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/IsFulfilled.php b/fixtures/bench/with-compactors/res/requirement-checker/src/IsFulfilled.php new file mode 100644 index 000000000..4087023d0 --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/IsFulfilled.php @@ -0,0 +1,10 @@ +requiredPhpVersion = $requiredPhpVersion; + } + public function __invoke() : bool + { + return Semver::satisfies(sprintf('%d.%d.%d', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION), $this->requiredPhpVersion); + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/Printer.php b/fixtures/bench/with-compactors/res/requirement-checker/src/Printer.php new file mode 100644 index 000000000..68ba63edb --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/Printer.php @@ -0,0 +1,105 @@ + "\x1b[0m", 'red' => "\x1b[31m", 'green' => "\x1b[32m", 'yellow' => "\x1b[33m", 'title' => "\x1b[33m", 'error' => "\x1b[37;41m", 'success' => "\x1b[30;42m"]; + private $verbosity; + private $supportColors; + private $width; + public function __construct(int $verbosity, bool $supportColors, ?int $width = null) + { + if (null === $width) { + $terminal = new Terminal(); + $width = $terminal->getWidth(); + } + $this->verbosity = $verbosity; + $this->supportColors = $supportColors; + $this->width = $width ?: 80; + } + public function getVerbosity() : int + { + return $this->verbosity; + } + public function setVerbosity($verbosity) : void + { + $this->verbosity = $verbosity; + } + public function title(string $title, int $verbosity, ?string $style = null) : void + { + if (null === $style) { + $style = 'title'; + } + $this->printvln('', $verbosity, $style); + $this->printvln($title, $verbosity, $style); + $this->printvln(str_repeat('=', min(strlen($title), $this->width)), $verbosity, $style); + $this->printvln('', $verbosity, $style); + } + public function getRequirementErrorMessage(Requirement $requirement) : ?string + { + if ($requirement->isFulfilled()) { + return null; + } + return wordwrap($requirement->getHelpText(), $this->width - 3, PHP_EOL . ' ') . PHP_EOL; + } + public function block(string $title, string $message, int $verbosity, ?string $style = null) : void + { + $prefix = ' [' . $title . '] '; + $lineLength = $this->width - strlen($prefix) - 1; + if ($lineLength < 0) { + $lineLength = 0; + } + $message = $prefix . trim($message); + $lines = []; + $remainingMessage = $message; + $wrapped = wordwrap($remainingMessage, $lineLength, '¬'); + $wrapped = explode('¬', $wrapped); + do { + $line = array_shift($wrapped); + if ($lines && $lineLength > 0) { + $line = str_repeat(' ', strlen($prefix)) . ltrim($line); + } + $lines[] = str_pad($line, $this->width, ' ', \STR_PAD_RIGHT); + } while (count($wrapped)); + $this->printvln('', $verbosity); + $this->printvln(str_repeat(' ', $this->width), $verbosity, $style); + foreach ($lines as $line) { + $this->printvln($line, $verbosity, $style); + } + $this->printv(str_repeat(' ', $this->width), $verbosity, $style); + $this->printvln('', $verbosity); + } + public function printvln(string $message, int $verbosity, ?string $style = null) : void + { + $this->printv($message, $verbosity, $style); + $this->printv(PHP_EOL, $verbosity, null); + } + public function printv(string $message, int $verbosity, ?string $style = null) : void + { + if ($verbosity > $this->verbosity) { + return; + } + $message = wordwrap($message, $this->width); + $message = sprintf('%s%s%s', $this->supportColors && isset($this->styles[$style]) ? $this->styles[$style] : '', $message, $this->supportColors ? $this->styles['reset'] : ''); + if ('1' === \getenv('BOX_REQUIREMENTS_CHECKER_LOG_TO_STDOUT')) { + echo $message; + } else { + \fwrite(\STDERR, $message); + } + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/Requirement.php b/fixtures/bench/with-compactors/res/requirement-checker/src/Requirement.php new file mode 100644 index 000000000..b18a73aa6 --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/Requirement.php @@ -0,0 +1,38 @@ +checkIsFulfilled = $checkIsFulfilled; + $this->testMessage = $testMessage; + $this->helpText = $helpText; + } + public function isFulfilled() : bool + { + if (!isset($this->fulfilled)) { + $this->fulfilled = $this->checkIsFulfilled->__invoke(); + } + return $this->fulfilled; + } + public function getIsFullfilledChecker() : IsFulfilled + { + return $this->checkIsFulfilled; + } + public function getTestMessage() : string + { + return $this->testMessage; + } + public function getHelpText() : string + { + return $this->helpText; + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/RequirementCollection.php b/fixtures/bench/with-compactors/res/requirement-checker/src/RequirementCollection.php new file mode 100644 index 000000000..d7a7b6fb4 --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/RequirementCollection.php @@ -0,0 +1,51 @@ +phpIniPath = null === $phpIniPath ? get_cfg_var('cfg_file_path') : $phpIniPath; + } + public function getIterator() : Traversable + { + return new ArrayIterator($this->requirements); + } + public function count() : int + { + return count($this->requirements); + } + public function add(Requirement $requirement) : void + { + $this->requirements[] = $requirement; + } + public function addRequirement(IsFulfilled $checkIsFulfilled, string $testMessage, string $helpText) : void + { + $this->add(new Requirement($checkIsFulfilled, $testMessage, $helpText)); + } + public function getRequirements() : array + { + return $this->requirements; + } + public function getPhpIniPath() + { + return $this->phpIniPath; + } + public function evaluateRequirements() + { + return \array_reduce($this->requirements, static function (bool $checkPassed, Requirement $requirement) : bool { + return $checkPassed && $requirement->isFulfilled(); + }, \true); + } +} diff --git a/fixtures/bench/with-compactors/res/requirement-checker/src/Terminal.php b/fixtures/bench/with-compactors/res/requirement-checker/src/Terminal.php new file mode 100644 index 000000000..999969357 --- /dev/null +++ b/fixtures/bench/with-compactors/res/requirement-checker/src/Terminal.php @@ -0,0 +1,118 @@ +&1', $output, $exitcode); + return self::$stty = 0 === $exitcode; + } + private static function initDimensions() : void + { + if ('\\' === DIRECTORY_SEPARATOR) { + if (preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', trim(getenv('ANSICON') ?: ''), $matches)) { + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + self::initDimensionsUsingStty(); + } elseif (null !== ($dimensions = self::getConsoleMode())) { + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; + } + } else { + self::initDimensionsUsingStty(); + } + } + private static function hasVt100Support() : bool + { + return function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'wb')); + } + private static function initDimensionsUsingStty() : void + { + if ($sttyString = self::getSttyColumns()) { + if (preg_match('/rows.(\\d+);.columns.(\\d+);/i', $sttyString, $matches)) { + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } elseif (preg_match('/;.(\\d+).rows;.(\\d+).columns/i', $sttyString, $matches)) { + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } + } + } + private static function getConsoleMode() : ?array + { + $info = self::readFromProcess('mode CON'); + if (null === $info || !preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) { + return null; + } + return [(int) $matches[2], (int) $matches[1]]; + } + private static function getSttyColumns() : ?string + { + return self::readFromProcess('stty -a | grep columns'); + } + private static function readFromProcess(string $command) : ?string + { + if (!function_exists('proc_open')) { + return null; + } + $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true]); + if (!is_resource($process)) { + return null; + } + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + return $info; + } +} diff --git a/fixtures/bench/with-compactors/res/schema.json b/fixtures/bench/with-compactors/res/schema.json new file mode 100644 index 000000000..bc273453d --- /dev/null +++ b/fixtures/bench/with-compactors/res/schema.json @@ -0,0 +1,218 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Settings used to build a new PHAR using Box.", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "description": "JSON schema location, e.g. ``vendor\/humbug\/box\/res\/schema.json``", + "type": [ "string", "null"] + }, + "algorithm": { + "description": "The algorithm to use for signing the PHAR.", + "type": ["string", "null"] + }, + "alias": { + "description": "The internal PHAR alias used for I/O streams.", + "type": ["string", "null"] + }, + "annotations": { + "description": "The PHP annotation compactor settings.", + "type": ["boolean", "object", "null"], + "properties": { + "ignore": { + "description": "A list of annotation names to ignore.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + } + }, + "banner": { + "description": "The header comment for the generated stub.", + "type": ["array", "boolean", "string", "null"] + }, + "banner-file": { + "description": "The header comment file for the generated stub.", + "type": ["string", "null"] + }, + "base-path": { + "description": "The base path where relative paths are resolved to.", + "type": ["string", "null"] + }, + "blacklist": { + "description": "A list of file paths to skip.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "check-requirements": { + "description": "If enabled, the PHAR will be able to check if the PHP environment used meets all the requirements to run the application.", + "type": ["boolean", "null"] + }, + "chmod": { + "description": "The permission mode for the new PHAR.", + "type": ["string", "null"] + }, + "compactors": { + "description": "The list of file contents compactor classes to register.", + "items": { + "type": "string" + }, + "type": ["array", "string", "null"] + }, + "compression": { + "description": "The compression algorithm to use for the PHAR.", + "type": ["string", "null"] + }, + "datetime": { + "description": "The replacement date for the current date and time.", + "type": ["string", "null"] + }, + "datetime-format": { + "description": "The format for the current date and time.", + "type": ["string", "null"] + }, + "datetime_format": { + "description": "The format for the current date and time.", + "type": ["string", "null"] + }, + "directories": { + "description": "A list of directory paths to search for scripts.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "directories-bin": { + "description": "A list of directory paths to search for binary safe files.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "dump-autoload": { + "description": "Will dump the optimized Composer autoloader.", + "type": ["boolean", "null"] + }, + "exclude-composer-files": { + "description": "Will remove the composer.json, composer.lock and installed.json files from the PHAR", + "type": ["boolean", "null"] + }, + "exclude-dev-files": { + "description": "Will remove the files from dev only packages from the PHAR", + "type": ["boolean", "null"] + }, + "files": { + "description": "A list of file paths to include.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "files-bin": { + "description": "A list of binary safe file paths to include.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "finder": { + "description": "A list of Finder configuration settings.", + "items": { + "type": "object" + }, + "type": ["array", "null"] + }, + "finder-bin": { + "description": "A list of Finder configuration settings for binary safe files.", + "items": { + "type": "object" + }, + "type": ["array", "null"] + }, + "force-autodiscovery": { + "description": "Forces the auto-discovery of files.", + "type": ["boolean", "null"] + }, + "git": { + "description": "The replacement name for the current pretty git version format.", + "type": ["string", "null"] + }, + "git-commit": { + "description": "The replacement name for the current git full commit hash.", + "type": ["string", "null"] + }, + "git-commit-short": { + "description": "The replacement name for the current git short commit hash.", + "type": ["string", "null"] + }, + "git-tag": { + "description": "The replacement name for the current git tag.", + "type": ["string", "null"] + }, + "git-version": { + "description": "The replacement name for the current git tag or commit hash.", + "type": ["string", "null"] + }, + "intercept": { + "description": "Allow the PHAR to intercept file functions?", + "type": ["boolean", "null"] + }, + "key": { + "description": "The path to the private key used for signing.", + "type": ["string", "null"] + }, + "key-pass": { + "description": "The password or prompt flag used for the private key.", + "type": ["boolean", "string", "null"] + }, + "main": { + "description": "The file path to the main script.", + "type": ["boolean", "string", "null"] + }, + "map": { + "description": "The mapping of file system paths to phar paths.", + "type": ["array", "null"], + "items": { + "type": "object" + } + }, + "metadata": { + "description": "Extra PHAR metadata." + }, + "output": { + "description": "The file name or path of the new PHAR.", + "type": ["string", "null"], + "not": { + "enum": ["", ".", ".."] + } + }, + "php-scoper": { + "description": "Path to the PHP-Scoper configuration file.", + "type": ["string", "null"] + }, + "replacement-sigil": { + "description": "The sigil that surrounds the replacement names.", + "type": ["string", "null"] + }, + "replacements": { + "description": "A list of replacement names and their values.", + "type": ["object", "null"] + }, + "shebang": { + "description": "The shebang line to use for the generated stub.", + "type": ["string", "boolean", "null"] + }, + "stub": { + "description": "The relative file path to the stub file, or the flag to use the default stub.", + "type": ["boolean", "string", "null"] + }, + "timestamp": { + "description": "The time at which the PHAR timestamp will be set.", + "type": ["string", "null"] + } + } +} diff --git a/fixtures/bench/without-compactors/box.json.dist b/fixtures/bench/without-compactors/box.json.dist index 3661decb2..51419897f 100644 --- a/fixtures/bench/without-compactors/box.json.dist +++ b/fixtures/bench/without-compactors/box.json.dist @@ -3,7 +3,10 @@ "main": "box.php", "output": "../../../dist/bench/box.phar", - "directories-bin": ["../../../res/requirement-checker"], - "datetime": "release-date", - "dump-autoload": false + + "directories-bin": ["res"], + "force-autodiscovery": true, + + "dump-autoload": false, + "datetime": "release-date" } diff --git a/fixtures/bench/without-compactors/res/requirement-checker/bin/check-requirements.php b/fixtures/bench/without-compactors/res/requirement-checker/bin/check-requirements.php new file mode 100644 index 000000000..43c38684f --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/bin/check-requirements.php @@ -0,0 +1,24 @@ +evaluateRequirements(); + $io = new IO(); + self::printCheck($checkPassed, new Printer($io->getVerbosity(), $io->hasColorSupport()), $requirements); + return $checkPassed; + } + public static function printCheck($checkPassed, Printer $printer, RequirementCollection $requirements) : void + { + if (\false === $checkPassed && IO::VERBOSITY_VERY_VERBOSE > $printer->getVerbosity()) { + $printer->setVerbosity(IO::VERBOSITY_VERY_VERBOSE); + } + $verbosity = IO::VERBOSITY_VERY_VERBOSE; + $iniPath = $requirements->getPhpIniPath(); + $printer->title('Box Requirements Checker', $verbosity); + $printer->printv('> Using PHP ', $verbosity); + $printer->printvln(\PHP_VERSION, $verbosity, 'green'); + if ($iniPath) { + $printer->printvln('> PHP is using the following php.ini file:', $verbosity); + $printer->printvln(' ' . $iniPath, $verbosity, 'green'); + } else { + $printer->printvln('> PHP is not using any php.ini file.', $verbosity, 'yellow'); + } + $printer->printvln('', $verbosity); + if (count($requirements) > 0) { + $printer->printvln('> Checking Box requirements:', $verbosity); + $printer->printv(' ', $verbosity); + } else { + $printer->printvln('> No requirements found.', $verbosity); + } + $errorMessages = []; + foreach ($requirements->getRequirements() as $requirement) { + if ($errorMessage = $printer->getRequirementErrorMessage($requirement)) { + if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { + $printer->printvln('✘ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'red'); + $printer->printv(' ', IO::VERBOSITY_DEBUG); + $errorMessages[] = $errorMessage; + } else { + $printer->printv('E', $verbosity, 'red'); + $errorMessages[] = $errorMessage; + } + continue; + } + if (IO::VERBOSITY_DEBUG === $printer->getVerbosity()) { + $printer->printvln('✔ ' . $requirement->getTestMessage(), IO::VERBOSITY_DEBUG, 'green'); + $printer->printv(' ', IO::VERBOSITY_DEBUG); + } else { + $printer->printv('.', $verbosity, 'green'); + } + } + if (IO::VERBOSITY_DEBUG !== $printer->getVerbosity() && count($requirements) > 0) { + $printer->printvln('', $verbosity); + } + if ($requirements->evaluateRequirements()) { + $printer->block('OK', 'Your system is ready to run the application.', $verbosity, 'success'); + } else { + $printer->block('ERROR', 'Your system is not ready to run the application.', $verbosity, 'error'); + $printer->title('Fix the following mandatory requirements:', $verbosity, 'red'); + foreach ($errorMessages as $errorMessage) { + $printer->printv(' * ' . $errorMessage, $verbosity); + } + } + $printer->printvln('', $verbosity); + } + private static function retrieveRequirements() : RequirementCollection + { + if (null === self::$requirementsConfig) { + self::$requirementsConfig = __DIR__ . '/../.requirements.php'; + } + $config = (require self::$requirementsConfig); + $requirements = new RequirementCollection(); + foreach ($config as $constraint) { + $requirements->addRequirement(self::createCondition($constraint['type'], $constraint['condition']), $constraint['message'], $constraint['helpMessage']); + } + return $requirements; + } + private static function createCondition($type, $condition) : IsFulfilled + { + switch ($type) { + case 'php': + return new IsPhpVersionFulfilled($condition); + case 'extension': + return new IsExtensionFulfilled($condition); + case 'extension-conflict': + return new IsExtensionConflictFulfilled($condition); + default: + throw new InvalidArgumentException(sprintf('Unknown requirement type "%s".', $type)); + } + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/IO.php b/fixtures/bench/without-compactors/res/requirement-checker/src/IO.php new file mode 100644 index 000000000..f9b3b12bf --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/IO.php @@ -0,0 +1,128 @@ +options = implode(' ', $_SERVER['argv']); + $shellVerbosity = $this->configureVerbosity(); + $this->interactive = $this->checkInteractivity($shellVerbosity); + $this->colorSupport = $this->checkColorSupport(); + } + public function isInteractive() : bool + { + return $this->interactive; + } + public function getVerbosity() : int + { + return $this->verbosity; + } + public function hasColorSupport() : bool + { + return $this->colorSupport; + } + public function hasParameter($values) : bool + { + $values = (array) $values; + foreach ($values as $value) { + $regexp = sprintf('/\\s%s\\b/', str_replace(' ', '\\s+', preg_quote($value, '/'))); + if (1 === preg_match($regexp, $this->options)) { + return \true; + } + } + return \false; + } + private function checkInteractivity(int $shellVerbosity) : bool + { + if (-1 === $shellVerbosity) { + return \false; + } + if (\true === $this->hasParameter(['--no-interaction', '-n'])) { + return \false; + } + if (function_exists('posix_isatty') && !@posix_isatty(STDOUT) && \false === getenv('SHELL_INTERACTIVE')) { + return \false; + } + return \true; + } + private function configureVerbosity() : int + { + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: + $this->verbosity = self::VERBOSITY_QUIET; + break; + case 1: + $this->verbosity = self::VERBOSITY_VERBOSE; + break; + case 2: + $this->verbosity = self::VERBOSITY_VERY_VERBOSE; + break; + case 3: + $this->verbosity = self::VERBOSITY_DEBUG; + break; + default: + $shellVerbosity = 0; + break; + } + if ($this->hasParameter(['--quiet', '-q'])) { + $this->verbosity = self::VERBOSITY_QUIET; + $shellVerbosity = -1; + } elseif ($this->hasParameter(['-vvv', '--verbose=3', '--verbose 3'])) { + $this->verbosity = self::VERBOSITY_DEBUG; + $shellVerbosity = 3; + } elseif ($this->hasParameter(['-vv', '--verbose=2', '--verbose 2'])) { + $this->verbosity = self::VERBOSITY_VERY_VERBOSE; + $shellVerbosity = 2; + } elseif ($this->hasParameter(['-v', '--verbose=1', '--verbose 1', '--verbose'])) { + $this->verbosity = self::VERBOSITY_VERBOSE; + $shellVerbosity = 1; + } + return $shellVerbosity; + } + private function checkColorSupport() : bool + { + if ($this->hasParameter(['--ansi'])) { + return \true; + } + if ($this->hasParameter(['--no-ansi'])) { + return \false; + } + if (DIRECTORY_SEPARATOR === '\\') { + return function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT) || \false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); + } + if (function_exists('stream_isatty')) { + return stream_isatty(STDOUT); + } + if (function_exists('posix_isatty')) { + return posix_isatty(STDOUT); + } + $stat = fstat(STDOUT); + return $stat ? 020000 === ($stat['mode'] & 0170000) : \false; + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php b/fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php new file mode 100644 index 000000000..a8fa58f59 --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionConflictFulfilled.php @@ -0,0 +1,19 @@ +conflictingExtension = $requiredExtension; + } + public function __invoke() : bool + { + return !extension_loaded($this->conflictingExtension); + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionFulfilled.php b/fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionFulfilled.php new file mode 100644 index 000000000..4e9111b2b --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/IsExtensionFulfilled.php @@ -0,0 +1,19 @@ +requiredExtension = $requiredExtension; + } + public function __invoke() : bool + { + return extension_loaded($this->requiredExtension); + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/IsFulfilled.php b/fixtures/bench/without-compactors/res/requirement-checker/src/IsFulfilled.php new file mode 100644 index 000000000..4087023d0 --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/IsFulfilled.php @@ -0,0 +1,10 @@ +requiredPhpVersion = $requiredPhpVersion; + } + public function __invoke() : bool + { + return Semver::satisfies(sprintf('%d.%d.%d', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION), $this->requiredPhpVersion); + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/Printer.php b/fixtures/bench/without-compactors/res/requirement-checker/src/Printer.php new file mode 100644 index 000000000..68ba63edb --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/Printer.php @@ -0,0 +1,105 @@ + "\x1b[0m", 'red' => "\x1b[31m", 'green' => "\x1b[32m", 'yellow' => "\x1b[33m", 'title' => "\x1b[33m", 'error' => "\x1b[37;41m", 'success' => "\x1b[30;42m"]; + private $verbosity; + private $supportColors; + private $width; + public function __construct(int $verbosity, bool $supportColors, ?int $width = null) + { + if (null === $width) { + $terminal = new Terminal(); + $width = $terminal->getWidth(); + } + $this->verbosity = $verbosity; + $this->supportColors = $supportColors; + $this->width = $width ?: 80; + } + public function getVerbosity() : int + { + return $this->verbosity; + } + public function setVerbosity($verbosity) : void + { + $this->verbosity = $verbosity; + } + public function title(string $title, int $verbosity, ?string $style = null) : void + { + if (null === $style) { + $style = 'title'; + } + $this->printvln('', $verbosity, $style); + $this->printvln($title, $verbosity, $style); + $this->printvln(str_repeat('=', min(strlen($title), $this->width)), $verbosity, $style); + $this->printvln('', $verbosity, $style); + } + public function getRequirementErrorMessage(Requirement $requirement) : ?string + { + if ($requirement->isFulfilled()) { + return null; + } + return wordwrap($requirement->getHelpText(), $this->width - 3, PHP_EOL . ' ') . PHP_EOL; + } + public function block(string $title, string $message, int $verbosity, ?string $style = null) : void + { + $prefix = ' [' . $title . '] '; + $lineLength = $this->width - strlen($prefix) - 1; + if ($lineLength < 0) { + $lineLength = 0; + } + $message = $prefix . trim($message); + $lines = []; + $remainingMessage = $message; + $wrapped = wordwrap($remainingMessage, $lineLength, '¬'); + $wrapped = explode('¬', $wrapped); + do { + $line = array_shift($wrapped); + if ($lines && $lineLength > 0) { + $line = str_repeat(' ', strlen($prefix)) . ltrim($line); + } + $lines[] = str_pad($line, $this->width, ' ', \STR_PAD_RIGHT); + } while (count($wrapped)); + $this->printvln('', $verbosity); + $this->printvln(str_repeat(' ', $this->width), $verbosity, $style); + foreach ($lines as $line) { + $this->printvln($line, $verbosity, $style); + } + $this->printv(str_repeat(' ', $this->width), $verbosity, $style); + $this->printvln('', $verbosity); + } + public function printvln(string $message, int $verbosity, ?string $style = null) : void + { + $this->printv($message, $verbosity, $style); + $this->printv(PHP_EOL, $verbosity, null); + } + public function printv(string $message, int $verbosity, ?string $style = null) : void + { + if ($verbosity > $this->verbosity) { + return; + } + $message = wordwrap($message, $this->width); + $message = sprintf('%s%s%s', $this->supportColors && isset($this->styles[$style]) ? $this->styles[$style] : '', $message, $this->supportColors ? $this->styles['reset'] : ''); + if ('1' === \getenv('BOX_REQUIREMENTS_CHECKER_LOG_TO_STDOUT')) { + echo $message; + } else { + \fwrite(\STDERR, $message); + } + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/Requirement.php b/fixtures/bench/without-compactors/res/requirement-checker/src/Requirement.php new file mode 100644 index 000000000..b18a73aa6 --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/Requirement.php @@ -0,0 +1,38 @@ +checkIsFulfilled = $checkIsFulfilled; + $this->testMessage = $testMessage; + $this->helpText = $helpText; + } + public function isFulfilled() : bool + { + if (!isset($this->fulfilled)) { + $this->fulfilled = $this->checkIsFulfilled->__invoke(); + } + return $this->fulfilled; + } + public function getIsFullfilledChecker() : IsFulfilled + { + return $this->checkIsFulfilled; + } + public function getTestMessage() : string + { + return $this->testMessage; + } + public function getHelpText() : string + { + return $this->helpText; + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/RequirementCollection.php b/fixtures/bench/without-compactors/res/requirement-checker/src/RequirementCollection.php new file mode 100644 index 000000000..d7a7b6fb4 --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/RequirementCollection.php @@ -0,0 +1,51 @@ +phpIniPath = null === $phpIniPath ? get_cfg_var('cfg_file_path') : $phpIniPath; + } + public function getIterator() : Traversable + { + return new ArrayIterator($this->requirements); + } + public function count() : int + { + return count($this->requirements); + } + public function add(Requirement $requirement) : void + { + $this->requirements[] = $requirement; + } + public function addRequirement(IsFulfilled $checkIsFulfilled, string $testMessage, string $helpText) : void + { + $this->add(new Requirement($checkIsFulfilled, $testMessage, $helpText)); + } + public function getRequirements() : array + { + return $this->requirements; + } + public function getPhpIniPath() + { + return $this->phpIniPath; + } + public function evaluateRequirements() + { + return \array_reduce($this->requirements, static function (bool $checkPassed, Requirement $requirement) : bool { + return $checkPassed && $requirement->isFulfilled(); + }, \true); + } +} diff --git a/fixtures/bench/without-compactors/res/requirement-checker/src/Terminal.php b/fixtures/bench/without-compactors/res/requirement-checker/src/Terminal.php new file mode 100644 index 000000000..999969357 --- /dev/null +++ b/fixtures/bench/without-compactors/res/requirement-checker/src/Terminal.php @@ -0,0 +1,118 @@ +&1', $output, $exitcode); + return self::$stty = 0 === $exitcode; + } + private static function initDimensions() : void + { + if ('\\' === DIRECTORY_SEPARATOR) { + if (preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', trim(getenv('ANSICON') ?: ''), $matches)) { + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + self::initDimensionsUsingStty(); + } elseif (null !== ($dimensions = self::getConsoleMode())) { + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; + } + } else { + self::initDimensionsUsingStty(); + } + } + private static function hasVt100Support() : bool + { + return function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'wb')); + } + private static function initDimensionsUsingStty() : void + { + if ($sttyString = self::getSttyColumns()) { + if (preg_match('/rows.(\\d+);.columns.(\\d+);/i', $sttyString, $matches)) { + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } elseif (preg_match('/;.(\\d+).rows;.(\\d+).columns/i', $sttyString, $matches)) { + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } + } + } + private static function getConsoleMode() : ?array + { + $info = self::readFromProcess('mode CON'); + if (null === $info || !preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) { + return null; + } + return [(int) $matches[2], (int) $matches[1]]; + } + private static function getSttyColumns() : ?string + { + return self::readFromProcess('stty -a | grep columns'); + } + private static function readFromProcess(string $command) : ?string + { + if (!function_exists('proc_open')) { + return null; + } + $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true]); + if (!is_resource($process)) { + return null; + } + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + return $info; + } +} diff --git a/fixtures/bench/without-compactors/res/schema.json b/fixtures/bench/without-compactors/res/schema.json new file mode 100644 index 000000000..bc273453d --- /dev/null +++ b/fixtures/bench/without-compactors/res/schema.json @@ -0,0 +1,218 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Settings used to build a new PHAR using Box.", + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "description": "JSON schema location, e.g. ``vendor\/humbug\/box\/res\/schema.json``", + "type": [ "string", "null"] + }, + "algorithm": { + "description": "The algorithm to use for signing the PHAR.", + "type": ["string", "null"] + }, + "alias": { + "description": "The internal PHAR alias used for I/O streams.", + "type": ["string", "null"] + }, + "annotations": { + "description": "The PHP annotation compactor settings.", + "type": ["boolean", "object", "null"], + "properties": { + "ignore": { + "description": "A list of annotation names to ignore.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + } + }, + "banner": { + "description": "The header comment for the generated stub.", + "type": ["array", "boolean", "string", "null"] + }, + "banner-file": { + "description": "The header comment file for the generated stub.", + "type": ["string", "null"] + }, + "base-path": { + "description": "The base path where relative paths are resolved to.", + "type": ["string", "null"] + }, + "blacklist": { + "description": "A list of file paths to skip.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "check-requirements": { + "description": "If enabled, the PHAR will be able to check if the PHP environment used meets all the requirements to run the application.", + "type": ["boolean", "null"] + }, + "chmod": { + "description": "The permission mode for the new PHAR.", + "type": ["string", "null"] + }, + "compactors": { + "description": "The list of file contents compactor classes to register.", + "items": { + "type": "string" + }, + "type": ["array", "string", "null"] + }, + "compression": { + "description": "The compression algorithm to use for the PHAR.", + "type": ["string", "null"] + }, + "datetime": { + "description": "The replacement date for the current date and time.", + "type": ["string", "null"] + }, + "datetime-format": { + "description": "The format for the current date and time.", + "type": ["string", "null"] + }, + "datetime_format": { + "description": "The format for the current date and time.", + "type": ["string", "null"] + }, + "directories": { + "description": "A list of directory paths to search for scripts.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "directories-bin": { + "description": "A list of directory paths to search for binary safe files.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "dump-autoload": { + "description": "Will dump the optimized Composer autoloader.", + "type": ["boolean", "null"] + }, + "exclude-composer-files": { + "description": "Will remove the composer.json, composer.lock and installed.json files from the PHAR", + "type": ["boolean", "null"] + }, + "exclude-dev-files": { + "description": "Will remove the files from dev only packages from the PHAR", + "type": ["boolean", "null"] + }, + "files": { + "description": "A list of file paths to include.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "files-bin": { + "description": "A list of binary safe file paths to include.", + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "finder": { + "description": "A list of Finder configuration settings.", + "items": { + "type": "object" + }, + "type": ["array", "null"] + }, + "finder-bin": { + "description": "A list of Finder configuration settings for binary safe files.", + "items": { + "type": "object" + }, + "type": ["array", "null"] + }, + "force-autodiscovery": { + "description": "Forces the auto-discovery of files.", + "type": ["boolean", "null"] + }, + "git": { + "description": "The replacement name for the current pretty git version format.", + "type": ["string", "null"] + }, + "git-commit": { + "description": "The replacement name for the current git full commit hash.", + "type": ["string", "null"] + }, + "git-commit-short": { + "description": "The replacement name for the current git short commit hash.", + "type": ["string", "null"] + }, + "git-tag": { + "description": "The replacement name for the current git tag.", + "type": ["string", "null"] + }, + "git-version": { + "description": "The replacement name for the current git tag or commit hash.", + "type": ["string", "null"] + }, + "intercept": { + "description": "Allow the PHAR to intercept file functions?", + "type": ["boolean", "null"] + }, + "key": { + "description": "The path to the private key used for signing.", + "type": ["string", "null"] + }, + "key-pass": { + "description": "The password or prompt flag used for the private key.", + "type": ["boolean", "string", "null"] + }, + "main": { + "description": "The file path to the main script.", + "type": ["boolean", "string", "null"] + }, + "map": { + "description": "The mapping of file system paths to phar paths.", + "type": ["array", "null"], + "items": { + "type": "object" + } + }, + "metadata": { + "description": "Extra PHAR metadata." + }, + "output": { + "description": "The file name or path of the new PHAR.", + "type": ["string", "null"], + "not": { + "enum": ["", ".", ".."] + } + }, + "php-scoper": { + "description": "Path to the PHP-Scoper configuration file.", + "type": ["string", "null"] + }, + "replacement-sigil": { + "description": "The sigil that surrounds the replacement names.", + "type": ["string", "null"] + }, + "replacements": { + "description": "A list of replacement names and their values.", + "type": ["object", "null"] + }, + "shebang": { + "description": "The shebang line to use for the generated stub.", + "type": ["string", "boolean", "null"] + }, + "stub": { + "description": "The relative file path to the stub file, or the flag to use the default stub.", + "type": ["boolean", "string", "null"] + }, + "timestamp": { + "description": "The time at which the PHAR timestamp will be set.", + "type": ["string", "null"] + } + } +}