Skip to content

Commit f607aa4

Browse files
committed
Add more string transformation methods
Improved semantics
1 parent 61d2ed1 commit f607aa4

File tree

6 files changed

+129
-25
lines changed

6 files changed

+129
-25
lines changed

src/Format/Str.php

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,25 @@ public function positionLast(string $needle, ?string $encoding = null): self
8383
return $inst;
8484
}
8585

86+
87+
/**
88+
* Get part of string
89+
* This method uses multibyte functionality and provides a polyfill if your environment lacks support.
90+
*
91+
* @param int $start The start position of the substring
92+
* @param int|null $length The length of the substring. If null, extract all characters to the end
93+
* @param string|null $encoding The character encoding (e.g., 'UTF-8'). Default is null
94+
* @return self
95+
* @throws ErrorException
96+
*/
97+
public function substr(int $start, ?int $length = null, ?string $encoding = null): self
98+
{
99+
$inst = clone $this;
100+
$mb = new MB($inst->raw);
101+
$inst->raw = (string)$mb->substr($start, $length, $encoding);
102+
return $inst;
103+
}
104+
86105
/**
87106
* Get string length
88107
* This method uses multibyte functionality and provides a polyfill if your environment lacks support.
@@ -151,6 +170,24 @@ public function getContains(string $needle): self
151170
return $inst;
152171
}
153172

173+
174+
/**
175+
* Get a substring that appears after the first occurrence of needle
176+
* Returns null if the needle is not found in the string
177+
*
178+
* @param string $needle The substring to search for
179+
* @param int $offset Additional offset to add after needle position (default: 0)
180+
* @return self
181+
* @throws ErrorException
182+
*/
183+
public function getContainAfter(string $needle, int $offset = 0): self
184+
{
185+
$inst = clone $this;
186+
$position = $this->position($needle)->get();
187+
$inst->raw = ($position !== false) ? $inst->substr($position + 1 + $offset)->get() : null;
188+
return $inst;
189+
}
190+
154191
/**
155192
* Checks if a string starts with a given substring and return needle if true else false
156193
*
@@ -439,7 +476,7 @@ public function toUpper(): self
439476
}
440477

441478
/**
442-
* Uppercase first letter in text
479+
* Uppercase the first letter in text
443480
*
444481
* @return self
445482
*/
@@ -451,7 +488,7 @@ public function ucFirst(): self
451488
}
452489

453490
/**
454-
* Uppercase first letter in every word
491+
* Uppercase the first letter in every word
455492
*
456493
* @return self
457494
*/
@@ -810,6 +847,34 @@ public function xss(): self
810847
return $this->escape();
811848
}
812849

850+
/**
851+
* Export a variable as a valid PHP string representation
852+
* This method uses PHP's var_export() function to get a parseable string representation
853+
* of the raw value
854+
*
855+
* @return self
856+
*/
857+
public function varExport(): self
858+
{
859+
$inst = clone $this;
860+
$inst->raw = var_export($inst->raw, true);
861+
return $inst;
862+
}
863+
864+
/**
865+
* Export raw value to string and escape special characters like newlines, tabs etc.
866+
* This method is used internally to get a readable string representation of the value.
867+
*
868+
* @return self
869+
*/
870+
public function exportReadableValue(): self
871+
{
872+
return $this->replace(
873+
["\n", "\r", "\t", "\v", "\0"],
874+
['\\n', '\\r', '\\t', '\\v', '\\0']
875+
)->varExport()->replace('\\\\', '\\');
876+
}
877+
813878
/**
814879
* Return a string to bool value
815880
*

src/Helpers.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ static function traversArrFromStr(array $array, string $key): mixed
6666
$new = $array;
6767
$exp = explode(".", $key);
6868
foreach ($exp as $index) {
69-
if(!isset($new[$index])) {
69+
$data = is_object($new) ? ($new->{$index} ?? null) : ($new[$index] ?? null);
70+
if(is_null($data)) {
7071
$new = false;
7172
break;
7273
}
73-
$new = $new[$index];
74+
$new = $data;
7475
}
7576
return $new;
7677
}

src/Iconv.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,23 @@ public function __construct(string $value)
4040
*/
4141
public function __toString(): string
4242
{
43-
return (string)$this->getValue();
43+
return (string)$this->get();
4444
}
4545

4646
/**
4747
* Get value
4848
* @return string|false
4949
*/
50-
public function getValue(): string|false
50+
public function get(): string|false
5151
{
5252
return $this->value;
5353
}
5454

55+
public function getValue(): string|false
56+
{
57+
return $this->get();
58+
}
59+
5560
/**
5661
* Will disable vanilla iconv function, used mostly for testing.
5762
*

src/MB.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,23 @@ public function __construct(string $value)
3232
*/
3333
public function __toString(): string
3434
{
35-
return (string)$this->getValue();
35+
return (string)$this->get();
3636
}
3737

3838
/**
3939
* Get value
4040
* @return string|false
4141
*/
42-
public function getValue(): string|false
42+
public function get(): string|false
4343
{
4444
return $this->value;
4545
}
4646

