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

Source for file Controller.php

Documentation is available at Controller.php

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

Documentation generated on Tue, 22 Jul 2008 08:00:05 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.