Completed
Pull Request — master (#61)
by Hiraku
02:17
created

ParallelDownloader::setupShareHandler()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 17
ccs 0
cts 0
cp 0
rs 8.8571
cc 5
eloc 9
nc 6
nop 3
crap 30
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
            if (!$host) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $host of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
91
                ++$this->skippedCnt;
92
                continue;
93
            }
94 2
            $src = Factory::getHttpGetRequest($host, $url, $this->io, $this->config, $pluginConfig);
95 2
            if (!in_array($p->getName(), $pluginConfig['privatePackages'])) {
96 2
                $src->maybePublic = (bool)preg_match('%^(?:https|git)://github\.com%', $p->getSourceUrl());
97 2
            }
98
            // make file resource
99
            $filepath = $cachedir
100
                . DIRECTORY_SEPARATOR
101 2
                . FileDownloaderDummy::getCacheKeyCompat($p, $src->getURL());
102 2
            if (file_exists($filepath)) {
103
                ++$this->skippedCnt;
104
                continue;
105
            }
106 2
            $dest = new OutputFile($filepath);
107
108 2
            $targets[] = compact('src', 'dest');
109 3
        }
110 3
        return $targets;
111
    }
112
113
    /**
114
     * @param string $url
115
     * @return string
116
     */
117 1
    private function makeDownloadingText($url)
118
    {
119 1
        $request = new Aspects\HttpGetRequest('example.com', $url, $this->io);
120 1
        $request->query = array();
121 1
        return "    <comment>$this->successCnt/$this->totalCnt</comment>:    {$request->getURL()}";
122
    }
123
}
124