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

VersionsCheck::createNotUpToDateOutput()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 29
rs 8.439
cc 6
eloc 18
nc 4
nop 2
1
<?php
2
3
namespace SLLH\ComposerVersionsCheck;
4
5
use Composer\Composer;
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
     * @var DependsCommandWrapper
31
     */
32
    private $dependsCommandWrapper;
33
34
    /**
35
     * @param DependsCommandWrapper $dependsCommandWrapper
36
     */
37
    public function __construct(DependsCommandWrapper $dependsCommandWrapper = null)
38
    {
39
        if (null === $dependsCommandWrapper) {
40
            @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
41
                'Instantiate '.__CLASS__.' without SLLH\ComposerVersionsCheck\DependsCommandWrapper as argument is deprecated since 1.2 and will be removed in 2.0.',
42
                E_USER_DEPRECATED
43
            );
44
        }
45
46
        $this->dependsCommandWrapper = $dependsCommandWrapper;
47
    }
48
49
    /**
50
     * @param ArrayRepository             $distRepository
51
     * @param WritableRepositoryInterface $localRepository
52
     * @param RootPackageInterface        $rootPackage
53
     */
54
    public function checkPackages(ArrayRepository $distRepository, WritableRepositoryInterface $localRepository, RootPackageInterface $rootPackage)
55
    {
56
        $packages = $localRepository->getPackages();
57
        foreach ($packages as $package) {
58
            // Old composer versions BC
59
            $versionConstraint = class_exists('Composer\Semver\Constraint\Constraint')
60
                ? new Constraint('>', $package->getVersion())
61
                : 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...
62
            ;
63
64
            $higherPackages = $distRepository->findPackages($package->getName(), $versionConstraint);
65
            // Remove not stable packages if unwanted
66
            if (true === $rootPackage->getPreferStable()) {
67
                $higherPackages = array_filter($higherPackages, function (PackageInterface $package) {
68
                    return 'stable' === $package->getStability();
69
                });
70
            }
71
            if (count($higherPackages) > 0) {
72
                // PHP 5.3 BC
73
                $that = $this;
74
                // Sort packages by highest version to lowest
75
                usort($higherPackages, function (PackageInterface $p1, PackageInterface $p2) use ($that) {
76
                    return $that->versionCompare($p1->getVersion(), '<', $p2->getVersion());
77
                });
78
                // Push actual and last package on outdated array
79
                array_push($this->outdatedPackages, new OutdatedPackage($package, $higherPackages[0]));
80
            }
81
        }
82
    }
83
84
    /**
85
     * @param bool $showDepends
86
     *
87
     * @return string
88
     */
89
    public function getOutput($showDepends = true)
90
    {
91
        $output = array();
92
93
        if (0 === count($this->outdatedPackages)) {
94
            $output[] = '<info>All packages are up to date.</info>';
95
        } else {
96
            $this->createNotUpToDateOutput($output, $showDepends);
97
        }
98
99
        return implode(PHP_EOL, $output).PHP_EOL;
100
    }
101
102
    /**
103
     * Version comparator bridge to handle BC with old composer versions.
104
     *
105
     * This method is public only for PHP 5.3 BC and SHOULD NOT be used.
106
     * Deprecate it and remove it on next major when PHP 5.3 support will be droped.
107
     *
108
     * @param string $version1
109
     * @param string $operator
110
     * @param string $version2
111
     *
112
     * @return bool
113
     */
114
    public function versionCompare($version1, $operator, $version2)
115
    {
116
        if (!class_exists('Composer\Semver\Comparator')) {
117
            $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...
118
119
            return $this->oldComparator->versionCompare($version1, $version2, $operator);
120
        }
121
122
        return Comparator::compare($version1, $operator, $version2);
123
    }
124
125
    /**
126
     * @param array $output
127
     * @param bool  $showDepends
128
     */
129
    private function createNotUpToDateOutput(array &$output, $showDepends = true)
130
    {
131
        $outdatedPackagesCount = count($this->outdatedPackages);
132
        $output[] = sprintf(
133
            '<warning>%d %s not up to date:</warning>',
134
            $outdatedPackagesCount,
135
            1 != $outdatedPackagesCount ? 'packages are' : 'package is'
136
        );
137
        $output[] = '';
138
139
        foreach ($this->outdatedPackages as $outdatedPackage) {
140
            $output[] = sprintf(
141
                '  - <info>%s</info> (<comment>%s</comment>) latest is <comment>%s</comment>',
142
                $outdatedPackage->getActual()->getPrettyName(),
143
                $outdatedPackage->getActual()->getPrettyVersion(),
144
                $outdatedPackage->getLast()->getPrettyVersion()
145
            );
146
147
            // `null !== $this->dependsCommandWrapper` is for BC. To be removed on 2.0
148
            if (true === $showDepends && null !== $this->dependsCommandWrapper) {
149
                try {
150
                    $output = array_merge($output, $this->dependsCommandWrapper->dependsOutput($outdatedPackage->getActual()));
151
                } catch (\InvalidArgumentException $e) {
152
                } // Do not manager depends command error. Simply try to get an output.
153
            }
154
155
            $output[] = '';
156
        }
157
    }
158
}
159