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

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