Completed
Pull Request — master (#54)
by Hiraku
02:14
created

ParallelDownloader::download()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 29
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 3

Importance

Changes 30
Bugs 9 Features 1
Metric Value
c 30
b 9
f 1
dl 0
loc 29
ccs 22
cts 22
cp 1
rs 8.8571
cc 3
eloc 20
nc 2
nop 2
crap 3
1
<?php
2
/*
3
 * hirak/prestissimo
4
 * @author Hiraku NAKANO
5
 * @license MIT https://github.com/hirak/prestissimo
6
 */
7
namespace Hirak\Prestissimo;
8
9
use Composer\Package;
10
use Composer\IO;
11
use Composer\Config as CConfig;
12
13
/**
14
 *
15
 */
16
class ParallelDownloader
17
{
18
    /** @var IO/IOInterface */
19
    protected $io;
20
21
    /** @var CConfig */
22
    protected $config;
23
24
    /** @var int */
25
    protected $totalCnt = 0;
26
    protected $successCnt = 0;
27
    protected $skippedCnt = 0;
28
    protected $failureCnt = 0;
29
30 4
    public function __construct(IO\IOInterface $io, CConfig $config)
31
    {
32 4
        $this->io = $io;
33 4
        $this->config = $config;
34 4
    }
35
36
    /**
37
     * @param Package\PackageInterface[] $packages
38
     * @param array $pluginConfig
39
     * @return void
40
     */
41 3
    public function download(array $packages, array $pluginConfig)
42
    {
43 3
        $multi = new CurlMulti($pluginConfig['maxConnections']);
44 3
        $multi->setupShareHandler($pluginConfig['pipeline']);
45
46 3
        $this->totalCnt = count($packages);
47 3
        $this->successCnt = $this->skippedCnt = $this->failureCnt = 0;
48 3
        $this->io->write("    Prefetch start: <comment>total: $this->totalCnt</comment>");
49
50 3
        $multi->setTargets($this->filterPackages($packages, $pluginConfig));
51
52
        do {
53 3
            $multi->setupEventLoop();
54 3
            $multi->wait();
55
56 3
            $result = $multi->getFinishedResults();
57 3
            $this->successCnt += $result['successCnt'];
58 3
            $this->failureCnt += $result['failureCnt'];
59 3
            foreach ($result['results'] as $url) {
60 1
                $this->io->write($this->makeDownloadingText($url));
61 3
            }
62 3
        } while ($multi->remain());
63
64 3
        $this->io->write(
65 3
            "    Finished: <comment>success:$this->successCnt,"
66 3
            . " skipped:$this->skippedCnt, failure:$this->failureCnt,"
67 3
            . " total: $this->totalCnt</comment>"
68 3
        );
69 3
    }
70
71
    /**
72
     * @param Package\PackageInterface[] $packages
73
     * @param string[] $pluginConfig
74
     * @return array [{src: Aspects\HttpGetRequest, dest: OutputFile}]
75
     */
76 3
    private function filterPackages(array $packages, array $pluginConfig)
77
    {
78 3
        $cachedir = rtrim($this->config->get('cache-files-dir'), '\/');
79 3
        $targets = array();
80 3
        foreach ($packages as $p) {
81 3
            $url = $p->getDistUrl();
82 3
            if (!$url) {
83 1
                ++$this->skippedCnt;
84 1
                continue;
85
            }
86 2
            if ($p->getDistMirrors()) {
87
                $url = current($p->getDistUrls());
88
            }
89 2
            $host = parse_url($url, PHP_URL_HOST) ?: '';
90 2
            $src = Factory::getHttpGetRequest($host, $url, $this->io, $this->config, $pluginConfig);
91 2
            if (in_array($p->getName(), $pluginConfig['privatePackages'])) {
92
                $src->maybePublic = false;
93
            } else {
94 2
                $src->maybePublic = (bool)preg_match('%^(?:https|git)://github\.com%', $p->getSourceUrl());
95
            }
96
            // make file resource
97
            $filepath = $cachedir
98
                . DIRECTORY_SEPARATOR
99 2
                . FileDownloaderDummy::getCacheKeyCompat($p, $src->getURL());
100 2
            if (file_exists($filepath)) {
101
                ++$this->skippedCnt;
102
                continue;
103
            }
104 2
            $dest = new OutputFile($filepath);
105
106 2
            $targets[] = compact('src', 'dest');
107 3
        }
108 3
        return $targets;
109
    }
110
111
    /**
112
     * @param string $url
113
     * @return string
114
     */
115 1
    private function makeDownloadingText($url)
116
    {
117 1
        $request = new Aspects\HttpGetRequest('example.com', $url, $this->io);
118 1
        $request->query = array();
119 1
        return "    <comment>$this->successCnt/$this->totalCnt</comment>:    {$request->getURL()}";
120
    }
121
}
122