Passed
Push — main ( 96d323...c12136 )
by Nils
15:53
created

PatternCommand   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 43
c 4
b 0
f 0
dl 0
loc 90
rs 10
wmc 12

3 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 9 1
A runAiAskCommand() 0 11 1
B doExecute() 0 53 10
1
<?php
2
3
namespace Startwind\Forrest\CliCommand\Search;
4
5
use Startwind\Forrest\CliCommand\Ai\AskCommand;
6
use Startwind\Forrest\Output\OutputHelper;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Input\ArrayInput;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
class PatternCommand extends SearchCommand
15
{
16
    const PERFECT_SCORE = 10;
17
18
    public const COMMAND_NAME = 'search:pattern';
19
20
    protected static $defaultName = self::COMMAND_NAME;
21
    protected static $defaultDescription = 'Search for commands that fit the given pattern.';
22
23
    protected function configure(): void
24
    {
25
        parent::configure();
26
27
        $this->addArgument('pattern', InputArgument::IS_ARRAY, 'The pattern you want to search for.');
28
        $this->addOption('force', null, InputOption::VALUE_NONE, 'Run the command without asking for permission.');
29
        $this->addOption('score', 's', InputOption::VALUE_OPTIONAL, 'The minimal search score.', 7);
30
31
        $this->setAliases(['pattern']);
32
    }
33
34
    protected function doExecute(InputInterface $input, OutputInterface $output): int
35
    {
36
        OutputHelper::renderHeader($output);
37
38
        $minScore = $input->getOption('score');
39
40
        $this->enrichRepositories();
41
42
        $pattern = $input->getArgument('pattern');
43
44
        if (count($pattern) == 1 && str_contains($pattern[0], ' ')) {
45
            $pattern = explode(' ', $pattern[0]);
46
        }
47
48
        $this->renderInfoBox('This is a list of commands that match the given pattern. Sorted by relevance.');
49
50
        $commands = $this->getRepositoryCollection()->searchByPattern($pattern);
51
52
        $filteredCommands = [];
53
        $perfectCommands = [];
54
55
        foreach ($commands as $key => $command) {
56
            if ($command->getScore() > $minScore) {
57
                $filteredCommands[$key] = $command;
58
            }
59
60
            if ($command->getScore() > self::PERFECT_SCORE) {
61
                $perfectCommands[$key] = $command;
62
            }
63
        }
64
65
        if (count($filteredCommands) == 0) {
66
            $filteredCommands = $commands;
67
        }
68
69
        if (count($perfectCommands) > 0) {
70
            $filteredCommands = $perfectCommands;
71
        }
72
73
        if (empty($filteredCommands)) {
74
            $this->renderErrorBox('No commands found that match the given pattern.');
75
            return Command::FAILURE;
76
        }
77
78
        $result = $this->runFromCommands($filteredCommands, [], true);
79
80
        if ($result !== true) {
81
            return $result;
82
        }
83
84
        $this->renderInfoBox('We are asking the Forrest AI...');
85
86
        return $this->runAiAskCommand($pattern);
87
    }
88
89
    /**
90
     * The run command can also be applied to a file. This is a shortcut for the
91
     * search:file symfony console command.
92
     */
93
    private function runAiAskCommand(array $patterns): int
94
    {
95
        $arguments = [
96
            'question' => $patterns,
97
            '--silent' => true
98
        ];
99
100
        $fileArguments = new ArrayInput($arguments);
101
        $fileCommand = $this->getApplication()->find(AskCommand::COMMAND_NAME);
102
103
        return $fileCommand->run($fileArguments, $this->getOutput());
104
    }
105
106
}
107