string = (string) $string; $this->encoding = $encoding ?? mb_internal_encoding(); } /** * Static initializing a String object. * * @param string|Stringable $string * @param string|null $encoding * * @return static * * @see Text::__construct() * @psalm-suppress UnsafeInstantiation */ public static function create(string|Stringable $string, ?string $encoding = null): static { return new static($string, $encoding); } /** * Returns the used encoding * * @return string */ public function getEncoding(): string { return $this->encoding; } /** * Get string length * * * $str = new Text('Hello World!');
* $str->length(); // 12 * * $str = new Text('いちりんしゃ');
* $str->length(); // 6 *
* * @return int Returns the length */ public function length(): int { return mb_strlen($this->string, $this->encoding); } /** * Appends $string and returns as a new Text * * @param string|Stringable $string * * @return Text */ public function append(string|Stringable $string): self { return new self($this->string . $string, $this->encoding); } /** * Prepends $string and returns as a new Text * * @param string|Stringable $string $string * * @return Text */ public function prepend(string|Stringable $string): self { return new self($string . $this->string, $this->encoding); } /** * Inserts a substring at the given index * * * $str = new Text('Hello World!');
* $str->insert('to this ', 5); // Hello to this World! *
* * @param string|Stringable $substring * @param int $index * * @return Text */ public function insert(string|Stringable $substring, int $index): self { if ($index <= 0) { return $this->prepend($substring); } if ($index > $this->length()) { return $this->append($substring); } $start = mb_substr($this->string, 0, $index, $this->encoding); $end = mb_substr($this->string, $index, $this->length(), $this->encoding); return new self($start . $substring . $end); } // // // SLICING AND SUBSTRING // // /** * Slices a piece of the string from a given offset with a specified length. * If no length is given, the String is sliced to its maximum length. * * @see #substring * * @param int $offset * @param int|null $length * * @return Text */ public function slice(int $offset, ?int $length = null): self { $offset = $this->prepareOffset($offset); $length = $this->prepareLength($offset, $length); return new self(mb_substr($this->string, $offset, $length, $this->encoding), $this->encoding); } /** * Slices a piece of the string from a given start to an end. * If no length is given, the String is sliced to its maximum length. * * @see #slice * * @param int $start * @param int|null $end * * @return Text */ public function substring(int $start, ?int $end = null): self { $length = $this->length(); if (null === $end) { $end = $length; } if ($end < 0) { $end = $length + $end; } $end = min($end, $length); $start = min($start, $end); $end = max($start, $end); $end = $end - $start; return new self(mb_substr($this->string, $start, $end, $this->encoding), $this->encoding); } /** * Count the number of substring occurrences. * * @param string|Stringable $substring The substring to count the occurrencies * @param bool $caseSensitive Force case-sensitivity * * @return int */ public function countSubstring(string|Stringable $substring, bool $caseSensitive = true): int { if (empty($substring)) { throw new \InvalidArgumentException('$substring cannot be empty'); } if ($caseSensitive) { return mb_substr_count($this->string, (string) $substring, $this->encoding); } $str = mb_strtoupper($this->string, $this->encoding); $substring = mb_strtoupper((string) $substring, $this->encoding); return mb_substr_count($str, $substring, $this->encoding); } // // // REPLACING // // /** * Replace all occurrences of the search string with the replacement string * * @see #supplant * * @param Arrayable|Stringable|array|string $search * The value being searched for, otherwise known as the needle. An array may be used * to designate multiple needles. * @param Arrayable|Stringable[]|array|string $replace * The replacement value that replaces found search values. An array may be used to * designate multiple replacements. * * @return Text * * @psalm-suppress MixedArgumentTypeCoercion */ public function replace(Arrayable|Stringable|array|string $search, Arrayable|Stringable|array|string $replace): self { $search = $search instanceof Stringable ? (string) $search : ($search instanceof Arrayable ? $search->toArray() : $search); $replace = $replace instanceof Stringable ? (string) $replace : ($replace instanceof Arrayable ? $replace->toArray() : $replace); return new self(str_replace($search, $replace, $this->string), $this->encoding); } /** * Replaces all occurrences of given replacement map. Keys will be replaced with its values. * * @param string[] $map the replacements. Keys will be replaced with its value. * * @return Text */ public function supplant(array $map): self { return new self(str_replace(array_keys($map), array_values($map), $this->string), $this->encoding); } /** * Replace text within a portion of a string. * * @param string|Stringable $replacement * @param int $offset * @param int|null $length * * @return Text */ public function splice(string|Stringable $replacement, int $offset, ?int $length = null): self { $offset = $this->prepareOffset($offset); $length = $this->prepareLength($offset, $length); $start = $this->substring(0, $offset); $end = $this->substring($offset + $length); return new self($start . $replacement . $end); } // // // STRING OPERATIONS // // /** * Strip whitespace (or other characters) from the beginning and end of the string * * @param string|Stringable $characters * Optionally, the stripped characters can also be specified using the mask parameter. * Simply list all characters that you want to be stripped. With .. you can specify a * range of characters. * * @return Text */ public function trim(string|Stringable $characters = " \t\n\r\v\0"): self { return new self(trim($this->string, (string) $characters), $this->encoding); } /** * Strip whitespace (or other characters) from the beginning of the string * * @param string|Stringable $characters * Optionally, the stripped characters can also be specified using the mask parameter. * Simply list all characters that you want to be stripped. With .. you can specify a * range of characters. * * @return Text */ public function trimStart(string|Stringable $characters = " \t\n\r\v\0"): self { return new self(ltrim($this->string, (string) $characters), $this->encoding); } /** * Strip whitespace (or other characters) from the end of the string * * @param string|Stringable $characters * Optionally, the stripped characters can also be specified using the mask parameter. * Simply list all characters that you want to be stripped. With .. you can specify a * range of characters. * * @return Text */ public function trimEnd(string|Stringable $characters = " \t\n\r\v\0"): self { return new self(rtrim($this->string, (string) $characters), $this->encoding); } /** * Adds padding to the start and end * * @param int $length * @param string|Stringable $padding * * @return Text */ public function pad(int $length, string|Stringable $padding = ' '): self { $len = $length - $this->length(); return $this->applyPadding(floor($len / 2), ceil($len / 2), $padding); } /** * Adds padding to the start * * @param int $length * @param string|Stringable $padding * * @return Text */ public function padStart(int $length, string|Stringable $padding = ' ') { return $this->applyPadding($length - $this->length(), 0, $padding); } /** * Adds padding to the end * * @param int $length * @param string|Stringable $padding * * @return Text */ public function padEnd(int $length, string|Stringable $padding = ' '): self { return $this->applyPadding(0, $length - $this->length(), $padding); } /** * Adds the specified amount of left and right padding to the given string. * The default character used is a space. * * @see https://github.com/danielstjules/Stringy/blob/master/src/Stringy.php * * @param int|float $left Length of left padding * @param int|float $right Length of right padding * @param string|Stringable $padStr String used to pad * * @return Text the padded string */ protected function applyPadding(int|float $left = 0, int|float $right = 0, string|Stringable $padStr = ' '): self { $length = mb_strlen((string) $padStr, $this->encoding); $strLength = $this->length(); $paddedLength = $strLength + $left + $right; if (!$length || $paddedLength <= $strLength) { return $this; } $leftPadding = mb_substr(str_repeat((string) $padStr, (int) ceil($left / $length)), 0, (int) $left, $this->encoding); $rightPadding = mb_substr(str_repeat((string) $padStr, (int) ceil($right / $length)), 0, (int) $right, $this->encoding); return new self($leftPadding . $this->string . $rightPadding); } /** * Ensures a given substring at the start of the string * * @param string $substring * * @return Text */ public function ensureStart(string $substring): self { if (!$this->startsWith($substring)) { return $this->prepend($substring); } return $this; } /** * Ensures a given substring at the end of the string * * @param string $substring * * @return Text */ public function ensureEnd(string $substring): self { if (!$this->endsWith($substring)) { return $this->append($substring); } return $this; } /** * Returns a copy of the string wrapped at a given number of characters * * @param int $width The number of characters at which the string will be wrapped. * @param string $break The line is broken using the optional break parameter. * @param bool $cut * If the cut is set to TRUE, the string is always wrapped at or before the specified * width. So if you have a word that is larger than the given width, it is broken apart. * * @return Text Returns the string wrapped at the specified length. */ public function wrapWords(int $width = 75, string $break = "\n", bool $cut = false): self { return new self(wordwrap($this->string, $width, $break, $cut), $this->encoding); } /** * Repeat the string $times times. If $times is 0, it returns ''. * * @param int $multiplier * * @throws \InvalidArgumentException If $times is negative. * * @return Text */ public function repeat(int $multiplier): self { return new self(str_repeat($this->string, $multiplier), $this->encoding); } /** * Reverses the character order * * @return Text */ public function reverse(): self { return new self(strrev($this->string), $this->encoding); } /** * Truncates the string with a substring and ensures it doesn't exceed the given length * * @param int $length * @param string $substring * * @return Text */ public function truncate(int $length, string $substring = ''): self { if ($this->length() <= $length) { return new self($this->string, $this->encoding); } $substrLen = mb_strlen($substring, $this->encoding); if ($this->length() + $substrLen > $length) { $length -= $substrLen; } return $this->substring(0, $length)->append($substring); } /** * Returns the native string * * @return string */ public function toString(): string { return $this->string; } protected function getString(): string { return $this->toString(); } // // // MAGIC HAPPENS HERE // // public function __toString(): string { return $this->string; } }