<?php
/**
 * DooTextHelper class file.
 *
 * @author Leng Sheng Hong <darkredz@gmail.com>
 * @link http://www.doophp.com/
 * @copyright Copyright &copy; 2009 Leng Sheng Hong
 * @license http://www.doophp.com/license
 */

/**
 * A helper class that helps to manipulate text.
 *
 * @author Leng Sheng Hong <darkredz@gmail.com>
 * @version $Id: DooTextHelper.php 1000 2009-08-4 11:17:22
 * @package doo.helper
 * @since 1.1
 */
class DooTextHelper {

    /**
     * Generates a random string.
     * @param int $length Length of the generated string
     * @return string
     */
    public static function randomName( $length = 6 ){
        $allchar = 'abcdefghijklmnopqrstuvwxyz01234567890';
        $str = "" ;
        mt_srand (( double) microtime() * 1000000 );
        for( $i=0; $i<$length; $i++ )
            $str .= substr( $allchar, mt_rand (0,36), 1 ) ;
        return date("YmdHis").rand(1000,9999).$str ;
    }

    /**
     * Removing repeated words from text.
     * @param string $str Original text to be processed.
     * @return string
     */
    public static function removeRepeatWords($str){
        return preg_replace("/s(w+s)1/i", "$1", $str);
    }


    /**
     * Removing repeated punctuation from text.
     * @param string $str Original text to be processed.
     * @return string
     */
    public static function removeRepeatPunc($str){
        return preg_replace("/.+/i", ".", $text);
    }


    /**
     * Convert all URLs in the text into hyperlinks.
     *
     * All URLs are converted. http://domain.com, www.domain.com, email@address.com
     * Passed in a false to disable converting Email to link.
     *
     * @param string $str
     * @param string $classname CSS class name of the link tag
     * @param string $target Target: _self, _blank, _parent, etc.
     * @param bool $convertEmail Convert email address into links. Default true.
     * @param string $emailHide Change this if you want to hide the email. eg. leng[AT]doophp.com, value = '[AT]'
     * @return string
     */
    public static function convertUrl($str, $classname='', $target='', $convertEmail=true, $emailHide='@'){
        if($classname!='')
            $classname = "class=\"$classname\"";

        if($target!='')
            $target = "target=\"$target\"";

        $str = preg_replace("#([ ]|^|])([a-z]+?)://([a-z0-9@:\-]+)\.([a-z0-9@:\-.\~]+)((?:/[^ ]*)?[^][\".,?!;: ])#i", "\\1<a href=\"\\2://\\3.\\4\\5\" $target $classname>\\2://\\3.\\4\\5</a>", $str);
        $str = preg_replace("#([ ]|^|])www\.([a-z0-9\-]+)\.([a-z0-9:\-.\~]+)((?:/[^ ]*)?[^][\".,?!;: ])#i", "\\1<a href=\"http://www.\\2.\\3\\4\" $target $classname>www.\\2.\\3\\4</a>", $str);

        if($convertEmail)
            if($emailHide=='@')
                $str = preg_replace("#([ ]|^|])([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)?[\w]+[^][\".,?!;: ])#i", "\\1<a href=\"mailto:\\2@\\3\" $target $classname>\\2@\\3</a>", $str);
            else
                $str = preg_replace("#([ ]|^|])([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)?[\w]+[^][\".,?!;: ])#i", "\\1\\2$emailHide\\3", $str);

        return $str;
    }

    /**
     * Count words.
     * @param string $str Input String
     * @return int Number of words
     */
    public static function countWord($str){
        return str_word_count($str);
    }

    /**
     * Escape/encode a string
     *
     * @param string $str The input string
     * @param string $escapeType Escape type: html, htmlall, url
     * @param string $charSet Character set, default ISO-8859-1
     * @return string
     */
    public static function escape($str, $escapeType='html', $charSet='ISO-8859-1'){
        switch ($escapeType){
            case 'url':
                return rawurlencode($str);

            case 'urlpathinfo':
                return str_replace('%2F','/',rawurlencode($str));

            case 'quotes':
                return preg_replace("%(?<!\\\\)'%", "\\'", $str);

            case 'hex':
                $rs = '';
                for($i=0; $i < strlen($str); $i++) {
                    $rs .= '%' . bin2hex($str[$i]);
                }
                return $rs;

            case 'hexentity':
                $rs = '';
                for($i=0; $i < strlen($str); $i++) {
                        $rs .= '&#x' . bin2hex($str[$i]) . ';';
                }
                return $rs;

            case 'decentity':
                $rs = '';
                for($i=0; $i < strlen($str); $i++) {
                    $rs .= '&#' . ord($str[$i]) . ';';
                }
                return $rs;

            case 'html':
               return htmlspecialchars($str, ENT_COMPAT, $charSet);

            case 'htmlall':
                return htmlentities($str, ENT_COMPAT, $charSet);

            case 'js':
                return strtr($str, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));

            case 'mail':
                return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $str);

