Installer   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 2
Metric Value
wmc 14
c 5
b 0
f 2
lcom 1
cbo 9
dl 0
loc 183
ccs 46
cts 46
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A activate() 0 4 1
A getSubscribedEvents() 0 7 1
A dumpVersionsClass() 0 16 1
A generateVersionsClass() 0 8 1
A writeVersionClassToFile() 0 12 1
A locateRootPackageInstallPath() 0 10 2
A getRootPackageAlias() 0 10 2
B getVersions() 0 16 5
1
<?php
2
3
namespace PackageVersions;
4
5
use Composer\Composer;
6
use Composer\Config;
7
use Composer\EventDispatcher\EventSubscriberInterface;
8
use Composer\IO\IOInterface;
9
use Composer\Package\AliasPackage;
10
use Composer\Package\Locker;
11
use Composer\Package\PackageInterface;
12
use Composer\Package\RootPackageInterface;
13
use Composer\Plugin\PluginInterface;
14
use Composer\Script\Event;
15
use Composer\Script\ScriptEvents;
16
17
final class Installer implements PluginInterface, EventSubscriberInterface
18
{
19
    private static $generatedClassTemplate = <<<'PHP'
20
<?php
21
22
namespace PackageVersions;
23
24
/**
25
 * This class is generated by samsonasik/package-versions, specifically by
26
 * @see \PackageVersions\Installer
27
 *
28
 * This file is overwritten at every run of `composer install` or `composer update`.
29
 */
30
%s
31
{
32
    const VERSIONS = %s;
33
34
    private function __construct()
35
    {
36
    }
37
38
    /**
39
     * @throws \OutOfBoundsException if a version cannot be located
40
     */
41
    public static function getVersion($packageName)
42
    {
43
        $selfVersion = self::VERSIONS;
44
45
        if (! isset($selfVersion[$packageName])) {
46
            throw new \OutOfBoundsException(
47
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
48
            );
49
        }
50
51
        return $selfVersion[$packageName];
52
    }
53
54
    /**
55
     * @throws \OutOfBoundsException if a version cannot be located
56
     */
57
    public static function getShortVersion($packageName)
58
    {
59
        return explode('@', static::getVersion($packageName))[0];
60
    }
61
62
    /**
63
     * @throws \OutOfBoundsException if a version cannot be located
64
     */
65
    public static function getMajorVersion($packageName)
66
    {
67
        return explode('.', static::getShortVersion($packageName))[0];
68
    }
69
}
70
71
PHP;
72
73
    /**
74
     * {@inheritDoc}
75
     */
76 1
    public function activate(Composer $composer, IOInterface $io)
77
    {
78 1
        $composer->getEventDispatcher()->addSubscriber($this);
79 1
    }
80
81
    /**
82
     * {@inheritDoc}
83
     */
84 1
    public static function getSubscribedEvents()
85
    {
86
        return [
87 1
            ScriptEvents::POST_INSTALL_CMD => 'dumpVersionsClass',
88 1
            ScriptEvents::POST_UPDATE_CMD  => 'dumpVersionsClass',
89
        ];
90
    }
91
92
    /**
93
     * @param Event $composerEvent
94
     *
95
     * @return void
96
     *
97
     * @throws \RuntimeException
98
     */
99 9
    public static function dumpVersionsClass(Event $composerEvent)
100
    {
101 9
        $io = $composerEvent->getIO();
102
103 9
        $io->write('<info>samsonasik/package-versions:</info>  Generating version class...');
104
105 9
        $composer = $composerEvent->getComposer();
106
107 9
        self::writeVersionClassToFile(
108 9
            self::generateVersionsClass($composer),
109 9
            $composer->getConfig(),
110 9
            $composer->getPackage()
111
        );
112
113 9
        $io->write('<info>samsonasik/package-versions:</info> ...done generating version class');
114 9
    }
115
116 9
    private static function generateVersionsClass(Composer $composer)
117
    {
118 9
        return sprintf(
119 9
            self::$generatedClassTemplate,
120 9
            'fin' . 'al ' . 'cla' . 'ss ' . 'Versions', // note: workaround for regex-based code parsers :-(
121 9
            var_export(iterator_to_array(self::getVersions($composer->getLocker(), $composer->getPackage())), true)
122
        );
123
    }
124
125
    /**
126
     * @param string               $versionClassSource
127
     * @param Config               $composerConfig
128
     * @param RootPackageInterface $rootPackage
129
     *
130
     * @return void
131
     *
132
     * @throws \RuntimeException
133
     */
134 9
    private static function writeVersionClassToFile(
135
        $versionClassSource,
136
        Config $composerConfig,
137
        RootPackageInterface $rootPackage
138
    ) {
139 9
        file_put_contents(
140 9
            self::locateRootPackageInstallPath($composerConfig, $rootPackage)
141 9
            . '/src/PackageVersions/Versions.php',
142
            $versionClassSource,
143 9
            0664
144
        );
145 9
    }
146
147
    /**
148
     * @param Config               $composerConfig
149
     * @param RootPackageInterface $rootPackage
150
     *
151
     * @return string
152
     *
153
     * @throws \RuntimeException
154
     */
155 9
    private static function locateRootPackageInstallPath(
156
        Config $composerConfig,
157
        RootPackageInterface $rootPackage
158
    ) {
159 9
        if ('samsonasik/package-versions' === self::getRootPackageAlias($rootPackage)->getName()) {
160 3
            return dirname($composerConfig->get('vendor-dir'));
161
        }
162
163 6
        return $composerConfig->get('vendor-dir') . '/samsonasik/package-versions';
164
    }
165
166 9
    private static function getRootPackageAlias(RootPackageInterface $rootPackage)
167
    {
168 9
        $package = $rootPackage;
169
170 9
        while ($package instanceof AliasPackage) {
171 4
            $package = $package->getAliasOf();
172
        }
173
174 9
        return $package;
175
    }
176
177
    /**
178
     * @param Locker               $locker
179
     * @param RootPackageInterface $rootPackage
180
     *
181
     * @return \Generator|\string[]
182
     */
183 9
    private static function getVersions(Locker $locker, RootPackageInterface $rootPackage)
184
    {
185 9
        $lockData = $locker->getLockData();
186
187 9
        $lockData['packages-dev'] = isset($lockData['packages-dev']) ? $lockData['packages-dev'] : [];
188
189 9
        foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) {
190 3
            yield $package['name'] => $package['version'] . '@' . (
191 3
                isset($package['source']['reference'])
192 2
                    ? $package['source']['reference']
193 3
                    : (isset($package['dist']['reference']) ? $package['dist']['reference'] : '')
194
            );
195
        }
196
197 9
        yield $rootPackage->getName() => $rootPackage->getVersion() . '@' . $rootPackage->getSourceReference();
198 9
    }
199
}
200