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

Source for file Installation.php

Documentation is available at Installation.php

  1. <?php
  2. require_once 'PEAR/Command.php';
  3. require_once 'PEAR/Frontend.php';
  4.  
  5. /**
  6. *   Installation dialog and user interaction interface
  7. *   for the PEAR Gtk2 installer
  8. *
  9. *   @author Christian Weiske <cweiske@php.net>
  10. */
  11. class PEAR_Frontend_Gtk2_Installation extends PEAR_Frontend
  12. {
  13.     protected $dlgParent     = null;
  14.     protected $glade         = null;
  15.     protected $dlgInstalling = null;
  16.     protected $txtLog        = null;
  17.  
  18.     protected $strPackage    = null;
  19.     protected $strChannel    = null;
  20.  
  21.     /**
  22.     *   The command which shall be executed (upgrade or uninstall)
  23.     *   @var string 
  24.     */
  25.     protected $strCommand    = null;
  26.  
  27.     /**
  28.     *   If the log detects an unrecoverable error (e.g. failed dependency)
  29.     *   an error symbol is shown, no matter if the callback for "uninstall ok"
  30.     *   is called.
  31.     *
  32.     *   @var boolean 
  33.     */
  34.     protected $bSeriousError = false;
  35.  
  36.     /**
  37.     *   Array with widgets from the glade file. They
  38.     *   are loaded in the buildDialog() methods
  39.     *   @var array 
  40.     */
  41.     protected $arWidgets     = array();
  42.  
  43.     protected $bQuitLoopOnClose  = true;
  44.  
  45.     protected $nPercentage = 0;
  46.  
  47.  
  48.  
  49.     /**
  50.     *   The widgets which shall be loaded from the glade
  51.     *   file into the $arWidgets array
  52.     *   @var array 
  53.     */
  54.     protected static $arRequestedWidgets = array(
  55.         'dlgInstalling''imgInstalling''progBarInstaller''btnCloseInstalling',
  56.         'lblInstalling''txtInstalling''expLog'
  57.     );
  58.  
  59.  
  60.  
  61.     public function __construct(GtkWidget $parentGladeXML $glade)
  62.     {
  63.         $this->dlgParent $parent;
  64.         $this->glade $glade;
  65.         $this->buildDialog();
  66.     }//public function __construct(GtkWidget $parent)
  67.  
  68.  
  69.  
  70.     /**
  71.     *   load the glade file, load the widgets, connect the signals
  72.     */
  73.     protected function buildDialog()
  74.     {
  75.         foreach (self::$arRequestedWidgets as $strWidgetName{
  76.             $this->arWidgets[$strWidgetName$this->glade->get_widget($strWidgetName);
  77.         }
  78.         $this->txtLog        $this->arWidgets['txtInstalling'];
  79.         $this->dlgInstalling $this->arWidgets['dlgInstalling'];
  80.         $this->dlgInstalling->set_transient_for($this->dlgParent);
  81.  
  82.         $this->arWidgets['btnCloseInstalling']->connect_simple('clicked'array($this'hideMe'));
  83.         $this->dlgInstalling->connect('delete-event'array($this'deleteWindow'));
  84.     }//protected function buildDialog()
  85.  
  86.  
  87.  
  88.     /**
  89.     *   Installs (or uninstalls) the given package.
  90.     *   If you want to install a file, set $strChannel and $strVersion
  91.     *   to NULL.
  92.     *
  93.     *   @param string   $strChannel The channel on which the package can be found
  94.     *   @param string   $strPackage The package to install
  95.     *   @param string   $strVersion Package version to install
  96.     *   @param boolean  $bInstall   If the package shall be installed (true) or uninstalled (false)
  97.     */
  98.     public function installPackage($strChannel$strPackage$strVersion$bInstall = true$strDepOptions = null$bForce = false)
  99.     {
  100.         //Bad code, but PEAR doesn't offer the possibility to do that a better way
  101.         $GLOBALS['_PEAR_FRONTEND_SINGLETON'$this;
  102.  
  103.         $this->bSeriousError = false;//there is no serious error *yet*
  104.         $this->strPackage    $strPackage;
  105.         $this->strChannel    $strChannel;
  106.  
  107.         $strText $bInstall 'I' 'Uni';
  108.         $strText .= 'nstalling ' $strChannel '/' $strPackage;
  109.         $this->dlgInstalling->set_title($strText);
  110.         $this->setCurrentAction($strText);
  111.         $this->setCurrentIcon(Gtk::STOCK_EXECUTE);
  112.         $this->setPercentage(0);
  113.  
  114.         $this->clearLog();
  115. //        $this->arWidgets['expLog']->set_expanded(false);
  116.  
  117.         $this->appendToLog($strText "\r\n");
  118.  
  119.         $this->showMe();
  120.  
  121.         $cmd              = PEAR_Command::factory('install'PEAR_Config::singleton());
  122.         if ($bInstall{
  123.             if ($strChannel === null && $strVersion === null{
  124.                 //Install file
  125.                 $strPackagePath $strPackage;
  126.                 $strCommand     'upgrade';
  127.             else {
  128.                 $strPackagePath 'channel://' $strChannel '/' $strPackage '-' $strVersion;
  129.                 $strCommand     'upgrade';
  130.             }
  131.         else {
  132.             $strPackagePath     'channel://' $strChannel '/' $strPackage;
  133.             $strCommand         'uninstall';
  134.         }
  135.         $this->strCommand $strCommand;
  136.  
  137.         while (Gtk::events_pending()) Gtk::main_iteration();}
  138.  
  139.         if ($strCommand === 'upgrade'{
  140.             $arOptions = array($strDepOptions => true);
  141.         else {
  142.             $arOptions = array();
  143.         }
  144.         if ($bForce{
  145.             $arOptions['force'= true;
  146.         }
  147.  
  148.         $cmd->run($strCommand$arOptionsarray($strPackagePath));
  149.  
  150.         //own main loop so that the next functions aren't executed until the window is closed
  151.         $this->bQuitLoopOnClose = true;
  152.         Gtk::main();
  153.     }//public function installPackage($strChannel, $strPackage, $strVersion, $bInstall = true, $strDepOptions = null, $bForce = false)
  154.  
  155.  
  156.  
  157.     /**
  158.     *   Executes a channel command
  159.     *
  160.     *   @param string   $strCommand     The command (delete, update, discover)
  161.     *   @param string   $strChannel     The channel name (or the url for discovering)
  162.     */
  163.     public function channelCommand($strCommand$strChannel)
  164.     {
  165.         $this->prepareFresh();
  166.         $this->showMe();
  167.         $cmd = PEAR_Command::factory('channel-' $strCommandPEAR_Config::singleton());
  168.         $ret $cmd->run('channel-' $strCommandarray()array($strChannel));
  169.         if (!PEAR::isError($ret)) {
  170.             $this->setFinished();
  171.         else {
  172.             $this->bSeriousError = true;
  173.             $this->setFinished();
  174.             $this->setCurrentAction($ret->getMessage());
  175.             $this->appendToLog($ret->getMessage("\r\n");
  176.             $this->appendToLog($ret->getUserinfo("\r\n");
  177.         }
  178.         $this->bQuitLoopOnClose = true;
  179.         Gtk::main();
  180.     }//public function channelCommand($strCommand, $strChannel)
  181.  
  182.  
  183.  
  184.     /**
  185.     *   Use this method to run commands by hand, and you need
  186.     *   the interface to be shown.
  187.     */
  188.     public function show($strAction$bQuitLoopOnClose = false)
  189.     {
  190.         $this->bSeriousError = false;
  191.         $this->bQuitLoopOnClose $bQuitLoopOnClose;
  192.         $this->prepareFresh();
  193.         $this->setCurrentAction($strAction);
  194.         $this->showMe();
  195.     }//public function show($strAction, $bQuitLoopOnClose = false)
  196.  
  197.  
  198.  
  199.     /**
  200.     *   Prepares the widgets to have a fresh look.
  201.     *   Use it before starting the actual work
  202.     */
  203.     protected function prepareFresh()
  204.     {
  205.         //Bad code, but PEAR doesn't offer the possibility to do that a better way
  206.         $GLOBALS['_PEAR_FRONTEND_SINGLETON'$this;
  207.  
  208.         $this->setPercentage(0);
  209.         $this->clearLog();
  210.         $this->setCurrentIcon(Gtk::STOCK_EXECUTE);
  211.         $this->setCurrentAction('');
  212.     }//protected function prepareFresh()
  213.  
  214.  
  215.     protected function showMe()
  216.     {
  217.         $this->dlgInstalling->set_modal(true);
  218.         $this->dlgInstalling->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
  219.         $this->dlgInstalling->show();
  220.         while (Gtk::events_pending()) Gtk::main_iteration();}
  221.     }//protected function showMe()
  222.  
  223.  
  224.  
  225.     public function hideMe()
  226.     {
  227.         $this->dlgInstalling->set_modal(false);
  228.         $this->dlgInstalling->hide();
  229.         if ($this->bQuitLoopOnClose{
  230.             Gtk::main_quit();
  231.         }
  232.     }//public function hideMe()
  233.  
  234.  
  235.  
  236.     /**
  237.     *   The user may not close the window by hand
  238.     */
  239.     public function deleteWindow()
  240.     {
  241.         return true;
  242.     }//public function deleteWindow()
  243.  
  244.  
  245.  
  246.     protected function appendToLog($strText)
  247.     {
  248.         $buffer $this->txtLog->get_buffer();
  249.         $end $buffer->get_end_iter();
  250.         $buffer->insert($end$strText);
  251.  
  252.         $this->txtLog->scroll_to_iter($buffer->get_end_iter()0.49);
  253.     }//protected function appendToLog($strText)
  254.  
  255.  
  256.  
  257.     protected function clearLog()
  258.     {
  259.         $buffer $this->txtLog->get_buffer();
  260.         $buffer->delete($buffer->get_start_iter()$buffer->get_end_iter());
  261.     }//protected function clearLog()
  262.  
  263.  
  264.  
  265.     protected function setCurrentAction($strText)
  266.     {
  267.         $this->arWidgets['lblInstalling']->set_text($strText);
  268.     }//protected function setCurrentAction($strText)
  269.  
  270.  
  271.  
  272.     /**
  273.     *   Set the icon for the dialog
  274.     *
  275.     *   @param int $nId     The stock item id
  276.     */
  277.     protected function setCurrentIcon($nId)
  278.     {
  279.         $this->arWidgets['imgInstalling']->set_from_stock($nIdGtk::ICON_SIZE_DIALOG);
  280.     }//protected function setCurrentIcon($nId)
  281.  
  282.  
  283.  
  284.     /**
  285.     *   Set the progress bar progress in percent (0-100)
  286.     */
  287.     protected function setPercentage($nPercent)
  288.     {
  289.         $nPercent $nPercent % 100;
  290.         $this->nPercentage $nPercent;
  291.         if ($nPercent <= 0{
  292.             $this->arWidgets['progBarInstaller']->set_fraction(0);
  293.         else {
  294.             $this->arWidgets['progBarInstaller']->set_fraction($nPercent/100);
  295.         }
  296.     }//protected function setPercentage($nPercent)
  297.  
  298.  
  299.  
  300.     /**
  301.     *   Add some percent to the progress bar
  302.     */
  303.     protected function addPercentage($nPercentToAdd)
  304.     {
  305.         $this->setPercentage($this->nPercentage $nPercentToAdd);
  306.     }//protected function addPercentage($nPercentToAdd)
  307.  
  308.  
  309.  
  310.     protected function setFinished()
  311.     {
  312.         if ($this->bSeriousError{
  313.             $this->setCurrentIcon(Gtk::STOCK_DIALOG_ERROR);
  314.             $this->arWidgets['expLog']->set_expanded(true);
  315.         else {
  316.             $this->setCurrentIcon(Gtk::STOCK_APPLY);
  317.         }
  318.         $this->setPercentage(100);
  319.     }//protected function setFinished()
  320.  
  321.  
  322.  
  323.     public function __call($function$arguments)
  324.     {
  325.         $this->appendToLog('__call: ' $function ' with ' count($arguments' arguments.' "\r\n");
  326.         foreach ($arguments as $strName => $strValue{
  327.             $this->appendToLog('   arg:' $strName ':' gettype($strValue'::' $strValue "\r\n");
  328.         }
  329.         while (Gtk::events_pending()) Gtk::main_iteration();}
  330.     }//public function __call($function, $arguments)
  331.  
  332.  
  333.  
  334.     /**
  335.     *   All functions which might be expected in a PEAR_Frontend go here
  336.     */
  337.     public function outputData($data$command = null)
  338.     {
  339.         $this->addPercentage(5);
  340.  
  341.         switch ($command{
  342.             case 'install':
  343.             case 'upgrade':
  344.             case 'upgrade-all':
  345.                 //FIXME: check for release warnings $data['release_warnings']
  346.                 $this->setCurrentAction('Installation of ' $this->strPackage ' done');
  347.                 $this->appendToLog($data['data'"\r\n");
  348.                 $this->setFinished();
  349.                 break;
  350.  
  351.             case 'uninstall':
  352.                 if ($this->bSeriousError{
  353.                     $this->setCurrentAction('Error uninstalling ' $this->strPackage);
  354.                     $this->arWidgets['expLog']->set_expanded(true);
  355.                 else {
  356.                     $this->setCurrentAction('Uninstallation of ' $this->strPackage ' ok');
  357.                     $this->appendToLog('Uninstall ok' "\r\n");
  358.                 }
  359.                 $this->setFinished();
  360.                 break;
  361.             case 'channel-discover':
  362.             case 'channel-delete':
  363.                 $this->setCurrentAction($data);
  364.                 $this->appendToLog($data "\r\n");
  365.                 $this->setFinished();
  366.                 break;
  367.  
  368.             case 'build':
  369.                 $this->appendToLog($data "\r\n");
  370.                 break;
  371.  
  372.             default:
  373. if ($command !== null{
  374.     echo 'Unsupported command in outputData: 'var_dump($command);
  375. }
  376.                 if (!is_array($data)) {
  377.                     $this->setCurrentAction($data);
  378.                     $this->appendToLog($data "\r\n");
  379.                     if (strpos($data'is up to date'!== false{
  380.                         $this->setFinished();
  381.                     else if (strpos(strtolower($data)'error:'!== false{
  382.                         $this->bSeriousError = true;
  383.                         $this->setFinished();
  384.                     }
  385.  
  386.                 else if (isset($data['headline'])) {
  387.                     $this->setCurrentAction($data['headline']);
  388.                     $this->appendToLog('!!!' $data['headline''!!!' "\r\n");
  389.                     if (stripos(strtolower($data['headline'])'error'!== false{
  390.                         $this->bSeriousError = true;
  391.                         $this->setFinished();
  392.                     }
  393.                     if (is_array($data['data'])) {
  394.                         //could somebody tell me if there is a fixed format?
  395.                         foreach ($data['data'as $nId => $arSubData{
  396.                             $this->appendToLog(implode(' / '$arSubData"\r\n");
  397.                         }
  398.                     else if (is_string($data['data'])) {
  399.                         $this->appendToLog($data['data'"\r\n");
  400.                     else {
  401.                         //What's this?
  402.                         $this->appendToLog('PEAR_Frontend_Gtk2_Installation::outputData: Unhandled type "' gettype($data['data']"\"\r\n");
  403.                     }
  404.                 }
  405.  
  406.                 while (Gtk::events_pending()) Gtk::main_iteration();}
  407.                 break;
  408.         }
  409.     }//public function outputData($data, $command = null)
  410.  
  411.  
  412.  
  413.     public function log($msg$append_crlf = true)
  414.     {
  415. //require_once 'Gtk2/VarDump.php'; new Gtk2_VarDump(array($level, $msg, $append_crlf), 'msg');
  416.         if (strpos($msg'is required by installed package'!== false
  417.             || strpos(strtolower($msg)'error:')
  418.         {
  419.             $this->bSeriousError = true;
  420.         }
  421.         if ($msg == '.' || $append_crlf === false{
  422.             $this->addPercentage(1);
  423.         else {
  424.             $this->addPercentage(10);
  425.         }
  426.  
  427.         $this->appendToLog($msg ($append_crlf "\r\n":''));
  428.         while (Gtk::events_pending()) Gtk::main_iteration();}
  429.     }//public function log($msg, $append_crlf = true)
  430.  
  431.  
  432.  
  433.     /**
  434.     *   Ask the user a question
  435.     *
  436.     *   @param string   $prompt     The question to ask
  437.     *   @param string   $default    The default value
  438.     */
  439.     public function userConfirm($prompt$default 'yes')
  440.     {
  441.         $dialog = new GtkMessageDialog(
  442.             $this->arWidgets['dlgInstalling']Gtk::DIALOG_MODALGtk::MESSAGE_QUESTION,
  443.             Gtk::BUTTONS_YES_NO$prompt
  444.         );
  445.         $answer $dialog->run();
  446.         $dialog->destroy();
  447.  
  448.         return ($answer == Gtk::RESPONSE_YES);
  449.     }//public function userConfirm($prompt, $default = 'yes')
  450.  
  451.  
  452. }//class PEAR_Frontend_Gtk2_Installation extends PEAR_Frontend
  453. ?>

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