PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.0
Independent Analytics – WordPress Analytics Plugin v2.15.0
2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / symfony / string / AbstractString.php
independent-analytics / vendor / symfony / string Last commit date
Exception 2 years ago Inflector 5 days ago Resources 5 days ago Slugger 5 days ago AbstractString.php 5 days ago AbstractUnicodeString.php 5 days ago ByteString.php 5 days ago CodePointString.php 5 days ago LazyString.php 5 days ago UnicodeString.php 5 days ago
AbstractString.php
564 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 namespace IAWPSCOPED\Symfony\Component\String;
12
13 use IAWPSCOPED\Symfony\Component\String\Exception\ExceptionInterface;
14 use IAWPSCOPED\Symfony\Component\String\Exception\InvalidArgumentException;
15 use IAWPSCOPED\Symfony\Component\String\Exception\RuntimeException;
16 /**
17 * Represents a string of abstract characters.
18 *
19 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
20 * This class is the abstract type to use as a type-hint when the logic you want to
21 * implement doesn't care about the exact variant it deals with.
22 *
23 * @author Nicolas Grekas <p@tchwork.com>
24 * @author Hugo Hamon <hugohamon@neuf.fr>
25 *
26 * @throws ExceptionInterface
27 * @internal
28 */
29 abstract class AbstractString implements \Stringable, \JsonSerializable
30 {
31 public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER;
32 public const PREG_SET_ORDER = \PREG_SET_ORDER;
33 public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE;
34 public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL;
35 public const PREG_SPLIT = 0;
36 public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY;
37 public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE;
38 public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE;
39 protected $string = '';
40 protected $ignoreCase = \false;
41 public abstract function __construct(string $string = '');
42 /**
43 * Unwraps instances of AbstractString back to strings.
44 *
45 * @return string[]|array
46 */
47 public static function unwrap(array $values) : array
48 {
49 foreach ($values as $k => $v) {
50 if ($v instanceof self) {
51 $values[$k] = $v->__toString();
52 } elseif (\is_array($v) && $values[$k] !== ($v = static::unwrap($v))) {
53 $values[$k] = $v;
54 }
55 }
56 return $values;
57 }
58 /**
59 * Wraps (and normalizes) strings in instances of AbstractString.
60 *
61 * @return static[]|array
62 */
63 public static function wrap(array $values) : array
64 {
65 $i = 0;
66 $keys = null;
67 foreach ($values as $k => $v) {
68 if (\is_string($k) && '' !== $k && $k !== ($j = (string) new static($k))) {
69 $keys = $keys ?? \array_keys($values);
70 $keys[$i] = $j;
71 }
72 if (\is_string($v)) {
73 $values[$k] = new static($v);
74 } elseif (\is_array($v) && $values[$k] !== ($v = static::wrap($v))) {
75 $values[$k] = $v;
76 }
77 ++$i;
78 }
79 return null !== $keys ? \array_combine($keys, $values) : $values;
80 }
81 /**
82 * @param string|string[] $needle
83 */
84 public function after(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0) : static
85 {
86 $str = clone $this;
87 $i = \PHP_INT_MAX;
88 if (\is_string($needle)) {
89 $needle = [$needle];
90 }
91 foreach ($needle as $n) {
92 $n = (string) $n;
93 $j = $this->indexOf($n, $offset);
94 if (null !== $j && $j < $i) {
95 $i = $j;
96 $str->string = $n;
97 }
98 }
99 if (\PHP_INT_MAX === $i) {
100 return $str;
101 }
102 if (!$includeNeedle) {
103 $i += $str->length();
104 }
105 return $this->slice($i);
106 }
107 /**
108 * @param string|string[] $needle
109 */
110 public function afterLast(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0) : static
111 {
112 $str = clone $this;
113 $i = null;
114 if (\is_string($needle)) {
115 $needle = [$needle];
116 }
117 foreach ($needle as $n) {
118 $n = (string) $n;
119 $j = $this->indexOfLast($n, $offset);
120 if (null !== $j && $j >= $i) {
121 $i = $offset = $j;
122 $str->string = $n;
123 }
124 }
125 if (null === $i) {
126 return $str;
127 }
128 if (!$includeNeedle) {
129 $i += $str->length();
130 }
131 return $this->slice($i);
132 }
133 public abstract function append(string ...$suffix) : static;
134 /**
135 * @param string|string[] $needle
136 */
137 public function before(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0) : static
138 {
139 $str = clone $this;
140 $i = \PHP_INT_MAX;
141 if (\is_string($needle)) {
142 $needle = [$needle];
143 }
144 foreach ($needle as $n) {
145 $n = (string) $n;
146 $j = $this->indexOf($n, $offset);
147 if (null !== $j && $j < $i) {
148 $i = $j;
149 $str->string = $n;
150 }
151 }
152 if (\PHP_INT_MAX === $i) {
153 return $str;
154 }
155 if ($includeNeedle) {
156 $i += $str->length();
157 }
158 return $this->slice(0, $i);
159 }
160 /**
161 * @param string|string[] $needle
162 */
163 public function beforeLast(string|iterable $needle, bool $includeNeedle = \false, int $offset = 0) : static
164 {
165 $str = clone $this;
166 $i = null;
167 if (\is_string($needle)) {
168 $needle = [$needle];
169 }
170 foreach ($needle as $n) {
171 $n = (string) $n;
172 $j = $this->indexOfLast($n, $offset);
173 if (null !== $j && $j >= $i) {
174 $i = $offset = $j;
175 $str->string = $n;
176 }
177 }
178 if (null === $i) {
179 return $str;
180 }
181 if ($includeNeedle) {
182 $i += $str->length();
183 }
184 return $this->slice(0, $i);
185 }
186 /**
187 * @return int[]
188 */
189 public function bytesAt(int $offset) : array
190 {
191 $str = $this->slice($offset, 1);
192 return '' === $str->string ? [] : \array_values(\unpack('C*', $str->string));
193 }
194 public abstract function camel() : static;
195 /**
196 * @return static[]
197 */
198 public abstract function chunk(int $length = 1) : array;
199 public function collapseWhitespace() : static
200 {
201 $str = clone $this;
202 $str->string = \trim(\preg_replace("/(?:[ \n\r\t\f]{2,}+|[\n\r\t\f])/", ' ', $str->string), " \n\r\t\f");
203 return $str;
204 }
205 /**
206 * @param string|string[] $needle
207 */
208 public function containsAny(string|iterable $needle) : bool
209 {
210 return null !== $this->indexOf($needle);
211 }
212 /**
213 * @param string|string[] $suffix
214 */
215 public function endsWith(string|iterable $suffix) : bool
216 {
217 if (\is_string($suffix)) {
218 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
219 }
220 foreach ($suffix as $s) {
221 if ($this->endsWith((string) $s)) {
222 return \true;
223 }
224 }
225 return \false;
226 }
227 public function ensureEnd(string $suffix) : static
228 {
229 if (!$this->endsWith($suffix)) {
230 return $this->append($suffix);
231 }
232 $suffix = \preg_quote($suffix);
233 $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D';
234 return $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1');
235 }
236 public function ensureStart(string $prefix) : static
237 {
238 $prefix = new static($prefix);
239 if (!$this->startsWith($prefix)) {
240 return $this->prepend($prefix);
241 }
242 $str = clone $this;
243 $i = $prefixLen = $prefix->length();
244 while ($this->indexOf($prefix, $i) === $i) {
245 $str = $str->slice($prefixLen);
246 $i += $prefixLen;
247 }
248 return $str;
249 }
250 /**
251 * @param string|string[] $string
252 */
253 public function equalsTo(string|iterable $string) : bool
254 {
255 if (\is_string($string)) {
256 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
257 }
258 foreach ($string as $s) {
259 if ($this->equalsTo((string) $s)) {
260 return \true;
261 }
262 }
263 return \false;
264 }
265 public abstract function folded() : static;
266 public function ignoreCase() : static
267 {
268 $str = clone $this;
269 $str->ignoreCase = \true;
270 return $str;
271 }
272 /**
273 * @param string|string[] $needle
274 */
275 public function indexOf(string|iterable $needle, int $offset = 0) : ?int
276 {
277 if (\is_string($needle)) {
278 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
279 }
280 $i = \PHP_INT_MAX;
281 foreach ($needle as $n) {
282 $j = $this->indexOf((string) $n, $offset);
283 if (null !== $j && $j < $i) {
284 $i = $j;
285 }
286 }
287 return \PHP_INT_MAX === $i ? null : $i;
288 }
289 /**
290 * @param string|string[] $needle
291 */
292 public function indexOfLast(string|iterable $needle, int $offset = 0) : ?int
293 {
294 if (\is_string($needle)) {
295 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
296 }
297 $i = null;
298 foreach ($needle as $n) {
299 $j = $this->indexOfLast((string) $n, $offset);
300 if (null !== $j && $j >= $i) {
301 $i = $offset = $j;
302 }
303 }
304 return $i;
305 }
306 public function isEmpty() : bool
307 {
308 return '' === $this->string;
309 }
310 public abstract function join(array $strings, string $lastGlue = null) : static;
311 public function jsonSerialize() : string
312 {
313 return $this->string;
314 }
315 public abstract function length() : int;
316 public abstract function lower() : static;
317 /**
318 * Matches the string using a regular expression.
319 *
320 * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression.
321 *
322 * @return array All matches in a multi-dimensional array ordered according to flags
323 */
324 public abstract function match(string $regexp, int $flags = 0, int $offset = 0) : array;
325 public abstract function padBoth(int $length, string $padStr = ' ') : static;
326 public abstract function padEnd(int $length, string $padStr = ' ') : static;
327 public abstract function padStart(int $length, string $padStr = ' ') : static;
328 public abstract function prepend(string ...$prefix) : static;
329 public function repeat(int $multiplier) : static
330 {
331 if (0 > $multiplier) {
332 throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
333 }
334 $str = clone $this;
335 $str->string = \str_repeat($str->string, $multiplier);
336 return $str;
337 }
338 public abstract function replace(string $from, string $to) : static;
339 public abstract function replaceMatches(string $fromRegexp, string|callable $to) : static;
340 public abstract function reverse() : static;
341 public abstract function slice(int $start = 0, int $length = null) : static;
342 public abstract function snake() : static;
343 public abstract function splice(string $replacement, int $start = 0, int $length = null) : static;
344 /**
345 * @return static[]
346 */
347 public function split(string $delimiter, int $limit = null, int $flags = null) : array
348 {
349 if (null === $flags) {
350 throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.');
351 }
352 if ($this->ignoreCase) {
353 $delimiter .= 'i';
354 }
355 \set_error_handler(static function ($t, $m) {
356 throw new InvalidArgumentException($m);
357 });
358 try {
359 if (\false === ($chunks = \preg_split($delimiter, $this->string, $limit, $flags))) {
360 $lastError = \preg_last_error();
361 foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
362 if ($lastError === $v && '_ERROR' === \substr($k, -6)) {
363 throw new RuntimeException('Splitting failed with ' . $k . '.');
364 }
365 }
366 throw new RuntimeException('Splitting failed with unknown error code.');
367 }
368 } finally {
369 \restore_error_handler();
370 }
371 $str = clone $this;
372 if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) {
373 foreach ($chunks as &$chunk) {
374 $str->string = $chunk[0];
375 $chunk[0] = clone $str;
376 }
377 } else {
378 foreach ($chunks as &$chunk) {
379 $str->string = $chunk;
380 $chunk = clone $str;
381 }
382 }
383 return $chunks;
384 }
385 /**
386 * @param string|string[] $prefix
387 */
388 public function startsWith(string|iterable $prefix) : bool
389 {
390 if (\is_string($prefix)) {
391 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
392 }
393 foreach ($prefix as $prefix) {
394 if ($this->startsWith((string) $prefix)) {
395 return \true;
396 }
397 }
398 return \false;
399 }
400 public abstract function title(bool $allWords = \false) : static;
401 public function toByteString(string $toEncoding = null) : ByteString
402 {
403 $b = new ByteString();
404 $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding;
405 if (null === $toEncoding || $toEncoding === ($fromEncoding = $this instanceof AbstractUnicodeString || \preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252')) {
406 $b->string = $this->string;
407 return $b;
408 }
409 \set_error_handler(static function ($t, $m) {
410 throw new InvalidArgumentException($m);
411 });
412 try {
413 try {
414 $b->string = \mb_convert_encoding($this->string, $toEncoding, 'UTF-8');
415 } catch (InvalidArgumentException $e) {
416 if (!\function_exists('iconv')) {
417 throw $e;
418 }
419 $b->string = \iconv('UTF-8', $toEncoding, $this->string);
420 }
421 } finally {
422 \restore_error_handler();
423 }
424 return $b;
425 }
426 public function toCodePointString() : CodePointString
427 {
428 return new CodePointString($this->string);
429 }
430 public function toString() : string
431 {
432 return $this->string;
433 }
434 public function toUnicodeString() : UnicodeString
435 {
436 return new UnicodeString($this->string);
437 }
438 public abstract function trim(string $chars = " \t\n\r\x00\v\f ") : static;
439 public abstract function trimEnd(string $chars = " \t\n\r\x00\v\f ") : static;
440 /**
441 * @param string|string[] $prefix
442 */
443 public function trimPrefix($prefix) : static
444 {
445 if (\is_array($prefix) || $prefix instanceof \Traversable) {
446 foreach ($prefix as $s) {
447 $t = $this->trimPrefix($s);
448 if ($t->string !== $this->string) {
449 return $t;
450 }
451 }
452 return clone $this;
453 }
454 $str = clone $this;
455 if ($prefix instanceof self) {
456 $prefix = $prefix->string;
457 } else {
458 $prefix = (string) $prefix;
459 }
460 if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === \substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) {
461 $str->string = \substr($this->string, \strlen($prefix));
462 }
463 return $str;
464 }
465 public abstract function trimStart(string $chars = " \t\n\r\x00\v\f ") : static;
466 /**
467 * @param string|string[] $suffix
468 */
469 public function trimSuffix($suffix) : static
470 {
471 if (\is_array($suffix) || $suffix instanceof \Traversable) {
472 foreach ($suffix as $s) {
473 $t = $this->trimSuffix($s);
474 if ($t->string !== $this->string) {
475 return $t;
476 }
477 }
478 return clone $this;
479 }
480 $str = clone $this;
481 if ($suffix instanceof self) {
482 $suffix = $suffix->string;
483 } else {
484 $suffix = (string) $suffix;
485 }
486 if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) {
487 $str->string = \substr($this->string, 0, -\strlen($suffix));
488 }
489 return $str;
490 }
491 public function truncate(int $length, string $ellipsis = '', bool $cut = \true) : static
492 {
493 $stringLength = $this->length();
494 if ($stringLength <= $length) {
495 return clone $this;
496 }
497 $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0;
498 if ($length < $ellipsisLength) {
499 $ellipsisLength = 0;
500 }
501 if (!$cut) {
502 if (null === ($length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1))) {
503 return clone $this;
504 }
505 $length += $ellipsisLength;
506 }
507 $str = $this->slice(0, $length - $ellipsisLength);
508 return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
509 }
510 public abstract function upper() : static;
511 /**
512 * Returns the printable length on a terminal.
513 */
514 public abstract function width(bool $ignoreAnsiDecoration = \true) : int;
515 public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false) : static
516 {
517 $lines = '' !== $break ? $this->split($break) : [clone $this];
518 $chars = [];
519 $mask = '';
520 if (1 === \count($lines) && '' === $lines[0]->string) {
521 return $lines[0];
522 }
523 foreach ($lines as $i => $line) {
524 if ($i) {
525 $chars[] = $break;
526 $mask .= '#';
527 }
528 foreach ($line->chunk() as $char) {
529 $chars[] = $char->string;
530 $mask .= ' ' === $char->string ? ' ' : '?';
531 }
532 }
533 $string = '';
534 $j = 0;
535 $b = $i = -1;
536 $mask = \wordwrap($mask, $width, '#', $cut);
537 while (\false !== ($b = \strpos($mask, '#', $b + 1))) {
538 for (++$i; $i < $b; ++$i) {
539 $string .= $chars[$j];
540 unset($chars[$j++]);
541 }
542 if ($break === $chars[$j] || ' ' === $chars[$j]) {
543 unset($chars[$j++]);
544 }
545 $string .= $break;
546 }
547 $str = clone $this;
548 $str->string = $string . \implode('', $chars);
549 return $str;
550 }
551 public function __sleep() : array
552 {
553 return ['string'];
554 }
555 public function __clone()
556 {
557 $this->ignoreCase = \false;
558 }
559 public function __toString() : string
560 {
561 return $this->string;
562 }
563 }
564