Completed
Pull Request — master (#402)
by Alejandro
05:51
created

GeolocationDbUpdater   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 52
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 8
eloc 20
dl 0
loc 52
rs 10
c 0
b 0
f 0
ccs 19
cts 19
cp 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
A buildIsTooOld() 0 5 1
A checkDbUpdate() 0 10 3
A downloadNewDb() 0 13 3
A __construct() 0 4 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\CLI\Util;
5
6
use Cake\Chronos\Chronos;
7
use GeoIp2\Database\Reader;
8
use InvalidArgumentException;
9
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
10
use Shlinkio\Shlink\Common\Exception\RuntimeException;
11
use Shlinkio\Shlink\Common\IpGeolocation\GeoLite2\DbUpdaterInterface;
12
13
class GeolocationDbUpdater implements GeolocationDbUpdaterInterface
14
{
15
    /** @var DbUpdaterInterface */
16
    private $dbUpdater;
17
    /** @var Reader */
18
    private $geoLiteDbReader;
19
20 40
    public function __construct(DbUpdaterInterface $dbUpdater, Reader $geoLiteDbReader)
21
    {
22 40
        $this->dbUpdater = $dbUpdater;
23 40
        $this->geoLiteDbReader = $geoLiteDbReader;
24
    }
25
26
    /**
27
     * @throws GeolocationDbUpdateFailedException
28
     */
29 40
    public function checkDbUpdate(callable $mustBeUpdated = null, callable $handleProgress = null): void
30
    {
31
        try {
32 40
            $meta = $this->geoLiteDbReader->metadata();
33 39
            if ($this->buildIsTooOld($meta->__get('buildEpoch'))) {
34 39
                $this->downloadNewDb(true, $mustBeUpdated, $handleProgress);
35
            }
36 5
        } catch (InvalidArgumentException $e) {
37
            // This is the exception thrown by the reader when the database file does not exist
38 1
            $this->downloadNewDb(false, $mustBeUpdated, $handleProgress);
39
        }
40
    }
41
42 39
    private function buildIsTooOld(int $buildTimestamp): bool
43
    {
44 39
        $buildDate = Chronos::createFromTimestamp($buildTimestamp);
45 39
        $now = Chronos::now();
46 39
        return $now->gt($buildDate->addDays(35));
47
    }
48
49
    /**
50
     * @throws GeolocationDbUpdateFailedException
51
     */
52 5
    private function downloadNewDb(
53
        bool $olderDbExists,
54
        callable $mustBeUpdated = null,
55
        callable $handleProgress = null
56
    ): void {
57 5
        if ($mustBeUpdated !== null) {
58 1
            $mustBeUpdated($olderDbExists);
59
        }
60
61
        try {
62 5
            $this->dbUpdater->downloadFreshCopy($handleProgress);
63 5
        } catch (RuntimeException $e) {
64 5
            throw GeolocationDbUpdateFailedException::create($olderDbExists, $e);
65
        }
66
    }
67
}
68