RunHelper::executeCommand()   A
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 5
eloc 16
c 4
b 0
f 0
nc 7
nop 3
dl 0
loc 27
rs 9.4222
1
<?php
2
3
namespace Startwind\Forrest\Output;
4
5
use Startwind\Forrest\Command\Command;
6
use Startwind\Forrest\Command\Prompt;
7
use Startwind\Forrest\Config\ConfigFileHandler;
8
use Startwind\Forrest\History\HistoryHandler;
9
use Startwind\Forrest\Runner\CommandRunner;
10
use Startwind\Forrest\Util\OSHelper;
11
use Startwind\Forrest\Util\OutputHelper;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Startwind\Forrest\Output\OutputHelper. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
use Symfony\Component\Console\Command\Command as SymfonyCommand;
13
use Symfony\Component\Console\Helper\QuestionHelper;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Question\ConfirmationQuestion;
17
18
class RunHelper
19
{
20
    private InputInterface $input;
21
22
    private OutputInterface $output;
23
24
    private ConfigFileHandler $configHandler;
25
26
    private QuestionHelper $questionHelper;
27
28
    private HistoryHandler $historyHandler;
29
30
    public function __construct(
31
        InputInterface $input,
32
        OutputInterface $output,
33
        QuestionHelper $questionHelper,
34
        ConfigFileHandler $configHandler,
35
        HistoryHandler $historyHandler
36
    ) {
37
        $this->input = $input;
38
        $this->output = $output;
39
        $this->questionHelper = $questionHelper;
40
        $this->configHandler = $configHandler;
41
        $this->historyHandler = $historyHandler;
42
    }
43
44
    public function handleForceOption(bool $force, Command $command, string $repositoryIdentifier): bool
45
    {
46
        if (!$force) {
47
            return true;
48
        }
49
50
        $hasChanged = $this->configHandler->hasChecksumChanged($command, $repositoryIdentifier);
51
52
        if ($hasChanged) {
53
            return $this->questionHelper->ask($this->input, $this->output, new ConfirmationQuestion('  The signature of the command has changed since you last run it. Do you confirm to still run it? [y/n] ', false));
54
        } else {
55
            return true;
56
        }
57
    }
58
59
    public function handleRunnable(Command $command, string $finalPrompt): bool
60
    {
61
        if (!$command->isRunnable()) {
62
            $copied = OSHelper::copyToClipboard($finalPrompt);
63
64
            if ($copied) {
65
                $clipboardText = " It was copied to your clipboard.";
66
            } else {
67
                $clipboardText = "";
68
            }
69
70
            OutputHelper::writeWarningBox($this->output, [
71
                'This command was marked as not runnable by Forrest.' . $clipboardText
72
            ]);
73
74
            return false;
75
        } else {
76
            return true;
77
        }
78
    }
79
80
    public function confirmRun(bool $force): bool
81
    {
82
        if (!$force) {
83
            return $this->questionHelper->ask($this->input, $this->output, new ConfirmationQuestion('  Are you sure you want to run that command? [y/n] ', false));
84
        }
85
86
        return true;
87
    }
88
89
    /**
90
     * Run every single command in the executable command.
91
     */
92
    public function executeCommand(OutputInterface $output, Command $actualCommand, Prompt $prompt): int
93
    {
94
        $commands = CommandRunner::stringToMultilinePrompt($prompt->getFinalPrompt());
95
96
        $commandRunner = new CommandRunner($this->historyHandler);
97
98
        foreach ($commands as $command) {
99
            if (count($commands) > 1) {
100
                if (PHP_VERSION >= 8) {
101
                    OutputHelper::writeMessage($output, 'Running: ' . $command, '<bg=#445760;fg=white>', '</>');
102
                } else {
103
                    OutputHelper::writeInfoBox($output, 'Running: ' . $command);
104
                }
105
            }
106
            $exitCode = $commandRunner->execute(
107
                $output,
108
                $command,
109
                true,
110
                $actualCommand->isAllowedInHistory()
111
            );
112
113
            if ($exitCode != SymfonyCommand::SUCCESS) {
114
                return $exitCode;
115
            }
116
        }
117
118
        return SymfonyCommand::SUCCESS;
119
    }
120
}
121