mirror of https://github.com/vdm-io/tcpdf.git
282 lines
7.2 KiB
PHP
282 lines
7.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Helper class to execute PHP via shell
|
|
*
|
|
* @author Philippe Jausions
|
|
* @license http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
|
|
*/
|
|
|
|
namespace Tecnickcom\TCPDF\Tests;
|
|
|
|
use RuntimeException;
|
|
|
|
class PhpExecutor
|
|
{
|
|
/**
|
|
* @var string PHP executable as a shell argument
|
|
*/
|
|
private $phpShell;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $extensionDir = null;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
private $phpVersion = null;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $phpVersionInfo = null;
|
|
|
|
/**
|
|
* @var bool[]
|
|
*/
|
|
private $builtInExtensions = array();
|
|
|
|
/**
|
|
* @var mixed[]
|
|
*/
|
|
private $extensionStatuses = array();
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
private $verbose;
|
|
|
|
/**
|
|
* @param string $php Path to PHP executable
|
|
* @param bool $verbose
|
|
*/
|
|
public function __construct($php, $verbose = false)
|
|
{
|
|
$this->phpShell = escapeshellarg($php);
|
|
$this->verbose = $verbose;
|
|
}
|
|
|
|
public function __toString()
|
|
{
|
|
return $this->phpShell;
|
|
}
|
|
|
|
/**
|
|
* @param string $command PHP command to execute
|
|
* @param string|null $cliOptions MUST be properly escaped for the shell
|
|
* @return string Result of the command
|
|
* @throws RuntimeException
|
|
*/
|
|
public function executeCommand($command, $cliOptions = null)
|
|
{
|
|
$exec = sprintf(
|
|
'%s %s -r %s',
|
|
$this->phpShell,
|
|
$cliOptions,
|
|
escapeshellarg($command)
|
|
);
|
|
if ($this->verbose) {
|
|
echo $exec . PHP_EOL;
|
|
}
|
|
exec($exec, $output, $resultCode);
|
|
if (0 !== $resultCode) {
|
|
throw new RuntimeException('Execution failed: ' . $exec);
|
|
}
|
|
return $output[0];
|
|
}
|
|
|
|
/**
|
|
* @return string PHP version information (multiline information)
|
|
* @throws RuntimeException
|
|
*/
|
|
public function getPhpVersionInfo()
|
|
{
|
|
if (null === $this->phpVersionInfo) {
|
|
$exec = sprintf('%s -n -v', $this->phpShell);
|
|
if ($this->verbose) {
|
|
echo $exec . PHP_EOL;
|
|
}
|
|
exec($exec, $output, $resultCode);
|
|
if (0 !== $resultCode) {
|
|
throw new RuntimeException('Execution failed: ' . $exec);
|
|
}
|
|
$this->phpVersionInfo = implode(PHP_EOL, $output);
|
|
}
|
|
return $this->phpVersionInfo;
|
|
}
|
|
|
|
/**
|
|
* @return int PHP version as a integer
|
|
* @throws RuntimeException
|
|
*/
|
|
public function getPhpVersion()
|
|
{
|
|
if (null === $this->phpVersion) {
|
|
$this->phpVersion = (int)$this->executeCommand('echo PHP_VERSION_ID;');
|
|
}
|
|
return $this->phpVersion;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
* @throws RuntimeException
|
|
*/
|
|
public function getPhpExtensionDir()
|
|
{
|
|
if (null === $this->extensionDir) {
|
|
$this->extensionDir = $this->executeCommand("echo ini_get('extension_dir');");
|
|
}
|
|
return $this->extensionDir;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
private function isWindows()
|
|
{
|
|
return stripos(PHP_OS, 'WIN') === 0;
|
|
}
|
|
|
|
/**
|
|
* @param string $extension Extension name (without .so, .dll, or "php_" prefix)
|
|
* @return string
|
|
*/
|
|
public function makePhpExtensionFileName($extension)
|
|
{
|
|
if ($this->isWindows()) {
|
|
if ('gd' === $extension && $this->getPhpVersion() < 80000) {
|
|
$extension = 'gd2';
|
|
}
|
|
return "php_$extension.dll";
|
|
}
|
|
return $extension . '.so';
|
|
}
|
|
|
|
/**
|
|
* @param string $path
|
|
* @return string
|
|
*/
|
|
private function escapePath($path)
|
|
{
|
|
if ($this->isWindows()) {
|
|
// if ($this->getPhpVersion() < 50400) {
|
|
// $path = str_replace('\\', '/', $path);
|
|
// }
|
|
if (strpos($path, '~') !== false) {
|
|
return "'" . $path . "'";
|
|
}
|
|
}
|
|
if (strpos($path, ' ') !== false) {
|
|
return "'" . $path . "'";
|
|
}
|
|
return escapeshellarg((string)$path);
|
|
}
|
|
|
|
/**
|
|
* @param string $path
|
|
* @return string
|
|
*/
|
|
private function escapePathForCliOption($path)
|
|
{
|
|
if ($this->isWindows()) {
|
|
if ($this->getPhpVersion() < 50400) {
|
|
$path = str_replace('\\', '/', $path);
|
|
return "'" . $path . "'";
|
|
}
|
|
if (strpos($path, '~') !== false) {
|
|
return "'" . $path . "'";
|
|
}
|
|
}
|
|
if (strpos($path, ' ') !== false) {
|
|
return "'" . $path . "'";
|
|
}
|
|
return (string)$path;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param string $value
|
|
* @return string
|
|
*/
|
|
public function makeCliOption($name, $value)
|
|
{
|
|
switch ($name) {
|
|
case 'auto_prepend_file':
|
|
case 'extension_dir':
|
|
case 'include_path':
|
|
$arg = $this->escapePathForCliOption($value);
|
|
break;
|
|
default:
|
|
$arg = escapeshellarg($value);
|
|
}
|
|
|
|
return sprintf('-d %s=%s', $name, $arg);
|
|
}
|
|
|
|
/**
|
|
* @param string $extension Extension name (without .so, .dll, or "php_" prefix)
|
|
* @return bool Whether the extension is available for loading into PHP
|
|
*/
|
|
public function isExtensionAvailable($extension)
|
|
{
|
|
$extensionLib = $this->makePhpExtensionFileName($extension);
|
|
return file_exists($this->getPhpExtensionDir() . DIRECTORY_SEPARATOR . $extensionLib);
|
|
}
|
|
|
|
/**
|
|
* @param string $extension Extension name (without .so, .dll, or "php_" prefix)
|
|
* @return bool Whether the extension is built in PHP
|
|
* @throws RuntimeException
|
|
*/
|
|
public function isExtensionBuiltIn($extension)
|
|
{
|
|
if (!isset($this->builtInExtensions[$extension])) {
|
|
$this->builtInExtensions[$extension] = (bool)$this->executeCommand("echo extension_loaded('$extension') ? 1 : 0;", '-n');
|
|
}
|
|
return $this->builtInExtensions[$extension];
|
|
}
|
|
|
|
/**
|
|
* @param string $extension Extension name (without .so, .dll, or "php_" prefix)
|
|
* @return bool|null
|
|
* <ul>
|
|
* <li>true: built in PHP,</li>
|
|
* <li>false: available,</li>
|
|
* <li>null: not available (not detected).</li>
|
|
* </ul>
|
|
*/
|
|
public function getExtensionStatus($extension)
|
|
{
|
|
if (!array_key_exists($extension, $this->extensionStatuses)) {
|
|
if ($this->isExtensionBuiltIn($extension)) {
|
|
$this->extensionStatuses[$extension] = true;
|
|
} elseif ($this->isExtensionAvailable($extension)) {
|
|
$this->extensionStatuses[$extension] = false;
|
|
} else {
|
|
$this->extensionStatuses[$extension] = null;
|
|
}
|
|
}
|
|
return $this->extensionStatuses[$extension];
|
|
}
|
|
|
|
/**
|
|
* @param string $file Path to file to lint
|
|
* @return bool Whether the PHP syntax of the file is okay
|
|
*/
|
|
public function isValidPhpFile($file)
|
|
{
|
|
$exec = sprintf(
|
|
'%s -l %s',
|
|
$this->phpShell,
|
|
$this->escapePath($file)
|
|
);
|
|
if ($this->verbose) {
|
|
echo $exec . PHP_EOL;
|
|
}
|
|
exec($exec, $output, $resultCode);
|
|
return (0 === $resultCode);
|
|
}
|
|
}
|