Completed
Pull Request — master (#30)
by
unknown
09:23 queued 02:28
created

CheckComposerUpdatesTask::run()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace BringYourOwnIdeas\UpdateChecker\Tasks;
4
5
use BringYourOwnIdeas\Maintenance\Tasks\UpdatePackageInfoTask;
6
use BringYourOwnIdeas\Maintenance\Util\ComposerLoader;
7
use BringYourOwnIdeas\UpdateChecker\UpdateChecker;
8
use Composer\Composer;
9
use Composer\Package\Link;
10
use Composer\Repository\ArrayRepository;
11
use Composer\Repository\BaseRepository;
12
use Composer\Repository\CompositeRepository;
13
use SilverStripe\Control\HTTPRequest;
14
use SilverStripe\Core\Config\Config;
15
use SilverStripe\Control\Director;
16
use SilverStripe\Dev\BuildTask;
17
18
/**
19
 * Task which does the actual checking of updates
20
 *
21
 * Originally from https://github.com/XploreNet/silverstripe-composerupdates
22
 *
23
 * @author Matt Dwen
24
 * @license MIT
25
 */
26
class CheckComposerUpdatesTask extends BuildTask
27
{
28
    /**
29
     * @var string
30
     */
31
    protected $title = 'Composer update checker';
32
33
    /**
34
     * @var string
35
     */
36
    protected $description = 'Checks if any composer dependencies can be updated.';
37
38
    private static $segment = "CheckComposerUpdates";
0 ignored issues
show
introduced by
The private property $segment is not used, and could be removed.
Loading history...
39
40
    private static $dependencies = [
0 ignored issues
show
introduced by
The private property $dependencies is not used, and could be removed.
Loading history...
41
        'ComposerLoader' => '%$BringYourOwnIdeas\\Maintenance\\Util\\ComposerLoader',
42
        'UpdateChecker' => '%$BringYourOwnIdeas\\UpdateChecker\\UpdateChecker',
43
    ];
44
45
    /**
46
     * @var ComposerLoader
47
     */
48
    protected $composerLoader;
49
50
    /**
51
     * @var UpdateChecker
52
     */
53
    protected $updateChecker;
54
55
    /**
56
     * Runs the actual steps to verify if there are updates available
57
     *
58
     * @param HTTPRequest $request
59
     */
60
    public function run($request)
61
    {
62
        $packages = $this->getPackages();
63
64
        // Run through the packages and check each for updates
65
        foreach ($packages as $packageData) {
66
            $this->getUpdateChecker()->checkForUpdates(
67
                $packageData['package'],
68
                $packageData['constraint']
69
            );
70
        }
71
72
        $this->message('The task finished running. You can find the updated information in the database now.');
73
    }
74
75
    /**
76
     * Retrieve an array of primary composer dependencies from composer.json.
77
     *
78
     * Packages are filtered by allowed type.
79
     *
80
     * @return array[]
81
     */
82
    protected function getPackages()
83
    {
84
        /** @var Composer $composer */
85
        $composer = $this->getComposerLoader()->getComposer();
86
87
        /** @var BaseRepository $repository */
88
        $repository = new CompositeRepository([
89
            new ArrayRepository([$composer->getPackage()]),
90
            $composer->getRepositoryManager()->getLocalRepository(),
91
        ]);
92
93
        $packages = [];
94
        foreach ($repository->getPackages() as $package) {
95
            // Filter out packages that are not "allowed types"
96
            if (!$this->isAllowedType($package->getType())) {
97
                continue;
98
            }
99
100
            // Find the constraint used for installation
101
            $constraint = $this->getInstalledConstraint($repository, $package->getName());
102
            $packages[$package->getName()] = [
103
                'constraint' => $constraint,
104
                'package' => $package,
105
            ];
106
        }
107
        return $packages;
108
    }
109
110
    /**
111
     * Find all dependency constraints for the given package in the current repository and return the strictest one
112
     *
113
     * @param BaseRepository $repository
114
     * @param string $packageName
115
     * @return string
116
     */
117
    protected function getInstalledConstraint(BaseRepository $repository, $packageName)
118
    {
119
        $constraints = [];
120
        foreach ($repository->getDependents($packageName) as $dependent) {
121
            /** @var Link $link */
122
            list (, $link) = $dependent;
123
            $constraints[] = $link->getPrettyConstraint();
124
        }
125
126
        usort($constraints, 'version_compare');
127
128
        return array_pop($constraints);
129
    }
130
131
    /**
132
     * Check whether the package type is "allowed", which will include it in reports. If the type is not allowed
133
     * then the package will be skipped.
134
     *
135
     * @param string $type
136
     * @return bool
137
     */
138
    protected function isAllowedType($type)
139
    {
140
        $allowedTypes = (array) Config::inst()->get(UpdatePackageInfoTask::class, 'allowed_types');
141
142
        return in_array($type, $allowedTypes);
143
    }
144
145
    /**
146
     * prints a message during the run of the task
147
     *
148
     * @param string $text
149
     */
150
    protected function message($text)
151
    {
152
        if (!Director::is_cli()) {
153
            $text = '<p>' . $text . '</p>';
154
        }
155
156
        echo $text . PHP_EOL;
157
    }
158
159
    /**
160
     * @param ComposerLoader $composerLoader
161
     * @return $this
162
     */
163
    public function setComposerLoader(ComposerLoader $composerLoader)
164
    {
165
        $this->composerLoader = $composerLoader;
166
        return $this;
167
    }
168
169
    /**
170
     * @return ComposerLoader
171
     */
172
    public function getComposerLoader()
173
    {
174
        return $this->composerLoader;
175
    }
176
177
    /**
178
     * @param UpdateChecker $updateChecker
179
     * @return $this
180
     */
181
    public function setUpdateChecker(UpdateChecker $updateChecker)
182
    {
183
        $this->updateChecker = $updateChecker;
184
        return $this;
185
    }
186
187
    /**
188
     * @return UpdateChecker
189
     */
190
    public function getUpdateChecker()
191
    {
192
        return $this->updateChecker;
193
    }
194
}
195