Completed
Pull Request — master (#7)
by Marco
01:56
created

Installer::locateRootPackageInstallPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2
Metric Value
dl 0
loc 10
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
crap 2
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 ocramius/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
final class Versions
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(string $packageName) : string
42
    {
43
        if (! isset(self::VERSIONS[$packageName])) {
44
            throw new \OutOfBoundsException(
45
                'Required package "' . $packageName . '" is not installed: cannot detect its version'
46
            );
47
        }
48
49
        return self::VERSIONS[$packageName];
50
    }
51
}
52
53
PHP;
54
55
    /**
56
     * {@inheritDoc}
57
     */
58 1
    public function activate(Composer $composer, IOInterface $io)
59
    {
60 1
        $composer->getEventDispatcher()->addSubscriber($this);
61 1
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66 1
    public static function getSubscribedEvents()
67
    {
68
        return [
69 1
            ScriptEvents::POST_INSTALL_CMD => 'dumpVersionsClass',
70 1
            ScriptEvents::POST_UPDATE_CMD  => 'dumpVersionsClass',
71
        ];
72
    }
73
74
    /**
75
     * @param Event $composerEvent
76
     *
77
     * @return void
78
     *
79
     * @throws \RuntimeException
80
     */
81 7
    public static function dumpVersionsClass(Event $composerEvent)
82
    {
83 7
        $io = $composerEvent->getIO();
84
85 7
        $io->write('<info>ocramius/package-versions:</info>  Generating version class...');
86
87 7
        $composer = $composerEvent->getComposer();
88
89 7
        self::writeVersionClassToFile(
90 7
            self::generateVersionsClass($composer),
91 7
            $composer->getConfig(),
92 7
            $composer->getPackage()
93
        );
94
95 7
        self::reDumpAutoloader($composer);
96
97 7
        $io->write('<info>ocramius/package-versions:</info> ...done generating version class');
98 7
    }
99
100 7
    private static function generateVersionsClass(Composer $composer) : string
101
    {
102 7
        return sprintf(
103 7
            self::$generatedClassTemplate,
104 7
            var_export(iterator_to_array(self::getVersions($composer->getLocker(), $composer->getPackage())), true)
105
        );
106
    }
107
108
    /**
109
     * @param string               $versionClassSource
110
     * @param Config               $composerConfig
111
     * @param RootPackageInterface $rootPackage
112
     *
113
     * @return void
114
     *
115
     * @throws \RuntimeException
116
     */
117 7
    private static function writeVersionClassToFile(
118
        string $versionClassSource,
119
        Config $composerConfig,
120
        RootPackageInterface $rootPackage
121
    ) {
122 7
        file_put_contents(
123 7
            self::locateRootPackageInstallPath($composerConfig, $rootPackage)
124 7
            . '/src/PackageVersions/Versions.php',
125
            $versionClassSource,
126 7
            0664
127
        );
128 7
    }
129
130
    /**
131
     * @param Config               $composerConfig
132
     * @param RootPackageInterface $rootPackage
133
     *
134
     * @return string
135
     *
136
     * @throws \RuntimeException
137
     */
138 7
    private static function locateRootPackageInstallPath(
139
        Config $composerConfig,
140
        RootPackageInterface $rootPackage
141
    ) : string {
0 ignored issues
show
Coding Style introduced by
There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration
Loading history...
142 7
        if ('ocramius/package-versions' === self::getRootPackageAlias($rootPackage)->getName()) {
143 3
            return dirname($composerConfig->get('vendor-dir'));
144
        }
145
146 4
        return $composerConfig->get('vendor-dir') . '/ocramius/package-versions';
147
    }
148
149 7
    private static function getRootPackageAlias(RootPackageInterface $rootPackage) : PackageInterface
150
    {
151 7
        $package = $rootPackage;
152
153 7
        while ($package instanceof AliasPackage) {
154 4
            $package = $package->getAliasOf();
155
        }
156
157 7
        return $package;
158
    }
159
160
    /**
161
     * @param Composer $composer
162
     *
163
     * @return void
164
     */
165 7
    private static function reDumpAutoloader(Composer $composer)
166
    {
167 7
        $composer->getAutoloadGenerator()->dump(
168 7
            $composer->getConfig(),
169 7
            $composer->getRepositoryManager()->getLocalRepository(),
170 7
            $composer->getPackage(),
171 7
            $composer->getInstallationManager(),
172 7
            'composer',
173 7
            true // CBA to provide this manually, for now
174
        );
175 7
    }
176
177
    /**
178
     * @param Locker               $locker
179
     * @param RootPackageInterface $rootPackage
180
     *
181
     * @return \Generator|\string[]
182
     */
183 7
    private static function getVersions(Locker $locker, RootPackageInterface $rootPackage) : \Generator
184
    {
185 7
        $lockData = $locker->getLockData();
186
187 7
        foreach (array_merge($lockData['packages'], $lockData['packages-dev'])  as $package) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space before "as"; 2 found
Loading history...
188 1
            yield $package['name']
189 1
                => $package['version'] . '@' . $package['source']['reference'];
190
        }
191
192 7
        yield $rootPackage->getName() => $rootPackage->getVersion() . '@' . $rootPackage->getSourceReference();
193
    }
194
}