Вход Регистрация
Файл: vendor/symfony/console/Command/TraceableCommand.php
Строк: 553
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentConsoleCommand;

use 
SymfonyComponentConsoleApplication;
use 
SymfonyComponentConsoleCompletionCompletionInput;
use 
SymfonyComponentConsoleCompletionCompletionSuggestions;
use 
SymfonyComponentConsoleHelperHelperInterface;
use 
SymfonyComponentConsoleHelperHelperSet;
use 
SymfonyComponentConsoleInputInputDefinition;
use 
SymfonyComponentConsoleInputInputInterface;
use 
SymfonyComponentConsoleOutputConsoleOutputInterface;
use 
SymfonyComponentConsoleOutputOutputInterface;
use 
SymfonyComponentStopwatchStopwatch;

/**
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class TraceableCommand extends Command implements SignalableCommandInterface
{
    public 
readonly Command $command;
    public 
int $exitCode;
    public ?
int $interruptedBySignal null;
    public 
bool $ignoreValidation;
    public 
bool $isInteractive false;
    public 
string $duration 'n/a';
    public 
string $maxMemoryUsage 'n/a';
    public 
InputInterface $input;
    public 
OutputInterface $output;
    
/** @var array<string, mixed> */
    
public array $arguments;
    
/** @var array<string, mixed> */
    
public array $options;
    
/** @var array<string, mixed> */
    
public array $interactiveInputs = [];
    public array 
$handledSignals = [];

    public function 
__construct(
        
Command $command,
        private 
readonly Stopwatch $stopwatch,
    ) {
        if (
$command instanceof LazyCommand) {
            
$command $command->getCommand();
        }

        
$this->command $command;

        
// prevent call to self::getDefaultDescription()
        
$this->setDescription($command->getDescription());

        
parent::__construct($command->getName());

        
// init below enables calling {@see parent::run()}
        
[$code$processTitle$ignoreValidationErrors] = Closure::bind(function () {
            return [
$this->code$this->processTitle$this->ignoreValidationErrors];
        }, 
$commandCommand::class)();

        if (
is_callable($code)) {
            
$this->setCode($code);
        }

        if (
$processTitle) {
            
parent::setProcessTitle($processTitle);
        }

        if (
$ignoreValidationErrors) {
            
parent::ignoreValidationErrors();
        }

        
$this->ignoreValidation $ignoreValidationErrors;
    }

    public function 
__call(string $name, array $arguments): mixed
    
{
        return 
$this->command->{$name}(...$arguments);
    }

    public function 
getSubscribedSignals(): array
    {
        return 
$this->command instanceof SignalableCommandInterface $this->command->getSubscribedSignals() : [];
    }

    public function 
handleSignal(int $signalint|false $previousExitCode 0): int|false
    
{
        if (!
$this->command instanceof SignalableCommandInterface) {
            return 
false;
        }

        
$event $this->stopwatch->start($this->getName().'.handle_signal');

        
$exit $this->command->handleSignal($signal$previousExitCode);

        
$event->stop();

        if (!isset(
$this->handledSignals[$signal])) {
            
$this->handledSignals[$signal] = [
                
'handled' => 0,
                
'duration' => 0,
                
'memory' => 0,
            ];
        }

        ++
$this->handledSignals[$signal]['handled'];
        
$this->handledSignals[$signal]['duration'] += $event->getDuration();
        
$this->handledSignals[$signal]['memory'] = max(
            
$this->handledSignals[$signal]['memory'],
            
$event->getMemory() >> 20
        
);

        return 
$exit;
    }

    
/**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    
public function ignoreValidationErrors(): void
    
{
        
$this->ignoreValidation true;
        
$this->command->ignoreValidationErrors();

        
parent::ignoreValidationErrors();
    }

    public function 
setApplication(?Application $application null): void
    
{
        
$this->command->setApplication($application);
    }

    public function 
getApplication(): ?Application
    
{
        return 
$this->command->getApplication();
    }

    public function 
setHelperSet(HelperSet $helperSet): void
    
{
        
$this->command->setHelperSet($helperSet);
    }

    public function 
getHelperSet(): ?HelperSet
    
{
        return 
$this->command->getHelperSet();
    }

    public function 
isEnabled(): bool
    
{
        return 
$this->command->isEnabled();
    }

    public function 
complete(CompletionInput $inputCompletionSuggestions $suggestions): void
    
{
        
$this->command->complete($input$suggestions);
    }

    
/**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    
public function setCode(callable $code): static
    {
        
$this->command->setCode($code);

        return 
parent::setCode(function (InputInterface $inputOutputInterface $output) use ($code): int {
            
$event $this->stopwatch->start($this->getName().'.code');

            
$this->exitCode $code($input$output);

            
$event->stop();

            return 
$this->exitCode;
        });
    }

    
/**
     * @internal
     */
    
