Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 96 additions & 81 deletions src/Status.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@
class Status
{
const ENV_RESTART = 'XDEBUG_HANDLER_RESTART';
const CHECK = 'Check';
const ERROR = 'Error';
const INFO = 'Info';
const NORESTART = 'NoRestart';
const RESTART = 'Restart';
const RESTARTING = 'Restarting';
const RESTARTED = 'Restarted';

/** @var bool */
private $active;

/** @var bool */
private $debug;
Expand All @@ -55,16 +51,23 @@ class Status
/**
* @param string $envAllowXdebug Prefixed _ALLOW_XDEBUG name
* @param bool $debug Whether debug output is required
* @param string|null $version Xdebug version
* @param string|null $mode Xdebug mode
*/
public function __construct(string $envAllowXdebug, bool $debug)
public function __construct(string $envAllowXdebug, bool $debug, ?string $version, ?string $mode)
{
$start = getenv(self::ENV_RESTART);
Process::setEnv(self::ENV_RESTART);
putenv(self::ENV_RESTART);
$this->ellapsed = is_numeric($start) ? (int) round((microtime(true) - $start) * 1000) : 0;

$this->envAllowXdebug = $envAllowXdebug;
$this->debug = $debug && defined('STDERR');
$this->modeOff = false;
$this->active = $this->debug = $debug && defined('STDERR');

if ((string) $version !== '') {
$this->loaded = '('.$version.')'.((string) $mode !== '' ? ' xdebug.mode='.$mode : '');
}

$this->modeOff = $mode === 'off';
$this->pid = (int) getmypid();
}

Expand All @@ -76,95 +79,84 @@ public function __construct(string $envAllowXdebug, bool $debug)
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
$this->active = true;
}

/**
* Calls a handler method to report a message
*
* @throws \InvalidArgumentException If $op is not known
* Checking status messages
*/
public function report(string $op, ?string $data): void
public function reportCheck(): void
{
if ($this->logger !== null || $this->debug) {
$param = (string) $data;

switch($op) {
case self::CHECK:
$this->reportCheck($param);
break;
case self::ERROR:
$this->reportError($param);
break;
case self::INFO:
$this->reportInfo($param);
break;
case self::NORESTART:
$this->reportNoRestart();
break;
case self::RESTART:
$this->reportRestart();
break;
case self::RESTARTED:
$this->reportRestarted();
break;
case self::RESTARTING:
$this->reportRestarting($param);
break;
default:
throw new \InvalidArgumentException('Unknown op handler: '.$op);
}
if ($this->active) {
$this->output('Checking '.$this->envAllowXdebug);
}
}

/**
* Outputs a status message
* Shows the loaded status and saves the current time
*/
private function output(string $text, ?string $level = null): void
public function reportRequired(): void
{
if ($this->logger !== null) {
$this->logger->log($level !== null ? $level: LogLevel::DEBUG, $text);
}

if ($this->debug) {
fwrite(STDERR, sprintf('xdebug-handler[%d] %s', $this->pid, $text.PHP_EOL));
if ($this->active) {
$this->output($this->getLoadedMessage());
// Set the timer environment variable
putenv(self::ENV_RESTART.'='.(string) microtime(true));
}
}

/**
* Checking status message
* Restarting status message
*
* @param list<string>|string $command
*/
private function reportCheck(string $loaded): void
public function reportRestarting($command): void
{
list($version, $mode) = explode('|', $loaded);
if (!$this->active) {
return;
}

if ($version !== '') {
$this->loaded = '('.$version.')'.($mode !== '' ? ' xdebug.mode='.$mode : '');
$text = sprintf('Process restarting (%s)', $this->getEnvAllow());
$this->output($text);

if (is_array($command)) {
$command = sprintf('[%s]', implode(', ', $command));
}
$this->modeOff = $mode === 'off';
$this->output('Checking '.$this->envAllowXdebug);
$text = 'Running: '.$command;
$this->output($text);
}

/**
* Error status message
* Exit message
*/
private function reportError(string $error): void
public function reportExit(int $exitCode): void
{
$this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
if ($this->active) {
$this->output('Restarted process exited '.$exitCode);
}
}

/**
* Info status message
* Restarted status message
*/
private function reportInfo(string $info): void
public function reportRestarted(): void
{
$this->output($info);
if ($this->active) {
$loaded = $this->getLoadedMessage();
$text = sprintf('Restarted (%d ms). %s', $this->ellapsed, $loaded);
$level = $this->loaded !== null ? LogLevel::WARNING : null;
$this->output($text, $level);
}
}

/**
* No restart status message
*/
private function reportNoRestart(): void
public function reportNoRestart(): void
{
if (!$this->active) {
return;
}

$this->output($this->getLoadedMessage());

if ($this->loaded !== null) {
Expand All @@ -177,34 +169,57 @@ private function reportNoRestart(): void
}

/**
* Restart status message
* Existing restart settings message
*/
private function reportRestart(): void
public function reportExisting(): void
{
$this->output($this->getLoadedMessage());
Process::setEnv(self::ENV_RESTART, (string) microtime(true));
if ($this->active) {
$this->output('Process called with existing restart settings');
}
}

/**
* Restarted status message
* Configuration error, logged as a warning
*/
private function reportRestarted(): void
public function configError(string $error): void
{
$loaded = $this->getLoadedMessage();
$text = sprintf('Restarted (%d ms). %s', $this->ellapsed, $loaded);
$level = $this->loaded !== null ? LogLevel::WARNING : null;
$this->output($text, $level);
if ($this->active) {
$this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING);
}
}

/**
* Restarting status message
* General info
*/
private function reportRestarting(string $command): void
public function info(string $info): void
{
$text = sprintf('Process restarting (%s)', $this->getEnvAllow());
$this->output($text);
$text = 'Running: '.$command;
$this->output($text);
if ($this->active) {
$this->output($info);
}
}

/**
* General error, logged as a warning
*/
public function error(string $error): void
{
if ($this->active) {
$this->output($error, LogLevel::WARNING);
}
}

/**
* Outputs a status message
*/
private function output(string $text, ?string $level = null): void
{
if ($this->logger !== null) {
$this->logger->log($level !== null ? $level: LogLevel::DEBUG, $text);
}

if ($this->debug) {
fwrite(STDERR, sprintf('xdebug-handler[%d] %s', $this->pid, $text.PHP_EOL));
}
}

/**
Expand Down
Loading
Loading