blob: 3f61028e7068bf9badd834cbc54387f836a81619 [file] [log] [blame]
<?php
/**
* File containing the ezcTemplateString class
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package Template
* @version //autogen//
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @access private
*/
/**
* This class contains a bundle of static functions, each implementing a specific
* function used inside the template language.
*
* @package Template
* @version //autogen//
* @access private
*/
class ezcTemplateString
{
/**
* Stores the charset used for iconv
*/
const CHARSET = 'utf-8';
/**
* Lower to upper case conversion table.
*
* Included on demand when mbstring functions are not available.
* Generated from http://www.unicode.org/Public/UNIDATA/UnicodeData.txt.
*
* @var array(string=>string)
*/
private static $lowerToUpper = null;
/**
* Upper to lower case conversion table.
*
* Included on demand when mbstring functions are not available.
* Generated from http://www.unicode.org/Public/UNIDATA/UnicodeData.txt.
*
* @var array(string=>string)
*/
private static $upperToLower = null;
/**
* Escapes all special chars within the given $charlist for using it within
* a regular expression character class definition (i.e []^-\ and the
* pattern delimiter). By default the pattern delimiter is '/'.
*
* @param string $charlist
* @param string $patternDelimiter
* @return string
*/
private static function escapeCharacterClassCharlist( $charlist, $patternDelimiter = '/' )
{
return preg_replace( '!([\\\\\\-\\]\\[^'. $patternDelimiter .'])!', '\\\${1}', $charlist );
}
/**
* Multibyte safe ltrim().
*
* Based on http://de.php.net/manual/en/function.trim.php#72562.
* Added the charlist to the regexp. rtrim seems to be safe for whitespaces.
*
* @param string $str
* @param string $charlist
* @return string
*/
public static function ltrim( $str, $charlist = null )
{
if ( is_null( $charlist ) )
{
return ltrim( $str );
}
$charlist = self::escapeCharacterClassCharlist( $charlist );
return preg_replace( '/^['.$charlist.']+/u', '', $str );
}
/**
* Multibyte safe rtrim().
*
* Based on http://de.php.net/manual/en/function.trim.php#72562.
* Added the charlist to the regexp. rtrim seems to be safe for whitespaces.
*
* @param string $str
* @param string $charlist
* @return string
*/
public static function rtrim( $str, $charlist = null )
{
if ( is_null( $charlist ) )
{
return rtrim( $str );
}
$charlist = self::escapeCharacterClassCharlist( $charlist );
return preg_replace( '/['.$charlist.']+$/u', '', $str );
}
/**
* Multibyte safe str_pad().
*
* @param string $input
* @param int $pad_length
* @param string $pad_string
* @param mixed $pad_type
* @return string
*/
public static function str_pad( $input, $pad_length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT )
{
$diff = strlen( $input ) - iconv_strlen( $input, self::CHARSET );
return str_pad( $input, $pad_length + $diff, $pad_string, $pad_type );
}
/**
* Returns the number of paragraphs found in the given string.
*
* @param string $string
* @return int
*/
public static function str_paragraph_count( $string )
{
if ( iconv_strlen( $string, self::CHARSET ) == 0 )
{
return 0;
}
$pos = 0;
$count = 1;
while ( preg_match( "/\n\n+/u", $string, $m, PREG_OFFSET_CAPTURE, $pos ) )
{
++$count;
$pos = $m[0][1] + 1;
}
return $count;
}
/**
* Multibyte safe str_word_count().
*
* Based on http://de.php.net/manual/en/function.str-word-count.php#85592.
* Added the $charlist parameter and fixed the offsets for $format=2.
*
* @param string $string
* @param int $format
* 0 - returns the number of words found
* 1 - returns an array containing all the words found inside the string
* 2 - returns an associative array, where the key is the numeric position of the word inside the string and the value is the actual word itself
* @param string $charlist
* @return mixed
*/
public static function str_word_count( $string, $format = 0, $charlist = null )
{
if ( !is_null( $charlist ) )
{
$charlist = self::escapeCharacterClassCharlist( $charlist );
}
else
{
$charlist = '';
}
$pattern = "/\p{L}[\p{L}\p{Mn}\p{Pd}'\x{2019}".$charlist."]*/u";
$matches = array();
switch ( $format )
{
case 1:
preg_match_all( $pattern, $string, $matches );
return $matches[0];
case 2:
preg_match_all( $pattern, $string, $matches, PREG_OFFSET_CAPTURE );
$result = array();
$diff = 0;
foreach ( $matches[0] as $match )
{
// reduce wrong offset by multibyte difference
$offset = $match[1] - $diff;
$result[$offset] = $match[0];
// add multibyte offset difference of current word
$diff += strlen( $match[0] ) - iconv_strlen( $match[0], self::CHARSET );
}
return $result;
default:
return preg_match_all( $pattern, $string, $matches );
}
}
/**
* Multibyte safe strpos().
*
* @param string $haystack
* @param mixed $needle
* @param int $offset
* @return int|bool
*/
public static function strpos( $haystack, $needle, $offset = 0 )
{
return iconv_strpos( $haystack, $needle, $offset, self::CHARSET );
}
/**
* Multibyte safe strrpos().
*
* @param string $haystack
* @param mixed $needle
* @param int $offset
* @param bool $useMbString
* @return string
*/
public static function strrpos( $haystack, $needle, $offset = 0, $useMbString = true )
{
if ( $useMbString === true && function_exists( 'mb_strrpos' ) )
{
return mb_strrpos( $haystack, $needle, $offset, self::CHARSET );
}
else
{
$addOffset = 0;
if ( $offset > 0 )
{
$haystack = iconv_substr( $haystack, $offset, iconv_strlen( $haystack, self::CHARSET ), self::CHARSET );
$addOffset = $offset;
}
elseif( $offset < 0 )
{
$haystack = iconv_substr( $haystack, 0, $offset, self::CHARSET );
}
$result = iconv_strrpos( $haystack, $needle, self::CHARSET );
return ( $result === false ) ? $result : $result + $addOffset;
}
}
/**
* Multibyte safe strrev().
*
* Based on http://de.php.net/manual/en/function.strrev.php#62422.
*
* @param string $str
* @return string
*/
public static function strrev( $string )
{
if ( empty( $string ) )
{
return $string;
}
$matches = array();
preg_match_all( '/./us', $string, $matches );
return implode( '', array_reverse( $matches[0] ) );
}
/**
* Multibyte safe strtolower().
* Uses mb_strtolower() if available otherwise falls back to own conversion
* table.
*
* @param string $str
* @param bool $useMbString
* @return string
*/
public static function strtolower( $str, $useMbString = true )
{
if ( empty( $str ) )
{
return $str;
}
if ( $useMbString === true && function_exists( 'mb_strtolower' ) )
{
return mb_strtolower( $str, self::CHARSET );
}
if ( is_null( self::$upperToLower ) )
{
self::$upperToLower = new ezcTemplateStringUpperToLowerUnicodeMap();
}
return strtr( $str, self::$upperToLower->unicodeTable );
}
/**
* Multibyte safe strtoupper().
* Uses mb_strtoupper() if available otherwise falls back to own conversion
* table.
*
* @param string $str
* @param bool $useMbString
* @return string
*/
public static function strtoupper( $str, $useMbString = true )
{
if ( empty( $str ) )
{
return $str;
}
if ( $useMbString === true && function_exists( 'mb_strtoupper' ) )
{
return mb_strtoupper( $str, self::CHARSET );
}
if ( is_null( self::$lowerToUpper ) )
{
self::$lowerToUpper = new ezcTemplateStringLowerToUpperUnicodeMap();
}
return strtr( $str, self::$lowerToUpper->unicodeTable );
}
/**
* Multibyte safe trim().
*
* @param string $str
* @param string $charlist
* @return string
*/
public static function trim( $str, $charlist = null )
{
if ( is_null( $charlist ) )
{
return trim( $str );
}
return self::ltrim( self::rtrim( $str, $charlist ), $charlist );
}
/**
* Multibyte safe ucfirst().
*
* @param string $string
* @return string
*/
public static function ucfirst( $string )
{
$strlen = iconv_strlen( $string, self::CHARSET );
if ( $strlen == 0 )
{
return '';
}
elseif ( $strlen == 1 )
{
return self::strtoupper( $string );
}
else
{
$matches = array();
preg_match( '/^(.{1})(.*)$/us', $string, $matches );
return self::strtoupper( $matches[1] ) . $matches[2];
}
}
/**
* Multibyte safe wordwrap().
*
* @param string $str
* @param int $width
* @param string $break
* @param bool $cut
* @return string
*/
public static function wordwrap( $str, $width = 75, $break = "\n", $cut = false )
{
if ( empty( $str ) )
{
return $str;
}
$lines = explode( $break, $str );
$return = '';
foreach ( $lines as $line )
{
$line = trim( $line );
$length = iconv_strlen( $line, self::CHARSET );
if ( $length > $width )
{
if ( $cut )
{
while ( $length > $width )
{
$return .= iconv_substr( $line, 0, $width, self::CHARSET ) . $break;
$line = iconv_substr( $line, $width, iconv_strlen( $line, self::CHARSET ) - $width, self::CHARSET );
$length = iconv_strlen( $line, self::CHARSET );
}
$return .= $line;
}
else
{
$words = explode( ' ', $line );
$tmp = '';
foreach ( $words as $word )
{
$word = trim( $word );
if ( iconv_strlen( $tmp . $word, self::CHARSET ) <= $width )
{
$tmp .= $word . ' ';
}
else
{
$return .= trim( $tmp ) . $break;
$tmp = $word . ' ';
}
}
$return .= trim( $tmp );
}
}
else
{
$return .= $line. $break;
}
}
return $return;
}
}
?>