            case 'nonstd':
                $rs = '';
                for($i = 0, $length = strlen($str); $i < $length; $i++) {
                    $ord = ord(substr($str, $i, 1));
                    $rs .= $ord >= 126 ? '&#' . $ord . ';' : substr($str, $i, 1);
                }
                return $rs;
            default:
                return $str;
        }
    }

    /**
     * Filter/censor word(s) from a string input
     *
     * <p>A list of disallowed words will be replaced to '*' or the replacement value
     * from the input string.</p>
     *
     * @param string $str Input string to be processed
     * @param array $censorWords List of words to be censored
     * @param string $replacement Optional replacement string for the censored word
     * @param bool $word True to be an exact word, False to censor within word 'Youprofanity'
     * @return string
     */
    public static function filter($str, $censorWords, $replacement='*', $word=true){
	if(!$word)
	    return str_ireplace($censorWords, $replacement, $str);

        foreach($censorWords as $c)
            $str = preg_replace("/\b(" . str_replace('\*', '\w*?', preg_quote($c)) . ")\b/i", $replacement, $str);

        return $str;
    }

    /**
     * Highlight PHP code
     *
     * @param string $str String of the PHP script
     * @return string
     */
    public static function highlightPHP($str){
        $str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
        $str = str_replace(array('&lt;?php', '?&gt;',  '\\'), array('phptagopen', 'phptagclose', 'backslashtmp'), $str);
        $str = '<?php //tempstart' . "\n" . $str . '//tempend ?>';
        $str = highlight_string($str, true);
        if(abs(phpversion()) < 5){
            $str = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $str);
            $str = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
        }
        $str = preg_replace("#\<code\>.+?//tempstart\<br />\</span\>#is", "<code>\n", $str);
        //$str = preg_replace("#\<code\>.+?//tempstart\<br />#is", "<code>\n", $str);
        $str = preg_replace("#//tempend.+#is", "</span>\n</code>", $str);
        $str = str_replace(array('phptagopen', 'phptagclose', 'backslashtmp'), array('&lt;?php', '?&gt;', '\\'), $str);
        return $str;
    }

    /**
     * Highlight word(s) within a string
     *
     * @param string $str String input
     * @param string $phrase The phrase to be highlighted
     * @param string $tagOpen HTML tag added right before the word
     * @param string $tagClose HTML tag added right after the word
     * @return string
     */
    public static function highlightWord($str, $phrase, $tagOpen='<span style="font-weight:bold;background-color:#ffff00">', $tagClose='</span>'){
        return preg_replace('/(' . preg_quote($phrase) . ')/i', $tagOpen . "\\1" . $tagClose, $str);
    }

    /**
     * Limit the string to a certain amount of words.
     *
     * @param string $str String input
     * @param int $limit Number of words to limit
     * @param string $ending End characters. Default '...'
     * @return string
     */
    public static function limitWord($str, $limit, $ending='...'){
        if(strlen($str) < $limit)
            return $str;

        $words = explode(' ', preg_replace("/\s+/", ' ', preg_replace("/(\r\n|\r|\n)/", " ", $str)));

        if(sizeof($words)<=$limit)
            return $str;

        $str = '';
        for($i=0; $i<$limit; $i++){
            $str .= $words[$i].' ';
        }
        return $str . $ending;
    }

    /**
     * Limit the string to a certain amount of characters.
     *
     * @param string $str String input
     * @param int $limit Number of characters to limit
     * @param string $ending End characters. Default '...'
     * @param string $encoding The character encoding. eg. utf8
     * @return string
     */
    public static function limitChar($str, $limit, $ending='...', $encoding=null){
        if($encoding==null){
            if(strlen($str) <= $limit)
                return $str;

            return substr($str, 0, $limit) . $ending;
        }else{
            if(mb_strlen($str, $encoding) <= $limit)
                return $str;

            return mb_substr($str, 0, $limit, $encoding) . $ending;
        }
    }

    /**
     * Replace all repeated spaces, newlines and tabs.
     *
     * @param string $str String input
     * @param string $replace Replacement value (optional)
     * @return string
     */
    public static function strip($str, $replace=' '){
        return preg_replace('/\s+/', $replace, $str);
    }

     /**
      * Word wraping of string
      *
      * Anything within [nowrap][/nowrap] in the string won't be wrapped.
      * 
      * @param string $str String input
      * @param int $charLimit Character limit per line
      * @param string $breakline Break line HTML replacement
      * @return string
      */
    public static function wordwrap($str, $charLimit, $breakline='<br/>'){
        if(!is_numeric($charLimit))
                $charLimit = 76;

        $str = preg_replace("| +|", " ", $str);
        $str = preg_replace("/\r\n|\r/", "\n", $str);

        $nowrap = array();
        if(preg_match_all("|(\[nowrap\].+?\[/nowrap\])|s", $str, $matches)){
            $count = count($matches['0']);
            for($i = 0; $i < $count; $i++){
                $nowrap[] = $matches['1'][$i];
                $str = str_replace($matches['1'][$i], "[[nowrapped".$i."]]", $str);
            }
        }

        $str = wordwrap($str, $charLimit, $breakline, false);

        $output = '';
        foreach(explode($breakline, $str) as $line) {
            if(strlen($line) <= $charLimit){
                $output .= $line . $breakline;
                continue;
            }

            $temp = '';
            while((strlen($line)) > $charLimit){
                if(preg_match("!\[url.+\]|://|wwww.!", $line))
                    break;

                $temp .= substr($line, 0, $charLimit-1);
                $line = substr($line, $charLimit-1);
            }
            $output .= ($temp != '' ? $temp.$line : $line) . $breakline;
        }

        if(count($nowrap) > 0){
            foreach($nowrap as $key => $val){
                $output = str_replace("[[nowrapped".$key."]]", $val, $output);
            }
        }

        $output = str_replace(array('[nowrap]', '[/nowrap]'), '', $output);
        return $output;
    }
}
