home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / Controller.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  12.9 KB  |  442 lines

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