Completed
Push — master ( 456765...439573 )
by Alejandro
14s queued 13s
created

DbUpdater::deleteTempFiles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.1481

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
ccs 2
cts 3
cp 0.6667
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2.1481
1
<?php
2
declare(strict_types=1);
3
4
namespace Shlinkio\Shlink\IpGeolocation\GeoLite2;
5
6
use Fig\Http\Message\RequestMethodInterface as RequestMethod;
7
use GuzzleHttp\ClientInterface;
8
use GuzzleHttp\Exception\GuzzleException;
9
use GuzzleHttp\RequestOptions;
10
use PharData;
11
use Shlinkio\Shlink\IpGeolocation\Exception\RuntimeException;
12
use Symfony\Component\Filesystem\Exception as FilesystemException;
13
use Symfony\Component\Filesystem\Filesystem;
14
use Throwable;
15
16
use function sprintf;
17
18
class DbUpdater implements DbUpdaterInterface
19
{
20
    private const DB_COMPRESSED_FILE = 'GeoLite2-City.tar.gz';
21
    private const DB_DECOMPRESSED_FILE = 'GeoLite2-City.mmdb';
22
23
    /** @var ClientInterface */
24
    private $httpClient;
25
    /** @var Filesystem */
26
    private $filesystem;
27
    /** @var GeoLite2Options */
28
    private $options;
29
30 7
    public function __construct(ClientInterface $httpClient, Filesystem $filesystem, GeoLite2Options $options)
31
    {
32 7
        $this->httpClient = $httpClient;
33 7
        $this->filesystem = $filesystem;
34 7
        $this->options = $options;
35
    }
36
37
    /**
38
     * @throws RuntimeException
39
     */
40 5
    public function downloadFreshCopy(?callable $handleProgress = null): void
41
    {
42 5
        $tempDir = $this->options->getTempDir();
43 5
        $compressedFile = sprintf('%s/%s', $tempDir, self::DB_COMPRESSED_FILE);
44
45 5
        $this->downloadDbFile($compressedFile, $handleProgress);
46 4
        $tempFullPath = $this->extractDbFile($compressedFile, $tempDir);
47 3
        $this->copyNewDbFile($tempFullPath);
48 1
        $this->deleteTempFiles([$compressedFile, $tempFullPath]);
49
    }
50
51 5
    private function downloadDbFile(string $dest, ?callable $handleProgress = null): void
52
    {
53
        try {
54 5
            $this->httpClient->request(RequestMethod::METHOD_GET, $this->options->getDownloadFrom(), [
55 5
                RequestOptions::SINK => $dest,
56 5
                RequestOptions::PROGRESS => $handleProgress,
57
            ]);
58 1
        } catch (Throwable | GuzzleException $e) {
59 1
            throw new RuntimeException(
60 1
                'An error occurred while trying to download a fresh copy of the GeoLite2 database',
61 1
                0,
62 1
                $e
63
            );
64
        }
65
    }
66
67 4
    private function extractDbFile(string $compressedFile, string $tempDir): string
68
    {
69
        try {
70 4
            $phar = new PharData($compressedFile);
71 3
            $internalPathToDb = sprintf('%s/%s', $phar->getBasename(), self::DB_DECOMPRESSED_FILE);
72 3
            $phar->extractTo($tempDir, $internalPathToDb, true);
73
74 3
            return sprintf('%s/%s', $tempDir, $internalPathToDb);
75 1
        } catch (Throwable $e) {
76 1
            throw new RuntimeException(
77 1
                sprintf('An error occurred while trying to extract the GeoLite2 database from %s', $compressedFile),
78 1
                0,
79 1
                $e
80
            );
81
        }
82
    }
83
84 3
    private function copyNewDbFile(string $from): void
85
    {
86
        try {
87 3
            $this->filesystem->copy($from, $this->options->getDbLocation(), true);
88 2
        } catch (FilesystemException\FileNotFoundException | FilesystemException\IOException $e) {
89 2
            throw new RuntimeException('An error occurred while trying to copy GeoLite2 db file to destination', 0, $e);
90
        }
91
    }
92
93 1
    private function deleteTempFiles(array $files): void
94
    {
95
        try {
96 1
            $this->filesystem->remove($files);
97
        } catch (FilesystemException\IOException $e) {
98
            // Ignore any error produced when trying to delete temp files
99
        }
100
    }
101
102 2
    public function databaseFileExists(): bool
103
    {
104 2
        return $this->filesystem->exists($this->options->getDbLocation());
105
    }
106
}
107