Completed
Push — master ( c58e43...03865c )
by Andrii
02:55
created

Plugin   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 42.48%

Importance

Changes 19
Bugs 4 Features 3
Metric Value
wmc 41
c 19
b 4
f 3
lcom 1
cbo 7
dl 0
loc 307
ccs 48
cts 113
cp 0.4248
rs 8.2769

17 Methods

Rating   Name   Duplication   Size   Complexity  
A activate() 0 15 2
A getComposer() 0 4 1
A hasManager() 0 4 1
A getManager() 0 4 1
A onPreDependenciesSolving() 0 8 2
A getSubscribedEvents() 0 17 1
B scanAssetDependencies() 0 34 6
A onCommand() 0 9 3
A onPostInstall() 0 10 2
A onPostUpdate() 0 5 1
A setPackages() 0 4 1
A getPackages() 0 9 2
A findPackage() 0 8 3
C scanPackages() 0 22 8
A loadPackages() 0 7 2
A runAction() 0 11 3
A getVendorDir() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like Plugin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Plugin, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * Composer plugin for bower/npm assets
5
 *
6
 * @link      https://github.com/hiqdev/composer-asset-plugin
7
 * @package   composer-asset-plugin
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hiqdev\composerassetplugin;
13
14
use Composer\Composer;
15
use Composer\EventDispatcher\EventSubscriberInterface;
16
use Composer\Installer\InstallerEvent;
17
use Composer\Installer\InstallerEvents;
18
use Composer\IO\IOInterface;
19
use Composer\Json\JsonFile;
20
use Composer\Package\PackageInterface;
21
use Composer\Plugin\CommandEvent;
22
use Composer\Plugin\PluginEvents;
23
use Composer\Plugin\PluginInterface;
24
use Composer\Script\Event;
25
use Composer\Script\ScriptEvents;
26
27
/**
28
 * Plugin class.
29
 *
30
 * @author Andrii Vasyliev <[email protected]>
31
 */
