Skip to content

Commit 10f2b66

Browse files
committed
Merge branch 'master' into 3.1
# Conflicts: # .github/workflows/test.yml # src/service-governance/src/Listener/RegisterServiceListener.php # src/stringable/composer.json # src/stringable/tests/StrTest.php
2 parents 6c8fb30 + 63d7ce0 commit 10f2b66

File tree

6 files changed

+919
-4
lines changed

6 files changed

+919
-4
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
steps:
1414
- name: Checkout code
15-
uses: actions/checkout@v2
15+
uses: actions/checkout@v4
1616
- name: Create Release
1717
id: create_release
1818
uses: actions/create-release@v1

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
},
1818
"require": {
1919
"php": ">=8.1",
20+
"ext-mbstring": "*",
2021
"hyperf/collection": "~3.1.0",
2122
"hyperf/conditionable": "~3.1.0",
2223
"hyperf/macroable": "~3.1.0",

src/Str.php

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Hyperf\Collection\Collection;
1717
use Hyperf\Macroable\Macroable;
1818
use InvalidArgumentException;
19+
use JsonException;
1920
use Ramsey\Uuid\Uuid;
2021
use Ramsey\Uuid\UuidInterface;
2122
use RuntimeException;
@@ -877,6 +878,178 @@ public static function orderedUuid(?DateTimeInterface $time = null): UuidInterfa
877878
return Uuid::uuid7($time);
878879
}
879880

