Completed
Pull Request — master (#19)
by Sullivan
03:17
created

VersionsCheck::getPackageDepends()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 19
rs 8.8571
cc 6
eloc 9
nc 3
nop 2
1
<?php
2
3
namespace SLLH\ComposerVersionsCheck;
4
5
use Composer\Composer;
6
use Composer\DependencyResolver\Pool;
7
use Composer\Package\Link;
8
use Composer\Package\LinkConstraint\VersionConstraint;
9
use Composer\Package\PackageInterface;
10
use Composer\Package\RootPackageInterface;
11
use Composer\Repository\ArrayRepository;
12
use Composer\Repository\CompositeRepository;
13
use Composer\Repository\WritableRepositoryInterface;
14
use Composer\Semver\Comparator;
15
use Composer\Semver\Constraint\Constraint;
16
17
/**
18
 * @author Sullivan Senechal <[email protected]>
19
 */
20
final class VersionsCheck
21
{
22
    /**
23
     * @var OutdatedPackage[]
24
     */
25
    private $outdatedPackages = array();
26
27
    /**
28
     * @var VersionConstraint|null
29
     */
30
    private $oldComparator = null;
31
32
    /**
33
     * @param ArrayRepository             $distRepository
34
     * @param WritableRepositoryInterface $localRepository
35
     * @param RootPackageInterface        $rootPackage
36
     */
37
    public function checkPackages(ArrayRepository $distRepository, WritableRepositoryInterface $localRepository, RootPackageInterface $rootPackage)
38
    {
39
        $packages = $localRepository->getPackages();
40
        foreach ($packages as $package) {
41
            // Old composer versions BC
42
            $versionConstraint = class_exists('Composer\Semver\Constraint\Constraint')
43
                ? new Constraint('>', $package->getVersion())
44
                : new VersionConstraint('>', $package->getVersion())
0 ignored issues
show
Deprecated Code introduced by
The class Composer\Package\LinkConstraint\VersionConstraint has been deprecated with message: use Composer\Semver\Constraint\Constraint instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
45
            ;
46
47
            $higherPackages = $distRepository->findPackages($package->getName(), $versionConstraint);
48
49
            // Remove not stable packages if unwanted
50
            if (true === $rootPackage->getPreferStable()) {
51
                $higherPackages = array_filter($higherPackages, function (PackageInterface $package) {
52
                    return 'stable' === $package->getStability();
53
                });
54
            }
55
56
            // We got higher packages! Let's push it.
57
            if (count($higherPackages) > 0) {
58
                // PHP 5.3 BC
59
                $that = $this;
60
61
                // Sort packages by highest version to lowest
62
                usort($higherPackages, function (PackageInterface $p1, PackageInterface $p2) use ($that) {
63
                    return $that->versionCompare($p1->getVersion(), '<', $p2->getVersion());
64
                });
65
66
                // Push actual and last package on outdated array
67
                array_push($this->outdatedPackages, new OutdatedPackage($package, $higherPackages[0], $this->getPackageDepends($localRepository, $package)));
68
            }
69
        }
70
    }
71
72
    /**
73
     * @param bool $showDepends
74
     *
75
     * @return string
76
     */
77
    public function getOutput($showDepends = true)
78
    {
79
        $output = array();
80
81
        if (0 === count($this->outdatedPackages)) {
82
            $output[] = '<info>All packages are up to date.</info>';
83
        } else {
84
            $this->createNotUpToDateOutput($output, $showDepends);
85
        }
86
87
        return implode(PHP_EOL, $output).PHP_EOL;
88
    }
89
90
    /**
91
     * Version comparator bridge to handle BC with old composer versions.
92
     *
93
     * This method is public only for PHP 5.3 BC and SHOULD NOT be used.
94
     * Deprecate it and remove it on next major when PHP 5.3 support will be droped.
95
     *
96
     * @param string $version1
97
     * @param string $operator
98
     * @param string $version2
99
     *
100
     * @return bool
101
     */
102
    public function versionCompare($version1, $operator, $version2)
103
    {
104
        if (!class_exists('Composer\Semver\Comparator')) {
105
            $this->oldComparator = $this->oldComparator ?: new VersionConstraint('==', '1.0');
0 ignored issues
show
Deprecated Code introduced by
The class Composer\Package\LinkConstraint\VersionConstraint has been deprecated with message: use Composer\Semver\Constraint\Constraint instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
106
107
            return $this->oldComparator->versionCompare($version1, $version2, $operator);
108
        }
109
110
        return Comparator::compare($version1, $operator, $version2);
111
    }
112
113
    /**
114
     * @param WritableRepositoryInterface $localRepository
115
     * @param PackageInterface            $needle
116
     *
117
     * @return Link[]
118
     */
119
    private function getPackageDepends(WritableRepositoryInterface $localRepository, PackageInterface $needle)
120
    {
121
        $depends = array();
122
123
        foreach ($localRepository->getPackages() as $package) {
124
            // Skip root package
125
            if ($package instanceof RootPackageInterface) {
126
                continue;
127
            }
128
129
            foreach ($package->getRequires() as $link) {
130
                if ($link->getTarget() === $needle->getName() && !in_array($link, $depends, true)) {
131
                    $depends[] = $link;
132
                }
133
            }
134
        }
135
136
        return $depends;
137
    }
138
139
    /**
140
     * @param array $output
141
     * @param bool  $showDepends
142
     */
143
    private function createNotUpToDateOutput(array &$output, $showDepends = true)
144
    {
145
        $outdatedPackagesCount = count($this->outdatedPackages);
146
        $output[] = sprintf(
147
            '<warning>%d %s not up to date:</warning>',
148
            $outdatedPackagesCount,
149
            1 != $outdatedPackagesCount ? 'packages are' : 'package is'
150
        );
151
        $output[] = '';
152
153
        foreach ($this->outdatedPackages as $outdatedPackage) {
154
            $output[] = sprintf(
155
                '  - <info>%s</info> (<comment>%s</comment>) latest is <comment>%s</comment>',
156
                $outdatedPackage->getActual()->getPrettyName(),
157
                $outdatedPackage->getActual()->getPrettyVersion(),
158
                $outdatedPackage->getLast()->getPrettyVersion()
159
            );
160
161
            if (true === $showDepends) {
162
                foreach ($outdatedPackage->getDepends() as $depend) {
163
                    $output[] = sprintf(
164
                        '    Required by <info>%s</info> (<comment>%s</comment>)',
165
                        $depend->getSource(),
166
                        $depend->getPrettyConstraint()
167
                    );
168
                }
169
            }
170
171
            $output[] = '';
172
        }
173
    }
174
}
175