Completed
Push — master ( 03865c...106ea4 )
by Andrii
03:04
created

Plugin::scanPackages()   D

Complexity

Conditions 9
Paths 32

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 33.0036

Importance

Changes 6
Bugs 1 Features 1
Metric Value
c 6
b 1
f 1
dl 0
loc 25
ccs 8
cts 24
cp 0.3333
rs 4.909
cc 9
eloc 15
nc 32
nop 0
crap 33.0036
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
            foreach ($requires as $reqkey => $require) {
164
                $target = $require->getTarget();
165
                if (strpos($target, '/') === false) {
166
                    continue;
167
                }
168
                list($vendor, $name) = explode('/', $target);
169
                if (substr($vendor, -6) !== '-asset') {
170
                    continue;
171
                }
172
                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...
173
                #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...
174
                if ($this->hasManager($manager)) {
175
                    $this->getManager($manager)->setKnownDeps($package, $deptype, $name, $require->getPrettyConstraint());
176
                    /*
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...
177
                    unset($requires[$reqkey]);
178
                    $method[0] = 's';
179
                    if (method_exists($package, $method)) {
180
                        $package->{$method}($requires);
181
                    }
182
                    */
183
                }
184
            }
185
        }
186
    }
187
188
    /**
189
     * @param CommandEvent $event
190
     */
191
    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...
192
    {
193
        return;
194
        $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...
195
        foreach ($repositories as $repository) {
196
            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...
197
            }
198
        }
199
    }
200
201
    /**
202
     * Perform install. Called by composer after install.
203
     *
204
     * @param Event $event
205
     * @void
206
     */
207 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...
208
    {
209 1
        $lockFile = new JsonFile($this->lockFile);
210 1
        if ($lockFile->exists()) {
211
            $this->loadPackages($lockFile);
212
        } else {
213 1
            $this->scanPackages();
214
        }
215 1
        $this->runAction('install');
216 1
    }
217
218
    /**
219
     * Perform update. Called by composer after update.
220
     *
221
     * @param Event $event
222
     */
223
    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...
224
    {
225
        $this->scanPackages();
226
        $this->runAction('update');
227
    }
228
229
    /**
230
     * Sets [[packages]].
231
     *
232
     * @param PackageInterface[] $packages
233
     */
234 3
    public function setPackages(array $packages)
235
    {
236 3
        $this->packages = $packages;
237 3
    }
238
239
    /**
240
     * Gets [[packages]].
241
     * @return \Composer\Package\PackageInterface[]
242
     */
243 2
    public function getPackages()
244
    {
245 2
        if ($this->packages === null) {
246
            $this->packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
247
            $this->packages[] = $this->composer->getPackage();
248
        }
249
250 2
        return $this->packages;
251
    }
252
253
    /**
254
     * Returns package with given name if exists.
255
     * @param string $name package name
256
     * @return \Composer\Package\PackageInterface|null
257
     */
258
    public function findPackage($name)
259
    {
260
        foreach ($this->getPackages() as $package) {
261
            if ($name === $package->getName()) {
262
                return $package;
263
            }
264
        }
265
    }
266
267
    /**
268
     * Scan packages from the composer objects.
269
     * @void
270
     */
271 1
    protected function scanPackages()
272
    {
273 1
        $rootPackage = $this->composer->getPackage();
274 1
        if ($rootPackage) {
275
            $extra = $rootPackage->getExtra();
276
            foreach ($this->managers as $manager) {
277
                $var = $manager->getName() . '-asset-library';
278
                if (isset($extra['asset-installer-paths'][$var])) {
279
                    $manager->setDestination($extra['asset-installer-paths'][$var]);
280
                }
281
            }
282
        }
283 1
        foreach ($this->getPackages() as $package) {
284
            if ($package instanceof \Composer\Package\CompletePackageInterface) {
285
                $this->scanAssetDependencies($package);
286
            }
287 1
        }
288 1
        foreach ($this->getPackages() as $package) {
289
            if ($package instanceof \Composer\Package\CompletePackageInterface) {
290
                foreach ($this->managers as $manager) {
291
                    $manager->scanPackage($package);
292
                }
293
            }
294 1
        }
295 1
    }
296
297
    /**
298
     * Load packages from given lock file.
299
     *
300
     * @param JsonFile $lockFile
301
     * @void
302
     */
303
    protected function loadPackages(JsonFile $lockFile)
304
    {
305
        $lock = $lockFile->read();
306
        foreach ($this->managers as $name => $m) {
307
            $m->setConfig($lock[$name]);
308
        }
309
    }
310
311
    /**
312
     * Install packages after loading/scanning.
313
     * @param string $action
314
     * @void
315
     */
316 1
    protected function runAction($action)
317
    {
318 1
        $dir = getcwd();
319 1
        chdir($this->getVendorDir());
320 1
        foreach ($this->managers as $m) {
321 1
            if ($m->hasDependencies()) {
322
                $m->runAction($action);
323
            }
324 1
        }
325 1
        chdir($dir);
326 1
    }
327
328
    /**
329
     * Get absolute path to composer vendor dir.
330
     * @return string
331
     */
332 1
    public function getVendorDir()
333
    {
334 1
        if ($this->vendorDir === null) {
335 1
            $this->vendorDir = $this->composer->getConfig()->get('vendor-dir', '/');
336 1
        }
337
338 1
        return $this->vendorDir;
339
    }
340
}
341