PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file Dependency.php

Documentation is available at Dependency.php

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 5                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Tomas V.V.Cox <cox@idecnet.com>                             |
  17. // |          Stig Bakken <ssb@php.net>                                   |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Dependency.php,v 1.36.4.1 2004/12/27 07:04:19 cellog Exp $
  21.  
  22. require_once "PEAR.php";
  23.  
  24. define('PEAR_DEPENDENCY_MISSING',        -1);
  25. define('PEAR_DEPENDENCY_CONFLICT',       -2);
  26. define('PEAR_DEPENDENCY_UPGRADE_MINOR',  -3);
  27. define('PEAR_DEPENDENCY_UPGRADE_MAJOR',  -4);
  28. define('PEAR_DEPENDENCY_BAD_DEPENDENCY'-5);
  29. define('PEAR_DEPENDENCY_MISSING_OPTIONAL'-6);
  30. define('PEAR_DEPENDENCY_CONFLICT_OPTIONAL',       -7);
  31. define('PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL',  -8);
  32. define('PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL',  -9);
  33.  
  34. /**
  35.  * Dependency check for PEAR packages
  36.  *
  37.  * The class is based on the dependency RFC that can be found at
  38.  * http://cvs.php.net/cvs.php/pearweb/rfc. It requires PHP >= 4.1
  39.  *
  40.  * @author Tomas V.V.Vox <cox@idecnet.com>
  41.  * @author Stig Bakken <ssb@php.net>
  42.  */
  43. class PEAR_Dependency
  44. {
  45.     // {{{ constructor
  46.     /**
  47.      * Constructor
  48.      *
  49.      * @access public
  50.      * @param  object Registry object
  51.      * @return void 
  52.      */
  53.     function PEAR_Dependency(&$registry)
  54.     {
  55.         $this->registry &$registry;
  56.     }
  57.  
  58.     // }}}
  59.     // {{{ callCheckMethod()
  60.  
  61.     /**
  62.     * This method maps the XML dependency definition to the
  63.     * corresponding one from PEAR_Dependency
  64.     *
  65.     * <pre>
  66.     * $opts => Array
  67.     *    (
  68.     *        [type] => pkg
  69.     *        [rel] => ge
  70.     *        [version] => 3.4
  71.     *        [name] => HTML_Common
  72.     *        [optional] => false
  73.     *    )
  74.     * </pre>
  75.     *
  76.     * @param  string Error message
  77.     * @param  array  Options
  78.     * @return boolean 
  79.     */
  80.     function callCheckMethod(&$errmsg$opts)
  81.     {
  82.         $rel = isset($opts['rel']$opts['rel''has';
  83.         $req = isset($opts['version']$opts['version': null;
  84.         $name = isset($opts['name']$opts['name': null;
  85.         $opt (isset($opts['optional']&& $opts['optional'== 'yes'?
  86.             $opts['optional': null;
  87.         $errmsg '';
  88.         switch ($opts['type']{
  89.             case 'pkg':
  90.                 return $this->checkPackage($errmsg$name$req$rel$opt);
  91.                 break;
  92.             case 'ext':
  93.                 return $this->checkExtension($errmsg$name$req$rel$opt);
  94.                 break;
  95.             case 'php':
  96.                 return $this->checkPHP($errmsg$req$rel);
  97.                 break;
  98.             case 'prog':
  99.                 return $this->checkProgram($errmsg$name);
  100.                 break;
  101.             case 'os':
  102.                 return $this->checkOS($errmsg$name);
  103.                 break;
  104.             case 'sapi':
  105.                 return $this->checkSAPI($errmsg$name);
  106.                 break;
  107.             case 'zend':
  108.                 return $this->checkZend($errmsg$name);
  109.                 break;
  110.             default:
  111.                 return "'{$opts['type']}' dependency type not supported";
  112.         }
  113.     }
  114.  
  115.     // }}}
  116.     // {{{ checkPackage()
  117.  
  118.     /**
  119.      * Package dependencies check method
  120.      *
  121.      * @param string $errmsg    Empty string, it will be populated with an error message, if any
  122.      * @param string $name      Name of the package to test
  123.      * @param string $req       The package version required
  124.      * @param string $relation  How to compare versions with each other
  125.      * @param bool   $opt       Whether the relationship is optional
  126.      *
  127.      * @return mixed bool false if no error or the error string
  128.      */
  129.     function checkPackage(&$errmsg$name$req = null$relation 'has',
  130.                           $opt = false)
  131.     {
  132.         if (is_string($req&& substr($req02== 'v.'{
  133.             $req substr($req2);
  134.         }
  135.         switch ($relation{
  136.             case 'has':
  137.                 if (!$this->registry->packageExists($name)) {
  138.                     if ($opt{
  139.                         $errmsg = "package `$name' is recommended to utilize some features.";
  140.                         return PEAR_DEPENDENCY_MISSING_OPTIONAL;
  141.                     }
  142.                     $errmsg = "requires package `$name'";
  143.                     return PEAR_DEPENDENCY_MISSING;
  144.                 }
  145.                 return false;
  146.             case 'not':
  147.                 if ($this->registry->packageExists($name)) {
  148.                     $errmsg = "conflicts with package `$name'";
  149.                     return PEAR_DEPENDENCY_CONFLICT;
  150.                 }
  151.                 return false;
  152.             case 'lt':
  153.             case 'le':
  154.             case 'eq':
  155.             case 'ne':
  156.             case 'ge':
  157.             case 'gt':
  158.                 $version $this->registry->packageInfo($name'version');
  159.                 if (!$this->registry->packageExists($name)
  160.                     || !version_compare("$version""$req"$relation))
  161.                 {
  162.                     $code $this->codeFromRelation($relation$version$req$opt);
  163.                     if ($opt{
  164.                         $errmsg = "package `$name' version " . $this->signOperator($relation.
  165.                             " $req is recommended to utilize some features.";
  166.                         if ($version{
  167.                             $errmsg .= "  Installed version is $version";
  168.                         }
  169.                         return $code;
  170.                     }
  171.                     $errmsg = "requires package `$name" .
  172.                         $this->signOperator($relation. " $req";
  173.                     return $code;
  174.                 }
  175.                 return false;
  176.         }
  177.         $errmsg = "relation '$relation' with requirement '$req' is not supported (name=$name)";
  178.         return PEAR_DEPENDENCY_BAD_DEPENDENCY;
  179.     }
  180.  
  181.     // }}}
  182.     // {{{ checkPackageUninstall()
  183.  
  184.     /**
  185.      * Check package dependencies on uninstall
  186.      *
  187.      * @param string $error     The resultant error string
  188.      * @param string $warning   The resultant warning string
  189.      * @param string $name      Name of the package to test
  190.      *
  191.      * @return bool true if there were errors
  192.      */
  193.     function checkPackageUninstall(&$error&$warning$package)
  194.     {
  195.         $error = null;
  196.         $packages $this->registry->listPackages();
  197.         foreach ($packages as $pkg{
  198.             if ($pkg == $package{
  199.                 continue;
  200.             }
  201.             $deps $this->registry->packageInfo($pkg'release_deps');
  202.             if (empty($deps)) {
  203.                 continue;
  204.             }
  205.             foreach ($deps as $dep{
  206.                 if ($dep['type'== 'pkg' && strcasecmp($dep['name']$package== 0{
  207.                     if ($dep['rel'== 'ne' || $dep['rel'== 'not'{
  208.                         continue;
  209.                     }
  210.                     if (isset($dep['optional']&& $dep['optional'== 'yes'{
  211.                         $warning .= "\nWarning: Package '$pkg' optionally depends on '$package'";
  212.                     else {
  213.                         $error .= "Package '$pkg' depends on '$package'\n";
  214.                     }
  215.                 }
  216.             }
  217.         }
  218.         return ($error? true : false;
  219.     }
  220.  
  221.     // }}}
  222.     // {{{ checkExtension()
  223.  
  224.     /**
  225.      * Extension dependencies check method
  226.      *
  227.      * @param string $name        Name of the extension to test
  228.      * @param string $req_ext_ver Required extension version to compare with
  229.      * @param string $relation    How to compare versions with eachother
  230.      * @param bool   $opt         Whether the relationship is optional
  231.      *
  232.      * @return mixed bool false if no error or the error string
  233.      */
  234.     function checkExtension(&$errmsg$name$req = null$relation 'has',
  235.         $opt = false)
  236.     {
  237.         if ($relation == 'not'{
  238.             if (extension_loaded($name)) {
  239.                 $errmsg = "conflicts with  PHP extension '$name'";
  240.                 return PEAR_DEPENDENCY_CONFLICT;
  241.             else {
  242.                 return false;
  243.             }
  244.         }
  245.  
  246.         if (!extension_loaded($name)) {
  247.             if ($relation == 'not'{
  248.                 return false;
  249.             }
  250.             if ($opt{
  251.                 $errmsg = "'$name' PHP extension is recommended to utilize some features";
  252.                 return PEAR_DEPENDENCY_MISSING_OPTIONAL;
  253.             }
  254.             $errmsg = "'$name' PHP extension is not installed";
  255.             return PEAR_DEPENDENCY_MISSING;
  256.         }
  257.         if ($relation == 'has'{
  258.             return false;
  259.         }
  260.         $code = false;
  261.         if (is_string($req&& substr($req02== 'v.'{
  262.             $req substr($req2);
  263.         }
  264.         $ext_ver phpversion($name);
  265.         $operator $relation;
  266.         // Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90)
  267.         if (!version_compare("$ext_ver""$req"$operator)) {
  268.             $errmsg = "'$name' PHP extension version " .
  269.                 $this->signOperator($operator. " $req is required";
  270.             $code $this->codeFromRelation($relation$ext_ver$req$opt);
  271.             if ($opt{
  272.                 $errmsg = "'$name' PHP extension version " . $this->signOperator($operator.
  273.                     " $req is recommended to utilize some features";
  274.                 return $code;
  275.             }
  276.         }
  277.         return $code;
  278.     }
  279.  
  280.     // }}}
  281.     // {{{ checkOS()
  282.  
  283.     /**
  284.      * Operating system  dependencies check method
  285.      *
  286.      * @param string $os  Name of the operating system
  287.      *
  288.      * @return mixed bool false if no error or the error string
  289.      */
  290.     function checkOS(&$errmsg$os)
  291.     {
  292.         // XXX Fixme: Implement a more flexible way, like
  293.         // comma separated values or something similar to PEAR_OS
  294.         static $myos;
  295.         if (empty($myos)) {
  296.             include_once "OS/Guess.php";
  297.             $myos = new OS_Guess();
  298.         }
  299.         // only 'has' relation is currently supported
  300.         if ($myos->matchSignature($os)) {
  301.             return false;
  302.         }
  303.         $errmsg = "'$os' operating system not supported";
  304.         return PEAR_DEPENDENCY_CONFLICT;
  305.     }
  306.  
  307.     // }}}
  308.     // {{{ checkPHP()
  309.  
  310.     /**
  311.      * PHP version check method
  312.      *
  313.      * @param string $req   which version to compare
  314.      * @param string $relation  how to compare the version
  315.      *
  316.      * @return mixed bool false if no error or the error string
  317.      */
  318.     function checkPHP(&$errmsg$req$relation 'ge')
  319.     {
  320.         // this would be a bit stupid, but oh well :)
  321.         if ($relation == 'has'{
  322.             return false;
  323.         }
  324.         if ($relation == 'not'{
  325.             $errmsg 'Invalid dependency - "not" is not allowed for php dependencies, ' .
  326.                 'php cannot conflict with itself';
  327.             return PEAR_DEPENDENCY_BAD_DEPENDENCY;
  328.         }
  329.         if (substr($req02== 'v.'{
  330.             $req substr($req,2strlen($req- 2);
  331.         }
  332.         $php_ver phpversion();
  333.         $operator $relation;
  334.         if (!version_compare("$php_ver""$req"$operator)) {
  335.             $errmsg "PHP version " $this->signOperator($operator.
  336.                 " $req is required";
  337.             return PEAR_DEPENDENCY_CONFLICT;
  338.         }
  339.         return false;
  340.     }
  341.  
  342.     // }}}
  343.     // {{{ checkProgram()
  344.  
  345.     /**
  346.      * External program check method.  Looks for executable files in
  347.      * directories listed in the PATH environment variable.
  348.      *
  349.      * @param string $program   which program to look for
  350.      *
  351.      * @return mixed bool false if no error or the error string
  352.      */
  353.     function checkProgram(&$errmsg$program)
  354.     {
  355.         // XXX FIXME honor safe mode
  356.         $exe_suffix OS_WINDOWS ? '.exe' '';
  357.         $path_elements explode(PATH_SEPARATORgetenv('PATH'));
  358.         foreach ($path_elements as $dir{
  359.             $file $dir . DIRECTORY_SEPARATOR . $program $exe_suffix;
  360.             if (@file_exists($file&& @is_executable($file)) {
  361.                 return false;
  362.             }
  363.         }
  364.         $errmsg = "'$program' program is not present in the PATH";
  365.         return PEAR_DEPENDENCY_MISSING;
  366.     }
  367.  
  368.     // }}}
  369.     // {{{ checkSAPI()
  370.  
  371.     /**
  372.      * SAPI backend check method.  Version comparison is not yet
  373.      * available here.
  374.      *
  375.      * @param string $name      name of SAPI backend
  376.      * @param string $req   which version to compare
  377.      * @param string $relation  how to compare versions (currently
  378.      *                           hardcoded to 'has')
  379.      * @return mixed bool false if no error or the error string
  380.      */
  381.     function checkSAPI(&$errmsg$name$req = null$relation 'has')
  382.     {
  383.         // XXX Fixme: There is no way to know if the user has or
  384.         // not other SAPI backends installed than the installer one
  385.  
  386.         $sapi_backend php_sapi_name();
  387.         // Version comparisons not supported, sapi backends don't have
  388.         // version information yet.
  389.         if ($sapi_backend == $name{
  390.             return false;
  391.         }
  392.         $errmsg = "'$sapi_backend' SAPI backend not supported";
  393.         return PEAR_DEPENDENCY_CONFLICT;
  394.     }
  395.  
  396.     // }}}
  397.     // {{{ checkZend()
  398.  
  399.     /**
  400.      * Zend version check method
  401.      *
  402.      * @param string $req   which version to compare
  403.      * @param string $relation  how to compare the version
  404.      *
  405.      * @return mixed bool false if no error or the error string
  406.      */
  407.     function checkZend(&$errmsg$req$relation 'ge')
  408.     {
  409.         if (substr($req02== 'v.'{
  410.             $req substr($req,2strlen($req- 2);
  411.         }
  412.         $zend_ver zend_version();
  413.         $operator substr($relation,0,2);
  414.         if (!version_compare("$zend_ver""$req"$operator)) {
  415.             $errmsg "Zend version " $this->signOperator($operator.
  416.                 " $req is required";
  417.             return PEAR_DEPENDENCY_CONFLICT;
  418.         }
  419.         return false;
  420.     }
  421.  
  422.     // }}}
  423.     // {{{ signOperator()
  424.  
  425.     /**
  426.      * Converts text comparing operators to them sign equivalents
  427.      *
  428.      * Example: 'ge' to '>='
  429.      *
  430.      * @access public
  431.      * @param  string Operator
  432.      * @return string Sign equivalent
  433.      */
  434.     function signOperator($operator)
  435.     {
  436.         switch($operator{
  437.             case 'lt'return '<';
  438.             case 'le'return '<=';
  439.             case 'gt'return '>';
  440.             case 'ge'return '>=';
  441.             case 'eq'return '==';
  442.             case 'ne'return '!=';
  443.             default:
  444.                 return $operator;
  445.         }
  446.     }
  447.  
  448.     // }}}
  449.     // {{{ codeFromRelation()
  450.  
  451.     /**
  452.      * Convert relation into corresponding code
  453.      *
  454.      * @access public
  455.      * @param  string Relation
  456.      * @param  string Version
  457.      * @param  string Requirement
  458.      * @param  bool   Optional dependency indicator
  459.      * @return integer 
  460.      */
  461.     function codeFromRelation($relation$version$req$opt = false)
  462.     {
  463.         $code PEAR_DEPENDENCY_BAD_DEPENDENCY;
  464.         switch ($relation{
  465.             case 'gt': case 'ge': case 'eq':
  466.                 // upgrade
  467.                 $have_major preg_replace('/\D.*/'''$version);
  468.                 $need_major preg_replace('/\D.*/'''$req);
  469.                 if ($need_major $have_major{
  470.                     $code $opt PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL :
  471.                                    PEAR_DEPENDENCY_UPGRADE_MAJOR;
  472.                 else {
  473.                     $code $opt PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL :
  474.                                    PEAR_DEPENDENCY_UPGRADE_MINOR;
  475.                 }
  476.                 break;
  477.             case 'lt': case 'le': case 'ne':
  478.                 $code $opt PEAR_DEPENDENCY_CONFLICT_OPTIONAL :
  479.                                PEAR_DEPENDENCY_CONFLICT;
  480.                 break;
  481.         }
  482.         return $code;
  483.     }
  484.  
  485.     // }}}
  486. }
  487. ?>

Documentation generated on Mon, 11 Mar 2019 14:23:56 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.