Subversion Repositories Applications.gtt

Rev

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

Rev Author Line No. Line
94 jpm 1
<?php
2
/**
3
 * PEAR_Dependency2, advanced dependency validation
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * @category   pear
8
 * @package    PEAR
9
 * @author     Greg Beaver <cellog@php.net>
187 mathias 10
 * @copyright  1997-2009 The Authors
11
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
94 jpm 12
 * @link       http://pear.php.net/package/PEAR
13
 * @since      File available since Release 1.4.0a1
14
 */
15
 
16
/**
17
 * Required for the PEAR_VALIDATE_* constants
18
 */
19
require_once 'PEAR/Validate.php';
20
 
21
/**
22
 * Dependency check for PEAR packages
23
 *
24
 * This class handles both version 1.0 and 2.0 dependencies
25
 * WARNING: *any* changes to this class must be duplicated in the
26
 * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
27
 * or unit tests will not actually validate the changes
28
 * @category   pear
29
 * @package    PEAR
30
 * @author     Greg Beaver <cellog@php.net>
187 mathias 31
 * @copyright  1997-2009 The Authors
32
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
33
 * @version    Release: 1.10.1
94 jpm 34
 * @link       http://pear.php.net/package/PEAR
35
 * @since      Class available since Release 1.4.0a1
36
 */
37
class PEAR_Dependency2
38
{
39
    /**
40
     * One of the PEAR_VALIDATE_* states
41
     * @see PEAR_VALIDATE_NORMAL
42
     * @var integer
43
     */
44
    var $_state;
187 mathias 45
 
94 jpm 46
    /**
47
     * Command-line options to install/upgrade/uninstall commands
48
     * @param array
49
     */
50
    var $_options;
187 mathias 51
 
94 jpm 52
    /**
53
     * @var OS_Guess
54
     */
55
    var $_os;
187 mathias 56
 
94 jpm 57
    /**
58
     * @var PEAR_Registry
59
     */
60
    var $_registry;
187 mathias 61
 
94 jpm 62
    /**
63
     * @var PEAR_Config
64
     */
65
    var $_config;
187 mathias 66
 
94 jpm 67
    /**
68
     * @var PEAR_DependencyDB
69
     */
70
    var $_dependencydb;
187 mathias 71
 
94 jpm 72
    /**
73
     * Output of PEAR_Registry::parsedPackageName()
74
     * @var array
75
     */
76
    var $_currentPackage;
187 mathias 77
 
94 jpm 78
    /**
79
     * @param PEAR_Config
80
     * @param array installation options
81
     * @param array format of PEAR_Registry::parsedPackageName()
82
     * @param int installation state (one of PEAR_VALIDATE_*)
83
     */
187 mathias 84
    function __construct(&$config, $installoptions, $package,
94 jpm 85
                              $state = PEAR_VALIDATE_INSTALLING)
86
    {
87
        $this->_config = &$config;
88
        if (!class_exists('PEAR_DependencyDB')) {
89
            require_once 'PEAR/DependencyDB.php';
90
        }
187 mathias 91
 
94 jpm 92
        if (isset($installoptions['packagingroot'])) {
93
            // make sure depdb is in the right location
94
            $config->setInstallRoot($installoptions['packagingroot']);
95
        }
187 mathias 96
 
94 jpm 97
        $this->_registry = &$config->getRegistry();
98
        $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
99
        if (isset($installoptions['packagingroot'])) {
100
            $config->setInstallRoot(false);
101
        }
187 mathias 102
 
94 jpm 103
        $this->_options = $installoptions;
104
        $this->_state = $state;
105
        if (!class_exists('OS_Guess')) {
106
            require_once 'OS/Guess.php';
107
        }
187 mathias 108
 
94 jpm 109
        $this->_os = new OS_Guess;
110
        $this->_currentPackage = $package;
111
    }
112
 
113
    function _getExtraString($dep)
114
    {
115
        $extra = ' (';
116
        if (isset($dep['uri'])) {
117
            return '';
118
        }
187 mathias 119
 
94 jpm 120
        if (isset($dep['recommended'])) {
121
            $extra .= 'recommended version ' . $dep['recommended'];
122
        } else {
123
            if (isset($dep['min'])) {
124
                $extra .= 'version >= ' . $dep['min'];
125
            }
187 mathias 126
 
94 jpm 127
            if (isset($dep['max'])) {
128
                if ($extra != ' (') {
129
                    $extra .= ', ';
130
                }
131
                $extra .= 'version <= ' . $dep['max'];
132
            }
187 mathias 133
 
94 jpm 134
            if (isset($dep['exclude'])) {
135
                if (!is_array($dep['exclude'])) {
136
                    $dep['exclude'] = array($dep['exclude']);
137
                }
187 mathias 138
 
94 jpm 139
                if ($extra != ' (') {
140
                    $extra .= ', ';
141
                }
187 mathias 142
 
94 jpm 143
                $extra .= 'excluded versions: ';
144
                foreach ($dep['exclude'] as $i => $exclude) {
145
                    if ($i) {
146
                        $extra .= ', ';
147
                    }
148
                    $extra .= $exclude;
149
                }
150
            }
151
        }
187 mathias 152
 
94 jpm 153
        $extra .= ')';
154
        if ($extra == ' ()') {
155
            $extra = '';
156
        }
187 mathias 157
 
94 jpm 158
        return $extra;
159
    }
160
 
161
    /**
162
     * This makes unit-testing a heck of a lot easier
163
     */
164
    function getPHP_OS()
165
    {
166
        return PHP_OS;
167
    }
168
 
169
    /**
170
     * This makes unit-testing a heck of a lot easier
171
     */
172
    function getsysname()
173
    {
174
        return $this->_os->getSysname();
175
    }
176
 
177
    /**
178
     * Specify a dependency on an OS.  Use arch for detailed os/processor information
179
     *
180
     * There are two generic OS dependencies that will be the most common, unix and windows.
181
     * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
182
     */
183
    function validateOsDependency($dep)
184
    {
187 mathias 185
        if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
94 jpm 186
            return true;
187
        }
187 mathias 188
 
94 jpm 189
        if ($dep['name'] == '*') {
190
            return true;
191
        }
187 mathias 192
 
193
        $not = isset($dep['conflicts']) ? true : false;
94 jpm 194
        switch (strtolower($dep['name'])) {
195
            case 'windows' :
196
                if ($not) {
197
                    if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
187 mathias 198
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 199
                            return $this->raiseError("Cannot install %s on Windows");
200
                        }
187 mathias 201
 
202
                        return $this->warning("warning: Cannot install %s on Windows");
94 jpm 203
                    }
204
                } else {
205
                    if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
187 mathias 206
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 207
                            return $this->raiseError("Can only install %s on Windows");
208
                        }
