GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Branch master (305ff3)
by Franck
01:48
created

Plugin::run()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 12
rs 9.4285
cc 1
eloc 8
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of the Dealerdirect PHP_CodeSniffer Standards
5
 * Composer Installer Plugin package.
6
 *
7
 * @copyright 2016 Dealerdirect B.V.
8
 * @license MIT
9
 */
10
11
namespace Dealerdirect\Composer\Plugin\Installers\PHPCodeSniffer;
12
13
use Composer\Composer;
14
use Composer\EventDispatcher\EventSubscriberInterface;
15
use Composer\IO\IOInterface;
16
use Composer\Package\AliasPackage;
17
use Composer\Package\PackageInterface;
18
use Composer\Plugin\PluginInterface;
19
use Composer\Script\Event;
20
use Composer\Script\ScriptEvents;
21
use Symfony\Component\Finder\Finder;
22
use Symfony\Component\Process\Exception\LogicException;
23
use Symfony\Component\Process\Exception\ProcessFailedException;
24
use Symfony\Component\Process\Exception\RuntimeException;
25
use Symfony\Component\Process\ProcessBuilder;
26
27
/**
28
 * PHP_CodeSniffer standard installation manager.
29
 *
30
 * @author Franck Nijhof <[email protected]>
31
 */
32
class Plugin implements PluginInterface, EventSubscriberInterface
33
{
34
    const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
35
    const MESSAGE_NOTHING_TO_INSTALL = 'Nothing to install or update';
36
    const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
37
38
    const PACKAGE_NAME = 'squizlabs/php_codesniffer';
39
    const PACKAGE_TYPE = 'phpcodesniffer-standard';
40
41
    const PHPCS_CONFIG_KEY = 'installed_paths';
42
43
    /**
44
     * @var Composer
45
     */
46
    private $composer;
47
48
    /**
49
     * @var IOInterface
50
     */
51
    private $io;
52
53
    /**
54
     * @var array
55
     */
56
    private $installedPaths;
57
58
    /**
59
     * @var ProcessBuilder
60
     */
61
    private $processBuilder;
62
63
    /**
64
     * Triggers the plugin's main functionality.
65
     *
66
     * Makes it possible to run the plugin as a custom command.
67
     *
68
     * @param Event $event
69
     *
70
     * @throws \InvalidArgumentException
71
     * @throws LogicException
72
     * @throws ProcessFailedException
73
     * @throws RuntimeException
74
     */
75
    public static function run(Event $event)
76
    {
77
        $io = $event->getIO();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
78
        $composer = $event->getComposer();
79
80
        $instance = new static();
81
82
        $instance->io = $io;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
83
        $instance->composer = $composer;
84
        $instance->init();
85
        $instance->onDependenciesChangedEvent();
86
    }
87
88
    /**
89
     * {@inheritDoc}
90
     *
91
     * @throws \RuntimeException
92
     * @throws LogicException
93
     * @throws RuntimeException
94
     * @throws ProcessFailedException
95
     */
96
    public function activate(Composer $composer, IOInterface $io)
97
    {
98
        $this->composer = $composer;
99
        $this->io = $io;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
100
101
        $this->init();
102
    }
103
104
    /**
105
     * Prepares the plugin so it's main functionality can be run.
106
     *
107
     * @throws \RuntimeException
108
     * @throws LogicException
109
     * @throws ProcessFailedException
110
     * @throws RuntimeException
111
     */
112
    private function init()
113
    {
114
        $this->installedPaths = [];
115
116
        $this->processBuilder = new ProcessBuilder();
117
        $this->processBuilder->setPrefix($this->composer->getConfig()->get('bin-dir') . DIRECTORY_SEPARATOR . 'phpcs');
118
119
        $this->loadInstalledPaths();
120
    }
121
122
    /**
123
     * {@inheritDoc}
124
     */
125
    public static function getSubscribedEvents()
126
    {
127
        return [
128
            ScriptEvents::POST_INSTALL_CMD => [
129
                ['onDependenciesChangedEvent', 0],
130
            ],
131
            ScriptEvents::POST_UPDATE_CMD => [
132
                ['onDependenciesChangedEvent', 0],
133
            ],
134
        ];
135
    }
136
137
    /**
138
     * Entry point for post install and post update events.
139
     *
140
     * @throws \InvalidArgumentException
141
     * @throws RuntimeException
142
     * @throws LogicException
143
     * @throws ProcessFailedException
144
     */
145
    public function onDependenciesChangedEvent()
146
    {
147
        $io = $this->io;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
148
        $isVerbose = $io->isVerbose();
149
150
        if ($isVerbose) {
151
            $io->write(sprintf('<info>%s</info>', self::MESSAGE_RUNNING_INSTALLER));
152
        }
153
154
        if ($this->isPHPCodeSnifferInstalled() === true) {
155
            $installPathCleaned = $this->cleanInstalledPaths();
156
            $installPathUpdated = $this->updateInstalledPaths();
157
158
            if ($installPathCleaned === true || $installPathUpdated === true) {
159
                $this->saveInstalledPaths();
160
            } elseif ($isVerbose) {
161
                $io->write(sprintf('<info>%s</info>', self::MESSAGE_NOTHING_TO_INSTALL));
162
            }
163
        } elseif ($isVerbose) {
164
            $io->write(sprintf('<info>%s</info>', self::MESSAGE_NOT_INSTALLED));
165
        }
166
    }
167
168
    /**
169
     * Load all paths from PHP_CodeSniffer into an array.
170
     *
171
     * @throws RuntimeException
172
     * @throws LogicException
173
     * @throws ProcessFailedException
174
     */
175
    private function loadInstalledPaths()
176
    {
177
        if ($this->isPHPCodeSnifferInstalled() === true) {
178
            $output = $this->processBuilder
179
                ->setArguments(['--config-show', self::PHPCS_CONFIG_KEY])
180
                ->getProcess()
181
                ->mustRun()
182
                ->getOutput();
183
184
            $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $output);
185
            $phpcsInstalledPaths = trim($phpcsInstalledPaths);
186
187
            if ($phpcsInstalledPaths !== '') {
188
                $this->installedPaths = explode(',', $phpcsInstalledPaths);
189
            }
190
        }
191
    }
