├── LICENSE ├── README.md ├── composer.json ├── phpstan.neon └── src ├── Strings.php └── helpers.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Sergey Romanenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Strings

2 |

3 | Strings Package provide a fluent, object-oriented interface for working with multibyte string, allowing you to chain multiple string operations together using a more readable syntax compared to traditional PHP strings functions. 4 |

5 | 6 |

7 | License MIT Total downloads GitHub Repo stars GitHub forks Hits of Code 8 |

9 | 10 |
11 | 12 | ### Installation 13 | 14 | #### With [Composer](https://getcomposer.org) 15 | 16 | ``` 17 | composer require glowy/strings 18 | ``` 19 | 20 | ### Resources 21 | * [Documentation](https://awilum.github.io/glowyphp/strings) 22 | 23 | ### Tests 24 | 25 | Run tests 26 | 27 | ``` 28 | ./vendor/bin/pest 29 | ``` 30 | 31 | ### License 32 | [The MIT License (MIT)](https://github.com/glowyphp/strings/blob/master/LICENSE) 33 | Copyright (c) [Sergey Romanenko](https://github.com/Awilum) 34 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "glowy/strings", 3 | "description": "Strings Component provide a fluent, object-oriented interface for working with multibyte string, allowing you to chain multiple string operations together using a more readable syntax compared to traditional PHP strings functions.", 4 | "license": "MIT", 5 | "keywords": [ 6 | "Strings", "strings", "php-strings", "php", "glowy", "glowyphp", "strings-manipulation" 7 | ], 8 | "support": { 9 | "source": "https://github.com/glowyphp/strings", 10 | "issues": "https://github.com/glowyphp/strings/issues" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Sergey Romanenko", 15 | "email": "awilum@msn.com", 16 | "homepage": "https://github.com/Awilum" 17 | } 18 | ], 19 | "require": { 20 | "php": "^8.1", 21 | "ext-json": "*", 22 | "ext-mbstring": "*", 23 | "glowy/macroable": "^4.0" 24 | }, 25 | "autoload":{ 26 | "psr-4": { 27 | "Glowy\\Strings\\": "src/" 28 | }, 29 | "files": [ 30 | "src/helpers.php" 31 | ] 32 | }, 33 | "config": { 34 | "apcu-autoloader": true, 35 | "optimize-autoloader": true, 36 | "platform-check": false, 37 | "sort-packages": true, 38 | "allow-plugins": { 39 | "pestphp/pest-plugin": true, 40 | "dealerdirect/phpcodesniffer-composer-installer": true 41 | } 42 | }, 43 | "require-dev": { 44 | "ext-iconv": "*", 45 | "doctrine/coding-standard": "9.0.0", 46 | "pestphp/pest": "^1.21.1", 47 | "phpstan/phpstan": "^1.8.0", 48 | "symfony/var-dumper": "^6.1.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 1 3 | checkMissingIterableValueType: false 4 | checkGenericClassInNonGenericObjectType: false 5 | paths: 6 | - src 7 | -------------------------------------------------------------------------------- /src/Strings.php: -------------------------------------------------------------------------------- 1 | encoding = mb_internal_encoding(); 164 | } else { 165 | $this->encoding = (string) $encoding; 166 | } 167 | 168 | $this->string = (string) $string; 169 | } 170 | 171 | /** 172 | * Returns the value in $string. 173 | * 174 | * @return string Returns string. 175 | */ 176 | public function __toString(): string 177 | { 178 | return (string) $this->string; 179 | } 180 | 181 | /** 182 | * Create a new stringable object from the given string. 183 | * 184 | * Initializes a Strings object and assigns both $string and $encoding properties 185 | * the supplied values. $string is cast to a string prior to assignment. Throws 186 | * an InvalidArgumentException if the first argument is an array or object 187 | * without a __toString method. 188 | * 189 | * @param mixed $string Value to modify, after being cast to string. Default: '' 190 | * @param string $encoding The character encoding. Default: UTF-8 191 | * 192 | * @return self Returns instance of The Strings class. 193 | */ 194 | public static function create($string = '', string $encoding = 'UTF-8'): self 195 | { 196 | return new Strings($string, $encoding); 197 | } 198 | 199 | /** 200 | * Set the character encoding. 201 | * 202 | * @param string $encoding Character encoding. 203 | * 204 | * @return self Returns instance of The Strings class. 205 | */ 206 | public function setEncoding(string $encoding): self 207 | { 208 | $this->encoding = $encoding; 209 | 210 | return $this; 211 | } 212 | 213 | /** 214 | * Get character encoding. 215 | * 216 | * @return string Returns internal encoding. 217 | */ 218 | public function getEncoding(): string 219 | { 220 | return $this->encoding; 221 | } 222 | 223 | /** 224 | * Removes any leading and traling slashes from a string. 225 | * 226 | * @return self Returns instance of The Strings class. 227 | */ 228 | public function trimSlashes(): self 229 | { 230 | $this->string = (string) $this->trim('/'); 231 | 232 | return $this; 233 | } 234 | 235 | /** 236 | * Reduces multiple slashes in a string to single slashes. 237 | * 238 | * @return self Returns instance of The Strings class. 239 | */ 240 | public function reduceSlashes(): self 241 | { 242 | $this->string = preg_replace('#(?string); 243 | 244 | return $this; 245 | } 246 | 247 | /** 248 | * Removes single and double quotes from a string. 249 | * 250 | * @return self Returns instance of The Strings class. 251 | */ 252 | public function stripQuotes(): self 253 | { 254 | $this->string = str_replace(['"', "'"], '', $this->string); 255 | 256 | return $this; 257 | } 258 | 259 | /** 260 | * Convert single and double quotes to entities. 261 | * 262 | * @param string $string String with single and double quotes 263 | * 264 | * @return self Returns instance of The Strings class. 265 | */ 266 | public function quotesToEntities(): self 267 | { 268 | $this->string = str_replace(["\'", '"', "'", '"'], [''', '"', ''', '"'], $this->string); 269 | 270 | return $this; 271 | } 272 | 273 | /** 274 | * Standardize line endings to unix-like. 275 | * 276 | * @return self Returns instance of The Strings class. 277 | */ 278 | public function normalizeNewLines(): self 279 | { 280 | $this->string = str_replace(["\r\n", "\r"], "\n", $this->string); 281 | 282 | return $this; 283 | } 284 | 285 | /** 286 | * Normalize white-spaces to a single space. 287 | * 288 | * @return self Returns instance of The Strings class. 289 | */ 290 | public function normalizeSpaces(): self 291 | { 292 | $this->string = preg_replace('/\s+/', ' ', $this->string); 293 | 294 | return $this; 295 | } 296 | 297 | /** 298 | * Creates a random string of characters. 299 | * 300 | * @param int $length The number of characters. Default is 16 301 | * @param string $keyspace The keyspace 302 | * 303 | * @return self Returns instance of The Strings class. 304 | */ 305 | public function random(int $length = 64, string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): self 306 | { 307 | if ($length <= 0) { 308 | $length = 1; 309 | } 310 | 311 | $pieces = []; 312 | $max = static::create($keyspace, '8bit')->length() - 1; 313 | 314 | for ($i = 0; $i < $length; ++$i) { 315 | $pieces[] = $keyspace[random_int(0, $max)]; 316 | } 317 | 318 | $this->string = implode('', $pieces); 319 | 320 | return $this; 321 | } 322 | 323 | /** 324 | * Add's _1 to a string or increment the ending number to allow _2, _3, etc. 325 | * 326 | * @param string $separator Separator 327 | * @param int $first Start with 328 | * 329 | * @return self Returns instance of The Strings class. 330 | */ 331 | public function increment(string $separator = '_', int $first = 1): self 332 | { 333 | preg_match('/(.+)' . $separator . '([0-9]+)$/', $this->string, $match); 334 | 335 | $this->string = isset($match[2]) ? $match[1] . $separator . ($match[2] + 1) : $this->string . $separator . $first; 336 | 337 | return $this; 338 | } 339 | 340 | /** 341 | * Returns a repeated string given a multiplier. 342 | * 343 | * @param int $multiplier The number of times to repeat the string. 344 | * 345 | * @return self Returns instance of The Strings class. 346 | */ 347 | public function repeat(int $multiplier): self 348 | { 349 | $this->string = str_repeat($this->string, $multiplier); 350 | 351 | return $this; 352 | } 353 | 354 | /** 355 | * Limit the number of characters in a string. 356 | * 357 | * @param int $limit Limit of characters 358 | * @param string $append Text to append to the string IF it gets truncated 359 | * 360 | * @return self Returns instance of The Strings class. 361 | */ 362 | public function limit(int $limit = 100, string $append = '...'): self 363 | { 364 | if (mb_strwidth($this->string, 'UTF-8') <= $limit) { 365 | $this->string = $this->string; 366 | } else { 367 | $this->string = static::create(mb_strimwidth($this->string, 0, $limit, '', $this->encoding), $this->encoding)->trimRight() . $append; 368 | } 369 | 370 | return $this; 371 | } 372 | 373 | /** 374 | * Masks a portion of a string with a repeated character. 375 | * 376 | * @param string $character Character. 377 | * @param int $index Index. 378 | * @param int|null $length Length. 379 | * 380 | * @return self Returns instance of The Strings class. 381 | */ 382 | public function mask(string $character, int $index, $length = null) 383 | { 384 | if ($character === '') { 385 | return $this->string; 386 | } 387 | 388 | if ($length === null) { 389 | $length = mb_strlen($this->string, $this->encoding); 390 | } 391 | 392 | $segment = static::create($this->string, $this->encoding)->substr($index, $length)->toString(); 393 | 394 | if ($segment === '') { 395 | return $this->string; 396 | } 397 | 398 | $start = mb_substr($this->toString(), 0, mb_strpos($this->toString(), $segment, 0, $this->encoding), $this->encoding); 399 | $end = mb_substr($this->toString(), mb_strpos($this->toString(), $segment, 0, $this->encoding) + mb_strlen($segment, $this->encoding)); 400 | 401 | return $start . str_repeat(mb_substr($character, 0, 1, $this->encoding), mb_strlen($segment, $this->encoding)) . $end; 402 | } 403 | 404 | /** 405 | * Convert the given string to title case for each word. 406 | * 407 | * @return self Returns instance of The Strings class. 408 | */ 409 | public function headline(): self 410 | { 411 | $parts = static::create($this->string)->replace(' ', '_')->segments('_'); 412 | 413 | $capParts = []; 414 | 415 | if (count($parts) > 1) { 416 | foreach($parts as $part) { 417 | $capParts[] = static::create($part)->capitalize()->toString(); 418 | } 419 | } 420 | 421 | $this->string = implode(' ', preg_split('/(?=[A-Z])/', static::create(implode($capParts))->studly()->toString(), -1, PREG_SPLIT_NO_EMPTY)); 422 | 423 | return $this; 424 | } 425 | 426 | /** 427 | * Transform the given string with random capitalization applied. 428 | * 429 | * @return self Returns instance of The Strings class. 430 | */ 431 | public function sponge(): self 432 | { 433 | $result = ''; 434 | 435 | foreach (static::create($this->string)->chars() as $char) { 436 | if (mt_rand(0, 100) > 50) { 437 | $result .= static::create($char)->upper()->toString(); 438 | } else { 439 | $result .= static::create($char)->lower()->toString(); 440 | } 441 | } 442 | 443 | $this->string = $result; 444 | 445 | return $this; 446 | } 447 | 448 | /** 449 | * Transform the given string by swapping every character from upper to lower case, or lower to upper case. 450 | * 451 | * @return self Returns instance of The Strings class. 452 | */ 453 | public function swap(): self 454 | { 455 | $result = ''; 456 | 457 | foreach (static::create($this->string)->chars() as $char) { 458 | if (static::create($char)->isUpper()) { 459 | $result .= static::create($char)->lower()->toString(); 460 | } else { 461 | $result .= static::create($char)->upper()->toString(); 462 | } 463 | } 464 | 465 | $this->string = $result; 466 | 467 | return $this; 468 | } 469 | 470 | /** 471 | * Convert the given string to lower-case. 472 | * 473 | * @return self Returns instance of The Strings class. 474 | */ 475 | public function lower(): self 476 | { 477 | $this->string = mb_strtolower($this->string, $this->encoding); 478 | 479 | return $this; 480 | } 481 | 482 | /** 483 | * Convert the given string to upper-case. 484 | * 485 | * @return self Returns instance of The Strings class. 486 | */ 487 | public function upper(): self 488 | { 489 | $this->string = mb_strtoupper($this->string, $this->encoding); 490 | 491 | return $this; 492 | } 493 | 494 | /** 495 | * Convert a string to studly caps case. 496 | * 497 | * @return self Returns instance of The Strings class. 498 | */ 499 | public function studly(): self 500 | { 501 | $this->string = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $this->string))); 502 | 503 | return $this; 504 | } 505 | 506 | /** 507 | * Convert a string to snake case. 508 | * 509 | * @param string $delimiter Delimeter 510 | * 511 | * @return self Returns instance of The Strings class. 512 | */ 513 | public function snake(string $delimiter = '_'): self 514 | { 515 | $key = $this->string; 516 | 517 | if (! ctype_lower($this->string)) { 518 | $string = preg_replace('/\s+/u', '', ucwords($this->string)); 519 | $string = static::create(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $string), $this->encoding)->lower(); 520 | 521 | $this->string = $string->toString(); 522 | } 523 | 524 | return $this; 525 | } 526 | 527 | /** 528 | * Convert a string to camel case. 529 | * 530 | * @return self Returns instance of The Strings class. 531 | */ 532 | public function camel(): self 533 | { 534 | $this->string = lcfirst((string) static::create($this->string, $this->encoding)->studly()); 535 | 536 | return $this; 537 | } 538 | 539 | /** 540 | * Convert a string to kebab case. 541 | * 542 | * @return self Returns instance of The Strings class. 543 | */ 544 | public function kebab(): self 545 | { 546 | $this->string = static::create($this->string, $this->encoding)->snake('-')->toString(); 547 | 548 | return $this; 549 | } 550 | 551 | /** 552 | * Limit the number of words in a string. 553 | * 554 | * @param int $words Words limit 555 | * @param string $append Text to append to the string IF it gets truncated 556 | * 557 | * @return self Returns instance of The Strings class. 558 | */ 559 | public function wordsLimit(int $words = 100, string $append = '...'): self 560 | { 561 | preg_match('/^\s*+(?:\S++\s*+){1,' . $words . '}/u', $this->string, $matches); 562 | 563 | if (! isset($matches[0]) || static::create($this->string, $this->encoding)->length() === static::create($matches[0], $this->encoding)->length()) { 564 | $this->string = $this->string; 565 | } 566 | 567 | $this->string = static::create($matches[0], $this->encoding)->trimRight() . $append; 568 | 569 | return $this; 570 | } 571 | 572 | /** 573 | * Get words from the string. 574 | * 575 | * @param string $ignore Ingnore symbols. 576 | * 577 | * @return array Returns words array. 578 | */ 579 | public function words(string $ignore = '?!;:,.'): array 580 | { 581 | $words = preg_split('/[\s' . $ignore . ']+/', $this->string); 582 | 583 | empty(end($words)) and array_pop($words); 584 | 585 | return $words; 586 | } 587 | 588 | /** 589 | * Get array of individual lines in the string. 590 | * 591 | * @return array Returns array of lines. 592 | */ 593 | public function lines(): array 594 | { 595 | $lines = preg_split('/\r\n|\n|\r/', $this->string); 596 | 597 | empty(end($lines)) and array_pop($lines); 598 | 599 | return $lines; 600 | } 601 | 602 | /** 603 | * Returns the length of the string, analog to length(). 604 | * 605 | * @return int Returns string length. 606 | */ 607 | public function count(): int 608 | { 609 | return $this->length(); 610 | } 611 | 612 | /** 613 | * Returns the number of occurrences of $substring in the given string. 614 | * By default, the comparison is case-sensitive, but can be made insensitive 615 | * by setting $caseSensitive to false. 616 | * 617 | * @param string $substring The substring to search. 618 | * @param bool $caseSensitive Whether or not to enforce case-sensitivity. Default is true. 619 | * 620 | * @return int Returns the number of occurrences of $substring in the given string. 621 | */ 622 | public function countSubString(string $substring, bool $caseSensitive = true): int 623 | { 624 | if ($caseSensitive) { 625 | return mb_substr_count($this->string, $substring); 626 | } 627 | 628 | return mb_substr_count( 629 | (string) static::create($this->string, $this->encoding)->lower(), 630 | (string) static::create($substring, $this->encoding)->lower() 631 | ); 632 | } 633 | 634 | /** 635 | * Get words count from the string. 636 | * 637 | * @param string $ignore Ingnore symbols. 638 | * 639 | * @return int Returns words count. 640 | */ 641 | public function wordsCount(string $ignore = '?!;:,.'): int 642 | { 643 | $words = preg_split('/[\s' . $ignore . ']+/', $this->string); 644 | 645 | empty(end($words)) and array_pop($words); 646 | 647 | return count($words); 648 | } 649 | 650 | /** 651 | * Determine if a given string contains a given substring. 652 | * 653 | * @param string|string[] $needles The string to find in haystack. 654 | * @param bool $caseSensitive Whether or not to enforce case-sensitivity. Default is true. 655 | * 656 | * @return bool Returns TRUE on success or FALSE otherwise. 657 | */ 658 | public function contains($needles, bool $caseSensitive = true): bool 659 | { 660 | foreach ((array) $needles as $needle) { 661 | if ($needle !== '' && static::create($this->string, $this->encoding)->indexOf($needle, 0, $caseSensitive) !== false) { 662 | return true; 663 | } 664 | } 665 | 666 | return false; 667 | } 668 | 669 | /** 670 | * Determine if a given string contains all array values. 671 | * 672 | * @param string[] $needles The array of strings to find in haystack. 673 | * @param bool $caseSensitive Whether or not to enforce case-sensitivity. Default is true. 674 | * 675 | * @return bool Returns TRUE on success or FALSE otherwise. 676 | */ 677 | public function containsAll(array $needles, bool $caseSensitive = true): bool 678 | { 679 | foreach ($needles as $needle) { 680 | if (! static::create($this->string, $this->encoding)->contains($needle, $caseSensitive)) { 681 | return false; 682 | } 683 | } 684 | 685 | return true; 686 | } 687 | 688 | /** 689 | * Determine if a given string contains any of array values. 690 | * 691 | * @param string $haystack The string being checked. 692 | * @param string[] $needles The array of strings to find in haystack. 693 | * @param bool $caseSensitive Whether or not to enforce case-sensitivity. Default is true. 694 | * 695 | * @return bool Returns TRUE on success or FALSE otherwise. 696 | */ 697 | public function containsAny(array $needles, bool $caseSensitive = true): bool 698 | { 699 | foreach ($needles as $needle) { 700 | if (static::create($this->string, $this->encoding)->contains($needle, $caseSensitive)) { 701 | return true; 702 | } 703 | } 704 | 705 | return false; 706 | } 707 | 708 | /** 709 | * Converts the first character of a string to upper case 710 | * and leaves the other characters unchanged. 711 | * 712 | * @return self Returns instance of The Strings class. 713 | */ 714 | public function ucfirst(): self 715 | { 716 | $this->string = static::create(static::create($this->string, $this->encoding)->substr(0, 1))->upper() . static::create($this->string, $this->encoding)->substr(1); 717 | 718 | return $this; 719 | } 720 | 721 | /** 722 | * Converts the first character of every word of string to upper case and the others to lower case. 723 | * 724 | * @return self Returns instance of The Strings class. 725 | */ 726 | public function capitalize(): self 727 | { 728 | $this->string = mb_convert_case($this->string, MB_CASE_TITLE, $this->encoding); 729 | 730 | return $this; 731 | } 732 | 733 | /** 734 | * Return the length of the given string. 735 | * 736 | * @return int Returns the length of the given string. 737 | */ 738 | public function length(): int 739 | { 740 | return mb_strlen($this->string, $this->encoding); 741 | } 742 | 743 | /** 744 | * Returns the portion of string specified by the start and length parameters. 745 | * 746 | * @param int $start If start is non-negative, the returned string will 747 | * start at the start'th position in $string, counting from zero. 748 | * For instance, in the string 'abcdef', the character at position 749 | * 0 is 'a', the character at position 2 is 'c', and so forth. 750 | * @param int|null $length Maximum number of characters to use from string. 751 | * If omitted or NULL is passed, extract all characters to the end of the string. 752 | * 753 | * @return self Returns instance of The Strings class. 754 | */ 755 | public function substr(int $start, ?int $length = null): self 756 | { 757 | $this->string = mb_substr($this->string, $start, $length, $this->encoding); 758 | 759 | return $this; 760 | } 761 | 762 | /** 763 | * Returns the index of the first occurrence of $needle in the string, 764 | * and false if not found. Accepts an optional offset from which to begin 765 | * the search. 766 | * 767 | * @param int|string $needle The string to find in haystack. 768 | * @param int $offset The search offset. If it is not specified, 0 is used. 769 | * @param bool $caseSensitive Whether or not to enforce case-sensitivity. Default is true. 770 | * 771 | * @return mixed Returns the index of the first occurrence of $needle in the string, 772 | * and false if not found. 773 | */ 774 | public function indexOf($needle, int $offset = 0, bool $caseSensitive = true) 775 | { 776 | if ($needle === '' || $this->string === '') { 777 | return false; 778 | } 779 | 780 | if ($caseSensitive) { 781 | return mb_strpos((string) $this->string, $needle, $offset, $this->encoding); 782 | } 783 | 784 | return mb_stripos((string) $this->string, $needle, $offset, $this->encoding); 785 | } 786 | 787 | /** 788 | * Returns the index of the last occurrence of $needle in the string, and false if not found. 789 | * Accepts an optional $offset from which to begin the search. Offsets may be negative to 790 | * count from the last character in the string. 791 | * 792 | * @param int|string $needle The string to find in haystack. 793 | * @param int $offset The search offset. If it is not specified, 0 is used. 794 | * @param bool $caseSensitive Whether or not to enforce case-sensitivity. Default is true. 795 | * 796 | * @return mixed Returns the index of the last occurrence of $needle in the string, and false if not found. 797 | */ 798 | public function indexOfLast(string $needle, int $offset = 0, bool $caseSensitive = true) 799 | { 800 | if ($needle === '' || $this->string === '') { 801 | return false; 802 | } 803 | 804 | $max_length = static::create($this->string, $this->encoding)->length(); 805 | 806 | if ($offset < 0) { 807 | $offset = $max_length - (int) abs($offset); 808 | } 809 | 810 | if ($offset > $max_length || $offset < 0) { 811 | return false; 812 | } 813 | 814 | if ($caseSensitive) { 815 | return mb_strrpos((string) $this->string, $needle, $offset, $this->encoding); 816 | } 817 | 818 | return mb_strripos((string) $this->string, $needle, $offset, $this->encoding); 819 | } 820 | 821 | /** 822 | * Strip whitespace (or other characters) from the beginning and end of a string. 823 | * 824 | * @param string $character_mask Stripped characters can also be specified using the character_mask parameter. 825 | * 826 | * @return self Returns instance of The Strings class. 827 | */ 828 | public function trim(string|null $character_mask = null): self 829 | { 830 | $this->string = trim(...array_merge([$this->string], func_get_args())); 831 | 832 | return $this; 833 | } 834 | 835 | /** 836 | * Strip whitespace (or other characters) from the beginning of a string. 837 | * 838 | * @param string $character_mask Stripped characters can also be specified using the character_mask parameter. 839 | * 840 | * @return self Returns instance of The Strings class. 841 | */ 842 | public function trimLeft(string|null $character_mask = null): self 843 | { 844 | $this->string = ltrim(...array_merge([$this->string], func_get_args())); 845 | 846 | return $this; 847 | } 848 | 849 | /** 850 | * Strip whitespace (or other characters) from the end of a string. 851 | * 852 | * @param string|null $character_mask Stripped characters can also be specified using the character_mask parameter. 853 | * 854 | * @return self Returns instance of The Strings class. 855 | */ 856 | public function trimRight(string|null $character_mask = null): self 857 | { 858 | $this->string = rtrim(...array_merge([$this->string], func_get_args())); 859 | 860 | return $this; 861 | } 862 | 863 | /** 864 | * Reverses string. 865 | * 866 | * @return self Returns instance of The Strings class. 867 | */ 868 | public function reverse(): self 869 | { 870 | $result = ''; 871 | 872 | for ($i = static::create($this->string, $this->encoding)->length(); $i >= 0; $i--) { 873 | $result .= (string) static::create($this->string, $this->encoding)->substr($i, 1); 874 | } 875 | 876 | $this->string = $result; 877 | 878 | return $this; 879 | } 880 | 881 | /** 882 | * Get array of segments from a string based on a delimiter. 883 | * 884 | * @param string $delimiter Delimeter 885 | * 886 | * @return array Returns array of segments. 887 | */ 888 | public function segments(string $delimiter = ' '): array 889 | { 890 | return explode($delimiter, $this->string); 891 | } 892 | 893 | /** 894 | * Get a segment from a string based on a delimiter. 895 | * Returns an empty string when the offset doesn't exist. 896 | * Use a negative index to start counting from the last element. 897 | * 898 | * @param int $index Index 899 | * @param string $delimiter Delimeter 900 | * 901 | * @return self Returns instance of The Strings class. 902 | */ 903 | public function segment(int $index, string $delimiter = ' '): self 904 | { 905 | $segments = explode($delimiter, $this->string); 906 | 907 | if ($index < 0) { 908 | $segments = array_reverse($segments); 909 | $index = abs($index) - 1; 910 | } 911 | 912 | $this->string = $segments[$index] ?? ''; 913 | 914 | return $this; 915 | } 916 | 917 | /** 918 | * Get the first segment from a string based on a delimiter. 919 | * 920 | * @param string $delimiter Delimeter 921 | * 922 | * @return self Returns instance of The Strings class. 923 | */ 924 | public function firstSegment(string $delimiter = ' '): self 925 | { 926 | $this->string = (string) $this->segment(0, $delimiter); 927 | 928 | return $this; 929 | } 930 | 931 | /** 932 | * Get the last segment from a string based on a delimiter. 933 | * 934 | * @param string $string String 935 | * @param string $delimiter Delimeter 936 | * 937 | * @return self Returns instance of The Strings class. 938 | */ 939 | public function lastSegment(string $delimiter = ' '): self 940 | { 941 | $this->string = (string) $this->segment(-1, $delimiter); 942 | 943 | return $this; 944 | } 945 | 946 | /** 947 | * Get the portion of a string between two given values. 948 | * 949 | * @param string $from From 950 | * @param string $to To 951 | * 952 | * @return self Returns instance of The Strings class. 953 | */ 954 | public function between(string $from, string $to): self 955 | { 956 | if ($from === '' || $to === '') { 957 | return $this; 958 | } 959 | 960 | $this->string = static::create((string) static::create($this->string, $this->encoding)->after($from), $this->encoding)->beforeLast($to)->toString(); 961 | 962 | return $this; 963 | } 964 | 965 | /** 966 | * Get the portion of a string between first two given values. 967 | * 968 | * @param string $from From 969 | * @param string $to To 970 | * 971 | * @return self Returns instance of The Strings class. 972 | */ 973 | public function betweenFirst(string $from, string $to): self 974 | { 975 | if ($from === '' || $to === '') { 976 | return $this; 977 | } 978 | 979 | $this->string = static::create((string) static::create($this->string, $this->encoding)->after($from), $this->encoding)->before($to)->toString(); 980 | 981 | return $this; 982 | } 983 | 984 | /** 985 | * Get the portion of a string before the first occurrence of a given value. 986 | * 987 | * @param string $search Search 988 | * 989 | * @return self Returns instance of The Strings class. 990 | */ 991 | public function before(string $search): self 992 | { 993 | $search === '' and $this->string = $search; 994 | 995 | $result = strstr($this->string, (string) $search, true); 996 | 997 | $this->string = $result === false ? $search : $result; 998 | 999 | return $this; 1000 | } 1001 | 1002 | /** 1003 | * Get the portion of a string before the last occurrence of a given value. 1004 | * 1005 | * @param string $search Search 1006 | * 1007 | * @return self Returns instance of The Strings class. 1008 | */ 1009 | public function beforeLast(string $search): self 1010 | { 1011 | $position = mb_strrpos($this->string, $search); 1012 | 1013 | if ($position === false) { 1014 | $this->string = $this->string; 1015 | } else { 1016 | $this->string = (string) static::create($this->string, $this->encoding)->substr(0, $position); 1017 | } 1018 | 1019 | return $this; 1020 | } 1021 | 1022 | /** 1023 | * Return the remainder of a string after the first occurrence of a given value. 1024 | * 1025 | * @param string $search Search 1026 | * 1027 | * @return self Returns instance of The Strings class. 1028 | */ 1029 | public function after(string $search): self 1030 | { 1031 | $this->string = $search === '' ? $this->string : array_reverse(explode($search, $this->string, 2))[0]; 1032 | 1033 | return $this; 1034 | } 1035 | 1036 | /** 1037 | * Return the remainder of a string after the last occurrence of a given value. 1038 | * 1039 | * @param string $search Search 1040 | * 1041 | * @return self Returns instance of The Strings class. 1042 | */ 1043 | public function afterLast(string $search): self 1044 | { 1045 | $position = mb_strrpos($this->string, (string) $search); 1046 | 1047 | if ($position === false) { 1048 | $this->string = $this->string; 1049 | } else { 1050 | $this->string = (string) $this->substr($position + static::create($search, $this->encoding)->length()); 1051 | } 1052 | 1053 | return $this; 1054 | } 1055 | 1056 | /** 1057 | * Pad both sides of a string with another. 1058 | * 1059 | * @param int $length If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place, and input will be returned. 1060 | * @param string $pad The pad string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length. 1061 | * 1062 | * @return self Returns instance of The Strings class. 1063 | */ 1064 | public function padBoth(int $length, string $pad = ' '): self 1065 | { 1066 | $this->string = str_pad($this->string, $length, $pad, STR_PAD_BOTH); 1067 | 1068 | return $this; 1069 | } 1070 | 1071 | /** 1072 | * Pad the left side of a string with another. 1073 | * 1074 | * @param int $length If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place, and input will be returned. 1075 | * @param string $pad The pad string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length. 1076 | * 1077 | * @return self Returns instance of The Strings class. 1078 | */ 1079 | public function padLeft(int $length, string $pad = ' '): self 1080 | { 1081 | $this->string = str_pad($this->string, $length, $pad, STR_PAD_LEFT); 1082 | 1083 | return $this; 1084 | } 1085 | 1086 | /** 1087 | * Pad the right side of a string with another. 1088 | * 1089 | * @param int $length If the value of pad_length is negative, less than, or equal to the length of the input string, no padding takes place, and input will be returned. 1090 | * @param string $pad The pad string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length. 1091 | * 1092 | * @return self Returns instance of The Strings class. 1093 | */ 1094 | public function padRight(int $length, string $pad = ' '): self 1095 | { 1096 | $this->string = str_pad($this->string, $length, $pad, STR_PAD_RIGHT); 1097 | 1098 | return $this; 1099 | } 1100 | 1101 | /** 1102 | * Strip all whitespaces from the given string. 1103 | * 1104 | * @return self Returns instance of The Strings class. 1105 | */ 1106 | public function stripSpaces(): self 1107 | { 1108 | $this->string = preg_replace('/\s+/u', '', $this->string); 1109 | 1110 | return $this; 1111 | } 1112 | 1113 | /** 1114 | * Replace all dashes characters in the string with the given value. 1115 | * 1116 | * @param string $replacement Value to replace dashes characters with replacement. Default is '' 1117 | * @param bool $strict Should spaces be preserved or not. Default is false. 1118 | * 1119 | * @return self Returns instance of The Strings class. 1120 | */ 1121 | public function replaceDashes(string $replacement = '', bool $strict = false): self 1122 | { 1123 | $this->string = preg_replace( 1124 | '/\p{Pd}/u', 1125 | $replacement, 1126 | static::create($this->string, $this->encoding)->trim()->toString() 1127 | ); 1128 | 1129 | if ($strict) { 1130 | $this->string = static::create($this->string, $this->encoding) 1131 | ->stripSpaces() 1132 | ->toString(); 1133 | } 1134 | 1135 | return $this; 1136 | } 1137 | 1138 | /** 1139 | * Replace all punctuations characters in the string with the given value. 1140 | * 1141 | * @param string $replacement Value to replace punctuations characters with replacement. Default is '' 1142 | * @param bool $strict Should spaces be preserved or not. Default is false. 1143 | * 1144 | * @return self Returns instance of The Strings class. 1145 | */ 1146 | public function replacePunctuations(string $replacement = '', bool $strict = false): self 1147 | { 1148 | $this->string = preg_replace( 1149 | '/\p{P}/u', 1150 | $replacement, 1151 | static::create($this->string, $this->encoding)->trim()->toString() 1152 | ); 1153 | 1154 | if ($strict) { 1155 | $this->string = static::create($this->string, $this->encoding) 1156 | ->stripSpaces() 1157 | ->toString(); 1158 | } 1159 | 1160 | return $this; 1161 | } 1162 | 1163 | /** 1164 | * Replace none alphanumeric characters in the string with the given value. 1165 | * 1166 | * @param string $replacement Value to replace none alphanumeric characters with. Default is '' 1167 | * @param bool $strict Should spaces be preserved or not. Default is false. 1168 | * 1169 | * @return self Returns instance of The Strings class. 1170 | */ 1171 | public function replaceNonAlphanumeric(string $replacement = '', bool $strict = false): self 1172 | { 1173 | $this->string = preg_replace( 1174 | '/[^\p{L}0-9\s]+/u', 1175 | $replacement, 1176 | static::create($this->string, $this->encoding)->trim()->toString() 1177 | ); 1178 | 1179 | if ($strict) { 1180 | $this->string = static::create($this->string, $this->encoding) 1181 | ->stripSpaces() 1182 | ->toString(); 1183 | } 1184 | 1185 | return $this; 1186 | } 1187 | 1188 | /** 1189 | * Replace none alpha characters in the string with the given value. 1190 | * 1191 | * @param string $replacement Value to replace none alpha characters with 1192 | * @param bool $strict Should spaces be preserved or not. Default is false. 1193 | * 1194 | * @return self Returns instance of The Strings class. 1195 | */ 1196 | public function replaceNonAlpha(string $replacement = '', bool $strict = false): self 1197 | { 1198 | $this->string = preg_replace( 1199 | '/[^\p{L}\s]+/u', 1200 | $replacement, 1201 | static::create($this->string, $this->encoding) 1202 | ->trim() 1203 | ->toString() 1204 | ); 1205 | 1206 | if ($strict) { 1207 | $this->string = static::create($this->string, $this->encoding) 1208 | ->stripSpaces() 1209 | ->toString(); 1210 | } 1211 | 1212 | return $this; 1213 | } 1214 | 1215 | /** 1216 | * Replace the given value within a portion of a string. 1217 | * 1218 | * @param string|array $replace The replacement string. 1219 | * @param array|int $offset Offset. 1220 | * @param array|int|null $length Length. 1221 | * 1222 | * @return self Returns instance of The Strings class. 1223 | */ 1224 | public function replaceSubstr($replace, $offset = 0, $length = null): self 1225 | { 1226 | if ($length === null) { 1227 | $length = mb_strlen($this->string); 1228 | } 1229 | 1230 | $this->string = mb_substr($this->string, 0, $offset, $this->encoding) . 1231 | $replace . 1232 | mb_substr($this->string, $offset + $length, mb_strlen($this->string, $this->encoding), $this->encoding); 1233 | 1234 | return $this; 1235 | } 1236 | 1237 | /** 1238 | * Replace the given value in the given string. 1239 | * 1240 | * @param string $search Search 1241 | * @param mixed $replace Replace 1242 | * 1243 | * @return self Returns instance of The Strings class. 1244 | */ 1245 | public function replace(string $search, $replace): self 1246 | { 1247 | $this->string = str_replace($search, $replace, $this->string); 1248 | 1249 | return $this; 1250 | } 1251 | 1252 | /** 1253 | * Replace a given value in the string sequentially with an array. 1254 | * 1255 | * @param string $search Search 1256 | * @param array $replace Replace 1257 | * 1258 | * @return self Returns instance of The Strings class. 1259 | */ 1260 | public function replaceArray(string $search, array $replace): self 1261 | { 1262 | $segments = explode($search, $this->string); 1263 | 1264 | $result = array_shift($segments); 1265 | 1266 | foreach ($segments as $segment) { 1267 | $result .= (array_shift($replace) ?? $search) . $segment; 1268 | } 1269 | 1270 | $this->string = $result; 1271 | 1272 | return $this; 1273 | } 1274 | 1275 | /** 1276 | * Replace the first occurrence of a given value in the string. 1277 | * 1278 | * @param string $search Search 1279 | * @param string $replace Replace 1280 | * 1281 | * @return self Returns instance of The Strings class. 1282 | */ 1283 | public function replaceFirst(string $search, string $replace): self 1284 | { 1285 | $position = strpos($this->string, $search); 1286 | 1287 | if ($position !== false) { 1288 | $this->string = substr_replace($this->string, $replace, $position, static::create($search, $this->encoding)->length()); 1289 | } else { 1290 | $this->string = $search; 1291 | } 1292 | 1293 | return $this; 1294 | } 1295 | 1296 | /** 1297 | * Replace the last occurrence of a given value in the string. 1298 | * 1299 | * @param string $search Search 1300 | * @param string $replace Replace 1301 | * 1302 | * @return self Returns instance of The Strings class. 1303 | */ 1304 | public function replaceLast(string $search, string $replace): self 1305 | { 1306 | $position = strrpos($this->string, $search); 1307 | 1308 | if ($position !== false) { 1309 | $this->string = substr_replace($this->string, $replace, $position, static::create($search, $this->encoding)->length()); 1310 | } else { 1311 | $this->string = $search; 1312 | } 1313 | 1314 | return $this; 1315 | } 1316 | 1317 | /** 1318 | * Begin a string with a single instance of a given value. 1319 | * 1320 | * @param string $prefix Prefix 1321 | * 1322 | * @return self Returns instance of The Strings class. 1323 | */ 1324 | public function start(string $prefix): self 1325 | { 1326 | $quoted = preg_quote($prefix, '/'); 1327 | 1328 | $this->string = $prefix . preg_replace('/^(?:' . $quoted . ')+/u', '', $this->string); 1329 | 1330 | return $this; 1331 | } 1332 | 1333 | /** 1334 | * Determine if a given string starts with a given substring. 1335 | * 1336 | * @param string|string[] $needles Needles 1337 | * 1338 | * @return bool Returns TRUE on success or FALSE otherwise. 1339 | */ 1340 | public function startsWith($needles): bool 1341 | { 1342 | foreach ((array) $needles as $needle) { 1343 | if ((string) $needle !== '' && strncmp($this->string, (string) $needle, static::create($needle, $this->encoding)->length()) === 0) { 1344 | return true; 1345 | } 1346 | } 1347 | 1348 | return false; 1349 | } 1350 | 1351 | /** 1352 | * Determine if a given string ends with a given substring. 1353 | * 1354 | * @param string|string[] $needles needles 1355 | * 1356 | * @return bool Returns TRUE on success or FALSE otherwise. 1357 | */ 1358 | public function endsWith($needles): bool 1359 | { 1360 | foreach ((array) $needles as $needle) { 1361 | if ($needle !== '' && (string) static::create($this->string, $this->encoding)->substr(-static::create($needle, $this->encoding)->length()) === (string) $needle) { 1362 | return true; 1363 | } 1364 | } 1365 | 1366 | return false; 1367 | } 1368 | 1369 | /** 1370 | * Cap a string with a single instance of a given value. 1371 | * 1372 | * @param string $cap Cap 1373 | * 1374 | * @return self Returns instance of The Strings class. 1375 | */ 1376 | public function finish(string $cap): self 1377 | { 1378 | $quoted = preg_quote($cap, '/'); 1379 | 1380 | $this->string = preg_replace('/(?:' . $quoted . ')+$/u', '', $this->string) . $cap; 1381 | 1382 | return $this; 1383 | } 1384 | 1385 | /** 1386 | * Prepend the given values to the string. 1387 | * 1388 | * @param string[] $values Values 1389 | * 1390 | * @return self Returns instance of The Strings class. 1391 | */ 1392 | public function prepend(string ...$values): self 1393 | { 1394 | $this->string = implode('', $values) . $this->string; 1395 | 1396 | return $this; 1397 | } 1398 | 1399 | /** 1400 | * Append the given values to the string. 1401 | * 1402 | * @param string[] $values Values 1403 | * 1404 | * @return self Returns instance of The Strings class. 1405 | */ 1406 | public function append(string ...$values): self 1407 | { 1408 | $this->string .= implode('', (array) $values); 1409 | 1410 | return $this; 1411 | } 1412 | 1413 | /** 1414 | * Generate a hash string from the input string. 1415 | * 1416 | * @param string $algorithm Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..). 1417 | * For a list of supported algorithms see hash_algos(). Default is md5. 1418 | * @param string $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Default is FALSE 1419 | * 1420 | * @return self Returns instance of The Strings class. 1421 | */ 1422 | public function hash(string $algorithm = 'md5', bool $raw_output = false): self 1423 | { 1424 | if (in_array($algorithm, hash_algos())) { 1425 | $this->string = hash($algorithm, $this->string, $raw_output); 1426 | } else { 1427 | $this->string = $this->string; 1428 | } 1429 | 1430 | return $this; 1431 | } 1432 | 1433 | /** 1434 | * Generate the crc32 polynomial from the input string. 1435 | * 1436 | * @return int Returns crc32 polynomial from the input string. 1437 | */ 1438 | public function crc32(): int 1439 | { 1440 | return crc32($this->string); 1441 | } 1442 | 1443 | /** 1444 | * Generate a md5 hash string from the input string. 1445 | * 1446 | * @param string $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Default is FALSE 1447 | * 1448 | * @return self Returns instance of The Strings class. 1449 | */ 1450 | public function md5(bool $raw_output = false): self 1451 | { 1452 | $this->string = hash('md5', $this->string, $raw_output); 1453 | 1454 | return $this; 1455 | } 1456 | 1457 | /** 1458 | * Generate a sha1 hash string from the input string. 1459 | * 1460 | * @param string $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Default is FALSE 1461 | * 1462 | * @return self Returns instance of The Strings class. 1463 | */ 1464 | public function sha1(bool $raw_output = false): self 1465 | { 1466 | $this->string = hash('sha1', $this->string, $raw_output); 1467 | 1468 | return $this; 1469 | } 1470 | 1471 | /** 1472 | * Generate a sha256 hash string from the input string. 1473 | * 1474 | * @param string $raw_output When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. Default is FALSE 1475 | * 1476 | * @return self Returns instance of The Strings class. 1477 | */ 1478 | public function sha256(bool $raw_output = false): self 1479 | { 1480 | $this->string = hash('sha256', $this->string, $raw_output); 1481 | 1482 | return $this; 1483 | } 1484 | 1485 | /** 1486 | * Encodes data with MIME base64. 1487 | * 1488 | * @return self Returns instance of The Strings class. 1489 | */ 1490 | public function base64Encode(): self 1491 | { 1492 | $this->string = base64_encode($this->string); 1493 | 1494 | return $this; 1495 | } 1496 | 1497 | /** 1498 | * Decodes data encoded with MIME base64 1499 | * 1500 | * @return self Returns instance of The Strings class. 1501 | */ 1502 | public function base64Decode(): self 1503 | { 1504 | $this->string = base64_decode($this->string); 1505 | 1506 | return $this; 1507 | } 1508 | 1509 | /** 1510 | * Randomly shuffles a string. 1511 | * 1512 | * @return self Returns instance of The Strings class. 1513 | */ 1514 | public function shuffle(): self 1515 | { 1516 | $indexes = range(0, static::create($this->string, $this->encoding)->length() - 1); 1517 | 1518 | shuffle($indexes); 1519 | 1520 | $shuffled_string = ''; 1521 | 1522 | foreach ($indexes as $i) { 1523 | $shuffled_string .= static::create($this->string, $this->encoding)->substr($i, 1); 1524 | } 1525 | 1526 | $this->string = $shuffled_string; 1527 | 1528 | return $this; 1529 | } 1530 | 1531 | /** 1532 | * Calculate the similarity between two strings. 1533 | * 1534 | * @param string $string The delimiting string. 1535 | * 1536 | * @return float Returns similarity percent. 1537 | */ 1538 | public function similarity(string $string): float 1539 | { 1540 | similar_text($this->string, $string, $percent); 1541 | 1542 | return $percent; 1543 | } 1544 | 1545 | /** 1546 | * Returns the character at $index, with indexes starting at 0. 1547 | * 1548 | * @param int $index Position of the character. 1549 | */ 1550 | public function at(int $index): self 1551 | { 1552 | $this->string = (string) $this->substr($index, 1); 1553 | 1554 | return $this; 1555 | } 1556 | 1557 | /** 1558 | * Sort words in string descending. 1559 | * 1560 | * @return self Returns instance of The Strings class. 1561 | */ 1562 | public function wordsSortDesc(): self 1563 | { 1564 | $words = mb_split('\s', $this->string); 1565 | 1566 | rsort($words); 1567 | 1568 | $this->string = implode(' ', $words); 1569 | 1570 | return $this; 1571 | } 1572 | 1573 | /** 1574 | * Sort words in string ascending. 1575 | * 1576 | * @return self Returns instance of The Strings class. 1577 | */ 1578 | public function wordsSortAsc(): self 1579 | { 1580 | $words = mb_split('\s', $this->string); 1581 | 1582 | sort($words); 1583 | 1584 | $this->string = implode(' ', $words); 1585 | 1586 | return $this; 1587 | } 1588 | 1589 | /** 1590 | * Returns an array consisting of the characters in the string. 1591 | * 1592 | * @return array Returns an array of string chars. 1593 | */ 1594 | public function chars(): array 1595 | { 1596 | $chars = []; 1597 | 1598 | for ($i = 0, $length = $this->length(); $i < $length; $i++) { 1599 | $chars[] = static::create($this->toString())->at($i)->toString(); 1600 | } 1601 | 1602 | return $chars; 1603 | } 1604 | 1605 | /** 1606 | * Get chars usage frequency array. 1607 | * 1608 | * @param int $decimals Number of decimal points. Default is 2. 1609 | * @param string $decPoint Separator for the decimal point. Default is ".". 1610 | * @param string $thousandsSep Thousands separator. Default is ",". 1611 | * 1612 | * @return array Returns an chars usage frequency array. 1613 | */ 1614 | public function charsFrequency(int $decimals = 2, string $decPoint = '.', string $thousandsSep = ','): array 1615 | { 1616 | $this->stripSpaces(); 1617 | $chars = preg_split('//u', $this->string, -1, PREG_SPLIT_NO_EMPTY); 1618 | $totalAllCharsArray = count($chars); 1619 | $charsCount = array_count_values($chars); 1620 | 1621 | arsort($charsCount); 1622 | 1623 | $percentageCount = []; 1624 | 1625 | foreach ($charsCount as $chars => $char) { 1626 | $percentageCount[$chars] = number_format($char / $totalAllCharsArray * 100, $decimals, $decPoint, $thousandsSep); 1627 | } 1628 | 1629 | return $percentageCount; 1630 | } 1631 | 1632 | /** 1633 | * Get words usage frequency array. 1634 | * 1635 | * @param int $decimals Number of decimal points. Default is 2. 1636 | * @param string $decPoint Separator for the decimal point. Default is ".". 1637 | * @param string $thousandsSep Thousands separator. Default is ",". 1638 | * 1639 | * @return array Returns an words usage frequency array. 1640 | */ 1641 | public function wordsFrequency(int $decimals = 2, string $decPoint = '.', string $thousandsSep = ','): array 1642 | { 1643 | $this->replacePunctuations(); 1644 | $words = mb_split('\s', $this->string); 1645 | $totalAllWordsArray = count($words); 1646 | $wordsCount = array_count_values($words); 1647 | 1648 | arsort($wordsCount); 1649 | 1650 | $percentageCount = []; 1651 | 1652 | foreach ($wordsCount as $words => $word) { 1653 | $percentageCount[$words] = number_format($word / $totalAllWordsArray * 100, $decimals, $decPoint, $thousandsSep); 1654 | } 1655 | 1656 | return $percentageCount; 1657 | } 1658 | 1659 | /** 1660 | * Move substring of desired $length to $destination index of the original string. 1661 | * In case $destination is less than $length returns the string untouched. 1662 | * 1663 | * @param int $start Start 1664 | * @param int $length Length 1665 | * @param int $destination Destination 1666 | * 1667 | * @return self Returns instance of The Strings class. 1668 | */ 1669 | public function move(int $start, int $length, int $destination): self 1670 | { 1671 | if ($destination <= $length) { 1672 | return $this; 1673 | } 1674 | 1675 | $string = $this->string; 1676 | $substr = mb_substr($string, $start, $length); 1677 | $string = mb_substr($string, 0, $destination) . $substr . mb_substr($string, $destination); 1678 | $pos = mb_strpos($string, $substr, 0); 1679 | if (!$pos) { 1680 | $pos = 0; 1681 | } 1682 | $string = mb_substr($string, 0, $pos) . mb_substr($string, $pos + mb_strlen($substr)); 1683 | $this->string = $string; 1684 | 1685 | return $this; 1686 | } 1687 | 1688 | /** 1689 | * Inserts $substring into the string at the $index provided. 1690 | * 1691 | * @param string $substring Substring 1692 | * @param int $index Index 1693 | * 1694 | * @return self Returns instance of The Strings class. 1695 | */ 1696 | public function insert(string $substring, int $index): self 1697 | { 1698 | $this->string = static::create($this->string)->substr(0, $index)->toString() . 1699 | $substring . 1700 | static::create($this->string)->substr($index)->toString(); 1701 | 1702 | return $this; 1703 | } 1704 | 1705 | /** 1706 | * Call the given callback. 1707 | * 1708 | * @param callable $callback Callback function. 1709 | * 1710 | * @return self Returns instance of the Strings class. 1711 | * 1712 | * @access public 1713 | */ 1714 | public function pipe(callable $callback) 1715 | { 1716 | return $callback($this); 1717 | } 1718 | 1719 | /** 1720 | * Apply the callback if the given "value" is (or resolves to) truthy. 1721 | * 1722 | * @param mixed $value Value 1723 | * @param callable $callback Callback function. 1724 | * @param callable $default Callback function. 1725 | * 1726 | * @return self Returns instance of the Strings class. 1727 | * 1728 | * @access public 1729 | */ 1730 | public function when($value, callable $callback = null, callable $default = null) 1731 | { 1732 | $value = $value instanceof Closure ? $value($this) : $value; 1733 | 1734 | if ($value) { 1735 | return $callback($this, $value) ?? $this; 1736 | } elseif ($default) { 1737 | return $default($this, $value) ?? $this; 1738 | } 1739 | 1740 | return $this; 1741 | } 1742 | 1743 | /** 1744 | * Execute the given callback if the string contains a given substring. 1745 | * 1746 | * @param string|string[] $needles The string to find in haystack. 1747 | * @param callable $callback Callback function. 1748 | * @param callable $default Callback function. 1749 | * 1750 | * @return self Returns instance of the Strings class. 1751 | * 1752 | * @access public 1753 | */ 1754 | public function whenContains($needles, $callback, $default = null) 1755 | { 1756 | return $this->when($this->contains($needles), $callback, $default); 1757 | } 1758 | 1759 | /** 1760 | * Execute the given callback if the string equal a given substring. 1761 | * 1762 | * @param string $string String to compare. 1763 | * @param callable $callback Callback function. 1764 | * @param callable $default Callback function. 1765 | * 1766 | * @return self Returns instance of the Strings class. 1767 | * 1768 | * @access public 1769 | */ 1770 | public function whenEqual($string, $callback, $default = null) 1771 | { 1772 | return $this->when($this->isEqual($string), $callback, $default); 1773 | } 1774 | 1775 | /** 1776 | * Execute the given callback if the string matches a given pattern. 1777 | * 1778 | * @param string|array $pattern Pattern to match. 1779 | * @param callable $callback Callback function. 1780 | * @param callable $default Callback function. 1781 | * 1782 | * @return self Returns instance of the Strings class. 1783 | * 1784 | * @access public 1785 | */ 1786 | public function whenIs($pattern, $callback, $default = null) 1787 | { 1788 | return $this->when($this->is($pattern), $callback, $default); 1789 | } 1790 | 1791 | /** 1792 | * Execute the given callback if the string is ASCII. 1793 | * 1794 | * @param callable $callback Callback function. 1795 | * @param callable $default Callback function. 1796 | * 1797 | * @return self Returns instance of the Strings class. 1798 | * 1799 | * @access public 1800 | */ 1801 | public function whenIsAscii($callback, $default = null) 1802 | { 1803 | return $this->when($this->isAscii(), $callback, $default); 1804 | } 1805 | 1806 | /** 1807 | * Execute the given callback if the string is a valid UUID. 1808 | * 1809 | * @param callable $callback Callback function. 1810 | * @param callable $default Callback function. 1811 | * 1812 | * @return self Returns instance of the Strings class. 1813 | * 1814 | * @access public 1815 | */ 1816 | public function whenIsUuid($callback, $default = null) 1817 | { 1818 | return $this->when($this->isUuid(), $callback, $default); 1819 | } 1820 | 1821 | /** 1822 | * Execute the given callback if the string starts with a given substring. 1823 | * 1824 | * @param string|string[] $needles The string to find in haystack. 1825 | * @param callable $callback Callback function. 1826 | * @param callable $default Callback function. 1827 | * 1828 | * @return self Returns instance of the Strings class. 1829 | * 1830 | * @access public 1831 | */ 1832 | public function whenStartsWith($needles, $callback, $default = null) 1833 | { 1834 | return $this->when($this->startsWith($needles), $callback, $default); 1835 | } 1836 | 1837 | /** 1838 | * Apply the callback if the given "value" is (or resolves to) falsy. 1839 | * 1840 | * @param mixed $value Value 1841 | * @param callable $callback Callback function. 1842 | * @param callable $default Callback function. 1843 | * 1844 | * @return self Returns instance of the Strings class. 1845 | * 1846 | * @access public 1847 | */ 1848 | public function unless($value, callable $callback = null, callable $default = null) 1849 | { 1850 | $value = $value instanceof Closure ? $value($this) : $value; 1851 | 1852 | if (!$value) { 1853 | return $callback($this, $value) ?? $this; 1854 | } elseif ($default) { 1855 | return $default($this, $value) ?? $this; 1856 | } 1857 | 1858 | return $this; 1859 | } 1860 | 1861 | /** 1862 | * Creates a new Strings object with the same string. 1863 | * 1864 | * @return self Returns instance of The Strings class. 1865 | */ 1866 | public function copy(): self 1867 | { 1868 | return clone $this; 1869 | } 1870 | 1871 | /** 1872 | * Echo the string. 1873 | * 1874 | * @return self Returns instance of The Strings class. 1875 | */ 1876 | public function echo(): self 1877 | { 1878 | echo $this->toString(); 1879 | 1880 | return $this; 1881 | } 1882 | 1883 | /** 1884 | * Return the formatted string. 1885 | * 1886 | * @param mixed ...$args Any number of elements to fill the string. 1887 | * 1888 | * @return self Returns instance of The Strings class. 1889 | */ 1890 | public function format(...$args): self 1891 | { 1892 | $this->string = sprintf($this->string, ...$args); 1893 | 1894 | return $this; 1895 | } 1896 | 1897 | /** 1898 | * Wrap the string with the given strings. 1899 | * 1900 | * @param string $before String to wrap before. 1901 | * @param string|null $after String to wrap after. 1902 | * 1903 | * @return self Returns instance of the Strings class. 1904 | * 1905 | * @access public 1906 | */ 1907 | public function wrap($before, $after = null) 1908 | { 1909 | $this->string = $before . $this->string . ($after ??= $before); 1910 | 1911 | return $this; 1912 | } 1913 | 1914 | 1915 | /** 1916 | * Returns true if the string matches a given pattern. 1917 | * 1918 | * @param string|array $pattern Pattern to match. 1919 | * 1920 | * @return bool Returns TRUE on success or FALSE otherwise. 1921 | */ 1922 | public function is($pattern): bool 1923 | { 1924 | $patterns = is_array($pattern) ? $pattern : [$pattern]; 1925 | $value = $this->toString(); 1926 | 1927 | if (empty($patterns)) { 1928 | return false; 1929 | } 1930 | 1931 | foreach ($patterns as $pattern) { 1932 | $pattern = (string) $pattern; 1933 | 1934 | if ($pattern === $value) { 1935 | return true; 1936 | } 1937 | 1938 | $pattern = preg_quote($pattern, '#'); 1939 | $pattern = str_replace('\*', '.*', $pattern); 1940 | 1941 | if (preg_match('#^'.$pattern.'\z#u', $value) === 1) { 1942 | return true; 1943 | } 1944 | } 1945 | 1946 | return false; 1947 | } 1948 | 1949 | /** 1950 | * Returns true if the string not matches a given pattern. 1951 | * 1952 | * @param string|array $pattern Pattern to match. 1953 | * 1954 | * @return bool Returns TRUE on success or FALSE otherwise. 1955 | */ 1956 | public function isNot($pattern): bool 1957 | { 1958 | return !$this->is($pattern); 1959 | } 1960 | 1961 | /** 1962 | * Returns true if the string is hex color, false otherwise. 1963 | * 1964 | * @return bool Returns TRUE on success or FALSE otherwise. 1965 | */ 1966 | public function isHexColor(): bool 1967 | { 1968 | return (bool) mb_ereg_match('^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$', $this->string); 1969 | } 1970 | 1971 | /** 1972 | * Returns true if the string is not hex color, false otherwise. 1973 | * 1974 | * @return bool Returns TRUE on success or FALSE otherwise. 1975 | */ 1976 | public function isNotHexColor(): bool 1977 | { 1978 | return !$this->isHexColor(); 1979 | } 1980 | 1981 | /** 1982 | * Returns true if the string is affirmative, false otherwise. 1983 | * 1984 | * @return bool Returns TRUE on success or FALSE otherwise. 1985 | */ 1986 | public function isAffirmative(): bool 1987 | { 1988 | return (bool) mb_ereg_match('^(?:1|t(?:rue)?|y(?:es)?|ok(?:ay)?)$', $this->string); 1989 | } 1990 | 1991 | /** 1992 | * Returns true if the string is not affirmative, false otherwise. 1993 | * 1994 | * @return bool Returns TRUE on success or FALSE otherwise. 1995 | */ 1996 | public function isNotAffirmative(): bool 1997 | { 1998 | return !$this->isAffirmative(); 1999 | } 2000 | 2001 | /** 2002 | * Returns true if the string is date and it is valid, false otherwise. 2003 | * 2004 | * @return bool Returns TRUE on success or FALSE otherwise. 2005 | */ 2006 | public function isDate(): bool 2007 | { 2008 | return (bool) strtotime($this->string); 2009 | } 2010 | 2011 | /** 2012 | * Returns true if the string is not date and it is valid, false otherwise. 2013 | * 2014 | * @return bool Returns TRUE on success or FALSE otherwise. 2015 | */ 2016 | public function isNotDate(): bool 2017 | { 2018 | return !$this->isDate(); 2019 | } 2020 | 2021 | /** 2022 | * Returns true if the string is email and it is valid, false otherwise. 2023 | * 2024 | * @return bool Returns TRUE on success or FALSE otherwise. 2025 | */ 2026 | public function isEmail(): bool 2027 | { 2028 | return (bool) filter_var($this->string, FILTER_VALIDATE_EMAIL); 2029 | } 2030 | 2031 | /** 2032 | * Returns true if the string is not email and it is valid, false otherwise. 2033 | * 2034 | * @return bool Returns TRUE on success or FALSE otherwise. 2035 | */ 2036 | public function isNotEmail(): bool 2037 | { 2038 | return !$this->isEmail(); 2039 | } 2040 | 2041 | /** 2042 | * Returns true if the string is url and it is valid, false otherwise. 2043 | * 2044 | * @return bool Returns TRUE on success or FALSE otherwise. 2045 | */ 2046 | public function isUrl(): bool 2047 | { 2048 | return (bool) filter_var($this->string, FILTER_VALIDATE_URL); 2049 | } 2050 | 2051 | /** 2052 | * Returns true if the string is not url and it is valid, false otherwise. 2053 | * 2054 | * @return bool Returns TRUE on success or FALSE otherwise. 2055 | */ 2056 | public function isNotUrl(): bool 2057 | { 2058 | return !$this->isUrl(); 2059 | } 2060 | 2061 | /** 2062 | * Returns true if the string is empty, false otherwise. 2063 | * 2064 | * @return bool Returns TRUE on success or FALSE otherwise. 2065 | */ 2066 | public function isEmpty(): bool 2067 | { 2068 | return empty($this->string); 2069 | } 2070 | 2071 | /** 2072 | * Returns true if the string is not empty, false otherwise. 2073 | * 2074 | * @return bool Returns TRUE on success or FALSE otherwise. 2075 | */ 2076 | public function isNotEmpty(): bool 2077 | { 2078 | return !$this->isEmpty(); 2079 | } 2080 | 2081 | /** 2082 | * Returns true if the string contains ASCII, false otherwise. 2083 | * 2084 | * @return bool Returns TRUE on success or FALSE otherwise. 2085 | */ 2086 | public function isAscii(): bool 2087 | { 2088 | return mb_ereg_match('^[[:ascii:]]*$', $this->string); 2089 | } 2090 | 2091 | /** 2092 | * Returns true if the string is not contains ASCII, false otherwise. 2093 | * 2094 | * @return bool Returns TRUE on success or FALSE otherwise. 2095 | */ 2096 | public function isNotAscii(): bool 2097 | { 2098 | return !$this->isAscii(); 2099 | } 2100 | 2101 | /** 2102 | * Returns true if the string contains only alphabetic and numeric chars, false otherwise. 2103 | * 2104 | * @return bool Returns TRUE on success or FALSE otherwise. 2105 | */ 2106 | public function isAlphanumeric(): bool 2107 | { 2108 | return mb_ereg_match('^[[:alnum:]]*$', $this->string); 2109 | } 2110 | 2111 | /** 2112 | * Returns true if the string is not contains only alphabetic and numeric chars, false otherwise. 2113 | * 2114 | * @return bool Returns TRUE on success or FALSE otherwise. 2115 | */ 2116 | public function isNotAlphanumeric(): bool 2117 | { 2118 | return !$this->isAlphanumeric(); 2119 | } 2120 | 2121 | /** 2122 | * Returns true if the string contains only alphabetic chars, false otherwise. 2123 | * 2124 | * @return bool Returns TRUE on success or FALSE otherwise. 2125 | */ 2126 | public function isAlpha(): bool 2127 | { 2128 | return mb_ereg_match('^[[:alpha:]]*$', $this->string); 2129 | } 2130 | 2131 | /** 2132 | * Returns true if the string is not contains only alphabetic chars, false otherwise. 2133 | * 2134 | * @return bool Returns TRUE on success or FALSE otherwise. 2135 | */ 2136 | public function isNotAlpha(): bool 2137 | { 2138 | return !$this->isAlpha(); 2139 | } 2140 | 2141 | /** 2142 | * Returns true if the string contains only whitespace chars, false otherwise. 2143 | * 2144 | * @return bool Returns TRUE on success or FALSE otherwise. 2145 | */ 2146 | public function isBlank(): bool 2147 | { 2148 | return mb_ereg_match('^[[:space:]]*$', $this->string); 2149 | } 2150 | 2151 | /** 2152 | * Returns true if the string is not contains only whitespace chars, false otherwise. 2153 | * 2154 | * @return bool Returns TRUE on success or FALSE otherwise. 2155 | */ 2156 | public function isNotBlank(): bool 2157 | { 2158 | return !$this->isBlank(); 2159 | } 2160 | 2161 | /** 2162 | * Returns true if the string is a number or a numeric strings, false otherwise. 2163 | * 2164 | * @return bool Returns TRUE on success or FALSE otherwise. 2165 | */ 2166 | public function isNumeric(): bool 2167 | { 2168 | return is_numeric($this->string); 2169 | } 2170 | 2171 | /** 2172 | * Returns true if the string is not a number or a numeric strings, false otherwise. 2173 | * 2174 | * @return bool Returns TRUE on success or FALSE otherwise. 2175 | */ 2176 | public function isNotNumeric(): bool 2177 | { 2178 | return !$this->isNumeric(); 2179 | } 2180 | 2181 | /** 2182 | * Returns true if the string contains only digit chars, false otherwise. 2183 | * 2184 | * @return bool Returns TRUE on success or FALSE otherwise. 2185 | */ 2186 | public function isDigit(): bool 2187 | { 2188 | return mb_ereg_match('^[[:digit:]]*$', $this->string); 2189 | } 2190 | 2191 | 2192 | /** 2193 | * Returns true if the string is not contains only digit chars, false otherwise. 2194 | * 2195 | * @return bool Returns TRUE on success or FALSE otherwise. 2196 | */ 2197 | public function isNotDigit(): bool 2198 | { 2199 | return !$this->isDigit(); 2200 | } 2201 | 2202 | /** 2203 | * Returns true if the string contains only lower case chars, false otherwise. 2204 | * 2205 | * @return bool Returns TRUE on success or FALSE otherwise. 2206 | */ 2207 | public function isLower(): bool 2208 | { 2209 | return mb_ereg_match('^[[:lower:]]*$', $this->string); 2210 | } 2211 | 2212 | /** 2213 | * Returns true if the string is not contains only lower case chars, false otherwise. 2214 | * 2215 | * @return bool Returns TRUE on success or FALSE otherwise. 2216 | */ 2217 | public function isNotLower(): bool 2218 | { 2219 | return !$this->isLower(); 2220 | } 2221 | 2222 | /** 2223 | * Returns true if the string contains only upper case chars, false otherwise. 2224 | * 2225 | * @return bool Returns TRUE on success or FALSE otherwise. 2226 | */ 2227 | public function isUpper(): bool 2228 | { 2229 | return mb_ereg_match('^[[:upper:]]*$', $this->string); 2230 | } 2231 | 2232 | /** 2233 | * Returns true if the string is not contains only upper case chars, false otherwise. 2234 | * 2235 | * @return bool Returns TRUE on success or FALSE otherwise. 2236 | */ 2237 | public function isNotUpper(): bool 2238 | { 2239 | return !$this->isUpper(); 2240 | } 2241 | 2242 | /** 2243 | * Returns true if the string contains only hexadecimal chars, false otherwise. 2244 | * 2245 | * @return bool Returns TRUE on success or FALSE otherwise. 2246 | */ 2247 | public function isHexadecimal(): bool 2248 | { 2249 | return mb_ereg_match('^[[:xdigit:]]*$', $this->string); 2250 | } 2251 | 2252 | /** 2253 | * Returns true if the string is not contains only hexadecimal chars, false otherwise. 2254 | * 2255 | * @return bool Returns TRUE on success or FALSE otherwise. 2256 | */ 2257 | public function isNotHexadecimal(): bool 2258 | { 2259 | return !$this->isHexadecimal(); 2260 | } 2261 | 2262 | /** 2263 | * Returns true if the string contains only printable (non-invisible) chars, false otherwise. 2264 | * 2265 | * @return bool Returns TRUE on success or FALSE otherwise. 2266 | */ 2267 | public function isPrintable(): bool 2268 | { 2269 | return mb_ereg_match('^[[:print:]]*$', $this->string); 2270 | } 2271 | 2272 | /** 2273 | * Returns true if the string is not contains only printable (non-invisible) chars, false otherwise. 2274 | * 2275 | * @return bool Returns TRUE on success or FALSE otherwise. 2276 | */ 2277 | public function isNotPrintable(): bool 2278 | { 2279 | return !$this->isPrintable(); 2280 | } 2281 | 2282 | /** 2283 | * Returns true if the string contains only punctuation chars, false otherwise. 2284 | * 2285 | * @return bool Returns TRUE on success or FALSE otherwise. 2286 | */ 2287 | public function isPunctuation(): bool 2288 | { 2289 | return mb_ereg_match('^[[:punct:]]*$', $this->string); 2290 | } 2291 | 2292 | /** 2293 | * Returns true if the string is not contains only punctuation chars, false otherwise. 2294 | * 2295 | * @return bool Returns TRUE on success or FALSE otherwise. 2296 | */ 2297 | public function isNotPunctuation(): bool 2298 | { 2299 | return !$this->isPunctuation(); 2300 | } 2301 | 2302 | /** 2303 | * Returns true if the string is serialized, false otherwise. 2304 | * 2305 | * @return bool Returns TRUE on success or FALSE otherwise. 2306 | */ 2307 | public function isSerialized(): bool 2308 | { 2309 | if ($this->string === '') { 2310 | return false; 2311 | } 2312 | 2313 | return $this->string === 'b:0;' || @unserialize($this->string) !== false; 2314 | } 2315 | 2316 | /** 2317 | * Returns true if the string is not serialized, false otherwise. 2318 | * 2319 | * @return bool Returns TRUE on success or FALSE otherwise. 2320 | */ 2321 | public function isNotSerialized(): bool 2322 | { 2323 | return !$this->isSerialized(); 2324 | } 2325 | 2326 | /** 2327 | * Returns true if the string is JSON, false otherwise. 2328 | * 2329 | * @return bool Returns TRUE on success or FALSE otherwise. 2330 | */ 2331 | public function isJson(): bool 2332 | { 2333 | json_decode($this->string); 2334 | 2335 | return json_last_error() === JSON_ERROR_NONE; 2336 | } 2337 | 2338 | /** 2339 | * Returns true if the string is not JSON, false otherwise. 2340 | * 2341 | * @return bool Returns TRUE on success or FALSE otherwise. 2342 | */ 2343 | public function isNotJson(): bool 2344 | { 2345 | return !$this->isJson(); 2346 | } 2347 | 2348 | /** 2349 | * Returns true if the string is base64 encoded, false otherwise. 2350 | * 2351 | * @return bool Returns TRUE on success or FALSE otherwise. 2352 | */ 2353 | public function isBase64(): bool 2354 | { 2355 | if ($this->length() === 0) { 2356 | return false; 2357 | } 2358 | 2359 | $decoded = base64_decode($this->string, true); 2360 | 2361 | if ($decoded === false) { 2362 | return false; 2363 | } 2364 | 2365 | return base64_encode($decoded) === $this->string; 2366 | } 2367 | 2368 | /** 2369 | * Returns true if the string is not base64 encoded, false otherwise. 2370 | * 2371 | * @return bool Returns TRUE on success or FALSE otherwise. 2372 | */ 2373 | public function isNotBase64(): bool 2374 | { 2375 | return !$this->isBase64(); 2376 | } 2377 | 2378 | /** 2379 | * Check if two strings are similar. 2380 | * 2381 | * @param string $string The string to compare against. 2382 | * @param float $minPercentForSimilarity The percentage of needed similarity. Default is 80% 2383 | * 2384 | * @return bool Returns TRUE on success or FALSE otherwise. 2385 | */ 2386 | public function isSimilar(string $string, float $minPercentForSimilarity = 80.0): bool 2387 | { 2388 | return $this->similarity($string) >= $minPercentForSimilarity; 2389 | } 2390 | 2391 | /** 2392 | * Check if two strings are not similar. 2393 | * 2394 | * @param string $string The string to compare against. 2395 | * @param float $minPercentForSimilarity The percentage of needed similarity. Default is 80% 2396 | * 2397 | * @return bool Returns TRUE on success or FALSE otherwise. 2398 | */ 2399 | public function isNotSimilar(string $string, float $minPercentForSimilarity = 80.0): bool 2400 | { 2401 | return !$this->isSimilar($string, $minPercentForSimilarity); 2402 | } 2403 | 2404 | /** 2405 | * Determine whether the string is equals to $string. 2406 | * 2407 | * @param string $string String to compare. 2408 | * 2409 | * @return bool Returns TRUE on success or FALSE otherwise. 2410 | */ 2411 | public function isEqual(string $string): bool 2412 | { 2413 | return $string === $this->toString(); 2414 | } 2415 | 2416 | /** 2417 | * Determine whether the string is not equals to $string. 2418 | * 2419 | * @param string $string String to compare. 2420 | * 2421 | * @return bool Returns TRUE on success or FALSE otherwise. 2422 | */ 2423 | public function isNotEqual(string $string): bool 2424 | { 2425 | return !$this->isEqual($string); 2426 | } 2427 | 2428 | /** 2429 | * Determine whether the string is IP and it is a valid IP address. 2430 | * 2431 | * @param int $flags Flags: 2432 | * FILTER_FLAG_IPV4 2433 | * FILTER_FLAG_IPV6 2434 | * FILTER_FLAG_NO_PRIV_RANGE 2435 | * FILTER_FLAG_NO_RES_RANGE 2436 | * 2437 | * @return bool Returns TRUE on success or FALSE otherwise. 2438 | */ 2439 | public function isIP(int $flags = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6): bool 2440 | { 2441 | return (bool) filter_var($this->toString(), FILTER_VALIDATE_IP, $flags); 2442 | } 2443 | 2444 | /** 2445 | * Determine whether the string is not IP and it is not a valid IP address. 2446 | * 2447 | * @param int $flags Flags: 2448 | * FILTER_FLAG_IPV4 2449 | * FILTER_FLAG_IPV6 2450 | * FILTER_FLAG_NO_PRIV_RANGE 2451 | * FILTER_FLAG_NO_RES_RANGE 2452 | * 2453 | * @return bool Returns TRUE on success or FALSE otherwise. 2454 | */ 2455 | public function isNotIP(int $flags = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6): bool 2456 | { 2457 | return !$this->isIP($flags); 2458 | } 2459 | 2460 | /** 2461 | * Determine whether the string is MAC address and it is a valid MAC address. 2462 | * 2463 | * @return bool Returns TRUE on success or FALSE otherwise. 2464 | */ 2465 | public function isMAC(): bool 2466 | { 2467 | return (bool) filter_var($this->toString(), FILTER_VALIDATE_MAC); 2468 | } 2469 | 2470 | /** 2471 | * Determine whether the string is not MAC address and it is not a valid MAC address. 2472 | * 2473 | * @return bool Returns TRUE on success or FALSE otherwise. 2474 | */ 2475 | public function isNotMAC(): bool 2476 | { 2477 | return !$this->isMAC(); 2478 | } 2479 | 2480 | /** 2481 | * Determine whether the string is HTML. 2482 | * 2483 | * @return bool Returns TRUE on success or FALSE otherwise. 2484 | */ 2485 | public function isHTML(): bool 2486 | { 2487 | return $this->toString() !== strip_tags($this->toString()); 2488 | } 2489 | 2490 | /** 2491 | * Determine whether the string is not HTML. 2492 | * 2493 | * @return bool Returns TRUE on success or FALSE otherwise. 2494 | */ 2495 | public function isNotHTML(): bool 2496 | { 2497 | return !$this->isHTML(); 2498 | } 2499 | 2500 | /** 2501 | * Determine whether the string is integer. 2502 | * 2503 | * @return bool Returns TRUE on success or FALSE otherwise. 2504 | */ 2505 | public function isInteger(): bool 2506 | { 2507 | return (bool) filter_var($this->toString(), FILTER_VALIDATE_INT); 2508 | } 2509 | 2510 | /** 2511 | * Determine whether the string is not integer. 2512 | * 2513 | * @return bool Returns TRUE on success or FALSE otherwise. 2514 | */ 2515 | public function isNotInteger(): bool 2516 | { 2517 | return !$this->isInteger(); 2518 | } 2519 | 2520 | /** 2521 | * Determine whether the string is float. 2522 | * 2523 | * @return bool Returns TRUE on success or FALSE otherwise. 2524 | */ 2525 | public function isFloat(): bool 2526 | { 2527 | return ((bool) filter_var($this->toString(), FILTER_VALIDATE_FLOAT) !== $this->isInteger()); 2528 | } 2529 | 2530 | /** 2531 | * Determine whether the string is not float. 2532 | * 2533 | * @return bool Returns TRUE on success or FALSE otherwise. 2534 | */ 2535 | public function isNotFloat(): bool { 2536 | return !$this->isFloat(); 2537 | } 2538 | 2539 | /** 2540 | * Determine whether the string is null. 2541 | * 2542 | * @return bool Returns TRUE on success or FALSE otherwise. 2543 | */ 2544 | public function isNull(): bool 2545 | { 2546 | return $this->toString() === null || $this->toString() === 'null'; 2547 | } 2548 | 2549 | /** 2550 | * Determine whether the string is not null. 2551 | * 2552 | * @return bool Returns TRUE on success or FALSE otherwise. 2553 | */ 2554 | public function isNotNull(): bool 2555 | { 2556 | return !$this->isNull(); 2557 | } 2558 | 2559 | /** 2560 | * Determine whether the string is Boolean. 2561 | * 2562 | * Boolean representation for logical strings: 2563 | * 'true', '1', 'on' and 'yes' will return true. 2564 | * 'false', '0', 'off', and 'no' will return false. 2565 | * 2566 | * In all instances, case is ignored. 2567 | * 2568 | * @return bool Returns TRUE on success or FALSE otherwise. 2569 | */ 2570 | public function isBoolean(): bool 2571 | { 2572 | return in_array(mb_strtolower($this->toString()), ['true', 'false', '1', '0', 'yes', 'no', 'on', 'off'], true); 2573 | } 2574 | 2575 | /** 2576 | * Determine whether the string is not Boolean. 2577 | * 2578 | * Boolean representation for logical strings: 2579 | * 'true', '1', 'on' and 'yes' will return true. 2580 | * 'false', '0', 'off', and 'no' will return false. 2581 | * 2582 | * In all instances, case is ignored. 2583 | * 2584 | * @return bool Returns TRUE on success or FALSE otherwise. 2585 | */ 2586 | public function isNotBoolean(): bool 2587 | { 2588 | return !$this->isBoolean(); 2589 | } 2590 | 2591 | /** 2592 | * Determine whether the string is Boolean and it is TRUE. 2593 | * 2594 | * @return bool Returns TRUE on success or FALSE otherwise. 2595 | */ 2596 | public function isTrue(): bool 2597 | { 2598 | return $this->toBoolean() === true; 2599 | } 2600 | 2601 | /** 2602 | * Determine whether the string is not Boolean and it is not TRUE. 2603 | * 2604 | * @return bool Returns TRUE on success or FALSE otherwise. 2605 | */ 2606 | public function isNotTrue(): bool 2607 | { 2608 | return !$this->isTrue(); 2609 | } 2610 | 2611 | /** 2612 | * Determine whether the string is Boolean and it is FALSE. 2613 | * 2614 | * @return bool Returns TRUE on success or FALSE otherwise. 2615 | */ 2616 | public function isFalse(): bool 2617 | { 2618 | return $this->toBoolean() === false; 2619 | } 2620 | 2621 | /** 2622 | * Determine whether the string is not Boolean and it is not FALSE. 2623 | * 2624 | * @return bool Returns TRUE on success or FALSE otherwise. 2625 | */ 2626 | public function isNotFalse(): bool 2627 | { 2628 | return !$this->isFalse(); 2629 | } 2630 | 2631 | /** 2632 | * Determine whether the string is UUID and it is valid. 2633 | * 2634 | * @return bool Returns TRUE on success or FALSE otherwise. 2635 | */ 2636 | public function isUuid(): bool 2637 | { 2638 | return preg_match('/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iD', $this->toString()) > 0; 2639 | } 2640 | 2641 | /** 2642 | * Determine whether the string is not UUID and it is not valid. 2643 | * 2644 | * @return bool Returns TRUE on success or FALSE otherwise. 2645 | */ 2646 | public function isNotUuid(): bool 2647 | { 2648 | return !$this->isUuid(); 2649 | } 2650 | 2651 | /** 2652 | * Return Strings object as string. 2653 | * 2654 | * @return string Returns strings object as string. 2655 | */ 2656 | public function toString(): string 2657 | { 2658 | return strval($this); 2659 | } 2660 | 2661 | /** 2662 | * Return Strings object as integer. 2663 | * 2664 | * @return int Return Strings object as integer. 2665 | */ 2666 | public function toInteger(): int 2667 | { 2668 | return intval($this->string); 2669 | } 2670 | 2671 | /** 2672 | * Return Strings object as float. 2673 | * 2674 | * @return float Return Strings object as float. 2675 | */ 2676 | public function toFloat(): float 2677 | { 2678 | return floatval($this->string); 2679 | } 2680 | 2681 | /** 2682 | * Return Strings object as null. 2683 | * 2684 | * @return null Return Strings object as null. 2685 | */ 2686 | public function toNull() 2687 | { 2688 | return null; 2689 | } 2690 | 2691 | /** 2692 | * Returns a boolean representation of the given logical string value. 2693 | * 2694 | * For example: 2695 | * 'true', '1', 'on' and 'yes' will return true. 2696 | * 'false', '0', 'off', and 'no' will return false. 2697 | * 2698 | * In all instances, case is ignored. 2699 | * 2700 | * For other numeric strings, their sign will determine the return value. 2701 | * In addition, blank strings consisting of only whitespace will return 2702 | * false. For all other strings, the return value is a result of a 2703 | * boolean cast. 2704 | * 2705 | * @return bool Returns a boolean representation of the given logical string value. 2706 | */ 2707 | public function toBoolean(): bool 2708 | { 2709 | $result = filter_var($this->string, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); 2710 | 2711 | return $result ?? true; 2712 | } 2713 | 2714 | /** 2715 | * Return Strings object as array based on a delimiter. 2716 | * 2717 | * @param string $delimiter Delimeter. Default is null. 2718 | * 2719 | * @return array Return Strings object as array based on a delimiter. 2720 | */ 2721 | public function toArray(string|null $delimiter = null): array 2722 | { 2723 | $encoding = $this->encoding; 2724 | $string = static::create($this->string, $encoding)->trim()->toString(); 2725 | 2726 | if ($delimiter !== null) { 2727 | $array = ! empty($delimiter) ? explode($delimiter, $string) : [$string]; 2728 | } else { 2729 | $array = [$string]; 2730 | } 2731 | 2732 | array_walk( 2733 | $array, 2734 | static function (&$value) use ($encoding): void { 2735 | if ((string) $value !== $value) { 2736 | return; 2737 | } 2738 | 2739 | $value = static::create($value, $encoding)->trim()->toString(); 2740 | } 2741 | ); 2742 | 2743 | return $array; 2744 | } 2745 | 2746 | /** 2747 | * Dumps the strings using the given function (print_r by default). 2748 | * 2749 | * @param callable $callback Function receiving the strings as parameter. 2750 | * 2751 | * @return self Returns instance of The Strings class. 2752 | */ 2753 | public function dump(?callable $callback = null): self 2754 | { 2755 | $callback ? $callback($this->toString()) : print_r($this->toString()); 2756 | 2757 | return $this; 2758 | } 2759 | 2760 | /** 2761 | * Dumps the string using the given function (print_r by default) and exit(1). 2762 | * 2763 | * @param callable $callback Function receiving the strings as parameter. 2764 | * 2765 | * @return void Return void. 2766 | */ 2767 | public function dd(?callable $callback = null): void 2768 | { 2769 | $this->dump($callback); 2770 | 2771 | exit(1); 2772 | } 2773 | 2774 | /** 2775 | * Append a new line to the string. 2776 | * 2777 | * @param int $count Count of new lines. Default is 1. 2778 | * 2779 | * @return self Returns instance of the Strings class. 2780 | * 2781 | * @access public 2782 | */ 2783 | public function newLine(int $count = 1): self 2784 | { 2785 | return $this->append(str_repeat(PHP_EOL, $count)); 2786 | } 2787 | 2788 | /** 2789 | * Returns a new ArrayIterator, thus implementing the IteratorAggregate 2790 | * interface. The ArrayIterator's constructor is passed an array of chars 2791 | * in the multibyte string. This enables the use of foreach with instances 2792 | * of Strings\Strings. 2793 | * 2794 | * @return ArrayIterator An iterator for the characters in the string 2795 | */ 2796 | public function getIterator(): ArrayIterator 2797 | { 2798 | return new ArrayIterator($this->chars()); 2799 | } 2800 | 2801 | /** 2802 | * Returns whether or not a character exists at an index. Offsets may be 2803 | * negative to count from the last character in the string. Implements 2804 | * part of the ArrayAccess interface. 2805 | * 2806 | * @param mixed $offset The index to check 2807 | * 2808 | * @return bool Return TRUE key exists in the array, FALSE otherwise. 2809 | */ 2810 | public function offsetExists($offset): bool 2811 | { 2812 | $length = $this->length(); 2813 | $offset = (int) $offset; 2814 | 2815 | if ($offset >= 0) { 2816 | return $length > $offset; 2817 | } 2818 | 2819 | return $length >= abs($offset); 2820 | } 2821 | 2822 | /** 2823 | * Returns the character at the given index. Offsets may be negative to 2824 | * count from the last character in the string. Implements part of the 2825 | * ArrayAccess interface, and throws an OutOfBoundsException if the index 2826 | * does not exist. 2827 | * 2828 | * @param mixed $offset The index from which to retrieve the char 2829 | * 2830 | * @return mixed The character at the specified index 2831 | * @return mixed Return TRUE key exists in the array, FALSE otherwise. 2832 | * 2833 | * @throws OutOfBoundsException If the positive or negative offset does 2834 | * not exist 2835 | */ 2836 | #[\ReturnTypeWillChange] 2837 | public function offsetGet($offset) 2838 | { 2839 | $offset = (int) $offset; 2840 | $length = $this->length(); 2841 | 2842 | if (($offset >= 0 && $length <= $offset) || $length < abs($offset)) { 2843 | throw new OutOfBoundsException('No character exists at the index'); 2844 | } 2845 | 2846 | return mb_substr($this->toString(), $offset, 1, $this->encoding); 2847 | } 2848 | 2849 | /** 2850 | * Implements part of the ArrayAccess interface, but throws an exception 2851 | * when called. This maintains the immutability of Strings objects. 2852 | * 2853 | * @param mixed $offset The index of the character 2854 | * @param mixed $value Value to set 2855 | * 2856 | * @throws Exception When called 2857 | */ 2858 | public function offsetSet($offset, $value): void 2859 | { 2860 | throw new Exception('Strings object is immutable, cannot modify char'); 2861 | } 2862 | 2863 | /** 2864 | * Implements part of the ArrayAccess interface, but throws an exception 2865 | * when called. This maintains the immutability of Strings objects. 2866 | * 2867 | * @param mixed $offset The index of the character 2868 | * 2869 | * @throws Exception When called 2870 | */ 2871 | public function offsetUnset($offset): void 2872 | { 2873 | throw new Exception('Strings object is immutable, cannot unset char'); 2874 | } 2875 | } 2876 | -------------------------------------------------------------------------------- /src/helpers.php: -------------------------------------------------------------------------------- 1 |