Subversion Repositories Applications.gtt

Rev

Rev 187 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
187 mathias 1
<?php
2
/**
3
 * PEAR_REST_13
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * @category   pear
8
 * @package    PEAR
9
 * @author     Greg Beaver <cellog@php.net>
10
 * @copyright  1997-2009 The Authors
11
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
12
 * @link       http://pear.php.net/package/PEAR
13
 * @since      File available since Release 1.4.0a12
14
 */
15
 
16
/**
17
 * For downloading REST xml/txt files
18
 */
19
require_once 'PEAR/REST.php';
20
require_once 'PEAR/REST/10.php';
21
 
22
/**
23
 * Implement REST 1.3
24
 *
25
 * @category   pear
26
 * @package    PEAR
27
 * @author     Greg Beaver <cellog@php.net>
28
 * @copyright  1997-2009 The Authors
29
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
30
 * @version    Release: 1.10.1
31
 * @link       http://pear.php.net/package/PEAR
32
 * @since      Class available since Release 1.4.0a12
33
 */
34
class PEAR_REST_13 extends PEAR_REST_10
35
{
36
    /**
37
     * Retrieve information about a remote package to be downloaded from a REST server
38
     *
39
     * This is smart enough to resolve the minimum PHP version dependency prior to download
40
     * @param string $base The uri to prepend to all REST calls
41
     * @param array $packageinfo an array of format:
42
     * <pre>
43
     *  array(
44
     *   'package' => 'packagename',
45
     *   'channel' => 'channelname',
46
     *  ['state' => 'alpha' (or valid state),]
47
     *  -or-
48
     *  ['version' => '1.whatever']
49
     * </pre>
50
     * @param string $prefstate Current preferred_state config variable value
51
     * @param bool $installed the installed version of this package to compare against
52
     * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
53
     */
54
    function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
55
    {
56
        $states = $this->betterStates($prefstate, true);
57
        if (!$states) {
58
            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
59
        }
60
 
61
        $channel  = $packageinfo['channel'];
62
        $package  = $packageinfo['package'];
63
        $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
64
        $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
65
        $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
66
 
67
        $info = $this->_rest->retrieveData($restFile, false, false, $channel);
68
        if (PEAR::isError($info)) {
69
            return PEAR::raiseError('No releases available for package "' .
70
                $channel . '/' . $package . '"');
71
        }
72
 
73
        if (!isset($info['r'])) {
74
            return false;
75
        }
76
 
77
        $release = $found = false;
78
        if (!is_array($info['r']) || !isset($info['r'][0])) {
79
            $info['r'] = array($info['r']);
80
        }
81
 
82
        $skippedphp = false;
83
        foreach ($info['r'] as $release) {
84
            if (!isset($this->_rest->_options['force']) && ($installed &&
85
                  version_compare($release['v'], $installed, '<'))) {
86
                continue;
87
            }
88
 
89
            if (isset($state)) {
90
                // try our preferred state first
91
                if ($release['s'] == $state) {
92
                    if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
93
                        // skip releases that require a PHP version newer than our PHP version
94
                        $skippedphp = $release;
95
                        continue;
96
                    }
97
                    $found = true;
98
                    break;
99
                }
100
 
101
                // see if there is something newer and more stable
102
                // bug #7221
103
                if (in_array($release['s'], $this->betterStates($state), true)) {
104
                    if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
105
                        // skip releases that require a PHP version newer than our PHP version
106
                        $skippedphp = $release;
107
                        continue;
108
                    }
109
                    $found = true;
110
                    break;
111
                }
112
            } elseif (isset($version)) {
113
                if ($release['v'] == $version) {
114
                    if (!isset($this->_rest->_options['force']) &&
115
                          !isset($version) &&
116
                          version_compare($release['m'], phpversion(), '>')) {
117
                        // skip releases that require a PHP version newer than our PHP version
118
                        $skippedphp = $release;
119
                        continue;
120
                    }
121
                    $found = true;
122
                    break;
123
                }
124
            } else {
125
                if (in_array($release['s'], $states)) {
126
                    if (version_compare($release['m'], phpversion(), '>')) {
127
                        // skip releases that require a PHP version newer than our PHP version
128
                        $skippedphp = $release;
129
                        continue;
130
                    }
131
                    $found = true;
132
                    break;
133
                }
134
            }
135
        }
