Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@14: declare(strict_types=1); Chris@14: Chris@0: namespace SebastianBergmann\Environment; Chris@0: Chris@0: /** Chris@0: * Utility class for HHVM/PHP environment handling. Chris@0: */ Chris@14: final class Runtime Chris@0: { Chris@0: /** Chris@0: * @var string Chris@0: */ Chris@0: private static $binary; Chris@0: Chris@0: /** Chris@0: * Returns true when Xdebug is supported or Chris@14: * the runtime used is PHPDBG. Chris@0: */ Chris@14: public function canCollectCodeCoverage(): bool Chris@0: { Chris@0: return $this->hasXdebug() || $this->hasPHPDBGCodeCoverage(); Chris@0: } Chris@0: Chris@0: /** Chris@14: * Returns true when OPcache is loaded and opcache.save_comments=0 is set. Chris@14: * Chris@14: * Code taken from Doctrine\Common\Annotations\AnnotationReader::__construct(). Chris@14: */ Chris@14: public function discardsComments(): bool Chris@14: { Chris@14: if (\extension_loaded('Zend Optimizer+') && (\ini_get('zend_optimizerplus.save_comments') === '0' || \ini_get('opcache.save_comments') === '0')) { Chris@14: return true; Chris@14: } Chris@14: Chris@14: if (\extension_loaded('Zend OPcache') && \ini_get('opcache.save_comments') == 0) { Chris@14: return true; Chris@14: } Chris@14: Chris@14: return false; Chris@14: } Chris@14: Chris@14: /** Chris@0: * Returns the path to the binary of the current runtime. Chris@0: * Appends ' --php' to the path when the runtime is HHVM. Chris@0: */ Chris@14: public function getBinary(): string Chris@0: { Chris@0: // HHVM Chris@0: if (self::$binary === null && $this->isHHVM()) { Chris@14: // @codeCoverageIgnoreStart Chris@14: if ((self::$binary = \getenv('PHP_BINARY')) === false) { Chris@0: self::$binary = PHP_BINARY; Chris@0: } Chris@0: Chris@14: self::$binary = \escapeshellarg(self::$binary) . ' --php' . Chris@14: ' -d hhvm.php7.all=1'; Chris@14: // @codeCoverageIgnoreEnd Chris@0: } Chris@0: Chris@14: if (self::$binary === null && PHP_BINARY !== '') { Chris@14: self::$binary = \escapeshellarg(PHP_BINARY); Chris@0: } Chris@0: Chris@0: if (self::$binary === null) { Chris@14: // @codeCoverageIgnoreStart Chris@14: $possibleBinaryLocations = [ Chris@0: PHP_BINDIR . '/php', Chris@0: PHP_BINDIR . '/php-cli.exe', Chris@0: PHP_BINDIR . '/php.exe' Chris@14: ]; Chris@0: Chris@0: foreach ($possibleBinaryLocations as $binary) { Chris@14: if (\is_readable($binary)) { Chris@14: self::$binary = \escapeshellarg($binary); Chris@0: break; Chris@0: } Chris@0: } Chris@14: // @codeCoverageIgnoreEnd Chris@0: } Chris@0: Chris@0: if (self::$binary === null) { Chris@14: // @codeCoverageIgnoreStart Chris@0: self::$binary = 'php'; Chris@14: // @codeCoverageIgnoreEnd Chris@0: } Chris@0: Chris@0: return self::$binary; Chris@0: } Chris@0: Chris@14: public function getNameWithVersion(): string Chris@0: { Chris@0: return $this->getName() . ' ' . $this->getVersion(); Chris@0: } Chris@0: Chris@14: public function getName(): string Chris@0: { Chris@0: if ($this->isHHVM()) { Chris@14: // @codeCoverageIgnoreStart Chris@0: return 'HHVM'; Chris@14: // @codeCoverageIgnoreEnd Chris@14: } Chris@14: Chris@14: if ($this->isPHPDBG()) { Chris@14: // @codeCoverageIgnoreStart Chris@0: return 'PHPDBG'; Chris@14: // @codeCoverageIgnoreEnd Chris@0: } Chris@14: Chris@14: return 'PHP'; Chris@0: } Chris@0: Chris@14: public function getVendorUrl(): string Chris@0: { Chris@0: if ($this->isHHVM()) { Chris@14: // @codeCoverageIgnoreStart Chris@0: return 'http://hhvm.com/'; Chris@14: // @codeCoverageIgnoreEnd Chris@0: } Chris@14: Chris@14: return 'https://secure.php.net/'; Chris@0: } Chris@0: Chris@14: public function getVersion(): string Chris@0: { Chris@0: if ($this->isHHVM()) { Chris@14: // @codeCoverageIgnoreStart Chris@0: return HHVM_VERSION; Chris@14: // @codeCoverageIgnoreEnd Chris@0: } Chris@14: Chris@14: return PHP_VERSION; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns true when the runtime used is PHP and Xdebug is loaded. Chris@0: */ Chris@14: public function hasXdebug(): bool Chris@0: { Chris@14: return ($this->isPHP() || $this->isHHVM()) && \extension_loaded('xdebug'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns true when the runtime used is HHVM. Chris@0: */ Chris@14: public function isHHVM(): bool Chris@0: { Chris@14: return \defined('HHVM_VERSION'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns true when the runtime used is PHP without the PHPDBG SAPI. Chris@0: */ Chris@14: public function isPHP(): bool Chris@0: { Chris@0: return !$this->isHHVM() && !$this->isPHPDBG(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns true when the runtime used is PHP with the PHPDBG SAPI. Chris@0: */ Chris@14: public function isPHPDBG(): bool Chris@0: { Chris@0: return PHP_SAPI === 'phpdbg' && !$this->isHHVM(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns true when the runtime used is PHP with the PHPDBG SAPI Chris@0: * and the phpdbg_*_oplog() functions are available (PHP >= 7.0). Chris@0: * Chris@14: * @codeCoverageIgnore Chris@0: */ Chris@14: public function hasPHPDBGCodeCoverage(): bool Chris@0: { Chris@14: return $this->isPHPDBG(); Chris@0: } Chris@0: }