<?php

require_once 'common/Object.php';

/**
 * Xml file reader class.
 * 
 * This class provides basic methods for reading an XML file.
 * 
 * @author  $Author: pruna $
 * @package xml
 * @version $Revision: 1.3 $
 * @created 23-Dec-2005
 * @modified $Date: 2005/12/06 02:56:45 $
 */
class XmlReader extends Object {
    
    /**
     * @const 
     */
    const TYPE_STRING = 'string';
    
    /**
     * @const 
     */
    const TYPE_BOOLEAN = 'boolean';
    
    /**
     * Reads an attribute from a SimpleXml tag.
     * 
     * Besides reading the value, performs a cast(), and accepts alternative 
     * default values.
     * 
     * @param   object      $tag      SimpleXml object tag
     * @param   string      $name     Attribute's name to look for
     * @param   string      $type     Type name to cast to
     * @param   mixed       $default  Default value
     * @access  public
     * @return  mixed
     */
    public function readAttr($tag, $name, $type = self::TYPE_STRING, $default = null) {
        return isset($tag[$name]) ? 
            $this->cast((string)$tag[$name], $type) : $default;
    }
    
    /**
     * Reads a comma separated list from a string attribute from 
     * a SimpleXml tag.
     * 
     * It's like readAttr(), but only for comma separated lists based on
     *  strings. And adds basic string's preparation.
     * 
     * @param   object      $tag      SimpleXml object tag
     * @param   string      $name     Attribute's name to look for
     * @access  public
     * @return  array
     */
    public function readAttrList($tag, $name) {
        $list = array();
        $strList = $this->readAttr($tag, $name, self::TYPE_STRING, '');
        if (sizeof($strList)) {
            foreach (explode(',', $strList) as $method) {
                $list[] = $this->prepareString($method, array('trim', ));
            }
        }
        return $list;
    }
    
    /**
     * Reads a string attribute from a SimpleXml tag.
     * 
     * It's like readAttr(), but only for strings. And adds support for 
     * string's preparation.
     * 
     * @param   object      $tag      SimpleXml object tag
     * @param   string      $name     Attribute's name to look for
     * @param   mixed       $default  Default value
     * @param   string      $options  Methods to apply to string
     * @access  public
     * @return  string
     */
    public function readAttrString($tag, $name, $default = null, $options = null) {
        return $this->prepareString(
            $this->readAttr($tag, $name, self::TYPE_STRING, $default), $options);
    }
    
    //
    // This 4 auxiliary methods will be moved to some other place.
    // cast(), first(), getCleanupFunctions(), prepareString()
    //
    
    /**
     * Returns $value var casted to $type.
     * 
     * Casts a var to a basic php type.
     * It performs a special case when using booleans, transforming string 
     * 'false' to boolean false.
     * 
     * @param   mixed       $value  Value to cast
     * @param   string      $type   Type name to cast to
     * @access  protected
     * @return  mixed
     */
    protected function cast($value, $type = null) {
        $type = $this->prepareString($type, $this->getCleanupFunctions());
        if (($type === self::TYPE_BOOLEAN) and ('false' ===
            $this->prepareString($value, $this->getCleanupFunctions()))) {
            // hack: 'cause else string 'false' gets into boolean true
            return false;
        }
        settype($value, ($type ? $type : self::TYPE_STRING));
        return $value;
    }
    
    /**
     * Returns first not empty() value.
     * 
     * Empty depends on data type, and uses php's empty directive.
     * This method can be used with only one array param, containing any
     * quantity of values, or with up to 3 value params.
     * 
     * @param   mixed       $mixed  First value or array with values
     * @param   mixed       $var1   Second value
     * @param   mixed       $var2   Third value
     * @access  protected
     * @return  mixed
     */
    protected function first($mixed, $var1 = null, $var2 = null) {
        if (!is_array($mixed)) {
            $mixed = array($mixed, $var1, $var2);
        }
        foreach ($mixed as $value) {
            if (!empty($value)) {
                return $value;
            }
        }
    }
    
    /**
     * Returns array with php function's names to be used to 'cleanup' readed 
     * strings
     * 
     * @access  protected
     * @return  array
     */
    protected function getCleanupFunctions() {
        return array('trim', 'strtolower');
    }
    
    /**
     * Performs string preparation (or "cleanup") based on $options.
     * 
     * Applies functions specified in $options successively to $string.
     * Options must be function names that takes one string param and returns 
     * a string. Options can be specified as array or comma-separated list.
     * 
     * @param   string      $str       String to prepare
     * @param   string      $options   Methods to apply to string
     * @access  protected
     * @return  string
     */
    protected function prepareString($str, $options = null) {
        if (is_string($str) && !is_null($options)) {
            if (is_string($options)) {
                $options = explode(',', $options);
            }
            foreach ($options as $method) {
                $str = $method($str);
            }
        }
        return $str;
    }
    
}

?>