src/Engine/PHP.php
<?php
/*
* Pickle
*
*
* @license
*
* New BSD License
*
* Copyright © 2015-2015, Pickle community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace Pickle\Engine;
use Exception;
use Pickle\Base\Abstracts;
use Pickle\Base\Interfaces;
class PHP extends Abstracts\Engine implements Interfaces\Engine
{
private $phpCliEscaped;
private $phpCli;
private $phpize;
private $version;
private $major;
private $minor;
private $release;
private $extra;
private $compiler;
private $architecture;
private $zts;
private $debug;
private $iniPath;
private $extensionDir;
private $hasSdk;
public function __construct($phpCli = PHP_BINARY)
{
if (!(is_file($phpCli) && is_executable($phpCli))) {
throw new Exception("Invalid php executable: {$phpCli}");
}
$this->phpCliEscaped = escapeshellcmd($phpCli);
$this->phpCli = $phpCli;
$this->getFromConstants();
}
public function getName()
{
return 'php';
}
public function hasSdk()
{
if (isset($this->hasSdk)) {
return $this->hasSdk;
}
$cliDir = dirname($this->phpCli);
$res = glob($cliDir . DIRECTORY_SEPARATOR . 'phpize*');
if (!$res) {
$this->hasSdk = false;
}
$this->phpize = $res[0];
return $this->hasSdk = false;
}
public function getArchitecture()
{
return $this->architecture;
}
public function getCompiler()
{
return $this->compiler;
}
public function getPath()
{
return $this->phpCli;
}
public function getMajorVersion()
{
return $this->major;
}
public function getMinorVersion()
{
return $this->minor;
}
public function getReleaseVersion()
{
return $this->release;
}
public function getVersion()
{
return $this->version;
}
public function getZts()
{
return $this->zts;
}
public function getExtensionDir()
{
return $this->extensionDir;
}
public function getIniPath()
{
return $this->iniPath;
}
protected function getFullPathExtDir($dir)
{
$realpathDir = realpath($dir);
$baseDir = dirname($realpathDir);
$baseDirPhp = dirname($this->phpCli);
if (empty($baseDir)) {
if (empty($dir)) {
return $baseDirPhp . 'ext';
}
return $baseDirPhp . '\\' . $dir;
}
if ($baseDir == $baseDirPhp) {
return $realpathDir;
}
}
protected function getExtensionDirFromPhpInfo($info)
{
$extensionDir = '';
foreach ($info as $s) {
$pos_ext_dir = strpos($s, 'extension_dir');
if ($pos_ext_dir !== false && substr($s, $pos_ext_dir - 1, 1) != '.') {
[, $extensionDir] = explode('=>', $s);
break;
}
}
$extensionDir = trim($extensionDir);
if ($extensionDir == '') {
throw new Exception('Cannot detect PHP extension directory');
}
return $this->getFullPathExtDir($extensionDir);
}
protected function getArchFromPhpInfo($info)
{
$arch = '';
foreach ($info as $s) {
if (strpos($s, 'Architecture') !== false) {
[, $arch] = explode('=>', $s);
break;
}
}
$arch = trim($arch);
if ($arch == '') {
throw new Exception('Cannot detect PHP build architecture');
}
return $arch;
}
protected function getIniPathFromPhpInfo($info)
{
$iniPath = '';
foreach ($info as $s) {
if (strpos($s, 'Loaded Configuration File') !== false) {
[, $iniPath] = explode('=>', $s);
if ($iniPath === '(None)') {
$iniPath = '';
}
break;
}
}
$iniPath = trim($iniPath);
if ($iniPath == '') {
throw new Exception('Cannot detect php.ini directory');
}
return $iniPath;
}
protected function getCompilerFromPhpInfo($info)
{
$compiler = '';
foreach ($info as $s) {
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
if (strpos($s, 'PHP Extension Build') !== false) {
[, $build] = explode('=>', $s);
[, , $compiler] = explode(',', $build);
$compiler = strtolower($compiler);
break;
}
} else {
if (strpos($s, 'Compiler') !== false) {
[, $compiler] = explode('=>', $s);
break;
}
}
}
$compiler = trim($compiler);
if ($compiler == '') {
throw new Exception('Cannot detect PHP build compiler version');
}
return $compiler;
}
private function getFromConstants()
{
$script = 'echo PHP_VERSION . \"\n\"; '
. 'echo PHP_MAJOR_VERSION . \"\n\"; '
. 'echo PHP_MINOR_VERSION . \"\n\"; '
. 'echo PHP_RELEASE_VERSION . \"\n\"; '
. 'echo PHP_EXTRA_VERSION . \"\n\"; '
. 'echo PHP_ZTS . \"\n\"; '
. 'echo PHP_DEBUG . \"\n\"; ';
$cmd = $this->phpCliEscaped . ' -n -r ' . '"' . str_replace("\n", '', $script) . '"';
if (DIRECTORY_SEPARATOR === '\\') {
$cmd .= ' 2>NUL';
} else {
$cmd .= ' 2>/dev/null';
}
$info = null;
exec($cmd, $info);
if (count($info) !== 7) {
throw new Exception('Could not determine info from the PHP binary');
}
[$this->version, $this->major, $this->minor, $this->release, $this->extra, $this->zts, $this->debug] = $info;
$this->zts = (bool) $this->zts;
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
[$this->compiler, $this->architecture, $this->iniPath, $this->extensionDir] = $this->getFromPhpInfo();
}
}
private function getFromPhpInfo()
{
$cmd = $this->phpCliEscaped . ' -i';
$info = null;
exec($cmd, $info);
if (!is_array($info)) {
throw new Exception('Cannot parse phpinfo output');
}
$arch = $this->getArchFromPhpInfo($info);
$iniPath = $this->getIniPathFromPhpInfo($info);
$extensionDir = $this->getExtensionDirFromPhpInfo($info);
$compiler = strtolower($this->getCompilerFromPhpInfo($info));
return [$compiler, $arch, $iniPath, $extensionDir];
}
}
/* vim: set tabstop=4 shiftwidth=4 expandtab: fdm=marker */