<?php
/**
 * String
 *
 * $Id$
 *
 * @author gERD Schaufelberger <gerd@php-tools.net>
 * @license PHP License
 * @package WB
 * @subpackage base
 */

/**
 * String
 *
 * Simple string functions
 *
 * @version 1.1.0
 * @package WB
 * @subpackage base
 */
class WBString extends WBStdClass
{
    /**
     * cache of super placeholders
     *
     * @var array
     */
    static protected $superPlaceholders =   array(
                                                'map'       =>  array(),
                                                'search'    =>  array(),
                                                'replace'   =>  array()
                                            );

    /**
     * Format array
     *
     * @param array $data
     * @param string $glue
     * @param string $delimiter
     * @return string
     */
    static public function formatArray($data, $glue = ':', $delimiter = '|')
    {
        if(!is_array($data)) {
            return '';
        }

        // transform to associative array to flat string
        $str    =   array();
        foreach ($data as $k => $v) {
            if (!is_scalar($v)) {
                if (!is_array($v)) {
                    // don't try any further
                    continue;
                }
                $v  =   sprintf('[%d]',  count($v));
            }
            $str[]  =   sprintf('%s%s%s', $k, $glue, $v);
        }

        $str    =   implode($delimiter, $str);
        return $str;
    }

    /**
     * fill placeolders
     *
     * Replace matching placehlders
     *
     * @param string $string
     * @param array $data
     * @return string
     */
    public static function populate($string, $data = array())
    {
        if (empty($data)) {
            return $string;
        }

        $search     =   array();
        $replace    =   array();
        foreach ($data as $k => $v) {
            if (!is_scalar($v)) {
                continue;
            }
            $search[]   =   '{' . strtoupper($k) . '}';
            $replace[]  =   $v;
        }
        return str_replace($search, $replace, $string);
    }

    /**
     * replace super global placeholders
     *
     * Filter [[DOCROOT]], [[SERVER_CSS]] and stuff.
     *
     * @param string $in
     * @param string $path
     * @return string
     */
    public static function replaceSuperPlaceholders($in, $path = '/')
    {
        // is there anything to replace?
        if (!strstr($in, '[[')) {
            return $in;
        }

        self::loadSuperPlaceHolder();

        // we actually know, that the first element is the "path"
        self::$superPlaceholders['replace'][0]  =   ltrim($path, '/');

        return str_replace(self::$superPlaceholders['search'], self::$superPlaceholders['replace'], $in);
    }

    /**
     * get list of placeholders
     *
     * Access both, mapping and search and replace lists for
     * super placeholders
     *
     * The returned array contains the following keys:
     *  - 'map' associative array of placeholder names and replacements
     *  - 'search' list of search strings
     *  - 'replace' list of replace strings accoring to search
     *
     * @see $superPlaceholders
     * @param string name of placeholder or null to get list of all
     * @return array|string
     */
    public static function getSuperPlaceHolder($name = null)
    {
        self::loadSuperPlaceHolder();

        if (empty($name)) {
            return self::$superPlaceholders;
        }

        if (isset(self::$superPlaceholders['map'][$name])) {
            return self::$superPlaceholders['map'][$name];
        }
        return null;
    }

    /**
     * add current language
     *
     * Append language to [[SERVER_HTML]]
     *
     * @param string $lang or null to remove language
     */
    public static function setLanguagePath($lang = null)
    {
        self::loadSuperPlaceHolder();

        self::$superPlaceholders['map']['service_html'] =   self::$superPlaceholders['map']['self_no_lang'];
        self::$superPlaceholders['map']['self']         =   self::$superPlaceholders['map']['self_no_lang'];
        if (!empty($lang)) {
            self::$superPlaceholders['map']['service_html'] .=  $lang . '/';
            self::$superPlaceholders['map']['self']         .=  $lang . '/';
        }

        for ($i = 0; $i < count(self::$superPlaceholders['search']); ++$i) {
            if ('[[SERVICE_HTML]]' == self::$superPlaceholders['search'][$i]) {
                self::$superPlaceholders['replace'][$i] =   self::$superPlaceholders['map']['service_html'];
            }
            if ('[[SELF]]' == self::$superPlaceholders['search'][$i]) {
                self::$superPlaceholders['replace'][$i] =   self::$superPlaceholders['map']['self'];
            }
        }
    }