32
class Plugin implements PluginInterface, EventSubscriberInterface
33
{
34
    /**
35
     * @var string the filename of a lock file. Defaults to `composer-asset-plugin.lock`
36
     */
37
    public $lockFile = 'composer-asset-plugin.lock';
38
39
    /**
40
     * @var Composer instance
41
     */
42
    protected $composer;
43
44
    /**
45
     * @var IOInterface
46
     */
47
    public $io;
48
49
    /**
50
     * @var Pool
51
     */
52
    protected $pool;
53
54
    /**
55
     * List of the available package managers/
56
     * Initialized at activate.
57
     * @var array|PackageManager[]
58
     * @see activate
59
     */
60
    protected $managers = [
61
        'bower' => 'hiqdev\composerassetplugin\Bower',
62
        'npm'   => 'hiqdev\composerassetplugin\Npm',
63
    ];
64
65
    /**
66
     * @var PackageInterface[] the array of active composer packages
67
     */
68
    protected $packages;
69
70
    /**
71
     * @var string absolute path to vendor directory.
72
     */
73
    protected $vendorDir;
74
75
    /**
76
     *
77
     */
78
    protected $requires = [];
79
80
    /**
81
     * Initializes the plugin object with the passed $composer and $io.
82
     * Also initializes package managers.
83
     *
84
     * @param Composer $composer
85
     * @param IOInterface $io
86
     * @void
87
     */
88 3
    public function activate(Composer $composer, IOInterface $io)
89
    {
90 3
        $managers = [];
91 3
        $this->composer = $composer;
92 3
        $this->io = $io;
93 3
        foreach ($this->managers as $name => $class) {
94 3
            $managers[$name] = new $class($this);
95 3
        }
96 3
        $this->managers = $managers;
97
98
        #$rm = $composer->getRepositoryManager();
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
99
100
        #$rm->setRepositoryClass('assets', 'hiqdev\composerassetplugin\AssetRepository');
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
101
        #$rm->addRepository($rm->createRepository('assets', ['plugin' => $this]));
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
102 3
    }
103
104
    public function getComposer()
105
    {
106
        return $this->composer;
107
    }
108
109
    public function hasManager($name)
110
    {
111
        return isset($this->managers[$name]);
112
    }
113
114
    public function getManager($name)
115
    {
116
        return $this->managers[$name];
117
    }
118
119
    /**
120
     * Returns list of events the plugin is subscribed to.
121
     *
122
     * @return array list of events
123
     */
124 1
    public static function getSubscribedEvents()
125
    {
126
        return [
127
#           InstallerEvents::PRE_DEPENDENCIES_SOLVING => array(
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
128
#               array('onPreDependenciesSolving', 0),
129
#           ),
130
#           PluginEvents::COMMAND => array(
131
#               ['onCommand', 0],
132
#           ),
133 1
            ScriptEvents::POST_INSTALL_CMD => [
134 1
                ['onPostInstall', 0],
135 1
            ],
136 1
            ScriptEvents::POST_UPDATE_CMD => [
137 1
                ['onPostUpdate', 0],
138 1
            ],
139 1
        ];
140
    }
141
142
    /**
143
     * @param InstallerEvent $event
144
     */
145
    public function onPreDependenciesSolving(InstallerEvent $event)
146
    {
147
        $pool = $event->getPool();
148
        for ($i=1; $i<= $pool->count(); $i++) {
149
            $package = $pool->packageById($i);
150
            $this->scanAssetDependencies($package);
151
        }
152
    }
153
154
    public function scanAssetDependencies(PackageInterface $package)
155
    {
156
        static $deptypes = [
157
            'dependencies'      => 'getRequires',
158
            'devDependencies'   => 'getDevRequires',
159
        ];
160
        $res = [];
0 ignored issues
show
Unused Code introduced by
$res is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
161
        foreach ($deptypes as $deptype => $method) {
162
            $requires = $package->$method();
163
164
            foreach ($requires as $reqkey => $require) {
165
                $target = $require->getTarget();
166
                if (strpos($target, '/') === false) {
167
                    continue;
168
                }
169
                list($vendor, $name) = explode('/', $target);
170
                if (substr($vendor, -6) !== '-asset') {
171
                    continue;
172
                }
173
                list($manager, $asset) = explode('-', $vendor);
0 ignored issues
show
Unused Code introduced by
The assignment to $asset is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
174
                #var_dump($target . ' ' . $require->getPrettyConstraint());
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
175
                if ($this->hasManager($manager)) {
176
                    $this->getManager($manager)->setKnownDeps($package, $deptype, $name, $require->getPrettyConstraint());
177
                    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
74% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
178
                    unset($requires[$reqkey]);
179
                    $method[0] = 's';
180
                    if (method_exists($package, $method)) {
181
                        $package->{$method}($requires);
182
                    }
183
                    */
184
                }
185
            }
186
        }
187
    }
188
189
    /**
190
     * @param CommandEvent $event
191
     */
192
    public function onCommand(CommandEvent $event)
0 ignored issues
show
Unused Code introduced by
The parameter $event 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...
193
    {
194
        return;
195
        $repositories = $this->composer->getRepositoryManager()->getRepositories();
0 ignored issues
show
Unused Code introduced by
$repositories = $this->c...r()->getRepositories(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
196
        foreach ($repositories as $repository) {
197
            foreach ($repository->getPackages() as $package) {
0 ignored issues
show
Unused Code introduced by
This foreach statement is empty and can be removed.

This check looks for foreach loops that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Consider removing the loop.

Loading history...
198
            }
199
        }
200
    }
201
202
    /**
203
     * Perform install. Called by composer after install.
204
     *
205
     * @param Event $event
206 1
     * @void
207
     */
208 1
    public function onPostInstall(Event $event)
0 ignored issues
show
Unused Code introduced by
The parameter $event 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...
209 1
    {
210
        $lockFile = new JsonFile($this->lockFile);
211
        if ($lockFile->exists()) {
212 1
            $this->loadPackages($lockFile);
213
        } else {
214 1
            $this->scanPackages();
215 1
        }
216
        $this->runAction('install');
217
    }
218
219
    /**
220
     * Perform update. Called by composer after update.
221
     *
222
     * @param Event $event
223
     */
224
    public function onPostUpdate(Event $event)
0 ignored issues
show
Unused Code introduced by
The parameter $event 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...
225
    {
226
        $this->scanPackages();
227
        $this->runAction('update');
228
    }
229
230
    /**
231
     * Sets [[packages]].
232
     *
233 3
     * @param PackageInterface[] $packages
234
     */
235 3
    public function setPackages(array $packages)
236 3
    {
237
        $this->packages = $packages;
238
    }
239
240
    /**
241
     * Gets [[packages]].
242 2
     * @return \Composer\Package\PackageInterface[]
243
     */
244 2
    public function getPackages()
245
    {
246
        if ($this->packages === null) {
247
            $this->packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
248
            $this->packages[] = $this->composer->getPackage();
249 2
        }
250
251
        return $this->packages;
252
    }
253
254
    /**
255
     * Returns package with given name if exists.
256
     * @param string $name package name
257
     * @return \Composer\Package\PackageInterface|null
258
     */
259
    public function findPackage($name)
260
    {
261
        foreach ($this->getPackages() as $package) {
262
            if ($name === $package->getName()) {
263
                return $package;
264
            }
265
        }
266
    }
267
268
    /**
269
     * Scan packages from the composer objects.
270 1
     * @void
271
     */
272 1
    protected function scanPackages()
273
    {
274
        $extra = $this->composer->getPackage()->getExtra();
275
        foreach ($this->managers as $manager) {
276 1
            $var = $manager->getName() . '-asset-library';
277 1
            if (isset($extra['asset-installer-paths'][$var])) {
278
                $manager->setDestination($extra['asset-installer-paths'][$var]);
279
            }
280
        }
281
        foreach ($this->getPackages() as $package) {
282
            if ($package instanceof \Composer\Package\CompletePackageInterface) {
283 1
                $this->scanAssetDependencies($package);
284 1
            }
285
        }
286
        foreach ($this->getPackages() as $package) {
287
            if ($package instanceof \Composer\Package\CompletePackageInterface) {
288
                foreach ($this->managers as $manager) {
289
                    $manager->scanPackage($package);
290
                }
291
            }
292
        }
293
    }
294
295
    /**
296
     * Load packages from given lock file.
297
     *
298
     * @param JsonFile $lockFile
299
     * @void
300
     */
301
    protected function loadPackages(JsonFile $lockFile)
302
    {
303
        $lock = $lockFile->read();
304
        foreach ($this->managers as $name => $m) {
305 1
            $m->setConfig($lock[$name]);
306
        }
307 1
    }
308 1
309 1
    /**
310 1
     * Install packages after loading/scanning.
311
     * @param string $action
312
     * @void
313 1
     */
314 1
    protected function runAction($action)
315 1
    {
316
        $dir = getcwd();
317
        chdir($this->getVendorDir());
318
        foreach ($this->managers as $m) {
319
            if ($m->hasDependencies()) {
320
                $m->runAction($action);
321 1
            }
322
        }
323 1
        chdir($dir);
324 1
    }
325 1
326
    /**
327 1
     * Get absolute path to composer vendor dir.
328
     * @return string
329
     */
330
    public function getVendorDir()
331
    {
332
        if ($this->vendorDir === null) {
333
            $this->vendorDir = $this->composer->getConfig()->get('vendor-dir', '/');
334
        }
335
336
        return $this->vendorDir;
337
    }
338
}
339