187 mathias 209
 
210
                        return $this->warning("warning: Can only install %s on Windows");
94 jpm 211
                    }
212
                }
213
            break;
214
            case 'unix' :
215
                $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
216
                if ($not) {
217
                    if (in_array($this->getSysname(), $unices)) {
187 mathias 218
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 219
                            return $this->raiseError("Cannot install %s on any Unix system");
220
                        }
187 mathias 221
 
222
                        return $this->warning( "warning: Cannot install %s on any Unix system");
94 jpm 223
                    }
224
                } else {
225
                    if (!in_array($this->getSysname(), $unices)) {
187 mathias 226
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 227
                            return $this->raiseError("Can only install %s on a Unix system");
228
                        }
187 mathias 229
 
230
                        return $this->warning("warning: Can only install %s on a Unix system");
94 jpm 231
                    }
232
                }
233
            break;
234
            default :
235
                if ($not) {
236
                    if (strtolower($dep['name']) == strtolower($this->getSysname())) {
237
                        if (!isset($this->_options['nodeps']) &&
238
                              !isset($this->_options['force'])) {
239
                            return $this->raiseError('Cannot install %s on ' . $dep['name'] .
240
                                ' operating system');
241
                        }
187 mathias 242
 
243
                        return $this->warning('warning: Cannot install %s on ' .
244
                            $dep['name'] . ' operating system');
94 jpm 245
                    }
246
                } else {
247
                    if (strtolower($dep['name']) != strtolower($this->getSysname())) {
187 mathias 248
                        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 249
                            return $this->raiseError('Cannot install %s on ' .
250
                                $this->getSysname() .
251
                                ' operating system, can only install on ' . $dep['name']);
252
                        }
187 mathias 253
 
254
                        return $this->warning('warning: Cannot install %s on ' .
255
                            $this->getSysname() .
256
                            ' operating system, can only install on ' . $dep['name']);
94 jpm 257
                    }
258
                }
259
        }
260
        return true;
261
    }
262
 
263
    /**
264
     * This makes unit-testing a heck of a lot easier
265
     */
266
    function matchSignature($pattern)
267
    {
268
        return $this->_os->matchSignature($pattern);
269
    }
270
 
271
    /**
272
     * Specify a complex dependency on an OS/processor/kernel version,
273
     * Use OS for simple operating system dependency.
274
     *
275
     * This is the only dependency that accepts an eregable pattern.  The pattern
276
     * will be matched against the php_uname() output parsed by OS_Guess
277
     */
278
    function validateArchDependency($dep)
279
    {
280
        if ($this->_state != PEAR_VALIDATE_INSTALLING) {
281
            return true;
282
        }
187 mathias 283
 
284
        $not = isset($dep['conflicts']) ? true : false;
94 jpm 285
        if (!$this->matchSignature($dep['pattern'])) {
286
            if (!$not) {
287
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
288
                    return $this->raiseError('%s Architecture dependency failed, does not ' .
289
                        'match "' . $dep['pattern'] . '"');
290
                }
187 mathias 291
 
292
                return $this->warning('warning: %s Architecture dependency failed, does ' .
293
                    'not match "' . $dep['pattern'] . '"');
94 jpm 294
            }
187 mathias 295
 
94 jpm 296
            return true;
187 mathias 297
        }
298
 
299
        if ($not) {
300
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
301
                return $this->raiseError('%s Architecture dependency failed, required "' .
302
                    $dep['pattern'] . '"');
94 jpm 303
            }
187 mathias 304
 
305
            return $this->warning('warning: %s Architecture dependency failed, ' .
306
                'required "' . $dep['pattern'] . '"');
94 jpm 307
        }
187 mathias 308
 
309
        return true;
94 jpm 310
    }
311
 
312
    /**
313
     * This makes unit-testing a heck of a lot easier
314
     */
315
    function extension_loaded($name)
316
    {
317
        return extension_loaded($name);
318
    }
319
 
320
    /**
321
     * This makes unit-testing a heck of a lot easier
322
     */
323
    function phpversion($name = null)
324
    {
325
        if ($name !== null) {
326
            return phpversion($name);
327
        }
187 mathias 328
 
329
        return phpversion();
94 jpm 330
    }
331
 
332
    function validateExtensionDependency($dep, $required = true)
333
    {
334
        if ($this->_state != PEAR_VALIDATE_INSTALLING &&
335
              $this->_state != PEAR_VALIDATE_DOWNLOADING) {
336
            return true;
337
        }
187 mathias 338
 
94 jpm 339
        $loaded = $this->extension_loaded($dep['name']);
187 mathias 340
        $extra  = $this->_getExtraString($dep);
94 jpm 341
        if (isset($dep['exclude'])) {
342
            if (!is_array($dep['exclude'])) {
343
                $dep['exclude'] = array($dep['exclude']);
344
            }
345
        }
187 mathias 346
 
94 jpm 347
        if (!isset($dep['min']) && !isset($dep['max']) &&
187 mathias 348
            !isset($dep['recommended']) && !isset($dep['exclude'])
349
        ) {
94 jpm 350
            if ($loaded) {
351
                if (isset($dep['conflicts'])) {
352
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
353
                        return $this->raiseError('%s conflicts with PHP extension "' .
354
                            $dep['name'] . '"' . $extra);
355
                    }
187 mathias 356
 
357
                    return $this->warning('warning: %s conflicts with PHP extension "' .
358
                        $dep['name'] . '"' . $extra);
94 jpm 359
                }
187 mathias 360
 
94 jpm 361
                return true;
187 mathias 362
            }
363
 
364
            if (isset($dep['conflicts'])) {
365
                return true;
366
            }
367
 
368
            if ($required) {
369
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
370
                    return $this->raiseError('%s requires PHP extension "' .
94 jpm 371
                        $dep['name'] . '"' . $extra);
372
                }
187 mathias 373
 
374
                return $this->warning('warning: %s requires PHP extension "' .
375
                    $dep['name'] . '"' . $extra);
94 jpm 376
            }
