Completed
Pull Request — master (#223)
by Kuba
02:50
created

Plugin::deactivate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
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\Composer;
10
use Composer\IO;
11
use Composer\Plugin as CPlugin;
12
use Composer\EventDispatcher;
13
use Composer\Installer;
14
15
class Plugin implements
16
    CPlugin\PluginInterface,
17
    EventDispatcher\EventSubscriberInterface
18
{
19
    /** @var IO\IOInterface */
20
    private $io;
21
22
    /** @var Composer\Config */
23
    private $config;
24
25
    /** @var array */
26
    private $package;
27
    private $cached = false;
28
29
    /** @var boolean */
30
    private $disabled = false;
31
32
    private static $pluginClasses = array(
33
        'BaseRequest',
34
        'ConfigFacade',
35
        'CopyRequest',
36
        'CurlMulti',
37
        'CurlRemoteFilesystem',
38
        'FetchException',
39
        'FetchRequest',
40
        'FileDownloaderDummy',
41
        'ParallelizedComposerRepository',
42
        'Plugin',
43
        'Prefetcher',
44
        'Share',
45
    );
46
47
    private static $supportedSchemes = array(
48
        'http',
49
        'https'
50
    );
51
52 3
    public function activate(Composer $composer, IO\IOInterface $io)
53
    {
54
        // Composer 2 comes with parallel downloads built-in
55 3
        if (strcmp(self::PLUGIN_API_VERSION, '2.0.0') >= 0) {
56
            return $this->disable();
57
        }
58
59
        // @codeCoverageIgnoreStart
60
        // guard for self-update problem
61
        if (__CLASS__ !== 'Hirak\Prestissimo\Plugin') {
62
            return $this->disable();
63
        }
64
        // guard for missing curl extension problem
65
        if (!extension_loaded('curl')) {
66
            $io->writeError('<error>Error: "curl" PHP extension not loaded; Prestissmo Composer plugin disabled.</error>');
67
            return $this->disable();
68
        }
69
        // @codeCoverageIgnoreEnd
70
71
        // load all classes
72 3
        foreach (self::$pluginClasses as $class) {
73 3
            class_exists(__NAMESPACE__ . '\\' . $class);
74
        }
75
76 3
        $this->io = $io;
77 3
        $this->config = $composer->getConfig();
0 ignored issues
show
Documentation Bug introduced by
It seems like $composer->getConfig() of type object<Composer\Config> is incompatible with the declared type object<Composer\Composer\Config> of property $config.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
78 3
        $this->package = $composer->getPackage();
0 ignored issues
show
Documentation Bug introduced by
It seems like $composer->getPackage() of type object<Composer\Package\RootPackageInterface> is incompatible with the declared type array of property $package.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
79
80 3
        if (array_key_exists('argv', $GLOBALS)) {
81 3
            if (in_array('help', $GLOBALS['argv'])) {
82
                return $this->disable();
83
            }
84
85 3
            foreach ($GLOBALS['argv'] as $arg) {
86 3
                switch ($arg) {
87 3
                    case 'create-project':
88 3
                    case 'update':
89 3
                    case 'outdated':
90 3
                    case 'require':
91
                        $this->prefetchComposerRepositories();
92
                        break 2;
93 3
                    case 'install':
94
                        if (file_exists('composer.json') && !file_exists('composer.lock')) {
95
                            $this->prefetchComposerRepositories();
96
                        }
97
                        break 2;
98
                }
99
            }
100
        }
101 3
    }
102
103 1
    public function deactivate(Composer $composer, IO\IOInterface $io)
0 ignored issues
show
Unused Code introduced by
The parameter $composer is not used and could be removed.

This check looks from 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 $io is not used and could be removed.

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

Loading history...
104
    {
105 1
        $this->disable();
106 1
    }
107
108 1
    public function uninstall(Composer $composer, IO\IOInterface $io)
0 ignored issues
show
Unused Code introduced by
The parameter $composer is not used and could be removed.

This check looks from 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 $io is not used and could be removed.

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

Loading history...
109
    {
110 1
        $this->disable();
111 1
    }
112
113 1
    public static function getSubscribedEvents()
114
    {
115
        return array(
116 1
            CPlugin\PluginEvents::PRE_FILE_DOWNLOAD => 'onPreFileDownload',
117 1
            Installer\InstallerEvents::POST_DEPENDENCIES_SOLVING => array(
118 1
                array('onPostDependenciesSolving', PHP_INT_MAX),
119
            ),
120
        );
121
    }
122
123
    /**
124
     * Keep-Alived file downloader
125
     */
126
    public function onPreFileDownload(CPlugin\PreFileDownloadEvent $ev)
127
    {
128
        if ($this->disabled) {
129
            return;
130
        }
131
132
        $scheme = parse_url($ev->getProcessedUrl(), PHP_URL_SCHEME);
133
        if (!in_array($scheme, self::$supportedSchemes, true)) {
134
            return;
135
        }
136
137
        $rfs = $ev->getRemoteFilesystem();
138
        $curlrfs = new CurlRemoteFilesystem(
139
            $this->io,
140
            $this->config,
141
            $rfs->getOptions()
142
        );
143
        $ev->setRemoteFilesystem($curlrfs);
144
    }
145
146 1
    public function prefetchComposerRepositories()
147
    {
148 1
        if ($this->disabled) {
149 1
            return;
150
        }
151 1
        if ($this->cached) {
152
            return;
153
        }
154 1
        $repos = $this->package->getRepositories();
0 ignored issues
show
Bug introduced by
The method getRepositories cannot be called on $this->package (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
155 1
        foreach ($repos as $label => $repo) {
156
            if (isset($repo['type']) && $repo['type'] === 'composer') {
157
                if (!empty($repo['force-lazy-providers'])) {
158
                    continue;
159
                }
160
161
                if (substr($repo['url'], 0, 6) !== 'https?') {
162
                    $scheme = parse_url($repo['url'], PHP_URL_SCHEME);
163
                    if (!in_array($scheme, self::$supportedSchemes, true)) {
164
                        continue;
165
                    }
166
                }
167
168
                $r = new ParallelizedComposerRepository($repo, $this->io, $this->config);
169
                $r->prefetch();
170
            }
171
        }
172 1
        $this->cached = true;
173 1
    }
174
175
    /**
176
     * pre-fetch parallel by curl_multi
177
     */
178 1
    public function onPostDependenciesSolving(Installer\InstallerEvent $ev)
179
    {
180 1
        if ($this->disabled) {
181 1
            return;
182
        }
183 1
        $prefetcher = new Prefetcher;
184 1
        $prefetcher->fetchAllFromOperations(
185 1
            $this->io,
186 1
            $this->config,
187 1
            $ev->getOperations()
188
        );
189 1
    }
190
191 4
    public function disable()
192
    {
193 4
        $this->disabled = true;
194 4
    }
195
196 3
    public function isDisabled()
197
    {
198 3
        return $this->disabled;
199
    }
200
}
201