Bearsampp 2026.9.23
Loading...
Searching...
No Matches
Dependency2.php
Go to the documentation of this file.
1<?php
15
19require_once 'PEAR/Validate.php';
20
38{
45
51
55 var $_os;
56
61
66
71
77
84 function __construct(&$config, $installoptions, $package,
86 {
87 $this->_config = &$config;
88 if (!class_exists('PEAR_DependencyDB')) {
89 require_once 'PEAR/DependencyDB.php';
90 }
91
92 if (isset($installoptions['packagingroot'])) {
93 // make sure depdb is in the right location
94 $config->setInstallRoot($installoptions['packagingroot']);
95 }
96
97 $this->_registry = &$config->getRegistry();
98 $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
99 if (isset($installoptions['packagingroot'])) {
100 $config->setInstallRoot(false);
101 }
102
103 $this->_options = $installoptions;
104 $this->_state = $state;
105 if (!class_exists('OS_Guess')) {
106 require_once 'OS/Guess.php';
107 }
108
109 $this->_os = new OS_Guess;
110 $this->_currentPackage = $package;
111 }
112
113 static function _getExtraString($dep)
114 {
115 $extra = ' (';
116 if (isset($dep['uri'])) {
117 return '';
118 }
119
120 if (isset($dep['recommended'])) {
121 $extra .= 'recommended version ' . $dep['recommended'];
122 } else {
123 if (isset($dep['min'])) {
124 $extra .= 'version >= ' . $dep['min'];
125 }
126
127 if (isset($dep['max'])) {
128 if ($extra != ' (') {
129 $extra .= ', ';
130 }
131 $extra .= 'version <= ' . $dep['max'];
132 }
133
134 if (isset($dep['exclude'])) {
135 if (!is_array($dep['exclude'])) {
136 $dep['exclude'] = array($dep['exclude']);
137 }
138
139 if ($extra != ' (') {
140 $extra .= ', ';
141 }
142
143 $extra .= 'excluded versions: ';
144 foreach ($dep['exclude'] as $i => $exclude) {
145 if ($i) {
146 $extra .= ', ';
147 }
148 $extra .= $exclude;
149 }
150 }
151 }
152
153 $extra .= ')';
154 if ($extra == ' ()') {
155 $extra = '';
156 }
157
158 return $extra;
159 }
160
164 function getPHP_OS()
165 {
166 return PHP_OS;
167 }
168
172 function getsysname()
173 {
174 return $this->_os->getSysname();
175 }
176
183 function validateOsDependency($dep)
184 {
185 if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
186 return true;
187 }
188
189 if ($dep['name'] == '*') {
190 return true;
191 }
192
193 $not = isset($dep['conflicts']) ? true : false;
194 switch (strtolower($dep['name'])) {
195 case 'windows' :
196 if ($not) {
197 if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
198 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
199 return $this->raiseError("Cannot install %s on Windows");
200 }
201
202 return $this->warning("warning: Cannot install %s on Windows");
203 }
204 } else {
205 if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
206 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
207 return $this->raiseError("Can only install %s on Windows");
208 }
209
210 return $this->warning("warning: Can only install %s on Windows");
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)) {
218 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
219 return $this->raiseError("Cannot install %s on any Unix system");
220 }
221
222 return $this->warning( "warning: Cannot install %s on any Unix system");
223 }
224 } else {
225 if (!in_array($this->getSysname(), $unices)) {
226 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
227 return $this->raiseError("Can only install %s on a Unix system");
228 }
229
230 return $this->warning("warning: Can only install %s on a Unix system");
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 }
242
243 return $this->warning('warning: Cannot install %s on ' .
244 $dep['name'] . ' operating system');
245 }
246 } else {
247 if (strtolower($dep['name']) != strtolower($this->getSysname())) {
248 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
249 return $this->raiseError('Cannot install %s on ' .
250 $this->getSysname() .
251 ' operating system, can only install on ' . $dep['name']);
252 }
253
254 return $this->warning('warning: Cannot install %s on ' .
255 $this->getSysname() .
256 ' operating system, can only install on ' . $dep['name']);
257 }
258 }
259 }
260 return true;
261 }
262
266 function matchSignature($pattern)
267 {
268 return $this->_os->matchSignature($pattern);
269 }
270
279 {
280 if ($this->_state != PEAR_VALIDATE_INSTALLING) {
281 return true;
282 }
283
284 $not = isset($dep['conflicts']) ? true : false;
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 }
291
292 return $this->warning('warning: %s Architecture dependency failed, does ' .
293 'not match "' . $dep['pattern'] . '"');
294 }
295
296 return true;
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'] . '"');
303 }
304
305 return $this->warning('warning: %s Architecture dependency failed, ' .
306 'required "' . $dep['pattern'] . '"');
307 }
308
309 return true;
310 }
311
315 function extension_loaded($name)
316 {
317 return extension_loaded($name);
318 }
319
323 function phpversion($name = null)
324 {
325 if ($name !== null) {
326 return phpversion($name);
327 }
328
329 return phpversion();
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
339 $loaded = $this->extension_loaded($dep['name']);
340 $extra = self::_getExtraString($dep);
341 if (isset($dep['exclude'])) {
342 if (!is_array($dep['exclude'])) {
343 $dep['exclude'] = array($dep['exclude']);
344 }
345 }
346
347 if (!isset($dep['min']) && !isset($dep['max']) &&
348 !isset($dep['recommended']) && !isset($dep['exclude'])
349 ) {
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 }
356
357 return $this->warning('warning: %s conflicts with PHP extension "' .
358 $dep['name'] . '"' . $extra);
359 }
360
361 return true;
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 "' .
371 $dep['name'] . '"' . $extra);
372 }
373
374 return $this->warning('warning: %s requires PHP extension "' .
375 $dep['name'] . '"' . $extra);
376 }
377
378 return $this->warning('%s can optionally use PHP extension "' .
379 $dep['name'] . '"' . $extra);
380 }
381
382 if (!$loaded) {
383 if (isset($dep['conflicts'])) {
384 return true;
385 }
386
387 if (!$required) {
388 return $this->warning('%s can optionally use PHP extension "' .
389 $dep['name'] . '"' . $extra);
390 }
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);
399 }
400
401 $version = (string) $this->phpversion($dep['name']);
402 if (empty($version)) {
403 $version = '0';
404 }
405
406 $fail = false;
407 if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
408 $fail = true;
409 }
410
411 if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
412 $fail = true;
413 }
414
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 }
420
421 return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
422 '"' . $extra . ', installed version is ' . $version);
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 }
428
429 return $this->warning('warning: %s conflicts with PHP extension "' .
430 $dep['name'] . '"' . $extra . ', installed version is ' . $version);
431 }
432
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 }
439
440 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
441 return $this->raiseError('%s is not compatible with PHP extension "' .
442 $dep['name'] . '" version ' .
443 $exclude);
444 }
445
446 return $this->warning('warning: %s is not compatible with PHP extension "' .
447 $dep['name'] . '" version ' .
448 $exclude);
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 }
454
455 return $this->warning('warning: %s conflicts with PHP extension "' .
456 $dep['name'] . '"' . $extra . ', installed version is ' . $version);
457 }
458 }
459 }
460
461 if (isset($dep['recommended'])) {
462 if (version_compare($version, $dep['recommended'], '==')) {
463 return true;
464 }
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'].'"');
476 }
477
478 return true;
479 }
480
482 {
483 if ($this->_state != PEAR_VALIDATE_INSTALLING &&
484 $this->_state != PEAR_VALIDATE_DOWNLOADING) {
485 return true;
486 }
487
488 $version = $this->phpversion();
489 $extra = self::_getExtraString($dep);
490 if (isset($dep['exclude'])) {
491 if (!is_array($dep['exclude'])) {
492 $dep['exclude'] = array($dep['exclude']);
493 }
494 }
495
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 }
502
503 return $this->warning('warning: %s requires PHP' .
504 $extra . ', installed version is ' . $version);
505 }
506 }
507
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 }
514
515 return $this->warning('warning: %s requires PHP' .
516 $extra . ', installed version is ' . $version);
517 }
518 }
519
520 if (isset($dep['exclude'])) {
521 foreach ($dep['exclude'] as $exclude) {
522 if (version_compare($version, $exclude, '==')) {
523 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
524 return $this->raiseError('%s is not compatible with PHP version ' .
525 $exclude);
526 }
527
528 return $this->warning(
529 'warning: %s is not compatible with PHP version ' .
530 $exclude);
531 }
532 }
533 }
534
535 return true;
536 }
537
541 function getPEARVersion()
542 {
543 return '1.10.18';
544 }
545
547 {
548 $pearversion = $this->getPEARVersion();
549 $extra = self::_getExtraString($dep);
550 if (isset($dep['exclude'])) {
551 if (!is_array($dep['exclude'])) {
552 $dep['exclude'] = array($dep['exclude']);
553 }
554 }
555
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 }
561
562 return $this->warning('warning: %s requires PEAR Installer' . $extra .
563 ', installed version is ' . $pearversion);
564 }
565
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 }
572
573 return $this->warning('warning: %s requires PEAR Installer' . $extra .
574 ', installed version is ' . $pearversion);
575 }
576 }
577
578 if (isset($dep['exclude'])) {
579 if (!isset($dep['exclude'][0])) {
580 $dep['exclude'] = array($dep['exclude']);
581 }
582
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 }
589
590 return $this->warning('warning: %s is not compatible with PEAR ' .
591 'Installer version ' . $exclude);
592 }
593 }
594 }
595
596 return true;
597 }
598
599 function validateSubpackageDependency($dep, $required, $params)
600 {
601 return $this->validatePackageDependency($dep, $required, $params);
602 }
603
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 }
618
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 }
632
633 if ($this->_state == PEAR_VALIDATE_INSTALLING) {
634 return $this->_validatePackageInstall($dep, $required, $depv1);
635 }
636
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 }
648
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 }
658
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 }
668
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 }
677
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 }
702
703 $extra = self::_getExtraString($dep);
704 if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
705 $dep['exclude'] = array($dep['exclude']);
706 }
707
708 if (!isset($dep['min']) && !isset($dep['max']) &&
709 !isset($dep['recommended']) && !isset($dep['exclude'])
710 ) {
711 if ($installed || $downloaded) {
712 $installed = $installed ? 'installed' : 'downloaded';
713 if (isset($dep['conflicts'])) {
714 $rest = '';
715 if ($version) {
716 $rest = ", $installed version is " . $version;
717 }
718
719 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
720 return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
721 }
722
723 return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
724 }
725
726 return true;
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);
736 }
737
738 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
739 }
740
741 return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
742 }
743
744 if (!$installed && !$downloaded) {
745 if (isset($dep['conflicts'])) {
746 return true;
747 }
748
749 if ($required) {
750 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
751 return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
752 }
753
754 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
755 }
756
757 return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
758 }
759
760 $fail = false;
761 if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
762 $fail = true;
763 }
764
765 if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
766 $fail = true;
767 }
768
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 }
777
778 return $this->warning('warning: %s requires package "' . $depname . '"' .
779 $extra . ", $installed version is " . $version);
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 }
787
788 return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
789 $extra . ", $installed version is " . $version);
790 }
791
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']) &&
797 !isset($this->_options['force'])
798 ) {
799 return $this->raiseError('%s is not compatible with ' .
800 $installed . ' package "' .
801 $depname . '" version ' .
802 $exclude);
803 }
804
805 return $this->warning('warning: %s is not compatible with ' .
806 $installed . ' package "' .
807 $depname . '" version ' .
808 $exclude);
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 }
815
816 return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
817 $extra . ", $installed version is " . $version);
818 }
819 }
820 }
821
822 if (isset($dep['recommended'])) {
823 $installed = $installed ? 'installed' : 'downloaded';
824 if (version_compare($version, $dep['recommended'], '==')) {
825 return true;
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 }
839 }
840
841 if ($found) {
842 if ($param->isCompatible($parent)) {
843 return true;
844 }
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;
850 }
851 }
852 }
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']);
866 }
867
868 return true;
869 }
870
871 function _validatePackageInstall($dep, $required, $depv1 = false)
872 {
873 return $this->_validatePackageDownload($dep, $required, array(), $depv1);
874 }
875
883 {
884 if (PEAR::isError($this->_dependencydb)) {
886 }
887
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 }
896 $dp = new PEAR_Downloader_Package($dl);
897 $dp->setPackageFile($downloaded[$i]);
898 $params[$i] = $dp;
899 }
900
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 }
911
912 if (isset($badpackages[$memyselfandI]['errors'])) {
913 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
914 if (is_array($error)) {
915 $dl->log(0, $error[0]);
916 } else {
917 $dl->log(0, $error->getMessage());
918 }
919 }
920
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 }
926
927 return $this->raiseError(
928 '%s cannot be uninstalled, other installed packages depend on this package');
929 }
930
931 return true;
932 }
933
934 // first, list the immediate parents of each package to be uninstalled
935 $perpackagelist = array();
936 $allparents = array();
937 foreach ($params as $i => $param) {
938 $a = array(
939 'channel' => strtolower($param->getChannel()),
940 'package' => strtolower($param->getPackage())
941 );
942
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 }
969
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 }
980
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 }
995
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 }
1005
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);
1025
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 }
1034
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 }
1060
1061 $this->_currentPackage = $save;
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 }
1069
1070 if (isset($badpackages[$memyselfandI]['errors'])) {
1071 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
1072 if (is_array($error)) {
1073 $dl->log(0, $error[0]);
1074 } else {
1075 $dl->log(0, $error->getMessage());
1076 }
1077 }
1078
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 }
1084
1085 return $this->raiseError(
1086 '%s cannot be uninstalled, other installed packages depend on this package');
1087 }
1088 }
1089
1090 return true;
1091 }
1092
1093 function _validatePackageUninstall($dep, $required, $dl)
1094 {
1095 $depname = $this->_registry->parsedPackageNameToString($dep, true);
1096 $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
1097 if (!$version) {
1098 return true;
1099 }
1100
1101 $extra = self::_getExtraString($dep);
1102 if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
1103 $dep['exclude'] = array($dep['exclude']);
1104 }
1105
1106 if (isset($dep['conflicts'])) {
1107 return true; // uninstall OK - these packages conflict (probably installed with --force)
1108 }
1109
1110 if (!isset($dep['min']) && !isset($dep['max'])) {
1111 if (!$required) {
1112 return $this->warning('"' . $depname . '" can be optionally used by ' .
1113 'installed package %s' . $extra);
1114 }
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);
1123 }
1124
1125 $fail = false;
1126 if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
1127 $fail = true;
1128 }
1129
1130 if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
1131 $fail = true;
1132 }
1133
1134 // we re-use this variable, preserve the original value
1135 $saverequired = $required;
1136 if (!$required) {
1137 return $this->warning($depname . $extra . ' can be optionally used by installed package' .
1138 ' "%s"');
1139 }
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"');
1148 }
1149
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 }
1170
1171 $fail = false;
1172 if ($deps) {
1173 if (!class_exists('PEAR_Downloader_Package')) {
1174 require_once 'PEAR/Downloader/Package.php';
1175 }
1176
1177 $dp = new PEAR_Downloader_Package($dl);
1178 if (is_object($pkg)) {
1179 $dp->setPackageFile($pkg);
1180 } else {
1181 $dp->setDownloadURL($pkg);
1182 }
1183
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 }
1199
1200 foreach ($ds as $d) {
1201 $checker = new PEAR_Dependency2($this->_config, $this->_options,
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 }
1217
1218 if ($fail) {
1219 return $this->raiseError(
1220 '%s cannot be installed, conflicts with installed packages');
1221 }
1222
1223 return true;
1224 }
1225
1229 function validateDependency1($dep, $params = array())
1230 {
1231 if (!isset($dep['optional'])) {
1232 $dep['optional'] = 'no';
1233 }
1234
1235 list($newdep, $type) = self::normalizeDep($dep);
1236 if (!$newdep) {
1237 return $this->raiseError("Invalid Dependency");
1238 }
1239
1240 if (method_exists($this, "validate{$type}Dependency")) {
1241 return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
1242 $params, true);
1243 }
1244 }
1245
1249 static function normalizeDep($dep)
1250 {
1251 $types = array(
1252 'pkg' => 'Package',
1253 'ext' => 'Extension',
1254 'os' => 'Os',
1255 'php' => 'Php'
1256 );
1257
1258 if (!isset($types[$dep['type']])) {
1259 return array(false, false);
1260 }
1261
1262 $type = $types[$dep['type']];
1263
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 }
1273
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'])) {
1309 $newdep['min'] = '4.4.0';
1310 }
1311
1312 if (!isset($newdep['max'])) {
1313 $newdep['max'] = '6.0.0';
1314 }
1315 }
1316 return array($newdep, $type);
1317 }
1318
1328 static 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 }
1347
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}
const PEAR_ERROR_RETURN
Definition PEAR.php:24
const PEAR_VALIDATE_DOWNLOADING
Definition Validate.php:21
const PEAR_VALIDATE_INSTALLING
Definition Validate.php:18
validateArchDependency($dep)
matchSignature($pattern)
validateDependency1($dep, $params=array())
phpversion($name=null)
validatePackage($pkg, &$dl, $params=array())
__construct(&$config, $installoptions, $package, $state=PEAR_VALIDATE_INSTALLING)
validatePackageDependency($dep, $required, $params, $depv1=false)
validatePearinstallerDependency($dep)
static normalizeDep($dep)
static _getExtraString($dep)
_validatePackageUninstall($dep, $required, $dl)
_validatePackageInstall($dep, $required, $depv1=false)
_validatePackageDownload($dep, $required, $params, $depv1=false)
validateSubpackageDependency($dep, $required, $params)
validateExtensionDependency($dep, $required=true)
validatePackageUninstall(&$dl)
static signOperator($operator)
validatePhpDependency($dep)
static & singleton(&$config, $depdb=false)
$config
Definition pearcmd.php:182