Completed
Push — master ( 0b917b...fc5a3e )
by Andrii
03:48
created

Plugin::hasManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
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 1
            InstallerEvents::PRE_DEPENDENCIES_SOLVING => array(
128 1
                array('onPreDependenciesSolving', 0),
129 1
            ),
130 1
            PluginEvents::COMMAND => array(
131 1
                ['onCommand', 0],
132 1
            ),
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->removeAssetDependencies($package);
151
        }
152
    }
153
154
    public function removeAssetDependencies(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
                if ($this->hasManager($manager)) {
174
                    $this->getManager($manager)->setKnownDeps($package, $deptype, $name, $require->getPrettyConstraint());
175
                    unset($requires[$reqkey]);
176
                    $method[0] = 's';
177
                    if (method_exists($package, $method)) {
178
                        $package->{$method}($requires);
179
                    }
180
                }
181
            }
182
        }
183
    }
184
185
    /**
186
     * @param CommandEvent $event
187
     */
188
    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...
189
    {
190
        var_dump('onCommand');
0 ignored issues
show
Security Debugging Code introduced by
var_dump('onCommand'); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
191
        return;
192
        $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...
193
        foreach ($repositories as $repository) {
194
            var_dump($repository->getProviderNames());
195
            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...
196
            }
197
        }
198
    }
199
200
    /**
201
     * Perform install. Called by composer after install.
202
     *
203
     * @param Event $event
204
     * @void
205
     */
206 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...
207
    {
208 1
        $lockFile = new JsonFile($this->lockFile);
209 1
        if ($lockFile->exists()) {
210
            $this->loadPackages($lockFile);
211
        } else {
212 1
            $this->scanPackages();
213
        }
214 1
        $this->runAction('install');
215 1
    }
216
217
    /**
218
     * Perform update. Called by composer after update.
219
     *
220
     * @param Event $event
221
     */
222
    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...
223
    {
224
        $this->scanPackages();
225
        $this->runAction('update');
226
    }
227
228
    /**
229
     * Sets [[packages]].
230
     *
231
     * @param PackageInterface[] $packages
232
     */
233 3
    public function setPackages(array $packages)
234
    {
235 3
        $this->packages = $packages;
236 3
    }
237
238
    /**
239
     * Gets [[packages]].
240
     * @return \Composer\Package\PackageInterface[]
241
     */
242 2
    public function getPackages()
243
    {
244 2
        if ($this->packages === null) {
245
            $this->packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
246
            $this->packages[] = $this->composer->getPackage();
247
        }
248
249 2
        return $this->packages;
250
    }
251
252
    /**
253
     * Returns package with given name if exists.
254
     * @param string $name package name
255
     * @return \Composer\Package\PackageInterface|null
256
     */
257
    public function findPackage($name)
258
    {
259
        foreach ($this->getPackages() as $package) {
260
            if ($name === $package->getName()) {
261
                return $package;
262
            }
263
        }
264
    }
265
266
    /**
267
     * Scan packages from the composer objects.
268
     * @void
269
     */
270 1
    protected function scanPackages()
271
    {
272 1
        foreach ($this->getPackages() as $package) {
273
            if ($package instanceof \Composer\Package\CompletePackageInterface) {
274
                foreach ($this->managers as $manager) {
275
                    $manager->scanPackage($package);
276
                }
277
            }
278 1
        }
279 1
    }
280
281
    /**
282
     * Load packages from given lock file.
283
     *
284
     * @param JsonFile $lockFile
285
     * @void
286
     */
287
    protected function loadPackages(JsonFile $lockFile)
288
    {
289
        $lock = $lockFile->read();
290
        foreach ($this->managers as $name => $m) {
291
            $m->setConfig($lock[$name]);
292
        }
293
    }
294
295
    /**
296
     * Install packages after loading/scanning.
297
     * @param string $action
298
     * @void
299
     */
300 1
    protected function runAction($action)
301
    {
302 1
        $dir = getcwd();
303 1
        chdir($this->getVendorDir());
304 1
        foreach ($this->managers as $m) {
305 1
            if ($m->hasDependencies()) {
306
                $m->runAction($action);
307
            }
308 1
        }
309 1
        chdir($dir);
310 1
    }
311
312
    /**
313
     * Get absolute path to composer vendor dir.
314
     * @return string
315
     */
316 1
    public function getVendorDir()
317
    {
318 1
        if ($this->vendorDir === null) {
319 1
            $this->vendorDir = $this->composer->getConfig()->get('vendor-dir', '/');
320 1
        }
321
322 1
        return $this->vendorDir;
323
    }
324
}
325