Location: PHPKode > projects > Ace Framework > Ace-master/Ace/Form/Element.php
<?php
/**
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the new BSD license.
 *
 * @package     Ace
 * @license     http://www.opensource.org/licenses/BSD-3-Clause New BSD license
 * @since       1.0
 */
abstract class Ace_Form_Element
{
    /**
     * If the element be rendered has XHTML
     * @var boolean 
     */
    protected static $xhtml = true;

    /**
     * Label format
     * @var string
     */
    public static $label_format = "%label% %required_suffix%";
    
    /**
     * Parent form
     * @var Ace_Form 
     */
    protected $parent = null;

    /**
     * Element required options
     * @var array 
     */
    protected $required_options = array();

    /**
     * Element attributes
     * @var array 
     */
    protected $attributes = array();

    /**
     * Element options
     * @var array 
     */
    protected $options = array();
    
    /**
     * Constructor.
     *
     * @param array $options
     * @param array $attributes
     */
    public function __construct($options = array(), $attributes = array())
    {
        $this->addOption('id_format', '%s');
        $this->addOption('is_hidden', false);
        $this->addOption('default', null);
        $this->addOption('label', null);
        
        $this->configure($options, $attributes);

        $current_option_keys = array_keys($this->getOptions());
        $option_keys = array_keys($options);

        // check option names
        if($diff = array_diff($option_keys, array_merge($current_option_keys, $this->required_options)))
        {
            throw new InvalidArgumentException(sprintf('%s does not support the following options : "%s".', get_class($this), implode('\', \'', $diff)));
        }

        // check required options
        if($diff = array_diff($this->required_options, array_merge($current_option_keys, $option_keys)))
        {
            throw new RuntimeException(sprintf('%s requires the following options : "%s".', get_class($this), implode('\', \'', $diff)));
        }

        $this->options = array_merge($this->options, $options);
        $this->attributes = array_merge($this->attributes, $attributes);
    }

    /**
     * Generate the label for the element
     *
     * @param string $name
     * @param string $label
     * @param Ace_Form_Validator $validator
     * @param string $required_label_suffix
     * @return string
     */
    public function generateLabel($name, $label, $validator, $required_label_suffix = null)
    {
        if(!is_null($required_label_suffix))
        {
            if($validator->getOption('required'))
            {

                $label = strtr(self::$label_format, array(
                    '%label%' => $label,
                    '%required_suffix%' => $required_label_suffix
                ));
            }
        }

        return $this->renderContentTag('label', $label, array('for' => $this->generateId($name)));
    }

    /**
     * Sets the parent form
     * 
     * @param Ace_Form $parent
     */
    public function setParent(Ace_Form $parent)
    {
        $this->parent = $parent;
    }

    /**
     * Gets the parent form
     * 
     * @return Ace_Form
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Sets the default value for the widget.
     *
     * @param string $value
     */
    public function setDefault($value)
    {
        $this->setOption('default', $value);
    }

    /**
     * Returns the default value for the widget.
     *
     * @return string
     */
    public function getDefault()
    {
        return $this->getOption('default');
    }

    /**
     * Sets the label for the widget.
     *
     * @param string $value
     */
    public function setLabel($value)
    {
        $this->setOption('label', $value);
    }

    /**
     * Returns the label for the widget.
     *
     * @return string
     */
    public function getLabel()
    {
        return $this->getOption('label');
    }

    /**
     * Sets the format for HTML id attributes.
     *
     * @param string $format
     */
    public function setIdFormat($format)
    {
        $this->setOption('id_format', $format);
    }

    /**
     * Gets the HTML format string for id attributes.
     *
     * @return string
     */
    public function getIdFormat()
    {
        return $this->getOption('id_format');
    }

    /**
     * Returns true if the widget is hidden.
     *
     * @return Boolean
     */
    public function isHidden()
    {
        return $this->getOption('is_hidden');
    }

    /**
     * Sets the hidden flag for the widget.
     *
     * @param bool $boolean
     */
    public function setHidden($boolean)
    {
        $this->setOption('is_hidden', (boolean) $boolean);
    }

    /**
     * Adds an HTML id attributes to the array of attributes if none is given and a name attribute exists.
     *
     * @param  array $attributes
     * @return array
     */
    protected function fixFormId($attributes)
    {
        if(!isset($attributes['id']) && isset($attributes['name']))
        {
            $attributes['id'] = $this->generateId($attributes['name'], isset($attributes['value']) ? $attributes['value'] : null);
        }

        return $attributes;
    }

    /**
     * Returns a formatted id based on the field name and optionally on the field value.
     *
     * @param  string $name
     * @param  string $value
     * @return string
     */
    public function generateId($name, $value = null)
    {
        if(false === $this->getOption('id_format'))
        {
            return null;
        }

        // check to see if we have an array variable for a field name
        if(strstr($name, '['))
        {
            $name = str_replace(array('[]', '][', '[', ']'), array((null !== $value ? '_' . $value : ''), '_', '_', ''), $name);
        }

        if(false !== strpos($this->getOption('id_format'), '%s'))
        {
            $name = sprintf($this->getOption('id_format'), $name);
        }

        // remove illegal characters
        $name = preg_replace(array('/^[^A-Za-z]+/', '/[^A-Za-z0-9\:_\.\-]/'), array('', '_'), $name);

        return $name;
    }

    /**
     * Generates a two chars range
     *
     * @param  integer $start
     * @param  integer $stop
     * @return array
     */
    static protected function generateTwoCharsRange($start, $stop)
    {
        $results = array();

        for($i = $start; $i <= $stop; $i++)
        {
            $results[$i] = sprintf('%02d', $i);
        }

        return $results;
    }