187 mathias 377
 
378
            return $this->warning('%s can optionally use PHP extension "' .
379
                $dep['name'] . '"' . $extra);
94 jpm 380
        }
187 mathias 381
 
94 jpm 382
        if (!$loaded) {
383
            if (isset($dep['conflicts'])) {
384
                return true;
385
            }
187 mathias 386
 
94 jpm 387
            if (!$required) {
388
                return $this->warning('%s can optionally use PHP extension "' .
389
                    $dep['name'] . '"' . $extra);
390
            }
187 mathias 391
 
392
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
393
                return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
394
                    '"' . $extra);
395
            }
396
 
397
            return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
398
                    '"' . $extra);
94 jpm 399
        }
187 mathias 400
 
94 jpm 401
        $version = (string) $this->phpversion($dep['name']);
402
        if (empty($version)) {
403
            $version = '0';
404
        }
187 mathias 405
 
94 jpm 406
        $fail = false;
187 mathias 407
        if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
408
            $fail = true;
94 jpm 409
        }
187 mathias 410
 
411
        if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
412
            $fail = true;
94 jpm 413
        }
187 mathias 414
 
94 jpm 415
        if ($fail && !isset($dep['conflicts'])) {
416
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
417
                return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
418
                    '"' . $extra . ', installed version is ' . $version);
419
            }
187 mathias 420
 
421
            return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
422
                '"' . $extra . ', installed version is ' . $version);
94 jpm 423
        } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
424
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
425
                return $this->raiseError('%s conflicts with PHP extension "' .
426
                    $dep['name'] . '"' . $extra . ', installed version is ' . $version);
427
            }
187 mathias 428
 
429
            return $this->warning('warning: %s conflicts with PHP extension "' .
430
                $dep['name'] . '"' . $extra . ', installed version is ' . $version);
94 jpm 431
        }
187 mathias 432
 
94 jpm 433
        if (isset($dep['exclude'])) {
434
            foreach ($dep['exclude'] as $exclude) {
435
                if (version_compare($version, $exclude, '==')) {
436
                    if (isset($dep['conflicts'])) {
437
                        continue;
438
                    }
187 mathias 439
 
440
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 441
                        return $this->raiseError('%s is not compatible with PHP extension "' .
442
                            $dep['name'] . '" version ' .
443
                            $exclude);
444
                    }
187 mathias 445
 
446
                    return $this->warning('warning: %s is not compatible with PHP extension "' .
447
                        $dep['name'] . '" version ' .
448
                        $exclude);
94 jpm 449
                } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
450
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
451
                        return $this->raiseError('%s conflicts with PHP extension "' .
452
                            $dep['name'] . '"' . $extra . ', installed version is ' . $version);
453
                    }
187 mathias 454
 
455
                    return $this->warning('warning: %s conflicts with PHP extension "' .
456
                        $dep['name'] . '"' . $extra . ', installed version is ' . $version);
94 jpm 457
                }
458
            }
459
        }
187 mathias 460
 
94 jpm 461
        if (isset($dep['recommended'])) {
462
            if (version_compare($version, $dep['recommended'], '==')) {
463
                return true;
464
            }
187 mathias 465
 
466
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
467
                return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
468
                    ' version "' . $version . '"' .
469
                    ' is not the recommended version "' . $dep['recommended'] .
470
                    '", but may be compatible, use --force to install');
471
            }
472
 
473
            return $this->warning('warning: %s dependency: PHP extension ' .
474
                $dep['name'] . ' version "' . $version . '"' .
475
                ' is not the recommended version "' . $dep['recommended'].'"');
94 jpm 476
        }
187 mathias 477
 
94 jpm 478
        return true;
479
    }
480
 
481
    function validatePhpDependency($dep)
482
    {
483
        if ($this->_state != PEAR_VALIDATE_INSTALLING &&
484
              $this->_state != PEAR_VALIDATE_DOWNLOADING) {
485
            return true;
486
        }
187 mathias 487
 
94 jpm 488
        $version = $this->phpversion();
187 mathias 489
        $extra   = $this->_getExtraString($dep);
94 jpm 490
        if (isset($dep['exclude'])) {
491
            if (!is_array($dep['exclude'])) {
492
                $dep['exclude'] = array($dep['exclude']);
493
            }
494
        }
187 mathias 495
 
94 jpm 496
        if (isset($dep['min'])) {
497
            if (!version_compare($version, $dep['min'], '>=')) {
498
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
499
                    return $this->raiseError('%s requires PHP' .
500
                        $extra . ', installed version is ' . $version);
501
                }
187 mathias 502
 
503
                return $this->warning('warning: %s requires PHP' .
504
                    $extra . ', installed version is ' . $version);
94 jpm 505
            }
506
        }
187 mathias 507
 
94 jpm 508
        if (isset($dep['max'])) {
509
            if (!version_compare($version, $dep['max'], '<=')) {
510
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
511
                    return $this->raiseError('%s requires PHP' .
512
                        $extra . ', installed version is ' . $version);
513
                }
187 mathias 514
 
515
                return $this->warning('warning: %s requires PHP' .
516
                    $extra . ', installed version is ' . $version);
94 jpm 517
            }
518
        }
187 mathias 519
 
