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 / QuickForm2 / Node.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  14.6 KB  |  505 lines

  1. <?php
  2. /**
  3.  * Base class for all HTML_QuickForm2 elements
  4.  *
  5.  * PHP version 5
  6.  *
  7.  * LICENSE:
  8.  *
  9.  * Copyright (c) 2006, 2007, Alexey Borzov <avb@php.net>,
  10.  *                           Bertrand Mansion <golgote@mamasam.com>
  11.  * All rights reserved.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  *
  17.  *    * Redistributions of source code must retain the above copyright
  18.  *      notice, this list of conditions and the following disclaimer.
  19.  *    * Redistributions in binary form must reproduce the above copyright
  20.  *      notice, this list of conditions and the following disclaimer in the
  21.  *      documentation and/or other materials provided with the distribution.
  22.  *    * The names of the authors may not be used to endorse or promote products
  23.  *      derived from this software without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  26.  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  27.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  29.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  30.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  31.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  32.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  33.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  34.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  35.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36.  *
  37.  * @category   HTML
  38.  * @package    HTML_QuickForm2
  39.  * @author     Alexey Borzov <avb@php.net>
  40.  * @author     Bertrand Mansion <golgote@mamasam.com>
  41.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  42.  * @version    CVS: $Id: Node.php,v 1.10 2007/07/27 08:28:28 avb Exp $
  43.  * @link       http://pear.php.net/package/HTML_QuickForm2
  44.  */
  45.  
  46. /**
  47.  * HTML_Common2 - base class for HTML elements
  48.  */
  49. require_once 'HTML/Common2.php';
  50.  
  51. /**
  52.  * Exception classes for HTML_QuickForm2
  53.  */
  54. require_once 'HTML/QuickForm2/Exception.php';
  55.  
  56. /**
  57.  * Static factory class for QuickForm2 elements
  58.  */
  59. require_once 'HTML/QuickForm2/Factory.php';
  60.  
  61. /**
  62.  * Abstract base class for all QuickForm2 Elements and Containers
  63.  *
  64.  * This class is mostly here to define the interface that should be implemented
  65.  * by the subclasses. It also contains static methods handling generation
  66.  * of unique ids for elements which do not have ids explicitly set.
  67.  *
  68.  * @category   HTML
  69.  * @package    HTML_QuickForm2
  70.  * @author     Alexey Borzov <avb@php.net>
  71.  * @author     Bertrand Mansion <golgote@mamasam.com>
  72.  * @version    Release: 0.2.0
  73.  */
  74. abstract class HTML_QuickForm2_Node extends HTML_Common2
  75. {
  76.    /**
  77.     * Array containing the parts of element ids
  78.     * @var array
  79.     */
  80.     protected static $ids = array();
  81.  
  82.    /**
  83.     * Element's "frozen" status
  84.     * @var boolean
  85.     */
  86.     protected $frozen = false;
  87.  
  88.    /**
  89.     * Whether element's value should persist when element is frozen
  90.     * @var boolean
  91.     */
  92.     protected $persistent = false;
  93.  
  94.    /**
  95.     * Element containing current
  96.     * @var HTML_QuickForm2_Container
  97.     */
  98.     protected $container = null;
  99.  
  100.    /**
  101.     * Contains options and data used for the element creation
  102.     * @var  array
  103.     */
  104.     protected $data = null;
  105.  
  106.    /**
  107.     * Validation rules for element
  108.     * @var  array
  109.     */
  110.     protected $rules = array();
  111.  
  112.    /**
  113.     * Error message (usually set via Rule if validation fails)
  114.     * @var  string
  115.     */
  116.     protected $error = null;
  117.  
  118.    /**
  119.     * Class constructor
  120.     *
  121.     * @param    string  Element name
  122.     * @param    mixed   Attributes (either a string or an array)
  123.     * @param    array   Element data (label, options and data used for element creation)
  124.     */
  125.     public function __construct($name = null, $attributes = null, array $data = array())
  126.     {
  127.         parent::__construct($attributes);
  128.         $this->setName($name);
  129.         // Autogenerating the id if not set on previous steps
  130.         if ('' == $this->getId()) {
  131.             $this->setId();
  132.         }
  133.         $this->data = $data;
  134.     }
  135.  
  136.  
  137.    /**
  138.     * Generates an id for the element
  139.     *
  140.     * Called when an element is created without explicitly given id
  141.     *
  142.     * @param  string   Element name
  143.     * @return string   The generated element id
  144.     */
  145.     protected static function generateId($elementName)
  146.     {
  147.         $tokens    =  strlen($elementName)?
  148.                       explode('[', str_replace(']', '', $elementName)):
  149.                       array('qfauto');
  150.         $container =& self::$ids;
  151.         $id        =  '';
  152.  
  153.         do {
  154.             $token = array_shift($tokens);
  155.             // Handle the 'array[]' names
  156.             if ('' === $token) {
  157.                 if (empty($container)) {
  158.                     $token = 0;
  159.                 } else {
  160.                     $keys  = array_keys($container);
  161.                     $token = end($keys);
  162.                     while (isset($container[$token])) {
  163.                         $token++;
  164.                     }
  165.                 }
  166.             }
  167.             $id .= '-' . $token;
  168.             if (!isset($container[$token])) {
  169.                 $container[$token] = array();
  170.             }
  171.             $container =& $container[$token];
  172.         } while (!empty($tokens));
  173.  
  174.         // Append the final index
  175.         $index = count($keys = array_keys($container))? end($keys): 0;
  176.         while (isset($container[$index])) {
  177.             $index++;
  178.         }
  179.         $container[$index] = array();
  180.         $id .= '-' . $index;
  181.  
  182.         return substr($id, 1);
  183.     }
  184.  
  185.  
  186.    /**
  187.     * Stores the explicitly given id to prevent duplicate id generation
  188.     *
  189.     * @param    string  Element id
  190.     */
  191.     protected static function storeId($id)
  192.     {
  193.         $tokens    =  explode('-', $id);
  194.         $container =& self::$ids;
  195.  
  196.         do {
  197.             $token = array_shift($tokens);
  198.             if (!isset($container[$token])) {
  199.                 $container[$token] = array();
  200.             }
  201.             $container =& $container[$token];
  202.         } while (!empty($tokens));
  203.     }
  204.  
  205.  
  206.    /**
  207.     * Returns the element's type
  208.     *
  209.     * @return   string
  210.     */
  211.     abstract public function getType();
  212.  
  213.  
  214.    /**
  215.     * Returns the element's name
  216.     *
  217.     * @return   string
  218.     */
  219.     abstract public function getName();
  220.  
  221.  
  222.    /**
  223.     * Sets the element's name
  224.     *
  225.     * @param    string
  226.     * @return   HTML_QuickForm2_Node
  227.     */
  228.     abstract public function setName($name);
  229.  
  230.  
  231.    /**
  232.     * Returns the element's id
  233.     *
  234.     * @return   string
  235.     */
  236.     abstract public function getId();
  237.  
  238.  
  239.    /**
  240.     * Sets the elements id
  241.     *
  242.     * Please note that elements should always have an id in QuickForm2 and
  243.     * therefore it will not be possible to remove the element's id or set it to
  244.     * an empty value. If id is not explicitly given, it will be autogenerated.
  245.     *
  246.     * @param    string  Element's id, will be autogenerated if not given
  247.     * @return   HTML_QuickForm2_Node
  248.     */
  249.     abstract public function setId($id = null);
  250.  
  251.  
  252.    /**
  253.     * Returns the element's value
  254.     *
  255.     * @return   mixed
  256.     */
  257.     abstract public function getValue();
  258.  
  259.  
  260.    /**
  261.     * Sets the element's value
  262.     *
  263.     * @param    mixed
  264.     * @return   HTML_QuickForm2_Node
  265.     */
  266.     abstract public function setValue($value);
  267.  
  268.  
  269.    /**
  270.     * Returns the element's label(s)
  271.     *
  272.     * @return   string|array
  273.     */
  274.     public function getLabel()
  275.     {
  276.         if (isset($this->data['label'])) {
  277.             return $this->data['label'];
  278.         }
  279.         return null;
  280.     }
  281.  
  282.  
  283.    /**
  284.     * Sets the element's label(s)
  285.     *
  286.     * @param    string|array    Label for the element (may be an array of labels)
  287.     * @return   HTML_QuickForm2_Node
  288.     */
  289.     public function setLabel($label)
  290.     {
  291.         $this->data['label'] = $label;
  292.         return $this;
  293.     }
  294.  
  295.  
  296.    /**
  297.     * Changes the element's frozen status
  298.     *
  299.     * @param    bool    Whether the element should be frozen or editable. If
  300.     *                   omitted, the method will not change the frozen status,
  301.     *                   just return its current value
  302.     * @return   bool    Old value of element's frozen status
  303.     */
  304.     public function toggleFrozen($freeze = null)
  305.     {
  306.         $old = $this->frozen;
  307.         if (null !== $freeze) {
  308.             $this->frozen = (bool)$freeze;
  309.         }
  310.         return $old;
  311.     }
  312.  
  313.  
  314.    /**
  315.     * Changes the element's persistent freeze behaviour
  316.     *
  317.     * If persistent freeze is on, the element's value will be kept (and
  318.     * submitted) in a hidden field when the element is frozen.
  319.     *
  320.     * @param    bool    New value for "persistent freeze". If omitted, the
  321.     *                   method will not set anything, just return the current
  322.     *                   value of the flag.
  323.     * @return   bool    Old value of "persistent freeze" flag
  324.     */
  325.     public function persistentFreeze($persistent = null)
  326.     {
  327.         $old = $this->persistent;
  328.         if (null !== $persistent) {
  329.             $this->persistent = (bool)$persistent;
  330.         }
  331.         return $old;
  332.     }
  333.  
  334.  
  335.    /**
  336.     * Adds the link to the element containing current
  337.     *
  338.     * @param    HTML_QuickForm2_Container  Element containing the current one,
  339.     *                                      null if the link should really be
  340.     *                                      removed (if removing from container)
  341.     * @throws   HTML_QuickForm2_InvalidArgumentException   If trying to set a
  342.     *                               child of an element as its container
  343.     */
  344.     protected function setContainer(HTML_QuickForm2_Container $container = null)
  345.     {
  346.         if (null !== $container) {
  347.             $check = $container;
  348.             do {
  349.                 if ($this === $check) {
  350.                     throw new HTML_QuickForm2_InvalidArgumentException(
  351.                         'Cannot set an element or its child as its own container'
  352.                     );
  353.                 }
  354.             } while ($check = $check->getContainer());
  355.             if (null !== $this->container && $container !== $this->container) {
  356.                 $this->container->removeChild($this);
  357.             }
  358.         }
  359.         $this->container = $container;
  360.         if (null !== $container) {
  361.             $this->updateValue();
  362.         }
  363.     }
  364.  
  365.  
  366.    /**
  367.     * Returns the element containing current
  368.     *
  369.     * @return   HTML_QuickForm2_Container|null
  370.     */
  371.     public function getContainer()
  372.     {
  373.         return $this->container;
  374.     }
  375.  
  376.    /**
  377.     * Returns the data sources for this element
  378.     *
  379.     * @return   array
  380.     */
  381.     protected function getDataSources()
  382.     {
  383.         if (empty($this->container)) {
  384.             return array();
  385.         } else {
  386.             return $this->container->getDataSources();
  387.         }
  388.     }
  389.  
  390.    /**
  391.     * Called when the element needs to update its value from form's data sources
  392.     */
  393.     abstract protected function updateValue();
  394.  
  395.    /**
  396.     * Adds a validation rule
  397.     *
  398.     * @param    HTML_QuickForm2_Rule|string     Validation rule or rule type
  399.     * @param    string                          Message to display if validation fails
  400.     * @param    mixed                           Additional data for the rule
  401.     * @return   HTML_QuickForm2_Rule            The added rule
  402.     * @throws   HTML_QuickForm2_InvalidArgumentException    if $rule is of a
  403.     *               wrong type or rule name isn't registered with Factory
  404.     * @throws   HTML_QuickForm2_NotFoundException   if class for a given rule
  405.     *               name cannot be found
  406.     */
  407.     public function addRule($rule, $message = '', $options = null)
  408.     {
  409.         if ($rule instanceof HTML_QuickForm2_Rule) {
  410.             $rule->setOwner($this);
  411.         } elseif (is_string($rule)) {
  412.             $rule = HTML_QuickForm2_Factory::createRule($rule, $this, $message, $options);
  413.         } else {
  414.             throw new HTML_QuickForm2_InvalidArgumentException(
  415.                 'addRule() expects either a rule type or ' .
  416.                 'a HTML_QuickForm2_Rule instance'
  417.             );
  418.         }
  419.  
  420.         $this->rules[] = $rule;
  421.         return $rule;
  422.     }
  423.  
  424.  
  425.    /**
  426.     * Creates a validation rule
  427.     *
  428.     * This method is mostly useful when when chaining several rules together
  429.     * via {@link HTML_QuickForm2_Rule::and_()} and {@link HTML_QuickForm2_Rule::or_()}
  430.     * methods:
  431.     * <code>
  432.     * $first->addRule('nonempty', 'Fill in either first or second field')
  433.     *     ->or_($second->createRule('nonempty'));
  434.     * </code>
  435.     *
  436.     * @param    string                  Rule type
  437.     * @param    string                  Message to display if validation fails
  438.     * @param    mixed                   Additional data for the rule
  439.     * @return   HTML_QuickForm2_Rule    The created rule
  440.     * @throws   HTML_QuickForm2_InvalidArgumentException If rule type is unknown
  441.     * @throws   HTML_QuickForm2_NotFoundException        If class for the rule
  442.     *           can't be found and/or loaded from file
  443.     */
  444.     public function createRule($type, $message = '', $options = null)
  445.     {
  446.         return HTML_QuickForm2_Factory::createRule($type, $this, $message, $options);
  447.     }
  448.  
  449.  
  450.    /**
  451.     * Checks whether an element is required
  452.     *
  453.     * @return   boolean
  454.     */
  455.     public function isRequired()
  456.     {
  457.         foreach ($this->rules as $rule) {
  458.             if ($rule instanceof HTML_QuickForm2_Rule_Required) {
  459.                 return true;
  460.             }
  461.         }
  462.         return false;
  463.     }
  464.  
  465.  
  466.    /**
  467.     * Performs the server-side validation
  468.     *
  469.     * @return   boolean     Whether the element is valid
  470.     */
  471.     protected function validate()
  472.     {
  473.         foreach ($this->rules as $rule) {
  474.             if (strlen($this->error)) {
  475.                 break;
  476.             }
  477.             $rule->validate();
  478.         }
  479.         return !strlen($this->error);
  480.     }
  481.  
  482.    /**
  483.     * Sets the error message to the element
  484.     *
  485.     * @param    string
  486.     * @return   HTML_QuickForm2_Node
  487.     */
  488.     public function setError($error = null)
  489.     {
  490.         $this->error = (string)$error;
  491.         return $this;
  492.     }
  493.  
  494.    /**
  495.     * Returns the error message for the element
  496.     *
  497.     * @return   string
  498.     */
  499.     public function getError()
  500.     {
  501.         return $this->error;
  502.     }
  503. }
  504. ?>
  505.