Downloader   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 20
eloc 65
c 2
b 0
f 0
dl 0
loc 176
ccs 69
cts 69
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A download() 0 11 3
A contentsDownload() 0 14 3
A displayProgress() 0 4 1
A setAdapter() 0 7 2
A __construct() 0 4 1
A getProgress() 0 3 1
A downloadProgress() 0 7 3
B curlDownload() 0 35 6
1
<?php
2
3
namespace PierInfor\GeoLite;
4
5
/**
6
 * Downloader class let download files
7
 */
8
class Downloader implements Interfaces\DownloaderInterface
9
{
10
11
    /**
12
     * factory adapter
13
     *
14
     * @var String
15
     */
16
    private $adapter;
17
18
    /**
19
     * Download progress percent
20
     *
21
     * @var Integer
22
     */
23
    private $progress;
24
25
    /**
26
     * Download progress percent
27
     *
28
     * @var Boolean
29
     */
30
    private $showProgress;
31
32
    /**
33
     * Instanciate
34
     */
35 18
    public function __construct()
36
    {
37 18
        $this->showProgress = false;
38 18
        $this->setAdapter();
39
    }
40
41
    /**
42
     * set adapter for download factory
43
     *
44
     * @param string $adapter
45
     * @return Downloader
46
     */
47 18
    public function setAdapter(string $adapter = self::ADAPTER_CURL): Downloader
48
    {
49 18
        if (!in_array($adapter, self::ADAPTERS)) {
50 1
            throw new \Exception('Downloader - bad adapter');
51
        }
52 18
        $this->adapter = $adapter;
53 18
        return $this;
54
    }
55
56
    /**
57
     * download factory
58
     *
59
     * @param string $url
60
     * @param string $toFilename
61
     * @return Downloader
62
     */
63 1
    public function download(string $url, string $toFilename): Downloader
64
    {
65 1
        switch ($this->adapter) {
66 1
            case self::ADAPTER_CONTENTS:
67 1
                $this->contentsDownload($url, $toFilename);
68 1
                break;
69 1
            case self::ADAPTER_CURL:
70 1
                $this->curlDownload($url, $toFilename);
71 1
                break;
72
        }
73 1
        return $this;
74
    }
75
76
    /**
77
     * download a file using file_get_content
78
     *
79
     * @param string $url
80
     * @param string $toFilename
81
     * @return Downloader
82
     */
83 3
    public function contentsDownload(string $url, string $toFilename): Downloader
84
    {
85 3
        $headers = get_headers($url);
86 3
        $statusCode = 0;
87 3
        if (isset($headers[0])) {
88 3
            $header = $headers[0];
89 3
            preg_match("/^HTTP.+\s(\d\d\d)\s/", $header, $m);
90 3
            $statusCode = $m[1];
91
        }
92 3
        if ($statusCode != 200) {
93 1
            throw new \Exception('Bad http code : ' . $statusCode);
94
        }
95 2
        file_put_contents($toFilename, file_get_contents($url));
96 2
        return $this;
97
    }
98
99
    /**
100
     * enable progress output when using curlDownload
101
     *
102
     * @param boolean $show
103
     * @return Downloader
104
     */
105 4
    public function displayProgress(bool $show = false): Downloader
106
    {
107 4
        $this->showProgress = $show;
108 4
        return $this;
109
    }
110
111
    /**
112
     * download a file using curl
113
     *
114
     * @param string $url
115
     * @param string $toFilename
116
     * @return Downloader
117
     */
118 3
    public function curlDownload(string $url, string $toFilename): Downloader
119
    {
120 3
        touch($toFilename, 0777);
121 3
        $handle = fopen($toFilename, 'wba+');
122 3
        $handleOk = false !== $handle;
123 3
        $cha = curl_init();
124 3
        if (false !== $cha && $handleOk) {
125 3
            curl_setopt($cha, CURLOPT_VERBOSE, false);
126 3
            curl_setopt($cha, CURLOPT_URL, $url);
127 3
            curl_setopt($cha, CURLOPT_POST, 0);
128 3
            curl_setopt($cha, CURLOPT_TIMEOUT, 300);
129 3
            curl_setopt($cha, CURLOPT_HEADER, false);
130 3
            curl_setopt($cha, CURLOPT_USERAGENT, self::USER_AGENT);
131 3
            curl_setopt($cha, CURLOPT_BUFFERSIZE, self::BUFFER_SIZE);
132 3
            curl_setopt($cha, CURLOPT_RETURNTRANSFER, 1);
133 3
            curl_setopt($cha, CURLOPT_FILE, $handle);
134 3
            curl_setopt($cha, CURLOPT_FOLLOWLOCATION, true);
135 3
            curl_setopt($cha, CURLOPT_BINARYTRANSFER, true);
136 3
            curl_setopt($cha, CURLOPT_FOLLOWLOCATION, true);
137 3
            curl_setopt($cha, CURLOPT_NOPROGRESS, false);
138 3
            curl_setopt($cha, CURLOPT_PROGRESSFUNCTION, [$this, self::DOWNLOAD_CALLBACK]);
139 3
            curl_setopt($cha, CURLOPT_AUTOREFERER, true);
140 3
            curl_exec($cha);
141 3
            if (!curl_errno($cha)) {
142 3
                $statusCode = curl_getinfo($cha, CURLINFO_HTTP_CODE);
143 3
                if ($statusCode != 200) {
144 1
                    throw new \Exception('Bad http code : ' . $statusCode);
145
                }
146
            }
147 2
            curl_close($cha);
148
        }
149 2
        if (is_resource($handle)) {
150 2
            fclose($handle);
151
        }
152 2
        return $this;
153
    }
154
155
    /**
156
     * download progress callback
157
     *
158
     * @param mixed $resource
159
     * @param integer $download_size
160
     * @param integer $downloaded
161
     * @param integer $upload_size
162
     * @param integer $uploaded
163
     * @return void
164
     */
165 2
    protected function downloadProgress($resource, int $download_size, int $downloaded, int $upload_size, int $uploaded)
166
    {
167 2
        if ($download_size > 0) {
168 2
            $this->progress = ($downloaded / $download_size) * 100;
169 2
            if ($this->showProgress === true) {
170 1
                echo self::WHEELS[$this->progress % 4]
171 1
                    . ' ' . $this->getProgress() . "%\r";
172
            }
173
        }
174
    }
175
176
    /**
177
     * returns progress value
178
     *
179
     * @return integer
180
     */
181 2
    protected function getProgress(): int
182
    {
183 2
        return $this->progress;
184
    }
185
}
186