94 jpm 520
        if (isset($dep['exclude'])) {
521
            foreach ($dep['exclude'] as $exclude) {
522
                if (version_compare($version, $exclude, '==')) {
187 mathias 523
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
94 jpm 524
                        return $this->raiseError('%s is not compatible with PHP version ' .
525
                            $exclude);
526
                    }
187 mathias 527
 
528
                    return $this->warning(
529
                        'warning: %s is not compatible with PHP version ' .
530
                        $exclude);
94 jpm 531
                }
532
            }
533
        }
187 mathias 534
 
94 jpm 535
        return true;
536
    }
537
 
538
    /**
539
     * This makes unit-testing a heck of a lot easier
540
     */
541
    function getPEARVersion()
542
    {
187 mathias 543
        return '1.10.1';
94 jpm 544
    }
545
 
546
    function validatePearinstallerDependency($dep)
547
    {
548
        $pearversion = $this->getPEARVersion();
549
        $extra = $this->_getExtraString($dep);
550
        if (isset($dep['exclude'])) {
551
            if (!is_array($dep['exclude'])) {
552
                $dep['exclude'] = array($dep['exclude']);
553
            }
554
        }
187 mathias 555
 
94 jpm 556
        if (version_compare($pearversion, $dep['min'], '<')) {
557
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
558
                return $this->raiseError('%s requires PEAR Installer' . $extra .
559
                    ', installed version is ' . $pearversion);
560
            }
187 mathias 561
 
562
            return $this->warning('warning: %s requires PEAR Installer' . $extra .
563
                ', installed version is ' . $pearversion);
94 jpm 564
        }
187 mathias 565
 
94 jpm 566
        if (isset($dep['max'])) {
567
            if (version_compare($pearversion, $dep['max'], '>')) {
568
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
569
                    return $this->raiseError('%s requires PEAR Installer' . $extra .
570
                        ', installed version is ' . $pearversion);
571
                }
187 mathias 572
 
573
                return $this->warning('warning: %s requires PEAR Installer' . $extra .
574
                    ', installed version is ' . $pearversion);
94 jpm 575
            }
576
        }
187 mathias 577
 
94 jpm 578
        if (isset($dep['exclude'])) {
579
            if (!isset($dep['exclude'][0])) {
580
                $dep['exclude'] = array($dep['exclude']);
581
            }
187 mathias 582
 
94 jpm 583
            foreach ($dep['exclude'] as $exclude) {
584
                if (version_compare($exclude, $pearversion, '==')) {
585
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
586
                        return $this->raiseError('%s is not compatible with PEAR Installer ' .
587
                            'version ' . $exclude);
588
                    }
187 mathias 589
 
590
                    return $this->warning('warning: %s is not compatible with PEAR ' .
591
                        'Installer version ' . $exclude);
94 jpm 592
                }
593
            }
594
        }
187 mathias 595
 
94 jpm 596
        return true;
597
    }
598
 
599
    function validateSubpackageDependency($dep, $required, $params)
600
    {
601
        return $this->validatePackageDependency($dep, $required, $params);
602
    }
603
 
604
    /**
605
     * @param array dependency information (2.0 format)
606
     * @param boolean whether this is a required dependency
607
     * @param array a list of downloaded packages to be installed, if any
608
     * @param boolean if true, then deps on pear.php.net that fail will also check
187 mathias 609
     *                against pecl.php.net packages to accommodate extensions that have
94 jpm 610
     *                moved to pecl.php.net from pear.php.net
611
     */
612
    function validatePackageDependency($dep, $required, $params, $depv1 = false)
613
    {
614
        if ($this->_state != PEAR_VALIDATE_INSTALLING &&
615
              $this->_state != PEAR_VALIDATE_DOWNLOADING) {
616
            return true;
617
        }
187 mathias 618
 
94 jpm 619
        if (isset($dep['providesextension'])) {
620
            if ($this->extension_loaded($dep['providesextension'])) {
621
                $save = $dep;
622
                $subdep = $dep;
623
                $subdep['name'] = $subdep['providesextension'];
624
                PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
625
                $ret = $this->validateExtensionDependency($subdep, $required);
626
                PEAR::popErrorHandling();
627
                if (!PEAR::isError($ret)) {
628
                    return true;
629
                }
630
            }
631
        }
187 mathias 632
 
94 jpm 633
        if ($this->_state == PEAR_VALIDATE_INSTALLING) {
634
            return $this->_validatePackageInstall($dep, $required, $depv1);
635
        }
187 mathias 636
 
94 jpm 637
        if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
638
            return $this->_validatePackageDownload($dep, $required, $params, $depv1);
639
        }
640
    }
641
 
642
    function _validatePackageDownload($dep, $required, $params, $depv1 = false)
643
    {
644
        $dep['package'] = $dep['name'];
645
        if (isset($dep['uri'])) {
646
            $dep['channel'] = '__uri';
647
        }
187 mathias 648
 
94 jpm 649
        $depname = $this->_registry->parsedPackageNameToString($dep, true);
650
        $found = false;
651
        foreach ($params as $param) {
652
            if ($param->isEqual(
653
                  array('package' => $dep['name'],
654
                        'channel' => $dep['channel']))) {
655
                $found = true;
656
                break;
657
            }
187 mathias 658
 
94 jpm 659
            if ($depv1 && $dep['channel'] == 'pear.php.net') {
660
                if ($param->isEqual(
661
                  array('package' => $dep['name'],
662
                        'channel' => 'pecl.php.net'))) {
663
                    $found = true;
664
                    break;
665
                }
666
            }
667
        }
187 mathias 668
 
94 jpm 669
        if (!$found && isset($dep['providesextension'])) {
670
            foreach ($params as $param) {
671
                if ($param->isExtension($dep['providesextension'])) {
672
                    $found = true;
673
                    break;
674
                }
675
            }
676
        }
187 mathias 677
 
94 jpm 678
        if ($found) {
679
            $version = $param->getVersion();
680
            $installed = false;
681
            $downloaded = true;
682
        } else {
683
            if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
684
                $installed = true;
685
                $downloaded = false;
686
                $version = $this->_registry->packageinfo($dep['name'], 'version',
687
                    $dep['channel']);
688
            } else {
689
                if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
690
                      'pear.php.net')) {
691
                    $installed = true;
692
                    $downloaded = false;
693
                    $version = $this->_registry->packageinfo($dep['name'], 'version',
694
                        'pear.php.net');
695
                } else {
696
                    $version = 'not installed or downloaded';
697
                    $installed = false;
698
                    $downloaded = false;
699
                }
700
            }
701
        }
187 mathias 702
 
94 jpm 703
        $extra = $this->_getExtraString($dep);
187 mathias 704
        if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
705
            $dep['exclude'] = array($dep['exclude']);
94 jpm 706
        }
187 mathias 707
 
94 jpm 708
        if (!isset($dep['min']) && !isset($dep['max']) &&
187 mathias 709
              !isset($dep['recommended']) && !isset($dep['exclude'])
710
        ) {
94 jpm 711
            if ($installed || $downloaded) {
712
                $installed = $installed ? 'installed' : 'downloaded';
713
                if (isset($dep['conflicts'])) {
187 mathias 714
                    $rest = '';
94 jpm 715
                    if ($version) {
716
                        $rest = ", $installed version is " . $version;
717
                    }
187 mathias 718
 
94 jpm 719
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
187 mathias 720
                        return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
94 jpm 721
                    }
187 mathias 722
 
723
                    return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
94 jpm 724
                }
187 mathias 725
 
94 jpm 726
                return true;
187 mathias 727
            }
728
 
729
            if (isset($dep['conflicts'])) {
730
                return true;
731
            }
732
 
733
            if ($required) {
734
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
735
                    return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
94 jpm 736
                }
187 mathias 737
 
738
                return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
94 jpm 739
            }
187 mathias 740
 
741
            return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
94 jpm 742
        }
187 mathias 743
 
94 jpm 744
        if (!$installed && !$downloaded) {
745
            if (isset($dep['conflicts'])) {
746
                return true;
747
            }
187 mathias 748
 
94 jpm 749
            if ($required) {
750
                if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
187 mathias 751
                    return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
94 jpm 752
                }
187 mathias 753
 
754
                return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
94 jpm 755
            }
187 mathias 756
 
757
            return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
94 jpm 758
        }
187 mathias 759
 
94 jpm 760
        $fail = false;
187 mathias 761
        if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
762
            $fail = true;
94 jpm 763
        }
187 mathias 764
 
765
        if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
766
            $fail = true;
94 jpm 767
        }
187 mathias 768
 
94 jpm 769
        if ($fail && !isset($dep['conflicts'])) {
770
            $installed = $installed ? 'installed' : 'downloaded';
771
            $dep['package'] = $dep['name'];
772
            $dep = $this->_registry->parsedPackageNameToString($dep, true);
773
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
774
                return $this->raiseError('%s requires package "' . $depname . '"' .
775
                    $extra . ", $installed version is " . $version);
776
            }
187 mathias 777
 
778
            return $this->warning('warning: %s requires package "' . $depname . '"' .
779
                $extra . ", $installed version is " . $version);
94 jpm 780
        } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
781
              isset($dep['conflicts']) && !isset($dep['exclude'])) {
782
            $installed = $installed ? 'installed' : 'downloaded';
783
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
784
                return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
785
                    ", $installed version is " . $version);
786
            }
187 mathias 787
 
788
            return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
789
                $extra . ", $installed version is " . $version);
94 jpm 790
        }
187 mathias 791
 
94 jpm 792
        if (isset($dep['exclude'])) {
793
            $installed = $installed ? 'installed' : 'downloaded';
794
            foreach ($dep['exclude'] as $exclude) {
795
                if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
796
                    if (!isset($this->_options['nodeps']) &&
187 mathias 797
                          !isset($this->_options['force'])
798
                    ) {
94 jpm 799
                        return $this->raiseError('%s is not compatible with ' .
800
                            $installed . ' package "' .
801
                            $depname . '" version ' .
802
                            $exclude);
803
                    }
187 mathias 804
 
805
                    return $this->warning('warning: %s is not compatible with ' .
806
                        $installed . ' package "' .
807
                        $depname . '" version ' .
808
                        $exclude);
94 jpm 809
                } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
810
                    $installed = $installed ? 'installed' : 'downloaded';
811
                    if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
812
                        return $this->raiseError('%s conflicts with package "' . $depname . '"' .
813
                            $extra . ", $installed version is " . $version);
814
                    }
187 mathias 815
 
816
                    return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
817
                        $extra . ", $installed version is " . $version);
94 jpm 818
                }
819
            }
820
        }
187 mathias 821
 
94 jpm 822
        if (isset($dep['recommended'])) {
823
            $installed = $installed ? 'installed' : 'downloaded';
824
            if (version_compare($version, $dep['recommended'], '==')) {
825
                return true;
187 mathias 826
            }
827
 
828
            if (!$found && $installed) {
829
                $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
830
            }
831
 
832
            if ($param) {
833
                $found = false;
834
                foreach ($params as $parent) {
835
                    if ($parent->isEqual($this->_currentPackage)) {
836
                        $found = true;
837
                        break;
838
                    }
94 jpm 839
                }
187 mathias 840
 
841
                if ($found) {
842
                    if ($param->isCompatible($parent)) {
843
                        return true;
94 jpm 844
                    }
187 mathias 845
                } else { // this is for validPackage() calls
846
                    $parent = $this->_registry->getPackage($this->_currentPackage['package'],
847
                        $this->_currentPackage['channel']);
848
                    if ($parent !== null && $param->isCompatible($parent)) {
849
                        return true;
94 jpm 850
                    }
851
                }
852
            }
187 mathias 853
 
854
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
855
                  !isset($this->_options['loose'])
856
            ) {
857
                return $this->raiseError('%s dependency package "' . $depname .
858
                    '" ' . $installed . ' version ' . $version .
859
                    ' is not the recommended version ' . $dep['recommended'] .
860
                    ', but may be compatible, use --force to install');
861
            }
862
 
863
            return $this->warning('warning: %s dependency package "' . $depname .
864
                '" ' . $installed . ' version ' . $version .
865
                ' is not the recommended version ' . $dep['recommended']);
94 jpm 866
        }
187 mathias 867
 
94 jpm 868
        return true;
869
    }
870
 
871
    function _validatePackageInstall($dep, $required, $depv1 = false)
872
    {
873
        return $this->_validatePackageDownload($dep, $required, array(), $depv1);
874
    }
875
 
876
    /**
877
     * Verify that uninstalling packages passed in to command line is OK.
878
     *
879
     * @param PEAR_Installer $dl
880
     * @return PEAR_Error|true
881
     */
882
    function validatePackageUninstall(&$dl)
883
    {
884
        if (PEAR::isError($this->_dependencydb)) {
885
            return $this->_dependencydb;
886
        }
187 mathias 887
 
94 jpm 888
        $params = array();
889
        // construct an array of "downloaded" packages to fool the package dependency checker
890
        // into using these to validate uninstalls of circular dependencies
891
        $downloaded = &$dl->getUninstallPackages();
892
        foreach ($downloaded as $i => $pf) {
893
            if (!class_exists('PEAR_Downloader_Package')) {
894
                require_once 'PEAR/Downloader/Package.php';
895
            }
187 mathias 896
            $dp = new PEAR_Downloader_Package($dl);
94 jpm 897
            $dp->setPackageFile($downloaded[$i]);
187 mathias 898
            $params[$i] = $dp;
94 jpm 899
        }
187 mathias 900
 
94 jpm 901
        // check cache
902
        $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
903
            strtolower($this->_currentPackage['package']);
904
        if (isset($dl->___uninstall_package_cache)) {
905
            $badpackages = $dl->___uninstall_package_cache;
906
            if (isset($badpackages[$memyselfandI]['warnings'])) {
907
                foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
908
                    $dl->log(0, $warning[0]);
909
                }
910
            }
187 mathias 911
 
94 jpm 912
            if (isset($badpackages[$memyselfandI]['errors'])) {
913
                foreach ($badpackages[$memyselfandI]['errors'] as $error) {
187 mathias 914
                    if (is_array($error)) {
915
                        $dl->log(0, $error[0]);
916
                    } else {
917
                        $dl->log(0, $error->getMessage());
918
                    }
94 jpm 919
                }
187 mathias 920
 
94 jpm 921
                if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
922
                    return $this->warning(
923
                        'warning: %s should not be uninstalled, other installed packages depend ' .
924
                        'on this package');
925
                }
187 mathias 926
 
927
                return $this->raiseError(
928
                    '%s cannot be uninstalled, other installed packages depend on this package');
94 jpm 929
            }
187 mathias 930
 
94 jpm 931
            return true;
932
        }
187 mathias 933
 
94 jpm 934
        // first, list the immediate parents of each package to be uninstalled
935
        $perpackagelist = array();
936
        $allparents = array();
937
        foreach ($params as $i => $param) {
187 mathias 938
            $a = array(
939
                'channel' => strtolower($param->getChannel()),
940
                'package' => strtolower($param->getPackage())
941
            );
942
 
94 jpm 943
            $deps = $this->_dependencydb->getDependentPackages($a);
944
            if ($deps) {
945
                foreach ($deps as $d) {
946
                    $pardeps = $this->_dependencydb->getDependencies($d);
947
                    foreach ($pardeps as $dep) {
948
                        if (strtolower($dep['dep']['channel']) == $a['channel'] &&
949
                              strtolower($dep['dep']['name']) == $a['package']) {
950
                            if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
951
                                $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
952
                            }
953
                            $perpackagelist[$a['channel'] . '/' . $a['package']][]
954
                                = array($d['channel'] . '/' . $d['package'], $dep);
955
                            if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
956
                                $allparents[$d['channel'] . '/' . $d['package']] = array();
957
                            }
958
                            if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
959
                                $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
960
                            }
961
                            $allparents[$d['channel'] . '/' . $d['package']]
962
                                       [$a['channel'] . '/' . $a['package']][]
963
                                = array($d, $dep);
964
                        }
965
                    }
966
                }
967
            }
968
        }
187 mathias 969
 
94 jpm 970
        // next, remove any packages from the parents list that are not installed
971
        $remove = array();
972
        foreach ($allparents as $parent => $d1) {
973
            foreach ($d1 as $d) {
974
                if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
975
                    continue;
976
                }
977
                $remove[$parent] = true;
978
            }
979
        }
187 mathias 980
 
94 jpm 981
        // next remove any packages from the parents list that are not passed in for
982
        // uninstallation
983
        foreach ($allparents as $parent => $d1) {
984
            foreach ($d1 as $d) {
985
                foreach ($params as $param) {
986
                    if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
987
                          strtolower($param->getPackage()) == $d[0][0]['package']) {
988
                        // found it
989
                        continue 3;
990
                    }
991
                }
992
                $remove[$parent] = true;
993
            }
994
        }
187 mathias 995
 
94 jpm 996
        // remove all packages whose dependencies fail
997
        // save which ones failed for error reporting
998
        $badchildren = array();
999
        do {
1000
            $fail = false;
1001
            foreach ($remove as $package => $unused) {
1002
                if (!isset($allparents[$package])) {
1003
                    continue;
1004
                }
187 mathias 1005
 
94 jpm 1006
                foreach ($allparents[$package] as $kid => $d1) {
1007
                    foreach ($d1 as $depinfo) {
1008
                        if ($depinfo[1]['type'] != 'optional') {
1009
                            if (isset($badchildren[$kid])) {
1010
                                continue;
1011
                            }
1012
                            $badchildren[$kid] = true;
1013
                            $remove[$kid] = true;
1014
                            $fail = true;
1015
                            continue 2;
1016
                        }
1017
                    }
1018
                }
1019
                if ($fail) {
1020
                    // start over, we removed some children
1021
                    continue 2;
1022
                }
1023
            }
1024
        } while ($fail);
187 mathias 1025
 
94 jpm 1026
        // next, construct the list of packages that can't be uninstalled
1027
        $badpackages = array();
