<?php
/**
* Web Application Component Toolkit
*
* @link http://www.phpwact.org/
*
* @author Wact Development Team
* @link http://www.phpwact.org/team
*
* @copyright Copyright 2006, Jeff Moore
* @license http://opensource.org/licenses/mit-license.php MIT
*/

// This class needs a PHP 5 tuneup

/**
* Base class for View components that output XML/HTML tags
*/
class Wact_View_Tag extends Wact_View_Partial {

    /**
    */
    var $tag;

    /**
    * Array of XML/HTML attributes
    * @var array
    */
    var $attributes = array();

    /**
    * Use an HTML Style close?
    * @var boolean
    */
    var $isClosingTagRequired = FALSE;

    /**
    */
    function __construct($tag, $attributes = array(), $isClosingTagRequired = FALSE) {
        $this->tag = $tag;
        $this->attributes = $attributes;
        $this->isClosingTagRequired = $isClosingTagRequired;
        parent::__construct();
    }

    /**
    * Returns the value of the ID attribute
    * @param string component class name
    * @return string
    */
    function getClientId() {
        return $this->getAttribute('id');
    }

    /**
    * returns the case-preserving, case-insensitive name of an attribute
    * @param string name of attribute
    * @return string canonical name of attribute
    */
    function getCanonicalAttributeName($attrib) {
        // quick check if they happen to use the same case.
        if (array_key_exists($attrib, $this->attributes)) {
            return $attrib;
        }

        // slow check
        foreach($this->attributes as $key => $value) {
            if (strcasecmp($attrib, $key) == 0) {
                return $key;
            }
        }

        return $attrib;
    }

    /**
    * Sets an attribute
    * @param string name of attribute
    * @param string value of attribute
    * @return void
    */
    function setAttribute($attrib, $value) {
        $attrib = $this->getCanonicalAttributeName($attrib);
        if (is_null($value)) {
            $this->attributes[$attrib] = $value;
        } else {
            $this->attributes[$attrib] = htmlspecialchars((string) $value, ENT_QUOTES);
        }
    }

    /**
    * Sets an attribute to an unfiltered value
    * @param string name of attribute
    * @param string value of attribute
    * @return void
    */
    function setAttributeUnfiltered($attrib, $value) {
        $attrib = $this->getCanonicalAttributeName($attrib);
        if (is_null($value)) {
            $this->attributes[$attrib] = $value;
        } else {
            $this->attributes[$attrib] = (string) $value;
        }
    }

    /**
    * Returns the value of an attribute, given it's name
    * @param string name of attribute
    * @return string value of attribute
    */
    function getAttribute($attrib) {
        $attrib = $this->getCanonicalAttributeName($attrib);
        if (isset($this->attributes[$attrib])) {
            return $this->attributes[$attrib];
        }
    }

    /**
    * Remove an attribute from the list
    * @param string name of attribute
    * @return void
    */
    function removeAttribute($attrib) {
        $attrib = $this->getCanonicalAttributeName($attrib);
        unset($this->attributes[$attrib]);
    }

    /**
    * Check to see whether a named attribute exists
    * @param string name of attribute
    * @return boolean
    */
    function hasAttribute($attrib) {
        $attrib = $this->getCanonicalAttributeName($attrib);
        return array_key_exists($attrib, $this->attributes);
    }

    /**
    */
    function hasContents() {
        return count($this->children) > 0;
    }

    /**
    * Outputs the open tag
    */
    function paintExtraAttributes() {
    }
    
    /**
    * Outputs the open tag
    */
    function paintOpen() {
        echo '<', $this->tag;
        foreach ($this->attributes as $name => $value) {
            echo ' ';
            echo $name;
            if ($value !== NULL) {
                echo '="', $value, '"';
            }
        }
        $this->paintExtraAttributes();
        if ( $this->isClosingTagRequired || $this->hasContents() ) {
            echo '>';
        } else {
            echo '/>';
       }
    }

    /**
    * Outputs the closing tag
    */
    function paintClose() {
       if ($this->isClosingTagRequired || $this->hasContents()) {
           echo '</', $this->tag ,'>';
       }
    }

    /**
    * @see Wact_View_Root.render
    */
    function render() {
        // Why are we not doing the pre-render event?
       $this->paintOpen();
       $this->paint();
       $this->paintClose();
    }

}

?>