PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.2.0
Independent Analytics – WordPress Analytics Plugin v2.2.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 2 years ago Resources 2 years ago Slugger 2 years ago AbstractString.php 2 years ago AbstractUnicodeString.php 2 years ago ByteString.php 2 years ago CodePointString.php 2 years ago LazyString.php 2 years ago UnicodeString.php 2 years ago
AbstractString.php
647 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 IAWP_SCOPED\Symfony\Component\String;
12
13 use IAWP_SCOPED\Symfony\Component\String\Exception\ExceptionInterface;
14 use IAWP_SCOPED\Symfony\Component\String\Exception\InvalidArgumentException;
15 use IAWP_SCOPED\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 * @return static
85 */
86 public function after($needle, bool $includeNeedle = \false, int $offset = 0) : self
87 {
88 $str = clone $this;
89 $i = \PHP_INT_MAX;
90 foreach ((array) $needle as $n) {
91 $n = (string) $n;
92 $j = $this->indexOf($n, $offset);
93 if (null !== $j && $j < $i) {
94 $i = $j;
95 $str->string = $n;
96 }
97 }
98 if (\PHP_INT_MAX === $i) {
99 return $str;
100 }
101 if (!$includeNeedle) {
102 $i += $str->length();
103 }
104 return $this->slice($i);
105 }
106 /**
107 * @param string|string[] $needle
108 *
109 * @return static
110 */
111 public function afterLast($needle, bool $includeNeedle = \false, int $offset = 0) : self
112 {
113 $str = clone $this;
114 $i = null;
115 foreach ((array) $needle as $n) {
116 $n = (string) $n;
117 $j = $this->indexOfLast($n, $offset);
118 if (null !== $j && $j >= $i) {
119 $i = $offset = $j;
120 $str->string = $n;
121 }
122 }
123 if (null === $i) {
124 return $str;
125 }
126 if (!$includeNeedle) {
127 $i += $str->length();
128 }
129 return $this->slice($i);
130 }
131 /**
132 * @return static
133 */
134 public abstract function append(string ...$suffix) : self;
135 /**
136 * @param string|string[] $needle
137 *
138 * @return static
139 */
140 public function before($needle, bool $includeNeedle = \false, int $offset = 0) : self
141 {
142 $str = clone $this;
143 $i = \PHP_INT_MAX;
144 foreach ((array) $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 * @return static
164 */
165 public function beforeLast($needle, bool $includeNeedle = \false, int $offset = 0) : self
166 {
167 $str = clone $this;
168 $i = null;
169 foreach ((array) $needle as $n) {
170 $n = (string) $n;
171 $j = $this->indexOfLast($n, $offset);
172 if (null !== $j && $j >= $i) {
173 $i = $offset = $j;
174 $str->string = $n;
175 }
176 }
177 if (null === $i) {
178 return $str;
179 }
180 if ($includeNeedle) {
181 $i += $str->length();
182 }
183 return $this->slice(0, $i);
184 }
185 /**
186 * @return int[]
187 */
188 public function bytesAt(int $offset) : array
189 {
190 $str = $this->slice($offset, 1);
191 return '' === $str->string ? [] : \array_values(\unpack('C*', $str->string));
192 }
193 /**
194 * @return static
195 */
196 public abstract function camel() : self;
197 /**
198 * @return static[]
199 */
200 public abstract function chunk(int $length = 1) : array;
201 /**
202 * @return static
203 */
204 public function collapseWhitespace() : self
205 {
206 $str = clone $this;
207 $str->string = \trim(\preg_replace("/(?:[ \n\r\t\f]{2,}+|[\n\r\t\f])/", ' ', $str->string), " \n\r\t\f");
208 return $str;
209 }
210 /**
211 * @param string|string[] $needle
212 */
213 public function containsAny($needle) : bool
214 {
215 return null !== $this->indexOf($needle);
216 }
217 /**
218 * @param string|string[] $suffix
219 */
220 public function endsWith($suffix) : bool
221 {
222 if (!\is_array($suffix) && !$suffix instanceof \Traversable) {
223 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
224 }
225 foreach ($suffix as $s) {
226 if ($this->endsWith((string) $s)) {
227 return \true;
228 }
229 }
230 return \false;
231 }
232 /**
233 * @return static
234 */
235 public function ensureEnd(string $suffix) : self
236 {
237 if (!$this->endsWith($suffix)) {
238 return $this->append($suffix);
239 }
240 $suffix = \preg_quote($suffix);
241 $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D';
242 return $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1');
243 }
244 /**
245 * @return static
246 */
247 public function ensureStart(string $prefix) : self
248 {
249 $prefix = new static($prefix);
250 if (!$this->startsWith($prefix)) {
251 return $this->prepend($prefix);
252 }
253 $str = clone $this;
254 $i = $prefixLen = $prefix->length();
255 while ($this->indexOf($prefix, $i) === $i) {
256 $str = $str->slice($prefixLen);
257 $i += $prefixLen;
258 }
259 return $str;
260 }
261 /**
262 * @param string|string[] $string
263 */
264 public function equalsTo($string) : bool
265 {
266 if (!\is_array($string) && !$string instanceof \Traversable) {
267 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
268 }
269 foreach ($string as $s) {
270 if ($this->equalsTo((string) $s)) {
271 return \true;
272 }
273 }
274 return \false;
275 }
276 /**
277 * @return static
278 */
279 public abstract function folded() : self;
280 /**
281 * @return static
282 */
283 public function ignoreCase() : self
284 {
285 $str = clone $this;
286 $str->ignoreCase = \true;
287 return $str;
288 }
289 /**
290 * @param string|string[] $needle
291 */
292 public function indexOf($needle, int $offset = 0) : ?int
293 {
294 if (!\is_array($needle) && !$needle instanceof \Traversable) {
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 = \PHP_INT_MAX;
298 foreach ($needle as $n) {
299 $j = $this->indexOf((string) $n, $offset);
300 if (null !== $j && $j < $i) {
301 $i = $j;
302 }
303 }
304 return \PHP_INT_MAX === $i ? null : $i;
305 }
306 /**
307 * @param string|string[] $needle
308 */
309 public function indexOfLast($needle, int $offset = 0) : ?int
310 {
311 if (!\is_array($needle) && !$needle instanceof \Traversable) {
312 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
313 }
314 $i = null;
315 foreach ($needle as $n) {
316 $j = $this->indexOfLast((string) $n, $offset);
317 if (null !== $j && $j >= $i) {
318 $i = $offset = $j;
319 }
320 }
321 return $i;
322 }
323 public function isEmpty() : bool
324 {
325 return '' === $this->string;
326 }
327 /**
328 * @return static
329 */
330 public abstract function join(array $strings, string $lastGlue = null) : self;
331 public function jsonSerialize() : string
332 {
333 return $this->string;
334 }
335 public abstract function length() : int;
336 /**
337 * @return static
338 */
339 public abstract function lower() : self;
340 /**
341 * Matches the string using a regular expression.
342 *
343 * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression.
344 *
345 * @return array All matches in a multi-dimensional array ordered according to flags
346 */
347 public abstract function match(string $regexp, int $flags = 0, int $offset = 0) : array;
348 /**
349 * @return static
350 */
351 public abstract function padBoth(int $length, string $padStr = ' ') : self;
352 /**
353 * @return static
354 */
355 public abstract function padEnd(int $length, string $padStr = ' ') : self;
356 /**
357 * @return static
358 */
359 public abstract function padStart(int $length, string $padStr = ' ') : self;
360 /**
361 * @return static
362 */
363 public abstract function prepend(string ...$prefix) : self;
364 /**
365 * @return static
366 */
367 public function repeat(int $multiplier) : self
368 {
369 if (0 > $multiplier) {
370 throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
371 }
372 $str = clone $this;
373 $str->string = \str_repeat($str->string, $multiplier);
374 return $str;
375 }
376 /**
377 * @return static
378 */
379 public abstract function replace(string $from, string $to) : self;
380 /**
381 * @param string|callable $to
382 *
383 * @return static
384 */
385 public abstract function replaceMatches(string $fromRegexp, $to) : self;
386 /**
387 * @return static
388 */
389 public abstract function reverse() : self;
390 /**
391 * @return static
392 */
393 public abstract function slice(int $start = 0, int $length = null) : self;
394 /**
395 * @return static
396 */
397 public abstract function snake() : self;
398 /**
399 * @return static
400 */
401 public abstract function splice(string $replacement, int $start = 0, int $length = null) : self;
402 /**
403 * @return static[]
404 */
405 public function split(string $delimiter, int $limit = null, int $flags = null) : array
406 {
407 if (null === $flags) {
408 throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.');
409 }
410 if ($this->ignoreCase) {
411 $delimiter .= 'i';
412 }
413 \set_error_handler(static function ($t, $m) {
414 throw new InvalidArgumentException($m);
415 });
416 try {
417 if (\false === ($chunks = \preg_split($delimiter, $this->string, $limit, $flags))) {
418 $lastError = \preg_last_error();
419 foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
420 if ($lastError === $v && '_ERROR' === \substr($k, -6)) {
421 throw new RuntimeException('Splitting failed with ' . $k . '.');
422 }
423 }
424 throw new RuntimeException('Splitting failed with unknown error code.');
425 }
426 } finally {
427 \restore_error_handler();
428 }
429 $str = clone $this;
430 if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) {
431 foreach ($chunks as &$chunk) {
432 $str->string = $chunk[0];
433 $chunk[0] = clone $str;
434 }
435 } else {
436 foreach ($chunks as &$chunk) {
437 $str->string = $chunk;
438 $chunk = clone $str;
439 }
440 }
441 return $chunks;
442 }
443 /**
444 * @param string|string[] $prefix
445 */
446 public function startsWith($prefix) : bool
447 {
448 if (!\is_array($prefix) && !$prefix instanceof \Traversable) {
449 throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
450 }
451 foreach ($prefix as $prefix) {
452 if ($this->startsWith((string) $prefix)) {
453 return \true;
454 }
455 }
456 return \false;
457 }
458 /**
459 * @return static
460 */
461 public abstract function title(bool $allWords = \false) : self;
462 public function toByteString(string $toEncoding = null) : ByteString
463 {
464 $b = new ByteString();
465 $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding;
466 if (null === $toEncoding || $toEncoding === ($fromEncoding = $this instanceof AbstractUnicodeString || \preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252')) {
467 $b->string = $this->string;
468 return $b;
469 }
470 \set_error_handler(static function ($t, $m) {
471 throw new InvalidArgumentException($m);
472 });
473 try {
474 try {
475 $b->string = \mb_convert_encoding($this->string, $toEncoding, 'UTF-8');
476 } catch (InvalidArgumentException $e) {
477 if (!\function_exists('iconv')) {
478 throw $e;
479 }
480 $b->string = \iconv('UTF-8', $toEncoding, $this->string);
481 }
482 } finally {
483 \restore_error_handler();
484 }
485 return $b;
486 }
487 public function toCodePointString() : CodePointString
488 {
489 return new CodePointString($this->string);
490 }
491 public function toString() : string
492 {
493 return $this->string;
494 }
495 public function toUnicodeString() : UnicodeString
496 {
497 return new UnicodeString($this->string);
498 }
499 /**
500 * @return static
501 */
502 public abstract function trim(string $chars = " \t\n\r\x00\v\f ") : self;
503 /**
504 * @return static
505 */
506 public abstract function trimEnd(string $chars = " \t\n\r\x00\v\f ") : self;
507 /**
508 * @param string|string[] $prefix
509 *
510 * @return static
511 */
512 public function trimPrefix($prefix) : self
513 {
514 if (\is_array($prefix) || $prefix instanceof \Traversable) {
515 foreach ($prefix as $s) {
516 $t = $this->trimPrefix($s);
517 if ($t->string !== $this->string) {
518 return $t;
519 }
520 }
521 return clone $this;
522 }
523 $str = clone $this;
524 if ($prefix instanceof self) {
525 $prefix = $prefix->string;
526 } else {
527 $prefix = (string) $prefix;
528 }
529 if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === \substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) {
530 $str->string = \substr($this->string, \strlen($prefix));
531 }
532 return $str;
533 }
534 /**
535 * @return static
536 */
537 public abstract function trimStart(string $chars = " \t\n\r\x00\v\f ") : self;
538 /**
539 * @param string|string[] $suffix
540 *
541 * @return static
542 */
543 public function trimSuffix($suffix) : self
544 {
545 if (\is_array($suffix) || $suffix instanceof \Traversable) {
546 foreach ($suffix as $s) {
547 $t = $this->trimSuffix($s);
548 if ($t->string !== $this->string) {
549 return $t;
550 }
551 }
552 return clone $this;
553 }
554 $str = clone $this;
555 if ($suffix instanceof self) {
556 $suffix = $suffix->string;
557 } else {
558 $suffix = (string) $suffix;
559 }
560 if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) {
561 $str->string = \substr($this->string, 0, -\strlen($suffix));
562 }
563 return $str;
564 }
565 /**
566 * @return static
567 */
568 public function truncate(int $length, string $ellipsis = '', bool $cut = \true) : self
569 {
570 $stringLength = $this->length();
571 if ($stringLength <= $length) {
572 return clone $this;
573 }
574 $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0;
575 if ($length < $ellipsisLength) {
576 $ellipsisLength = 0;
577 }
578 if (!$cut) {
579 if (null === ($length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1))) {
580 return clone $this;
581 }
582 $length += $ellipsisLength;
583 }
584 $str = $this->slice(0, $length - $ellipsisLength);
585 return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
586 }
587 /**
588 * @return static
589 */
590 public abstract function upper() : self;
591 /**
592 * Returns the printable length on a terminal.
593 */
594 public abstract function width(bool $ignoreAnsiDecoration = \true) : int;
595 /**
596 * @return static
597 */
598 public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false) : self
599 {
600 $lines = '' !== $break ? $this->split($break) : [clone $this];
601 $chars = [];
602 $mask = '';
603 if (1 === \count($lines) && '' === $lines[0]->string) {
604 return $lines[0];
605 }
606 foreach ($lines as $i => $line) {
607 if ($i) {
608 $chars[] = $break;
609 $mask .= '#';
610 }
611 foreach ($line->chunk() as $char) {
612 $chars[] = $char->string;
613 $mask .= ' ' === $char->string ? ' ' : '?';
614 }
615 }
616 $string = '';
617 $j = 0;
618 $b = $i = -1;
619 $mask = \wordwrap($mask, $width, '#', $cut);
620 while (\false !== ($b = \strpos($mask, '#', $b + 1))) {
621 for (++$i; $i < $b; ++$i) {
622 $string .= $chars[$j];
623 unset($chars[$j++]);
624 }
625 if ($break === $chars[$j] || ' ' === $chars[$j]) {
626 unset($chars[$j++]);
627 }
628 $string .= $break;
629 }
630 $str = clone $this;
631 $str->string = $string . \implode('', $chars);
632 return $str;
633 }
634 public function __sleep() : array
635 {
636 return ['string'];
637 }
638 public function __clone()
639 {
640 $this->ignoreCase = \false;
641 }
642 public function __toString() : string
643 {
644 return $this->string;
645 }
646 }
647