136
 
137
        if (!$found && $skippedphp) {
138
            $found = null;
139
        }
140
 
141
        return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
142
    }
143
 
144
    function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
145
                               $prefstate = 'stable', $installed = false, $channel = false)
146
    {
147
        $states = $this->betterStates($prefstate, true);
148
        if (!$states) {
149
            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
150
        }
151
 
152
        $channel  = $dependency['channel'];
153
        $package  = $dependency['name'];
154
        $state    = isset($dependency['state'])   ? $dependency['state']   : null;
155
        $version  = isset($dependency['version']) ? $dependency['version'] : null;
156
        $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
157
 
158
        $info = $this->_rest->retrieveData($restFile, false, false, $channel);
159
        if (PEAR::isError($info)) {
160
            return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
161
                . '" dependency "' . $channel . '/' . $package . '" has no releases');
162
        }
163
 
164
        if (!is_array($info) || !isset($info['r'])) {
165
            return false;
166
        }
167
 
168
        $exclude = array();
169
        $min = $max = $recommended = false;
170
        if ($xsdversion == '1.0') {
171
            $pinfo['package'] = $dependency['name'];
172
            $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
173
            switch ($dependency['rel']) {
174
                case 'ge' :
175
                    $min = $dependency['version'];
176
                break;
177
                case 'gt' :
178
                    $min = $dependency['version'];
179
                    $exclude = array($dependency['version']);
180
                break;
181
                case 'eq' :
182
                    $recommended = $dependency['version'];
183
                break;
184
                case 'lt' :
185
                    $max = $dependency['version'];
186
                    $exclude = array($dependency['version']);
187
                break;
188
                case 'le' :
189
                    $max = $dependency['version'];
190
                break;
191
                case 'ne' :
192
                    $exclude = array($dependency['version']);
193
                break;
194
            }
195
        } else {
196
            $pinfo['package'] = $dependency['name'];
197
            $min = isset($dependency['min']) ? $dependency['min'] : false;
198
            $max = isset($dependency['max']) ? $dependency['max'] : false;
199
            $recommended = isset($dependency['recommended']) ?
200
                $dependency['recommended'] : false;
201
            if (isset($dependency['exclude'])) {
202
                if (!isset($dependency['exclude'][0])) {
203
                    $exclude = array($dependency['exclude']);
204
                }
205
            }
206
        }
207
 
208
        $skippedphp = $found = $release = false;
209
        if (!is_array($info['r']) || !isset($info['r'][0])) {
210
            $info['r'] = array($info['r']);
211
        }
212
 
213
        foreach ($info['r'] as $release) {
214
            if (!isset($this->_rest->_options['force']) && ($installed &&
215
                  version_compare($release['v'], $installed, '<'))) {
216
                continue;
217
            }
218
 
219
            if (in_array($release['v'], $exclude)) { // skip excluded versions
220
                continue;
221
            }
222
 
223
            // allow newer releases to say "I'm OK with the dependent package"
224
            if ($xsdversion == '2.0' && isset($release['co'])) {
225
                if (!is_array($release['co']) || !isset($release['co'][0])) {
226
                    $release['co'] = array($release['co']);
227
                }
228
 
229
                foreach ($release['co'] as $entry) {
230
                    if (isset($entry['x']) && !is_array($entry['x'])) {
231
                        $entry['x'] = array($entry['x']);
232
                    } elseif (!isset($entry['x'])) {
233
                        $entry['x'] = array();
234
                    }
235
 
236
                    if ($entry['c'] == $deppackage['channel'] &&
237
                          strtolower($entry['p']) == strtolower($deppackage['package']) &&
238
                          version_compare($deppackage['version'], $entry['min'], '>=') &&
239
                          version_compare($deppackage['version'], $entry['max'], '<=') &&
240
                          !in_array($release['v'], $entry['x'])) {
241
                        if (version_compare($release['m'], phpversion(), '>')) {
242
                            // skip dependency releases that require a PHP version
243
                            // newer than our PHP version
244
                            $skippedphp = $release;
245
                            continue;
246
                        }
247
 
248
                        $recommended = $release['v'];
249
                        break;
250
                    }
251
                }
252
            }
253
 
254
            if ($recommended) {
255
                if ($release['v'] != $recommended) { // if we want a specific
256
                    // version, then skip all others
257
                    continue;
258
                }
259
 
260
                if (!in_array($release['s'], $states)) {
261
                    // the stability is too low, but we must return the
262
                    // recommended version if possible
263
                    return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
264
                }
265
            }
266
 
267
            if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
268
                continue;
269
            }
