This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php namespace BuildR\Utils; |
||
2 | |||
3 | use BuildR\Foundation\Exception\InvalidArgumentException; |
||
4 | use BuildR\Foundation\Object\StringConvertibleInterface; |
||
5 | use BuildR\Utils\Extension\AbstractExtensionReceiver; |
||
6 | use BuildR\Utils\Extension\StringObjectExtensionInterface; |
||
7 | use \Countable; |
||
8 | use \IteratorAggregate; |
||
9 | use \ArrayIterator; |
||
10 | |||
11 | /** |
||
12 | * This object represents a string in OO format and allow nifty manipulation |
||
13 | * and analysis of the provided string. |
||
14 | * |
||
15 | * BuildR PHP Framework |
||
16 | * |
||
17 | * @author Zoltán Borsos <[email protected]> |
||
18 | * @package Utils |
||
19 | * |
||
20 | * @copyright Copyright 2016, Zoltán Borsos. |
||
21 | * @license https://github.com/BuildrPHP/Utils/blob/master/LICENSE.md |
||
22 | * @link https://github.com/BuildrPHP/Utils |
||
23 | */ |
||
24 | class StringObject |
||
25 | extends AbstractExtensionReceiver |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
26 | implements StringConvertibleInterface, Countable, IteratorAggregate { |
||
0 ignored issues
–
show
|
|||
27 | |||
28 | /** |
||
29 | * @type string |
||
30 | */ |
||
31 | private $string; |
||
32 | |||
33 | /** |
||
34 | * StringObject constructor. |
||
35 | * |
||
36 | * @param $string |
||
37 | * |
||
38 | * @throws \BuildR\Foundation\Exception\InvalidArgumentException |
||
39 | */ |
||
40 | 92 | public function __construct($string) { |
|
41 | 92 | if(!is_string($string)) { |
|
42 | 3 | throw new InvalidArgumentException('The given value is not a string!'); |
|
43 | } |
||
44 | |||
45 | 89 | $this->string = $string; |
|
46 | 89 | } |
|
47 | |||
48 | /** |
||
49 | * Remove all whitespace character from the given string |
||
50 | * |
||
51 | * @return \BuildR\Utils\StringObject |
||
52 | */ |
||
53 | 4 | public function removeWhitespace() { |
|
54 | 4 | $result = str_replace(["\\r", "\\n", "\\t", "\\0"], '', $this->string); |
|
55 | |||
56 | 4 | return $this->createClone($result); |
|
57 | } |
||
58 | |||
59 | /** |
||
60 | * Appends the given substring to the current string |
||
61 | * |
||
62 | * @param string $substring |
||
63 | * |
||
64 | * @return \BuildR\Utils\StringObject |
||
65 | */ |
||
66 | 5 | public function append($substring) { |
|
67 | 5 | $newValue = $this->string . $substring; |
|
68 | |||
69 | 5 | return $this->createClone($newValue); |
|
70 | } |
||
71 | |||
72 | /** |
||
73 | * Prepends the given substring to the current string |
||
74 | * |
||
75 | * @param string $substring |
||
76 | * |
||
77 | * @return \BuildR\Utils\StringObject |
||
78 | */ |
||
79 | 6 | public function prepend($substring) { |
|
80 | 6 | $newValue = $substring . $this->string; |
|
81 | |||
82 | 6 | return $this->createClone($newValue); |
|
83 | } |
||
84 | |||
85 | /** |
||
86 | * Return an array where each element represent a single character from the current string |
||
87 | * |
||
88 | * @return array |
||
89 | */ |
||
90 | 9 | public function chars() { |
|
91 | 9 | $string = $this->string; |
|
92 | |||
93 | 9 | return preg_split('/(?<!^)(?!$)/u', $string); |
|
94 | } |
||
95 | |||
96 | /** |
||
97 | * Determines the length of the current string |
||
98 | * |
||
99 | * @return int |
||
100 | */ |
||
101 | 3 | public function length() { |
|
102 | 3 | $string = $this->string; |
|
103 | |||
104 | 3 | return mb_strlen($string); |
|
105 | } |
||
106 | |||
107 | /** |
||
108 | * Determines that character exist in the given position |
||
109 | * If the character is a whitespace this function will return |
||
110 | * TRUE to indicate that index is part of the string |
||
111 | * |
||
112 | * This function counts characters from 1 |
||
113 | * |
||
114 | * @param int $index |
||
115 | * |
||
116 | * @return \BuildR\Utils\StringObject |
||
117 | */ |
||
118 | 5 | public function charAt($index) { |
|
119 | 5 | $index = $index - 1; |
|
120 | 5 | $chars = $this->chars(); |
|
121 | 5 | $char = (isset($chars[$index])) ? $chars[$index] : ''; |
|
122 | |||
123 | 5 | return $this->createClone($char); |
|
124 | } |
||
125 | |||
126 | /** |
||
127 | * Format the string to lowercase |
||
128 | * |
||
129 | * @return \BuildR\Utils\StringObject |
||
130 | */ |
||
131 | 6 | public function toLower() { |
|
132 | 6 | $newValue = mb_strtolower($this->string); |
|
133 | |||
134 | 6 | return $this->createClone($newValue); |
|
135 | } |
||
136 | |||
137 | /** |
||
138 | * Format the string to uppercase |
||
139 | * |
||
140 | * @return \BuildR\Utils\StringObject |
||
141 | */ |
||
142 | 4 | public function toUpper() { |
|
143 | 4 | $newValue = mb_strtoupper($this->string); |
|
144 | |||
145 | 4 | return $this->createClone($newValue); |
|
146 | } |
||
147 | |||
148 | /** |
||
149 | * Format the current string first character to uppercase. |
||
150 | * Leave any other character untouched |
||
151 | * |
||
152 | * @return \BuildR\Utils\StringObject |
||
153 | * |
||
154 | * @codeCoverageIgnore |
||
155 | */ |
||
156 | public function ucfirst() { |
||
157 | $result = StringUtils::multiByteUcfirst($this->string); |
||
158 | |||
159 | return $this->createClone($result); |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Split the current string trough spaces and makes every words first |
||
164 | * character uppercase. Leave any other character untouched |
||
165 | * |
||
166 | * @return \BuildR\Utils\StringObject |
||
167 | * |
||
168 | * @codeCoverageIgnore |
||
169 | */ |
||
170 | public function ucwords() { |
||
171 | $result = StringUtils::multiByteUcwords($this->string); |
||
172 | |||
173 | return $this->createClone($result); |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Determines that the current string starts with |
||
178 | * the given substring |
||
179 | * |
||
180 | * @param string $match |
||
181 | * |
||
182 | * @return bool |
||
183 | * |
||
184 | * @codeCoverageIgnore |
||
185 | */ |
||
186 | public function startsWith($match) { |
||
187 | return StringUtils::startsWith($this->string, $match); |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Determines that the current string ends with |
||
192 | * the given substring |
||
193 | * |
||
194 | * @param string $match |
||
195 | * |
||
196 | * @return bool |
||
197 | * |
||
198 | * @codeCoverageIgnore |
||
199 | */ |
||
200 | public function endsWith($match) { |
||
201 | return StringUtils::endsWith($this->string, $match); |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * Determines that the given string contains the |
||
206 | * given substring |
||
207 | * |
||
208 | * @param string $match |
||
209 | * |
||
210 | * @return bool |
||
211 | * |
||
212 | * @codeCoverageIgnore |
||
213 | */ |
||
214 | public function contains($match) { |
||
215 | return StringUtils::contains($this->string, $match); |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * Determines that the current string contains ALL of the |
||
220 | * given substring(s) |
||
221 | * |
||
222 | * @param array $matches |
||
223 | * |
||
224 | * @return bool |
||
225 | */ |
||
226 | 4 | View Code Duplication | public function containsAll(array $matches = []) { |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
227 | 4 | foreach($matches as $match) { |
|
228 | 4 | if(!StringUtils::contains($this->string, $match)) { |
|
229 | 1 | return FALSE; |
|
230 | } |
||
231 | 4 | } |
|
232 | |||
233 | 3 | return TRUE; |
|
234 | } |
||
235 | |||
236 | /** |
||
237 | * Determines that the current string contains ANY of the |
||
238 | * given substring(s) |
||
239 | * |
||
240 | * @param array $matches |
||
241 | * |
||
242 | * @return bool |
||
243 | */ |
||
244 | 3 | View Code Duplication | public function containsAny(array $matches = []) { |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
245 | 3 | foreach($matches as $match) { |
|
246 | 3 | if(StringUtils::contains($this->string, $match)) { |
|
247 | 2 | return TRUE; |
|
248 | } |
||
249 | 1 | } |
|
250 | |||
251 | 1 | return FALSE; |
|
252 | } |
||
253 | |||
254 | /** |
||
255 | * Returns the defined part of the current string |
||
256 | * |
||
257 | * @param int $start Tha starting character (If -1 starts from the end) |
||
258 | * @param int|NULL $length |
||
259 | * |
||
260 | * @return \BuildR\Utils\StringObject |
||
261 | */ |
||
262 | 20 | public function substring($start, $length = NULL) { |
|
263 | //TODO: Fix to PHP #42101 |
||
264 | 20 | if($length === NULL) { |
|
265 | 8 | $newValue = mb_substr($this->string, $start); |
|
266 | 8 | } else { |
|
267 | 12 | $newValue = mb_substr($this->string, $start, $length); |
|
268 | } |
||
269 | |||
270 | 20 | return $this->createClone($newValue); |
|
271 | } |
||
272 | |||
273 | /** |
||
274 | * Returns the firs X character from the string. If the provided number higher |
||
275 | * tha the string length the full string will be returned but not more. |
||
276 | * |
||
277 | * @param int $charCount |
||
278 | * |
||
279 | * @return \BuildR\Utils\StringObject |
||
280 | */ |
||
281 | 9 | View Code Duplication | public function first($charCount) { |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
282 | 9 | if($charCount <= 0) { |
|
283 | 2 | return $this->createClone(''); |
|
284 | } |
||
285 | |||
286 | 7 | $newValue = $this->substring(0, (int) $charCount); |
|
287 | |||
288 | 7 | return $this->createClone($newValue); |
|
289 | } |
||
290 | |||
291 | /** |
||
292 | * Returns the last X character from the current string |
||
293 | * |
||
294 | * @param int $charCount |
||
295 | * |
||
296 | * @return \BuildR\Utils\StringObject |
||
297 | */ |
||
298 | 7 | View Code Duplication | public function last($charCount) { |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
299 | 7 | if($charCount <= 0) { |
|
300 | 2 | return $this->createClone(''); |
|
301 | } |
||
302 | |||
303 | 5 | $newValue = $this->substring(($charCount * -1)); |
|
304 | |||
305 | 5 | return $this->createClone($newValue); |
|
306 | } |
||
307 | |||
308 | /** |
||
309 | * Iterates over parts of the string. The current string split through |
||
310 | * the given delimiter and the closure will be called on all elements. |
||
311 | * |
||
312 | * The closer takes two arguments: |
||
313 | * - (string) $part The current part of the string |
||
314 | * - (string) $delimiter the delimiter passed to this function |
||
315 | * |
||
316 | * @param string $delimiter |
||
317 | * @param callable $callback |
||
318 | */ |
||
319 | 3 | public function map($delimiter, callable $callback) { |
|
320 | 3 | $parts = $this->split($delimiter); |
|
321 | |||
322 | 3 | foreach($parts as $part) { |
|
323 | 3 | call_user_func_array($callback, [$part, $delimiter]); |
|
324 | 3 | } |
|
325 | 3 | } |
|
326 | |||
327 | /** |
||
328 | * Split string along the delimiter |
||
329 | * |
||
330 | * @param string $delimiter |
||
331 | * |
||
332 | * @return array |
||
333 | */ |
||
334 | 15 | public function split($delimiter = ' ') { |
|
335 | 15 | $delimiter = (empty($delimiter)) ? ' ' : $delimiter; |
|
336 | |||
337 | 15 | return explode($delimiter, $this->string); |
|
338 | } |
||
339 | |||
340 | /** |
||
341 | * Split the string along the delimiter and returns |
||
342 | * the given index from the segments |
||
343 | * |
||
344 | * @param string $delimiter |
||
345 | * @param int $index |
||
346 | * |
||
347 | * @return \BuildR\Utils\StringObject |
||
348 | */ |
||
349 | 5 | public function segment($delimiter, $index) { |
|
350 | 5 | $parts = $this->split($delimiter); |
|
351 | 5 | $returnValue = (isset($parts[$index - 1])) ? $parts[$index - 1] : ''; |
|
352 | |||
353 | 5 | return $this->createClone($returnValue); |
|
354 | } |
||
355 | |||
356 | /** |
||
357 | * Split string along the delimiter and |
||
358 | * return the last segment |
||
359 | * |
||
360 | * @param string $delimiter |
||
361 | * |
||
362 | * @return \BuildR\Utils\StringObject |
||
363 | * |
||
364 | * @codeCoverageIgnore |
||
365 | */ |
||
366 | public function lastSegment($delimiter) { |
||
367 | $parts = $this->split($delimiter); |
||
368 | $returnValue = end($parts); |
||
369 | |||
370 | return $this->createClone($returnValue); |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Split the string along the delimiter and |
||
375 | * returns the first segment |
||
376 | * |
||
377 | * @param string $delimiter |
||
378 | * |
||
379 | * @return \BuildR\Utils\StringObject |
||
380 | * |
||
381 | * @codeCoverageIgnore |
||
382 | */ |
||
383 | public function firstSegment($delimiter) { |
||
384 | $parts = $this->split($delimiter); |
||
385 | $returnValue = current($parts); |
||
386 | |||
387 | return $this->createClone($returnValue); |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * Limit the length of the current string. If the current string is |
||
392 | * longer tha the given limit chopped down to limit and the end |
||
393 | * substring will be concatenated. |
||
394 | * |
||
395 | * @param int $limit |
||
396 | * @param string $end |
||
397 | * |
||
398 | * @return \BuildR\Utils\StringObject |
||
399 | */ |
||
400 | 3 | public function limit($limit = 120, $end = '...') { |
|
401 | 3 | $returnValue = $this->string; |
|
402 | |||
403 | 3 | if($this->length() > $limit) { |
|
404 | 2 | $returnValue = rtrim((string) $this->first($limit)->toString()) . $end; |
|
405 | 2 | } |
|
406 | |||
407 | 3 | return $this->createClone($returnValue); |
|
408 | } |
||
409 | |||
410 | /** |
||
411 | * Split down cameCase or PascalCase strings |
||
412 | * |
||
413 | * Example: |
||
414 | * helloWorld -> hello World |
||
415 | * ExampleHelloWorld -> ExampleHelloWorld |
||
416 | * |
||
417 | * @return \BuildR\Utils\StringObject |
||
418 | */ |
||
419 | 5 | public function splitCamelCase() { |
|
420 | 5 | preg_match_all('/((?:^|[\p{Lu}])[\p{Ll}_]+)/mu', $this->string, $matches); |
|
421 | 5 | $returnValue = implode(' ', $matches[0]); |
|
422 | |||
423 | 5 | return $this->createClone($returnValue); |
|
424 | } |
||
425 | |||
426 | /** |
||
427 | * Split snake_case string. |
||
428 | * |
||
429 | * Example |
||
430 | * hello_world -> hello world |
||
431 | * |
||
432 | * @return \BuildR\Utils\StringObject |
||
433 | */ |
||
434 | 5 | public function splitSnakeCase() { |
|
435 | 5 | $parts = $this->split('_'); |
|
436 | 5 | $returnValue = implode(' ', $parts); |
|
437 | |||
438 | 5 | return $this->createClone($returnValue); |
|
439 | } |
||
440 | |||
441 | /** |
||
442 | * Try to split any case method into words. |
||
443 | * This convert the following cases into words: |
||
444 | * |
||
445 | * - PascalCase |
||
446 | * - camelCase |
||
447 | * - snake_case |
||
448 | * |
||
449 | * Example: |
||
450 | * helloExampleWorld_olah -> hello Example World olah |
||
451 | * |
||
452 | * @return \BuildR\Utils\StringObject |
||
453 | */ |
||
454 | 2 | public function caseFree() { |
|
455 | 2 | $returnValue = $this->splitSnakeCase()->splitCamelCase(); |
|
456 | |||
457 | 2 | return $this->createClone((string) $returnValue); |
|
458 | } |
||
459 | |||
460 | /** |
||
461 | * Convert current string to 'Title Case' |
||
462 | * |
||
463 | * Example: |
||
464 | * 'hello world example' -> 'Hello World Example' |
||
465 | * |
||
466 | * @return \BuildR\Utils\StringObject |
||
467 | */ |
||
468 | 2 | public function toTitleCase() { |
|
469 | 2 | $returnValue = mb_convert_case((string) $this->toLower(), MB_CASE_TITLE); |
|
470 | |||
471 | 2 | return $this->createClone($returnValue); |
|
472 | } |
||
473 | |||
474 | /** |
||
475 | * Convert current string to snake_case |
||
476 | * |
||
477 | * @return \BuildR\Utils\StringObject |
||
478 | */ |
||
479 | 2 | public function toSnakeCase() { |
|
480 | 2 | $newValue = implode('_', $this->split(' ')); |
|
481 | |||
482 | 2 | return $this->createClone($newValue); |
|
483 | } |
||
484 | |||
485 | /** |
||
486 | * Convert current string to PascalCase |
||
487 | * |
||
488 | * @return \BuildR\Utils\StringObject |
||
489 | */ |
||
490 | 2 | public function toPascalCase() { |
|
491 | 2 | $newValue = $this->toLower()->toTitleCase()->toString(); |
|
492 | 2 | $newValue = implode('', explode(' ', $newValue)); |
|
493 | |||
494 | 2 | return $this->createClone($newValue); |
|
495 | } |
||
496 | |||
497 | /** |
||
498 | * Convert current string to camelCase |
||
499 | * |
||
500 | * @return \BuildR\Utils\StringObject |
||
501 | */ |
||
502 | 2 | public function toCamelCase() { |
|
503 | 2 | $parts = $this->toLower()->split(' '); |
|
504 | 2 | $index = 0; |
|
505 | 2 | $result = ''; |
|
506 | |||
507 | //Yeah, Its ugly. But fast... |
||
508 | 2 | foreach($parts as $part) { |
|
509 | 2 | if($index === 0) { |
|
510 | 2 | $index++; |
|
511 | 2 | $result .= $part; |
|
512 | |||
513 | 2 | continue; |
|
514 | } |
||
515 | |||
516 | 2 | $result .= (string) $this->createClone($part)->ucfirst(); |
|
517 | 2 | $index++; |
|
518 | 2 | } |
|
519 | |||
520 | 2 | return $this->createClone($result); |
|
521 | } |
||
522 | |||
523 | /** |
||
524 | * Clone the current object a set a new value (base string) |
||
525 | * on the clone. |
||
526 | * |
||
527 | * This method allow instances immutability, but allow instances |
||
528 | * to retain loaded extensions. |
||
529 | * |
||
530 | * @param $newValue |
||
531 | * |
||
532 | * @return \BuildR\Utils\StringObject |
||
533 | */ |
||
534 | 69 | protected function createClone($newValue) { |
|
535 | 69 | if($newValue instanceof StringObject) { |
|
536 | 12 | $newValue == $newValue->toString(); |
|
537 | 12 | } |
|
538 | |||
539 | 69 | $newInstance = clone $this; |
|
540 | 69 | $newInstance->string = $newValue; |
|
541 | |||
542 | 69 | return $newInstance; |
|
543 | } |
||
544 | |||
545 | //=========================================== |
||
546 | // StringConvertibleInterface Implementation |
||
547 | //=========================================== |
||
548 | |||
549 | /** |
||
550 | * {@inheritDoc} |
||
551 | */ |
||
552 | 16 | public function __toString() { |
|
553 | 16 | return $this->string; |
|
554 | } |
||
555 | |||
556 | /** |
||
557 | * {@inheritDoc} |
||
558 | */ |
||
559 | 74 | public function toString() { |
|
560 | 74 | return $this->string; |
|
561 | } |
||
562 | |||
563 | // ========================= |
||
564 | // Countable Implementation |
||
565 | // ========================= |
||
566 | |||
567 | /** |
||
568 | * {@inheritDoc} |
||
569 | * |
||
570 | * @codeCoverageIgnore |
||
571 | */ |
||
572 | public function count() { |
||
573 | return $this->length(); |
||
574 | } |
||
575 | |||
576 | // ============================= |
||
577 | // ArrayIterator Implementation |
||
578 | // ============================= |
||
579 | |||
580 | /** |
||
581 | * {@inheritDoc} |
||
582 | */ |
||
583 | 4 | public function getIterator() { |
|
584 | 4 | return new ArrayIterator($this->chars()); |
|
585 | } |
||
586 | |||
587 | // ========================================== |
||
588 | // ExtensionReceiverInterface Implementation |
||
589 | // ========================================== |
||
590 | |||
591 | /** |
||
592 | * {@inheritDoc} |
||
593 | * |
||
594 | * @internal |
||
595 | */ |
||
596 | 5 | public function shouldReceiveType() { |
|
597 | 5 | return StringObjectExtensionInterface::class; |
|
598 | } |
||
599 | |||
600 | /** |
||
601 | * {@inheritDoc} |
||
602 | * |
||
603 | * @internal |
||
604 | */ |
||
605 | 2 | public function getCurrentValue() { |
|
606 | 2 | return $this->string; |
|
607 | } |
||
608 | |||
609 | /** |
||
610 | * {@inheritDoc} |
||
611 | * |
||
612 | * @internal |
||
613 | */ |
||
614 | 2 | public function processResult(array $result) { |
|
615 | 2 | list($result, $isRaw) = array_values($result); |
|
616 | |||
617 | 2 | if(!$isRaw && is_string($result)) { |
|
618 | 1 | return $this->createClone($result); |
|
619 | } |
||
620 | |||
621 | 1 | return $result; |
|
622 | } |
||
623 | |||
624 | } |
||
625 |