Dep: update

주로 PHAN
This commit is contained in:
2021-08-06 22:39:09 +09:00
parent 5310c2e7f6
commit b306601c72
1098 changed files with 92137 additions and 33228 deletions
+126 -42
View File
@@ -30,13 +30,14 @@ class XdebugHandler
private static $inRestart;
private static $name;
private static $skipped;
private static $xdebugActive;
private $cli;
private $colorOption;
private $debug;
private $envAllowXdebug;
private $envOriginalInis;
private $loaded;
private $mode;
private $persistent;
private $script;
/** @var Status|null */
@@ -50,12 +51,11 @@ class XdebugHandler
* would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS.
*
* @param string $envPrefix Value used in environment variables
* @param string $colorOption Command-line long option to force color output
* @throws \RuntimeException If a parameter is invalid
* @throws \RuntimeException If the parameter is invalid
*/
public function __construct($envPrefix, $colorOption = '')
public function __construct($envPrefix)
{
if (!is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
if (!is_string($envPrefix) || empty($envPrefix)) {
throw new \RuntimeException('Invalid constructor parameter');
}
@@ -63,13 +63,23 @@ class XdebugHandler
$this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW;
$this->envOriginalInis = self::$name.self::SUFFIX_INIS;
$this->colorOption = $colorOption;
if (extension_loaded('xdebug')) {
$ext = new \ReflectionExtension('xdebug');
$this->loaded = $ext->getVersion() ?: 'unknown';
$this->loaded = phpversion('xdebug') ?: 'unknown';
if (version_compare($this->loaded, '3.1', '>=')) {
/** @phpstan-ignore-next-line */
$modes = xdebug_info('mode');
$this->mode = empty($modes) ? 'off' : implode(',', $modes);
} elseif (false !== ($mode = ini_get('xdebug.mode'))) {
$this->mode = getenv('XDEBUG_MODE') ?: ($mode ?: 'off');
if (preg_match('/^,+$/', str_replace(' ', '', $this->mode))) {
$this->mode = 'off';
}
}
}
self::$xdebugActive = $this->loaded && $this->mode !== 'off';
if ($this->cli = PHP_SAPI === 'cli') {
$this->debug = getenv(self::DEBUG);
}
@@ -123,23 +133,22 @@ class XdebugHandler
*/
public function check()
{
$this->notify(Status::CHECK, $this->loaded);
$this->notify(Status::CHECK, $this->loaded.'|'.$this->mode);
$envArgs = explode('|', (string) getenv($this->envAllowXdebug));
if (empty($envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
if (empty($envArgs[0]) && $this->requiresRestart(self::$xdebugActive)) {
// Restart required
$this->notify(Status::RESTART);
if ($this->prepareRestart()) {
$command = $this->getCommand();
$this->notify(Status::RESTARTING, $command);
$this->restart($command);
}
return;
}
if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
// Restarting, so unset environment variable and use saved values
// Restarted, so unset environment variable and use saved values
$this->notify(Status::RESTARTED);
Process::setEnv($this->envAllowXdebug);
@@ -150,6 +159,8 @@ class XdebugHandler
self::$skipped = $envArgs[1];
}
$this->tryEnableSignals();
// Put restart settings in the environment
$this->setEnvRestartSettings($envArgs);
return;
@@ -204,7 +215,7 @@ class XdebugHandler
if (count($envArgs) !== 6
|| (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
return;
return null;
}
return array(
@@ -228,21 +239,39 @@ class XdebugHandler
}
/**
* Returns true if Xdebug is loaded, or as directed by an extending class
* Returns whether Xdebug is loaded and active
*
* @param bool $isLoaded Whether Xdebug is loaded
* true: if Xdebug is loaded and is running in an active mode.
* false: if Xdebug is not loaded, or it is running with xdebug.mode=off.
*
* @return bool
*/
protected function requiresRestart($isLoaded)
public static function isXdebugActive()
{
return $isLoaded;
return self::$xdebugActive;
}
/**
* Allows an extending class to decide if there should be a restart
*
* The default is to restart if Xdebug is loaded and its mode is not "off".
* Do not typehint for 1.x compatibility.
*
* @param bool $default The default behaviour
*
* @return bool Whether the process should restart
*/
protected function requiresRestart($default)
{
return $default;
}
/**
* Allows an extending class to access the tmpIni
*
* @param string $command
* Do not typehint for 1.x compatibility
*
* @param array $command
*/
protected function restart($command)
{
@@ -252,12 +281,35 @@ class XdebugHandler
/**
* Executes the restarted command then deletes the tmp ini
*
* @param string $command
* @param array $command
*/
private function doRestart($command)
private function doRestart(array $command)
{
passthru($command, $exitCode);
$this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
$this->tryEnableSignals();
$this->notify(Status::RESTARTING, implode(' ', $command));
if (PHP_VERSION_ID >= 70400) {
$cmd = $command;
} else {
$cmd = Process::escapeShellCommand($command);
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
// Outer quotes required on cmd string below PHP 8
$cmd = '"'.$cmd.'"';
}
}
$process = proc_open($cmd, array(), $pipes);
if (is_resource($process)) {
$exitCode = proc_close($process);
}
if (!isset($exitCode)) {
// Unlikely that php or the default shell cannot be invoked
$this->notify(Status::ERROR, 'Unable to restart process');
$exitCode = -1;
} else {
$this->notify(Status::INFO, 'Restarted process exited '.$exitCode);
}
if ($this->debug === '2') {
$this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni);
@@ -329,7 +381,8 @@ class XdebugHandler
}
$content = '';
$regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
$sectionRegex = '/^\s*\[(?:PATH|HOST)\s*=/mi';
$xdebugRegex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
foreach ($iniFiles as $file) {
// Check for inaccessible ini files
@@ -337,7 +390,11 @@ class XdebugHandler
$error = 'Unable to read ini: '.$file;
return false;
}
$content .= preg_replace($regex, ';$1', $data).PHP_EOL;
// Check and remove directives after HOST and PATH sections
if (preg_match($sectionRegex, $data, $matches, PREG_OFFSET_CAPTURE)) {
$data = substr($data, 0, $matches[0][1]);
}
$content .= preg_replace($xdebugRegex, ';$1', $data).PHP_EOL;
}
// Merge loaded settings into our ini content, if it is valid
@@ -353,9 +410,9 @@ class XdebugHandler
}
/**
* Returns the restart command line
* Returns the command line arguments for the restart
*
* @return string
* @return array
*/
private function getCommand()
{
@@ -367,18 +424,7 @@ class XdebugHandler
array_push($php, '-n', '-c', $this->tmpIni);
}
if (defined('STDOUT') && Process::supportsColor(STDOUT)) {
$args = Process::addColorOption($args, $this->colorOption);
}
$args = array_merge($php, array($this->script), $args);
$cmd = Process::escape(array_shift($args), true, true);
foreach ($args as $arg) {
$cmd .= ' '.Process::escape($arg);
}
return $cmd;
return array_merge($php, array($this->script), $args);
}
/**
@@ -490,7 +536,7 @@ class XdebugHandler
/**
* Adds restart settings to the environment
*
* @param string $envArgs
* @param string[] $envArgs
*/
private function setEnvRestartSettings($envArgs)
{
@@ -542,11 +588,12 @@ class XdebugHandler
* Returns true if there are no known configuration issues
*
* @param string $info Set by method
* @return bool
*/
private function checkConfiguration(&$info)
{
if (false !== strpos(ini_get('disable_functions'), 'passthru')) {
$info = 'passthru function is disabled';
if (!function_exists('proc_open')) {
$info = 'proc_open function is disabled';
return false;
}
@@ -560,6 +607,43 @@ class XdebugHandler
}
}
$workingDir = getcwd();
if (0 === strpos($workingDir, '\\\\')) {
if (defined('PHP_WINDOWS_VERSION_BUILD') && PHP_VERSION_ID < 70400) {
$info = 'cmd.exe does not support UNC paths: '.$workingDir;
return false;
}
}
return true;
}
/**
* Enables async signals and control interrupts in the restarted process
*
* Available on Unix PHP 7.1+ with the pcntl extension and Windows PHP 7.4+.
*/
private function tryEnableSignals()
{
if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
pcntl_async_signals(true);
$message = 'Async signals enabled';
if (!self::$inRestart) {
// Restarting, so ignore SIGINT in parent
pcntl_signal(SIGINT, SIG_IGN);
} elseif (is_int(pcntl_signal_get_handler(SIGINT))) {
// Restarted, no handler set so force default action
pcntl_signal(SIGINT, SIG_DFL);
}
}
if (!self::$inRestart && function_exists('sapi_windows_set_ctrl_handler')) {
// Restarting, so set a handler to ignore CTRL events in the parent.
// This ensures that CTRL+C events will be available in the child
// process without having to enable them there, which is unreliable.
sapi_windows_set_ctrl_handler(function ($evt) {});
}
}
}