RepositoryCollection::searchByPattern()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 14
rs 10
1
<?php
2
3
namespace Startwind\Forrest\Repository;
4
5
use Startwind\Forrest\Command\Command;
6
use Startwind\Forrest\Logger\ForrestLogger;
7
8
class RepositoryCollection implements SearchAware, QuestionAware
9
{
10
    public const COMMAND_SEPARATOR = ':';
11
12
    /**
13
     * @var Repository[]
14
     */
15
    private array $repositories = [];
16
17
    public function addRepository(string $identifier, Repository $repository): void
18
    {
19
        $this->repositories[$identifier] = $repository;
20
    }
21
22
    /**
23
     * Return all repositories
24
     */
25
    public function getRepositories(): array
26
    {
27
        return $this->repositories;
28
    }
29
30
    /**
31
     * Get a repository by identifier.
32
     */
33
    public function getRepository($identifier): Repository
34
    {
35
        if (!array_key_exists($identifier, $this->repositories)) {
36
            throw new \RuntimeException('No repository with identifier "' . $identifier . '" found.');
37
        }
38
39
        return $this->repositories[$identifier];
40
    }
41
42
    /**
43
     * @inheritDoc
44
     */
45
    public function searchByFile(array $files): array
46
    {
47
        $fileCommands = [];
48
49
        foreach ($this->repositories as $repositoryIdentifier => $repository) {
50
            if ($repository instanceof SearchAware) {
51
                try {
52
                    $foundCommands = $repository->searchByFile($files);
53
                } catch (\Exception $exception) {
54
                    ForrestLogger::error("Unable to \"search by file\" in repository " . $repositoryIdentifier . ' (' . $exception->getMessage() . ')');
55
                    continue;
56
                }
57
                foreach ($foundCommands as $foundCommand) {
58
                    $fileCommands[self::createUniqueCommandName($repositoryIdentifier, $foundCommand)] = $foundCommand;
59
                }
60
            }
61
        }
62
63
        return $fileCommands;
64
    }
65
66
    /**
67
     * @inheritDoc
68
     */
69
    public function searchByPattern(array $patterns): array
70
    {
71
        $commands = [];
72
73
        foreach ($this->repositories as $repositoryIdentifier => $repository) {
74
            if ($repository instanceof SearchAware) {
75
                $foundCommands = $repository->searchByPattern($patterns);
76
                foreach ($foundCommands as $foundCommand) {
77
                    $commands[RepositoryCollection::createUniqueCommandName($repositoryIdentifier, $foundCommand)] = $foundCommand;
78
                }
79
            }
80
        }
81
82
        return $commands;
83
    }
84
85
    /**
86
     * @inheritDoc
87
     */
88
    public function searchByTools(array $tools): array
89
    {
90
        $commands = [];
91
92
        foreach ($this->repositories as $repositoryIdentifier => $repository) {
93
            if ($repository instanceof SearchAware) {
94
                $foundCommands = $repository->searchByTools($tools);
95
                foreach ($foundCommands as $foundCommand) {
96
                    $commands[RepositoryCollection::createUniqueCommandName($repositoryIdentifier, $foundCommand)] = $foundCommand;
97
                }
98
            }
99
        }
100
101
        return $commands;
102
    }
103
104
    /**
105
     * @return \Startwind\Forrest\Command\Tool\Tool[]
106
     */
107
    public function getToolInformation(string $tool): array
108
    {
109
        $toolInformation = [];
110
111
        foreach ($this->getRepositories() as $repoName => $repository) {
112
            if ($repository instanceof ToolAware) {
113
                $toolInfo = $repository->findToolInformation($tool);
114
                if ($toolInfo) {
115
                    $toolInformation[$repoName] = $repository->findToolInformation($tool);
116
                }
117
            }
118
        }
119
120
        return $toolInformation;
121
    }
122
123
    /**
124
     * Return a command by the fully qualified command name.
125
     */
126
    public function getCommand(string $fullyQualifiedCommandName): Command
127
    {
128
        $repositoryIdentifier = RepositoryCollection::getRepositoryIdentifier($fullyQualifiedCommandName);
129
        $commandName = RepositoryCollection::getCommandName($fullyQualifiedCommandName);
130
131
        try {
132
            $command = $this->getRepository($repositoryIdentifier)->getCommand($commandName);
133
        } catch (\Exception $exception) {
134
            throw new \RuntimeException('Unable to load command from ' . $repositoryIdentifier . ': ' . lcfirst($exception->getMessage()));
135
        }
136
137
        $command->setFullyQualifiedIdentifier($fullyQualifiedCommandName);
138
139
        return $command;
140
    }
141
142
    /**
143
     * Return the identifier of the repository from a full command name.
144
     */
145
    public static function getRepositoryIdentifier(string $identifier): string
146
    {
147
        return substr($identifier, 0, strpos($identifier, self::COMMAND_SEPARATOR));
148
    }
149
150
    public static function getCommandName(string $fullyQualifiedCommandName): string
151
    {
152
        return substr($fullyQualifiedCommandName, strpos($fullyQualifiedCommandName, self::COMMAND_SEPARATOR) + 1);
153
    }
154
155
    public static function createUniqueCommandName(string $repositoryIdentifier, Command $command): string
156
    {
157
        return $repositoryIdentifier . ':' . $command->getName();
158
    }
159
160
    public function ask(string $question): array
161
    {
162
        $answers = [];
163
164
        foreach ($this->repositories as $repositoryName => $repository) {
165
            if ($repository instanceof QuestionAware) {
166
                $answerList = $repository->ask($question);
167
                foreach ($answerList as $item) {
168
                    $answers[$repositoryName][] = $item;
169
                }
170
            }
171
        }
172
173
        return $answers;
174
    }
175
176
    public function explain(string $prompt): array
177
    {
178
        $answers = [];
179
180
        foreach ($this->repositories as $repositoryName => $repository) {
181
            if ($repository instanceof QuestionAware) {
182
                $answerList = $repository->explain($prompt);
183
                foreach ($answerList as $item) {
184
                    $answers[$repositoryName][] = $item;
185
                }
186
            }
187
        }
188
189
        return $answers;
190
    }
191
192
    public function pushStatus(string $fullyQualifiedCommandName, string $status): void
193
    {
194
        $repositoryIdentifier = RepositoryCollection::getRepositoryIdentifier($fullyQualifiedCommandName);
195
        $commandName = RepositoryCollection::getCommandName($fullyQualifiedCommandName);
196
197
        $repository = $this->getRepository($repositoryIdentifier);
198
199
        if ($repository instanceof StatusAwareRepository) {
200
            try {
201
                $repository->pushStatus($commandName, $status);
202
            } catch (\Exception $exception) {
203
                ForrestLogger::warn($exception->getMessage());
204
            }
205
        }
206
    }
207
}
208