diff --git a/src/Symfony/Component/String/AbstractString.php b/src/Symfony/Component/String/AbstractString.php index d3d95d40a467..62a4f89200c6 100644 --- a/src/Symfony/Component/String/AbstractString.php +++ b/src/Symfony/Component/String/AbstractString.php @@ -95,12 +95,16 @@ public static function wrap(array $values): array * * @return static */ - public function after($needle, bool $includeNeedle = false, int $offset = 0): self + public function after(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = \PHP_INT_MAX; - foreach ((array) $needle as $n) { + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); @@ -126,12 +130,16 @@ public function after($needle, bool $includeNeedle = false, int $offset = 0): se * * @return static */ - public function afterLast($needle, bool $includeNeedle = false, int $offset = 0): self + public function afterLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = null; - foreach ((array) $needle as $n) { + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); @@ -162,12 +170,16 @@ abstract public function append(string ...$suffix): self; * * @return static */ - public function before($needle, bool $includeNeedle = false, int $offset = 0): self + public function before(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = \PHP_INT_MAX; - foreach ((array) $needle as $n) { + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); @@ -193,12 +205,16 @@ public function before($needle, bool $includeNeedle = false, int $offset = 0): s * * @return static */ - public function beforeLast($needle, bool $includeNeedle = false, int $offset = 0): self + public function beforeLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = null; - foreach ((array) $needle as $n) { + if (\is_string($needle)) { + $needle = [$needle]; + } + + foreach ($needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); @@ -253,7 +269,7 @@ public function collapseWhitespace(): self /** * @param string|string[] $needle */ - public function containsAny($needle): bool + public function containsAny(string|iterable $needle): bool { return null !== $this->indexOf($needle); } @@ -261,9 +277,9 @@ public function containsAny($needle): bool /** * @param string|string[] $suffix */ - public function endsWith($suffix): bool + public function endsWith(string|iterable $suffix): bool { - if (!\is_array($suffix) && !$suffix instanceof \Traversable) { + if (\is_string($suffix)) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -316,9 +332,9 @@ public function ensureStart(string $prefix): self /** * @param string|string[] $string */ - public function equalsTo($string): bool + public function equalsTo(string|iterable $string): bool { - if (!\is_array($string) && !$string instanceof \Traversable) { + if (\is_string($string)) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -350,9 +366,9 @@ public function ignoreCase(): self /** * @param string|string[] $needle */ - public function indexOf($needle, int $offset = 0): ?int + public function indexOf(string|iterable $needle, int $offset = 0): ?int { - if (!\is_array($needle) && !$needle instanceof \Traversable) { + if (\is_string($needle)) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -372,9 +388,9 @@ public function indexOf($needle, int $offset = 0): ?int /** * @param string|string[] $needle */ - public function indexOfLast($needle, int $offset = 0): ?int + public function indexOfLast(string|iterable $needle, int $offset = 0): ?int { - if (!\is_array($needle) && !$needle instanceof \Traversable) { + if (\is_string($needle)) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } @@ -467,7 +483,7 @@ abstract public function replace(string $from, string $to): self; * * @return static */ - abstract public function replaceMatches(string $fromRegexp, $to): self; + abstract public function replaceMatches(string $fromRegexp, string|callable $to): self; /** * @return static @@ -540,9 +556,9 @@ public function split(string $delimiter, int $limit = null, int $flags = null): /** * @param string|string[] $prefix */ - public function startsWith($prefix): bool + public function startsWith(string|iterable $prefix): bool { - if (!\is_array($prefix) && !$prefix instanceof \Traversable) { + if (\is_string($prefix)) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } diff --git a/src/Symfony/Component/String/AbstractUnicodeString.php b/src/Symfony/Component/String/AbstractUnicodeString.php index 00e48984c6df..e24fa3c37dc4 100644 --- a/src/Symfony/Component/String/AbstractUnicodeString.php +++ b/src/Symfony/Component/String/AbstractUnicodeString.php @@ -303,7 +303,7 @@ public function padStart(int $length, string $padStr = ' '): parent return $this->pad($length, $pad, \STR_PAD_LEFT); } - public function replaceMatches(string $fromRegexp, $to): parent + public function replaceMatches(string $fromRegexp, string|callable $to): parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; diff --git a/src/Symfony/Component/String/ByteString.php b/src/Symfony/Component/String/ByteString.php index bbf8614cf7be..63183bd489b4 100644 --- a/src/Symfony/Component/String/ByteString.php +++ b/src/Symfony/Component/String/ByteString.php @@ -129,27 +129,23 @@ public function chunk(int $length = 1): array return $chunks; } - public function endsWith($suffix): bool + public function endsWith(string|iterable|AbstractString $suffix): bool { - if ($suffix instanceof parent) { + if ($suffix instanceof AbstractString) { $suffix = $suffix->string; - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { + } elseif (!\is_string($suffix)) { return parent::endsWith($suffix); - } else { - $suffix = (string) $suffix; } return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); } - public function equalsTo($string): bool + public function equalsTo(string|iterable|AbstractString $string): bool { - if ($string instanceof parent) { + if ($string instanceof AbstractString) { $string = $string->string; - } elseif (\is_array($string) || $string instanceof \Traversable) { + } elseif (!\is_string($string)) { return parent::equalsTo($string); - } else { - $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { @@ -167,14 +163,12 @@ public function folded(): parent return $str; } - public function indexOf($needle, int $offset = 0): ?int + public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int { - if ($needle instanceof parent) { + if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { + } elseif (!\is_string($needle)) { return parent::indexOf($needle, $offset); - } else { - $needle = (string) $needle; } if ('' === $needle) { @@ -186,14 +180,12 @@ public function indexOf($needle, int $offset = 0): ?int return false === $i ? null : $i; } - public function indexOfLast($needle, int $offset = 0): ?int + public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int { - if ($needle instanceof parent) { + if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { + } elseif (!\is_string($needle)) { return parent::indexOfLast($needle, $offset); - } else { - $needle = (string) $needle; } if ('' === $needle) { @@ -305,7 +297,7 @@ public function replace(string $from, string $to): parent return $str; } - public function replaceMatches(string $fromRegexp, $to): parent + public function replaceMatches(string $fromRegexp, string|callable $to): parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; @@ -404,9 +396,9 @@ public function split(string $delimiter, int $limit = null, int $flags = null): return $chunks; } - public function startsWith($prefix): bool + public function startsWith(string|iterable|AbstractString $prefix): bool { - if ($prefix instanceof parent) { + if ($prefix instanceof AbstractString) { $prefix = $prefix->string; } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); diff --git a/src/Symfony/Component/String/CodePointString.php b/src/Symfony/Component/String/CodePointString.php index 8ab9209413b5..de52a821942c 100644 --- a/src/Symfony/Component/String/CodePointString.php +++ b/src/Symfony/Component/String/CodePointString.php @@ -80,14 +80,12 @@ public function codePointsAt(int $offset): array return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')]; } - public function endsWith($suffix): bool + public function endsWith(string|iterable|AbstractString $suffix): bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { + } elseif (!\is_string($suffix)) { return parent::endsWith($suffix); - } else { - $suffix = (string) $suffix; } if ('' === $suffix || !preg_match('//u', $suffix)) { @@ -101,14 +99,12 @@ public function endsWith($suffix): bool return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix)); } - public function equalsTo($string): bool + public function equalsTo(string|iterable|AbstractString $string): bool { if ($string instanceof AbstractString) { $string = $string->string; - } elseif (\is_array($string) || $string instanceof \Traversable) { + } elseif (!\is_string($string)) { return parent::equalsTo($string); - } else { - $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { @@ -118,14 +114,12 @@ public function equalsTo($string): bool return $string === $this->string; } - public function indexOf($needle, int $offset = 0): ?int + public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { + } elseif (!\is_string($needle)) { return parent::indexOf($needle, $offset); - } else { - $needle = (string) $needle; } if ('' === $needle) { @@ -137,14 +131,12 @@ public function indexOf($needle, int $offset = 0): ?int return false === $i ? null : $i; } - public function indexOfLast($needle, int $offset = 0): ?int + public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { + } elseif (!\is_string($needle)) { return parent::indexOfLast($needle, $offset); - } else { - $needle = (string) $needle; } if ('' === $needle) { @@ -247,14 +239,12 @@ public function split(string $delimiter, int $limit = null, int $flags = null): return $chunks; } - public function startsWith($prefix): bool + public function startsWith(string|iterable|AbstractString $prefix): bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; - } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { + } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); - } else { - $prefix = (string) $prefix; } if ('' === $prefix || !preg_match('//u', $prefix)) { diff --git a/src/Symfony/Component/String/LazyString.php b/src/Symfony/Component/String/LazyString.php index f2cca423f8ad..7f32c47c4572 100644 --- a/src/Symfony/Component/String/LazyString.php +++ b/src/Symfony/Component/String/LazyString.php @@ -25,10 +25,10 @@ class LazyString implements \Stringable, \JsonSerializable * * @return static */ - public static function fromCallable($callback, ...$arguments): self + public static function fromCallable(callable|array $callback, mixed ...$arguments): self { - if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, get_debug_type($callback))); + if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '['.implode(', ', array_map('get_debug_type', $callback)).']')); } $lazyString = new static(); @@ -50,16 +50,10 @@ public static function fromCallable($callback, ...$arguments): self } /** - * @param string|int|float|bool|\Stringable $value - * * @return static */ - public static function fromStringable($value): self + public static function fromStringable(string|int|float|bool|\Stringable $value): self { - if (!self::isStringable($value)) { - throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, get_debug_type($value))); - } - if (\is_object($value)) { return static::fromCallable([$value, '__toString']); } @@ -73,19 +67,17 @@ public static function fromStringable($value): self /** * Tells whether the provided value can be cast to string. */ - final public static function isStringable($value): bool + final public static function isStringable(mixed $value): bool { - return \is_string($value) || $value instanceof self || (\is_object($value) ? method_exists($value, '__toString') : is_scalar($value)); + return \is_string($value) || $value instanceof \Stringable || is_scalar($value); } /** * Casts scalars and stringable objects to strings. * - * @param object|string|int|float|bool $value - * * @throws \TypeError When the provided value is not stringable */ - final public static function resolve($value): string + final public static function resolve(\Stringable|string|int|float|bool $value): string { return $value; } diff --git a/src/Symfony/Component/String/Slugger/AsciiSlugger.php b/src/Symfony/Component/String/Slugger/AsciiSlugger.php index 5aecfeb5fcd7..a4bcd817184e 100644 --- a/src/Symfony/Component/String/Slugger/AsciiSlugger.php +++ b/src/Symfony/Component/String/Slugger/AsciiSlugger.php @@ -66,15 +66,8 @@ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface */ private $transliterators = []; - /** - * @param array|\Closure|null $symbolsMap - */ - public function __construct(string $defaultLocale = null, $symbolsMap = null) + public function __construct(string $defaultLocale = null, array|\Closure|null $symbolsMap = null) { - if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) { - throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap))); - } - $this->defaultLocale = $defaultLocale; $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } diff --git a/src/Symfony/Component/String/UnicodeString.php b/src/Symfony/Component/String/UnicodeString.php index b3b5527d41a8..b3d4f50fd215 100644 --- a/src/Symfony/Component/String/UnicodeString.php +++ b/src/Symfony/Component/String/UnicodeString.php @@ -82,14 +82,12 @@ public function chunk(int $length = 1): array return $chunks; } - public function endsWith($suffix): bool + public function endsWith(string|iterable|AbstractString $suffix): bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; - } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { + } elseif (!\is_string($suffix)) { return parent::endsWith($suffix); - } else { - $suffix = (string) $suffix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -106,14 +104,12 @@ public function endsWith($suffix): bool return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); } - public function equalsTo($string): bool + public function equalsTo(string|iterable|AbstractString $string): bool { if ($string instanceof AbstractString) { $string = $string->string; - } elseif (\is_array($string) || $string instanceof \Traversable) { + } elseif (!\is_string($string)) { return parent::equalsTo($string); - } else { - $string = (string) $string; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -126,14 +122,12 @@ public function equalsTo($string): bool return $string === $this->string; } - public function indexOf($needle, int $offset = 0): ?int + public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { + } elseif (!\is_string($needle)) { return parent::indexOf($needle, $offset); - } else { - $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -152,14 +146,12 @@ public function indexOf($needle, int $offset = 0): ?int return false === $i ? null : $i; } - public function indexOfLast($needle, int $offset = 0): ?int + public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; - } elseif (\is_array($needle) || $needle instanceof \Traversable) { + } elseif (!\is_string($needle)) { return parent::indexOfLast($needle, $offset); - } else { - $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; @@ -256,7 +248,7 @@ public function replace(string $from, string $to): AbstractString return $str; } - public function replaceMatches(string $fromRegexp, $to): AbstractString + public function replaceMatches(string $fromRegexp, string|callable $to): AbstractString { $str = parent::replaceMatches($fromRegexp, $to); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); @@ -327,14 +319,12 @@ public function split(string $delimiter, int $limit = null, int $flags = null): return $chunks; } - public function startsWith($prefix): bool + public function startsWith(string|iterable|AbstractString $prefix): bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; - } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { + } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); - } else { - $prefix = (string) $prefix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;