12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358 |
- <?php
- /**
- * PEAR_Dependency2, advanced dependency validation
- *
- * PHP versions 4 and 5
- *
- * @category pear
- * @package PEAR
- * @author Greg Beaver <cellog@php.net>
- * @copyright 1997-2009 The Authors
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Dependency2.php 313023 2011-07-06 19:17:11Z dufuz $
- * @link http://pear.php.net/package/PEAR
- * @since File available since Release 1.4.0a1
- */
- /**
- * Required for the PEAR_VALIDATE_* constants
- */
- require_once 'PEAR/Validate.php';
- /**
- * Dependency check for PEAR packages
- *
- * This class handles both version 1.0 and 2.0 dependencies
- * WARNING: *any* changes to this class must be duplicated in the
- * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
- * or unit tests will not actually validate the changes
- * @category pear
- * @package PEAR
- * @author Greg Beaver <cellog@php.net>
- * @copyright 1997-2009 The Authors
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.9.4
- * @link http://pear.php.net/package/PEAR
- * @since Class available since Release 1.4.0a1
- */
- class PEAR_Dependency2
- {
- /**
- * One of the PEAR_VALIDATE_* states
- * @see PEAR_VALIDATE_NORMAL
- * @var integer
- */
- var $_state;
- /**
- * Command-line options to install/upgrade/uninstall commands
- * @param array
- */
- var $_options;
- /**
- * @var OS_Guess
- */
- var $_os;
- /**
- * @var PEAR_Registry
- */
- var $_registry;
- /**
- * @var PEAR_Config
- */
- var $_config;
- /**
- * @var PEAR_DependencyDB
- */
- var $_dependencydb;
- /**
- * Output of PEAR_Registry::parsedPackageName()
- * @var array
- */
- var $_currentPackage;
- /**
- * @param PEAR_Config
- * @param array installation options
- * @param array format of PEAR_Registry::parsedPackageName()
- * @param int installation state (one of PEAR_VALIDATE_*)
- */
- function PEAR_Dependency2(&$config, $installoptions, $package,
- $state = PEAR_VALIDATE_INSTALLING)
- {
- $this->_config = &$config;
- if (!class_exists('PEAR_DependencyDB')) {
- require_once 'PEAR/DependencyDB.php';
- }
- if (isset($installoptions['packagingroot'])) {
- // make sure depdb is in the right location
- $config->setInstallRoot($installoptions['packagingroot']);
- }
- $this->_registry = &$config->getRegistry();
- $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
- if (isset($installoptions['packagingroot'])) {
- $config->setInstallRoot(false);
- }
- $this->_options = $installoptions;
- $this->_state = $state;
- if (!class_exists('OS_Guess')) {
- require_once 'OS/Guess.php';
- }
- $this->_os = new OS_Guess;
- $this->_currentPackage = $package;
- }
- function _getExtraString($dep)
- {
- $extra = ' (';
- if (isset($dep['uri'])) {
- return '';
- }
- if (isset($dep['recommended'])) {
- $extra .= 'recommended version ' . $dep['recommended'];
- } else {
- if (isset($dep['min'])) {
- $extra .= 'version >= ' . $dep['min'];
- }
- if (isset($dep['max'])) {
- if ($extra != ' (') {
- $extra .= ', ';
- }
- $extra .= 'version <= ' . $dep['max'];
- }
- if (isset($dep['exclude'])) {
- if (!is_array($dep['exclude'])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- if ($extra != ' (') {
- $extra .= ', ';
- }
- $extra .= 'excluded versions: ';
- foreach ($dep['exclude'] as $i => $exclude) {
- if ($i) {
- $extra .= ', ';
- }
- $extra .= $exclude;
- }
- }
- }
- $extra .= ')';
- if ($extra == ' ()') {
- $extra = '';
- }
- return $extra;
- }
- /**
- * This makes unit-testing a heck of a lot easier
- */
- function getPHP_OS()
- {
- return PHP_OS;
- }
- /**
- * This makes unit-testing a heck of a lot easier
- */
- function getsysname()
- {
- return $this->_os->getSysname();
- }
- /**
- * Specify a dependency on an OS. Use arch for detailed os/processor information
- *
- * There are two generic OS dependencies that will be the most common, unix and windows.
- * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
- */
- function validateOsDependency($dep)
- {
- if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
- return true;
- }
- if ($dep['name'] == '*') {
- return true;
- }
- $not = isset($dep['conflicts']) ? true : false;
- switch (strtolower($dep['name'])) {
- case 'windows' :
- if ($not) {
- if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError("Cannot install %s on Windows");
- }
- return $this->warning("warning: Cannot install %s on Windows");
- }
- } else {
- if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError("Can only install %s on Windows");
- }
- return $this->warning("warning: Can only install %s on Windows");
- }
- }
- break;
- case 'unix' :
- $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
- if ($not) {
- if (in_array($this->getSysname(), $unices)) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError("Cannot install %s on any Unix system");
- }
- return $this->warning( "warning: Cannot install %s on any Unix system");
- }
- } else {
- if (!in_array($this->getSysname(), $unices)) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError("Can only install %s on a Unix system");
- }
- return $this->warning("warning: Can only install %s on a Unix system");
- }
- }
- break;
- default :
- if ($not) {
- if (strtolower($dep['name']) == strtolower($this->getSysname())) {
- if (!isset($this->_options['nodeps']) &&
- !isset($this->_options['force'])) {
- return $this->raiseError('Cannot install %s on ' . $dep['name'] .
- ' operating system');
- }
- return $this->warning('warning: Cannot install %s on ' .
- $dep['name'] . ' operating system');
- }
- } else {
- if (strtolower($dep['name']) != strtolower($this->getSysname())) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('Cannot install %s on ' .
- $this->getSysname() .
- ' operating system, can only install on ' . $dep['name']);
- }
- return $this->warning('warning: Cannot install %s on ' .
- $this->getSysname() .
- ' operating system, can only install on ' . $dep['name']);
- }
- }
- }
- return true;
- }
- /**
- * This makes unit-testing a heck of a lot easier
- */
- function matchSignature($pattern)
- {
- return $this->_os->matchSignature($pattern);
- }
- /**
- * Specify a complex dependency on an OS/processor/kernel version,
- * Use OS for simple operating system dependency.
- *
- * This is the only dependency that accepts an eregable pattern. The pattern
- * will be matched against the php_uname() output parsed by OS_Guess
- */
- function validateArchDependency($dep)
- {
- if ($this->_state != PEAR_VALIDATE_INSTALLING) {
- return true;
- }
- $not = isset($dep['conflicts']) ? true : false;
- if (!$this->matchSignature($dep['pattern'])) {
- if (!$not) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s Architecture dependency failed, does not ' .
- 'match "' . $dep['pattern'] . '"');
- }
- return $this->warning('warning: %s Architecture dependency failed, does ' .
- 'not match "' . $dep['pattern'] . '"');
- }
- return true;
- }
- if ($not) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s Architecture dependency failed, required "' .
- $dep['pattern'] . '"');
- }
- return $this->warning('warning: %s Architecture dependency failed, ' .
- 'required "' . $dep['pattern'] . '"');
- }
- return true;
- }
- /**
- * This makes unit-testing a heck of a lot easier
- */
- function extension_loaded($name)
- {
- return extension_loaded($name);
- }
- /**
- * This makes unit-testing a heck of a lot easier
- */
- function phpversion($name = null)
- {
- if ($name !== null) {
- return phpversion($name);
- }
- return phpversion();
- }
- function validateExtensionDependency($dep, $required = true)
- {
- if ($this->_state != PEAR_VALIDATE_INSTALLING &&
- $this->_state != PEAR_VALIDATE_DOWNLOADING) {
- return true;
- }
- $loaded = $this->extension_loaded($dep['name']);
- $extra = $this->_getExtraString($dep);
- if (isset($dep['exclude'])) {
- if (!is_array($dep['exclude'])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- }
- if (!isset($dep['min']) && !isset($dep['max']) &&
- !isset($dep['recommended']) && !isset($dep['exclude'])
- ) {
- if ($loaded) {
- if (isset($dep['conflicts'])) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s conflicts with PHP extension "' .
- $dep['name'] . '"' . $extra);
- }
- return $this->warning('warning: %s conflicts with PHP extension "' .
- $dep['name'] . '"' . $extra);
- }
- return true;
- }
- if (isset($dep['conflicts'])) {
- return true;
- }
- if ($required) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PHP extension "' .
- $dep['name'] . '"' . $extra);
- }
- return $this->warning('warning: %s requires PHP extension "' .
- $dep['name'] . '"' . $extra);
- }
- return $this->warning('%s can optionally use PHP extension "' .
- $dep['name'] . '"' . $extra);
- }
- if (!$loaded) {
- if (isset($dep['conflicts'])) {
- return true;
- }
- if (!$required) {
- return $this->warning('%s can optionally use PHP extension "' .
- $dep['name'] . '"' . $extra);
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
- '"' . $extra);
- }
- return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
- '"' . $extra);
- }
- $version = (string) $this->phpversion($dep['name']);
- if (empty($version)) {
- $version = '0';
- }
- $fail = false;
- if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
- $fail = true;
- }
- if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
- $fail = true;
- }
- if ($fail && !isset($dep['conflicts'])) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
- '"' . $extra . ', installed version is ' . $version);
- }
- return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
- '"' . $extra . ', installed version is ' . $version);
- } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s conflicts with PHP extension "' .
- $dep['name'] . '"' . $extra . ', installed version is ' . $version);
- }
- return $this->warning('warning: %s conflicts with PHP extension "' .
- $dep['name'] . '"' . $extra . ', installed version is ' . $version);
- }
- if (isset($dep['exclude'])) {
- foreach ($dep['exclude'] as $exclude) {
- if (version_compare($version, $exclude, '==')) {
- if (isset($dep['conflicts'])) {
- continue;
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s is not compatible with PHP extension "' .
- $dep['name'] . '" version ' .
- $exclude);
- }
- return $this->warning('warning: %s is not compatible with PHP extension "' .
- $dep['name'] . '" version ' .
- $exclude);
- } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s conflicts with PHP extension "' .
- $dep['name'] . '"' . $extra . ', installed version is ' . $version);
- }
- return $this->warning('warning: %s conflicts with PHP extension "' .
- $dep['name'] . '"' . $extra . ', installed version is ' . $version);
- }
- }
- }
- if (isset($dep['recommended'])) {
- if (version_compare($version, $dep['recommended'], '==')) {
- return true;
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
- ' version "' . $version . '"' .
- ' is not the recommended version "' . $dep['recommended'] .
- '", but may be compatible, use --force to install');
- }
- return $this->warning('warning: %s dependency: PHP extension ' .
- $dep['name'] . ' version "' . $version . '"' .
- ' is not the recommended version "' . $dep['recommended'].'"');
- }
- return true;
- }
- function validatePhpDependency($dep)
- {
- if ($this->_state != PEAR_VALIDATE_INSTALLING &&
- $this->_state != PEAR_VALIDATE_DOWNLOADING) {
- return true;
- }
- $version = $this->phpversion();
- $extra = $this->_getExtraString($dep);
- if (isset($dep['exclude'])) {
- if (!is_array($dep['exclude'])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- }
- if (isset($dep['min'])) {
- if (!version_compare($version, $dep['min'], '>=')) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PHP' .
- $extra . ', installed version is ' . $version);
- }
- return $this->warning('warning: %s requires PHP' .
- $extra . ', installed version is ' . $version);
- }
- }
- if (isset($dep['max'])) {
- if (!version_compare($version, $dep['max'], '<=')) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PHP' .
- $extra . ', installed version is ' . $version);
- }
- return $this->warning('warning: %s requires PHP' .
- $extra . ', installed version is ' . $version);
- }
- }
- if (isset($dep['exclude'])) {
- foreach ($dep['exclude'] as $exclude) {
- if (version_compare($version, $exclude, '==')) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s is not compatible with PHP version ' .
- $exclude);
- }
- return $this->warning(
- 'warning: %s is not compatible with PHP version ' .
- $exclude);
- }
- }
- }
- return true;
- }
- /**
- * This makes unit-testing a heck of a lot easier
- */
- function getPEARVersion()
- {
- return '1.9.4';
- }
- function validatePearinstallerDependency($dep)
- {
- $pearversion = $this->getPEARVersion();
- $extra = $this->_getExtraString($dep);
- if (isset($dep['exclude'])) {
- if (!is_array($dep['exclude'])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- }
- if (version_compare($pearversion, $dep['min'], '<')) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PEAR Installer' . $extra .
- ', installed version is ' . $pearversion);
- }
- return $this->warning('warning: %s requires PEAR Installer' . $extra .
- ', installed version is ' . $pearversion);
- }
- if (isset($dep['max'])) {
- if (version_compare($pearversion, $dep['max'], '>')) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires PEAR Installer' . $extra .
- ', installed version is ' . $pearversion);
- }
- return $this->warning('warning: %s requires PEAR Installer' . $extra .
- ', installed version is ' . $pearversion);
- }
- }
- if (isset($dep['exclude'])) {
- if (!isset($dep['exclude'][0])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- foreach ($dep['exclude'] as $exclude) {
- if (version_compare($exclude, $pearversion, '==')) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s is not compatible with PEAR Installer ' .
- 'version ' . $exclude);
- }
- return $this->warning('warning: %s is not compatible with PEAR ' .
- 'Installer version ' . $exclude);
- }
- }
- }
- return true;
- }
- function validateSubpackageDependency($dep, $required, $params)
- {
- return $this->validatePackageDependency($dep, $required, $params);
- }
- /**
- * @param array dependency information (2.0 format)
- * @param boolean whether this is a required dependency
- * @param array a list of downloaded packages to be installed, if any
- * @param boolean if true, then deps on pear.php.net that fail will also check
- * against pecl.php.net packages to accomodate extensions that have
- * moved to pecl.php.net from pear.php.net
- */
- function validatePackageDependency($dep, $required, $params, $depv1 = false)
- {
- if ($this->_state != PEAR_VALIDATE_INSTALLING &&
- $this->_state != PEAR_VALIDATE_DOWNLOADING) {
- return true;
- }
- if (isset($dep['providesextension'])) {
- if ($this->extension_loaded($dep['providesextension'])) {
- $save = $dep;
- $subdep = $dep;
- $subdep['name'] = $subdep['providesextension'];
- PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
- $ret = $this->validateExtensionDependency($subdep, $required);
- PEAR::popErrorHandling();
- if (!PEAR::isError($ret)) {
- return true;
- }
- }
- }
- if ($this->_state == PEAR_VALIDATE_INSTALLING) {
- return $this->_validatePackageInstall($dep, $required, $depv1);
- }
- if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
- return $this->_validatePackageDownload($dep, $required, $params, $depv1);
- }
- }
- function _validatePackageDownload($dep, $required, $params, $depv1 = false)
- {
- $dep['package'] = $dep['name'];
- if (isset($dep['uri'])) {
- $dep['channel'] = '__uri';
- }
- $depname = $this->_registry->parsedPackageNameToString($dep, true);
- $found = false;
- foreach ($params as $param) {
- if ($param->isEqual(
- array('package' => $dep['name'],
- 'channel' => $dep['channel']))) {
- $found = true;
- break;
- }
- if ($depv1 && $dep['channel'] == 'pear.php.net') {
- if ($param->isEqual(
- array('package' => $dep['name'],
- 'channel' => 'pecl.php.net'))) {
- $found = true;
- break;
- }
- }
- }
- if (!$found && isset($dep['providesextension'])) {
- foreach ($params as $param) {
- if ($param->isExtension($dep['providesextension'])) {
- $found = true;
- break;
- }
- }
- }
- if ($found) {
- $version = $param->getVersion();
- $installed = false;
- $downloaded = true;
- } else {
- if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
- $installed = true;
- $downloaded = false;
- $version = $this->_registry->packageinfo($dep['name'], 'version',
- $dep['channel']);
- } else {
- if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
- 'pear.php.net')) {
- $installed = true;
- $downloaded = false;
- $version = $this->_registry->packageinfo($dep['name'], 'version',
- 'pear.php.net');
- } else {
- $version = 'not installed or downloaded';
- $installed = false;
- $downloaded = false;
- }
- }
- }
- $extra = $this->_getExtraString($dep);
- if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- if (!isset($dep['min']) && !isset($dep['max']) &&
- !isset($dep['recommended']) && !isset($dep['exclude'])
- ) {
- if ($installed || $downloaded) {
- $installed = $installed ? 'installed' : 'downloaded';
- if (isset($dep['conflicts'])) {
- $rest = '';
- if ($version) {
- $rest = ", $installed version is " . $version;
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
- }
- return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
- }
- return true;
- }
- if (isset($dep['conflicts'])) {
- return true;
- }
- if ($required) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
- }
- return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
- }
- return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
- }
- if (!$installed && !$downloaded) {
- if (isset($dep['conflicts'])) {
- return true;
- }
- if ($required) {
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
- }
- return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
- }
- return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
- }
- $fail = false;
- if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
- $fail = true;
- }
- if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
- $fail = true;
- }
- if ($fail && !isset($dep['conflicts'])) {
- $installed = $installed ? 'installed' : 'downloaded';
- $dep['package'] = $dep['name'];
- $dep = $this->_registry->parsedPackageNameToString($dep, true);
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s requires package "' . $depname . '"' .
- $extra . ", $installed version is " . $version);
- }
- return $this->warning('warning: %s requires package "' . $depname . '"' .
- $extra . ", $installed version is " . $version);
- } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
- isset($dep['conflicts']) && !isset($dep['exclude'])) {
- $installed = $installed ? 'installed' : 'downloaded';
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
- ", $installed version is " . $version);
- }
- return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
- $extra . ", $installed version is " . $version);
- }
- if (isset($dep['exclude'])) {
- $installed = $installed ? 'installed' : 'downloaded';
- foreach ($dep['exclude'] as $exclude) {
- if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
- if (!isset($this->_options['nodeps']) &&
- !isset($this->_options['force'])
- ) {
- return $this->raiseError('%s is not compatible with ' .
- $installed . ' package "' .
- $depname . '" version ' .
- $exclude);
- }
- return $this->warning('warning: %s is not compatible with ' .
- $installed . ' package "' .
- $depname . '" version ' .
- $exclude);
- } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
- $installed = $installed ? 'installed' : 'downloaded';
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('%s conflicts with package "' . $depname . '"' .
- $extra . ", $installed version is " . $version);
- }
- return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
- $extra . ", $installed version is " . $version);
- }
- }
- }
- if (isset($dep['recommended'])) {
- $installed = $installed ? 'installed' : 'downloaded';
- if (version_compare($version, $dep['recommended'], '==')) {
- return true;
- }
- if (!$found && $installed) {
- $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
- }
- if ($param) {
- $found = false;
- foreach ($params as $parent) {
- if ($parent->isEqual($this->_currentPackage)) {
- $found = true;
- break;
- }
- }
- if ($found) {
- if ($param->isCompatible($parent)) {
- return true;
- }
- } else { // this is for validPackage() calls
- $parent = $this->_registry->getPackage($this->_currentPackage['package'],
- $this->_currentPackage['channel']);
- if ($parent !== null && $param->isCompatible($parent)) {
- return true;
- }
- }
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
- !isset($this->_options['loose'])
- ) {
- return $this->raiseError('%s dependency package "' . $depname .
- '" ' . $installed . ' version ' . $version .
- ' is not the recommended version ' . $dep['recommended'] .
- ', but may be compatible, use --force to install');
- }
- return $this->warning('warning: %s dependency package "' . $depname .
- '" ' . $installed . ' version ' . $version .
- ' is not the recommended version ' . $dep['recommended']);
- }
- return true;
- }
- function _validatePackageInstall($dep, $required, $depv1 = false)
- {
- return $this->_validatePackageDownload($dep, $required, array(), $depv1);
- }
- /**
- * Verify that uninstalling packages passed in to command line is OK.
- *
- * @param PEAR_Installer $dl
- * @return PEAR_Error|true
- */
- function validatePackageUninstall(&$dl)
- {
- if (PEAR::isError($this->_dependencydb)) {
- return $this->_dependencydb;
- }
- $params = array();
- // construct an array of "downloaded" packages to fool the package dependency checker
- // into using these to validate uninstalls of circular dependencies
- $downloaded = &$dl->getUninstallPackages();
- foreach ($downloaded as $i => $pf) {
- if (!class_exists('PEAR_Downloader_Package')) {
- require_once 'PEAR/Downloader/Package.php';
- }
- $dp = &new PEAR_Downloader_Package($dl);
- $dp->setPackageFile($downloaded[$i]);
- $params[$i] = &$dp;
- }
- // check cache
- $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
- strtolower($this->_currentPackage['package']);
- if (isset($dl->___uninstall_package_cache)) {
- $badpackages = $dl->___uninstall_package_cache;
- if (isset($badpackages[$memyselfandI]['warnings'])) {
- foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
- $dl->log(0, $warning[0]);
- }
- }
- if (isset($badpackages[$memyselfandI]['errors'])) {
- foreach ($badpackages[$memyselfandI]['errors'] as $error) {
- if (is_array($error)) {
- $dl->log(0, $error[0]);
- } else {
- $dl->log(0, $error->getMessage());
- }
- }
- if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
- return $this->warning(
- 'warning: %s should not be uninstalled, other installed packages depend ' .
- 'on this package');
- }
- return $this->raiseError(
- '%s cannot be uninstalled, other installed packages depend on this package');
- }
- return true;
- }
- // first, list the immediate parents of each package to be uninstalled
- $perpackagelist = array();
- $allparents = array();
- foreach ($params as $i => $param) {
- $a = array(
- 'channel' => strtolower($param->getChannel()),
- 'package' => strtolower($param->getPackage())
- );
- $deps = $this->_dependencydb->getDependentPackages($a);
- if ($deps) {
- foreach ($deps as $d) {
- $pardeps = $this->_dependencydb->getDependencies($d);
- foreach ($pardeps as $dep) {
- if (strtolower($dep['dep']['channel']) == $a['channel'] &&
- strtolower($dep['dep']['name']) == $a['package']) {
- if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
- $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
- }
- $perpackagelist[$a['channel'] . '/' . $a['package']][]
- = array($d['channel'] . '/' . $d['package'], $dep);
- if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
- $allparents[$d['channel'] . '/' . $d['package']] = array();
- }
- if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
- $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
- }
- $allparents[$d['channel'] . '/' . $d['package']]
- [$a['channel'] . '/' . $a['package']][]
- = array($d, $dep);
- }
- }
- }
- }
- }
- // next, remove any packages from the parents list that are not installed
- $remove = array();
- foreach ($allparents as $parent => $d1) {
- foreach ($d1 as $d) {
- if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
- continue;
- }
- $remove[$parent] = true;
- }
- }
- // next remove any packages from the parents list that are not passed in for
- // uninstallation
- foreach ($allparents as $parent => $d1) {
- foreach ($d1 as $d) {
- foreach ($params as $param) {
- if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
- strtolower($param->getPackage()) == $d[0][0]['package']) {
- // found it
- continue 3;
- }
- }
- $remove[$parent] = true;
- }
- }
- // remove all packages whose dependencies fail
- // save which ones failed for error reporting
- $badchildren = array();
- do {
- $fail = false;
- foreach ($remove as $package => $unused) {
- if (!isset($allparents[$package])) {
- continue;
- }
- foreach ($allparents[$package] as $kid => $d1) {
- foreach ($d1 as $depinfo) {
- if ($depinfo[1]['type'] != 'optional') {
- if (isset($badchildren[$kid])) {
- continue;
- }
- $badchildren[$kid] = true;
- $remove[$kid] = true;
- $fail = true;
- continue 2;
- }
- }
- }
- if ($fail) {
- // start over, we removed some children
- continue 2;
- }
- }
- } while ($fail);
- // next, construct the list of packages that can't be uninstalled
- $badpackages = array();
- $save = $this->_currentPackage;
- foreach ($perpackagelist as $package => $packagedeps) {
- foreach ($packagedeps as $parent) {
- if (!isset($remove[$parent[0]])) {
- continue;
- }
- $packagename = $this->_registry->parsePackageName($parent[0]);
- $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
- $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
- $packagename['package'] = $pa->getPackage();
- $this->_currentPackage = $packagename;
- // parent is not present in uninstall list, make sure we can actually
- // uninstall it (parent dep is optional)
- $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
- $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
- $parentname['package'] = $pa->getPackage();
- $parent[1]['dep']['package'] = $parentname['package'];
- $parent[1]['dep']['channel'] = $parentname['channel'];
- if ($parent[1]['type'] == 'optional') {
- $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
- if ($test !== true) {
- $badpackages[$package]['warnings'][] = $test;
- }
- } else {
- $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
- if ($test !== true) {
- $badpackages[$package]['errors'][] = $test;
- }
- }
- }
- }
- $this->_currentPackage = $save;
- $dl->___uninstall_package_cache = $badpackages;
- if (isset($badpackages[$memyselfandI])) {
- if (isset($badpackages[$memyselfandI]['warnings'])) {
- foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
- $dl->log(0, $warning[0]);
- }
- }
- if (isset($badpackages[$memyselfandI]['errors'])) {
- foreach ($badpackages[$memyselfandI]['errors'] as $error) {
- if (is_array($error)) {
- $dl->log(0, $error[0]);
- } else {
- $dl->log(0, $error->getMessage());
- }
- }
- if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
- return $this->warning(
- 'warning: %s should not be uninstalled, other installed packages depend ' .
- 'on this package');
- }
- return $this->raiseError(
- '%s cannot be uninstalled, other installed packages depend on this package');
- }
- }
- return true;
- }
- function _validatePackageUninstall($dep, $required, $dl)
- {
- $depname = $this->_registry->parsedPackageNameToString($dep, true);
- $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
- if (!$version) {
- return true;
- }
- $extra = $this->_getExtraString($dep);
- if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
- $dep['exclude'] = array($dep['exclude']);
- }
- if (isset($dep['conflicts'])) {
- return true; // uninstall OK - these packages conflict (probably installed with --force)
- }
- if (!isset($dep['min']) && !isset($dep['max'])) {
- if (!$required) {
- return $this->warning('"' . $depname . '" can be optionally used by ' .
- 'installed package %s' . $extra);
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError('"' . $depname . '" is required by ' .
- 'installed package %s' . $extra);
- }
- return $this->warning('warning: "' . $depname . '" is required by ' .
- 'installed package %s' . $extra);
- }
- $fail = false;
- if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
- $fail = true;
- }
- if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
- $fail = true;
- }
- // we re-use this variable, preserve the original value
- $saverequired = $required;
- if (!$required) {
- return $this->warning($depname . $extra . ' can be optionally used by installed package' .
- ' "%s"');
- }
- if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
- return $this->raiseError($depname . $extra . ' is required by installed package' .
- ' "%s"');
- }
- return $this->raiseError('warning: ' . $depname . $extra .
- ' is required by installed package "%s"');
- }
- /**
- * validate a downloaded package against installed packages
- *
- * As of PEAR 1.4.3, this will only validate
- *
- * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
- * $pkg package identifier (either
- * array('package' => blah, 'channel' => blah) or an array with
- * index 'info' referencing an object)
- * @param PEAR_Downloader $dl
- * @param array $params full list of packages to install
- * @return true|PEAR_Error
- */
- function validatePackage($pkg, &$dl, $params = array())
- {
- if (is_array($pkg) && isset($pkg['info'])) {
- $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
- } else {
- $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
- }
- $fail = false;
- if ($deps) {
- if (!class_exists('PEAR_Downloader_Package')) {
- require_once 'PEAR/Downloader/Package.php';
- }
- $dp = &new PEAR_Downloader_Package($dl);
- if (is_object($pkg)) {
- $dp->setPackageFile($pkg);
- } else {
- $dp->setDownloadURL($pkg);
- }
- PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
- foreach ($deps as $channel => $info) {
- foreach ($info as $package => $ds) {
- foreach ($params as $packd) {
- if (strtolower($packd->getPackage()) == strtolower($package) &&
- $packd->getChannel() == $channel) {
- $dl->log(3, 'skipping installed package check of "' .
- $this->_registry->parsedPackageNameToString(
- array('channel' => $channel, 'package' => $package),
- true) .
- '", version "' . $packd->getVersion() . '" will be ' .
- 'downloaded and installed');
- continue 2; // jump to next package
- }
- }
- foreach ($ds as $d) {
- $checker = &new PEAR_Dependency2($this->_config, $this->_options,
- array('channel' => $channel, 'package' => $package), $this->_state);
- $dep = $d['dep'];
- $required = $d['type'] == 'required';
- $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
- if (is_array($ret)) {
- $dl->log(0, $ret[0]);
- } elseif (PEAR::isError($ret)) {
- $dl->log(0, $ret->getMessage());
- $fail = true;
- }
- }
- }
- }
- PEAR::popErrorHandling();
- }
- if ($fail) {
- return $this->raiseError(
- '%s cannot be installed, conflicts with installed packages');
- }
- return true;
- }
- /**
- * validate a package.xml 1.0 dependency
- */
- function validateDependency1($dep, $params = array())
- {
- if (!isset($dep['optional'])) {
- $dep['optional'] = 'no';
- }
- list($newdep, $type) = $this->normalizeDep($dep);
- if (!$newdep) {
- return $this->raiseError("Invalid Dependency");
- }
- if (method_exists($this, "validate{$type}Dependency")) {
- return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
- $params, true);
- }
- }
- /**
- * Convert a 1.0 dep into a 2.0 dep
- */
- function normalizeDep($dep)
- {
- $types = array(
- 'pkg' => 'Package',
- 'ext' => 'Extension',
- 'os' => 'Os',
- 'php' => 'Php'
- );
- if (!isset($types[$dep['type']])) {
- return array(false, false);
- }
- $type = $types[$dep['type']];
- $newdep = array();
- switch ($type) {
- case 'Package' :
- $newdep['channel'] = 'pear.php.net';
- case 'Extension' :
- case 'Os' :
- $newdep['name'] = $dep['name'];
- break;
- }
- $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
- switch ($dep['rel']) {
- case 'has' :
- return array($newdep, $type);
- break;
- case 'not' :
- $newdep['conflicts'] = true;
- break;
- case '>=' :
- case '>' :
- $newdep['min'] = $dep['version'];
- if ($dep['rel'] == '>') {
- $newdep['exclude'] = $dep['version'];
- }
- break;
- case '<=' :
- case '<' :
- $newdep['max'] = $dep['version'];
- if ($dep['rel'] == '<') {
- $newdep['exclude'] = $dep['version'];
- }
- break;
- case 'ne' :
- case '!=' :
- $newdep['min'] = '0';
- $newdep['max'] = '100000';
- $newdep['exclude'] = $dep['version'];
- break;
- case '==' :
- $newdep['min'] = $dep['version'];
- $newdep['max'] = $dep['version'];
- break;
- }
- if ($type == 'Php') {
- if (!isset($newdep['min'])) {
- $newdep['min'] = '4.4.0';
- }
- if (!isset($newdep['max'])) {
- $newdep['max'] = '6.0.0';
- }
- }
- return array($newdep, $type);
- }
- /**
- * Converts text comparing operators to them sign equivalents
- *
- * Example: 'ge' to '>='
- *
- * @access public
- * @param string Operator
- * @return string Sign equivalent
- */
- function signOperator($operator)
- {
- switch($operator) {
- case 'lt': return '<';
- case 'le': return '<=';
- case 'gt': return '>';
- case 'ge': return '>=';
- case 'eq': return '==';
- case 'ne': return '!=';
- default:
- return $operator;
- }
- }
- function raiseError($msg)
- {
- if (isset($this->_options['ignore-errors'])) {
- return $this->warning($msg);
- }
- return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
- $this->_currentPackage, true)));
- }
- function warning($msg)
- {
- return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
- $this->_currentPackage, true)));
- }
- }
|