Completed
Pull Request — master (#43)
by Pádraic
02:52 queued 52s
created

GithubStrategy::allowMajorVersionUpdates()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
/**
3
 * Humbug
4
 *
5
 * @category   Humbug
6
 * @package    Humbug
7
 * @copyright  Copyright (c) 2015 Pádraic Brady (http://blog.astrumfutura.com)
8
 * @license    https://github.com/padraic/phar-updater/blob/master/LICENSE New BSD License
9
 *
10
 * This class is partially patterned after Composer's self-update.
11
 */
12
13
namespace Humbug\SelfUpdate\Strategy;
14
15
use Humbug\SelfUpdate\Updater;
16
use Humbug\SelfUpdate\VersionParser;
17
use Humbug\SelfUpdate\Exception\HttpRequestException;
18
use Humbug\SelfUpdate\Exception\InvalidArgumentException;
19
use Humbug\SelfUpdate\Exception\JsonParsingException;
20
21
class GithubStrategy implements StrategyInterface
22
{
23
    const API_URL = 'https://packagist.org/packages/%s.json';
24
25
    const STABLE = 'stable';
26
27
    const UNSTABLE = 'unstable';
28
29
    const ANY = 'any';
30
31
    /**
32
     * @var string
33
     */
34
    private $localVersion;
35
36
    /**
37
     * @var string
38
     */
39
    private $remoteVersion;
40
41
    /**
42
     * @var string
43
     */
44
    private $remoteUrl;
45
46
    /**
47
     * @var string
48
     */
49
    private $pharName;
50
51
    /**
52
     * @var string
53
     */
54
    private $packageName;
55
56
    /**
57
     * @var string
58
     */
59
    private $stability = self::STABLE;
60
61
    /**
62
     * @var boolean
63
     */
64
    private $allowMajor = false;
65
66
    /**
67
     * Download the remote Phar file.
68
     *
69
     * @param Updater $updater
70
     * @return void
71
     */
72 View Code Duplication
    public function download(Updater $updater)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
73
    {
74
        /** Switch remote request errors to HttpRequestExceptions */
75
        set_error_handler(array($updater, 'throwHttpRequestException'));
76
        $result = file_get_contents($this->remoteUrl);
77
        restore_error_handler();
78
        if (false === $result) {
79
            throw new HttpRequestException(sprintf(
80
                'Request to URL failed: %s', $this->remoteUrl
81
            ));
82
        }
83
84
        file_put_contents($updater->getTempPharFile(), $result);
85
    }
86
87
    /**
88
     * Retrieve the current version available remotely.
89
     *
90
     * @param Updater $updater
91
     * @return string|bool
92
     */
93
    public function getCurrentRemoteVersion(Updater $updater)
94
    {
95
        /** Switch remote request errors to HttpRequestExceptions */
96
        set_error_handler(array($updater, 'throwHttpRequestException'));
97
        $packageUrl = $this->getApiUrl();
98
        $package = json_decode(file_get_contents($packageUrl), true);
99
        restore_error_handler();
100
101
        if (null === $package || json_last_error() !== JSON_ERROR_NONE) {
102
            throw new JsonParsingException(
103
                'Error parsing JSON package data'
104
                . (function_exists('json_last_error_msg') ? ': ' . json_last_error_msg() : '')
105
            );
106
        }
107
108
        $versions = array_keys($package['package']['versions']);
109
110
        if (false === $this->allowMajor) {
111
            $versions = $this->filterByLocalMajorVersion($versions);
112
        }
113
114
        $versionParser = new VersionParser($versions);
115
        if ($this->getStability() === self::STABLE) {
116
            $this->remoteVersion = $versionParser->getMostRecentStable();
117
        } elseif ($this->getStability() === self::UNSTABLE) {
118
            $this->remoteVersion = $versionParser->getMostRecentUnstable();
119
        } else {
120
            $this->remoteVersion = $versionParser->getMostRecentAll();
121
        }
122
123
        /**
124
         * Setup remote URL if there's an actual version to download
125
         */
126
        if (!empty($this->remoteVersion)) {
127
            $this->remoteUrl = $this->getDownloadUrl($package);
128
        }
129
130
        return $this->remoteVersion;
131
    }
132
133
    /**
134
     * Retrieve the current version of the local phar file.
135
     *
136
     * @param Updater $updater
137
     * @return string
138
     */
139
    public function getCurrentLocalVersion(Updater $updater)
140
    {
141
        return $this->localVersion;
142
    }
143
144
    /**
145
     * Set version string of the local phar
146
     *
147
     * @param string $version
148
     * @return self
149
     */
150
    public function setCurrentLocalVersion($version)
151
    {
152
        $this->localVersion = $version;
153
        return $this;
154
    }
155
156
    /**
157
     * Set Package name
158
     *
159
     * @param string $name
160
     * @return self
161
     */
162
    public function setPackageName($name)
163
    {
164
        $this->packageName = $name;
165
        return $this;
166
    }
167
168
    /**
169
     * Get Package name
170
     *
171
     * @return string
172
     */
173
    public function getPackageName()
174
    {
175
        return $this->packageName;
176
    }
177
178
    /**
179
     * Set phar file's name
180
     *
181
     * @param string $name
182
     * @return self
183
     */
184
    public function setPharName($name)
185
    {
186
        $this->pharName = $name;
187
        return $this;
188
    }
189
190
    /**
191
     * Get phar file's name
192
     *
193
     * @return string
194
     */
195
    public function getPharName()
196
    {
197
        return $this->pharName;
198
    }
199
200
    /**
201
     * Set target stability
202
     *
203
     * @param string $stability
204
     * @return self
205
     */
206
    public function setStability($stability)
207
    {
208
        if ($stability !== self::STABLE && $stability !== self::UNSTABLE && $stability !== self::ANY) {
209
            throw new InvalidArgumentException(
210
                'Invalid stability value. Must be one of "stable", "unstable" or "any".'
211
            );
212
        }
213
        $this->stability = $stability;
214
        return $this;
215
    }
216
217
    /**
218
     * Get target stability
219
     *
220
     * @return string
221
     */
222
    public function getStability()
223
    {
224
        return $this->stability;
225
    }
226
227
    /**
228
     * @return self
229
     */
230
    public function allowMajorVersionUpdates()
231
    {
232
        $this->allowMajor = true;
233
        return $this;
234
    }
235
236
    /**
237
     * @return string
238
     */
239
    protected function getApiUrl()
240
    {
241
        return sprintf(self::API_URL, $this->getPackageName());
242
    }
243
244
    /**
245
     * @param  array  $package
246
     * @return string
247
     */
248
    protected function getDownloadUrl(array $package)
249
    {
250
        $baseUrl = preg_replace(
251
            '{\.git$}',
252
            '',
253
            $package['package']['versions'][$this->remoteVersion]['source']['url']
254
        );
255
        $downloadUrl = sprintf(
256
            '%s/releases/download/%s/%s',
257
            $baseUrl,
258
            $this->remoteVersion,
259
            $this->getPharName()
260
        );
261
        return $downloadUrl;
262
    }
263
264
    /**
265
     * Filter a list of versions to those that match the current local version.
266
     *
267
     * @param string[] $versions
268
     * @return string[]
269
     */
270
    private function filterByLocalMajorVersion(array $versions)
271
    {
272
        list($localMajorVersion, ) = explode('.', $this->localVersion, 2);
273
274
        return array_filter($versions, function ($version) use ($localMajorVersion) {
275
            list($majorVersion, ) = explode('.', $version, 2);
276
            return $majorVersion === $localMajorVersion;
277
        });
278
    }
279
}
280