Completed
Push — master ( 3d202f...7091a7 )
by
unknown
02:36 queued 12s
created

ComposerLoaderExtension::onAfterBuild()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 7
eloc 11
c 4
b 1
f 0
nc 12
nop 0
dl 0
loc 23
rs 8.8333
1
<?php
2
3
namespace BringYourOwnIdeas\UpdateChecker\Extensions;
4
5
use Composer\Composer;
6
use Composer\Factory;
7
use Composer\IO\NullIO;
8
use Composer\Package\Link;
9
use Composer\Repository\ArrayRepository;
10
use Composer\Repository\BaseRepository;
11
use Composer\Repository\CompositeRepository;
12
use Composer\Repository\RepositoryInterface;
13
use SilverStripe\Core\Environment;
14
use SilverStripe\Core\Extension;
15
16
class ComposerLoaderExtension extends Extension
17
{
18
    /**
19
     * @var Composer
20
     */
21
    protected $composer;
22
23
    /**
24
     * @param Composer $composer
25
     * @return $this
26
     */
27
    public function setComposer(Composer $composer)
28
    {
29
        $this->composer = $composer;
30
        return $this;
31
    }
32
33
    /**
34
     * @return Composer
35
     */
36
    public function getComposer()
37
    {
38
        return $this->composer;
39
    }
40
41
    /**
42
     * Retrieve an array of primary composer dependencies from composer.json.
43
     *
44
     * Packages are filtered by allowed type.
45
     *
46
     * @param array|null $allowedTypes An array of "allowed" package types. Dependencies in composer.json that do not
47
     *                                 match any of the given types are not returned.
48
     * @return array[]
49
     */
50
    public function getPackages(array $allowedTypes = null)
51
    {
52
        $packages = [];
53
        $repository = $this->getRepository();
54
        foreach ($repository->getPackages() as $package) {
55
            // Filter out packages that are not "allowed types"
56
            if (is_array($allowedTypes) && !in_array($package->getType(), $allowedTypes)) {
57
                continue;
58
            }
59
60
            // Find the constraint used for installation
61
            $constraint = $this->getInstalledConstraint($repository, $package->getName());
62
            $packages[$package->getName()] = [
63
                'constraint' => $constraint,
64
                'package' => $package,
65
            ];
66
        }
67
        return $packages;
68
    }
69
70
    /**
71
     * Provides access to the Composer repository
72
     *
73
     * @return RepositoryInterface
74
     */
75
    protected function getRepository()
76
    {
77
        /** @var Composer $composer */
78
        $composer = $this->getComposer();
79
80
        /** @var BaseRepository $repository */
81
        return new CompositeRepository([
82
            new ArrayRepository([$composer->getPackage()]),
83
            $composer->getRepositoryManager()->getLocalRepository(),
84
        ]);
85
    }
86
87
    /**
88
     * Find all dependency constraints for the given package in the current repository and return the strictest one
89
     *
90
     * @param BaseRepository $repository
91
     * @param string $packageName
92
     * @return string
93
     */
94
    protected function getInstalledConstraint(BaseRepository $repository, $packageName)
95
    {
96
        $constraints = [];
97
        foreach ($repository->getDependents($packageName) as $dependent) {
98
            /** @var Link $link */
99
            list (, $link) = $dependent;
100
            $constraints[] = $link->getPrettyConstraint();
101
        }
102
103
        usort($constraints, 'version_compare');
104
105
        return array_pop($constraints);
106
    }
107
108
    /**
109
     * Builds an instance of Composer
110
     */
111
    public function onAfterBuild()
112
    {
113
        // Mock COMPOSER_HOME if it's not defined already. Composer requires one of the two to be set.
114
        if (!Environment::getEnv('COMPOSER_HOME')) {
115
            $home = Environment::getEnv('HOME');
116
            if (!$home || !is_dir($home) || !is_writable($home)) {
117
                // Set our own directory
118
                putenv('COMPOSER_HOME=' . sys_get_temp_dir());
119
            }
120
        }
121
122
        $originalDir = getcwd();
123
124
        if ($originalDir !== BASE_PATH) {
125
            chdir(BASE_PATH);
126
        }
127
128
        /** @var Composer $composer */
129
        $composer = Factory::create(new NullIO());
130
        $this->setComposer($composer);
131
132
        if ($originalDir !== BASE_PATH) {
133
            chdir($originalDir);
134
        }
135
    }
136
}
137