    /**
     * Configures the current widget.
     *
     * This method allows each widget to add options or HTML attributes
     * during widget creation.
     *
     * If some options and HTML attributes are given in the Ace_Form_Element constructor
     * they will take precedence over the options and HTML attributes you configure
     * in this method.
     *
     * @param array $options
     * @param array $attributes

     * @see __construct()
     */
    protected function configure($options = array(), $attributes = array()){}

    /**
     * Renders the widget as HTML.
     *
     * All subclasses must implement this method.
     *
     * @param  string $name
     * @param  mixed $value
     * @param  array $attributes
     * @param  array $errors
     * @return string
     */
    abstract public function render($name, $value = null, $attributes = array(), $errors = array());

    /**
     * Adds a required option.
     *
     * @param string $name

     */
    public function addRequiredOption($name)
    {
        $this->required_options[] = $name;
    }

    /**
     * Returns all required option names.
     *
     * @return array
     */
    public function getRequiredOptions()
    {
        return $this->required_options;
    }

    /**
     * Adds a new option value with a default value.
     *
     * @param string $name
     * @param mixed $value

     */
    public function addOption($name, $value = null)
    {
        $this->options[$name] = $value;
    }

    /**
     * Changes an option value.
     *
     * @param string $name
     * @param mixed $value
     * @return Ace_Form_Element
     */
    public function setOption($name, $value)
    {
        if(!in_array($name, array_merge(array_keys($this->options), $this->required_options)))
        {
            throw new InvalidArgumentException(sprintf('%s does not support the following option: \'%s\'.', get_class($this), $name));
        }

        $this->options[$name] = $value;
        return $this;
    }

    /**
     * Gets  an option value.
     *
     * @param string $name
     * @return mixed
     */
    public function getOption($name)
    {
        return isset($this->options[$name]) ? $this->options[$name] : null;
    }

    /**
     * Remove an option
     * 
     * @param string $name
     */
    public function removeOption($name)
    {
        if(array_key_exists($name, $this->options))
        {
            unset($this->options[$name]);
        }
    }

    /**
     * Returns true if the option exists.
     *
     * @param  string $name
     * @return bool
     */
    public function hasOption($name)
    {
        return array_key_exists($name, $this->options);
    }

    /**
     * Gets  all options.
     *
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Sets the options.
     *
     * @param array $options
     */
    public function setOptions($options)
    {
        $this->options = $options;
    }

    /**
     * Returns the default HTML attributes.
     *
     * @return array
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * Sets a default HTML attribute.
     *
     * @param string $name
     * @param string $value
     */
    public function setAttribute($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    /**
     * Returns the HTML attribute value for a given attribute name.
     *
     * @param  string $name
     * @return string
     */
    public function getAttribute($name)
    {
        return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
    }

    /**
     * Sets the HTML attributes.
     *
     * @param array $attributes
     */
    public function setAttributes($attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * Sets the XHTML generation flag.
     *
     * @param bool $boolean
     */
    static public function setXhtml($boolean)
    {
        self::$xhtml = (boolean) $boolean;
    }

    /**
     * Returns whether to generate XHTML tags or not.
     *
     * @return bool
     */
    static public function isXhtml()
    {
        return self::$xhtml;
    }

    /**
     * Renders a HTML tag.
     *
     * @param  string $tag
     * @param  array  $attributes
     * @return string
     */
    public function renderTag($tag, $attributes = array())
    {
        if(empty($tag))
        {
            return '';
        }

        $attributes = $this->fixFormId($attributes);

        return sprintf('<%s%s%s', $tag, $this->attributesToHtml($attributes), self::$xhtml ? ' />' : (strtolower($tag) == 'input' ? '>' : sprintf('></%s>', $tag)));
    }

    /**
     * Renders a HTML content tag.
     *
     * @param  string $tag
     * @param  string $content
     * @param  array  $attributes
     * @return string
     */
    public function renderContentTag($tag, $content = null, $attributes = array())
    {
        $attributes = $this->fixFormId($attributes);
            
        if(empty($tag))
        {
            return '';
        }

        return sprintf('<%s%s>%s</%s>', $tag, $this->attributesToHtml($attributes), $content, $tag);
    }

    /**
     * Escapes a string.
     *
     * @param  string $value
     * @return string
     */
    static public function escapeOnce($value)
    {
        return self::fixDoubleEscape(htmlspecialchars((string) $value, ENT_QUOTES));
    }

    /**
     * Fixes double escaped strings.
     *
     * @param  string $escaped string to fix
     * @return string single escaped string
     */
    static public function fixDoubleEscape($escaped)
    {
        return preg_replace('/&amp;([a-z]+|(#\d+)|(#x[\da-f]+));/i', '&$1;', $escaped);
    }

    /**
     * Converts an array of attributes to its HTML representation.
     *
     * @param  array $attributes
     * @return string
     */
    public function attributesToHtml($attributes)
    {
        return implode('', array_map(array($this, 'attributesToHtmlCallback'), array_keys($attributes), array_values($attributes)));
    }

    /**
     * Prepares an attribute key and value for HTML representation.
     *
     * @param  string $k
     * @param  string $v
     * @return string
     */
    protected function attributesToHtmlCallback($k, $v)
    {
        return false === $v || null === $v || ('' === $v && 'value' != $k) ? '' : sprintf(' %s="%s"', $k, self::escapeOnce($v));
    }
}
Return current item: Ace Framework