1: <?php
2:
3: /**
4: * This file contains the multi byte wrapper class for strings.
5: *
6: * @package Core
7: * @subpackage Util
8: * @author Frederic Schneider <frederic.schneider@4fb.de>
9: * @author Marcus Gnaß <marcus.gnass@4fb.de>
10: * @copyright four for business AG <www.4fb.de>
11: * @license http://www.contenido.org/license/LIZENZ.txt
12: * @link http://www.4fb.de
13: * @link http://www.contenido.org
14: */
15:
16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
17:
18: /**
19: * Wrapper class for mbstring functions to be used with strings.
20: *
21: * Each method is a wrapper for a mbstring function that implements a fallback
22: * to the regular string function if the mbstring function does not exist
23: * or the mbstring extension itself is not available.
24: *
25: * @package Core
26: * @subpackage Util
27: * @todo add mb_chr(), mb_ord()
28: */
29: class cStringMultiByteWrapper {
30:
31: /**
32: * Checks if a given mbstring function exists.
33: *
34: * Caches informations about existing mbstring functions for better
35: * performance.
36: *
37: * @param string $functionName
38: * @return bool
39: */
40: protected static function _functionExists($functionName) {
41: static $cache;
42: if (!isset($cache)) {
43: $cache = array();
44: foreach (array(
45: 'mb_strtolower', 'mb_strtoupper', 'mb_strlen', 'mb_substr',
46: 'mb_substr_count', 'mb_send_mail', 'mb_strpos', 'mb_strrpos', 'mb_stripos',
47: 'mb_strripos', 'mb_stristr', 'mb_strrchr'
48: ) as $function) {
49: $cache[$function] = function_exists($function);
50: }
51: }
52: return isset($cache[$functionName]) ? $cache[$functionName] : false;
53: }
54:
55: /**
56: * Determines multi byte encoding to be used for various mbstring functions.
57: *
58: * If NULL is given the encoding for the current language is used
59: * which tends to be awfully slow as it requires a database lookup!
60: *
61: * If none could be determined the current set encoding is used.
62: *
63: * @param string|null $encoding
64: * - give a string to use a specific encoding
65: * - give null to use the encoding of the current language
66: * @return string
67: */
68: protected static function _getEncoding($encoding = null) {
69: if (!is_string($encoding)) {
70: $encoding = mb_internal_encoding();
71: }
72: return $encoding;
73: }
74:
75: /**
76: * Make a string lowercase
77: *
78: * @param string $string
79: * The string being lowercased
80: * @param string|null $encoding
81: * encoding parameter, standard: cRegistry::getEncoding()
82: * @return string
83: * with all alphabetic characters converted to lowercases
84: * @link http://php.net/manual/de/function.mb-strtolower.php
85: */
86: public static function toLowerCase($string, $encoding = null) {
87: if (self::_functionExists('mb_strtolower')) {
88: $result = mb_strtolower($string, self::_getEncoding($encoding));
89: } else {
90: $result = strtolower($string);
91: }
92: return $result;
93: }
94:
95: /**
96: * Make a string uppercase
97: *
98: * @param string $string
99: * The string being uppercased
100: * @param string|null $encoding
101: * encoding parameter, standard: cRegistry::getEncoding()
102: * @return string
103: * with all alphabetic characters converted to uppercases
104: * @link http://php.net/manual/de/function.mb-strtoupper.php
105: */
106: public static function toUpperCase($string, $encoding = null) {
107: if (self::_functionExists('mb_strtoupper')) {
108: $result = mb_strtoupper($string, self::_getEncoding($encoding));
109: } else {
110: $result = strtoupper($string);
111: }
112: return $result;
113: }
114:
115: /**
116: * Get string length
117: *
118: * @param string $string
119: * The string being checked for length
120: * @param string|null $encoding
121: * encoding parameter, standard: cRegistry::getEncoding()
122: * @return int
123: * Returns the number of characters
124: * @link http://php.net/manual/de/function.mb-strlen.php
125: */
126: public static function getStringLength($string, $encoding = null) {
127: if (self::_functionExists('mb_strlen')) {
128: $result = mb_strlen($string, self::_getEncoding($encoding));
129: } else {
130: $result = strlen($string);
131: }
132: return $result;
133: }
134:
135: /**
136: * Get string length
137: *
138: * @param string $string
139: * The string to extract the substring form
140: * @param int $start
141: * @param int $length [Optional]
142: * Maximum number of characters to use from $string, standard is NULL
143: * @param string|null $encoding
144: * encoding parameter, standard: cRegistry::getEncoding()
145: * @return string
146: * Returns the number of characters
147: * @link http://php.net/manual/de/function.mb-substr.php
148: */
149: public static function getPartOfString($string, $start, $length = null, $encoding = null) {
150: if (self::_functionExists('mb_substr')) {
151: $result = mb_substr($string, $start, $length, self::_getEncoding($encoding));
152: } else {
153: $result = substr($string, $start, $length);
154: }
155: return $result;
156: }
157:
158: /**
159: * Count the number of substring occurences
160: *
161: * @param string $haystack
162: * The string being checked
163: * @param string $needle
164: * The string being found
165: * @param string|null $encoding
166: * encoding parameter, standard: cRegistry::getEncoding()
167: * @return int
168: * The number of times the needle substring occurs in the haystack string.
169: * @link http://php.net/manual/de/function.mb-substr-count.php
170: */
171: public static function countSubstring($haystack, $needle, $encoding = null) {
172: if (self::_functionExists('mb_substr_count')) {
173: $result = mb_substr_count($haystack, $needle, self::_getEncoding($encoding));
174: } else {
175: $result = substr_count($haystack, $needle);
176: }
177: return $result;
178: }
179:
180: /**
181: * Send encoded mail
182: *
183: * @param string $to
184: * The mail addresses being sent to (multiple recipents comma separated)
185: * @param string $subject
186: * The subject of the mail
187: * @param string $message
188: * The message of the mail
189: * @param string $additional_headers [Optional]
190: * @param string $additional_parameter [Optional]
191: * @return boolean
192: * true or false
193: * @link http://php.net/manual/de/function.mb-send-mail.php
194: */
195: public static function mail($to, $subject, $message, $additional_headers = null, $additional_parameter = null) {
196: if (self::_functionExists('mb_send_mail')) {
197: $result = mb_send_mail($to, $subject, $message, $additional_headers, $additional_parameter);
198: } else {
199: $result = mail($to, $subject, $message, $additional_headers, $additional_parameter);
200: }
201: return $result;
202: }
203:
204: /**
205: * Find the position of first occurence of string in a string
206: *
207: * @param string $haystack
208: * @param string $needle
209: * @param integer $offset [Optional]
210: * @param string|null $encoding
211: * encoding parameter, standard: cRegistry::getEncoding()
212: * @return int
213: * Returns the numeric position of the first occurrence of needle in the haystack string
214: * @link http://php.net/manual/de/function.mb-strpos.php
215: */
216: public static function findFirstPos($haystack, $needle, $offset = 0, $encoding = null) {
217: if (self::_functionExists('mb_strpos')) {
218: $result = mb_strpos($haystack, $needle, $offset, self::_getEncoding($encoding));
219: } else {
220: $result = strpos($haystack, $needle, $offset);
221: }
222: return $result;
223: }
224:
225: /**
226: * Find the position of last occurence of string in a string
227: *
228: * @param string $haystack
229: * @param string $needle
230: * @param integer $offset [Optional]
231: * @param string|null $encoding
232: * encoding parameter, standard: cRegistry::getEncoding()
233: * @return int
234: * Returns the numeric position of the last occurrence of needle in the haystack string
235: * @link http://php.net/manual/de/function.mb-strrpos.php
236: */
237: public static function findLastPos($haystack, $needle, $offset = 0, $encoding = null) {
238: if (self::_functionExists('mb_strrpos')) {
239: $result = mb_strrpos($haystack, $needle, $offset, self::_getEncoding($encoding));
240: } else {
241: $result = strrpos($haystack, $needle, $offset);
242: }
243: return $result;
244: }
245:
246: /**
247: * Finds position of first occurrence of a string within another, case insensitive
248: *
249: * @param string $haystack
250: * @param string $needle
251: * @param integer $offset [Optional]
252: * @param string|null $encoding
253: * encoding parameter, standard: cRegistry::getEncoding()
254: * @return int
255: * Returns the numeric position of the first occurrence of needle in the haystack string
256: * @link http://php.net/manual/de/function.mb-stripos.php
257: */
258: public static function findFirstPosCI($haystack, $needle, $offset = 0, $encoding = null) {
259: if (self::_functionExists('mb_stripos')) {
260: $result = mb_stripos($haystack, $needle, $offset, self::_getEncoding($encoding));
261: } else {
262: $result = stripos($haystack, $needle, $offset);
263: }
264: return $result;
265: }
266:
267: /**
268: * Finds position of last occurrence of a string within another, case insensitive
269: *
270: * @param string $haystack
271: * @param string $needle
272: * @param integer $offset [Optional]
273: * @param string|null $encoding
274: * encoding parameter, standard: cRegistry::getEncoding()
275: * @return int
276: * Returns the numeric position of the last occurrence of needle in the haystack string
277: * @link http://php.net/manual/de/function.mb-strripos.php
278: */
279: public static function findLastPosCI($haystack, $needle, $offset = 0, $encoding = null) {
280: if (self::_functionExists('mb_strripos')) {
281: $result = mb_strripos($haystack, $needle, $offset, self::_getEncoding($encoding));
282: } else {
283: $result = strripos($haystack, $needle, $offset);
284: }
285: return $result;
286: }
287:
288: /**
289: * Finds first occurrence of a string within another, case insensitive
290: *
291: * @param string $haystack
292: * @param string $needle
293: * @param boolean $before_needle [Optional]
294: * @param string|null $encoding
295: * encoding parameter, standard: cRegistry::getEncoding()
296: * @return string
297: * Returns the portion of haystack, or FALSE if needle is not found.
298: * @link http://php.net/manual/de/function.mb-stristr.php
299: */
300: public static function findFirstOccurrenceCI($haystack, $needle, $before_needle = false, $encoding = null) {
301: if (self::_functionExists('mb_stristr')) {
302: $result = mb_stristr($haystack, $needle, $before_needle, self::_getEncoding($encoding));
303: } else {
304: $result = stristr($haystack, $needle, $before_needle);
305: }
306: return $result;
307: }
308:
309: /**
310: * Finds first occurrence of a string within another, case insensitive
311: *
312: * @param string $haystack
313: * @param string $needle
314: * @param boolean $part [Optional]
315: * @param string|null $encoding
316: * encoding parameter, standard: cRegistry::getEncoding()
317: * @return string
318: * Returns the portion of haystack, or FALSE if needle is not found.
319: * @link http://php.net/manual/de/function.mb-strrchr.php
320: */
321: public static function findLastOccurrence($haystack, $needle, $part = false, $encoding = null) {
322: if (self::_functionExists('mb_strrchr')) {
323: $result = mb_strrchr($haystack, $needle, $part, self::_getEncoding($encoding));
324: } elseif (!$part) {
325: $result = strrchr($haystack, $needle);
326: } else {
327: // TODO strrchr canot handle $part = true
328: $result = null;
329: }
330: return $result;
331: }
332:
333: /**
334: * Regular expression match
335: *
336: * @param string $pattern
337: * @param string $string
338: * @param array $regs [Optional]
339: * @return int
340: * @link http://php.net/manual/de/function.mb-ereg.php
341: */
342: public static function ereg($pattern, $string, &$regs = array()) {
343: // TODO provide fallback multibyte extension is missing
344: return mb_ereg($pattern, $string, $regs);
345: }
346:
347: /**
348: * Regular expression match ignoring case
349: *
350: * @param string $pattern
351: * @param string $string
352: * @param array $regs [Optional]
353: * @return int Returns the byte length of the matched string if a match for pattern was found in string
354: * @link http://php.net/manual/de/function.mb-eregi.php
355: */
356: public static function eregi($pattern, $string, &$regs = array()) {
357: // TODO provide fallback multibyte extension is missing
358: return mb_eregi($pattern, $string, $regs);
359: }
360:
361: /**
362: * Replace regular expression
363: *
364: * @param string $pattern
365: * @param string $replacement
366: * @param string $string
367: * @param string $option [Optional]
368: * @return false|string Returns the byte length of the matched string if a match for pattern was found in string
369: * @link http://php.net/manual/de/function.mb-ereg-replace.php
370: */
371: public static function ereg_replace($pattern, $replacement, $string, $option = 'msr') {
372: // TODO provide fallback multibyte extension is missing
373: return mb_ereg_replace($pattern, $replacement, $string, $option);
374: }
375:
376: /**
377: * Replace regular expression ignoring case
378: *
379: * @param string $pattern
380: * @param string $replacement
381: * @param string $string
382: * @param string $option [Optional]
383: * @return false|string Returns the byte length of the matched string if a match for pattern was found in string
384: * @link http://php.net/manual/de/function.mb-eregi-replace.php
385: */
386: public static function eregi_replace($pattern, $replacement, $string, $option = 'msr') {
387: // TODO provide fallback multibyte extension is missing
388: return mb_eregi_replace($pattern, $replacement, $string, $option);
389: }
390:
391: /**
392: * Split string using regular expression
393: *
394: * @param string $pattern
395: * @param string $string
396: * @param integer $limit [Optional]
397: * @return string[] The result as an array
398: * @link http://php.net/manual/de/function.mb-split.php
399: */
400: public static function split($pattern, $string, $limit = -1) {
401: // TODO provide fallback multibyte extension is missing
402: return mb_split($pattern, $string, $limit);
403: }
404:
405: }
406: