<?php
/**
 * YANA library
 *
 * @package yana
 * @licence http://creativecommons.org/licenses/by-nc-sa/2.5/
 *
 * @ignore
 */

/**
 * «utility» class Layout
 *
 * This is a global namespace for layout specific functions.
 * These functions implement recursive replacement of tokens.
 * This functionality is used for registry-files (sml/config)
 * of the framework.
 *
 * @static
 * @access      public
 * @package     yana
 * @subpackage  core
 *
 * @ignore
 */
class Layout
{

    /**
     * replace each token within a text/template
     *
     * NOTE: this method is case-insensitive
     *
     * This means if your reference array contains
     * keys with the same name but different writing,
     * e.g. 'a' and 'A', the keys that last of the both
     * keys is used and the other is ignored.
     *
     * Also note that token that refer to a non-existing value
     * in the reference array are left alone and will not be replaced.
     * This is you can call this function multiple times with different
     * reference arrays to easily implement a simple fallback behaviour.
     *
     * @access  public
     * @param   string  $template  the text containing the token to be replaced
     * @param   array   &$REF      a reference array containing the values
     * @return  string
     * @static
     */
    function fillTemplate($template, &$REF)
    {
        assert('is_string($template);');
        assert('is_array($REF);');
        settype($template, "string");

        if (is_array($REF) && count($REF)>0) {
            Layout::_replace($template, $REF);
            assert('is_string($template);');
            return $template;
        } else {
            assert('is_string($template);');
            return $template;
        }
    }

    /**
     * replace each token within a text/template
     *
     * NOTE: this method is case-insensitive
     *
     * @access  private
     * @param   string   $template
     * @param   array    &$REF
     * @param   bool     &$first_run  DO NOT SET
     * @return  string
     * @static
     */
    function _replace(&$template, &$REF, $first_run = true)
    {
        settype($template,"string");
        settype($REF,"array");

        $ldim = preg_quote(YANA_UNI_DELIMITER);
        $rdim = preg_quote(YANA_UNI_DELIMITER);
        if ($first_run === true) {
            $reference = changeCaseArray($REF, CASE_UPPER);
        } else {
            $reference =& $REF;
        }

        $match = array();
        if (preg_match_all("/$ldim([\w_\.][\w_\/\.]+)$rdim/s", $template,$match)>0) {
            $match = $match[1];
            $match = array_unique($match);
            for ($i=0;$i<count($match);$i++)
            {
                $tmp = Hashtable::get($reference, strtoupper(current($match)));
                /* if $tmp is NULL, the reference $match is pointing to a non-existing value */
                if (is_null($tmp)) {
                    $tmp = strtoupper(current($match));
                    $test = false;
                } else {
                    $test = true;
                }
                if (!is_scalar($tmp) || is_null($tmp)) {
                    trigger_error("The token '".current($match)."' refers to a non-scalar value inside a string contetx. It's value will be converted to the string 'true'.", E_USER_NOTICE);
                    $tmp = "true";
                }
                settype($tmp,"string");
                /* if the content string we got from the reference array contains token as well,
                 * we recursivle replace them as well
                 */
                if (preg_match("/$ldim([\w_\.][\w_\/\.]+)$rdim/",$tmp)) {
                    assert('is_string($tmp);');
                    Layout::_replace($tmp, $reference, true);
                }
                if ($test === true) {
                    assert('is_string($tmp);');
                    $template = preg_replace("/(<textarea [^>]*>[^<]*)$ldim".toRegExp(current($match))."$rdim([^<]*<\/textarea>)/Usi", '${1}'.$tmp.'${2}', $template);
                    $template = preg_replace("/(<[^\!^>]+)$ldim".toRegExp(current($match))."$rdim([^>]+>)/Usi", '${1}'.Layout::htmlSpecialCharsWithoutAmp($tmp).'${2}', $template);
        		    $template = preg_replace("/$ldim".toRegExp(current($match))."$rdim/Ui", DisplayUtility::embeddedTags($tmp), $template);
                    $template = preg_replace("/(<textarea [^>]*>[^<]*)\[br\]([^<]*<\/textarea>)/Usi", "\\1\n\\2", $template);
                } /* end if */
                next($match);
            } /* end for */
        } /* end if */
        assert('is_string($template);');
    }

    /**
     * replace token within a provided text
     *
     * Note that this function replaces ALL entities found.
     * If a token refers to a non-existing value it is replaced by string("").
     *
     * @static
     * @access  public
     * @param   string  $string
     * @return  string
     */
    function replaceToken($string)
    {
        global $YANA;

        if (!is_string($string) || empty($string) || strpos($string,YANA_UNI_DELIMITER) === false) {
            return $string;
        } else {
            if (isset($YANA)) {
                $string = Layout::fillTemplate($string, $YANA->registry->options);
            }
            $dim    = toRegExp(YANA_UNI_DELIMITER);
            $string = preg_replace("/$dim([A-Z]|\.){1,}$dim/U", "", $string);
            return $string;
        }
    
    }
    
    /**
     * convert html special characters
     *
     * This function is much like the original htmlspecialchars() function,
     * except for the point that it leaves the ampersand '&' character alone.
     *
     * @static
     * @access  public
     * @param   string  $string
     * @return  string
     *
     * @ignore
     */
    function htmlSpecialCharsWithoutAmp($string)
    {                                      
        if (!is_null($string)) {
            assert('is_scalar($string);');
            settype($string, "string");
            $string = str_replace('"', "&quot;", $string);
            $string = str_replace('<', "&lt;", $string);
            $string = str_replace('>', "&gt;", $string);
        
            return $string;
        } else {
            return "";
        }
    
    }

}
?>