Completed
Push — master ( d6b303...8271f2 )
by Sullivan
02:14
created

VersionsCheck::createNotUpToDateOutput()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 31
rs 8.439
cc 5
eloc 20
nc 3
nop 2
1
<?php
2
3
namespace SLLH\ComposerVersionsCheck;
4
5
use Composer\Package\Link;
6
use Composer\Package\LinkConstraint\VersionConstraint;
7
use Composer\Package\PackageInterface;
8
use Composer\Package\RootPackageInterface;
9
use Composer\Repository\ArrayRepository;
10
use Composer\Repository\WritableRepositoryInterface;
11
use Composer\Semver\Comparator;
12
use Composer\Semver\Constraint\Constraint;
13
14
/**
15
 * @author Sullivan Senechal <[email protected]>
16
 */
17
final class VersionsCheck
18
{
19
    /**
20
     * @var OutdatedPackage[]
21
     */
22
    private $outdatedPackages = array();
23
24
    /**
25
     * @var VersionConstraint|null
26
     */
27
    private $oldComparator = null;
28
29
    /**
30
     * @param ArrayRepository             $distRepository
31
     * @param WritableRepositoryInterface $localRepository
32
     * @param RootPackageInterface        $rootPackage
33
     */
34
    public function checkPackages(ArrayRepository $distRepository, WritableRepositoryInterface $localRepository, RootPackageInterface $rootPackage)
35
    {
36
        $packages = $localRepository->getPackages();
37
        foreach ($packages as $package) {
38
            // Old composer versions BC
39
            $versionConstraint = class_exists('Composer\Semver\Constraint\Constraint')
40
                ? new Constraint('>', $package->getVersion())
41
                : 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...
42
            ;
43
44
            $higherPackages = $distRepository->findPackages($package->getName(), $versionConstraint);
45
46
            // Remove not stable packages if unwanted
47
            if (true === $rootPackage->getPreferStable()) {
48
                $higherPackages = array_filter($higherPackages, function (PackageInterface $package) {
49
                    return 'stable' === $package->getStability();
50
                });
51
            }
52
53
            // We got higher packages! Let's push it.
54
            if (count($higherPackages) > 0) {
55
                // PHP 5.3 BC
56
                $that = $this;
57
58
                // Sort packages by highest version to lowest
59
                usort($higherPackages, function (PackageInterface $p1, PackageInterface $p2) use ($that) {
60
                    return $that->versionCompare($p1->getVersion(), '<', $p2->getVersion());
61
                });
62
63
                // Push actual and last package on outdated array
64
                array_push($this->outdatedPackages, new OutdatedPackage($package, $higherPackages[0], $this->getPackageDepends($localRepository, $package)));
65
            }
66
        }
67
    }
68
69
    /**
70
     * @param bool $showDepends
71
     *
72
     * @return string
73
     */
74
    public function getOutput($showDepends = true)
75
    {
76
        $output = array();
77
78
        if (0 === count($this->outdatedPackages)) {
79
            $output[] = '<info>All packages are up to date.</info>';
80
        } else {
81
            $this->createNotUpToDateOutput($output, $showDepends);
82
        }
83
84
        return implode(PHP_EOL, $output).PHP_EOL;
85
    }
86
87
    /**
88
     * Version comparator bridge to handle BC with old composer versions.
89
     *
90
     * This method is public only for PHP 5.3 BC and SHOULD NOT be used.
91
     * Deprecate it and remove it on next major when PHP 5.3 support will be droped.
92
     *
93
     * @param string $version1
94
     * @param string $operator
95
     * @param string $version2
96
     *
97
     * @return bool
98
     */
99
    public function versionCompare($version1, $operator, $version2)
100
    {
101
        if (!class_exists('Composer\Semver\Comparator')) {
102
            $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...
103
104
            return $this->oldComparator->versionCompare($version1, $version2, $operator);
105
        }
106
107
        return Comparator::compare($version1, $operator, $version2);
108
    }
109
110
    /**
111
     * @param WritableRepositoryInterface $localRepository
112
     * @param PackageInterface            $needle
113
     *
114
     * @return Link[]
115
     */
116
    private function getPackageDepends(WritableRepositoryInterface $localRepository, PackageInterface $needle)
117
    {
118
        $depends = array();
119
120
        foreach ($localRepository->getPackages() as $package) {
121
            // Skip root package
122
            if ($package instanceof RootPackageInterface) {
123
                continue;
124
            }
125
126
            foreach ($package->getRequires() as $link) {
127
                if ($link->getTarget() === $needle->getName() && !in_array($link, $depends, true)) {
128
                    $depends[] = $link;
129
                }
130
            }
131
        }
132
133
        return $depends;
134
    }
135
136
    /**
137
     * @param array $output
138
     * @param bool  $showLinks
139
     */
140
    private function createNotUpToDateOutput(array &$output, $showLinks = true)
141
    {
142
        $outdatedPackagesCount = count($this->outdatedPackages);
143
        $output[] = sprintf(
144
            '<warning>%d %s not up to date:</warning>',
145
            $outdatedPackagesCount,
146
            1 != $outdatedPackagesCount ? 'packages are' : 'package is'
147
        );
148
        $output[] = '';
149
150
        foreach ($this->outdatedPackages as $outdatedPackage) {
151
            $output[] = sprintf(
152
                '  - <info>%s</info> (<comment>%s</comment>) latest is <comment>%s</comment>',
153
                $outdatedPackage->getActual()->getPrettyName(),
154
                $outdatedPackage->getActual()->getPrettyVersion(),
155
                $outdatedPackage->getLast()->getPrettyVersion()
156
            );
157
158
            if (true === $showLinks) {
159
                foreach ($outdatedPackage->getLinks() as $depend) {
160
                    $output[] = sprintf(
161
                        '    Required by <info>%s</info> (<comment>%s</comment>)',
162
                        $depend->getSource(),
163
                        $depend->getPrettyConstraint()
164
                    );
165
                }
166
            }
167
168
            $output[] = '';
169
        }
170
    }
171
}
172