Completed
Push — master ( 5710d1...ace12f )
by Peter
24s queued 12s
created

MaxMindDownloader::download()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 72
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 6

Importance

Changes 8
Bugs 2 Features 1
Metric Value
cc 6
eloc 43
c 8
b 2
f 1
nc 12
nop 2
dl 0
loc 72
ccs 35
cts 35
cp 1
crap 6
rs 8.6097

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * GpsLab component.
6
 *
7
 * @author    Peter Gribanov <[email protected]>
8
 * @copyright Copyright (c) 2017, Peter Gribanov
9
 * @license   http://opensource.org/licenses/MIT
10
 */
11
12
namespace GpsLab\Bundle\GeoIP2Bundle\Downloader;
13
14
use Psr\Log\LoggerInterface;
15
use splitbrain\PHPArchive\Tar;
0 ignored issues
show
Bug introduced by
The type splitbrain\PHPArchive\Tar was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Symfony\Component\Filesystem\Filesystem;
17
18
/**
19
 * MaxMind downloader.
20
 *
21
 * Expect GeoIP2 archive from https://download.maxmind.com/ with structure:
22
 *
23
 * GeoLite2-City.tar.gz
24
 *  - GeoLite2-City_20200114
25
 *    - COPYRIGHT.txt
26
 *    - GeoLite2-City.mmdb
27
 *    - LICENSE.txt
28
 *    - README.txt
29
 */
30
class MaxMindDownloader implements Downloader
31
{
32
    /**
33
     * @var Filesystem
34
     */
35
    private $fs;
36
37
    /**
38
     * @var LoggerInterface
39
     */
40
    private $logger;
41
42
    /**
43
     * @param Filesystem      $fs
44
     * @param LoggerInterface $logger
45 2
     */
46
    public function __construct(Filesystem $fs, LoggerInterface $logger)
47 2
    {
48 2
        $this->fs = $fs;
49 2
        $this->logger = $logger;
50
    }
51
52
    /**
53
     * @param string $url
54
     * @param string $target
55 2
     */
56
    public function download(string $url, string $target): void
57 2
    {
58 2
        $id = uniqid('', true);
59 2
        $tmp_zip = sprintf('%s/%s_GeoLite2.tar.gz', sys_get_temp_dir(), $id);
60 2
        $tmp_unzip = sprintf('%s/%s_GeoLite2.tar', sys_get_temp_dir(), $id);
61
        $tmp_untar = sprintf('%s/%s_GeoLite2', sys_get_temp_dir(), $id);
62
63 2
        // remove old files and folders for correct overwrite it
64
        $this->fs->remove([$tmp_zip, $tmp_unzip, $tmp_untar]);
65 2
66
        $this->logger->debug(sprintf('Beginning download of file %s', $url));
67 2
68
        $this->fs->copy($url, $tmp_zip, true);
69 2
70 2
        $this->logger->debug(sprintf('Download complete to %s', $tmp_zip));
71
72 2
        $this->fs->mkdir(dirname($target), 0755);
73
74
        if (class_exists(Tar::class)) {
75 2
            $this->logger->debug(sprintf('Extracting archive file to %s', $tmp_untar));
76 2
77
            // extract tar.gz archive
78 2
            $tar = new Tar();
79 2
            $tar->open($tmp_zip);
80
            $tar->extract($tmp_untar);
81
            $tar->close();
82 2
            unset($tar);
83
        } else {
84 2
            $this->logger->debug(sprintf('De-compressing file to %s', $tmp_unzip));
85
86
            // decompress gz file
87 2
            $zip = new \PharData($tmp_zip);
88 2
            $tar = $zip->decompress();
89 2
90
            $this->logger->debug('Decompression complete');
91 1
            $this->logger->debug(sprintf('Extract tar file to %s', $tmp_untar));
92 1
93 1
            // extract tar archive
94 1
            $tar->extractTo($tmp_untar);
95 1
            unset($zip, $tar);
96 1
        }
97 1
98 1
        $this->logger->debug('Tar archive extracted');
99
100
        // find database in archive
101
        $database = '';
102 1
        $files = glob(sprintf('%s/**/*.mmdb', $tmp_untar)) ?: [];
103
        foreach ($files as $file) {
104
            // expected something like that "GeoLite2-City_20200114"
105 2
            if (preg_match('/(?<database>[^\/]+)_(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})/', $file, $match)) {
106 1
                $this->logger->debug(sprintf(
107
                    'Found %s database updated at %s-%s-%s in %s',
108
                    $match['database'],
109 1
                    $match['year'],
110 1
                    $match['month'],
111 1
                    $match['day'],
112
                    $file
113 1
                ));
114 1
            }
115
116
            $database = $file;
117
        }
118
119
        if (!$database) {
120
            throw new \RuntimeException('Not found GeoLite2 database in archive.');
121
        }
122
123
        $this->fs->copy($database, $target, true);
124
        $this->fs->chmod($target, 0755);
125
        $this->fs->remove([$tmp_zip, $tmp_unzip, $tmp_untar]);
126
127
        $this->logger->debug(sprintf('Database moved to %s', $target));
128
    }
129
}
130