home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / HTML / QuickForm / Controller.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  15.9 KB  |  519 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5.  * The class representing a Controller of MVC design pattern.
  6.  * 
  7.  * PHP versions 4 and 5
  8.  *
  9.  * LICENSE: This source file is subject to version 3.01 of the PHP license
  10.  * that is available through the world-wide-web at the following URI:
  11.  * http://www.php.net/license/3_01.txt If you did not receive a copy of
  12.  * the PHP License and are unable to obtain it through the web, please
  13.  * send a note to license@php.net so we can mail you a copy immediately.
  14.  *
  15.  * @category    HTML
  16.  * @package     HTML_QuickForm_Controller
  17.  * @author      Alexey Borzov <avb@php.net>
  18.  * @author      Bertrand Mansion <bmansion@mamasam.com>
  19.  * @copyright   2003-2007 The PHP Group
  20.  * @license     http://www.php.net/license/3_01.txt PHP License 3.01
  21.  * @version     CVS: $Id: Controller.php,v 1.13 2007/05/18 09:34:18 avb Exp $
  22.  * @link        http://pear.php.net/package/HTML_QuickForm_Controller
  23.  */
  24.  
  25. /**
  26.  * The class representing a page of a multipage form.
  27.  */
  28. require_once 'HTML/QuickForm/Page.php';
  29.  
  30. /**
  31.  * The class representing a Controller of MVC design pattern.
  32.  *
  33.  * This class keeps track of pages and (default) action handlers for the form,
  34.  * it manages keeping the form values in session, setting defaults and
  35.  * constants for the form as a whole and getting its submit values.
  36.  *
  37.  * Generally you don't need to subclass this.
  38.  *
  39.  * @category    HTML
  40.  * @package     HTML_QuickForm_Controller
  41.  * @author      Alexey Borzov <avb@php.net>
  42.  * @author      Bertrand Mansion <bmansion@mamasam.com>
  43.  * @version     Release: 1.0.8
  44.  */
  45. class HTML_QuickForm_Controller
  46. {
  47.    /**
  48.     * Contains the pages (HTML_QuickForm_Page objects) of the miultipage form
  49.     * @var array
  50.     */
  51.     var $_pages = array();
  52.  
  53.    /**
  54.     * Contains the mapping of actions to corresponding HTML_QuickForm_Action objects
  55.     * @var array
  56.     */
  57.     var $_actions = array();
  58.  
  59.    /**
  60.     * Name of the form, used to store the values in session
  61.     * @var string
  62.     */
  63.     var $_name;
  64.  
  65.    /**
  66.     * Whether the form is modal
  67.     * @var bool
  68.     */
  69.     var $_modal = true;
  70.  
  71.    /**
  72.     * The action extracted from HTTP request: array('page', 'action')
  73.     * @var array
  74.     */
  75.     var $_actionName = null;
  76.  
  77.    /**
  78.     * Class constructor.
  79.     *
  80.     * Sets the form name and modal/non-modal behaviuor. Different multipage
  81.     * forms should have different names, as they are used to store form
  82.     * values in session. Modal forms allow passing to the next page only when
  83.     * all of the previous pages are valid.
  84.     *
  85.     * @access public
  86.     * @param  string  form name
  87.     * @param  bool    whether the form is modal
  88.     */
  89.     function HTML_QuickForm_Controller($name, $modal = true)
  90.     {
  91.         $this->_name  = $name;
  92.         $this->_modal = $modal;
  93.     }
  94.  
  95.  
  96.    /**
  97.     * Returns a reference to a session variable containing the form-page
  98.     * values and pages' validation status.
  99.     *
  100.     * This is a "low-level" method, use exportValues() if you want just to
  101.     * get the form's values.
  102.     *
  103.     * @access public
  104.     * @param  bool      If true, then reset the container: clear all default, constant and submitted values
  105.     * @return array
  106.     */
  107.     function &container($reset = false)
  108.     {
  109.         $name = '_' . $this->_name . '_container';
  110.         if (!isset($_SESSION[$name]) || $reset) {
  111.             $_SESSION[$name] = array(
  112.                 'defaults'  => array(),
  113.                 'constants' => array(),
  114.                 'values'    => array(),
  115.                 'valid'     => array()
  116.             );
  117.         }
  118.         foreach (array_keys($this->_pages) as $pageName) {
  119.             if (!isset($_SESSION[$name]['values'][$pageName])) {
  120.                 $_SESSION[$name]['values'][$pageName] = array();
  121.                 $_SESSION[$name]['valid'][$pageName]  = null;
  122.             }
  123.         }
  124.         return $_SESSION[$name];
  125.     }
  126.  
  127.  
  128.    /**
  129.     * Processes the request.
  130.     *
  131.     * This finds the current page, the current action and passes the action
  132.     * to the page's handle() method.
  133.     *
  134.     * @access public
  135.     * @throws PEAR_Error
  136.     */
  137.     function run()
  138.     {
  139.         // the names of the action and page should be saved
  140.         list($page, $action) = $this->_actionName = $this->getActionName();
  141.         return $this->_pages[$page]->handle($action);
  142.     }
  143.  
  144.  
  145.    /**
  146.     * Registers a handler for a specific action.
  147.     *
  148.     * @access public
  149.     * @param  string                name of the action
  150.     * @param  HTML_QuickForm_Action the handler for the action
  151.     */
  152.     function addAction($actionName, &$action)
  153.     {
  154.         $this->_actions[$actionName] =& $action;
  155.     }
  156.  
  157.  
  158.    /**
  159.     * Adds a new page to the form
  160.     *
  161.     * @access public
  162.     * @param  HTML_QuickForm_Page
  163.     */
  164.     function addPage(&$page)
  165.     {
  166.         $page->controller =& $this;
  167.         $this->_pages[$page->getAttribute('id')] =& $page;
  168.     }
  169.  
  170.  
  171.    /**
  172.     * Returns a page
  173.     *
  174.     * @access public
  175.     * @param  string                Name of a page
  176.     * @return HTML_QuickForm_Page   A reference to the page
  177.     * @throws PEAR_Error
  178.     */
  179.     function &getPage($pageName)
  180.     {
  181.         if (!isset($this->_pages[$pageName])) {
  182.             return PEAR::raiseError('HTML_QuickForm_Controller: Unknown page "' . $pageName . '"');
  183.         }
  184.         return $this->_pages[$pageName];
  185.     }
  186.  
  187.  
  188.    /**
  189.     * Handles an action.
  190.     *
  191.     * This will be called if the page itself does not have a handler
  192.     * to a specific action. The method also loads and uses default handlers
  193.     * for common actions, if specific ones were not added.
  194.     *
  195.     * @access public
  196.     * @param  HTML_QuickForm_Page   The page that failed to handle the action
  197.     * @param  string                Name of the action
  198.     * @throws PEAR_Error
  199.     */
  200.     function handle(&$page, $actionName)
  201.     {
  202.         if (isset($this->_actions[$actionName])) {
  203.             return $this->_actions[$actionName]->perform($page, $actionName);
  204.         }
  205.         switch ($actionName) {
  206.             case 'next':
  207.             case 'back':
  208.             case 'submit':
  209.             case 'display':
  210.             case 'jump':
  211.                 include_once 'HTML/QuickForm/Action/' . ucfirst($actionName) . '.php';
  212.                 $className = 'HTML_QuickForm_Action_' . $actionName;
  213.                 $this->_actions[$actionName] =& new $className();
  214.                 return $this->_actions[$actionName]->perform($page, $actionName);
  215.                 break;
  216.             default:
  217.                 return PEAR::raiseError('HTML_QuickForm_Controller: Unhandled action "' . $actionName . '" in page "' . $page->getAttribute('id') . '"');
  218.         } // switch
  219.     }
  220.  
  221.  
  222.    /**
  223.     * Checks whether the form is modal.
  224.     *
  225.     * @access public
  226.     * @return bool
  227.     */
  228.     function isModal()
  229.     {
  230.         return $this->_modal;
  231.     }
  232.  
  233.  
  234.    /**
  235.     * Checks whether the pages of the controller are valid
  236.     *
  237.     * @access public
  238.     * @param  string    If set, check only the pages before (not including) that page
  239.     * @return bool
  240.     * @throws PEAR_Error
  241.     */
  242.     function isValid($pageName = null)
  243.     {
  244.         $data =& $this->container();
  245.         foreach (array_keys($this->_pages) as $key) {
  246.             if (isset($pageName) && $pageName == $key) {
  247.                 return true;
  248.             } elseif (!$data['valid'][$key]) {
  249.                 // We should handle the possible situation when the user has never
  250.                 // seen a page of a non-modal multipage form
  251.                 if (!$this->isModal() && null === $data['valid'][$key]) {
  252.                     $page =& $this->_pages[$key];
  253.                     // Fix for bug #8687: the unseen page was considered
  254.                     // submitted, so defaults for checkboxes and multiselects
  255.                     // were not used. Shouldn't break anything since this flag
  256.                     // will be reset right below in loadValues(). 
  257.                     $page->_flagSubmitted = false;
  258.                     // Use controller's defaults and constants, if present
  259.                     $this->applyDefaults($key);
  260.                     $page->isFormBuilt() or $page->BuildForm();
  261.                     // We use defaults and constants as if they were submitted
  262.                     $data['values'][$key] = $page->exportValues();
  263.                     $page->loadValues($data['values'][$key]);
  264.                     // Is the page now valid?
  265.                     if (PEAR::isError($valid = $page->validate())) {
  266.                         return $valid;
  267.                     }
  268.                     $data['valid'][$key] = $valid;
  269.                     if (true === $valid) {
  270.                         continue;
  271.                     }
  272.                 }
  273.                 return false;
  274.             }
  275.         }
  276.         return true;
  277.     }
  278.  
  279.  
  280.    /**
  281.     * Returns the name of the page before the given.
  282.     *
  283.     * @access public
  284.     * @param  string
  285.     * @return string
  286.     */
  287.     function getPrevName($pageName)
  288.     {
  289.         $prev = null;
  290.         foreach (array_keys($this->_pages) as $key) {
  291.             if ($key == $pageName) {
  292.                 return $prev;
  293.             }
  294.             $prev = $key;
  295.         }
  296.     }
  297.  
  298.  
  299.    /**
  300.     * Returns the name of the page after the given.
  301.     *
  302.     * @access public
  303.     * @param  string
  304.     * @return string
  305.     */
  306.     function getNextName($pageName)
  307.     {
  308.         $prev = null;
  309.         foreach (array_keys($this->_pages) as $key) {
  310.             if ($prev == $pageName) {
  311.                 return $key;
  312.             }
  313.             $prev = $key;
  314.         }
  315.         return null;
  316.     }
  317.  
  318.  
  319.    /**
  320.     * Finds the (first) invalid page
  321.     *
  322.     * @access public
  323.     * @return string  Name of an invalid page
  324.     */
  325.     function findInvalid()
  326.     {
  327.         $data =& $this->container();
  328.         foreach (array_keys($this->_pages) as $key) {
  329.             if (!$data['valid'][$key]) {
  330.                 return $key;
  331.             }
  332.         }
  333.         return null;
  334.     }
  335.  
  336.  
  337.    /**
  338.     * Extracts the names of the current page and the current action from
  339.     * HTTP request data.
  340.     *
  341.     * @access public
  342.     * @return array     first element is page name, second is action name
  343.     */
  344.     function getActionName()
  345.     {
  346.         if (is_array($this->_actionName)) {
  347.             return $this->_actionName;
  348.         }
  349.         $names = array_map('preg_quote', array_keys($this->_pages));
  350.         $regex = '/^_qf_(' . implode('|', $names) . ')_(.+?)(_x)?$/';
  351.         foreach (array_keys($_REQUEST) as $key) {
  352.             if (preg_match($regex, $key, $matches)) {
  353.                 return array($matches[1], $matches[2]);
  354.             }
  355.         }
  356.         if (isset($_REQUEST['_qf_default'])) {
  357.             $matches = explode(':', $_REQUEST['_qf_default'], 2);
  358.             if (isset($this->_pages[$matches[0]])) {
  359.                 return $matches;
  360.             }
  361.         }
  362.         reset($this->_pages);
  363.         return array(key($this->_pages), 'display');
  364.     }
  365.  
  366.  
  367.    /**
  368.     * Initializes default form values.
  369.     *
  370.     * @access public
  371.     * @param  array  default values
  372.     * @param  mixed  filter(s) to apply to default values
  373.     * @throws PEAR_Error
  374.     */
  375.     function setDefaults($defaultValues = null, $filter = null)
  376.     {
  377.         if (is_array($defaultValues)) {
  378.             $data =& $this->container();
  379.             return $this->_setDefaultsOrConstants($data['defaults'], $defaultValues, $filter);
  380.         }
  381.     }
  382.  
  383.  
  384.    /**
  385.     * Initializes constant form values.
  386.     * These values won't get overridden by POST or GET vars
  387.     *
  388.     * @access public
  389.     * @param  array  constant values
  390.     * @param  mixed  filter(s) to apply to constant values
  391.     * @throws PEAR_Error
  392.     */
  393.     function setConstants($constantValues = null, $filter = null)
  394.     {
  395.         if (is_array($constantValues)) {
  396.             $data =& $this->container();
  397.             return $this->_setDefaultsOrConstants($data['constants'], $constantValues, $filter);
  398.         }
  399.     }
  400.  
  401.  
  402.    /**
  403.     * Adds new values to defaults or constants array
  404.     *
  405.     * @access   private
  406.     * @param    array   array to add values to (either defaults or constants)
  407.     * @param    array   values to add
  408.     * @param    mixed   filters to apply to new values
  409.     * @throws   PEAR_Error
  410.     */
  411.     function _setDefaultsOrConstants(&$values, $newValues, $filter = null)
  412.     {
  413.         if (isset($filter)) {
  414.             if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
  415.                 foreach ($filter as $val) {
  416.                     if (!is_callable($val)) {
  417.                         return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm_Controller::_setDefaultsOrConstants()", 'HTML_QuickForm_Error', true);
  418.                     } else {
  419.                         $newValues = $this->_arrayMapRecursive($val, $newValues);
  420.                     }
  421.                 }
  422.             } elseif (!is_callable($filter)) {
  423.                 return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm_Controller::_setDefaultsOrConstants()", 'HTML_QuickForm_Error', true);
  424.             } else {
  425.                 $newValues = $this->_arrayMapRecursive($val, $newValues);
  426.             }
  427.         }
  428.         $values = HTML_QuickForm::arrayMerge($values, $newValues);
  429.     }
  430.  
  431.  
  432.    /**
  433.     * Recursively applies the callback function to the value
  434.     *
  435.     * @param    mixed   Callback function
  436.     * @param    mixed   Value to process
  437.     * @access   private
  438.     * @return   mixed   Processed values
  439.     */
  440.     function _arrayMapRecursive($callback, $value)
  441.     {
  442.         if (!is_array($value)) {
  443.             return call_user_func($callback, $value);
  444.         } else {
  445.             $map = array();
  446.             foreach ($value as $k => $v) {
  447.                 $map[$k] = $this->_arrayMapRecursive($callback, $v);
  448.             }
  449.             return $map;
  450.         }
  451.     }
  452.  
  453.  
  454.    /**
  455.     * Sets the default values for the given page
  456.     *
  457.     * @access public
  458.     * @param  string  Name of a page
  459.     */
  460.     function applyDefaults($pageName)
  461.     {
  462.         $data =& $this->container();
  463.         if (!empty($data['defaults'])) {
  464.             $this->_pages[$pageName]->setDefaults($data['defaults']);
  465.         }
  466.         if (!empty($data['constants'])) {
  467.             $this->_pages[$pageName]->setConstants($data['constants']);
  468.         }
  469.     }
  470.  
  471.  
  472.    /**
  473.     * Returns the form's values
  474.     *
  475.     * @access public
  476.     * @param  string    name of the page, if not set then returns values for all pages
  477.     * @return array
  478.     */
  479.     function exportValues($pageName = null)
  480.     {
  481.         $data   =& $this->container();
  482.         $values =  array();
  483.         if (isset($pageName)) {
  484.             $pages = array($pageName);
  485.         } else {
  486.             $pages = array_keys($data['values']);
  487.         }
  488.         foreach ($pages as $page) {
  489.             // skip elements representing actions
  490.             foreach ($data['values'][$page] as $key => $value) {
  491.                 if (0 !== strpos($key, '_qf_')) {
  492.                     if (isset($values[$key]) && is_array($value)) {
  493.                         $values[$key] = HTML_QuickForm::arrayMerge($values[$key], $value);
  494.                     } else {
  495.                         $values[$key] = $value;
  496.                     }
  497.                 }
  498.             }
  499.         }
  500.         return $values;
  501.     }
  502.  
  503.  
  504.    /**
  505.     * Returns the element's value
  506.     *
  507.     * @access public
  508.     * @param  string    name of the page
  509.     * @param  string    name of the element in the page
  510.     * @return mixed     value for the element
  511.     */
  512.     function exportValue($pageName, $elementName)
  513.     {
  514.         $data =& $this->container();
  515.         return isset($data['values'][$pageName][$elementName])? $data['values'][$pageName][$elementName]: null;
  516.     }
  517. }
  518. ?>
  519.