UpdateOrigins::createResourcesGateway()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\SatCatalogosPopulate\Commands;
6
7
use PhpCfdi\SatCatalogosPopulate\Database\Repository;
8
use PhpCfdi\SatCatalogosPopulate\Importers\SourcesImporter;
9
use PhpCfdi\SatCatalogosPopulate\Origins\Origins;
10
use PhpCfdi\SatCatalogosPopulate\Origins\OriginsIO;
11
use PhpCfdi\SatCatalogosPopulate\Origins\Reviewers;
12
use PhpCfdi\SatCatalogosPopulate\Origins\ReviewStatus;
13
use PhpCfdi\SatCatalogosPopulate\Origins\Upgrader;
14
use PhpCfdi\SatCatalogosPopulate\Origins\WebResourcesGateway;
15
use Psr\Log\LoggerInterface;
16
use RuntimeException;
17
18
final class UpdateOrigins implements CommandInterface
19
{
20
    private const DEFAULT_ORIGINS_FILENAME = 'origins.xml';
21
22
    private readonly string $originsFile;
23
24
    private readonly string $workingFolder;
25
26
    private readonly bool $updateDatabase;
27
28
    public function __construct(
29
        string $originsFile,
30
        private readonly bool $updateOrigins,
31
        private readonly string $databaseLocation,
32
        private LoggerInterface $logger
33
    ) {
34
        if ('' === $originsFile) {
35
            throw new RuntimeException('Invalid origins: empty string received');
36
        }
37
        if (is_dir($originsFile)) {
38
            $originsFile = $originsFile . DIRECTORY_SEPARATOR . self::DEFAULT_ORIGINS_FILENAME;
39
        }
40
        if (! file_exists($originsFile) || ! is_readable($originsFile)) {
41
            throw new RuntimeException('Invalid origins: file does not exists');
42
        }
43
44
        $this->originsFile = $originsFile;
0 ignored issues
show
Bug introduced by
The property originsFile is declared read-only in PhpCfdi\SatCatalogosPopu...\Commands\UpdateOrigins.
Loading history...
45
        $this->workingFolder = dirname($originsFile);
0 ignored issues
show
Bug introduced by
The property workingFolder is declared read-only in PhpCfdi\SatCatalogosPopu...\Commands\UpdateOrigins.
Loading history...
46
        $this->updateDatabase = ('' !== $this->databaseLocation);
0 ignored issues
show
Bug introduced by
The property updateDatabase is declared read-only in PhpCfdi\SatCatalogosPopu...\Commands\UpdateOrigins.
Loading history...
47
    }
48
49
    public function getOriginsFile(): string
50
    {
51
        return $this->originsFile;
52
    }
53
54
    public function getWorkingFolder(): string
55
    {
56
        return $this->workingFolder;
57
    }
58
59
    public function updateOrigins(): bool
60
    {
61
        return $this->updateOrigins;
62
    }
63
64
    public function updateDatabase(): bool
65
    {
66
        return $this->updateDatabase;
67
    }
68
69
    public function getDatabaseLocation(): string
70
    {
71
        return $this->databaseLocation;
72
    }
73
74
    protected function originsRestore(): Origins
75
    {
76
        return (new OriginsIO())->readFile($this->getOriginsFile());
77
    }
78
79
    protected function originsStore(Origins $origins): void
80
    {
81
        (new OriginsIO())->writeFile($this->getOriginsFile(), $origins);
82
    }
83
84
    public function createResourcesGateway(): WebResourcesGateway
85
    {
86
        return new WebResourcesGateway();
87
    }
88
89
    public function run(): int
90
    {
91
        $origins = $this->originsRestore();
92
        $resourcesGateway = $this->createResourcesGateway();
93
        $reviewers = Reviewers::createWithDefaultReviewers($resourcesGateway);
94
        $reviews = $reviewers->review($origins);
95
96
        $notFoundReviews = $reviews->filterStatus(ReviewStatus::notFound());
97
        $notUpdatedReviews = $reviews->filterStatus(ReviewStatus::notUpdated());
98
        $upToDateReviews = $reviews->filterStatus(ReviewStatus::uptodate());
99
100
        foreach ($upToDateReviews as $review) {
101
            $this->logger->info(sprintf(
102
                'El origen %s desde %s para %s está actualizado',
103
                $review->origin()->name(),
104
                $review->origin()->downloadUrl(),
105
                $review->origin()->destinationFilename(),
106
            ));
107
        }
108
        foreach ($notUpdatedReviews as $review) {
109
            if (! $review->origin()->hasLastVersion()) {
110
                $this->logger->info(sprintf(
111
                    'El origen %s desde %s para %s no existe, se descargará',
112
                    $review->origin()->name(),
113
                    $review->origin()->downloadUrl(),
114
                    $review->origin()->destinationFilename(),
115
                ));
116
            } else {
117
                $this->logger->info(sprintf(
118
                    'El origen %s desde %s para %s está desactualizado, la nueva versión tiene fecha %s',
119
                    $review->origin()->name(),
120
                    $review->origin()->downloadUrl(),
121
                    $review->origin()->destinationFilename(),
122
                    $review->origin()->lastVersion()->format('c')
123
                ));
124
            }
125
        }
126
        foreach ($notFoundReviews as $review) {
127
            $this->logger->info(sprintf(
128
                'El origen %s para %s no fue encontrado',
129
                $review->origin()->name(),
130
                $review->origin()->destinationFilename()
131
            ));
132
        }
133
        if ($notFoundReviews->count() > 0) {
134
            $this->logger->error(sprintf('No se encontraron %d orígenes', $notFoundReviews->count()));
135
            return 1;
136
        }
137
138
        if ($upToDateReviews->count() === count($reviews)) {
139
            $this->logger->info('No existen orígenes para actualizar');
140
            return 0;
141
        }
142
143
        if (! $this->updateOrigins()) {
144
            $this->logger->info(sprintf('Existen %d orígenes para actualizar', $notUpdatedReviews->count()));
145
            return 0;
146
        }
147
        // have to perform upgrade
148
        $upgrader = new Upgrader($resourcesGateway, $this->getWorkingFolder(), $this->logger);
149
        $recentOrigins = $upgrader->upgradeReviews($reviews);
150
        $this->logger->info('Se actualizaron todos los orígenes');
151
        $this->originsStore($recentOrigins);
152
        $this->logger->info('Se actualizó el archivo de orígenes');
153
154
        if (! $this->updateDatabase()) {
155
            return 0;
156
        }
157
158
        $dbUpdateCommand = new UpdateDatabase($this->getWorkingFolder(), $this->getDatabaseLocation(), $this->logger);
159
        return $dbUpdateCommand->run();
160
    }
161
162
    protected function createRepository(): Repository
163
    {
164
        return new Repository($this->getDatabaseLocation());
165
    }
166
167
    protected function createImporter(): SourcesImporter
168
    {
169
        return new SourcesImporter();
170
    }
171
172
    public function setLogger(LoggerInterface $logger): void
173
    {
174
        $this->logger = $logger;
175
    }
176
177
    public static function help(string $commandName): string
178
    {
179
        return implode(PHP_EOL, [
180
            "Sintax: $commandName update-origins [--dry-run] [--update-database database] origins-file|origins-folder",
181
            '    --update-database|-w:  location to update database',
182
            '    --dry-run|-n:          do not update, just report checks',
183
            '    origins-file:          location where origins file is',
184
            '    origins-folder:        directory location where ' . self::DEFAULT_ORIGINS_FILENAME . ' is',
185
        ]);
186
    }
187
188
    public static function createFromArguments(array $arguments): self
189
    {
190
        // update-origins --dry-run --update-database database origins-file-or-folder
191
        $count = count($arguments);
192
        $dryRun = false;
193
        $databaseFilename = '';
194
        $originsFile = '';
195
        for ($i = 0; $i < $count; $i++) {
196
            $current = $arguments[$i];
197
            if (in_array($current, ['--dry-run', '-n'], true)) {
198
                $dryRun = true;
199
                continue;
200
            }
201
            if (in_array($current, ['--update-database', '-w'], true)) {
202
                $databaseFilename = $arguments[$i + 1] ?? '';
203
                $i = $i + 1;
204
                continue;
205
            }
206
            if ('' === $originsFile) {
207
                $originsFile = $current;
208
                continue;
209
            }
210
211
            throw new RuntimeException(sprintf("Unexpected argument '%s'", $current));
212
        }
213
214
        return new self($originsFile, ! $dryRun, $databaseFilename, new TerminalLogger());
215
    }
216
}
217