CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.0 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.0
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Auth
    • Core
    • Error
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
    • Network
      • Email
      • Http
    • Routing
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • I18n
  • L10n
  • Multibyte

Functions

  • mb_encode_mimeheader
  • mb_stripos
  • mb_stristr
  • mb_strlen
  • mb_strpos
  • mb_strrchr
  • mb_strrichr
  • mb_strripos
  • mb_strrpos
  • mb_strstr
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
   1: <?php
   2: /**
   3:  * Multibyte handling methods.
   4:  *
   5:  *
   6:  * PHP 5
   7:  *
   8:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
   9:  * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10:  *
  11:  * Licensed under The MIT License
  12:  * Redistributions of files must retain the above copyright notice.
  13:  *
  14:  * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15:  * @link          http://cakephp.org CakePHP(tm) Project
  16:  * @package       Cake.I18n
  17:  * @since         CakePHP(tm) v 1.2.0.6833
  18:  * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
  19:  */
  20: 
  21: /**
  22:  * Find position of first occurrence of a case-insensitive string.
  23:  *
  24:  * @param string $haystack The string from which to get the position of the first occurrence of $needle.
  25:  * @param string $needle The string to find in $haystack.
  26:  * @param integer $offset The position in $haystack to start searching.
  27:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
  28:  * @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string, or false
  29:  *    if $needle is not found.
  30:  */
  31: if (!function_exists('mb_stripos')) {
  32:     function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) {
  33:         return Multibyte::stripos($haystack, $needle, $offset);
  34:     }
  35: }
  36: 
  37: /**
  38:  * Finds first occurrence of a string within another, case insensitive.
  39:  *
  40:  * @param string $haystack The string from which to get the first occurrence of $needle.
  41:  * @param string $needle The string to find in $haystack.
  42:  * @param boolean $part Determines which portion of $haystack this function returns.
  43:  *    If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
  44:  *    If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
  45:  *    Default value is false.
  46:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
  47:  * @return string|boolean The portion of $haystack, or false if $needle is not found.
  48:  */
  49: if (!function_exists('mb_stristr')) {
  50:     function mb_stristr($haystack, $needle, $part = false, $encoding = null) {
  51:         return Multibyte::stristr($haystack, $needle, $part);
  52:     }
  53: }
  54: 
  55: /**
  56:  * Get string length.
  57:  *
  58:  * @param string $string The string being checked for length.
  59:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
  60:  * @return integer The number of characters in string $string having character encoding encoding.
  61:  *    A multi-byte character is counted as 1.
  62:  */
  63: if (!function_exists('mb_strlen')) {
  64:     function mb_strlen($string, $encoding = null) {
  65:         return Multibyte::strlen($string);
  66:     }
  67: }
  68: 
  69: /**
  70:  * Find position of first occurrence of a string.
  71:  *
  72:  * @param string $haystack The string being checked.
  73:  * @param string $needle The position counted from the beginning of haystack.
  74:  * @param integer $offset The search offset. If it is not specified, 0 is used.
  75:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
  76:  * @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string.
  77:  *    If $needle is not found, it returns false.
  78:  */
  79: if (!function_exists('mb_strpos')) {
  80:     function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) {
  81:         return Multibyte::strpos($haystack, $needle, $offset);
  82:     }
  83: }
  84: 
  85: /**
  86:  * Finds the last occurrence of a character in a string within another.
  87:  *
  88:  * @param string $haystack The string from which to get the last occurrence of $needle.
  89:  * @param string $needle The string to find in $haystack.
  90:  * @param boolean $part Determines which portion of $haystack this function returns.
  91:  *    If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
  92:  *    If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
  93:  *    Default value is false.
  94:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
  95:  * @return string|boolean The portion of $haystack. or false if $needle is not found.
  96:  */
  97: if (!function_exists('mb_strrchr')) {
  98:     function mb_strrchr($haystack, $needle, $part = false, $encoding = null) {
  99:         return Multibyte::strrchr($haystack, $needle, $part);
 100:     }
 101: }
 102: 
 103: /**
 104:  * Finds the last occurrence of a character in a string within another, case insensitive.
 105:  *
 106:  * @param string $haystack The string from which to get the last occurrence of $needle.
 107:  * @param string $needle The string to find in $haystack.
 108:  * @param boolean $part Determines which portion of $haystack this function returns.
 109:  *    If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
 110:  *    If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
 111:  *    Default value is false.
 112:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 113:  * @return string|boolean The portion of $haystack. or false if $needle is not found.
 114:  */
 115: if (!function_exists('mb_strrichr')) {
 116:     function mb_strrichr($haystack, $needle, $part = false, $encoding = null) {
 117:         return Multibyte::strrichr($haystack, $needle, $part);
 118:     }
 119: }
 120: 
 121: /**
 122:  * Finds position of last occurrence of a string within another, case insensitive
 123:  *
 124:  * @param string $haystack The string from which to get the position of the last occurrence of $needle.
 125:  * @param string $needle The string to find in $haystack.
 126:  * @param integer $offset The position in $haystack to start searching.
 127:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 128:  * @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string,
 129:  *    or false if $needle is not found.
 130:  */
 131: if (!function_exists('mb_strripos')) {
 132:     function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) {
 133:         return Multibyte::strripos($haystack, $needle, $offset);
 134:     }
 135: }
 136: 
 137: /**
 138:  * Find position of last occurrence of a string in a string.
 139:  *
 140:  * @param string $haystack The string being checked, for the last occurrence of $needle.
 141:  * @param string $needle The string to find in $haystack.
 142:  * @param integer $offset May be specified to begin searching an arbitrary number of characters into the string.
 143:  *    Negative values will stop searching at an arbitrary point prior to the end of the string.
 144:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 145:  * @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string.
 146:  *    If $needle is not found, it returns false.
 147:  */
 148: if (!function_exists('mb_strrpos')) {
 149:     function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) {
 150:         return Multibyte::strrpos($haystack, $needle, $offset);
 151:     }
 152: }
 153: 
 154: /**
 155:  * Finds first occurrence of a string within another
 156:  *
 157:  * @param string $haystack The string from which to get the first occurrence of $needle.
 158:  * @param string $needle The string to find in $haystack
 159:  * @param boolean $part Determines which portion of $haystack this function returns.
 160:  *    If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
 161:  *    If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
 162:  *    Default value is FALSE.
 163:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 164:  * @return string|boolean The portion of $haystack, or true if $needle is not found.
 165:  */
 166: if (!function_exists('mb_strstr')) {
 167:     function mb_strstr($haystack, $needle, $part = false, $encoding = null) {
 168:         return Multibyte::strstr($haystack, $needle, $part);
 169:     }
 170: }
 171: 
 172: /**
 173:  * Make a string lowercase
 174:  *
 175:  * @param string $string The string being lowercased.
 176:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 177:  * @return string with all alphabetic characters converted to lowercase.
 178:  */
 179: if (!function_exists('mb_strtolower')) {
 180:     function mb_strtolower($string, $encoding = null) {
 181:         return Multibyte::strtolower($string);
 182:     }
 183: }
 184: 
 185: /**
 186:  * Make a string uppercase
 187:  *
 188:  * @param string $string The string being uppercased.
 189:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 190:  * @return string with all alphabetic characters converted to uppercase.
 191:  */
 192: if (!function_exists('mb_strtoupper')) {
 193:     function mb_strtoupper($string, $encoding = null) {
 194:         return Multibyte::strtoupper($string);
 195:     }
 196: }
 197: 
 198: /**
 199:  * Count the number of substring occurrences
 200:  *
 201:  * @param string $haystack The string being checked.
 202:  * @param string $needle The string being found.
 203:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 204:  * @return integer The number of times the $needle substring occurs in the $haystack string.
 205:  */
 206: if (!function_exists('mb_substr_count')) {
 207:     function mb_substr_count($haystack, $needle, $encoding = null) {
 208:         return Multibyte::substrCount($haystack, $needle);
 209:     }
 210: }
 211: 
 212: /**
 213:  * Get part of string
 214:  *
 215:  * @param string $string The string being checked.
 216:  * @param integer $start The first position used in $string.
 217:  * @param integer $length The maximum length of the returned string.
 218:  * @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
 219:  * @return string The portion of $string specified by the $string and $length parameters.
 220:  */
 221: if (!function_exists('mb_substr')) {
 222:     function mb_substr($string, $start, $length = null, $encoding = null) {
 223:         return Multibyte::substr($string, $start, $length);
 224:     }
 225: }
 226: 
 227: /**
 228:  * Encode string for MIME header
 229:  *
 230:  * @param string $str The string being encoded
 231:  * @param string $charset specifies the name of the character set in which str is represented in.
 232:  *    The default value is determined by the current NLS setting (mbstring.language).
 233:  * @param string $transfer_encoding specifies the scheme of MIME encoding.
 234:  *    It should be either "B" (Base64) or "Q" (Quoted-Printable). Falls back to "B" if not given.
 235:  * @param string $linefeed specifies the EOL (end-of-line) marker with which
 236:  *    mb_encode_mimeheader() performs line-folding
 237:  *    (a ยป RFC term, the act of breaking a line longer than a certain length into multiple lines.
 238:  *    The length is currently hard-coded to 74 characters). Falls back to "\r\n" (CRLF) if not given.
 239:  * @param integer $indent [definition unknown and appears to have no affect]
 240:  * @return string A converted version of the string represented in ASCII.
 241:  */
 242: if (!function_exists('mb_encode_mimeheader')) {
 243:     function mb_encode_mimeheader($str, $charset = 'UTF-8', $transfer_encoding = 'B', $linefeed = "\r\n", $indent = 1) {
 244:         return Multibyte::mimeEncode($str, $charset, $linefeed);
 245:     }
 246: }
 247: 
 248: /**
 249:  * Multibyte handling methods.
 250:  *
 251:  *
 252:  * @package       Cake.I18n
 253:  */
 254: class Multibyte {
 255: 
 256: /**
 257:  *  Holds the case folding values
 258:  *
 259:  * @var array
 260:  */
 261:     protected static $_caseFold = array();
 262: 
 263: /**
 264:  * Holds an array of Unicode code point ranges
 265:  *
 266:  * @var array
 267:  */
 268:     protected static $_codeRange = array();
 269: 
 270: /**
 271:  * Holds the current code point range
 272:  *
 273:  * @var string
 274:  */
 275:     protected static $_table = null;
 276: 
 277: /**
 278:  * Converts a multibyte character string
 279:  * to the decimal value of the character
 280:  *
 281:  * @param string $string
 282:  * @return array
 283:  */
 284:     public static function utf8($string) {
 285:         $map = array();
 286: 
 287:         $values = array();
 288:         $find = 1;
 289:         $length = strlen($string);
 290: 
 291:         for ($i = 0; $i < $length; $i++) {
 292:             $value = ord($string[$i]);
 293: 
 294:             if ($value < 128) {
 295:                 $map[] = $value;
 296:             } else {
 297:                 if (empty($values)) {
 298:                     $find = ($value < 224) ? 2 : 3;
 299:                 }
 300:                 $values[] = $value;
 301: 
 302:                 if (count($values) === $find) {
 303:                     if ($find == 3) {
 304:                         $map[] = (($values[0] % 16) * 4096) + (($values[1] % 64) * 64) + ($values[2] % 64);
 305:                     } else {
 306:                         $map[] = (($values[0] % 32) * 64) + ($values[1] % 64);
 307:                     }
 308:                     $values = array();
 309:                     $find = 1;
 310:                 }
 311:             }
 312:         }
 313:         return $map;
 314:     }
 315: 
 316: /**
 317:  * Converts the decimal value of a multibyte character string
 318:  * to a string
 319:  *
 320:  * @param array $array
 321:  * @return string
 322:  */
 323:     public static function ascii($array) {
 324:         $ascii = '';
 325: 
 326:         foreach ($array as $utf8) {
 327:             if ($utf8 < 128) {
 328:                 $ascii .= chr($utf8);
 329:             } elseif ($utf8 < 2048) {
 330:                 $ascii .= chr(192 + (($utf8 - ($utf8 % 64)) / 64));
 331:                 $ascii .= chr(128 + ($utf8 % 64));
 332:             } else {
 333:                 $ascii .= chr(224 + (($utf8 - ($utf8 % 4096)) / 4096));
 334:                 $ascii .= chr(128 + ((($utf8 % 4096) - ($utf8 % 64)) / 64));
 335:                 $ascii .= chr(128 + ($utf8 % 64));
 336:             }
 337:         }
 338:         return $ascii;
 339:     }
 340: 
 341: /**
 342:  * Find position of first occurrence of a case-insensitive string.
 343:  *
 344:  * @param string $haystack The string from which to get the position of the first occurrence of $needle.
 345:  * @param string $needle The string to find in $haystack.
 346:  * @param integer $offset The position in $haystack to start searching.
 347:  * @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string,
 348:  *    or false if $needle is not found.
 349:  */
 350:     public static function stripos($haystack, $needle, $offset = 0) {
 351:         if (Multibyte::checkMultibyte($haystack)) {
 352:             $haystack = Multibyte::strtoupper($haystack);
 353:             $needle = Multibyte::strtoupper($needle);
 354:             return Multibyte::strpos($haystack, $needle, $offset);
 355:         }
 356:         return stripos($haystack, $needle, $offset);
 357:     }
 358: 
 359: /**
 360:  * Finds first occurrence of a string within another, case insensitive.
 361:  *
 362:  * @param string $haystack The string from which to get the first occurrence of $needle.
 363:  * @param string $needle The string to find in $haystack.
 364:  * @param boolean $part Determines which portion of $haystack this function returns.
 365:  *    If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
 366:  *    If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
 367:  *    Default value is false.
 368:  * @return integer|boolean The portion of $haystack, or false if $needle is not found.
 369:  */
 370:     public static function stristr($haystack, $needle, $part = false) {
 371:         $php = (PHP_VERSION < 5.3);
 372: 
 373:         if (($php && $part) || Multibyte::checkMultibyte($haystack)) {
 374:             $check = Multibyte::strtoupper($haystack);
 375:             $check = Multibyte::utf8($check);
 376:             $found = false;
 377: 
 378:             $haystack = Multibyte::utf8($haystack);
 379:             $haystackCount = count($haystack);
 380: 
 381:             $needle = Multibyte::strtoupper($needle);
 382:             $needle = Multibyte::utf8($needle);
 383:             $needleCount = count($needle);
 384: 
 385:             $parts = array();
 386:             $position = 0;
 387: 
 388:             while (($found === false) && ($position < $haystackCount)) {
 389:                 if (isset($needle[0]) && $needle[0] === $check[$position]) {
 390:                     for ($i = 1; $i < $needleCount; $i++) {
 391:                         if ($needle[$i] !== $check[$position + $i]) {
 392:                             break;
 393:                         }
 394:                     }
 395:                     if ($i === $needleCount) {
 396:                         $found = true;
 397:                     }
 398:                 }
 399:                 if (!$found) {
 400:                     $parts[] = $haystack[$position];
 401:                     unset($haystack[$position]);
 402:                 }
 403:                 $position++;
 404:             }
 405: 
 406:             if ($found && $part && !empty($parts)) {
 407:                 return Multibyte::ascii($parts);
 408:             } elseif ($found && !empty($haystack)) {
 409:                 return Multibyte::ascii($haystack);
 410:             }
 411:             return false;
 412:         }
 413: 
 414:         if (!$php) {
 415:             return stristr($haystack, $needle, $part);
 416:         }
 417:         return stristr($haystack, $needle);
 418:     }
 419: 
 420: /**
 421:  * Get string length.
 422:  *
 423:  * @param string $string The string being checked for length.
 424:  * @return integer The number of characters in string $string
 425:  */
 426:     public static function strlen($string) {
 427:         if (Multibyte::checkMultibyte($string)) {
 428:             $string = Multibyte::utf8($string);
 429:             return count($string);
 430:         }
 431:         return strlen($string);
 432:     }
 433: 
 434: /**
 435:  * Find position of first occurrence of a string.
 436:  *
 437:  * @param string $haystack The string being checked.
 438:  * @param string $needle The position counted from the beginning of haystack.
 439:  * @param integer $offset The search offset. If it is not specified, 0 is used.
 440:  * @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string.
 441:  *    If $needle is not found, it returns false.
 442:  */
 443:     public static function strpos($haystack, $needle, $offset = 0) {
 444:         if (Multibyte::checkMultibyte($haystack)) {
 445:             $found = false;
 446: 
 447:             $haystack = Multibyte::utf8($haystack);
 448:             $haystackCount = count($haystack);
 449: 
 450:             $needle = Multibyte::utf8($needle);
 451:             $needleCount = count($needle);
 452: 
 453:             $position = $offset;
 454: 
 455:             while (($found === false) && ($position < $haystackCount)) {
 456:                 if (isset($needle[0]) && $needle[0] === $haystack[$position]) {
 457:                     for ($i = 1; $i < $needleCount; $i++) {
 458:                         if ($needle[$i] !== $haystack[$position + $i]) {
 459:                             break;
 460:                         }
 461:                     }
 462:                     if ($i === $needleCount) {
 463:                         $found = true;
 464:                         $position--;
 465:                     }
 466:                 }
 467:                 $position++;
 468:             }
 469:             if ($found) {
 470:                 return $position;
 471:             }
 472:             return false;
 473:         }
 474:         return strpos($haystack, $needle, $offset);
 475:     }
 476: 
 477: /**
 478:  * Finds the last occurrence of a character in a string within another.
 479:  *
 480:  * @param string $haystack The string from which to get the last occurrence of $needle.
 481:  * @param string $needle The string to find in $haystack.
 482:  * @param boolean $part Determines which portion of $haystack this function returns.
 483:  *    If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
 484:  *    If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
 485:  *    Default value is false.
 486:  * @return string|boolean The portion of $haystack. or false if $needle is not found.
 487:  */
 488:     public static function strrchr($haystack, $needle, $part = false) {
 489:         $check = Multibyte::utf8($haystack);
 490:         $found = false;
 491: 
 492:         $haystack = Multibyte::utf8($haystack);
 493:         $haystackCount = count($haystack);
 494: 
 495:         $matches = array_count_values($check);
 496: 
 497:         $needle = Multibyte::utf8($needle);
 498:         $needleCount = count($needle);
 499: 
 500:         $parts = array();
 501:         $position = 0;
 502: 
 503:         while (($found === false) && ($position < $haystackCount)) {
 504:             if (isset($needle[0]) && $needle[0] === $check[$position]) {
 505:                 for ($i = 1; $i < $needleCount; $i++) {
 506:                     if ($needle[$i] !== $check[$position + $i]) {
 507:                         if ($needle[$i] === $check[($position + $i) -1]) {
 508:                             $found = true;
 509:                         }
 510:                         unset($parts[$position - 1]);
 511:                         $haystack = array_merge(array($haystack[$position]), $haystack);
 512:                         break;
 513:                     }
 514:                 }
 515:                 if (isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) {
 516:                     $matches[$needle[0]] = $matches[$needle[0]] - 1;
 517:                 } elseif ($i === $needleCount) {
 518:                     $found = true;
 519:                 }
 520:             }
 521: 
 522:             if (!$found && isset($haystack[$position])) {
 523:                 $parts[] = $haystack[$position];
 524:                 unset($haystack[$position]);
 525:             }
 526:             $position++;
 527:         }
 528: 
 529:         if ($found && $part && !empty($parts)) {
 530:             return Multibyte::ascii($parts);
 531:         } elseif ($found && !empty($haystack)) {
 532:             return Multibyte::ascii($haystack);
 533:         }
 534:         return false;
 535:     }
 536: 
 537: /**
 538:  * Finds the last occurrence of a character in a string within another, case insensitive.
 539:  *
 540:  * @param string $haystack The string from which to get the last occurrence of $needle.
 541:  * @param string $needle The string to find in $haystack.
 542:  * @param boolean $part Determines which portion of $haystack this function returns.
 543:  *    If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
 544:  *    If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
 545:  *    Default value is false.
 546:  * @return string|boolean The portion of $haystack. or false if $needle is not found.
 547:  */
 548:     public static function strrichr($haystack, $needle, $part = false) {
 549:         $check = Multibyte::strtoupper($haystack);
 550:         $check = Multibyte::utf8($check);
 551:         $found = false;
 552: 
 553:         $haystack = Multibyte::utf8($haystack);
 554:         $haystackCount = count($haystack);
 555: 
 556:         $matches = array_count_values($check);
 557: 
 558:         $needle = Multibyte::strtoupper($needle);
 559:         $needle = Multibyte::utf8($needle);
 560:         $needleCount = count($needle);
 561: 
 562:         $parts = array();
 563:         $position = 0;
 564: 
 565:         while (($found === false) && ($position < $haystackCount)) {
 566:             if (isset($needle[0]) && $needle[0] === $check[$position]) {
 567:                 for ($i = 1; $i < $needleCount; $i++) {
 568:                     if ($needle[$i] !== $check[$position + $i]) {
 569:                         if ($needle[$i] === $check[($position + $i) -1]) {
 570:                             $found = true;
 571:                         }
 572:                         unset($parts[$position - 1]);
 573:                         $haystack = array_merge(array($haystack[$position]), $haystack);
 574:                         break;
 575:                     }
 576:                 }
 577:                 if (isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) {
 578:                     $matches[$needle[0]] = $matches[$needle[0]] - 1;
 579:                 } elseif ($i === $needleCount) {
 580:                     $found = true;
 581:                 }
 582:             }
 583: 
 584:             if (!$found && isset($haystack[$position])) {
 585:                 $parts[] = $haystack[$position];
 586:                 unset($haystack[$position]);
 587:             }
 588:             $position++;
 589:         }
 590: 
 591:         if ($found && $part && !empty($parts)) {
 592:             return Multibyte::ascii($parts);
 593:         } elseif ($found && !empty($haystack)) {
 594:             return Multibyte::ascii($haystack);
 595:         }
 596:         return false;
 597:     }
 598: 
 599: /**
 600:  * Finds position of last occurrence of a string within another, case insensitive
 601:  *
 602:  * @param string $haystack The string from which to get the position of the last occurrence of $needle.
 603:  * @param string $needle The string to find in $haystack.
 604:  * @param integer $offset The position in $haystack to start searching.
 605:  * @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string,
 606:  *    or false if $needle is not found.
 607:  */
 608:     public static function strripos($haystack, $needle, $offset = 0) {
 609:         if (Multibyte::checkMultibyte($haystack)) {
 610:             $found = false;
 611:             $haystack = Multibyte::strtoupper($haystack);
 612:             $haystack = Multibyte::utf8($haystack);
 613:             $haystackCount = count($haystack);
 614: 
 615:             $matches = array_count_values($haystack);
 616: 
 617:             $needle = Multibyte::strtoupper($needle);
 618:             $needle = Multibyte::utf8($needle);
 619:             $needleCount = count($needle);
 620: 
 621:             $position = $offset;
 622: 
 623:             while (($found === false) && ($position < $haystackCount)) {
 624:                 if (isset($needle[0]) && $needle[0] === $haystack[$position]) {
 625:                     for ($i = 1; $i < $needleCount; $i++) {
 626:                         if ($needle[$i] !== $haystack[$position + $i]) {
 627:                             if ($needle[$i] === $haystack[($position + $i) -1]) {
 628:                                 $position--;
 629:                                 $found = true;
 630:                                 continue;
 631:                             }
 632:                         }
 633:                     }
 634: 
 635:                     if (!$offset && isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) {
 636:                         $matches[$needle[0]] = $matches[$needle[0]] - 1;
 637:                     } elseif ($i === $needleCount) {
 638:                         $found = true;
 639:                         $position--;
 640:                     }
 641:                 }
 642:                 $position++;
 643:             }
 644:             return ($found) ? $position : false;
 645:         }
 646:         return strripos($haystack, $needle, $offset);
 647:     }
 648: 
 649: /**
 650:  * Find position of last occurrence of a string in a string.
 651:  *
 652:  * @param string $haystack The string being checked, for the last occurrence of $needle.
 653:  * @param string $needle The string to find in $haystack.
 654:  * @param integer $offset May be specified to begin searching an arbitrary number of characters into the string.
 655:  *    Negative values will stop searching at an arbitrary point prior to the end of the string.
 656:  * @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string.
 657:  *    If $needle is not found, it returns false.
 658:  */
 659:     public static function strrpos($haystack, $needle, $offset = 0) {
 660:         if (Multibyte::checkMultibyte($haystack)) {
 661:             $found = false;
 662: 
 663:             $haystack = Multibyte::utf8($haystack);
 664:             $haystackCount = count($haystack);
 665: 
 666:             $matches = array_count_values($haystack);
 667: 
 668:             $needle = Multibyte::utf8($needle);
 669:             $needleCount = count($needle);
 670: 
 671:             $position = $offset;
 672: 
 673:             while (($found === false) && ($position < $haystackCount)) {
 674:                 if (isset($needle[0]) && $needle[0] === $haystack[$position]) {
 675:                     for ($i = 1; $i < $needleCount; $i++) {
 676:                         if ($needle[$i] !== $haystack[$position + $i]) {
 677:                             if ($needle[$i] === $haystack[($position + $i) -1]) {
 678:                                 $position--;
 679:                                 $found = true;
 680:                                 continue;
 681:                             }
 682:                         }
 683:                     }
 684: 
 685:                     if (!$offset && isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) {
 686:                         $matches[$needle[0]] = $matches[$needle[0]] - 1;
 687:                     } elseif ($i === $needleCount) {
 688:                         $found = true;
 689:                         $position--;
 690:                     }
 691:                 }
 692:                 $position++;
 693:             }
 694:             return ($found) ? $position : false;
 695:         }
 696:         return strrpos($haystack, $needle, $offset);
 697:     }
 698: 
 699: /**
 700:  * Finds first occurrence of a string within another
 701:  *
 702:  * @param string $haystack The string from which to get the first occurrence of $needle.
 703:  * @param string $needle The string to find in $haystack
 704:  * @param boolean $part Determines which portion of $haystack this function returns.
 705:  *    If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
 706:  *    If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
 707:  *    Default value is FALSE.
 708:  * @return string|boolean The portion of $haystack, or true if $needle is not found.
 709:  */
 710:     public static function strstr($haystack, $needle, $part = false) {
 711:         $php = (PHP_VERSION < 5.3);
 712: 
 713:         if (($php && $part) || Multibyte::checkMultibyte($haystack)) {
 714:             $check = Multibyte::utf8($haystack);
 715:             $found = false;
 716: 
 717:             $haystack = Multibyte::utf8($haystack);
 718:             $haystackCount = count($haystack);
 719: 
 720:             $needle = Multibyte::utf8($needle);
 721:             $needleCount = count($needle);
 722: 
 723:             $parts = array();
 724:             $position = 0;
 725: 
 726:             while (($found === false) && ($position < $haystackCount)) {
 727:                 if (isset($needle[0]) && $needle[0] === $check[$position]) {
 728:                     for ($i = 1; $i < $needleCount; $i++) {
 729:                         if ($needle[$i] !== $check[$position + $i]) {
 730:                             break;
 731:                         }
 732:                     }
 733:                     if ($i === $needleCount) {
 734:                         $found = true;
 735:                     }
 736:                 }
 737:                 if (!$found) {
 738:                     $parts[] = $haystack[$position];
 739:                     unset($haystack[$position]);
 740:                 }
 741:                 $position++;
 742:             }
 743: 
 744:             if ($found && $part && !empty($parts)) {
 745:                 return Multibyte::ascii($parts);
 746:             } elseif ($found && !empty($haystack)) {
 747:                 return Multibyte::ascii($haystack);
 748:             }
 749:             return false;
 750:         }
 751: 
 752:         if (!$php) {
 753:             return strstr($haystack, $needle, $part);
 754:         }
 755:         return strstr($haystack, $needle);
 756:     }
 757: 
 758: /**
 759:  * Make a string lowercase
 760:  *
 761:  * @param string $string The string being lowercased.
 762:  * @return string with all alphabetic characters converted to lowercase.
 763:  */
 764:     public static function strtolower($string) {
 765:         $utf8Map = Multibyte::utf8($string);
 766: 
 767:         $length = count($utf8Map);
 768:         $lowerCase = array();
 769: 
 770:         for ($i = 0 ; $i < $length; $i++) {
 771:             $char = $utf8Map[$i];
 772: 
 773:             if ($char < 128) {
 774:                 $str = strtolower(chr($char));
 775:                 $strlen = strlen($str);
 776:                 for ($ii = 0 ; $ii < $strlen; $ii++) {
 777:                     $lower = ord(substr($str, $ii, 1));
 778:                 }
 779:                 $lowerCase[] = $lower;
 780:                 $matched = true;
 781:             } else {
 782:                 $matched = false;
 783:                 $keys = self::_find($char, 'upper');
 784: 
 785:                 if (!empty($keys)) {
 786:                     foreach ($keys as $key => $value) {
 787:                         if ($keys[$key]['upper'] == $char && count($keys[$key]['lower'][0]) === 1) {
 788:                             $lowerCase[] = $keys[$key]['lower'][0];
 789:                             $matched = true;
 790:                             break 1;
 791:                         }
 792:                     }
 793:                 }
 794:             }
 795:             if ($matched === false) {
 796:                 $lowerCase[] = $char;
 797:             }
 798:         }
 799:         return Multibyte::ascii($lowerCase);
 800:     }
 801: 
 802: /**
 803:  * Make a string uppercase
 804:  *
 805:  * @param string $string The string being uppercased.
 806:  * @return string with all alphabetic characters converted to uppercase.
 807:  */
 808:     public static function strtoupper($string) {
 809:         $utf8Map = Multibyte::utf8($string);
 810: 
 811:         $length = count($utf8Map);
 812:         $replaced = array();
 813:         $upperCase = array();
 814: 
 815:         for ($i = 0 ; $i < $length; $i++) {
 816:             $char = $utf8Map[$i];
 817: 
 818:             if ($char < 128) {
 819:                 $str = strtoupper(chr($char));
 820:                 $strlen = strlen($str);
 821:                 for ($ii = 0 ; $ii < $strlen; $ii++) {
 822:                     $upper = ord(substr($str, $ii, 1));
 823:                 }
 824:                 $upperCase[] = $upper;
 825:                 $matched = true;
 826: 
 827:             } else {
 828:                 $matched = false;
 829:                 $keys = self::_find($char);
 830:                 $keyCount = count($keys);
 831: 
 832:                 if (!empty($keys)) {
 833:                     foreach ($keys as $key => $value) {
 834:                         $matched = false;
 835:                         $replace = 0;
 836:                         if ($length > 1 && count($keys[$key]['lower']) > 1) {
 837:                             $j = 0;
 838: 
 839:                             for ($ii = 0, $count = count($keys[$key]['lower']); $ii < $count; $ii++) {
 840:                                 $nextChar = $utf8Map[$i + $ii];
 841: 
 842:                                 if (isset($nextChar) && ($nextChar == $keys[$key]['lower'][$j + $ii])) {
 843:                                     $replace++;
 844:                                 }
 845:                             }
 846:                             if ($replace == $count) {
 847:                                 $upperCase[] = $keys[$key]['upper'];
 848:                                 $replaced = array_merge($replaced, array_values($keys[$key]['lower']));
 849:                                 $matched = true;
 850:                                 break 1;
 851:                             }
 852:                         } elseif ($length > 1 && $keyCount > 1) {
 853:                             $j = 0;
 854:                             for ($ii = 1; $ii < $keyCount; $ii++) {
 855:                                 $nextChar = $utf8Map[$i + $ii - 1];
 856: 
 857:                                 if (in_array($nextChar, $keys[$ii]['lower'])) {
 858: 
 859:                                     for ($jj = 0, $count = count($keys[$ii]['lower']); $jj < $count; $jj++) {
 860:                                         $nextChar = $utf8Map[$i + $jj];
 861: 
 862:                                         if (isset($nextChar) && ($nextChar == $keys[$ii]['lower'][$j + $jj])) {
 863:                                             $replace++;
 864:                                         }
 865:                                     }
 866:                                     if ($replace == $count) {
 867:                                         $upperCase[] = $keys[$ii]['upper'];
 868:                                         $replaced = array_merge($replaced, array_values($keys[$ii]['lower']));
 869:                                         $matched = true;
 870:                                         break 2;
 871:                                     }
 872:                                 }
 873:                             }
 874:                         }
 875:                         if ($keys[$key]['lower'][0] == $char) {
 876:                             $upperCase[] = $keys[$key]['upper'];
 877:                             $matched = true;
 878:                             break 1;
 879:                         }
 880:                     }
 881:                 }
 882:             }
 883:             if ($matched === false && !in_array($char, $replaced, true)) {
 884:                 $upperCase[] = $char;
 885:             }
 886:         }
 887:         return Multibyte::ascii($upperCase);
 888:     }
 889: 
 890: /**
 891:  * Count the number of substring occurrences
 892:  *
 893:  * @param string $haystack The string being checked.
 894:  * @param string $needle The string being found.
 895:  * @return integer The number of times the $needle substring occurs in the $haystack string.
 896:  */
 897:     public static function substrCount($haystack, $needle) {
 898:         $count = 0;
 899:         $haystack = Multibyte::utf8($haystack);
 900:         $haystackCount = count($haystack);
 901:         $matches = array_count_values($haystack);
 902:         $needle = Multibyte::utf8($needle);
 903:         $needleCount = count($needle);
 904: 
 905:         if ($needleCount === 1 && isset($matches[$needle[0]])) {
 906:             return $matches[$needle[0]];
 907:         }
 908: 
 909:         for ($i = 0; $i < $haystackCount; $i++) {
 910:             if (isset($needle[0]) && $needle[0] === $haystack[$i]) {
 911:                 for ($ii = 1; $ii < $needleCount; $ii++) {
 912:                     if ($needle[$ii] === $haystack[$i + 1]) {
 913:                         if ((isset($needle[$ii + 1]) && $haystack[$i + 2]) && $needle[$ii + 1] !== $haystack[$i + 2]) {
 914:                             $count--;
 915:                         } else {
 916:                             $count++;
 917:                         }
 918:                     }
 919:                 }
 920:             }
 921:         }
 922:         return $count;
 923:     }
 924: 
 925: /**
 926:  * Get part of string
 927:  *
 928:  * @param string $string The string being checked.
 929:  * @param integer $start The first position used in $string.
 930:  * @param integer $length The maximum length of the returned string.
 931:  * @return string The portion of $string specified by the $string and $length parameters.
 932:  */
 933:     public static function substr($string, $start, $length = null) {
 934:         if ($start === 0 && $length === null) {
 935:             return $string;
 936:         }
 937: 
 938:         $string = Multibyte::utf8($string);
 939: 
 940:         for ($i = 1; $i <= $start; $i++) {
 941:             unset($string[$i - 1]);
 942:         }
 943: 
 944:         if ($length === null || count($string) < $length) {
 945:             return Multibyte::ascii($string);
 946:         }
 947:         $string = array_values($string);
 948: 
 949:         $value = array();
 950:         for ($i = 0; $i < $length; $i++) {
 951:             $value[] = $string[$i];
 952:         }
 953:         return Multibyte::ascii($value);
 954:     }
 955: 
 956: /**
 957:  * Prepare a string for mail transport, using the provided encoding
 958:  *
 959:  * @param string $string value to encode
 960:  * @param string $charset charset to use for encoding. defaults to UTF-8
 961:  * @param string $newline
 962:  * @return string
 963:  * @TODO: add support for 'Q'('Quoted Printable') encoding
 964:  */
 965:     public static function mimeEncode($string, $charset = null, $newline = "\r\n") {
 966:         if (!Multibyte::checkMultibyte($string) && strlen($string) < 75) {
 967:             return $string;
 968:         }
 969: 
 970:         if (empty($charset)) {
 971:             $charset = Configure::read('App.encoding');
 972:         }
 973:         $charset = strtoupper($charset);
 974: 
 975:         $start = '=?' . $charset . '?B?';
 976:         $end = '?=';
 977:         $spacer = $end . $newline . ' ' . $start;
 978: 
 979:         $length = 75 - strlen($start) - strlen($end);
 980:         $length = $length - ($length % 4);
 981:         if ($charset == 'UTF-8') {
 982:             $parts = array();
 983:             $maxchars = floor(($length * 3) / 4);
 984:             while (strlen($string) > $maxchars) {
 985:                 $i = (int)$maxchars;
 986:                 $test = ord($string[$i]);
 987:                 while ($test >= 128 && $test <= 191) {
 988:                     $i--;
 989:                     $test = ord($string[$i]);
 990:                 }
 991:                 $parts[] = base64_encode(substr($string, 0, $i));
 992:                 $string = substr($string, $i);
 993:             }
 994:             $parts[] = base64_encode($string);
 995:             $string = implode($spacer, $parts);
 996:         } else {
 997:             $string = chunk_split(base64_encode($string), $length, $spacer);
 998:             $string = preg_replace('/' . preg_quote($spacer) . '$/', '', $string);
 999:         }
1000:         return $start . $string . $end;
1001:     }
1002: 
1003: /**
1004:  * Return the Code points range for Unicode characters
1005:  *
1006:  * @param integer $decimal
1007:  * @return string
1008:  */
1009:     protected static function _codepoint($decimal) {
1010:         if ($decimal > 128 && $decimal < 256)  {
1011:             $return = '0080_00ff'; // Latin-1 Supplement
1012:         } elseif ($decimal < 384) {
1013:             $return = '0100_017f'; // Latin Extended-A
1014:         } elseif ($decimal < 592) {
1015:             $return = '0180_024F'; // Latin Extended-B
1016:         } elseif ($decimal < 688) {
1017:             $return = '0250_02af'; // IPA Extensions
1018:         } elseif ($decimal >= 880 && $decimal < 1024) {
1019:             $return = '0370_03ff'; // Greek and Coptic
1020:         } elseif ($decimal < 1280) {
1021:             $return = '0400_04ff'; // Cyrillic
1022:         } elseif ($decimal < 1328) {
1023:             $return = '0500_052f'; // Cyrillic Supplement
1024:         } elseif ($decimal < 1424) {
1025:             $return = '0530_058f'; // Armenian
1026:         } elseif ($decimal >= 7680 && $decimal < 7936) {
1027:             $return = '1e00_1eff'; // Latin Extended Additional
1028:         } elseif ($decimal < 8192) {
1029:             $return = '1f00_1fff'; // Greek Extended
1030:         } elseif ($decimal >= 8448 && $decimal < 8528) {
1031:             $return = '2100_214f'; // Letterlike Symbols
1032:         } elseif ($decimal < 8592) {
1033:             $return = '2150_218f'; // Number Forms
1034:         } elseif ($decimal >= 9312 && $decimal < 9472) {
1035:             $return = '2460_24ff'; // Enclosed Alphanumerics
1036:         } elseif ($decimal >= 11264 && $decimal < 11360) {
1037:             $return = '2c00_2c5f'; // Glagolitic
1038:         } elseif ($decimal < 11392) {
1039:             $return = '2c60_2c7f'; // Latin Extended-C
1040:         } elseif ($decimal < 11520) {
1041:             $return = '2c80_2cff'; // Coptic
1042:         } elseif ($decimal >= 65280 && $decimal < 65520) {
1043:             $return = 'ff00_ffef'; // Halfwidth and Fullwidth Forms
1044:         } else {
1045:             $return = false;
1046:         }
1047:         self::$_codeRange[$decimal] = $return;
1048:         return $return;
1049:     }
1050: 
1051: /**
1052:  * Find the related code folding values for $char
1053:  *
1054:  * @param integer $char decimal value of character
1055:  * @param string $type
1056:  * @return array
1057:  */
1058:     protected static function _find($char, $type = 'lower') {
1059:         $found = array();
1060:         if (!isset(self::$_codeRange[$char])) {
1061:             $range = self::_codepoint($char);
1062:             if ($range === false) {
1063:                 return null;
1064:             }
1065:             if (!Configure::configured('_cake_core_')) {
1066:                 App::uses('PhpReader', 'Configure');
1067:                 Configure::config('_cake_core_', new PhpReader(CAKE . 'Config' . DS));
1068:             }
1069:             Configure::load('unicode' . DS . 'casefolding' . DS . $range, '_cake_core_');
1070:             self::$_caseFold[$range] = Configure::read($range);
1071:             Configure::delete($range);
1072:         }
1073: 
1074:         if (!self::$_codeRange[$char]) {
1075:             return null;
1076:         }
1077:         self::$_table = self::$_codeRange[$char];
1078:         $count = count(self::$_caseFold[self::$_table]);
1079: 
1080:         for ($i = 0; $i < $count; $i++) {
1081:             if ($type === 'lower' && self::$_caseFold[self::$_table][$i][$type][0] === $char) {
1082:                 $found[] = self::$_caseFold[self::$_table][$i];
1083:             } elseif ($type === 'upper' && self::$_caseFold[self::$_table][$i][$type] === $char) {
1084:                 $found[] = self::$_caseFold[self::$_table][$i];
1085:             }
1086:         }
1087:         return $found;
1088:     }
1089: 
1090: /**
1091:  * Check the $string for multibyte characters
1092:  * @param string $string value to test
1093:  * @return boolean
1094:  */
1095:     public static function checkMultibyte($string) {
1096:         $length = strlen($string);
1097: 
1098:         for ($i = 0; $i < $length; $i++ ) {
1099:             $value = ord(($string[$i]));
1100:             if ($value > 128) {
1101:                 return true;
1102:             }
1103:         }
1104:         return false;
1105:     }
1106: }
1107: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs