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