| <?php | 
 |  | 
 | interface TStringFunc { | 
 |     public function substr($str, $start, $length = null); | 
 |     public function strlen($str); | 
 | } | 
 |  | 
 | class TStringFunc_Core | 
 | implements TStringFunc { | 
 |     public function substr($str, $start, $length = null) { | 
 |         // specifying a null $length would return an empty string | 
 |         if($length === null) { | 
 |             return substr($str, $start); | 
 |         } | 
 |         return substr($str, $start, $length); | 
 |     } | 
 |  | 
 |     public function strlen($str) { | 
 |         return strlen($str); | 
 |     } | 
 | } | 
 |  | 
 | class TStringFunc_Mbstring | 
 | implements TStringFunc { | 
 |     public function substr($str, $start, $length = null) { | 
 |         /** | 
 |          * We need to set the charset parameter, which is the second | 
 |          * optional parameter and the first optional parameter can't | 
 |          * be null or false as a "magic" value because that would | 
 |          * cause an empty string to be returned, so we need to | 
 |          * actually calculate the proper length value. | 
 |          */ | 
 |         if($length === null) { | 
 |             $length = $this->strlen($str) - $start; | 
 |         } | 
 |  | 
 |         return mb_substr($str, $start, $length, '8bit'); | 
 |     } | 
 |  | 
 |     public function strlen($str) { | 
 |         return mb_strlen($str, '8bit'); | 
 |     } | 
 | } | 
 |  | 
 | class TStringFuncFactory { | 
 |     private static $_instance; | 
 |  | 
 |     /** | 
 |      * Get the Singleton instance of TStringFunc implementation that is | 
 |      * compatible with the current system's mbstring.func_overload settings. | 
 |      * | 
 |      * @return TStringFunc | 
 |      */ | 
 |     public static function create() { | 
 |         if(!self::$_instance) { | 
 |             self::_setInstance(); | 
 |         } | 
 |  | 
 |         return self::$_instance; | 
 |     } | 
 |  | 
 |     private static function _setInstance() { | 
 |         /** | 
 |          * Cannot use str* functions for byte counting because multibyte | 
 |          * characters will be read a single bytes. | 
 |          * | 
 |          * See: http://us.php.net/manual/en/mbstring.overload.php | 
 |          */ | 
 |         if(ini_get('mbstring.func_overload') & 2) { | 
 |             self::$_instance = new TStringFunc_Mbstring(); | 
 |         } | 
 |         /** | 
 |          * mbstring is not installed or does not have function overloading | 
 |          * of the str* functions enabled so use PHP core str* functions for | 
 |          * byte counting. | 
 |          */ | 
 |         else { | 
 |             self::$_instance = new TStringFunc_Core(); | 
 |         } | 
 |     } | 
 | } |