public function mergeApplicationDefinition(bool $mergeArgs true): void
    
{
        
$this->command->mergeApplicationDefinition($mergeArgs);
    }

    public function 
setDefinition(array|InputDefinition $definition): static
    {
        
$this->command->setDefinition($definition);

        return 
$this;
    }

    public function 
getDefinition(): InputDefinition
    
{
        return 
$this->command->getDefinition();
    }

    public function 
getNativeDefinition(): InputDefinition
    
{
        return 
$this->command->getNativeDefinition();
    }

    public function 
addArgument(string $name, ?int $mode nullstring $description ''mixed $default null, array|Closure $suggestedValues = []): static
    {
        
$this->command->addArgument($name$mode$description$default$suggestedValues);

        return 
$this;
    }

    public function 
addOption(string $namestring|array|null $shortcut null, ?int $mode nullstring $description ''mixed $default null, array|Closure $suggestedValues = []): static
    {
        
$this->command->addOption($name$shortcut$mode$description$default$suggestedValues);

        return 
$this;
    }

    
/**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    
public function setProcessTitle(string $title): static
    {
        
$this->command->setProcessTitle($title);

        return 
parent::setProcessTitle($title);
    }

    public function 
setHelp(string $help): static
    {
        
$this->command->setHelp($help);

        return 
$this;
    }

    public function 
getHelp(): string
    
{
        return 
$this->command->getHelp();
    }

    public function 
getProcessedHelp(): string
    
{
        return 
$this->command->getProcessedHelp();
    }

    public function 
getSynopsis(bool $short false): string
    
{
        return 
$this->command->getSynopsis($short);
    }

    public function 
addUsage(string $usage): static
    {
        
$this->command->addUsage($usage);

        return 
$this;
    }

    public function 
getUsages(): array
    {
        return 
$this->command->getUsages();
    }

    public function 
getHelper(string $name): HelperInterface
    
{
        return 
$this->command->getHelper($name);
    }

    public function 
run(InputInterface $inputOutputInterface $output): int
    
{
        
$this->input $input;
        
$this->output $output;
        
$this->arguments $input->getArguments();
        
$this->options $input->getOptions();
        
$event $this->stopwatch->start($this->getName(), 'command');

        try {
            
$this->exitCode parent::run($input$output);
        } finally {
            
$event->stop();

            if (
$output instanceof ConsoleOutputInterface && $output->isDebug()) {
                
$output->getErrorOutput()->writeln((string) $event);
            }

            
$this->duration $event->getDuration().' ms';
            
$this->maxMemoryUsage = ($event->getMemory() >> 20).' MiB';

            if (
$this->isInteractive) {
                
$this->extractInteractiveInputs($input->getArguments(), $input->getOptions());
            }
        }

        return 
$this->exitCode;
    }

    protected function 
initialize(InputInterface $inputOutputInterface $output): void
    
{
        
$event $this->stopwatch->start($this->getName().'.init''command');

        
$this->command->initialize($input$output);

        
$event->stop();
    }

    protected function 
interact(InputInterface $inputOutputInterface $output): void
    
{
        if (!
$this->isInteractive Command::class !== (new ReflectionMethod($this->command'interact'))->getDeclaringClass()->getName()) {
            return;
        }

        
$event $this->stopwatch->start($this->getName().'.interact''command');

        
$this->command->interact($input$output);

        
$event->stop();
    }

    protected function 
execute(InputInterface $inputOutputInterface $output): int
    
{
        
$event $this->stopwatch->start($this->getName().'.execute''command');

        
$exitCode $this->command->execute($input$output);

        
$event->stop();

        return 
$exitCode;
    }

    private function 
extractInteractiveInputs(array $arguments, array $options): void
    
{
        foreach (
$arguments as $argName => $argValue) {
            if (
array_key_exists($argName$this->arguments) && $this->arguments[$argName] === $argValue) {
                continue;
            }

            
$this->interactiveInputs[$argName] = $argValue;
        }

        foreach (
$options as $optName => $optValue) {
            if (
array_key_exists($optName$this->options) && $this->options[$optName] === $optValue) {
                continue;
            }

            
$this->interactiveInputs['--'.$optName] = $optValue;
        }
    }
}
Онлайн: 1
Реклама