270
 
271
            if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
272
                continue;
273
            }
274
 
275
            if ($installed && version_compare($release['v'], $installed, '<')) {
276
                continue;
277
            }
278
 
279
            if (in_array($release['s'], $states)) { // if in the preferred state...
280
                if (version_compare($release['m'], phpversion(), '>')) {
281
                    // skip dependency releases that require a PHP version
282
                    // newer than our PHP version
283
                    $skippedphp = $release;
284
                    continue;
285
                }
286
 
287
                $found = true; // ... then use it
288
                break;
289
            }
290
        }
291
 
292
        if (!$found && $skippedphp) {
293
            $found = null;
294
        }
295
 
296
        return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
297
    }
298
 
299
    /**
300
     * List package upgrades but take the PHP version into account.
301
     */
302
    function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
303
    {
304
        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
305
        if (PEAR::isError($packagelist)) {
306
            return $packagelist;
307
        }
308
 
309
        $ret = array();
310
        if (!is_array($packagelist) || !isset($packagelist['p'])) {
311
            return $ret;
312
        }
313
 
314
        if (!is_array($packagelist['p'])) {
315
            $packagelist['p'] = array($packagelist['p']);
316
        }
317
 
318
        foreach ($packagelist['p'] as $package) {
319
            if (!isset($installed[strtolower($package)])) {
320
                continue;
321
            }
322
 
323
            $inst_version = $reg->packageInfo($package, 'version', $channel);
324
            $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
325
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
326
            $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
327
                '/allreleases2.xml', false, false, $channel);
328
            PEAR::popErrorHandling();
329
            if (PEAR::isError($info)) {
330
                continue; // no remote releases
331
            }
332
 
333
            if (!isset($info['r'])) {
334
                continue;
335
            }
336
 
337
            $release = $found = false;
338
            if (!is_array($info['r']) || !isset($info['r'][0])) {
339
                $info['r'] = array($info['r']);
340
            }
341
 
342
            // $info['r'] is sorted by version number
343
            usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
344
            foreach ($info['r'] as $release) {
345
                if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
346
                    // not newer than the one installed
347
                    break;
348
                }
349
                if (version_compare($release['m'], phpversion(), '>')) {
350
                    // skip dependency releases that require a PHP version
351
                    // newer than our PHP version
352
                    continue;
353
                }
354
 
355
                // new version > installed version
356
                if (!$pref_state) {
357
                    // every state is a good state
358
                    $found = true;
359
                    break;
360
                } else {
361
                    $new_state = $release['s'];
362
                    // if new state >= installed state: go
363
                    if (in_array($new_state, $this->betterStates($inst_state, true))) {
364
                        $found = true;
365
                        break;
366
                    } else {
367
                        // only allow to lower the state of package,
368
                        // if new state >= preferred state: go
369
                        if (in_array($new_state, $this->betterStates($pref_state, true))) {
370
                            $found = true;
371
                            break;
372
                        }
373
                    }
374
                }
375
            }
376
 
377
            if (!$found) {
378
                continue;
379
            }
380
 
381
            $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
382
                $release['v'] . '.xml', false, false, $channel);
383
            if (PEAR::isError($relinfo)) {
384
                return $relinfo;
385
            }
386
 
387
            $ret[$package] = array(
388
                'version'  => $release['v'],
389
                'state'    => $release['s'],
390
                'filesize' => $relinfo['f'],
391
            );
392
        }
393
 
394
        return $ret;
395
    }
396
}