├── 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 |
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 |