/libs/HTML/Common2.php
PHP | 488 lines | 378 code | 8 blank | 102 comment | 8 complexity | a9c9b708cd3f2691192171bb78177db3 MD5 | raw file
- <?php
- /**
- * HTML_Common2: port of HTML_Common package to PHP5
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * Copyright (c) 2004-2009, Alexey Borzov <avb@php.net>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * 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.
- *
- * @category HTML
- * @package HTML_Common2
- * @author Alexey Borzov <avb@php.net>
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Common2.php 295050 2010-02-14 05:01:19Z clockwerx $
- * @link http://pear.php.net/package/HTML_Common2
- */
- /**
- * Base class for HTML classes
- *
- * Implements methods for working with HTML attributes, parsing and generating
- * attribute strings. Port of HTML_Common class for PHP4 originally written by
- * Adam Daniel with contributions from numerous other developers.
- *
- * @category HTML
- * @package HTML_Common2
- * @author Alexey Borzov <avb@php.net>
- * @version Release: @package_version@
- */
- abstract class HTML_Common2
- {
- /**
- * Associative array of attributes
- * @var array
- */
- protected $attributes = array();
- /**
- * List of attribites changes to which will be announced via onAttributeChange()
- * method rather than performed by HTML_Common2 class itself
- * @var array
- * @see onAttributeChange()
- */
- protected $watchedAttributes = array();
- /**
- * Indentation level of the element
- * @var int
- */
- private $_indentLevel = 0;
- /**
- * Comment associated with the element
- * @var string
- */
- private $_comment = null;
- /**
- * Global options for all elements generated by subclasses of HTML_Common2
- *
- * Preset options are
- * - 'charset': charset parameter used in htmlspecialchars() calls,
- * defaults to 'ISO-8859-1'
- * - 'indent': string used to indent HTML elements, defaults to "\11"
- * - 'linebreak': string used to indicate linebreak, defaults to "\12"
- *
- * @var array
- */
- private static $_options = array(
- 'charset' => 'ISO-8859-1',
- 'indent' => "\11",
- 'linebreak' => "\12"
- );
- /**
- * Sets global option(s)
- *
- * @param string|array Option name or array ('option name' => 'option value')
- * @param mixed Option value, if first argument is not an array
- */
- public static function setOption($nameOrOptions, $value = null)
- {
- if (is_array($nameOrOptions)) {
- foreach ($nameOrOptions as $k => $v) {
- self::setOption($k, $v);
- }
- } else {
- $linebreaks = array('win' => "\15\12", 'unix' => "\12", 'mac' => "\15");
- if ('linebreak' == $nameOrOptions && isset($linebreaks[$value])) {
- $value = $linebreaks[$value];
- }
- self::$_options[$nameOrOptions] = $value;
- }
- }
- /**
- * Returns global option(s)
- *
- * @param string Option name
- * @return mixed Option value, null if option does not exist,
- * array of all options if $name is not given
- */
- public static function getOption($name = null)
- {
- if (null === $name) {
- return self::$_options;
- } else {
- return isset(self::$_options[$name])? self::$_options[$name]: null;
- }
- }
- /**
- * Parses the HTML attributes given as string
- *
- * @param string HTML attribute string
- * @return array An associative aray of attributes
- */
- protected static function parseAttributes($attrString)
- {
- $attributes = array();
- if (preg_match_all(
- "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" .
- "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/",
- $attrString,
- $regs
- )) {
- for ($i = 0; $i < count($regs[1]); $i++) {
- $name = trim($regs[1][$i]);
- $check = trim($regs[0][$i]);
- $value = trim($regs[7][$i]);
- if ($name == $check) {
- $attributes[strtolower($name)] = strtolower($name);
- } else {
- if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
- $value = substr($value, 1, -1);
- }
- $attributes[strtolower($name)] = $value;
- }
- }
- }
- return $attributes;
- }
- /**
- * Creates a valid attribute array from either a string or an array
- *
- * @param mixed Array of attributes or HTML attribute string
- * @return array An associative aray of attributes
- */
- protected static function prepareAttributes($attributes)
- {
- $prepared = array();
- if (is_string($attributes)) {
- return self::parseAttributes($attributes);
- } elseif (is_array($attributes)) {
- foreach ($attributes as $key => $value) {
- if (is_int($key)) {
- $key = strtolower($value);
- $prepared[$key] = $key;
- } else {
- $prepared[strtolower($key)] = (string)$value;
- }
- }
- }
- return $prepared;
- }
- /**
- * Removes an attribute from an attribute array
- *
- * @param array Attribute array
- * @param string Name of attribute to remove
- */
- protected static function removeAttributeArray(&$attributes, $name)
- {
- unset($attributes[strtolower($name)]);
- }
- /**
- * Creates HTML attribute string from array
- *
- * @param array Attribute array
- * @return string Attribute string
- */
- protected static function getAttributesString($attributes)
- {
- $str = '';
- if (is_array($attributes)) {
- $charset = self::getOption('charset');
- foreach ($attributes as $key => $value) {
- $str .= ' ' . $key . '="' . htmlspecialchars($value, ENT_QUOTES, $charset) . '"';
- }
- }
- return $str;
- }
- /**
- * Class constructor, sets default attributes
- *
- * @param mixed Array of attribute 'name' => 'value' pairs or HTML attribute string
- */
- public function __construct($attributes = null)
- {
- $this->mergeAttributes($attributes);
- }
- /**
- * Sets the value of the attribute
- *
- * @param string Attribute name
- * @param string Attribute value (will be set to $name if omitted)
- * @return HTML_Common2
- */
- public function setAttribute($name, $value = null)
- {
- $name = strtolower($name);
- if (is_null($value)) {
- $value = $name;
- }
- if (in_array($name, $this->watchedAttributes)) {
- $this->onAttributeChange($name, $value);
- } else {
- $this->attributes[$name] = (string)$value;
- }
- return $this;
- }
- /**
- * Returns the value of an attribute
- *
- * @param string Attribute name
- * @return string Attribute value, null if attribute does not exist
- */
- public function getAttribute($name)
- {
- $name = strtolower($name);
- return isset($this->attributes[$name])? $this->attributes[$name]: null;
- }
- /**
- * Sets the attributes
- *
- * @param mixed Array of attribute 'name' => 'value' pairs or HTML attribute string
- * @return HTML_Common2
- */
- public function setAttributes($attributes)
- {
- $attributes = self::prepareAttributes($attributes);
- $watched = array();
- foreach ($this->watchedAttributes as $watchedKey) {
- if (isset($attributes[$watchedKey])) {
- $this->setAttribute($watchedKey, $attributes[$watchedKey]);
- unset($attributes[$watchedKey]);
- } else {
- $this->removeAttribute($watchedKey);
- }
- if (isset($this->attributes[$watchedKey])) {
- $watched[$watchedKey] = $this->attributes[$watchedKey];
- }
- }
- $this->attributes = array_merge($watched, $attributes);
- return $this;
- }
- /**
- * Returns the attribute array or string
- *
- * @param bool Whether to return attributes as string
- * @return mixed Either an array or string of attributes
- */
- public function getAttributes($asString = false)
- {
- if ($asString) {
- return self::getAttributesString($this->attributes);
- } else {
- return $this->attributes;
- }
- }
- /**
- * Merges the existing attributes with the new ones
- *
- * @param mixed Array of attribute 'name' => 'value' pairs or HTML attribute string
- * @return HTML_Common2
- */
- public function mergeAttributes($attributes)
- {
- $attributes = self::prepareAttributes($attributes);
- foreach ($this->watchedAttributes as $watchedKey) {
- if (isset($attributes[$watchedKey])) {
- $this->onAttributeChange($watchedKey, $attributes[$watchedKey]);
- unset($attributes[$watchedKey]);
- }
- }
- $this->attributes = array_merge($this->attributes, $attributes);
- return $this;
- }
- /**
- * Removes an attribute
- *
- * @param string Name of attribute to remove
- * @return HTML_Common2
- */
- public function removeAttribute($attribute)
- {
- if (in_array(strtolower($attribute), $this->watchedAttributes)) {
- $this->onAttributeChange(strtolower($attribute), null);
- } else {
- self::removeAttributeArray($this->attributes, $attribute);
- }
- return $this;
- }
- /**
- * Sets the indentation level
- *
- * @param int
- * @return HTML_Common2
- */
- public function setIndentLevel($level)
- {
- $level = intval($level);
- if (0 <= $level) {
- $this->_indentLevel = $level;
- }
- return $this;
- }
- /**
- * Gets the indentation level
- *
- * @return int
- */
- public function getIndentLevel()
- {
- return $this->_indentLevel;
- }
- /**
- * Returns the string to indent the element
- *
- * @return string
- */
- protected function getIndent()
- {
- return str_repeat(self::getOption('indent'), $this->getIndentLevel());
- }
- /**
- * Sets the comment for the element
- *
- * @param string
- * @return HTML_Common2
- */
- public function setComment($comment)
- {
- $this->_comment = $comment;
- return $this;
- }
- /**
- * Returns the comment associated with the element
- *
- * @return string
- */
- public function getComment()
- {
- return $this->_comment;
- }
- /**
- * Checks whether the element has given CSS class
- *
- * @param string Class name
- * @return bool
- */
- public function hasClass($class)
- {
- $regex = '/(^|\s)' . preg_quote($class, '/') . '(\s|$)/';
- return (bool)preg_match($regex, $this->getAttribute('class'));
- }
- /**
- * Adds the given CSS class(es) to the element
- *
- * @param string|array Class name, multiple class names separated by
- * whitespace, array of class names
- * @return HTML_Common2
- */
- public function addClass($class)
- {
- if (!is_array($class)) {
- $class = preg_split('/\s+/', $class, null, PREG_SPLIT_NO_EMPTY);
- }
- $curClass = preg_split('/\s+/', $this->getAttribute('class'),
- null, PREG_SPLIT_NO_EMPTY);
- foreach ($class as $c) {
- if (!in_array($c, $curClass)) {
- $curClass[] = $c;
- }
- }
- $this->setAttribute('class', implode(' ', $curClass));
- return $this;
- }
- /**
- * Removes the given CSS class(es) from the element
- *
- * @param string|array Class name, multiple class names separated by
- * whitespace, array of class names
- * @return HTML_Common2
- */
- public function removeClass($class)
- {
- if (!is_array($class)) {
- $class = preg_split('/\s+/', $class, null, PREG_SPLIT_NO_EMPTY);
- }
- $curClass = array_diff(
- preg_split('/\s+/', $this->getAttribute('class'),
- null, PREG_SPLIT_NO_EMPTY),
- $class
- );
- if (0 == count($curClass)) {
- $this->removeAttribute('class');
- } else {
- $this->setAttribute('class', implode(' ', $curClass));
- }
- return $this;
- }
- /**
- * Returns the HTML representation of the element
- *
- * This magic method allows using the instances of HTML_Common2 in string
- * contexts
- *
- * @return string
- */
- abstract public function __toString();
- /**
- * Called if trying to change an attribute with name in $watchedAttributes
- *
- * This method is called for each attribute whose name is in the
- * $watchedAttributes array and which is being changed by setAttribute(),
- * setAttributes() or mergeAttributes() or removed via removeAttribute().
- * Note that the operation for the attribute is not carried on after calling
- * this method, it is the responsibility of this method to change or remove
- * (or not) the attribute.
- *
- * @param string Attribute name
- * @param string Attribute value, null if attribute is being removed
- */
- protected function onAttributeChange($name, $value = null)
- {
- }
- }
- ?>