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

Documentation generated on Thu, 12 Jun 2008 13:09:39 -0500 by phpDocumentor 1.4.1