UpdateCommand::getLatestVersionDate()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
ccs 0
cts 5
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpCfdi\RfcLinc\Application\Cli\Commands;
6
7
use PhpCfdi\RfcLinc\Application\Cli\OutputLogger;
8
use PhpCfdi\RfcLinc\Application\Cli\ProgressByHit;
9
use PhpCfdi\RfcLinc\Application\Config;
10
use PhpCfdi\RfcLinc\DataGateway\FactoryInterface;
11
use PhpCfdi\RfcLinc\Domain\Catalog;
12
use PhpCfdi\RfcLinc\Domain\VersionDate;
13
use PhpCfdi\RfcLinc\Updater\Blob;
14
use PhpCfdi\RfcLinc\Updater\Updater;
15
use Pimple\Container;
16
use Symfony\Component\Console\Command\Command;
17
use Symfony\Component\Console\Input\InputArgument;
18
use Symfony\Component\Console\Input\InputInterface;
19
use Symfony\Component\Console\Input\InputOption;
20
use Symfony\Component\Console\Output\OutputInterface;
21
22
class UpdateCommand extends Command
23
{
24
    /** @var Container */
25
    private $container;
26
27 5
    public function __construct(Container $container)
28
    {
29 5
        parent::__construct('update');
30 5
        $this->container = $container;
31 5
    }
32
33 1
    public function gateways(): FactoryInterface
34
    {
35 1
        return $this->container['gateways'];
36
    }
37
38 1
    public function config(): Config
39
    {
40 1
        return $this->container['config'];
41
    }
42
43 5
    protected function configure()
44
    {
45 5
        $this->setDescription('Update the database with a new catalog');
46 5
        $this->addArgument('date', InputArgument::REQUIRED, 'Update the database to this date');
47 5
        $this->addArgument(
48 5
            'blobs',
49 5
            InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
50 5
            'Use this blobs instead of downloading'
51
        );
52 5
        $this->addOption(
53 5
            'report-every',
54 5
            're',
55 5
            InputOption::VALUE_OPTIONAL,
56 5
            'Update the database to this date',
57 5
            '500000'
58
        );
59 5
    }
60
61 1
    public function getOptionReportEvery(string $value): int
62
    {
63 1
        $inputReportEvery = $value;
64 1
        if (! is_numeric($inputReportEvery)) {
65
            $inputReportEvery = 5000000;
66
        } else {
67 1
            $inputReportEvery = (int) $inputReportEvery;
68
        }
69 1
        return $inputReportEvery;
70
    }
71
72 1
    public function getArgumentDate(string $value): VersionDate
73
    {
74 1
        return VersionDate::createFromString($value);
75
    }
76
77
    /**
78
     * @return VersionDate|null
79
     */
80
    public function getLatestVersionDate()
81
    {
82
        $latest = $this->gateways()->catalog()->latest();
83
        if ($latest instanceof Catalog) {
84
            return $latest->date();
85
        }
86
        return null;
87
    }
88
89 1
    protected function execute(InputInterface $input, OutputInterface $output)
90
    {
91
        // input arguments
92 1
        $reportEvery = $this->getOptionReportEvery((string) $input->getOption('report-every'));
93 1
        $date = $this->getArgumentDate((string) $input->getArgument('date'));
94
95
        // create logger
96 1
        $logger = new OutputLogger($output);
97
98
        // report working info
99 1
        $logger->notice('Update date: ' . $date->format());
100 1
        $logger->debug(sprintf('Report progress every %d lines', $reportEvery));
101
102
        // show debug messages of database config
103 1
        $config = $this->config();
104 1
        $logger->debug(sprintf('DB: [%s], Username: [%s]', $config->dbDsn(), $config->dbUsername()));
105
106
        // verify previous version
107 1
        $latestDate = $this->getLatestVersionDate();
108 1
        if (null !== $latestDate) {
109 1
            $logger->debug(sprintf('Latest catalog is %s', $latestDate->format()));
110 1
            if ($date->compare($latestDate) <= 0) {
111
                throw new \RuntimeException(sprintf(
112
                    'The update date %s is less or equal to the latest catalog %s',
113
                    $date->format(),
114 1
                    $latestDate->format()
115
                ));
116
            }
117
        } else {
118
            $logger->debug('Cannot found any previus catalog');
119
        }
120
121
        // check upper boud
122 1
        $today = VersionDate::createFromString('today');
123 1
        if ($date->compare($today) > 0) {
124
            throw new \RuntimeException(sprintf(
125
                'The update date %s is greater than today %s',
126
                $date->format(),
127
                $today->format()
128
            ));
129
        }
130
131 1
        $updater = $this->createUpdater($date);
132 1
        if (! $output->isQuiet()) {
133 1
            $updater->setLogger($logger);
134
135 1
            $progress = new ProgressByHit(null, [], $reportEvery);
136 1
            $progress->attach($logger);
137 1
            $updater->setProgress($progress);
138
        }
139
140
        // separate into a different method to allow mock & test
141 1
        $blobFiles = $input->getArgument('blobs');
142 1
        if (is_array($blobFiles) && count($blobFiles)) {
143
            $blobs = [];
144
            foreach ($blobFiles as $index => $blobSourceFile) {
145
                $blobFile = (string) realpath($blobSourceFile);
146
                if ('' === $blobFile) {
147
                    throw new \RuntimeException('Cannot find file ' . $blobSourceFile);
148
                }
149
                $blobs[] = new Blob($blobFile, 'file://' . $blobFile, '');
150
            }
151
            $this->runUpdaterWithBlobs($updater, ...$blobs);
152
        } else {
153 1
            $this->runUpdater($updater);
154
        }
155
156 1
        return 0;
157
    }
158
159
    public function runUpdater(Updater $updater)
160
    {
161
        $updater->run();
162
    }
163
164
    public function runUpdaterWithBlobs(Updater $updater, Blob ...$blobs)
165
    {
166
        $updater->runBlobs(...$blobs);
167
    }
168
169 1
    public function createUpdater(VersionDate $date): Updater
170
    {
171 1
        return new Updater($date, $this->gateways());
172
    }
173
}
174