Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
aba1cd8b EM |
2 | |
3 | /** | |
4 | * Class CRM_Utils_StringTest | |
acb109b7 | 5 | * @group headless |
aba1cd8b | 6 | */ |
6a488035 | 7 | class CRM_Utils_StringTest extends CiviUnitTestCase { |
6a488035 | 8 | |
00be9182 | 9 | public function setUp() { |
6a488035 TO |
10 | parent::setUp(); |
11 | } | |
12 | ||
00be9182 | 13 | public function testStripPathChars() { |
9099cab3 | 14 | $testSet = [ |
6a488035 TO |
15 | '' => '', |
16 | NULL => NULL, | |
17 | 'civicrm' => 'civicrm', | |
18 | 'civicrm/dashboard' => 'civicrm/dashboard', | |
19 | 'civicrm/contribute/transact' => 'civicrm/contribute/transact', | |
20 | 'civicrm/<hack>attempt</hack>' => 'civicrm/_hack_attempt_/hack_', | |
21 | 'civicrm dashboard & force = 1,;' => 'civicrm_dashboard___force___1__', | |
9099cab3 | 22 | ]; |
6a488035 | 23 | |
6a488035 TO |
24 | foreach ($testSet as $in => $expected) { |
25 | $out = CRM_Utils_String::stripPathChars($in); | |
26 | $this->assertEquals($out, $expected, "Output does not match"); | |
27 | } | |
28 | } | |
29 | ||
00be9182 | 30 | public function testExtractName() { |
9099cab3 CW |
31 | $cases = [ |
32 | [ | |
6a488035 TO |
33 | 'full_name' => 'Alan', |
34 | 'first_name' => 'Alan', | |
9099cab3 CW |
35 | ], |
36 | [ | |
6a488035 TO |
37 | 'full_name' => 'Alan Arkin', |
38 | 'first_name' => 'Alan', | |
39 | 'last_name' => 'Arkin', | |
9099cab3 CW |
40 | ], |
41 | [ | |
6a488035 TO |
42 | 'full_name' => '"Alan Arkin"', |
43 | 'first_name' => 'Alan', | |
44 | 'last_name' => 'Arkin', | |
9099cab3 CW |
45 | ], |
46 | [ | |
6a488035 TO |
47 | 'full_name' => 'Alan A Arkin', |
48 | 'first_name' => 'Alan', | |
49 | 'middle_name' => 'A', | |
50 | 'last_name' => 'Arkin', | |
9099cab3 CW |
51 | ], |
52 | [ | |
6a488035 TO |
53 | 'full_name' => 'Adams, Amy', |
54 | 'first_name' => 'Amy', | |
55 | 'last_name' => 'Adams', | |
9099cab3 CW |
56 | ], |
57 | [ | |
6a488035 TO |
58 | 'full_name' => 'Adams, Amy A', |
59 | 'first_name' => 'Amy', | |
60 | 'middle_name' => 'A', | |
61 | 'last_name' => 'Adams', | |
9099cab3 CW |
62 | ], |
63 | [ | |
6a488035 TO |
64 | 'full_name' => '"Adams, Amy A"', |
65 | 'first_name' => 'Amy', | |
66 | 'middle_name' => 'A', | |
67 | 'last_name' => 'Adams', | |
9099cab3 CW |
68 | ], |
69 | ]; | |
6a488035 | 70 | foreach ($cases as $case) { |
9099cab3 | 71 | $actual = []; |
6a488035 TO |
72 | CRM_Utils_String::extractName($case['full_name'], $actual); |
73 | $this->assertEquals($actual['first_name'], $case['first_name']); | |
e65f9c8f E |
74 | $this->assertEquals(CRM_Utils_Array::value('last_name', $actual), CRM_Utils_Array::value('last_name', $case)); |
75 | $this->assertEquals(CRM_Utils_Array::value('middle_name', $actual), CRM_Utils_Array::value('middle_name', $case)); | |
6a488035 TO |
76 | } |
77 | } | |
78 | ||
00be9182 | 79 | public function testEllipsify() { |
6a488035 | 80 | $maxLen = 5; |
9099cab3 | 81 | $cases = [ |
6a488035 TO |
82 | '1' => '1', |
83 | '12345' => '12345', | |
84 | '123456' => '12...', | |
9099cab3 | 85 | ]; |
6a488035 TO |
86 | foreach ($cases as $input => $expected) { |
87 | $this->assertEquals($expected, CRM_Utils_String::ellipsify($input, $maxLen)); | |
7a0ea0f3 | 88 | } |
69a8e7e6 | 89 | // test utf-8 string, CRM-18997 |
90 | $input = 'Registro de eventos on-line: Taller: "Onboarding - Cómo integrar exitosamente a los nuevos talentos dentro de su organización - Formación práctica."'; | |
91 | $maxLen = 128; | |
06abe035 | 92 | $this->assertEquals(TRUE, mb_check_encoding(CRM_Utils_String::ellipsify($input, $maxLen), 'UTF-8')); |
6a488035 TO |
93 | } |
94 | ||
00be9182 | 95 | public function testRandom() { |
6a488035 TO |
96 | for ($i = 0; $i < 4; $i++) { |
97 | $actual = CRM_Utils_String::createRandom(4, 'abc'); | |
98 | $this->assertEquals(4, strlen($actual)); | |
99 | $this->assertRegExp('/^[abc]+$/', $actual); | |
100 | ||
101 | $actual = CRM_Utils_String::createRandom(6, '12345678'); | |
102 | $this->assertEquals(6, strlen($actual)); | |
103 | $this->assertRegExp('/^[12345678]+$/', $actual); | |
104 | } | |
105 | } | |
fc7a0aee | 106 | |
4cbe18b8 EM |
107 | /** |
108 | * @return array | |
109 | */ | |
fc7a0aee | 110 | public function parsePrefixData() { |
9099cab3 CW |
111 | $cases = []; |
112 | $cases[] = ['administer CiviCRM', NULL, [NULL, 'administer CiviCRM']]; | |
113 | $cases[] = ['administer CiviCRM', 'com_civicrm', ['com_civicrm', 'administer CiviCRM']]; | |
114 | $cases[] = ['Drupal:access user profiles', NULL, ['Drupal', 'access user profiles']]; | |
115 | $cases[] = ['Joomla:component:perm', NULL, ['Joomla', 'component:perm']]; | |
fc7a0aee TO |
116 | return $cases; |
117 | } | |
118 | ||
119 | /** | |
120 | * @dataProvider parsePrefixData | |
1e1fdcf6 EM |
121 | * @param $input |
122 | * @param $defaultPrefix | |
123 | * @param $expected | |
fc7a0aee TO |
124 | */ |
125 | public function testParsePrefix($input, $defaultPrefix, $expected) { | |
126 | $actual = CRM_Utils_String::parsePrefix(':', $input, $defaultPrefix); | |
127 | $this->assertEquals($expected, $actual); | |
128 | } | |
a5b8726f | 129 | |
7fe37828 EM |
130 | /** |
131 | * @return array | |
132 | */ | |
00be9182 | 133 | public function booleanDataProvider() { |
39b959db | 134 | // array(0 => $input, 1 => $expectedOutput) |
9099cab3 CW |
135 | $cases = []; |
136 | $cases[] = [TRUE, TRUE]; | |
137 | $cases[] = [FALSE, FALSE]; | |
138 | $cases[] = [1, TRUE]; | |
139 | $cases[] = [0, FALSE]; | |
140 | $cases[] = ['1', TRUE]; | |
141 | $cases[] = ['0', FALSE]; | |
142 | $cases[] = [TRUE, TRUE]; | |
143 | $cases[] = [FALSE, FALSE]; | |
144 | $cases[] = ['Y', TRUE]; | |
145 | $cases[] = ['N', FALSE]; | |
146 | $cases[] = ['y', TRUE]; | |
147 | $cases[] = ['n', FALSE]; | |
148 | $cases[] = ['Yes', TRUE]; | |
149 | $cases[] = ['No', FALSE]; | |
150 | $cases[] = ['True', TRUE]; | |
151 | $cases[] = ['False', FALSE]; | |
152 | $cases[] = ['yEs', TRUE]; | |
153 | $cases[] = ['nO', FALSE]; | |
154 | $cases[] = ['tRuE', TRUE]; | |
155 | $cases[] = ['FaLsE', FALSE]; | |
a5b8726f TO |
156 | return $cases; |
157 | } | |
158 | ||
159 | /** | |
160 | * @param $input | |
5a4f6742 CW |
161 | * @param bool $expected |
162 | * * @dataProvider booleanDataProvider | |
a5b8726f | 163 | */ |
00be9182 | 164 | public function testStrToBool($input, $expected) { |
a5b8726f TO |
165 | $actual = CRM_Utils_String::strtobool($input); |
166 | $this->assertTrue($expected === $actual); | |
167 | } | |
168 | ||
83d511e6 | 169 | public function startEndCases() { |
9099cab3 CW |
170 | $cases = []; |
171 | $cases[] = ['startsWith', 'foo', '', TRUE]; | |
172 | $cases[] = ['startsWith', 'foo', 'f', TRUE]; | |
173 | $cases[] = ['startsWith', 'foo', 'fo', TRUE]; | |
174 | $cases[] = ['startsWith', 'foo', 'foo', TRUE]; | |
175 | $cases[] = ['startsWith', 'foo', 'fooo', FALSE]; | |
176 | $cases[] = ['startsWith', 'foo', 'o', FALSE]; | |
177 | $cases[] = ['endsWith', 'foo', 'f', FALSE]; | |
178 | $cases[] = ['endsWith', 'foo', '', TRUE]; | |
179 | $cases[] = ['endsWith', 'foo', 'o', TRUE]; | |
180 | $cases[] = ['endsWith', 'foo', 'oo', TRUE]; | |
181 | $cases[] = ['endsWith', 'foo', 'foo', TRUE]; | |
182 | $cases[] = ['endsWith', 'foo', 'fooo', FALSE]; | |
183 | $cases[] = ['endsWith', 'foo*', '*', TRUE]; | |
83d511e6 TO |
184 | return $cases; |
185 | } | |
186 | ||
187 | /** | |
188 | * @param string $func | |
189 | * One of: 'startsWith' or 'endsWith'. | |
190 | * @param $string | |
191 | * @param $fragment | |
192 | * @param $expectedResult | |
193 | * @dataProvider startEndCases | |
194 | */ | |
195 | public function testStartEndWith($func, $string, $fragment, $expectedResult) { | |
196 | $actualResult = \CRM_Utils_String::$func($string, $fragment); | |
197 | $this->assertEquals($expectedResult, $actualResult, "Checking $func($string,$fragment)"); | |
198 | } | |
199 | ||
200 | public function wildcardCases() { | |
9099cab3 CW |
201 | $cases = []; |
202 | $cases[] = ['*', ['foo.bar.1', 'foo.bar.2', 'foo.whiz', 'bang.bang']]; | |
203 | $cases[] = ['foo.*', ['foo.bar.1', 'foo.bar.2', 'foo.whiz']]; | |
204 | $cases[] = ['foo.bar.*', ['foo.bar.1', 'foo.bar.2']]; | |
205 | $cases[] = [['foo.bar.*', 'foo.bar.2'], ['foo.bar.1', 'foo.bar.2']]; | |
206 | $cases[] = [['foo.bar.2', 'foo.w*'], ['foo.bar.2', 'foo.whiz']]; | |
83d511e6 TO |
207 | return $cases; |
208 | } | |
209 | ||
210 | /** | |
211 | * @param $patterns | |
212 | * @param $expectedResults | |
213 | * @dataProvider wildcardCases | |
214 | */ | |
215 | public function testFilterByWildCards($patterns, $expectedResults) { | |
9099cab3 | 216 | $data = ['foo.bar.1', 'foo.bar.2', 'foo.whiz', 'bang.bang']; |
83d511e6 TO |
217 | |
218 | $actualResults = CRM_Utils_String::filterByWildcards($patterns, $data); | |
219 | $this->assertEquals($expectedResults, $actualResults); | |
220 | ||
221 | $patterns = (array) $patterns; | |
222 | $patterns[] = 'noise'; | |
223 | ||
224 | $actualResults = CRM_Utils_String::filterByWildcards($patterns, $data, FALSE); | |
225 | $this->assertEquals($expectedResults, $actualResults); | |
226 | ||
227 | $actualResults = CRM_Utils_String::filterByWildcards($patterns, $data, TRUE); | |
9099cab3 | 228 | $this->assertEquals(array_merge($expectedResults, ['noise']), $actualResults); |
83d511e6 TO |
229 | } |
230 | ||
6c094ca6 SM |
231 | /** |
232 | * CRM-20821 | |
233 | * CRM-14283 | |
234 | * | |
235 | * @param string $imageURL | |
236 | * @param book $forceHttps | |
237 | * @param string $expected | |
238 | * | |
239 | * @dataProvider simplifyURLProvider | |
240 | */ | |
241 | public function testSimplifyURL($imageURL, $forceHttps, $expected) { | |
242 | $this->assertEquals( | |
243 | $expected, | |
244 | CRM_Utils_String::simplifyURL($imageURL, $forceHttps) | |
245 | ); | |
246 | } | |
247 | ||
248 | /** | |
249 | * Used for testNormalizeImageURL above | |
250 | * | |
251 | * @return array | |
252 | */ | |
253 | public function simplifyURLProvider() { | |
6c094ca6 | 254 | $config = CRM_Core_Config::singleton(); |
57530e56 TO |
255 | $urlParts = CRM_Utils_String::simpleParseUrl($config->userFrameworkBaseURL); |
256 | $localDomain = $urlParts['host+port']; | |
257 | if (empty($localDomain)) { | |
258 | throw new \Exception("Failed to determine local base URL"); | |
259 | } | |
6c094ca6 SM |
260 | $externalDomain = 'example.org'; |
261 | ||
262 | // Ensure that $externalDomain really is different from $localDomain | |
263 | if ($externalDomain == $localDomain) { | |
264 | $externalDomain = 'example.net'; | |
265 | } | |
266 | ||
9099cab3 CW |
267 | return [ |
268 | 'prototypical example' => [ | |
6c094ca6 SM |
269 | "https://$localDomain/sites/default/files/coffee-mug.jpg", |
270 | FALSE, | |
271 | '/sites/default/files/coffee-mug.jpg', | |
9099cab3 CW |
272 | ], |
273 | 'external domain with https' => [ | |
6c094ca6 SM |
274 | "https://$externalDomain/sites/default/files/coffee-mug.jpg", |
275 | FALSE, | |
276 | "https://$externalDomain/sites/default/files/coffee-mug.jpg", | |
9099cab3 CW |
277 | ], |
278 | 'external domain with http forced to https' => [ | |
6c094ca6 SM |
279 | "http://$externalDomain/sites/default/files/coffee-mug.jpg", |
280 | TRUE, | |
281 | "https://$externalDomain/sites/default/files/coffee-mug.jpg", | |
9099cab3 CW |
282 | ], |
283 | 'external domain with http not forced' => [ | |
6c094ca6 SM |
284 | "http://$externalDomain/sites/default/files/coffee-mug.jpg", |
285 | FALSE, | |
286 | "http://$externalDomain/sites/default/files/coffee-mug.jpg", | |
9099cab3 CW |
287 | ], |
288 | 'local URL' => [ | |
6c094ca6 SM |
289 | "/sites/default/files/coffee-mug.jpg", |
290 | FALSE, | |
291 | "/sites/default/files/coffee-mug.jpg", | |
9099cab3 CW |
292 | ], |
293 | 'local URL without a forward slash' => [ | |
6c094ca6 SM |
294 | "sites/default/files/coffee-mug.jpg", |
295 | FALSE, | |
296 | "/sites/default/files/coffee-mug.jpg", | |
9099cab3 CW |
297 | ], |
298 | 'empty input' => [ | |
6c094ca6 SM |
299 | '', |
300 | FALSE, | |
301 | '', | |
9099cab3 CW |
302 | ], |
303 | ]; | |
6c094ca6 SM |
304 | } |
305 | ||
306 | /** | |
307 | * @param string $url | |
308 | * @param array $expected | |
309 | * | |
310 | * @dataProvider parseURLProvider | |
311 | */ | |
312 | public function testSimpleParseUrl($url, $expected) { | |
313 | $this->assertEquals( | |
314 | $expected, | |
315 | CRM_Utils_String::simpleParseUrl($url) | |
316 | ); | |
317 | } | |
318 | ||
319 | /** | |
320 | * Used for testSimpleParseUrl above | |
321 | * | |
322 | * @return array | |
323 | */ | |
324 | public function parseURLProvider() { | |
9099cab3 CW |
325 | return [ |
326 | "prototypical example" => [ | |
6c094ca6 | 327 | "https://example.com:8000/foo/bar/?id=1#fragment", |
9099cab3 | 328 | [ |
6c094ca6 SM |
329 | 'host+port' => "example.com:8000", |
330 | 'path+query' => "/foo/bar/?id=1", | |
9099cab3 CW |
331 | ], |
332 | ], | |
333 | "default port example" => [ | |
57530e56 | 334 | "https://example.com/foo/bar/?id=1#fragment", |
9099cab3 | 335 | [ |
57530e56 TO |
336 | 'host+port' => "example.com", |
337 | 'path+query' => "/foo/bar/?id=1", | |
9099cab3 CW |
338 | ], |
339 | ], | |
340 | "empty" => [ | |
6c094ca6 | 341 | "", |
9099cab3 | 342 | [ |
6c094ca6 SM |
343 | 'host+port' => "", |
344 | 'path+query' => "", | |
9099cab3 CW |
345 | ], |
346 | ], | |
347 | "path only" => [ | |
6c094ca6 | 348 | "/foo/bar/image.png", |
9099cab3 | 349 | [ |
6c094ca6 SM |
350 | 'host+port' => "", |
351 | 'path+query' => "/foo/bar/image.png", | |
9099cab3 CW |
352 | ], |
353 | ], | |
354 | ]; | |
6c094ca6 SM |
355 | } |
356 | ||
7652022e SL |
357 | public function purifyHTMLProvider() { |
358 | $tests = []; | |
359 | $tests[] = ['<span onmouseover=alert(0)>HOVER</span>', '<span>HOVER</span>']; | |
18b586ef | 360 | $tests[] = ['<a href="https://civicrm.org" target="_blank" class="button-purple">hello</a>', '<a href="https://civicrm.org" target="_blank" class="button-purple" rel="noreferrer noopener">hello</a>']; |
7652022e SL |
361 | return $tests; |
362 | } | |
363 | ||
364 | /** | |
365 | * Test ouput of purifyHTML | |
366 | * @param string $testString | |
367 | * @param string $expectedString | |
368 | * @dataProvider purifyHTMLProvider | |
369 | */ | |
370 | public function testPurifyHTML($testString, $expectedString) { | |
371 | $this->assertEquals($expectedString, CRM_Utils_String::purifyHTML($testString)); | |
372 | } | |
373 | ||
b2ce794b TO |
374 | public function getGoodSerializeExamples() { |
375 | $strs = []; | |
376 | ||
377 | $strs[] = ['a:1:{s:1:"a";s:1:"b";}']; | |
378 | $strs[] = ['d:1.2;']; | |
379 | $strs[] = ['s:3:"abc";']; | |
380 | $strs[] = ['N;']; | |
381 | $strs[] = ['a:7:{i:0;N;i:1;s:3:"abc";i:2;i:1;i:3;d:2.3;i:4;b:1;i:5;b:0;i:6;i:0;}']; | |
382 | ||
383 | return $strs; | |
384 | } | |
385 | ||
386 | /** | |
387 | * @param string $str | |
388 | * A safe serialized value. | |
389 | * @dataProvider getGoodSerializeExamples | |
390 | */ | |
391 | public function testGoodSerialize($str) { | |
392 | $this->assertEquals(unserialize($str), CRM_Utils_String::unserialize($str)); | |
393 | } | |
394 | ||
395 | public function getBadSerializeExamples() { | |
396 | $strs = []; | |
397 | ||
398 | $strs[] = ['O:8:"stdClass":0:{}']; | |
399 | $strs[] = ['O:9:"Exception":7:{s:10:"*message";s:3:"abc";s:17:"Exceptionstring";s:0:"";s:7:"*code";i:0;s:7:"*file";s:17:"Command line code";s:7:"*line";i:1;s:16:"Exceptiontrace";a:0:{}s:19:"Exceptionprevious";N;}']; | |
400 | ||
401 | return $strs; | |
402 | } | |
403 | ||
404 | /** | |
405 | * @param string $str | |
406 | * An unsafe serialized value. | |
407 | * @dataProvider getBadSerializeExamples | |
b2ce794b TO |
408 | */ |
409 | public function testBadSerializeExamples($str) { | |
ddcfa228 | 410 | $this->assertFalse(CRM_Utils_String::unserialize($str)); |
b2ce794b TO |
411 | } |
412 | ||
6a488035 | 413 | } |