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

Source for file PackageUpdate.php

Documentation is available at PackageUpdate.php

  1. <?php
  2. /**
  3.  * A package to make adding self updating functionality to other
  4.  * packages easy.
  5.  *
  6.  * PHP versions 4 and 5
  7.  *
  8.  * LICENSE: This source file is subject to version 3.01 of the PHP license
  9.  * that is available through the world-wide-web at the following URI:
  10.  * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
  11.  * the PHP License and are unable to obtain it through the web, please
  12.  * send a note to license@php.net so we can mail you a copy immediately.
  13.  *
  14.  * CREDITS: To Ian Eure <ieure@php.net>
  15.  *          for repackage PEAR_Errors for use with ErrorStack
  16.  *          see repackagePEARError()
  17.  *
  18.  * @category  PEAR
  19.  * @package   PEAR_PackageUpdate
  20.  * @author    Scott Mattocks <scottmattocks@php.net>
  21.  * @author    Laurent Laville <pear@laurent-laville.org>
  22.  * @copyright 2006-2008 Scott Mattocks
  23.  * @license   http://www.php.net/license/3_01.txt  PHP License 3.01
  24.  * @version   CVS: $Id: PackageUpdate.php,v 1.34 2008/06/14 22:01:45 farell Exp $
  25.  * @link      http://pear.php.net/package/PEAR_PackageUpdate
  26.  * @since     File available since Release 0.4.0a1
  27.  */
  28.  
  29. require_once 'PEAR/ErrorStack.php';
  30. require_once 'PEAR/Config.php';
  31.  
  32. // PEAR_PACKAGEUPDATE_PREF_*  Constants for preferences.
  33. /**
  34.  * Check to see if the user wants to be notified about any updates for
  35.  * this package.
  36.  */
  37. define('PEAR_PACKAGEUPDATE_PREF_NOUPDATES'0);
  38. /**
  39.  * Check to see if the user has requested not to be asked until a new
  40.  * version is released.
  41.  */
  42. define('PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE'1);
  43. /**
  44.  * Check to see if the user only wants to be asked about a certain
  45.  * type of release (bug|minor|major).
  46.  */
  47. define('PEAR_PACKAGEUPDATE_PREF_TYPE'2);
  48. /**
  49.  * Check to see if the user has requested not to be asked about the
  50.  * state of the latest release.
  51.  */
  52. define('PEAR_PACKAGEUPDATE_PREF_STATE'3);
  53.  
  54. // PEAR_PACKAGEUPDATE_STATE_*  Constants for states.
  55. /**
  56.  * Check to see if the user has requested to be asked when
  57.  * the latest release is a snapshot release.
  58.  */
  59. define('PEAR_PACKAGEUPDATE_STATE_SNAPSHOT''snapshot');
  60. /**
  61.  * Check to see if the user has requested to be asked when
  62.  * the latest release is a devel release.
  63.  */
  64. define('PEAR_PACKAGEUPDATE_STATE_DEVEL''devel');
  65. /**
  66.  * Check to see if the user has requested to be asked when
  67.  * the latest release is an alpha release.
  68.  */
  69. define('PEAR_PACKAGEUPDATE_STATE_ALPHA''alpha');
  70. /**
  71.  * Check to see if the user has requested to be asked when
  72.  * the latest release is an beta release.
  73.  */
  74. define('PEAR_PACKAGEUPDATE_STATE_BETA''beta');
  75. /**
  76.  * Check to see if the user has requested to be asked when
  77.  * the latest release is a stable release.
  78.  */
  79. define('PEAR_PACKAGEUPDATE_STATE_STABLE''stable');
  80.  
  81. // PEAR_PACKAGEUPDATE_TYPE_*  Constants for release types.
  82. /**
  83.  * Check to see if the user only wants to be asked about a bug release
  84.  */
  85. define('PEAR_PACKAGEUPDATE_TYPE_BUG''bug');
  86. /**
  87.  * Check to see if the user only wants to be asked about a minor release
  88.  */
  89. define('PEAR_PACKAGEUPDATE_TYPE_MINOR''minor');
  90. /**
  91.  * Check to see if the user only wants to be asked about a major release
  92.  */
  93. define('PEAR_PACKAGEUPDATE_TYPE_MAJOR''major');
  94.  
  95. // PEAR_PACKAGEUPDATE_ERROR_*  Constants for errors.
  96. /**
  97.  * No package name provided
  98.  */
  99. define('PEAR_PACKAGEUPDATE_ERROR_NOPACKAGE'-1);
  100. /**
  101.  * No channel name provided
  102.  */
  103. define('PEAR_PACKAGEUPDATE_ERROR_NOCHANNEL'-2);
  104. /**
  105.  * No update information is available for the package
  106.  */
  107. define('PEAR_PACKAGEUPDATE_ERROR_NOINFO'-3);
  108. /**
  109.  * The package is not installed. It cannot be updated.
  110.  */
  111. define('PEAR_PACKAGEUPDATE_ERROR_NOTINSTALLED'-4);
  112. /**
  113.  * Preferences cannot be read from file because of access permission errors
  114.  */
  115. define('PEAR_PACKAGEUPDATE_ERROR_PREFFILE_READACCESS'-5);
  116. /**
  117.  * Preferences cannot be written to file because of access permission errors
  118.  */
  119. define('PEAR_PACKAGEUPDATE_ERROR_PREFFILE_WRITEACCESS'-6);
  120. /**
  121.  * An error occurred while trying to write the preferences to file
  122.  */
  123. define('PEAR_PACKAGEUPDATE_ERROR_PREFFILE_WRITEERROR'-7);
  124. /**
  125.  * Preferences file is corrupted
  126.  */
  127. define('PEAR_PACKAGEUPDATE_ERROR_PREFFILE_CORRUPTED'-8);
  128. /**
  129.  * Invalid release type
  130.  */
  131. define('PEAR_PACKAGEUPDATE_ERROR_INVALIDTYPE'-9);
  132. /**
  133.  * Invalid release state
  134.  */
  135. define('PEAR_PACKAGEUPDATE_ERROR_INVALIDSTATE'-10);
  136. /**
  137.  * Invalid preference identifier
  138.  */
  139. define('PEAR_PACKAGEUPDATE_ERROR_INVALIDPREF'-11);
  140. /**
  141. * Driver (backend) could not be found.
  142.  */
  143. define('PEAR_PACKAGEUPDATE_ERROR_NONEXISTENTDRIVER'-12);
  144. /**
  145.  * Invalid INI file
  146.  */
  147. define('PEAR_PACKAGEUPDATE_ERROR_INVALIDINIFILE'-13);
  148.  
  149. // Error messages.
  150. $GLOBALS['_PEAR_PACKAGEUPDATE_ERRORS'=
  151.     array(
  152.             'No package name provided',
  153.             'No channel name provided',
  154.             'No update information is available for %packagename%.',
  155.             '%packagename% is not installed. It cannot be updated.',
  156.             'Preferences cannot be read from %file%.',
  157.             'Preferences cannot be written to %file% ' .
  158.             'because of access permission errors.',
  159.             'An error occurred while trying to write the preferences to %file%.',
  160.             'Preferences file is corrupted.',
  161.             'Invalid release type: %type%',
  162.             'Invalid release state: %state%',
  163.             'Invalid preference: %preference%',
  164.             'Driver %drivername% could not be found.',
  165.             'Invalid (%layer%) INI file : %file%'
  166.     );
  167.  
  168. /**
  169.  * The package allows a developer to add a few lines of code to
  170.  * their existing packages and have the ability to update their
  171.  * package automatically. This auto-update ability allows users
  172.  * to stay up to date much more easily than requiring them to
  173.  * update manually.
  174.  *
  175.  * This package keeps track of user preferences such as "don't
  176.  * remind me again".
  177.  *
  178.  * This package is designed to be a backend to different front
  179.  * ends written for this package. For example, this package can
  180.  * be used to drive a PHP-GTK 2, CLI or web front end. The API
  181.  * for this package should be flexible enough to allow any type
  182.  * of front end to be used and also to allow the package to be
  183.  * used directly in another package without a front end driver.
  184.  *
  185.  * The interface for this package must allow for the following
  186.  * functionality:
  187.  * - check to see if a new version is available for a given
  188.  *   package on a given channel
  189.  *   - check minimum state
  190.  * - present information regarding the upgrade (version, size)
  191.  *   - inform user about dependencies
  192.  * - allow user to confirm or cancel upgrade
  193.  * - download and install the package
  194.  * - track preferences on a per package basis
  195.  *   - don't ask again
  196.  *   - don't ask until next release
  197.  *   - only ask for state XXXX or higher
  198.  *   - bug/minor/major updates only
  199.  * - update channel automatically
  200.  * - force application to exit when upgrade complete
  201.  *   - PHP-GTK/CLI apps must exit to allow classes to reload
  202.  *   - web front end could send headers to reload certain page
  203.  *
  204.  * This class is simply a wrapper for PEAR classes that actually
  205.  * do the work.
  206.  *
  207.  * EXAMPLE:
  208.  * <code>
  209.  * <?php
  210.  *  class Goo {
  211.  *      function __construct()
  212.  *      {
  213.  *          // Check for updates...
  214.  *          require_once 'PEAR/PackageUpdate.php';
  215.  *          $ppu =& PEAR_PackageUpdate::factory('Gtk2', 'Goo', 'pear');
  216.  *          if ($ppu !== false) {
  217.  *              if ($ppu->checkUpdate()) {
  218.  *                  // Use a dialog window to ask permission to update.
  219.  *                  if ($ppu->presentUpdate()) {
  220.  *                      if ($ppu->update()) {
  221.  *                          // If the update succeeded, the application should
  222.  *                          // be restarted.
  223.  *                          $ppu->forceRestart();
  224.  *                      }
  225.  *                  }
  226.  *              }
  227.  *          }
  228.  *          // ...
  229.  *      }
  230.  *      // ...
  231.  *  }
  232.  * ?>
  233.  * </code>
  234.  *
  235.  * @category  PEAR
  236.  * @package   PEAR_PackageUpdate
  237.  * @author    Scott Mattocks <scottmattocks@php.net>
  238.  * @author    Laurent Laville <pear@laurent-laville.org>
  239.  * @copyright 2006-2008 Scott Mattocks
  240.  * @license   http://www.php.net/license/3_01.txt  PHP License 3.01
  241.  * @version   Release: 1.0.2
  242.  * @link      http://pear.php.net/package/PEAR_PackageUpdate
  243.  * @since     Class available since Release 0.4.0a1
  244.  */
  245.  
  246. {
  247.     /**
  248.      * The user's update preferences.
  249.      *
  250.      * @access public
  251.      * @var    array 
  252.      * @since  0.4.0a1
  253.      */
  254.     var $preferences = array();
  255.  
  256.     /**
  257.      * The file to read PPU user-defined options from
  258.      *
  259.      * @access public
  260.      * @var    string 
  261.      * @since  0.7.0
  262.      */
  263.     var $pref_file;
  264.  
  265.     /**
  266.      * The file to read PEAR user-defined options from
  267.      *
  268.      * @access public
  269.      * @var    string 
  270.      * @since  0.7.0
  271.      */
  272.     var $user_file;
  273.  
  274.     /**
  275.      * The file to read PEAR system-wide defaults from
  276.      *
  277.      * @access public
  278.      * @var    string 
  279.      * @since  0.7.0
  280.      */
  281.     var $system_file;
  282.  
  283.     /**
  284.      * The name of the package.
  285.      *
  286.      * @access public
  287.      * @var    string 
  288.      * @since  0.4.0a1
  289.      */
  290.     var $packageName;
  291.  
  292.     /**
  293.      * The channel the package is hosted on.
  294.      *
  295.      * @access public
  296.      * @var    string 
  297.      * @since  0.4.0a1
  298.      */
  299.     var $channel;
  300.  
  301.     /**
  302.      * The latest version available for the given package.
  303.      *
  304.      * @access public
  305.      * @var    string 
  306.      * @since  0.4.0a1
  307.      */
  308.     var $latestVersion;
  309.  
  310.     /**
  311.      * Information about the latest version of the package.
  312.      *
  313.      * @access public
  314.      * @var    array 
  315.      * @since  0.4.0a1
  316.      */
  317.     var $info = array();
  318.  
  319.     /**
  320.      * The current installed version of the package.
  321.      *
  322.      * @access public
  323.      * @var    string 
  324.      * @since  0.4.0a1
  325.      */
  326.     var $instVersion;
  327.  
  328.     /**
  329.      * Informations about the current installed version of the package.
  330.      *
  331.      * @access protected
  332.      * @var    array 
  333.      * @since  0.6.0
  334.      * @see    PEAR_Registry::packageInfo()
  335.      */
  336.     var $instInfo;
  337.  
  338.     /**
  339.      * A collection of errors that have occurred.
  340.      *
  341.      * @access public
  342.      * @var    object 
  343.      * @since  0.4.0a1
  344.      */
  345.     var $errors;
  346.  
  347.     /**
  348.      * PHP 4 style constructor. Calls the PHP 5 style constructor.
  349.      *
  350.      * @param string $packageName The package to update.
  351.      * @param string $channel     The channel the package resides on.
  352.      * @param string $user_file   (optional) file to read PEAR user-defined
  353.      *                             options from
  354.      * @param string $system_file (optional) file to read PEAR system-wide
  355.      *                             defaults from
  356.      * @param string $pref_file   (optional) file to read PPU user-defined
  357.      *                             options from
  358.      *
  359.      * @access public
  360.      * @return void 
  361.      * @since  version 0.4.0a1 (2006-03-28)
  362.      */
  363.     function PEAR_PackageUpdate($packageName$channel,
  364.         $user_file ''$system_file ''$pref_file '')
  365.     {
  366.         PEAR_PackageUpdate::__construct($packageName$channel,
  367.             $user_file$system_file$pref_file);
  368.     }
  369.  
  370.     /**
  371.      * PHP 5 style constructor. Loads the user preferences.
  372.      *
  373.      * @param string $packageName The package to update.
  374.      * @param string $channel     The channel the package resides on.
  375.      * @param string $user_file   (optional) file to read PEAR user-defined
  376.      *                             options from
  377.      * @param string $system_file (optional) file to read PEAR system-wide
  378.      *                             defaults from
  379.      * @param string $pref_file   (optional) file to read PPU user-defined
  380.      *                             options from
  381.      *
  382.      * @access public
  383.      * @return void 
  384.      * @since  version 0.4.0a1 (2006-03-28)
  385.      * @throws PEAR_PACKAGEUPDATE_ERROR_INVALIDINIFILE
  386.      */
  387.     function __construct($packageName$channel,
  388.         $user_file ''$system_file ''$pref_file '')
  389.     {
  390.         // Create a pear error stack.
  391.         $this->errors =PEAR_ErrorStack::singleton(get_class($this));
  392.         $this->errors->setContextCallback(array(&$this'_getBacktrace'));
  393.  
  394.         // Set the package name and channel.
  395.         $this->packageName = $packageName;
  396.         $this->channel     = $channel;
  397.  
  398.         if ($user_file && !file_exists($user_file)) {
  399.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_INVALIDINIFILE,
  400.                 'warning',
  401.                 array('layer' => 'pear-user''file' => $user_file));
  402.             $user_file ''// force to use default user configuration
  403.         }
  404.         if ($system_file && !file_exists($system_file)) {
  405.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_INVALIDINIFILE,
  406.                 'warning',
  407.                 array('layer' => 'pear-system''file' => $system_file));
  408.             $system_file ''// force to use default system configuration
  409.         }
  410.  
  411.         // Set the file to read PEAR user-defined options from
  412.         $this->user_file = $user_file;
  413.         // Set the file to read PEAR system-wide defaults from
  414.         $this->system_file = $system_file;
  415.         // Set the file to read PPU user-defined options from
  416.         $this->pref_file = $pref_file;
  417.  
  418.         // Load the user's preferences.
  419.         $this->loadPreferences($pref_file);
  420.     }
  421.  
  422.     /**
  423.      * Callback that generates context information (location of error)
  424.      * for the package error stack.
  425.      *
  426.      * @access private
  427.      * @return mixed  backtrace context array or false is unavailable
  428.      * @since  version 0.4.3 (2006-04-25)
  429.      */
  430.     function _getBacktrace()
  431.     {
  432.         $backtrace debug_backtrace();
  433.         $backtrace $backtrace[count($backtrace)-1];
  434.         return $backtrace;
  435.     }
  436.  
  437.     /**
  438.      * Creates an instance of the given update class.
  439.      *
  440.      * @param string $driver      The type of PPU to create.
  441.      * @param string $packageName The package to update.
  442.      * @param string $channel     The channel the package resides on.
  443.      * @param string $user_file   (optional) file to read PEAR user-defined
  444.      *                             options from
  445.      * @param string $system_file (optional) file to read PEAR system-wide
  446.      *                             defaults from
  447.      * @param string $pref_file   (optional) file to read PPU user-defined
  448.      *                             options from
  449.      *
  450.      * @return object An instance of type PEAR_PackageUpdate_$driver
  451.      * @static
  452.      * @access public
  453.      * @since  version 0.4.0a1 (2006-03-28)
  454.      * @throws PEAR_PACKAGEUPDATE_ERROR_NONEXISTENTDRIVER
  455.      */
  456.     function &factory($driver$packageName$channel,
  457.         $user_file ''$system_file ''$pref_file '')
  458.     {
  459.         $class 'PEAR_PackageUpdate_' $driver;
  460.  
  461.         // Attempt to include a custom version of the named class, but don't treat
  462.         // a failure as fatal.  The caller may have already included their own
  463.         // version of the named class.
  464.         if (!class_exists($class)) {
  465.  
  466.             // Try to include the driver.
  467.             $file 'PEAR/PackageUpdate/' $driver '.php';
  468.  
  469.             if (!PEAR_PackageUpdate::isIncludable($file)) {
  470.                 PEAR_ErrorStack::staticPush('PEAR_PackageUpdate',
  471.                     PEAR_PACKAGEUPDATE_ERROR_NONEXISTENTDRIVER,
  472.                     null,
  473.                     array('drivername' => $driver),
  474.                     $GLOBALS['_PEAR_PACKAGEUPDATE_ERRORS']
  475.                         [PEAR_PACKAGEUPDATE_ERROR_NONEXISTENTDRIVER]);
  476.                 // Must assign a variable to avoid notice about references.
  477.                 $false = false;
  478.                 return $false;
  479.             }
  480.             include_once $file;
  481.         }
  482.  
  483.         // See if the class exists now.
  484.         if (!class_exists($class)) {
  485.             // Must assign a variable to avoid notice about references.
  486.             $false = false;
  487.             return $false;
  488.         }
  489.  
  490.         // Try to instantiate the class.
  491.         $instance =new $class($packageName$channel,
  492.                        $user_file$system_file$pref_file);
  493.         return $instance;
  494.     }
  495.  
  496.     /**
  497.      * Returns whether or not a path is in the include path.
  498.      *
  499.      * @param string $path Path to filename to check if includable
  500.      *
  501.      * @static
  502.      * @access public
  503.      * @return boolean true if the path is in the include path.
  504.      * @since  version 0.4.2 (2006-04-20)
  505.      */
  506.     function isIncludable($path)
  507.     {
  508.         // Break up the include path and check to see if the path is readable.
  509.         foreach (explode(PATH_SEPARATORget_include_path()) as $ip{
  510.             if (file_exists($ip . DIRECTORY_SEPARATOR . $path)
  511.                 && is_readable($ip . DIRECTORY_SEPARATOR . $path)
  512.                 {
  513.                 return true;
  514.             }
  515.         }
  516.  
  517.         // If we got down here, the path is not readable from the include path.
  518.         return false;
  519.     }
  520.  
  521.     /**
  522.      * Loads the user's preferences from a file.
  523.      *
  524.      * The preferences are stored in the user's home directory
  525.      * as the file .ppurc. The file contains a serialized array
  526.      * of preferences for each package that has been checked for
  527.      * updates so far.
  528.      *
  529.      * @param string $pref_file (optional) file to read PPU user-defined options from
  530.      *
  531.      * @access protected
  532.      * @return boolean   true on success, false on error
  533.      * @since  version 0.4.0a1 (2006-03-28)
  534.      * @throws PEAR_PACKAGEUPDATE_ERROR_PREFFILE_READACCESS,
  535.      *          PEAR_PACKAGEUPDATE_ERROR_PREFFILE_CORRUPTED,
  536.      *          PEAR_PACKAGEUPDATE_ERROR_INVALIDINIFILE
  537.      */
  538.     function loadPreferences($pref_file '')
  539.     {
  540.         if ($pref_file && !file_exists($pref_file)) {
  541.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_INVALIDINIFILE,
  542.                 'warning',
  543.                 array('layer' => 'ppu-pref''file' => $pref_file));
  544.             $pref_file ''// force to use default PPU configuration
  545.         }
  546.  
  547.         // Get the preferences file.
  548.         if (empty($pref_file)) {
  549.             $prefFile $this->determinePrefFile();
  550.         else {
  551.             $prefFile $pref_file;
  552.         }
  553.  
  554.         // Make sure the prefFile exists.
  555.         if (!@file_exists($prefFile)) {
  556.             // Try to create it by saving the current preferences (probably
  557.             // just an empty array).
  558.             $this->savePreferences($prefFile);
  559.         }
  560.  
  561.         // Make sure the prefFile is readable.
  562.         if (!@is_readable($prefFile)) {
  563.                 nullarray('file' => $prefFile));
  564.             return false;
  565.         }
  566.  
  567.         // Get the contents of the prefFile.
  568.         $contents file_get_contents($prefFile);
  569.  
  570.         // Unserialize the data.
  571.         $preferences unserialize($contents);
  572.  
  573.         // Make sure the contents were unserialized properly.
  574.         // Borrowed from PEAR_Config.
  575.         if ($preferences === false{
  576.             return false;
  577.         }
  578.  
  579.         $this->preferences = $preferences;
  580.         $this->pref_file   = $prefFile;
  581.  
  582.         return true;
  583.     }
  584.  
  585.     /**
  586.      * Returns the path to the preferences file.
  587.      *
  588.      * @access protected
  589.      * @return string 
  590.      * @since  version 0.4.0a1 (2006-03-28)
  591.      */
  592.     function determinePrefFile()
  593.     {
  594.         if (OS_WINDOWS{
  595.             $cfgName 'ppurc.ini';
  596.         else {
  597.             $cfgName '.ppurc';
  598.         }
  599.  
  600.         // PEAR 1.7.0 introduced new feature like configuration directory (cfg_dir)
  601.         $config =PEAR_Config::singleton($this->user_file$this->system_file);
  602.         $cfgDir $config->get('cfg_dir');
  603.  
  604.         if (!is_null($cfgDir&& is_dir($cfgDir)) {
  605.             // detect PEAR configuration directive (cfg_dir)
  606.         else {
  607.             if (OS_WINDOWS{
  608.                 $cfgDir = PEAR_CONFIG_SYSCONFDIR;
  609.             else {
  610.                 $cfgDir getenv('HOME');
  611.             }
  612.         }
  613.         $prefFile $cfgDir . DIRECTORY_SEPARATOR . $cfgName;
  614.  
  615.         return $prefFile;
  616.     }
  617.  
  618.     /**
  619.      * Checks to see if an update is available.
  620.      *
  621.      * Respects the user preferences when determining if an
  622.      * update is available. Returns true if an update is available
  623.      * and the user may want to update the package.
  624.      *
  625.      * @access public
  626.      * @return boolean true if an update is available.
  627.      * @since  version 0.4.0a1 (2006-03-28)
  628.      */
  629.     function checkUpdate()
  630.     {
  631.         // Check to see if an update is available.
  632.         if (empty($this->latestVersion|| empty ($this->info)) {
  633.             if (!$this->getInstalledRelease()) {
  634.                 return false;
  635.             }
  636.         }
  637.  
  638.         // See if the installed version is older than the current version.
  639.         if (version_compare($this->latestVersion$this->instVersion'>')) {
  640.             // Check to see if the user's preferences allow an update.
  641.             if (!$this->preferencesAllowUpdate()) {
  642.                 // User doesn't want to update to the latest version.
  643.                 return false;
  644.             }
  645.             return true;
  646.         else {
  647.             return false;
  648.         }
  649.     }
  650.  
  651.     /**
  652.      * Returns the latest information about the given package.
  653.      *
  654.      * @access protected
  655.      * @return boolean   true on success, false on error
  656.      * @since  version 0.4.0a1 (2006-03-28)
  657.      * @throws PEAR_PACKAGEUPDATE_ERROR_NOPACKAGE,
  658.      *          PEAR_PACKAGEUPDATE_ERROR_NOCHANNEL,
  659.      *          PEAR_PACKAGEUPDATE_ERROR_NOINFO
  660.      */
  661.     function getPackageInfo()
  662.     {
  663.         // Only check once.
  664.         if (isset($this->latestVersion&& isset($this->info)) {
  665.             return true;
  666.         }
  667.  
  668.         // Make sure the channel and package are set.
  669.         if (empty($this->packageName)) {
  670.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_NOPACKAGE);
  671.             return false;
  672.         }
  673.  
  674.         if (empty($this->channel)) {
  675.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_NOCHANNEL);
  676.             return false;
  677.         }
  678.  
  679.         // Create a config object.
  680.         $config =PEAR_Config::singleton($this->user_file$this->system_file);
  681.  
  682.         if (empty($this->user_file)) {
  683.             if (empty($this->system_file)) {
  684.                 $layer = null;
  685.             else {
  686.                 $layer 'system';
  687.             }
  688.         else {
  689.             $layer 'user';
  690.         }
  691.         // Get the config's registry object.
  692.         $reg $config->getRegistry($layer);
  693.  
  694.         // Parse the package name.
  695.         $parsed $reg->parsePackageName($this->channel . '/' $this->packageName);
  696.  
  697.         // Check for errors.
  698.         if (PEAR::isError($parsed)) {
  699.             $this->pushError($parsed);
  700.             return false;
  701.         }
  702.  
  703.         // Get a channel object.
  704.         $chan   =$reg->getChannel($this->channel);
  705.         $mirror $config->get('preferred_mirror');
  706.         if ($chan->supportsREST($mirror)
  707.             && $base $chan->getBaseURL('REST1.0'$mirror)) {
  708.  
  709.             $rest =$config->getREST('1.0'array());
  710.             $info =  $rest->packageInfo($base$parsed['package']);
  711.         else {
  712.             $r    =$config->getRemote();
  713.             $info =  $r->call('package.info'$parsed['package']);
  714.         }
  715.  
  716.         // Check to make sure the package was found.
  717.         if (PEAR::isError($info|| !isset($info['name'])) {
  718.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_NOINFOnull,
  719.                 array('packagename' => $this->packageName));
  720.             return false;
  721.         }
  722.  
  723.         // Get full installed data of the package.
  724.         $this->instInfo = $reg->packageInfo($parsed['package']null,
  725.                               $parsed['channel']);
  726.         if (is_null($this->instInfo)) {
  727.             $this->instVersion = '';
  728.         else {
  729.             if ($this->instInfo['xsdversion'== '1.0'{
  730.                 $this->instVersion = $this->instInfo['version'];
  731.             else {
  732.                 $this->instVersion = $this->instInfo['version']['release'];
  733.             }
  734.         }
  735.  
  736.         // If the package is not installed, create a dummy version.
  737.         if (empty($this->instVersion)) {
  738.             $this->instVersion = '0.0.0';
  739.         }
  740.  
  741.         // Pull out the latest information.
  742.         $this->latestVersion = reset(array_keys($info['releases']));
  743.  
  744.         $this->info                = reset($info['releases']);
  745.         $this->info['version']     $this->latestVersion;
  746.         $this->info['summary']     $info['summary'];
  747.         $this->info['description'$info['description'];
  748.  
  749.         return true;
  750.     }
  751.  
  752.     /**
  753.      * Returns the preferences associated with the given package.
  754.      *
  755.      * The preferences returned are an array with the folling values:
  756.      * - don't ask again
  757.      * - don't ask until next version
  758.      * - only ask for state x
  759.      * - bug/minor/major updates only
  760.      *
  761.      * @access public
  762.      * @return array 
  763.      * @since  version 0.4.0a1 (2006-03-28)
  764.      */
  765.     function getPackagePreferences()
  766.     {
  767.         if (isset($this->preferences[$this->channel][$this->packageName])) {
  768.             return $this->preferences[$this->channel][$this->packageName];
  769.         else {
  770.             return array();
  771.         }
  772.     }
  773.  
  774.     /**
  775.      * Saves the current preferences to the RC file.
  776.      *
  777.      * @param string $pref_file (optional) file to save PPU user-defined options to
  778.      *
  779.      * @access public
  780.      * @return boolean true on success, false on error
  781.      * @since  version 0.4.0a1 (2006-03-28)
  782.      * @throws PEAR_PACKAGEUPDATE_ERROR_PREFFILE_WRITEACCESS,
  783.      *          PEAR_PACKAGEUPDATE_ERROR_PREFFILE_WRITEERROR
  784.      * @see    determinePrefFile()
  785.      */
  786.     function savePreferences($pref_file '')
  787.     {
  788.         // Get the file to save the preferences to.
  789.         if (empty($pref_file)) {
  790.             $prefFile $this->determinePrefFile();
  791.         else {
  792.             $prefFile $pref_file;
  793.         }
  794.  
  795.         // Open the file for writing.
  796.         $fp fopen($prefFile'w');
  797.         if ($fp === false{
  798.                 nullarray('file' => $prefFile));
  799.             return false;
  800.         }
  801.  
  802.         // Serialize the contents.
  803.         $serialCont serialize($this->preferences);
  804.  
  805.         // Write the contents to the file.
  806.         if (fwrite($fp$serialCont=== false{
  807.                 nullarray('file' => $prefFile));
  808.             return false;
  809.         }
  810.  
  811.         // Close the file.
  812.         if (!fclose($fp)) {
  813.                 nullarray('file' => $prefFile));
  814.             return false;
  815.         else {
  816.             $this->pref_file = $prefFile;
  817.             return true;
  818.         }
  819.     }
  820.  
  821.     /**
  822.      * Returns whether or not the user's preferences will allow an update to
  823.      * take place.
  824.      *
  825.      * The user's preferences may define restrictions such as:
  826.      *   - don't update
  827.      *   - don't ask until next version (remembers last version asked)
  828.      *   - only ask for state XXXX or higher
  829.      *   - minor or higher (no bug fix)
  830.      *   - major only
  831.      *
  832.      * @access public
  833.      * @return boolean true if the preferences will allow an update for the
  834.      *                  latest version.
  835.      * @since  version 0.4.0a1 (2006-03-28)
  836.      * @see    getPackagePreferences()
  837.      */
  838.     function preferencesAllowUpdate()
  839.     {
  840.         // Get the preferences for the package.
  841.         $prefs $this->getPackagePreferences();
  842.  
  843.         // Check to see if the user wants to be notified about any updates for
  844.         // this package.
  845.         if (isset($prefs[PEAR_PACKAGEUPDATE_PREF_NOUPDATES])
  846.             && $prefs[PEAR_PACKAGEUPDATE_PREF_NOUPDATES]
  847.             {
  848.             return false;
  849.         }
  850.  
  851.         // Check to see if the user has requested not to be asked until a new
  852.         // version is released.
  853.         if (isset($prefs[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE])
  854.             && !version_compare($this->latestVersion,
  855.                              $prefs[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE],
  856.                              '>')
  857.             {
  858.             return false;
  859.         }
  860.  
  861.         // Check to see if the user has requested not to be asked about the
  862.         // state of the latest release.
  863.         // Create an array of states.
  864.         $states = array(PEAR_PACKAGEUPDATE_STATE_SNAPSHOT => -1,
  865.                         PEAR_PACKAGEUPDATE_STATE_DEVEL  => 0,
  866.                         PEAR_PACKAGEUPDATE_STATE_ALPHA  => 1,
  867.                         PEAR_PACKAGEUPDATE_STATE_BETA   => 2,
  868.                         PEAR_PACKAGEUPDATE_STATE_STABLE => 3
  869.                         );
  870.         if (isset($prefs[PEAR_PACKAGEUPDATE_PREF_STATE])
  871.             && $states[$prefs[PEAR_PACKAGEUPDATE_PREF_STATE]] >
  872.                 $states[$this->info['state']]
  873.             {
  874.             return false;
  875.         }
  876.  
  877.         // Check to see if the user only wants to be asked about a certain
  878.         // type of release (bug|minor|major).
  879.         // Create an array for the types of releases.
  880.         $releases = array(PEAR_PACKAGEUPDATE_TYPE_BUG   => 0,
  881.                           PEAR_PACKAGEUPDATE_TYPE_MINOR => 1,
  882.                           PEAR_PACKAGEUPDATE_TYPE_MAJOR => 2
  883.                           );
  884.         if (isset($prefs[PEAR_PACKAGEUPDATE_PREF_TYPE])
  885.             && $releases[$prefs[PEAR_PACKAGEUPDATE_PREF_TYPE]] >
  886.                 $releases[$this->releaseType()]
  887.             {
  888.             return false;
  889.         }
  890.  
  891.         // If we got down here, either there are no preferences for this
  892.         // package or everything checked out.
  893.         return true;
  894.     }
  895.  
  896.     /**
  897.      * Returns the type of release. (bug|minor|major);
  898.      *
  899.      * @access protected
  900.      * @return string 
  901.      * @since  version 0.4.0a1 (2006-03-28)
  902.      */
  903.     function releaseType()
  904.     {
  905.         // Break the two versions into pieces.
  906.         $latest  explode('.'$this->latestVersion);
  907.         $current explode('.'$this->instVersion);
  908.  
  909.         if ($latest[0$current[0]{
  910.             $type PEAR_PACKAGEUPDATE_TYPE_MAJOR;
  911.         elseif ($latest[1$current[1]{
  912.             $type PEAR_PACKAGEUPDATE_TYPE_MINOR;
  913.         else {
  914.             $type PEAR_PACKAGEUPDATE_TYPE_BUG;
  915.         }
  916.  
  917.         return $type;
  918.     }
  919.  
  920.     /**
  921.      * Returns informations about current installed version of the package
  922.      *
  923.      * @author Laurent Laville
  924.      * @access public
  925.      * @return array|bool  false on error, data array otherwise
  926.      * @since  version 0.6.0 (2007-01-11)
  927.      */
  928.     function getInstalledRelease()
  929.     {
  930.         if (!$this->getPackageInfo()) {
  931.             return false;
  932.         }
  933.         // compatibility for package.xml version 2.0
  934.         if (isset($this->instInfo['old'])) {
  935.             $instInfo $this->instInfo['old'];
  936.             $instInfo['packagerversion']
  937.                 = $this->instInfo['attribs']['packagerversion'];
  938.         else {
  939.             $instInfo $this->instInfo;
  940.             if (!isset($instInfo['packagerversion'])) {
  941.                 $instInfo['packagerversion''';
  942.             }
  943.         }
  944.         $info = array(
  945.             'version'         => $instInfo['version'],
  946.             'license'         => $instInfo['release_license'],
  947.             'summary'         => $this->instInfo['summary'],
  948.             'description'     => $this->instInfo['description'],
  949.             'releasedate'     => $instInfo['release_date'],
  950.             'releasenotes'    => $instInfo['release_notes'],
  951.             'state'           => $instInfo['release_state'],
  952.             'deps'            => $instInfo['release_deps'],
  953.             'xsdversion'      => $this->instInfo['xsdversion'],
  954.             'packagerversion' => $instInfo['packagerversion'],
  955.         );
  956.         return $info;
  957.     }
  958.  
  959.     /**
  960.      * Returns information on latest version available
  961.      *
  962.      * @author Laurent Laville
  963.      * @access public
  964.      * @return array|bool  false on error, data array otherwise
  965.      * @since  version 0.6.0 (2007-01-11)
  966.      */
  967.     function getLatestRelease()
  968.     {
  969.         if (!$this->getPackageInfo()) {
  970.             return false;
  971.         }
  972.         $info $this->info;
  973.         unset($info['doneby']);
  974.         return $info;
  975.     }
  976.  
  977.     /**
  978.      * Sets the user's preference for asking about all updates for this
  979.      * package.
  980.      *
  981.      * @param boolean $dontAsk User's preference for asking about all updates
  982.      *
  983.      * @access public
  984.      * @return boolean true on success, false on failure
  985.      * @since  version 0.4.0a1 (2006-03-28)
  986.      */
  987.     function setDontAskAgain($dontAsk)
  988.     {
  989.         // Make sure the value is a boolean.
  990.         settype($dontAsk'boolean');
  991.  
  992.         // Set the preference.
  993.         return $this->setPreference(PEAR_PACKAGEUPDATE_PREF_NOUPDATES$dontAsk);
  994.     }
  995.  
  996.     /**
  997.      * Sets the user's preference for asking about updates again until the next
  998.      * release.
  999.      *
  1000.      * @param boolean $nextrelease User's preference for asking about updates again
  1001.      *
  1002.      * @access public
  1003.      * @return boolean true on success, false on failure
  1004.      * @since  version 0.4.0a1 (2006-03-28)
  1005.      * @throws PEAR_PACKAGEUPDATE_ERROR_NOINFO
  1006.      */
  1007.     function setDontAskUntilNextRelease($nextrelease)
  1008.     {
  1009.         // If nextrelease is true, we have to swap its value out with the
  1010.         // latest version.
  1011.         if ($nextrelease{
  1012.             // Make sure that the package info was found.
  1013.             if (empty($this->latestVersion)) {
  1014.                 $this->pushError(PEAR_PACKAGEUPDATE_ERROR_NOINFO);
  1015.                 return false;
  1016.             }
  1017.             $nextrelease $this->latestVersion;
  1018.         }
  1019.  
  1020.         // Set the preference.
  1021.         return $this->setPreference(PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE,
  1022.                                     $nextrelease);
  1023.     }
  1024.  
  1025.     /**
  1026.      * Sets the user's preference for asking about release types.
  1027.      *
  1028.      * @param string $minType The minimum release type to allow.
  1029.      *
  1030.      * @access public
  1031.      * @return boolean true on success, false on failure
  1032.      * @since  version 0.4.0a1 (2006-03-28)
  1033.      * @throws PEAR_PACKAGEUPDATE_ERROR_INVALIDTYPE
  1034.      */
  1035.     function setMinimumReleaseType($minType)
  1036.     {
  1037.         // Make sure the type is acceptable.
  1038.         if ($minType != PEAR_PACKAGEUPDATE_TYPE_BUG
  1039.             && $minType != PEAR_PACKAGEUPDATE_TYPE_MINOR
  1040.             && $minType != PEAR_PACKAGEUPDATE_TYPE_MAJOR
  1041.             {
  1042.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_INVALIDTYPEnull,
  1043.                 array('type' => $minType));
  1044.             return false;
  1045.         }
  1046.  
  1047.         // Set the preference.
  1048.         return $this->setPreference(PEAR_PACKAGEUPDATE_PREF_TYPE$minType);
  1049.     }
  1050.  
  1051.     /**
  1052.      * Sets the user's preference for asking about release states.
  1053.      *
  1054.      * @param string $minState The minimum release state to allow.
  1055.      *
  1056.      * @access public
  1057.      * @return boolean true on success, false on failure
  1058.      * @since  version 0.4.0a1 (2006-03-28)
  1059.      * @throws PEAR_PACKAGEUPDATE_ERROR_INVALIDSTATE
  1060.      */
  1061.     function setMinimumState($minState)
  1062.     {
  1063.         // Make sure the type is acceptable.
  1064.         if ($minState != PEAR_PACKAGEUPDATE_STATE_SNAPSHOT
  1065.             && $minState != PEAR_PACKAGEUPDATE_STATE_DEVEL
  1066.             && $minState != PEAR_PACKAGEUPDATE_STATE_ALPHA
  1067.             && $minState != PEAR_PACKAGEUPDATE_STATE_BETA
  1068.             && $minState != PEAR_PACKAGEUPDATE_STATE_STABLE
  1069.             {
  1070.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_INVALIDSTATEnull,
  1071.                 array('state' => $minState));
  1072.             return false;
  1073.         }
  1074.  
  1075.         // Set the preference.
  1076.         return $this->setPreference(PEAR_PACKAGEUPDATE_PREF_STATE$minState);
  1077.     }
  1078.  
  1079.     /**
  1080.      * Sets the given preference to the given value.
  1081.      *
  1082.      * Don't take any chances. Anytime a preference is set, the preferences are
  1083.      * saved. We can't rely on the developer to call savePreferences.
  1084.      *
  1085.      * @param integer $pref  One of the preference constants.
  1086.      * @param mixed   $value The value of the preference.
  1087.      *
  1088.      * @return boolean   true if the preference was set and saved properly.
  1089.      * @access protected
  1090.      * @since  version 0.4.0a1 (2006-03-28)
  1091.      * @throws PEAR_PACKAGEUPDATE_ERROR_INVALIDPREF
  1092.      */
  1093.     function setPreference($pref$value)
  1094.     {
  1095.         // Make sure the preference is valid.
  1096.         if ($pref != PEAR_PACKAGEUPDATE_PREF_NOUPDATES
  1097.             && $pref != PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE
  1098.             && $pref != PEAR_PACKAGEUPDATE_PREF_TYPE
  1099.             && $pref != PEAR_PACKAGEUPDATE_PREF_STATE
  1100.             {
  1101.             // Invalid preference!
  1102.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_INVALIDPREFnull,
  1103.                 array('preference' => $pref));
  1104.             return false;
  1105.         }
  1106.  
  1107.         // Make sure the preferences for the channel exist.
  1108.         if (!isset($this->preferences[$this->channel])) {
  1109.             $this->preferences[$this->channel= array();
  1110.         }
  1111.  
  1112.         // Make sure the preferences for the package exist.
  1113.         if (!isset($this->preferences[$this->channel][$this->packageName])) {
  1114.             $this->preferences[$this->channel][$this->packageName= array();
  1115.         }
  1116.  
  1117.         // Set the preference value.
  1118.         $this->preferences[$this->channel][$this->packageName][$pref$value;
  1119.  
  1120.         // Save the preferences.
  1121.         return $this->savePreferences($this->pref_file);
  1122.     }
  1123.  
  1124.     /**
  1125.      * Sets all preferences at once.
  1126.      *
  1127.      * @param array $preferences All user's preferences
  1128.      *
  1129.      * @return boolean true if the preferences were set and saved.
  1130.      * @since  version 0.4.0a1 (2006-03-28)
  1131.      * @access public
  1132.      */
  1133.     function setPreferences($preferences)
  1134.     {
  1135.         // Make sure preferences is an array.
  1136.         settype($preferences'array');
  1137.  
  1138.         // Make sure there is only valid preference information.
  1139.         foreach ($preferences as $pref => $value{
  1140.             if ($pref != PEAR_PACKAGEUPDATE_PREF_NOUPDATES
  1141.                 && $pref != PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE
  1142.                 && $pref != PEAR_PACKAGEUPDATE_PREF_TYPE
  1143.                 && $pref != PEAR_PACKAGEUPDATE_PREF_STATE
  1144.                 {
  1145.                 unset($preferences[$pref]);
  1146.             }
  1147.         }
  1148.  
  1149.         // Make sure that next release has the latest release.
  1150.         if ($preferences[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE]{
  1151.             $preferences[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE$this->latestVersion;
  1152.         }
  1153.  
  1154.         // Set the preferences.
  1155.         $this->preferences[$this->channel][$this->packageName$preferences;
  1156.  
  1157.         // Save the preferences.
  1158.         return $this->savePreferences($this->pref_file);
  1159.     }
  1160.  
  1161.     /**
  1162.      * Updates the source for the package.
  1163.      *
  1164.      * We have to update required dependencies automatically to make sure that
  1165.      * everything still works properly.
  1166.      *
  1167.      * It is the developers responsibility to make sure the user is given the
  1168.      * option to update any optional dependencies if needed. This can be done
  1169.      * by creating a new instance of PEAR_PackageUpdate for the optional
  1170.      * dependency.
  1171.      *
  1172.      * @access public
  1173.      * @return boolean true if the update was successful.
  1174.      * @since  version 0.4.0a1 (2006-03-28)
  1175.      * @throws PEAR_PACKAGEUPDATE_ERROR_NOTINSTALLED
  1176.      */
  1177.     function update()
  1178.     {
  1179.         // Create a config object.
  1180.         $config =PEAR_Config::singleton($this->user_file$this->system_file);
  1181.  
  1182.         // Change the verbosity but keep track of the value to reset it just in
  1183.         // case this does something permanent.
  1184.         $verbose $config->get('verbose');
  1185.         $config->set('verbose'0);
  1186.  
  1187.         // Create a command object to do the upgrade.
  1188.         // If the current version is 0.0.0 don't upgrade. That would be a
  1189.         // sneaky way for devs to install packages without the use knowing.
  1190.         if ($this->instVersion == '0.0.0'{
  1191.             $this->pushError(PEAR_PACKAGEUPDATE_ERROR_NOTINSTALLEDnull,
  1192.                 array('packagename' => $this->packageName));
  1193.             return false;
  1194.         }
  1195.  
  1196.         include_once 'PEAR/Command.php';
  1197.         $upgrade = PEAR_Command::factory('upgrade'$config);
  1198.  
  1199.         // Try to upgrade the application.
  1200.         $channelPackage $this->channel . '/' $this->packageName;
  1201.         $result         $upgrade->doInstall('upgrade',
  1202.                                       array('onlyreqdeps' => true),
  1203.                                       array($channelPackage));
  1204.  
  1205.         // Reset the verbose level just to be safe.
  1206.         $config->set('verbose'$verbose);
  1207.  
  1208.         // Check for errors.
  1209.         if (PEAR::isError($result)) {
  1210.             $this->pushError($result);
  1211.             return false;
  1212.         else {
  1213.             return true;
  1214.         }
  1215.     }
  1216.  
  1217.     /**
  1218.      * Redirects or exits to force the user to restart the application.
  1219.      *
  1220.      * @abstract
  1221.      * @access public
  1222.      * @return void 
  1223.      * @since  version 0.4.0a1 (2006-03-28)
  1224.      */
  1225.     function forceRestart()
  1226.     {
  1227.         $this->pushError('forceRestart is an abstract method that must be' .
  1228.             ' overridden in the child class.');
  1229.     }
  1230.  
  1231.     /**
  1232.      * Presents the user with the option to update.
  1233.      *
  1234.      * @abstract
  1235.      * @access public
  1236.      * @return boolean true if the user wants to update
  1237.      * @since  version 0.4.0a1 (2006-03-28)
  1238.      */
  1239.     function presentUpdate()
  1240.     {
  1241.         $this->pushError('presentUpdate is an abstract method that must be' .
  1242.             ' overridden in the child class.');
  1243.  
  1244.         // Return false just in case something odd has happened.
  1245.         return false;
  1246.     }
  1247.  
  1248.     /**
  1249.      * Pushes an error onto an error stack.
  1250.      *
  1251.      * This method is just for collecting errors that occur while checking for
  1252.      * updates and updating a package. The child class is responsible for
  1253.      * displaying all errors and handling them properly. This is because the
  1254.      * way errors are handled varies greatly depending on the driver used.
  1255.      *
  1256.      * @param int    $code      Package-specific error code
  1257.      * @param string $level     Error level.  This is NOT spell-checked
  1258.      * @param array  $params    associative array of error parameters
  1259.      * @param string $msg       Error message, or a portion of it if the
  1260.      *                           message is to be generated
  1261.      * @param array  $repackage If this error re-packages an error pushed by
  1262.      *                           another package, place the array returned from
  1263.      *                           {@link pop()} in this parameter
  1264.      * @param array  $backtrace Protected parameter: use this to pass in the
  1265.      *                           {@link debug_backtrace()} that should be used
  1266.      *                           to find error context
  1267.      *
  1268.      * @return PEAR_Error|array|Exception
  1269.      *                           if compatibility mode is on, a PEAR_Error is
  1270.      *                           also thrown.  If the class Exception exists,
  1271.      *                           then one is returned.
  1272.      * @since  version 0.4.0a1 (2006-03-28)
  1273.      * @access public
  1274.      */
  1275.     function pushError($code$level 'error'$params = array(),
  1276.                         $msg = false$repackage = false$backtrace = false)
  1277.     {
  1278.         // Check to see if a PEAR_Error was pushed.
  1279.         if (PEAR::isError($code)) {
  1280.             return $this->repackagePEARError($code);
  1281.         }
  1282.  
  1283.         // Check the arguments to see if just a code was submitted.
  1284.         if (is_int($code)
  1285.             && !(bool) $msg
  1286.             && isset($GLOBALS['_PEAR_PACKAGEUPDATE_ERRORS'][$code])
  1287.             {
  1288.             $msg $GLOBALS['_PEAR_PACKAGEUPDATE_ERRORS'][$code];
  1289.         }
  1290.  
  1291.         // Append the error onto the stack.
  1292.         return $this->errors->push($code$level$params$msg,
  1293.                                    $repackage$backtrace);
  1294.     }
  1295.  
  1296.     /**
  1297.      * Repackages PEAR_Errors for use with ErrorStack.
  1298.      *
  1299.      * @param object &$error A PEAR_Error
  1300.      *
  1301.      * @return mixed  The return from PEAR::ErrorStack::push()
  1302.      * @since  version 0.4.0a1 (2006-03-28)
  1303.      * @access public
  1304.      * @author Ian Eure <ieure@php.net>
  1305.      */
  1306.     function repackagePEARError(&$error)
  1307.     {
  1308.         static $map;
  1309.         if (!isset($map)) {
  1310.             $map = array(
  1311.                          E_ERROR            => 'error',
  1312.                          E_WARNING          => 'warning',
  1313.                          E_PARSE            => 'exception',
  1314.                          E_NOTICE           => 'notice',
  1315.                          E_CORE_ERROR       => 'error',
  1316.                          E_CORE_WARNING     => 'warning',
  1317.                          E_COMPILE_ERROR    => 'exception',
  1318.                          E_COMPILE_WARNING  => 'warning',
  1319.                          E_USER_ERROR       => 'error',
  1320.                          E_USER_WARNING     => 'warning',
  1321.                          E_USER_NOTICE      => 'notice'
  1322.                          );
  1323.         }
  1324.  
  1325.         // Strip this function from the trace
  1326.         if (is_array($error->backtrace)) {
  1327.             array_shift($error->backtrace);
  1328.             $error->userinfo['backtrace'=$error->backtrace;
  1329.         }
  1330.  
  1331.         return $this->errors->push($error->code$map[$error->level],
  1332.                                    $error->userinfo$error->messagefalse,
  1333.                                    $error->backtrace);
  1334.     }
  1335.  
  1336.     /**
  1337.      * Pops an error off the error stack.
  1338.      *
  1339.      * This method is just for collecting errors that occur while checking for
  1340.      * updates and updating a package. The child class is responsible for
  1341.      * displaying all errors and handling them properly. This is because the
  1342.      * way errors are handled varies greatly depending on the driver used.
  1343.      *
  1344.      * @access public
  1345.      * @return mixed details of an error (array) or false if no errors exist.
  1346.      * @since  version 0.4.0a1 (2006-03-28)
  1347.      * @see    hasErrors()
  1348.      */
  1349.     function popError()
  1350.     {
  1351.         return $this->errors->pop();
  1352.     }
  1353.  
  1354.     /**
  1355.      * Returns whether or not errors have occurred (and been captured).
  1356.      *
  1357.      * @param string|array$level Level name. Use to determine if any errors
  1358.      *                             of level (string), or levels (array)
  1359.      *                             have been pushed
  1360.      *
  1361.      * @access public
  1362.      * @return boolean 
  1363.      * @since  version 0.4.0a1 (2006-03-28)
  1364.      * @see    popError()
  1365.      */
  1366.     function hasErrors($level = false)
  1367.     {
  1368.         return $this->errors->hasErrors($level);
  1369.     }
  1370. }
  1371. /*
  1372.  * Local variables:
  1373.  * tab-width: 4
  1374.  * c-basic-offset: 4
  1375.  * End:
  1376.  */
  1377. ?>

Documentation generated on Sun, 15 Jun 2008 10:30:06 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.