1028
        $save = $this->_currentPackage;
1029
        foreach ($perpackagelist as $package => $packagedeps) {
1030
            foreach ($packagedeps as $parent) {
1031
                if (!isset($remove[$parent[0]])) {
1032
                    continue;
1033
                }
187 mathias 1034
 
94 jpm 1035
                $packagename = $this->_registry->parsePackageName($parent[0]);
1036
                $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
1037
                $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
1038
                $packagename['package'] = $pa->getPackage();
1039
                $this->_currentPackage = $packagename;
1040
                // parent is not present in uninstall list, make sure we can actually
1041
                // uninstall it (parent dep is optional)
1042
                $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
1043
                $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
1044
                $parentname['package'] = $pa->getPackage();
1045
                $parent[1]['dep']['package'] = $parentname['package'];
1046
                $parent[1]['dep']['channel'] = $parentname['channel'];
1047
                if ($parent[1]['type'] == 'optional') {
1048
                    $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
1049
                    if ($test !== true) {
1050
                        $badpackages[$package]['warnings'][] = $test;
1051
                    }
1052
                } else {
1053
                    $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
1054
                    if ($test !== true) {
1055
                        $badpackages[$package]['errors'][] = $test;
1056
                    }
1057
                }
1058
            }
1059
        }
187 mathias 1060
 
1061
        $this->_currentPackage          = $save;
94 jpm 1062
        $dl->___uninstall_package_cache = $badpackages;
1063
        if (isset($badpackages[$memyselfandI])) {
1064
            if (isset($badpackages[$memyselfandI]['warnings'])) {
1065
                foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
1066
                    $dl->log(0, $warning[0]);
1067
                }
1068
            }
187 mathias 1069
 
94 jpm 1070
            if (isset($badpackages[$memyselfandI]['errors'])) {
1071
                foreach ($badpackages[$memyselfandI]['errors'] as $error) {
187 mathias 1072
                    if (is_array($error)) {
1073
                        $dl->log(0, $error[0]);
1074
                    } else {
1075
                        $dl->log(0, $error->getMessage());
1076
                    }
94 jpm 1077
                }
187 mathias 1078
 
94 jpm 1079
                if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
1080
                    return $this->warning(
1081
                        'warning: %s should not be uninstalled, other installed packages depend ' .
1082
                        'on this package');
1083
                }
187 mathias 1084
 
1085
                return $this->raiseError(
1086
                    '%s cannot be uninstalled, other installed packages depend on this package');
94 jpm 1087
            }
1088
        }
187 mathias 1089
 
94 jpm 1090
        return true;
1091
    }
1092
 
1093
    function _validatePackageUninstall($dep, $required, $dl)
1094
    {
1095
        $depname = $this->_registry->parsedPackageNameToString($dep, true);
187 mathias 1096
        $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
94 jpm 1097
        if (!$version) {
1098
            return true;
1099
        }
187 mathias 1100
 
94 jpm 1101
        $extra = $this->_getExtraString($dep);
187 mathias 1102
        if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
1103
            $dep['exclude'] = array($dep['exclude']);
94 jpm 1104
        }
187 mathias 1105
 
94 jpm 1106
        if (isset($dep['conflicts'])) {
1107
            return true; // uninstall OK - these packages conflict (probably installed with --force)
1108
        }
187 mathias 1109
 
94 jpm 1110
        if (!isset($dep['min']) && !isset($dep['max'])) {
187 mathias 1111
            if (!$required) {
94 jpm 1112
                return $this->warning('"' . $depname . '" can be optionally used by ' .
1113
                        'installed package %s' . $extra);
1114
            }
187 mathias 1115
 
1116
            if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
1117
                return $this->raiseError('"' . $depname . '" is required by ' .
1118
                    'installed package %s' . $extra);
1119
            }
1120
 
1121
            return $this->warning('warning: "' . $depname . '" is required by ' .
1122
                'installed package %s' . $extra);
94 jpm 1123
        }
187 mathias 1124
 
94 jpm 1125
        $fail = false;
187 mathias 1126
        if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
1127
            $fail = true;
94 jpm 1128
        }
187 mathias 1129
 
1130
        if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
1131
            $fail = true;
94 jpm 1132
        }
187 mathias 1133
 
94 jpm 1134
        // we re-use this variable, preserve the original value
1135
        $saverequired = $required;
187 mathias 1136
        if (!$required) {
94 jpm 1137
            return $this->warning($depname . $extra . ' can be optionally used by installed package' .
1138
                    ' "%s"');
1139
        }
187 mathias 1140
 
1141
        if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
1142
            return $this->raiseError($depname . $extra . ' is required by installed package' .
1143
                ' "%s"');
1144
        }
1145
 
1146
        return $this->raiseError('warning: ' . $depname . $extra .
1147
            ' is required by installed package "%s"');
94 jpm 1148
    }
1149
 
1150
    /**
1151
     * validate a downloaded package against installed packages
187 mathias 1152
     *
94 jpm 1153
     * As of PEAR 1.4.3, this will only validate
1154
     *
1155
     * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
1156
     *              $pkg package identifier (either
1157
     *                   array('package' => blah, 'channel' => blah) or an array with
1158
     *                   index 'info' referencing an object)
1159
     * @param PEAR_Downloader $dl
1160
     * @param array $params full list of packages to install
1161
     * @return true|PEAR_Error
1162
     */
1163
    function validatePackage($pkg, &$dl, $params = array())
