Completed
Push — master ( 01982b...3c7394 )
by ANTHONIUS
11s
created

Downloader::handleNotification()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 4.909
c 0
b 0
f 0
cc 9
eloc 20
nc 9
nop 6
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the dotfiles project.
7
 *
8
 *     (c) Anthonius Munthi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Dotfiles\Core\Util;
15
16
use Dotfiles\Core\Config\Config;
17
use Psr\Log\LoggerInterface;
18
use Symfony\Component\Console\Helper\ProgressBar;
19
use Symfony\Component\Console\Output\OutputInterface;
20
21
class Downloader
22
{
23
    /**
24
     * @var int
25
     */
26
    private $bytesMax;
27
28
    /**
29
     * @var Config
30
     */
31
    private $config;
32
33
    /**
34
     * @var string
35
     */
36
    private $contents;
37
38
    /**
39
     * @var bool
40
     */
41
    private $hasError = false;
42
43
    /**
44
     * @var LoggerInterface
45
     */
46
    private $logger;
47
48
    /**
49
     * @var OutputInterface
50
     */
51
    private $output;
52
53
    /**
54
     * @var ProgressBar
55
     */
56
    private $progressBar;
57
58
    public function __construct(OutputInterface $output, LoggerInterface $logger, Config $config)
59
    {
60
        $this->output = $output;
61
        $this->logger = $logger;
62
        $this->progressBar = new ProgressBar($output);
63
        $this->config = $config;
64
    }
65
66
    /**
67
     * @return ProgressBar
68
     */
69
    public function getProgressBar(): ProgressBar
70
    {
71
        return $this->progressBar;
72
    }
73
74
    public function handleError($bar, $message): void
75
    {
76
        $this->hasError = true;
77
        $this->output->writeln("<comment>Error:</comment>\n<info>${message}</info>\n");
78
    }
79
80
    public function handleNotification($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax): void
81
    {
82
        switch ($notificationCode) {
83
            case STREAM_NOTIFY_RESOLVE:
84
            case STREAM_NOTIFY_AUTH_REQUIRED:
85
            case STREAM_NOTIFY_FAILURE:
86
            case STREAM_NOTIFY_AUTH_RESULT:
87
                // handle error here
88
                break;
89
            case STREAM_NOTIFY_REDIRECTED:
90
                $this->progressBar->clear();
91
92
                break;
93
            case STREAM_NOTIFY_FILE_SIZE_IS:
94
                $this->progressBar->start($bytesMax);
95
                $this->bytesMax = $bytesMax;
96
97
                break;
98
            case STREAM_NOTIFY_PROGRESS:
99
                $this->progressBar->setProgress($bytesTransferred);
100
101
                break;
102
            case STREAM_NOTIFY_COMPLETED:
103
                $this->progressBar->setProgress($bytesMax);
104
                $this->progressBar->clear();
105
106
                break;
107
        }
108
    }
109
110
    public function run($url, $targetFile): void
111
    {
112
        $dryRun = $this->config->get('dotfiles.dry_run');
113
        $fullName = basename($targetFile);
114
        $this->progressBar->setFormat("Download <comment>$fullName</comment>: <comment>%percent:3s%%</comment> <info>%estimated:-6s%</info>");
115
116
        Toolkit::ensureFileDir($targetFile);
117
        $this->hasError = false;
118
        $this->logger->debug(sprintf('Downloading <info>%s</info> to <info>%s</info>', $url, $targetFile));
119
        if (!$dryRun) {
120
            $context = stream_context_create(array(), array('notification' => array($this, 'handleNotification')));
121
            set_error_handler(array($this, 'handleError'));
122
            $this->contents = file_get_contents($url, false, $context);
123
            restore_error_handler();
124
            if ($this->hasError) {
125
                throw new \RuntimeException('Failed to download '.$url);
126
            }
127
            $this->output->writeln('');
128
            file_put_contents($targetFile, $this->contents, LOCK_EX);
129
        }
130
        $this->logger->debug('Download <comment>finished</comment>');
131
    }
132
}
133