192
193
    /**
194
     * Save all coding standard paths back into PHP_CodeSniffer
195
     *
196
     * @throws RuntimeException
197
     * @throws LogicException
198
     * @throws ProcessFailedException
199
     */
200
    private function saveInstalledPaths()
201
    {
202
        // Check if we found installed paths to set.
203
        if (count($this->installedPaths) !== 0) {
204
            $paths = implode(',', $this->installedPaths);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
205
            $arguments = ['--config-set', self::PHPCS_CONFIG_KEY, $paths];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
206
            $configMessage = sprintf(
207
                'PHP CodeSniffer Config <info>%s</info> <comment>set to</comment> <info>%s</info>',
208
                self::PHPCS_CONFIG_KEY,
209
                $paths
210
            );
211
        } else {
212
            // Delete the installed paths if none were found.
213
            $arguments = ['--config-delete', self::PHPCS_CONFIG_KEY];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
214
            $configMessage = sprintf(
215
                'PHP CodeSniffer Config <info>%s</info> <comment>delete</comment>',
216
                self::PHPCS_CONFIG_KEY
217
            );
218
        }
219
220
        $this->io->write($configMessage);
221
222
        $configResult = $this->processBuilder
223
            ->setArguments($arguments)
224
            ->getProcess()
225
            ->mustRun()
226
            ->getOutput()
227
        ;
228
        if ($this->io->isVerbose() && !empty($configResult)) {
229
            $this->io->write(sprintf('<info>%s</info>', $configResult));
230
        }
231
    }
232
233
    /**
234
     * Iterate trough all known paths and check if they are still valid.
235
     *
236
     * If path does not exists, is not an directory or isn't readable, the path
237
     * is removed from the list.
238
     *
239
     * @return bool True if changes where made, false otherwise
240
     */
241
    private function cleanInstalledPaths()
242
    {
243
        $changes = false;
244
        foreach ($this->installedPaths as $key => $path) {
245
            if (file_exists($path) === false || is_dir($path) === false || is_readable($path) === false) {
246
                unset($this->installedPaths[$key]);
247
                $changes = true;
248
            }
249
        }
250
        return $changes;
251
    }
252
253
    /**
254
     * Check all installed packages against the installed paths from
255
     * PHP_CodeSniffer and add the missing ones.
256
     *
257
     * @return bool True if changes where made, false otherwise
258
     *
259
     * @throws \InvalidArgumentException
260
     */
261
    private function updateInstalledPaths()
262
    {
263
        $changes = false;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 16 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
264
        $codingStandardPackages = $this->getPHPCodingStandardPackages();
265
266
        foreach ($codingStandardPackages as $package) {
267
            $packageInstallPath = $this->composer->getInstallationManager()->getInstallPath($package);
268
            $finder = new Finder();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 13 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
269
            $finder->files()
270
              ->ignoreVCS(true)
271
              ->in($packageInstallPath)
272
              ->depth('> 1')
273
              ->depth('< 4')
274
              ->name('ruleset.xml');
275
            foreach ($finder as $ruleset) {
276
                $standardsPath = dirname(dirname($ruleset));
277
                if (in_array($standardsPath, $this->installedPaths, true) === false) {
278
                    $this->installedPaths[] = $standardsPath;
279
                    $changes = true;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 16 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
280
                }
281
            }
282
        }
283
284
        return $changes;
285
    }
286
287
    /**
288
     * Iterates through Composers' local repository looking for valid Coding
289
     * Standard packages.
290
     *
291
     * @return array Composer packages containing coding standard(s)
292
     */
293
    private function getPHPCodingStandardPackages()
294
    {
295
        $codingStandardPackages = array_filter(
296
            $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(),
297
            function (PackageInterface $package) {
298
                if ($package instanceof AliasPackage) {
299
                    return false;
300
                }
301
                return $package->getType() === Plugin::PACKAGE_TYPE;
302
            }
303
        );
304
305
        if ($this->composer->getPackage()->getType() === self::PACKAGE_TYPE) {
306
            $codingStandardPackages[] = $this->composer->getPackage();
307
        }
308
309
        return $codingStandardPackages;
310
    }
311
312
    /**
313
     * Simple check if PHP_CodeSniffer is installed.
314
     *
315
     * @return bool Whether PHP_CodeSniffer is installed
316
     */
317
    private function isPHPCodeSnifferInstalled()
318
    {
319
        $packages = $this
320
            ->composer
321
            ->getRepositoryManager()
322
            ->getLocalRepository()
323
            ->findPackages(self::PACKAGE_NAME)
324
        ;
325
326
        $packageCount = count($packages);
327
328
        return ($packageCount !== 0);
329
    }
330
}
331