    /**
     * Update DocRoot
     *
     * Set folder to be used as DOCROOT - this will reload super placeholders and
     * update them
     *
     * @param string
     */
    public static function setDocRoot($root)
    {
        $config =   WBClass::create('WBConfig');
        $config->load('config');
        $conf   =   $config->get('page');
        $conf['docroot']    =   $root;
        self::updateSuperPlaceholder($conf);
    }

    /**
     * Set Super Placeholder
     *
     * Change super placeholder on the fly
     *
     * @param string
     * @param string
     */
    public static function setSuperPlaceholder($name, $value)
    {
        self::loadSuperPlaceHolder();
        if (!isset(self::$superPlaceholders['map'][$name])) {
            return;
        }

        $name   =   strtolower($name);
        self::$superPlaceholders['map'][$name]  =   $value;
        $name   =   '[[' . strtoupper($name) . ']]';
        foreach (self::$superPlaceholders['search'] as $i => $v) {
            if ($name == $v) {
                self::$superPlaceholders['replace'][$i] =   $value;
                break;
            }
        }
    }

    /**
     * load placeholders from config
     *
     * The placeholser variables are loaded from the main configuration file:
     *   etc/config.xml
     *
     */
    protected static function loadSuperPlaceHolder()
    {
        // load only once
        if (!empty(self::$superPlaceholders['map'])) {
            return;
        }

        // load config to fill placeholders
        $config =   WBClass::create('WBConfig');
        $config->load('config');
        self::updateSuperPlaceholder($config->get('page'));
    }

    /**
     * Update Super Placeholders With Config
     *
     * Helper method to generate array of search and replace super placeholders
     * @param array
     */
    static private function updateSuperPlaceholder($conf)
    {
        $conf['docroot']            =   rtrim($conf['docroot'], '/');
        $conf['service']['html']    =   trim($conf['service']['html'], '/');
        if (!empty($conf['service']['html'])) {
            $conf['service']['html']    .=  '/';
        }

        // Get protocol from request
        $req    =   WBClass::create('WBRequest');

        $page                   =   array();
        $page['protocol']       =   $req->protocol;
        $page['server']         =   trim($conf['server']);
        if (empty($page['server'])) {
            $page['server'] =   $req->getMeta('HTTP_HOST', '');
        }

        $page['server_addr']    =   $req->getMeta('SERVER_ADDR');
        $page['docroot']        =   $conf['docroot'];
        $page['self']           =   sprintf('%s/%s', $conf['docroot'], $conf['service']['html']);
        $page['self_no_lang']   =   $page['self'];
        foreach ($conf['service'] as $name => $script) {
            $script                     =   trim($script, '/');
            if (!empty($script)) {
                $script	.=	'/';
            }
            $page['service_' . $name]   =   sprintf('%s/%s', $conf['docroot'], $script);
        }

        uasort($page, array('WBString', 'compareSuperPlaceHolder'));

        self::$superPlaceholders['map']     =   $page;
        self::$superPlaceholders['search']  =   array_keys($page);
        self::$superPlaceholders['replace'] =   array_values($page);

        // add "path" in front
        array_unshift(self::$superPlaceholders['search'], 'path');
        array_unshift(self::$superPlaceholders['replace'], '');

        foreach (self::$superPlaceholders['search'] as &$s) {
            $s  =   '[[' . strtoupper( $s ) . ']]';
        }
    }

    /**
     * compare string length if super place holders
     *
     * @param string $a
     * @param string $b
     * @return int 0, 1 or -1
     */
    private static function compareSuperPlaceHolder($a, $b)
    {
        $al =   strlen($a);
        $bl =   strlen($b);
        if ($al == $bl) {
            return 0;
        }
        if ($al < $bl) {
            return 1;
        }
        return -1;
    }
}
?>