47+
public function getValue(): string|false
48+
{
49+
return $this->get();
50+
}
51+
4752
/**
4853
* Will disable vanilla iconv function, used mostly for testing.
4954
*

src/Traverse.php

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,42 @@
1919

2020
/**
2121
* @method self strStrVal()
22-
* @method self strPosition(string $needle, int $offset, ?string $encoding)
23-
* @method self strPositionLast(string $needle, ?string $encoding)
24-
* @method self strStrlen(?string $encoding)
22+
* @method self strPosition(string $needle, int $offset = '0', ?string $encoding = '')
23+
* @method self strPositionLast(string $needle, ?string $encoding = '')
24+
* @method self strSubstr(int $start, ?int $length = '', ?string $encoding = '')
25+
* @method self strStrlen(?string $encoding = '')
2526
* @method self strContains(string $needle)
2627
* @method self strStartsWith(string $needle)
2728
* @method self strEndsWith(string $needle)
2829
* @method self strGetContains(string $needle)
30+
* @method self strGetContainAfter(string $needle, int $offset = '0')
2931
* @method self strGetStartsWith(string $needle)
3032
* @method self strGetEndsWith(string $needle)
31-
* @method self strExcerpt(int $length, string $ending, ?string $encoding)
33+
* @method self strExcerpt(int $length = '40', string $ending = '...', ?string $encoding = '')
3234
* @method self strNl2br()
3335
* @method self strAddTrailingSlash()
3436
* @method self strTrailingSlash()
3537
* @method self strTrimTrailingSlash()
36-
* @method self strStripTags(string $whitelist)
37-
* @method self strEncode(int $flag)
38-
* @method self strDecode(?int $flag)
39-
* @method self strSpecialChars(int $flag, string $encoding)
38+
* @method self strStripTags(string $whitelist = '')
39+
* @method self strEncode(int $flag = '3')
40+
* @method self strDecode(?int $flag = '3')
41+
* @method self strSpecialChars(int $flag = '3', string $encoding = 'UTF-8')
4042
* @method self strSanitizeIdentifiers()
4143
* @method self strClearBreaks()
4244
* @method self strNormalizeSpaces()
4345
* @method self strNormalizeSeparators()
44-
* @method self strEntityEncode(int $flags, ?string $encoding, bool $doubleEncode)
45-
* @method self strEntityDecode(int $flags, ?string $encoding)
46-
* @method self strTrim(string $characters)
47-
* @method self strLtrim(string $characters)
48-
* @method self strRtrim(string $characters)
46+
* @method self strEntityEncode(int $flags = '11', ?string $encoding = '', bool $doubleEncode = '1')
47+
* @method self strEntityDecode(int $flags = '11', ?string $encoding = '')
48+
* @method self strTrim(string $characters = ' \n\r\t\v\0')
49+
* @method self strLtrim(string $characters = ' \n\r\t\v\0')
50+
* @method self strRtrim(string $characters = ' \n\r\t\v\0')
4951
* @method self strToLower()
5052
* @method self strToUpper()
5153
* @method self strUcFirst()
5254
* @method self strUcWords()
53-
* @method self strPad(int $length, string $padString, int $padType)
54-
* @method self strLeadingZero(int $length)
55-
* @method self strReplaceSpaces(string $replaceWith)
55+
* @method self strPad(int $length, string $padString = ' ', int $padType = '1')
56+
* @method self strLeadingZero(int $length = '2')
57+
* @method self strReplaceSpaces(string $replaceWith = '-')
5658
* @method self strFormatEmail()
5759
* @method self strSlug()
5860
* @method self strFormatSlug()
@@ -79,7 +81,9 @@
7981
* @method self strGetDirname()
8082
* @method self strEscape()
8183
* @method self strXss()
82-
* @method self strJsonDecode(?bool $associative, int $depth, int $flags)
84+
* @method self strVarExport()
85+
* @method self strExportReadableValue()
86+
* @method self strJsonDecode(?bool $associative = '', int $depth = '512', int $flags = '0')
8387
* @method self strCompare(string|int|float|bool|null $compare)
8488
* @method self strGet()
8589
* @method self strFallback(string $fallback)
@@ -347,6 +351,16 @@ public function toJson(int $flags = 0, int $depth = 512): string|false
347351
return json_encode($this->get(), $flags, $depth);
348352
}
349353

354+
/**
355+
* Returns the string representation of the value
356+
*
357+
* @return string
358+
*/
359+
public function toString(): string
360+
{
361+
return (string)$this->get();
362+
}
363+
350364
/**
351365
* Returns the int representation of the value
352366
*

tests/unitary-dto-string.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
use MaplePHP\DTO\Format\Arr;
4+
use MaplePHP\DTO\Format\Str;
45
use MaplePHP\DTO\Traverse;
56

67
$unit = new MaplePHP\Unitary\Unit();
@@ -22,6 +23,7 @@
2223
"json" => '{"name":"Alice","email":"alice@example.com","roles":["admin","editor"]}',
2324
"date" => "2023-08-21 14:35:12",
2425
"content" => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse euismod turpis eget elit eleifend, non pulvinar enim dapibus.\n Nullam blandit vitae justo vitae viverra. Aliquam varius eu leo a euismod.",
26+
"exportReadable" => "hello \n\t",
2527
]);
2628

2729
$this->add($obj->firstname->str()->stripTags()->ucFirst()->get(), [
@@ -53,6 +55,18 @@
5355
"equal" => 18,
5456
], "strlen: Failed");
5557

58+
$this->add($obj->content->str()->substr(0, 5)->get(), [
59+
"equal" => "Lorem",
60+
], "substr: Failed");
61+
62+
$this->add($obj->email->str()->getContainAfter("@")->get(), [
63+
"equal" => "gmail.com",
64+
], "getContainAfter required to be true");
65+
66+
$this->add($obj->exportReadable->str()->exportReadableValue()->get(), [
67+
"equal" => Str::value("hello \n\t")->exportReadableValue()->get(),
68+
], "exportReadableValue required to be true");
69+
5670
$data = $obj->json->str()->jsonDecode()->get();
5771
$this->add($data->name ?? "", [
5872
"equal" => 'Alice',

0 commit comments

Comments
 (0)