881+
public static function betweenFirst($subject, $from, $to)
882+
{
883+
if ($from === '' || $to === '') {
884+
return $subject;
885+
}
886+
887+
return Str::before(Str::after($subject, $from), $to);
888+
}
889+
890+
public static function classNamespace($value): string
891+
{
892+
if ($pos = strrpos($value, '\\')) {
893+
return substr($value, 0, $pos);
894+
}
895+
896+
return '';
897+
}
898+
899+
public static function convertCase(string $string, int $mode = MB_CASE_FOLD, ?string $encoding = 'UTF-8'): string
900+
{
901+
return mb_convert_case($string, $mode, $encoding);
902+
}
903+
904+
public static function excerpt($text, $phrase = '', $options = [])
905+
{
906+
$radius = $options['radius'] ?? 100;
907+
$omission = $options['omission'] ?? '...';
908+
909+
preg_match('/^(.*?)(' . preg_quote((string) $phrase) . ')(.*)$/iu', (string) $text, $matches);
910+
911+
if (empty($matches)) {
912+
return null;
913+
}
914+
915+
$startStr = ltrim($matches[1]);
916+
$start = Str::of(mb_substr($matches[1], max(mb_strlen($startStr, 'UTF-8') - $radius, 0), $radius, 'UTF-8'))->ltrim();
917+
$start = $start->unless(
918+
(fn ($startWithRadius) => $startWithRadius->exactly($startStr))($start),
919+
fn ($startWithRadius) => $startWithRadius->prepend($omission),
920+
);
921+
922+
$endStr = rtrim($matches[3]);
923+
$end = Str::of(mb_substr($endStr, 0, $radius, 'UTF-8'))->rtrim();
924+
$end = $end->unless(
925+
(fn ($endWithRadius) => $endWithRadius->exactly($endStr))($end),
926+
fn ($endWithRadius) => $endWithRadius->append($omission),
927+
);
928+
929+
return $start->append($matches[2], $end)->__toString();
930+
}
931+
932+
public static function isJson($value): bool
933+
{
934+
if (! is_string($value)) {
935+
return false;
936+
}
937+
938+
if (function_exists('json_validate')) {
939+
return json_validate($value, 512);
940+
}
941+
942+
try {
943+
json_decode($value, true, 512, JSON_THROW_ON_ERROR);
944+
} catch (JsonException $e) {
945+
return false;
946+
}
947+
948+
return true;
949+
}
950+
951+
public static function lcfirst($string): string
952+
{
953+
return Str::lower(Str::substr($string, 0, 1)) . Str::substr($string, 1);
954+
}
955+
956+
public static function password($length = 32, $letters = true, $numbers = true, $symbols = true, $spaces = false)
957+
{
958+
return (new Collection())
959+
->when($letters, fn ($c) => $c->merge([
960+
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
961+
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
962+
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
963+
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
964+
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
965+
]))
966+
->when($numbers, fn ($c) => $c->merge([
967+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
968+
]))
969+
->when($symbols, fn ($c) => $c->merge([
970+
'~', '!', '#', '$', '%', '^', '&', '*', '(', ')', '-',
971+
'_', '.', ',', '<', '>', '?', '/', '\\', '{', '}', '[',
972+
']', '|', ':', ';',
973+
]))
974+
->when($spaces, fn ($c) => $c->merge([' ']))
975+
->pipe(fn ($c) => Collection::times($length, fn () => $c[random_int(0, $c->count() - 1)]))
976+
->implode('');
977+
}
978+
979+
public static function replaceStart($search, $replace, $subject)
980+
{
981+
$search = (string) $search;
982+
983+
if ($search === '') {
984+
return $subject;
985+
}
986+
987+
if (static::startsWith($subject, $search)) {
988+
return static::replaceFirst($search, $replace, $subject);
989+
}
990+
991+
return $subject;
992+
}
993+
994+
public static function replaceEnd($search, $replace, $subject)
995+
{
996+
$search = (string) $search;
997+
998+
if ($search === '') {
999+
return $subject;
1000+
}
1001+
1002+
if (static::endsWith($subject, $search)) {
1003+
return static::replaceLast($search, $replace, $subject);
1004+
}
1005+
1006+
return $subject;
1007+
}
1008+
1009+
public static function reverse($value): string
1010+
{
1011+
return implode(array_reverse(mb_str_split($value)));
1012+
}
1013+
1014+
public static function squish($value): array|string|null
1015+
{
1016+
return preg_replace('~(\s|\x{3164}|\x{1160})+~u', ' ', preg_replace('~^[\s\x{FEFF}]+|[\s\x{FEFF}]+$~u', '', $value));
1017+
}
1018+
1019+
public static function substrReplace($string, $replace, $offset = 0, $length = null): array|string
1020+
{
1021+
if ($length === null) {
1022+
$length = strlen($string);
1023+
}
1024+
1025+
return substr_replace($string, $replace, $offset, $length);
1026+
}
1027+
1028+
public static function swap(array $map, $subject): array|string
1029+
{
1030+
return str_replace(array_keys($map), array_values($map), $subject);
1031+
}
1032+
1033+
public static function ucsplit($string): array|bool
1034+
{
1035+
return preg_split('/(?=\p{Lu})/u', $string, -1, PREG_SPLIT_NO_EMPTY);
1036+
}
1037+
1038+
public static function wordCount($string): array|int
1039+
{
1040+
return str_word_count($string);
1041+
}
1042+
1043+
public static function wrap($value, $before, $after = null): string
1044+
{
1045+
return $before . $value . ($after ??= $before);
1046+
}
1047+
1048+
public static function wordWrap($string, $characters = 75, $break = "\n", $cutLongWords = false): string
1049+
{
1050+
return wordwrap($string, $characters, $break, $cutLongWords);
1051+
}
1052+
8801053
/**
8811054
* Returns the replacements for the ascii method.
8821055
* Note: Adapted from Stringy\Stringy.

src/Stringable.php

Lines changed: 156 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use ArrayAccess;
1515
use Closure;
16+
use Hyperf\Collection\Collection;
1617
use Hyperf\Conditionable\Conditionable;
1718
use Hyperf\Macroable\Macroable;
1819
use Hyperf\Tappable\Tappable;
@@ -246,7 +247,7 @@ public function exactly($value)
246247
*
247248
* @param string $delimiter
248249
* @param int $limit
249-
* @return \Hyperf\Collection\Collection
250+
* @return Collection
250251
*/
251252
public function explode($delimiter, $limit = PHP_INT_MAX)
252253
{
@@ -259,7 +260,7 @@ public function explode($delimiter, $limit = PHP_INT_MAX)
259260
* @param int|string $pattern
260261
* @param int $limit
261262
* @param int $flags
262-
* @return \Hyperf\Collection\Collection
263+
* @return Collection
263264
*/
264265
public function split($pattern, $limit = -1, $flags = 0)
265266
{
@@ -404,7 +405,7 @@ public function isMatch($pattern)
404405
* Get the string matching the given pattern.
405406
*
406407
* @param string $pattern
407-
* @return \Hyperf\Collection\Collection
408+
* @return Collection
408409
*/
409410
public function matchAll($pattern)
410411
{
@@ -865,4 +866,156 @@ public function offsetUnset(mixed $offset): void
865866
{
866867
unset($this->value[$offset]);
867868
}
869+
870+
public function betweenFirst($from, $to): static
871+
{
872+
return new static(Str::betweenFirst($this->value, $from, $to));
873+
}
874+
875+
public function classNamespace(): static
876+
{
877+
return new static(Str::classNamespace($this->value));
878+
}
879+
880+
public function convertCase($mode = MB_CASE_FOLD, $encoding = 'UTF-8'): static
881+
{
882+
return new static(Str::convertCase($this->value, $mode, $encoding));
883+
}
884+
885+
public function excerpt($phrase = '', $options = []): ?string
886+
{
887+
return Str::excerpt($this->value, $phrase, $options);
888+
}
889+
890+
public function isJson(): bool
891+
{
892+
return Str::isJson($this->value);
893+
}
894+
895+
public function lcfirst(): static
896+
{
897+
return new static(Str::lcfirst($this->value));
898+
}
899+
900+
public function newLine($count = 1): static
901+
{
902+
return $this->append(str_repeat(PHP_EOL, $count));
903+
}
904+
905+
public function replaceStart($search, $replace): static
906+
{
907+
return new static(Str::replaceStart($search, $replace, $this->value));
908+
}
909+
910+
public function replaceEnd($search, $replace): static
911+
{
912+
return new static(Str::replaceEnd($search, $replace, $this->value));
913+
}
914+
915+
public function reverse(): static
916+
{
917+
return new static(Str::reverse($this->value));
918+
}
919+
920+
public function scan($format): Collection
921+
{
922+
return collect(sscanf($this->value, $format));
923+
}
924+
925+
public function squish(): static
926+
{
927+
return new static(Str::squish($this->value));
928+
}
929+
930+
public function substrReplace($replace, $offset = 0, $length = null): static
931+
{
932+
return new static(Str::substrReplace($this->value, $replace, $offset, $length));
933+
}
934+
935+
public function swap(array $map)
936+
{
937+
return new static(strtr($this->value, $map));
938+
}
939+
940+
public function toString(): string
941+
{
942+
return $this->value;
943+
}
944+
945+
public function ucsplit(): Collection
946+
{
947+
return collect(Str::ucsplit($this->value));
948+
}
949+
950+
public function value(): string
951+
{
952+
return $this->toString();
953+
}
954+
955+
public function whenContains($needles, $callback, $default = null)
956+
{
957+
return $this->when($this->contains($needles), $callback, $default);
958+
}
959+
960+
public function whenContainsAll(array $needles, $callback, $default = null)
961+
{
962+
return $this->when($this->containsAll($needles), $callback, $default);
963+
}
964+
965+
public function whenEndsWith($needles, $callback, $default = null)
966+
{
967+
return $this->when($this->endsWith($needles), $callback, $default);
968+
}
969+
970+
public function whenExactly($needles, $callback, $default = null)
971+
{
972+
return $this->when($this->exactly($needles), $callback, $default);
973+
}
974+
975+
public function whenIs($pattern, $callback, $default = null)
976+
{
977+
return $this->when($this->is($pattern), $callback, $default);
978+
}
979+
980+
public function whenIsUlid($callback, $default = null)
981+
{
982+
return $this->when($this->isUlid(), $callback, $default);
983+
}
984+
985+
public function whenIsUuid($callback, $default = null)
986+
{
987+
return $this->when($this->isUuid(), $callback, $default);
988+
}
989+
990+
public function whenNotExactly($needles, $callback, $default = null)
991+
{
992+
return $this->when(! $this->exactly($needles), $callback, $default);
993+
}
994+
995+
public function whenStartsWith($needles, $callback, $default = null)
996+
{
997+
return $this->when($this->startsWith($needles), $callback, $default);
998+
}
999+
1000+
public function whenTest($pattern, $callback, $default = null)
1001+
{
1002+
return $this->when($this->test($pattern), $callback, $default);
1003+
}
1004+
1005+
public function wrap($before, $after = null)
1006+
{
1007+
return new static(Str::wrap($this->value, $before, $after));
1008+
}
1009+
1010+
/**
1011+
* Wrap a string to a given number of characters.
1012+
*
1013+
* @param mixed $characters
1014+
* @param mixed $break
1015+
* @param mixed $cutLongWords
1016+
*/
1017+
public function wordWrap($characters = 75, $break = "\n", $cutLongWords = false): static
1018+
{
1019+
return new static(Str::wordWrap($this->value, $characters, $break, $cutLongWords));
1020+
}
8681021
}

0 commit comments

Comments
 (0)