1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* PHP: Nelson Martell Library file |
4
|
|
|
* |
5
|
|
|
* Content: |
6
|
|
|
* - Class definition: [NelsonMartell\Extensions] String |
7
|
|
|
* |
8
|
|
|
* Copyright © 2015-2016 Nelson Martell (http://nelson6e65.github.io) |
9
|
|
|
* |
10
|
|
|
* Licensed under The MIT License (MIT) |
11
|
|
|
* For full copyright and license information, please see the LICENSE |
12
|
|
|
* Redistributions of files must retain the above copyright notice. |
13
|
|
|
* |
14
|
|
|
* @copyright 2015-2017 Nelson Martell |
15
|
|
|
* @link http://nelson6e65.github.io/php_nml/ |
16
|
|
|
* @since v0.7.0 |
17
|
|
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License (MIT) |
18
|
|
|
* */ |
19
|
|
|
namespace NelsonMartell\Extensions; |
20
|
|
|
|
21
|
|
|
use InvalidArgumentException; |
22
|
|
|
use Cake\Utility\Text as TextBase; |
23
|
|
|
|
24
|
|
|
use function NelsonMartell\msg; |
25
|
|
|
use function NelsonMartell\typeof; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Provides extension methods to handle strings. |
29
|
|
|
* This class is based on \Cake\Utility\Text of CakePHP(tm) class. |
30
|
|
|
* |
31
|
|
|
* @see \Cake\Utility\Text::insert |
32
|
|
|
* @link http://book.cakephp.org/3.0/en/core-libraries/text.html |
33
|
|
|
* */ |
34
|
|
|
class Text extends TextBase |
35
|
|
|
{ |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Replaces format elements in a string with the string representation of an |
39
|
|
|
* object matching the list of arguments specified. You can give as many |
40
|
|
|
* params as you need, or an array with values. |
41
|
|
|
* |
42
|
|
|
* ##Usage |
43
|
|
|
* Using numbers as placeholders (encloses between `{` and `}`), you can get |
44
|
|
|
* the matching string representation of each object given. Use `{0}` for |
45
|
|
|
* the fist object, `{1}` for the second, and so on: |
46
|
|
|
* |
47
|
|
|
* ```php |
48
|
|
|
* $format = '{0} is {1} years old, and have {2} cats.'; |
49
|
|
|
* echo Text::format($format, 'Bob', 65, 101); // 'Bob is 65 years old, and have 101 cats.' |
50
|
|
|
* ``` |
51
|
|
|
* |
52
|
|
|
* You can also use an array to give objects values: |
53
|
|
|
* |
54
|
|
|
* ```php |
55
|
|
|
* $format = '{0} is {1} years old, and have {2} cats.'; |
56
|
|
|
* $data = ['Bob', 65, 101]; |
57
|
|
|
* echo Text::format($format, $data); // 'Bob is 65 years old, and have 101 cats.' |
58
|
|
|
* ``` |
59
|
|
|
* |
60
|
|
|
* This is specially useful to be able to use non-numeric placeholders (named placeholders): |
61
|
|
|
* |
62
|
|
|
* ```php |
63
|
|
|
* $format = '{name} is {age} years old, and have {n} cats.'; |
64
|
|
|
* $data = ['name' => 'Bob', 'n' => 101, 'age' => 65]; |
65
|
|
|
* echo Text::format($format, $data); // 'Bob is 65 years old, and have 101 cats.' |
66
|
|
|
* ``` |
67
|
|
|
* |
68
|
|
|
* For numeric placeholders, yo can convert the array into a list of arguments. |
69
|
|
|
* |
70
|
|
|
* ```php |
71
|
|
|
* $format = '{0} is {1} years old, and have {2} cats.'; |
72
|
|
|
* $data = ['Bob', 65, 101]; |
73
|
|
|
* echo Text::format($format, ...$data); // 'Bob is 65 years old, and have 101 cats.' |
74
|
|
|
* ``` |
75
|
|
|
* |
76
|
|
|
* > Note: If objects are not convertible to string, it will throws and catchable exception |
77
|
|
|
* (`InvalidArgumentException`). |
78
|
|
|
* |
79
|
|
|
* @param string $format An string containing variable placeholders to be replaced. If you provide name |
80
|
|
|
* placeholders, you must pass the target array as |
81
|
|
|
* @param array|mixed $args Object(s) to be replaced into $format placeholders. |
82
|
|
|
* You can provide one item only of type array for named placeholders replacement. For numeric placeholders, you |
83
|
|
|
* can still pass the array or convert it into arguments by using the '...' syntax instead. |
84
|
|
|
* |
85
|
|
|
* @return string |
86
|
|
|
* @throws InvalidArgumentException if $format is not an string or placeholder values are not string-convertibles. |
87
|
|
|
* @todo Implement formatting, like IFormatProvider or something like that. |
88
|
|
|
* @author Nelson Martell <[email protected]> |
89
|
|
|
*/ |
90
|
234 |
|
public static function format($format, ...$args) |
91
|
|
|
{ |
92
|
234 |
|
static $options = [ |
93
|
|
|
'before' => '{', |
94
|
|
|
'after' => '}', |
95
|
|
|
]; |
96
|
|
|
|
97
|
234 |
|
$originalData = $args; |
98
|
|
|
|
99
|
|
|
// Make it compatible with named placeholders along numeric ones if passed only 1 array as argument |
100
|
234 |
|
if (count($args) === 1 && is_array($args[0])) { |
101
|
227 |
|
$originalData = $args[0]; |
102
|
|
|
} |
103
|
|
|
|
104
|
234 |
|
$data = []; |
105
|
|
|
// Sanitize values to be convertibles into strings |
106
|
234 |
|
foreach ($originalData as $placeholder => $value) { |
107
|
234 |
|
$valueType = typeof($value); |
108
|
|
|
|
109
|
234 |
|
if ($valueType->canBeString() === false) { |
110
|
3 |
|
$msg = 'Value for "{{0}}" placeholder is not convertible to string; "{1}" type given.'; |
111
|
3 |
|
throw new InvalidArgumentException(msg($msg, $placeholder, $valueType)); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
// This is to work-arround a bug in use of ``asort()`` function in ``Text::insert`` (at v3.2.5) |
|
|
|
|
115
|
|
|
// without SORT_STRING flag... by forcing value to be string. |
116
|
234 |
|
settype($value, 'string'); |
117
|
234 |
|
$data[$placeholder] = $value; |
118
|
|
|
} |
119
|
|
|
|
120
|
234 |
|
return static::insert($format, $data, $options); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Ensures that object given is not null. If is `null`, throws and exception. |
125
|
|
|
* |
126
|
|
|
* @param mixed $obj Object to validate |
127
|
|
|
* |
128
|
|
|
* @return mixed Same object |
129
|
|
|
* @throws InvalidArgumentException if object is `null`. |
130
|
|
|
*/ |
131
|
303 |
|
public static function ensureIsNotNull($obj) |
132
|
|
|
{ |
133
|
303 |
|
if (is_null($obj)) { |
134
|
|
|
$msg = msg('Provided object must not be NULL.'); |
135
|
|
|
throw new InvalidArgumentException($msg); |
136
|
|
|
} |
137
|
|
|
|
138
|
303 |
|
return $obj; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Ensures that object given is an string. Else, thows an exception |
143
|
|
|
* |
144
|
|
|
* @param mixed $obj Object to validate. |
145
|
|
|
* |
146
|
|
|
* @return string Same object given, but ensured that is an string. |
147
|
|
|
* @throws InvalidArgumentException if object is not an `string`. |
148
|
|
|
*/ |
149
|
303 |
|
public static function ensureIsString($obj) |
150
|
|
|
{ |
151
|
303 |
|
if (!is_string(static::ensureIsNotNull($obj))) { |
152
|
1 |
|
$msg = msg('Provided object must to be an string; "{0}" given.', typeof($obj)); |
153
|
1 |
|
throw new InvalidArgumentException($msg); |
154
|
|
|
} |
155
|
|
|
|
156
|
303 |
|
return $obj; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Ensures that given string is not empty. |
161
|
|
|
* |
162
|
|
|
* @param string $string String to validate. |
163
|
|
|
* |
164
|
|
|
* @return string Same string given, but ensured that is not empty. |
165
|
|
|
* @throws InvalidArgumentException if string is null or empty. |
166
|
|
|
*/ |
167
|
|
View Code Duplication |
public static function ensureIsNotEmpty($string) |
|
|
|
|
168
|
|
|
{ |
169
|
|
|
if (static::ensureIsString($string) === '') { |
170
|
|
|
$msg = msg('Provided string must not be empty.'); |
171
|
|
|
throw new InvalidArgumentException($msg); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
return $string; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Ensures that given string is not empty or whitespaces. |
179
|
|
|
* |
180
|
|
|
* @param string $string String to validate. |
181
|
|
|
* |
182
|
|
|
* @return string Same string given, but ensured that is not whitespaces. |
183
|
|
|
* @throws InvalidArgumentException if object is not an `string`. |
184
|
|
|
* @see \trim() |
185
|
|
|
*/ |
186
|
|
View Code Duplication |
public static function ensureIsNotWhiteSpaces($string) |
|
|
|
|
187
|
|
|
{ |
188
|
|
|
if (trim(static::ensureIsNotEmpty($string)) === '') { |
189
|
|
|
$msg = msg('Provided string must not be white spaces.'); |
190
|
|
|
throw new InvalidArgumentException($msg); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return $string; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Ensures that an string follows the PHP variables naming convention. |
198
|
|
|
* |
199
|
|
|
* @param string $string String to be ensured. |
200
|
|
|
* |
201
|
|
|
* @return string |
202
|
|
|
* @throws InvalidArgumentException if object is not an `string` or do not |
203
|
|
|
* follows the PHP variables naming convention. |
204
|
|
|
*/ |
205
|
303 |
|
public static function ensureIsValidVarName($string) |
206
|
|
|
{ |
207
|
303 |
|
$pattern = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/'; |
208
|
|
|
|
209
|
303 |
|
if (!preg_match($pattern, static::ensureIsString($string))) { |
210
|
|
|
$msg = msg('Provided string do not follows PHP variables naming convention: "{0}".', $string); |
211
|
|
|
throw new InvalidArgumentException($msg); |
212
|
|
|
} |
213
|
|
|
|
214
|
303 |
|
return $string; |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.