Passed
Push — develop ( b2fd72...a6815b )
by Портнов
08:05 queued 03:28
created

WorkerDownloader::progressGuzzle()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
dl 0
loc 15
rs 9.9
c 1
b 0
f 0
cc 4
nc 5
nop 4
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\PBXCoreREST\Workers;
21
22
require_once 'Globals.php';
23
24
use MikoPBX\Core\Workers\WorkerBase;
25
use MikoPBX\Core\System\Util;
26
use GuzzleHttp;
27
use GuzzleHttp\Exception\GuzzleException;
28
29
30
class WorkerDownloader extends WorkerBase
31
{
32
    private string $old_memory_limit;
33
    private int $progress = 0;
34
    private array $settings;
35
    private string $progress_file = '';
36
    private string $error_file = '';
37
    private int $file_size = 0;
38
39
    /**
40
     * WorkerDownloader entry point.
41
     *
42
     * @param $params
43
     */
44
    public function start($params): void
45
    {
46
        $this->old_memory_limit = ini_get('memory_limit');
47
        $filename = $params[2]??'';
48
        if (file_exists($filename)) {
49
            $this->settings = json_decode(file_get_contents($filename), true);
50
        } else {
51
            Util::sysLogMsg(__CLASS__, 'Wrong download settings', LOG_ERR);
52
            return;
53
        }
54
        ini_set('memory_limit', '300M');
55
56
        $temp_dir            = dirname($this->settings['res_file']);
57
        $this->progress_file = $temp_dir . '/progress';
58
        $this->error_file    = $temp_dir . '/error';
59
60
        $result = $this->getFile();
61
        $result = $result && $this->checkFile();
62
        if ( ! $result) {
63
            Util::sysLogMsg(__CLASS__, 'Download error...', LOG_ERR);
64
        }
65
    }
66
67
    /**
68
     * Downloads file from remote resource by link
69
     */
70
    public function getFile(): bool
71
    {
72
        if (empty($this->settings)) {
73
            return false;
74
        }
75
        if (file_exists($this->settings['res_file'])) {
76
            unlink($this->settings['res_file']);
77
        }
78
        if (isset($this->settings['size'])){
79
            $this->file_size = $this->settings['size'];
80
        } else {
81
            $this->file_size = $this->remoteFileSize($this->settings['url']);
82
        }
83
84
        file_put_contents($this->progress_file, 0);
85
        $client = new GuzzleHttp\Client();
86
        try {
87
            $res = $client->request('GET', $this->settings['url'], [
88
                'sink'     => $this->settings['res_file'],
89
                'progress' => [$this, 'progressGuzzle']
90
            ]);
91
            $http_code = $res->getStatusCode();
92
        }catch ( GuzzleException  $e){
93
            file_put_contents($this->error_file, $e->getMessage(), FILE_APPEND);
94
            $http_code = -1;
95
        }
96
97
        if ($http_code !== 200) {
98
            file_put_contents($this->error_file, "Curl return code $http_code. ", FILE_APPEND);
99
        }
100
101
        return $http_code === 200;
102
    }
103
104
    public function progressGuzzle( $downloadTotal, $downloadedBytes, $uploadTotal, $uploadedBytes) :void
0 ignored issues
show
Unused Code introduced by
The parameter $uploadedBytes is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

104
    public function progressGuzzle( $downloadTotal, $downloadedBytes, $uploadTotal, /** @scrutinizer ignore-unused */ $uploadedBytes) :void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $uploadTotal is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

104
    public function progressGuzzle( $downloadTotal, $downloadedBytes, /** @scrutinizer ignore-unused */ $uploadTotal, $uploadedBytes) :void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
105
    {
106
        if ($downloadedBytes === 0) {
107
            return;
108
        }
109
        if ($this->file_size < 0) {
110
            $new_progress = $downloadedBytes / $downloadTotal * 100;
111
        } else {
112
            $new_progress = $downloadedBytes / $this->file_size * 100;
113
        }
114
        $delta = $new_progress - $this->progress;
115
        if ($delta > 1) {
116
            $this->progress = round($new_progress);
117
            $this->progress = min($this->progress, 99);
118
            file_put_contents($this->progress_file, $this->progress);
119
        }
120
    }
121
122
    /**
123
     * Remote File Size Using cURL
124
     *
125
     * @param string $url
126
     *
127
     * @return int
128
     */
129
    private function remoteFileSize(string $url): int
130
    {
131
        $fileSize = -1;
132
        try{
133
            $client    = new GuzzleHttp\Client();
134
            $response  = $client->head($url);
135
            $fileSize  = $response->getHeader('Content-Length')[0];
136
        }catch ( GuzzleException  $e){
137
            file_put_contents($this->error_file, $e->getMessage(), FILE_APPEND);
138
        }
139
        return $fileSize;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $fileSize could return the type string which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
140
    }
141
142
    /**
143
     * Checks file md5 sum and size
144
     */
145
    public function checkFile(): bool
146
    {
147
        $result = true;
148
        if ( ! file_exists($this->settings['res_file'])) {
149
            file_put_contents($this->error_file, 'File did not upload', FILE_APPEND);
150
            return false;
151
        }
152
        if (md5_file($this->settings['res_file']) !== $this->settings['md5']) {
153
            unlink($this->settings['res_file']);
154
            file_put_contents($this->error_file, 'Error on comparing MD5 sum', FILE_APPEND);
155
156
            $result = false;
157
        }elseif($this->file_size !== filesize($this->settings['res_file'])) {
158
            unlink($this->settings['res_file']);
159
            file_put_contents($this->error_file, 'Error on comparing file size', FILE_APPEND);
160
            $result = false;
161
        }
162
        file_put_contents($this->progress_file, 100);
163
        return $result;
164
    }
165
166
    /**
167
     * Returns memory_limit to default value.
168
     */
169
    public function __destruct()
170
    {
171
        parent::__destruct();
172
        ini_set('memory_limit', $this->old_memory_limit);
173
    }
174
175
}
176
177
// Start worker process
178
WorkerDownloader::startWorker($argv??null, false);
179