1164
    {
1165
        if (is_array($pkg) && isset($pkg['info'])) {
1166
            $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
1167
        } else {
1168
            $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
1169
        }
187 mathias 1170
 
94 jpm 1171
        $fail = false;
1172
        if ($deps) {
1173
            if (!class_exists('PEAR_Downloader_Package')) {
1174
                require_once 'PEAR/Downloader/Package.php';
1175
            }
187 mathias 1176
 
1177
            $dp = new PEAR_Downloader_Package($dl);
94 jpm 1178
            if (is_object($pkg)) {
1179
                $dp->setPackageFile($pkg);
1180
            } else {
1181
                $dp->setDownloadURL($pkg);
1182
            }
187 mathias 1183
 
94 jpm 1184
            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1185
            foreach ($deps as $channel => $info) {
1186
                foreach ($info as $package => $ds) {
1187
                    foreach ($params as $packd) {
1188
                        if (strtolower($packd->getPackage()) == strtolower($package) &&
1189
                              $packd->getChannel() == $channel) {
1190
                            $dl->log(3, 'skipping installed package check of "' .
1191
                                        $this->_registry->parsedPackageNameToString(
1192
                                            array('channel' => $channel, 'package' => $package),
1193
                                            true) .
1194
                                        '", version "' . $packd->getVersion() . '" will be ' .
1195
                                        'downloaded and installed');
1196
                            continue 2; // jump to next package
1197
                        }
1198
                    }
187 mathias 1199
 
94 jpm 1200
                    foreach ($ds as $d) {
187 mathias 1201
                        $checker = new PEAR_Dependency2($this->_config, $this->_options,
94 jpm 1202
                            array('channel' => $channel, 'package' => $package), $this->_state);
1203
                        $dep = $d['dep'];
1204
                        $required = $d['type'] == 'required';
1205
                        $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
1206
                        if (is_array($ret)) {
1207
                            $dl->log(0, $ret[0]);
1208
                        } elseif (PEAR::isError($ret)) {
1209
                            $dl->log(0, $ret->getMessage());
1210
                            $fail = true;
1211
                        }
1212
                    }
1213
                }
1214
            }
1215
            PEAR::popErrorHandling();
1216
        }
187 mathias 1217
 
94 jpm 1218
        if ($fail) {
1219
            return $this->raiseError(
1220
                '%s cannot be installed, conflicts with installed packages');
1221
        }
187 mathias 1222
 
94 jpm 1223
        return true;
1224
    }
1225
 
1226
    /**
1227
     * validate a package.xml 1.0 dependency
1228
     */
1229
    function validateDependency1($dep, $params = array())
1230
    {
1231
        if (!isset($dep['optional'])) {
1232
            $dep['optional'] = 'no';
1233
        }
187 mathias 1234
 
94 jpm 1235
        list($newdep, $type) = $this->normalizeDep($dep);
1236
        if (!$newdep) {
1237
            return $this->raiseError("Invalid Dependency");
1238
        }
187 mathias 1239
 
94 jpm 1240
        if (method_exists($this, "validate{$type}Dependency")) {
1241
            return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
1242
                $params, true);
1243
        }
1244
    }
1245
 
1246
    /**
1247
     * Convert a 1.0 dep into a 2.0 dep
1248
     */
1249
    function normalizeDep($dep)
1250
    {
1251
        $types = array(
1252
            'pkg' => 'Package',
1253
            'ext' => 'Extension',
1254
            'os' => 'Os',
1255
            'php' => 'Php'
1256
        );
187 mathias 1257
 
1258
        if (!isset($types[$dep['type']])) {
94 jpm 1259
            return array(false, false);
1260
        }
187 mathias 1261
 
1262
        $type = $types[$dep['type']];
1263
 
94 jpm 1264
        $newdep = array();
1265
        switch ($type) {
1266
            case 'Package' :
1267
                $newdep['channel'] = 'pear.php.net';
1268
            case 'Extension' :
1269
            case 'Os' :
1270
                $newdep['name'] = $dep['name'];
1271
            break;
1272
        }
187 mathias 1273
 
94 jpm 1274
        $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
1275
        switch ($dep['rel']) {
1276
            case 'has' :
1277
                return array($newdep, $type);
1278
            break;
1279
            case 'not' :
1280
                $newdep['conflicts'] = true;
1281
            break;
1282
            case '>=' :
1283
            case '>' :
1284
                $newdep['min'] = $dep['version'];
1285
                if ($dep['rel'] == '>') {
1286
                    $newdep['exclude'] = $dep['version'];
1287
                }
1288
            break;
1289
            case '<=' :
1290
            case '<' :
1291
                $newdep['max'] = $dep['version'];
1292
                if ($dep['rel'] == '<') {
1293
                    $newdep['exclude'] = $dep['version'];
1294
                }
1295
            break;
1296
            case 'ne' :
1297
            case '!=' :
1298
                $newdep['min'] = '0';
1299
                $newdep['max'] = '100000';
1300
                $newdep['exclude'] = $dep['version'];
1301
            break;
1302
            case '==' :
1303
                $newdep['min'] = $dep['version'];
1304
                $newdep['max'] = $dep['version'];
1305
            break;
1306
        }
1307
        if ($type == 'Php') {
1308
            if (!isset($newdep['min'])) {
187 mathias 1309
                $newdep['min'] = '4.4.0';
94 jpm 1310
            }
187 mathias 1311
 
94 jpm 1312
            if (!isset($newdep['max'])) {
1313
                $newdep['max'] = '6.0.0';
1314
            }
1315
        }
1316
        return array($newdep, $type);
1317
    }
1318
 
1319
    /**
1320
     * Converts text comparing operators to them sign equivalents
1321
     *
1322
     * Example: 'ge' to '>='
1323
     *
1324
     * @access public
1325
     * @param  string Operator
1326
     * @return string Sign equivalent
1327
     */
1328
    function signOperator($operator)
1329
    {
1330
        switch($operator) {
1331
            case 'lt': return '<';
1332
            case 'le': return '<=';
1333
            case 'gt': return '>';
1334
            case 'ge': return '>=';
1335
            case 'eq': return '==';
1336
            case 'ne': return '!=';
1337
            default:
1338
                return $operator;
1339
        }
1340
    }
1341
 
1342
    function raiseError($msg)
1343
    {
1344
        if (isset($this->_options['ignore-errors'])) {
1345
            return $this->warning($msg);
1346
        }
187 mathias 1347
 
94 jpm 1348
        return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
1349
            $this->_currentPackage, true)));
1350
    }
1351
 
1352
    function warning($msg)
1353
    {
1354
        return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
1355
            $this->_currentPackage, true)));
1356
    }
1357
}