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

Source for file Packages.php

Documentation is available at Packages.php

  1. <?php
  2. require_once 'PEAR/Frontend/Gtk2/Package.php';
  3. require_once 'PEAR/Config.php';
  4.  
  5. /**
  6. *   This class deals with packages: local package loading,
  7. *   remote package loading and so.
  8. *
  9. *   The callback is called after everything has been finished
  10. *   with parameters (true, true) to signal that it's done.
  11. *
  12. *   @author Christian Weiske <cweiske@php.net>
  13. */
  14. class PEAR_Frontend_Gtk2_Packages
  15. {
  16.     /**
  17.     *   The currently active channel name
  18.     *   @var string 
  19.     */
  20.     protected $strActiveChannel = null;
  21.  
  22.     /**
  23.     *   Array of channel => package arrays
  24.     *   @var array 
  25.     */
  26.     protected $arPackages = null;
  27.  
  28.     /**
  29.     *   Array of channel => category strings
  30.     *   @var array 
  31.     */
  32.     protected $arCategories = null;
  33.  
  34.     public static $EXCEPTION_NO_REST = 451;
  35.  
  36.  
  37.  
  38.     public function __construct($strActiveChannel = null)
  39.     {
  40.         $this->setActiveChannel($strActiveChannel);
  41.     }//public function __construct($strActiveChannel = null)
  42.  
  43.  
  44.  
  45.     public function setActiveChannel($strActiveChannel)
  46.     {
  47.         $this->strActiveChannel $strActiveChannel;
  48.     }//public function setActiveChannel($strActiveChannel)
  49.  
  50.  
  51.  
  52.     public function getActiveChannel()
  53.     {
  54.         return $this->strActiveChannel;
  55.     }//public function getActiveChannel()
  56.  
  57.  
  58.  
  59.     /**
  60.     *   Returns a list with all packages, or all packages in the given category.
  61.     *   Package list is cached, so that it's faster after the first call.
  62.     *
  63.     *   @param string   $strCategory    If given, the list is filtered by category name
  64.     *   @param callback $callback       The function to call before a package information is downloaded
  65.     *   @param booleab  $bWorkOffline   If the user wants to work offline (don't connect to the internet)
  66.     *
  67.     *   @return array   Array of PEAR_Frontend_Gtk2_Package's
  68.     */
  69.     public function getPackages($strCategory = null$callback = null$bWorkOffline = false)
  70.     {
  71.         if (!$this->packagesLoaded()) {
  72.             $this->arPackages[$this->strActiveChannel= PEAR_Frontend_Gtk2_Packages::getAllPackages($this->strActiveChannel$callback$bWorkOffline);
  73.         }
  74.         if ($strCategory === null{
  75.             return $this->arPackages[$this->strActiveChannel];
  76.         }
  77.  
  78.         $arSelectedPackages = array();
  79.         foreach ($this->arPackages[$this->strActiveChannelas $strName => $package{
  80.             if ($package->getCategory(== $strCategory{
  81.                 $arSelectedPackages[$strName$package;
  82.             }
  83.         }
  84.         return $arSelectedPackages;
  85.     }//public function getPackages($strCategory = null, $callback = null, $bWorkOffline = false)
  86.  
  87.  
  88.  
  89.     /**
  90.     *   Gets an array of packages for the active channel
  91.     *   (local and remote packages)
  92.     *
  93.     *   @param string   $strChannel     Channel to get packages for
  94.     *   @param callback $callback       The callback to call for each single remote package
  95.     *   @param boolean  $bWorkOffline   If the users wants to work offline
  96.     *
  97.     *   @return array   Array of Packages
  98.     */
  99.     public static function getAllPackages($strChannel$callback = null$bWorkOffline = false)
  100.     {
  101.         return PEAR_Frontend_Gtk2_Packages::getRemotePackages(
  102.                     $strChannel,
  103.                     true,
  104.                     $callback,
  105.                     PEAR_Frontend_Gtk2_Packages::getLocalPackages($strChannel),
  106.                     $bWorkOffline
  107.                 );
  108.     }//public static function getAllPackages($strChannel, $callback = null, $bWorkOffline = false)
  109.  
  110.  
  111.  
  112.     /**
  113.     *   Loads the locally installed packages of the given
  114.     *   channel
  115.     *
  116.     *   @param  string  $strChannel         The channel name
  117.     *   @param  array   $arLocalPackages    Array with already existing local packages. If set, package info will be incorporated.
  118.     *   @return array   Array of locally installed packages
  119.     *   @static
  120.     */
  121.     public static function getLocalPackages($strChannel$arLocalPackages = array())
  122.     {
  123.         $config        = PEAR_Config::singleton();
  124.         $arRawPackages $config->getRegistry()->packageInfo(nullnull$strChannel);
  125.         $arExisting    is_null($arLocalPackages? array(array_keys($arLocalPackages);
  126.         $arFound       = array();
  127.  
  128.         foreach ($arRawPackages as $strPackageId => $dontuseit{
  129.             if (isset($arRawPackages[$strPackageId]['name'])) {
  130.                 $strPackageName $arRawPackages[$strPackageId]['name'];
  131.             else {
  132.                 $strPackageName $arRawPackages[$strPackageId]['package'];
  133.             }
  134.             if (!isset($arLocalPackages[$strPackageName])) {
  135.                 $arLocalPackages[$strPackageName= new PEAR_Frontend_Gtk2_Package($strPackageName$strChannel);
  136.                 $arLocalPackages[$strPackageName]->setCategory(PEAR_Frontend_Gtk2_Package::guessCategory($strPackageName));
  137.             }
  138.             $arLocalPackages[$strPackageName]->incorporateLocalInfo($arRawPackages[$strPackageId]);
  139.             $arFound[$strPackageName= true;
  140.         }
  141.  
  142.         foreach ($arExisting as $strId => $strPackageName{
  143.             if (isset($arFound[$strPackageName])) {
  144.                 unset($arExisting[$strId]);
  145.             }
  146.         }
  147.  
  148.         //The ones still in here aren't installed locally any more
  149.         foreach ($arExisting as $strPackageName{
  150.             $arLocalPackages[$strPackageName]->setInstalledVersion(null);
  151.         }
  152.  
  153.         return $arLocalPackages;
  154.     }//public static function getLocalPackages($strChannel, $arLocalPackages = array())
  155.  
  156.  
  157.  
  158.     /**
  159.     *   Loads the remotely available packages for the given channel
  160.     *
  161.     *   @param string   $strChannel         The channel name
  162.     *   @param boolean  $bLoadPackageData   If all the package data shall be loaded, not only the names
  163.     *   @param callback $callback           The callback to call after a package info has been loaded
  164.     *   @param array    $arExistingPackages Array with local packages already loaded
  165.     *   @param boolean  $bWorkOffline       If we should use the local cache if possible
  166.     *
  167.     *   @return array   Array of remotely available packages (PEAR_Frontend_Gtk2_Package)
  168.     *   @throws Exception If the channel has no REST support or if the connection failed
  169.     *   @static
  170.     */
  171.     public static function getRemotePackages($strChannel$bLoadPackageData = true$callback = null$arExistingPackages = array()$bWorkOffline = false)
  172.     {
  173.         $config     = PEAR_Config::singleton();
  174.         $channel    $config->getRegistry()->getChannel($strChannel);
  175.         $strBaseUrl $channel->getBaseURL('REST1.0');
  176.         $strServer  $channel->getServer();
  177.         $rest       $config->getREST('1.0');
  178.  
  179.         if ($channel->supportsREST($strServer&& $strBaseUrl{
  180.             $arXmlPackages = PEAR_Frontend_Gtk2_Packages::listPackages($strChannel$bWorkOffline);
  181.             if (PEAR::isError($arXmlPackages)) {
  182.                 throw new Exception(
  183.                     'Error listing packages on channel ' $strChannel ":\r\n"
  184.                         . $arXmlPackages->getMessage(),
  185.                     $arXmlPackages->getCode()
  186.                 );
  187.             }
  188.         else {
  189.             throw new Exception($strChannel ' has no REST support'PEAR_Frontend_Gtk2_Packages::$EXCEPTION_NO_REST);
  190.         }
  191.  
  192.         if (count($arXmlPackages== 0
  193.             || (count($arXmlPackages== 1 && $arXmlPackages[0=== null)
  194.         {
  195.             //No packages...
  196.             return $arExistingPackages;
  197.         }
  198.  
  199.         foreach ($arXmlPackages as $id => $strName{
  200.             if (!isset($arExistingPackages[$strName])) {
  201.                 $arExistingPackages[$strName= new PEAR_Frontend_Gtk2_Package($strName$strChannel);
  202.             }
  203.         }
  204.  
  205.         if ($bLoadPackageData === false{
  206.             return $arExistingPackages;
  207.         else {
  208.             return PEAR_Frontend_Gtk2_Packages::loadRemotePackageData($arExistingPackages$strChannel$callback$bWorkOffline);
  209.         }
  210.     }//public static function getRemotePackages($strChannel, $bLoadPackageData = true, $callback = null, $arExistingPackages = array(), $bWorkOffline = false)
  211.  
  212.  
  213.  
  214.     /**
  215.     *   Copy of the PEAR_REST#listPackages function with the change
  216.     *   that this one is able to get the list from the local cache.
  217.     *
  218.     *   @param string   $strChannel     The channel which packages shall be listed
  219.     *   @param boolean  $bWorkOffline   If false, the local cache is used - if true, the online list is loaded
  220.     *
  221.     *   @return mixed   PEAR_Error or array (package list)
  222.     */
  223.     public static function listPackages($strChannel$bWorkOffline = false)
  224.     {
  225.         $config     = PEAR_Config::singleton();
  226.         $channel    $config->getRegistry()->getChannel($strChannel);
  227.         $strBaseUrl $channel->getBaseURL('REST1.0');
  228.         $strServer  $channel->getServer();
  229.         $rest       $config->getREST('1.0');
  230.  
  231.         if ($bWorkOffline{
  232.             //We can't use the retrieveCacheFirst function as it would
  233.             //try to connect if the local cache is empty
  234.             $url       $strBaseUrl 'p/packages.xml';
  235.             $cachefile $config->get('cache_dir'. DIRECTORY_SEPARATOR . md5($url'rest.cachefile';
  236.             if (@file_exists($cachefile)) {
  237.                 //local package list cache file
  238.                 $arCache unserialize(implode(''file($cachefile)));
  239.                 if (PEAR::isError($arCache)) {
  240.                     return $arCache;
  241.                 }
  242.                 if (!is_array($arCache|| !isset($arCache['p'])) {
  243.                     return array();
  244.                 }
  245.                 if (!is_array($arCache['p'])) {
  246.                     $arCache['p'= array($arCache['p']);
  247.                 }
  248.                 return $arCache['p'];
  249.  
  250.             else {
  251.                 //no local cache -> return empty package list
  252.                 return array();
  253.             }
  254.         else {
  255.             //online => list online packages
  256.             return $rest->listPackages($strBaseUrl);
  257.         }
  258.     }//public static function listPackages($strChannel, $bWorkOffline = false)
  259.  
  260.  
  261.  
  262.  
  263.     /**
  264.     *   Loads all available information for the given packages
  265.     *
  266.     *   @param array    $arRemotePackages   Array with PEAR_Frontend_Gtk2_Package-s
  267.     *   @param string   $strChannel         The channel name to retrieve packages from
  268.     *   @param callback $callback           The callback to call after a package info has been loaded
  269.     *   @param boolean  $bWorkOffline       If the local cache *only* shall be used, or (if no local cache is there)
  270.     *                                            an connection to the internet server shall be made
  271.     *   @param boolean  $bUseCache          If the cache shall be used. If not, the only chance to get package data is
  272.     *                                            reading them from the online server (if $bWorkOffline is false)
  273.     *
  274.     *   @return array   Array of packages (locally installed and remotely available) (PEAR_Frontend_Gtk2_Package)
  275.     *   @static
  276.     */
  277.     public static function loadRemotePackageData($arRemotePackages$strChannel$callback = null$bWorkOffline = false$bUseCache = true)
  278.     {
  279.         $config     = PEAR_Config::singleton();
  280.         $rest10     $config->getREST('1.0');
  281.         $rest       $rest10->_rest;//FIXME: could change in future pear versions
  282.         $channel    $config->getRegistry()->getChannel($strChannel);
  283.         $strBaseUrl $channel->getBaseURL('REST1.0');
  284.  
  285.         $nNumberPackages count($arRemotePackages);
  286.         $nCurrentPackageNumber = 0;
  287.  
  288.         foreach ($arRemotePackages as $strId => $dontuseit{
  289.             if ($callback !== null{
  290.                 call_user_func_array($callbackarray($nNumberPackages++$nCurrentPackageNumber));
  291.             }
  292.             $package $arRemotePackages[$strId];
  293.             $inf = PEAR_Frontend_Gtk2_Packages::retrieveCacheFirst(
  294.                         PEAR_Frontend_Gtk2_Packages::getInfoUrl($strBaseUrl$package->getName()),
  295.                         $config,
  296.                         $rest,
  297.                         $bWorkOffline,
  298.                         $bUseCache
  299.                     );
  300.             if (PEAR::isError($inf)) {
  301.                 if (strpos(strtolower($inf->message)'404 not found'!== false{
  302.                     //FIXME: That is a hack because the error hasn't an error code yet.
  303.                     //We continue because it's an 404 error, maybe the package isn't there yet.
  304.                     //Happens if you installed new packages which haven't been uploaded to the server yet.
  305.                     $package->setCategory($package->guessCategory($package->getName()));
  306.                     continue;
  307.                 }
  308.                 throw new Exception($inf->getMessage());
  309.             }
  310.             if ($inf['ca']['_content'!== null{
  311.                 $package->setCategory(   $inf['ca']['_content']);
  312.             }
  313.             $package->setSummary(    $inf['s']);
  314.             $package->setDescription($inf['d']);
  315.             $package->setLatestVersion(
  316.                 //FIXME: use preferred_state config option
  317.                 PEAR_Frontend_Gtk2_Packages::retrieveCacheFirst(
  318.                     PEAR_Frontend_Gtk2_Packages::getLatestVersionUrl($strBaseUrl$package->getName()),
  319.                     $config,
  320.                     $rest,
  321.                     $bWorkOffline,
  322.                     $bUseCache
  323.                 )
  324.             );
  325.         }
  326.  
  327.         if ($callback !== null{
  328.             call_user_func_array($callbackarray(truetrue));
  329.         }
  330.  
  331.         return $arRemotePackages;
  332.     }//public static function loadRemotePackageData($arRemotePackages, $strChannel, $callback = null, $bWorkOffline = false, $bUseCache = true)
  333.  
  334.  
  335.  
  336.     /**
  337.     *   Copy of the PEAR_REST#retrieveCacheFirst() function with the addition
  338.     *   that one can specify if the cache only shall be loaded, or if the cache
  339.     *   is not available, an connection shall be made.
  340.     *
  341.     *   If the user works offline, and no cache is there, NULL is returned.
  342.     *
  343.     *   @param string       $url            The URL to get the data from
  344.     *   @param PEAR_Config  $config         The PEAR configuration
  345.     *   @param PEAR_REST    $rest           The REST object which can be used to retrieve the data
  346.     *   @param boolean      $bWorkOffline   If the local cache *only* shall be used, or (if no local cache is there)
  347.     *                                            an connection to the internet server shall be made
  348.     *   @param boolean      $bUseCache      If the cache shall be used. If not, the only chance to get package data is
  349.     *                                            reading them from the online server (if $bWorkOffline is false)
  350.     */
  351.     public static function retrieveCacheFirst($url$config$rest$bWorkOffline = false$bUseCache = true)
  352.     {
  353.         if ($bUseCache{
  354.             $cachefile $config->get('cache_dir'. DIRECTORY_SEPARATOR . md5($url'rest.cachefile';
  355.             if (@file_exists($cachefile)) {
  356.                 return unserialize(implode(''file($cachefile)));
  357.             }
  358.         }
  359.         if ($bWorkOffline{
  360.             return null;
  361.         else {
  362.             return $rest->retrieveData($url);
  363.         }
  364.     }//public static function retrieveCacheFirst($url, $config, $rest, $bWorkOffline = false, $bUseCache = true)
  365.  
  366.  
  367.  
  368.  
  369.     /**
  370.     *   Path to info.xml for the specific package
  371.     */
  372.     public static function getInfoUrl($strBaseUrl$strPackageName)
  373.     {
  374.         return $strBaseUrl 'p/' strtolower($strPackageName'/info.xml';
  375.     }//public static function getInfoUrl($strBaseUrl, $strPackageName)
  376.  
  377.  
  378.  
  379.     /**
  380.     *   Path to latest.txt for the specific package
  381.     */
  382.     public static function getLatestVersionUrl($strBaseUrl$strPackageName)
  383.     {
  384.         return $strBaseUrl 'r/' strtolower($strPackageName'/latest.txt';
  385.     }//public static function getLatestVersionUrl($strBaseUrl, $strPackageName)
  386.  
  387.  
  388.  
  389.     /**
  390.     *   Creates an array of categories (strings) of the current
  391.     *   channel server
  392.     *
  393.     *   @param callback $callback       The callback to call when package information is loaded
  394.     *   @param boolean  $bWorkOffline   If the user wants to work offline (don't try to connect to the internet)
  395.     *
  396.     *   @return array   Array of category strings
  397.     */
  398.     public function getCategories($callback = null$bWorkOffline = false)
  399.     {
  400.         if (!isset($this->arCategories[$this->strActiveChannel])) {
  401.             $arPackages $this->getPackages(null$callback$bWorkOffline);
  402.  
  403.             $this->arCategories[$this->strActiveChannel= array();
  404.             if (count($arPackages> 0{
  405.                 foreach ($arPackages as $package{
  406.                     $strCategory $package->getCategory();
  407.                     $this->arCategories[$this->strActiveChannel][$strCategory$strCategory;
  408.                 }
  409.                 natcasesort($this->arCategories[$this->strActiveChannel]);
  410.             }
  411.         }
  412.  
  413.         return $this->arCategories[$this->strActiveChannel];
  414.     }//public function getCategories($callback = null)
  415.  
  416.  
  417.  
  418.     /**
  419.     *   Checks if the packages for the given channel have already been loaded
  420.     *
  421.     *   @param string $strChannel   The channel to check (active channel if null)
  422.     *   @return boolean     true if the packages already have been loaded, false if not
  423.     */
  424.     public function packagesLoaded($strChannel = null)
  425.     {
  426.         if ($strChannel === null{
  427.             $strChannel $this->strActiveChannel;
  428.         }
  429.         return (isset($this->arPackages[$strChannel]&& $this->arPackages[$strChannel!== null);
  430.     }//public function packagesLoaded($strChannel = null)
  431.  
  432.  
  433.  
  434.     /**
  435.     *   Refreshs the package list of the given channel by re-reading
  436.     *   the local package info
  437.     *
  438.     *   @param string   $strChannel     The channel to update. If NULL, the active one is used
  439.     *   @return array   Package list for the given channel
  440.     */
  441.     public function refreshLocalPackages($strChannel = null)
  442.     {
  443.         if ($strChannel === null{
  444.             $strChannel $this->strActiveChannel;
  445.         }
  446.         $this->arPackages[$strChannel= self::getLocalPackages($strChannel$this->arPackages[$strChannel]);
  447.         return $this->arPackages[$strChannel];
  448.     }//public function refreshLocalPackages($strChannel = null)
  449.  
  450.  
  451.  
  452.     /**
  453.     *   Refreshs the package list of the given channel by re-reading the remote
  454.     *   package information.
  455.     *
  456.     *   @param string   $strChannel     The channel to update. If NULL, the active one is used
  457.     *   @return array   Package list for the given channel
  458.     */
  459.     public function refreshRemotePackages($strChannel = null$callback = null)
  460.     {
  461.         if ($strChannel === null{
  462.             $strChannel $this->strActiveChannel;
  463.         }
  464.         $this->arPackages[$strChannel= self::loadRemotePackageData($this->arPackages[$strChannel]$strChannel$callbackfalsefalse);
  465.         return $this->arPackages[$strChannel];
  466.     }//public function refreshRemotePackages($strChannel = null, $callback = null)
  467.  
  468. }//class PEAR_Frontend_Gtk2_Packages
  469. ?>

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