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

Source for file Web.php

Documentation is available at Web.php

  1. <?php
  2. /*
  3.  * This is a HTML driver for PEAR_PackageUpdate.
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.01 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   PEAR
  14.  * @package    PEAR_PackageUpdate_Web
  15.  * @author     Laurent Laville <pear@laurent-laville.org>
  16.  * @copyright  2006 Laurent Laville
  17.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  18.  * @version    CVS: $Id: Web.php,v 1.2 2006/05/25 14:44:40 farell Exp $
  19.  * @since      File available since Release 0.1.0
  20.  */
  21.  
  22. require_once 'PEAR/PackageUpdate.php';
  23. require_once 'HTML/QuickForm.php';
  24.  
  25. if (!defined('PEAR_PACKAGEUPDATE_DATA_DIR')) {
  26.     define('PEAR_PACKAGEUPDATE_DATA_DIR',
  27.         '@data_dir@' . DIRECTORY_SEPARATOR .
  28.         '@package_name@' . DIRECTORY_SEPARATOR);
  29. }
  30.  
  31. /**
  32.  * This is a HTML driver for PEAR_PackageUpdate.
  33.  *
  34.  * A package to make adding self updating functionality to other
  35.  * packages easy.
  36.  *
  37.  * The interface for this package must allow for the following
  38.  * functionality:
  39.  * - check to see if a new version is available for a given
  40.  *   package on a given channel
  41.  *   - check minimum state
  42.  * - present information regarding the upgrade (version, size)
  43.  *   - inform user about dependencies
  44.  * - allow user to confirm or cancel upgrade
  45.  * - download and install the package
  46.  * - track preferences on a per package basis
  47.  *   - don't ask again
  48.  *   - don't ask until next release
  49.  *   - only ask for state XXXX or higher
  50.  *   - bug/minor/major updates only
  51.  * - update channel automatically
  52.  * - force application to exit when upgrade complete
  53.  *   - PHP-GTK/CLI apps must exit to allow classes to reload
  54.  *   - web front end could send headers to reload certain page
  55.  *
  56.  * This class is simply a wrapper for PEAR classes that actually
  57.  * do the work.
  58.  *
  59.  * EXAMPLE:
  60.  * <code>
  61.  * <?php
  62.  *  class Goo {
  63.  *      function __construct()
  64.  *      {
  65.  *          // Check for updates...
  66.  *          require_once 'PEAR/PackageUpdate.php';
  67.  *          $ppu =& PEAR_PackageUpdate::factory('Web', 'XML_RPC', 'pear');
  68.  *          if ($ppu !== false) {
  69.  *              if ($ppu->checkUpdate()) {
  70.  *                  // Use a dialog window to ask permission to update.
  71.  *                  if ($ppu->presentUpdate()) {
  72.  *                      if ($ppu->update()) {
  73.  *                          // If the update succeeded, the application should
  74.  *                          // be restarted.
  75.  *                          $ppu->forceRestart();
  76.  *                      }
  77.  *                  }
  78.  *              }
  79.  *          }
  80.  *          // ...
  81.  *      }
  82.  *      // ...
  83.  *  }
  84.  * ?>
  85.  * </code>
  86.  *
  87.  * @category   PEAR
  88.  * @package    PEAR_PackageUpdate_Web
  89.  * @author     Laurent Laville <pear@laurent-laville.org>
  90.  * @copyright  2006 Laurent Laville
  91.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  92.  * @version    Release: @package_version@
  93.  * @since      Class available since Release 0.1.0
  94.  */
  95.  
  96. class PEAR_PackageUpdate_Web extends PEAR_PackageUpdate
  97. {
  98.     /**
  99.      * The main Dialog widget.
  100.      *
  101.      * @access public
  102.      * @var    object 
  103.      * @since  0.1.0
  104.      */
  105.     var $mainwidget;
  106.  
  107.     /**
  108.      * The preference Dialog widget.
  109.      *
  110.      * @access public
  111.      * @var    object 
  112.      * @since  0.1.0
  113.      */
  114.     var $prefwidget;
  115.  
  116.     /**
  117.      * The error Dialog widget.
  118.      *
  119.      * @access public
  120.      * @var    object 
  121.      * @since  0.1.0
  122.      */
  123.     var $errwidget;
  124.  
  125.     /**
  126.      * Creates the dialog that will ask the user if it is ok to update.
  127.      *
  128.      * @access protected
  129.      * @return void 
  130.      * @since  0.1.0
  131.      */
  132.     function createMainDialog()
  133.     {
  134.         // Create the dialog
  135.         $this->mainwidget = new HTML_QuickForm('infoPPU');
  136.         $this->mainwidget->removeAttribute('name');        // XHTML compliance
  137.  
  138.         // Create a title string.
  139.         $title 'Update available for: ' $this->packageName;
  140.         $this->mainwidget->addElement('header'''$title);
  141.  
  142.         // Create an image placeholder and the message for the dialog.
  143.         $msg  'A new version of ' $this->packageName ' ';
  144.         $msg .= " is available.\n\nWould you like to upgrade?";
  145.         $this->mainwidget->addElement('static''message''<div id="widget-icon-info"></div>'nl2br($msg));
  146.  
  147.         // The update details.
  148.         $this->mainwidget->addElement('text''current_version''Current Version:');
  149.         $this->mainwidget->addElement('text''release_version''Release Version:');
  150.         $this->mainwidget->addElement('text''release_date''Release Date:');
  151.         $this->mainwidget->addElement('text''release_state''Release State:');
  152.         $this->mainwidget->addElement('static''release_notes''Release Notes:',
  153.             '<div class="autoscroll">' .
  154.             nl2br($this->info['releasenotes'].
  155.             '</div>'
  156.         );
  157.         $this->mainwidget->addElement('text''release_by''Released By:');
  158.  
  159.         $this->mainwidget->setDefaults(array(
  160.             'current_version' => $this->instVersion,
  161.             'release_version' => $this->latestVersion,
  162.             'release_date'    => $this->info['releasedate'],
  163.             'release_state'   => $this->info['state'],
  164.             'release_by'      => $this->info['doneby']
  165.         ));
  166.  
  167.         $buttons = array();
  168.         // Add the preferences button.
  169.         $buttons[&HTML_QuickForm::createElement('submit''btnPrefs''Preferences');
  170.  
  171.         // Add the yes/no buttons.
  172.         $buttons[&HTML_QuickForm::createElement('submit''mainBtnNo''No');
  173.         $buttons[&HTML_QuickForm::createElement('submit''mainBtnYes''Yes');
  174.  
  175.         $this->mainwidget->addGroup($buttons'buttons''''&nbsp;'false);
  176.  
  177.         $this->mainwidget->freeze();
  178.     }
  179.  
  180.     /**
  181.      * Creates the dialog that will ask the user for his preferences.
  182.      *
  183.      * @access protected
  184.      * @return void 
  185.      * @since  0.1.0
  186.      */
  187.     function createPrefDialog($prefs)
  188.     {
  189.         // Create the dialog
  190.         $this->prefwidget = new HTML_QuickForm('prefPPU');
  191.         $this->prefwidget->removeAttribute('name');        // XHTML compliance
  192.  
  193.         // Create the preferences dialog title.
  194.         $title $this->packageName ' Update Preferences';
  195.         $this->prefwidget->addElement('header'''$title);
  196.  
  197.         // It needs a check box for "Don't ask again"
  198.         $this->prefwidget->addElement('checkbox''dontAsk''''Don\'t ask me again');
  199.         // Set the default.
  200.         if (isset($prefs[PEAR_PACKAGEUPDATE_PREF_NOUPDATES])) {
  201.             $this->prefwidget->setDefaults(array('dontAsk' => $prefs[PEAR_PACKAGEUPDATE_PREF_NOUPDATES]));
  202.         }
  203.  
  204.         // It needs a check box for the next release.
  205.         $this->prefwidget->addElement('checkbox''nextRelease''''Don\'t ask again until the next release.');
  206.         // Set the default.
  207.         if (isset($prefs[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE])) {
  208.             $this->prefwidget->setDefaults(array('nextRelease' => $prefs[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE]));
  209.         }
  210.  
  211.         // It needs a radio group for the state.
  212.         $allStates = array();
  213.         $allStates[&HTML_QuickForm::createElement('radio'nullnull'All states''all');
  214.         $allStates[&HTML_QuickForm::createElement('radio'nullnull'devel'PEAR_PACKAGEUPDATE_STATE_DEVEL);
  215.         $allStates[&HTML_QuickForm::createElement('radio'nullnull'alpha'PEAR_PACKAGEUPDATE_STATE_ALPHA);
  216.         $allStates[&HTML_QuickForm::createElement('radio'nullnull'beta'PEAR_PACKAGEUPDATE_STATE_BETA);
  217.         $allStates[&HTML_QuickForm::createElement('radio'nullnull'stable'PEAR_PACKAGEUPDATE_STATE_STABLE);
  218.         $this->prefwidget->addGroup($allStates'allStates''Only ask when the state is at least:''<br />');
  219.         // Set the default.
  220.         $stateDef (isset($prefs[PEAR_PACKAGEUPDATE_PREF_STATE])) ?
  221.             $prefs[PEAR_PACKAGEUPDATE_PREF_STATE'all';
  222.         $this->prefwidget->setDefaults(array('allStates' => $stateDef));
  223.  
  224.  
  225.         // It needs a radio group for the type.
  226.         $allTypes = array();
  227.         $allTypes[&HTML_QuickForm::createElement('radio'nullnull'All Release Types''all');
  228.         $allTypes[&HTML_QuickForm::createElement('radio'nullnull'Bug fix'PEAR_PACKAGEUPDATE_TYPE_BUG);
  229.         $allTypes[&HTML_QuickForm::createElement('radio'nullnull'Minor'PEAR_PACKAGEUPDATE_TYPE_MINOR);
  230.         $allTypes[&HTML_QuickForm::createElement('radio'nullnull'Major'PEAR_PACKAGEUPDATE_TYPE_MAJOR);
  231.         $this->prefwidget->addGroup($allTypes'allTypes''Only ask when the type is at least:''<br />');
  232.         // Set the default.
  233.         $typeDef (isset($prefs[PEAR_PACKAGEUPDATE_PREF_TYPE])) ?
  234.             $prefs[PEAR_PACKAGEUPDATE_PREF_TYPE'all';
  235.         $this->prefwidget->setDefaults(array('allTypes' => $typeDef));
  236.  
  237.         $buttons = array();
  238.         // Add the yes/no buttons.
  239.         $buttons[&HTML_QuickForm::createElement('submit''prefBtnNo''No');
  240.         $buttons[&HTML_QuickForm::createElement('submit''prefBtnYes''Yes');
  241.  
  242.         $this->prefwidget->addGroup($buttons'buttons''''&nbsp;'false);
  243.     }
  244.  
  245.     /**
  246.      * Creates the dialog that will show errors to the user.
  247.      *
  248.      * @access protected
  249.      * @return void 
  250.      * @since  0.1.0
  251.      */
  252.     function createErrorDialog($context = false)
  253.     {
  254.         // Don't do anything if the dialog already exists.
  255.         if (isset($this->errwidget)) {
  256.             return;
  257.         }
  258.  
  259.         // Create the dialog
  260.         $this->errwidget = new HTML_QuickForm('errorPPU');
  261.         $this->errwidget->removeAttribute('name');        // XHTML compliance
  262.  
  263.         // Create a title string.
  264.         $title 'Error(s) occured while trying to Update for: ' $this->packageName;
  265.         $this->errwidget->addElement('header'''$title);
  266.  
  267.         // Create an image placeholder and the message for the dialog.
  268.         $this->errwidget->addElement('static''icon''<div id="widget-icon-error"></div>');
  269.         $this->errwidget->addElement('static''message''Message:');
  270.  
  271.         if ($context{
  272.             // The error context details.
  273.             $this->errwidget->addElement('text''context_file''File:');
  274.             $this->errwidget->addElement('text''context_line''Line:');
  275.             $this->errwidget->addElement('text''context_function''Function:');
  276.             $this->errwidget->addElement('text''context_class''Class:');
  277.         }
  278.  
  279.         $buttons = array();
  280.         // Add the Ok button.
  281.         $buttons[&HTML_QuickForm::createElement('submit''errorBtnOk''Ok');
  282.  
  283.         $this->errwidget->addGroup($buttons'buttons''''&nbsp;'false);
  284.  
  285.         $this->errwidget->freeze();
  286.     }
  287.  
  288.     /**
  289.      * Creates and runs a dialog for setting preferences.
  290.      *
  291.      * @access public
  292.      * @return boolean true if the preferences were set and saved.
  293.      * @since  0.1.0
  294.      */
  295.     function prefDialog()
  296.     {
  297.         // The preferences dialog needs to have some inputs for the user.
  298.         // Get the current preferences so that defaults can be set.
  299.         $prefs $this->getPackagePreferences();
  300.  
  301.         // Create the preference dialog widget.
  302.         $this->createPrefDialog($prefs);
  303.  
  304.         $renderer &$this->getHtmlRendererWithoutLabel($this->prefwidget);
  305.  
  306.         // Get Html code to display
  307.         $html $this->toHtml($renderer);
  308.  
  309.         // Run the dialog and return whether or not the user clicked "Yes".
  310.         if ($this->prefwidget->validate()) {
  311.             $safe $this->prefwidget->exportValues();
  312.  
  313.             if (isset($safe['prefBtnYes'])) {
  314.                 // Get all of the preferences.
  315.                 $prefs = array();
  316.  
  317.                 // Check for the don't ask preference.
  318.                 $prefs[PEAR_PACKAGEUPDATE_PREF_NOUPDATES= isset($safe['dontAsk']);
  319.  
  320.                 // Check for next version.
  321.                 $prefs[PEAR_PACKAGEUPDATE_PREF_NEXTRELEASE= isset($safe['nextRelease']);
  322.  
  323.                 // Check for type.
  324.                 $prefs[PEAR_PACKAGEUPDATE_PREF_TYPE$safe['allTypes'];
  325.  
  326.                 // Check for state.
  327.                 $prefs[PEAR_PACKAGEUPDATE_PREF_STATE$safe['allStates'];
  328.  
  329.                 // Save the preferences.
  330.                 return $this->setPreferences($prefs);
  331.  
  332.             elseif (isset($safe['prefBtnNo'])) {
  333.                 return false;
  334.             }
  335.         }
  336.         echo $html;
  337.         exit();
  338.     }
  339.  
  340.     /**
  341.      * Redirects or exits to force the user to restart the application.
  342.      *
  343.      * @access public
  344.      * @return void 
  345.      * @since  0.1.0
  346.      */
  347.     function forceRestart()
  348.     {
  349.         // Reload current page.
  350.         header('Location: ' $_SERVER['PHP_SELF']);
  351.         exit();
  352.     }
  353.  
  354.     /**
  355.      * Presents the user with the option to update.
  356.      *
  357.      * @access public
  358.      * @return boolean true if the user would like to update the package.
  359.      * @since  0.1.0
  360.      */
  361.     function presentUpdate()
  362.     {
  363.         // Make sure the info has been grabbed.
  364.         // This will just return if the info has already been grabbed.
  365.         $this->getPackageInfo();
  366.  
  367.         // Create the main dialog widget.
  368.         $this->createMainDialog();
  369.  
  370.         $renderer &$this->getHtmlRendererWithLabel($this->mainwidget);
  371.  
  372.         // Get Html code to display
  373.         $html $this->toHtml($renderer);
  374.  
  375.         // Run the dialog and return whether or not the user clicked "Yes".
  376.         if ($this->mainwidget->validate()) {
  377.             $safe $this->mainwidget->exportValues();
  378.  
  379.             if (isset($safe['mainBtnYes'])) {
  380.                 return true;
  381.             elseif (isset($safe['mainBtnNo'])) {
  382.                 return false;
  383.             else {
  384.                 $this->prefDialog();
  385.             }
  386.         }
  387.         echo $html;
  388.         exit();
  389.     }
  390.  
  391.     /**
  392.      * Presents an error in a dialog window.
  393.      *
  394.      * @access public
  395.      * @param  boolean $context  true if you want to have error context details
  396.      * @return boolean true if an error was displayed.
  397.      * @since  0.1.0
  398.      */
  399.     function errorDialog($context = false)
  400.     {
  401.         // Check to see if there are errors into stack.
  402.         if ($this->hasErrors()) {
  403.             $error $this->popError();
  404.  
  405.             // Create the error dialog widget.
  406.             $this->createErrorDialog($context);
  407.             $this->errwidget->setConstants(array('message' => $error['message']));
  408.             // Fill the context details
  409.             if ($context{
  410.                 $file $line $function $class '';
  411.  
  412.                 if (isset($error['context']['file'])) {
  413.                     $file $error['context']['file'];
  414.                 }
  415.                 if (isset($error['context']['line'])) {
  416.                     $line $error['context']['line'];
  417.                 }
  418.                 if (isset($error['context']['function'])) {
  419.                     $function $error['context']['function'];
  420.                 }
  421.                 if (isset($error['context']['class'])) {
  422.                     $class $error['context']['class'];
  423.                 }
  424.  
  425.                 $this->errwidget->setConstants(array(
  426.                     'context_file' => $file,
  427.                     'context_line' => $line,
  428.                     'context_function' => $function,
  429.                     'context_class' => $class
  430.                     ));
  431.             }
  432.  
  433.             $renderer &$this->getHtmlRendererWithLabel($this->errwidget);
  434.  
  435.             // Get Html code to display
  436.             $html $this->toHtml($renderer);
  437.  
  438.             // Run the dialog.
  439.             if ($this->errwidget->validate()) {
  440.                 return true;
  441.             }
  442.             echo $html;
  443.             exit();
  444.         }
  445.         // Nothing to do.
  446.         return false;
  447.     }
  448.  
  449.     /**
  450.      * Returns HTML renderer for a dialog with input labels and values
  451.      *
  452.      * @access protected
  453.      * @return object  instance of a QuickForm renderer
  454.      * @since  0.1.0
  455.      */
  456.     function &getHtmlRendererWithLabel(&$widget)
  457.     {
  458.         // Templates string
  459.         $formTemplate "\n<form{attributes}>"
  460.             . "\n<table class=\"dialogbox\">"
  461.             . "\n{content}"
  462.             . "\n</table>"
  463.             . "\n</form>";
  464.  
  465.         $headerTemplate "\n<tr>"
  466.             . "\n\t<td class=\"widget-header\" colspan=\"2\">"
  467.             . "\n\t\t{header}"
  468.             . "\n\t</td>"
  469.             . "\n</tr>";
  470.  
  471.         $elementTemplate "\n<tr>"
  472.             . "\n\t<td class=\"widget-label\"><!-- BEGIN label -->{label}<!-- END label --></td>"
  473.             . "\n\t<td class=\"widget-input\">{element}</td>"
  474.             . "\n</tr>";
  475.  
  476.         $elementNavig "\n<tr class=\"widget-buttons\">"
  477.             . "\n\t<td>&nbsp;</td>"
  478.             . "\n\t<td>{element}</td>"
  479.             . "\n</tr>";
  480.  
  481.         $renderer =$widget->defaultRenderer();
  482.  
  483.         $renderer->setFormTemplate($formTemplate);
  484.         $renderer->setHeaderTemplate($headerTemplate);
  485.         $renderer->setElementTemplate($elementTemplate);
  486.         $renderer->setElementTemplate($elementNavig'buttons');
  487.  
  488.         $widget->accept($renderer);
  489.  
  490.         return $renderer;
  491.     }
  492.  
  493.     /**
  494.      * Returns HTML renderer for a dialog with only input values (no labels)
  495.      *
  496.      * @access protected
  497.      * @return object  instance of a QuickForm renderer
  498.      * @since  0.1.0
  499.      */
  500.     function &getHtmlRendererWithoutLabel(&$widget)
  501.     {
  502.         // Templates string
  503.         $formTemplate "\n<form{attributes}>"
  504.             . "\n<table class=\"dialogbox\">"
  505.             . "\n{content}"
  506.             . "\n</table>"
  507.             . "\n</form>";
  508.  
  509.         $headerTemplate "\n<tr>"
  510.             . "\n\t<td class=\"widget-header\">"
  511.             . "\n\t\t{header}"
  512.             . "\n\t</td>"
  513.             . "\n</tr>";
  514.  
  515.         $elementTemplate "\n<tr>"
  516.             . "\n\t<td class=\"widget-input\">{element}</td>"
  517.             . "\n</tr>";
  518.  
  519.         $elementNavig "\n<tr class=\"widget-buttons\">"
  520.             . "\n\t<td>{element}</td>"
  521.             . "\n</tr>";
  522.  
  523.         $elementRadio "\n<tr>"
  524.             . "\n\t<td class=\"widget-input\"><!-- BEGIN label -->{label}<!-- END label --><br />{element}</td>"
  525.             . "\n</tr>";
  526.  
  527.         $renderer =$widget->defaultRenderer();
  528.  
  529.         $renderer->setFormTemplate($formTemplate);
  530.         $renderer->setHeaderTemplate($headerTemplate);
  531.         $renderer->setElementTemplate($elementTemplate);
  532.         $renderer->setElementTemplate($elementNavig'buttons');
  533.         $renderer->setElementTemplate($elementRadio'allStates');
  534.         $renderer->setElementTemplate($elementRadio'allTypes');
  535.  
  536.         $widget->accept($renderer);
  537.  
  538.         return $renderer;
  539.     }
  540.  
  541.     /**
  542.      * Returns HTML code of a dialog box.
  543.      *
  544.      * @access public
  545.      * @return string 
  546.      * @since  0.1.0
  547.      */
  548.     function toHtml($renderer)
  549.     {
  550.         $css PEAR_PACKAGEUPDATE_DATA_DIR . 'ppu.css';
  551.         if (file_exists($css)) {
  552.             $styles file_get_contents($css);
  553.         else {
  554.             $styles '
  555. .widget-header {
  556.   white-space: nowrap;
  557.   background-color: #CCCCCC;
  558.   font-weight: bold;
  559. }
  560.  
  561. .widget-label {
  562.   white-space: nowrap;
  563.   vertical-align: top;
  564.   font-weight: bold;
  565. }';
  566.         }
  567.         $body $renderer->toHtml();
  568.  
  569.         $styles = <<<CSS
  570. <style type="text/css">
  571. <!--
  572. $styles
  573.  -->
  574. </style>
  575. CSS;
  576.  
  577.         $html = <<<HTML
  578. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  579. <html>
  580. <head>
  581. <title>PEAR_PackageUpdate Web Frontend</title>
  582. <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  583. $styles
  584. </head>
  585. <body>
  586. $body
  587. </body>
  588. </html>
  589. HTML;
  590.         return $html;
  591.     }
  592. }
  593. ?>

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