1 <?php
2
3 namespace Alo\CLI;
4
5 use Alo\Curl;
6 use Alo\FileSystem\File;
7
8 if (!defined('GEN_START')) {
9 http_response_code(404);
10 } else {
11
12 /**
13 * Downloads an external resource to disk, echoing the progress
14 *
15 * @author Art <a.molcanovas@gmail.com>
16 */
17 class Downloader {
18
19 /**
20 * Static reference to the last instance of the class
21 *
22 * @var Downloader
23 */
24 static $this;
25 /**
26 * Curl handler
27 *
28 * @var Curl
29 */
30 protected $curl;
31 /**
32 * Download destination
33 *
34 * @var string
35 */
36 protected $dest;
37 /**
38 * Timestamp when we last reported the status
39 *
40 * @var int
41 */
42 protected $lastReportTime;
43 /**
44 * The last reported status
45 *
46 * @var string
47 */
48 protected $lastReportStatus;
49 /**
50 * Output
51 *
52 * @var resource
53 */
54 protected $fp;
55 /**
56 * Number of times the status has been reported
57 *
58 * @var int
59 */
60 protected $reportCount;
61
62 /**
63 * Instantiates the class
64 *
65 * @author Art <a.molcanovas@gmail.com>
66 *
67 * @param string $source Download source
68 * @param string $destination Download destination
69 */
70 function __construct($source, $destination) {
71 $this->dest = $destination;
72 $this->reportCount = 0;
73
74 $this->curl = new Curl($source);
75 $this->curl->setProgressFunction([$this, 'progressFunction']);
76
77 self::$this = &$this;
78 }
79
80 /**
81 * The progress function
82 *
83 * @author Art <a.molcanovas@gmail.com>
84 *
85 * @param resource $resource Coulsn't find documentation on this one, most likely the curl resource
86 * @param int $downloadSize How much we are downloading
87 * @param int $downloaded How much we have downloaded
88 * @param int $uploadSize How much we are uploading
89 * @param int $uploaded How much we have uploaded
90 */
91 function progressFunction($resource, $downloadSize, $downloaded, $uploadSize, $uploaded) {
92 $ed = $size = 0;
93
94 if ($downloadSize > 0 && $downloaded > 0) {
95 $ed = $downloaded;
96 $size = $downloadSize;
97 } elseif ($uploadSize > 0 && $uploaded > 0) {
98 $ed = $uploaded;
99 $size = $uploadSize;
100 }
101
102 if ($ed && $size && $this->reportCount++ != 0) {
103 $status = File::convertSize($ed) . '/' . File::convertSize($size) . ' downloaded [' .
104 round(($ed / $size) * 100, 3) . ' %]';
105
106 $time = time();
107 if ($status != $this->lastReportStatus && ($time != $this->lastReportTime || $ed == $size)) {
108 $this->lastReportTime = $time;
109 $this->lastReportStatus = $status;
110 echo $status . PHP_EOL;
111 }
112
113 $this->reportCount++;
114 }
115
116 //Unnecessary, but stops the IDE from thinking the variable is unused
117 unset($resource);
118 }
119
120 /**
121 * Starts the download
122 *
123 * @author Art <a.molcanovas@gmail.com>
124 * @return bool Whther the download was successful (on the Curl side)
125 */
126 function download() {
127 if (file_exists($this->dest)) {
128 unlink($this->dest);
129 }
130
131 $this->fp = fopen($this->dest, 'w');
132 $this->curl->setopt(CURLOPT_FILE, $this->fp);
133 $this->curl->exec();
134 fclose($this->fp);
135
136 $errno = $this->curl->errno();
137
138 if ($errno === CURLE_OK) {
139 return true;
140 } else {
141 echo $this->curl->error() . PHP_EOL;
142
143 return false;
144 }
145 }
146 }
147 }
148