SupportHelpersTest.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. <?php
  2. namespace Illuminate\Tests\Support;
  3. use ArrayAccess;
  4. use Illuminate\Contracts\Support\Htmlable;
  5. use Illuminate\Support\Env;
  6. use Illuminate\Support\Optional;
  7. use LogicException;
  8. use Mockery as m;
  9. use PHPUnit\Framework\TestCase;
  10. use RuntimeException;
  11. use stdClass;
  12. class SupportHelpersTest extends TestCase
  13. {
  14. protected function tearDown(): void
  15. {
  16. m::close();
  17. }
  18. public function testE()
  19. {
  20. $str = 'A \'quote\' is <b>bold</b>';
  21. $this->assertSame('A &#039;quote&#039; is &lt;b&gt;bold&lt;/b&gt;', e($str));
  22. $html = m::mock(Htmlable::class);
  23. $html->shouldReceive('toHtml')->andReturn($str);
  24. $this->assertEquals($str, e($html));
  25. }
  26. public function testClassBasename()
  27. {
  28. $this->assertSame('Baz', class_basename('Foo\Bar\Baz'));
  29. $this->assertSame('Baz', class_basename('Baz'));
  30. }
  31. public function testValue()
  32. {
  33. $this->assertSame('foo', value('foo'));
  34. $this->assertSame('foo', value(function () {
  35. return 'foo';
  36. }));
  37. $this->assertSame('foo', value(function ($arg) {
  38. return $arg;
  39. }, 'foo'));
  40. }
  41. public function testObjectGet()
  42. {
  43. $class = new stdClass;
  44. $class->name = new stdClass;
  45. $class->name->first = 'Taylor';
  46. $this->assertSame('Taylor', object_get($class, 'name.first'));
  47. }
  48. public function testDataGet()
  49. {
  50. $object = (object) ['users' => ['name' => ['Taylor', 'Otwell']]];
  51. $array = [(object) ['users' => [(object) ['name' => 'Taylor']]]];
  52. $dottedArray = ['users' => ['first.name' => 'Taylor', 'middle.name' => null]];
  53. $arrayAccess = new SupportTestArrayAccess(['price' => 56, 'user' => new SupportTestArrayAccess(['name' => 'John']), 'email' => null]);
  54. $this->assertSame('Taylor', data_get($object, 'users.name.0'));
  55. $this->assertSame('Taylor', data_get($array, '0.users.0.name'));
  56. $this->assertNull(data_get($array, '0.users.3'));
  57. $this->assertSame('Not found', data_get($array, '0.users.3', 'Not found'));
  58. $this->assertSame('Not found', data_get($array, '0.users.3', function () {
  59. return 'Not found';
  60. }));
  61. $this->assertSame('Taylor', data_get($dottedArray, ['users', 'first.name']));
  62. $this->assertNull(data_get($dottedArray, ['users', 'middle.name']));
  63. $this->assertSame('Not found', data_get($dottedArray, ['users', 'last.name'], 'Not found'));
  64. $this->assertEquals(56, data_get($arrayAccess, 'price'));
  65. $this->assertSame('John', data_get($arrayAccess, 'user.name'));
  66. $this->assertSame('void', data_get($arrayAccess, 'foo', 'void'));
  67. $this->assertSame('void', data_get($arrayAccess, 'user.foo', 'void'));
  68. $this->assertNull(data_get($arrayAccess, 'foo'));
  69. $this->assertNull(data_get($arrayAccess, 'user.foo'));
  70. $this->assertNull(data_get($arrayAccess, 'email', 'Not found'));
  71. }
  72. public function testDataGetWithNestedArrays()
  73. {
  74. $array = [
  75. ['name' => 'taylor', 'email' => 'taylorotwell@gmail.com'],
  76. ['name' => 'abigail'],
  77. ['name' => 'dayle'],
  78. ];
  79. $this->assertEquals(['taylor', 'abigail', 'dayle'], data_get($array, '*.name'));
  80. $this->assertEquals(['taylorotwell@gmail.com', null, null], data_get($array, '*.email', 'irrelevant'));
  81. $array = [
  82. 'users' => [
  83. ['first' => 'taylor', 'last' => 'otwell', 'email' => 'taylorotwell@gmail.com'],
  84. ['first' => 'abigail', 'last' => 'otwell'],
  85. ['first' => 'dayle', 'last' => 'rees'],
  86. ],
  87. 'posts' => null,
  88. ];
  89. $this->assertEquals(['taylor', 'abigail', 'dayle'], data_get($array, 'users.*.first'));
  90. $this->assertEquals(['taylorotwell@gmail.com', null, null], data_get($array, 'users.*.email', 'irrelevant'));
  91. $this->assertSame('not found', data_get($array, 'posts.*.date', 'not found'));
  92. $this->assertNull(data_get($array, 'posts.*.date'));
  93. }
  94. public function testDataGetWithDoubleNestedArraysCollapsesResult()
  95. {
  96. $array = [
  97. 'posts' => [
  98. [
  99. 'comments' => [
  100. ['author' => 'taylor', 'likes' => 4],
  101. ['author' => 'abigail', 'likes' => 3],
  102. ],
  103. ],
  104. [
  105. 'comments' => [
  106. ['author' => 'abigail', 'likes' => 2],
  107. ['author' => 'dayle'],
  108. ],
  109. ],
  110. [
  111. 'comments' => [
  112. ['author' => 'dayle'],
  113. ['author' => 'taylor', 'likes' => 1],
  114. ],
  115. ],
  116. ],
  117. ];
  118. $this->assertEquals(['taylor', 'abigail', 'abigail', 'dayle', 'dayle', 'taylor'], data_get($array, 'posts.*.comments.*.author'));
  119. $this->assertEquals([4, 3, 2, null, null, 1], data_get($array, 'posts.*.comments.*.likes'));
  120. $this->assertEquals([], data_get($array, 'posts.*.users.*.name', 'irrelevant'));
  121. $this->assertEquals([], data_get($array, 'posts.*.users.*.name'));
  122. }
  123. public function testDataFill()
  124. {
  125. $data = ['foo' => 'bar'];
  126. $this->assertEquals(['foo' => 'bar', 'baz' => 'boom'], data_fill($data, 'baz', 'boom'));
  127. $this->assertEquals(['foo' => 'bar', 'baz' => 'boom'], data_fill($data, 'baz', 'noop'));
  128. $this->assertEquals(['foo' => [], 'baz' => 'boom'], data_fill($data, 'foo.*', 'noop'));
  129. $this->assertEquals(
  130. ['foo' => ['bar' => 'kaboom'], 'baz' => 'boom'],
  131. data_fill($data, 'foo.bar', 'kaboom')
  132. );
  133. }
  134. public function testDataFillWithStar()
  135. {
  136. $data = ['foo' => 'bar'];
  137. $this->assertEquals(
  138. ['foo' => []],
  139. data_fill($data, 'foo.*.bar', 'noop')
  140. );
  141. $this->assertEquals(
  142. ['foo' => [], 'bar' => [['baz' => 'original'], []]],
  143. data_fill($data, 'bar', [['baz' => 'original'], []])
  144. );
  145. $this->assertEquals(
  146. ['foo' => [], 'bar' => [['baz' => 'original'], ['baz' => 'boom']]],
  147. data_fill($data, 'bar.*.baz', 'boom')
  148. );
  149. $this->assertEquals(
  150. ['foo' => [], 'bar' => [['baz' => 'original'], ['baz' => 'boom']]],
  151. data_fill($data, 'bar.*', 'noop')
  152. );
  153. }
  154. public function testDataFillWithDoubleStar()
  155. {
  156. $data = [
  157. 'posts' => [
  158. (object) [
  159. 'comments' => [
  160. (object) ['name' => 'First'],
  161. (object) [],
  162. ],
  163. ],
  164. (object) [
  165. 'comments' => [
  166. (object) [],
  167. (object) ['name' => 'Second'],
  168. ],
  169. ],
  170. ],
  171. ];
  172. data_fill($data, 'posts.*.comments.*.name', 'Filled');
  173. $this->assertEquals([
  174. 'posts' => [
  175. (object) [
  176. 'comments' => [
  177. (object) ['name' => 'First'],
  178. (object) ['name' => 'Filled'],
  179. ],
  180. ],
  181. (object) [
  182. 'comments' => [
  183. (object) ['name' => 'Filled'],
  184. (object) ['name' => 'Second'],
  185. ],
  186. ],
  187. ],
  188. ], $data);
  189. }
  190. public function testDataSet()
  191. {
  192. $data = ['foo' => 'bar'];
  193. $this->assertEquals(
  194. ['foo' => 'bar', 'baz' => 'boom'],
  195. data_set($data, 'baz', 'boom')
  196. );
  197. $this->assertEquals(
  198. ['foo' => 'bar', 'baz' => 'kaboom'],
  199. data_set($data, 'baz', 'kaboom')
  200. );
  201. $this->assertEquals(
  202. ['foo' => [], 'baz' => 'kaboom'],
  203. data_set($data, 'foo.*', 'noop')
  204. );
  205. $this->assertEquals(
  206. ['foo' => ['bar' => 'boom'], 'baz' => 'kaboom'],
  207. data_set($data, 'foo.bar', 'boom')
  208. );
  209. $this->assertEquals(
  210. ['foo' => ['bar' => 'boom'], 'baz' => ['bar' => 'boom']],
  211. data_set($data, 'baz.bar', 'boom')
  212. );
  213. $this->assertEquals(
  214. ['foo' => ['bar' => 'boom'], 'baz' => ['bar' => ['boom' => ['kaboom' => 'boom']]]],
  215. data_set($data, 'baz.bar.boom.kaboom', 'boom')
  216. );
  217. }
  218. public function testDataSetWithStar()
  219. {
  220. $data = ['foo' => 'bar'];
  221. $this->assertEquals(
  222. ['foo' => []],
  223. data_set($data, 'foo.*.bar', 'noop')
  224. );
  225. $this->assertEquals(
  226. ['foo' => [], 'bar' => [['baz' => 'original'], []]],
  227. data_set($data, 'bar', [['baz' => 'original'], []])
  228. );
  229. $this->assertEquals(
  230. ['foo' => [], 'bar' => [['baz' => 'boom'], ['baz' => 'boom']]],
  231. data_set($data, 'bar.*.baz', 'boom')
  232. );
  233. $this->assertEquals(
  234. ['foo' => [], 'bar' => ['overwritten', 'overwritten']],
  235. data_set($data, 'bar.*', 'overwritten')
  236. );
  237. }
  238. public function testDataSetWithDoubleStar()
  239. {
  240. $data = [
  241. 'posts' => [
  242. (object) [
  243. 'comments' => [
  244. (object) ['name' => 'First'],
  245. (object) [],
  246. ],
  247. ],
  248. (object) [
  249. 'comments' => [
  250. (object) [],
  251. (object) ['name' => 'Second'],
  252. ],
  253. ],
  254. ],
  255. ];
  256. data_set($data, 'posts.*.comments.*.name', 'Filled');
  257. $this->assertEquals([
  258. 'posts' => [
  259. (object) [
  260. 'comments' => [
  261. (object) ['name' => 'Filled'],
  262. (object) ['name' => 'Filled'],
  263. ],
  264. ],
  265. (object) [
  266. 'comments' => [
  267. (object) ['name' => 'Filled'],
  268. (object) ['name' => 'Filled'],
  269. ],
  270. ],
  271. ],
  272. ], $data);
  273. }
  274. public function testHead()
  275. {
  276. $array = ['a', 'b', 'c'];
  277. $this->assertSame('a', head($array));
  278. }
  279. public function testLast()
  280. {
  281. $array = ['a', 'b', 'c'];
  282. $this->assertSame('c', last($array));
  283. }
  284. public function testClassUsesRecursiveShouldReturnTraitsOnParentClasses()
  285. {
  286. $this->assertSame([
  287. SupportTestTraitTwo::class => SupportTestTraitTwo::class,
  288. SupportTestTraitOne::class => SupportTestTraitOne::class,
  289. ],
  290. class_uses_recursive(SupportTestClassTwo::class));
  291. }
  292. public function testClassUsesRecursiveAcceptsObject()
  293. {
  294. $this->assertSame([
  295. SupportTestTraitTwo::class => SupportTestTraitTwo::class,
  296. SupportTestTraitOne::class => SupportTestTraitOne::class,
  297. ],
  298. class_uses_recursive(new SupportTestClassTwo));
  299. }
  300. public function testClassUsesRecursiveReturnParentTraitsFirst()
  301. {
  302. $this->assertSame([
  303. SupportTestTraitTwo::class => SupportTestTraitTwo::class,
  304. SupportTestTraitOne::class => SupportTestTraitOne::class,
  305. SupportTestTraitThree::class => SupportTestTraitThree::class,
  306. ],
  307. class_uses_recursive(SupportTestClassThree::class));
  308. }
  309. public function testTap()
  310. {
  311. $object = (object) ['id' => 1];
  312. $this->assertEquals(2, tap($object, function ($object) {
  313. $object->id = 2;
  314. })->id);
  315. $mock = m::mock();
  316. $mock->shouldReceive('foo')->once()->andReturn('bar');
  317. $this->assertEquals($mock, tap($mock)->foo());
  318. }
  319. public function testThrow()
  320. {
  321. $this->expectException(LogicException::class);
  322. throw_if(true, new LogicException);
  323. }
  324. public function testThrowDefaultException()
  325. {
  326. $this->expectException(RuntimeException::class);
  327. throw_if(true);
  328. }
  329. public function testThrowExceptionWithMessage()
  330. {
  331. $this->expectException(RuntimeException::class);
  332. $this->expectExceptionMessage('test');
  333. throw_if(true, 'test');
  334. }
  335. public function testThrowExceptionAsStringWithMessage()
  336. {
  337. $this->expectException(LogicException::class);
  338. $this->expectExceptionMessage('test');
  339. throw_if(true, LogicException::class, 'test');
  340. }
  341. public function testThrowUnless()
  342. {
  343. $this->expectException(LogicException::class);
  344. throw_unless(false, new LogicException);
  345. }
  346. public function testThrowUnlessDefaultException()
  347. {
  348. $this->expectException(RuntimeException::class);
  349. throw_unless(false);
  350. }
  351. public function testThrowUnlessExceptionWithMessage()
  352. {
  353. $this->expectException(RuntimeException::class);
  354. $this->expectExceptionMessage('test');
  355. throw_unless(false, 'test');
  356. }
  357. public function testThrowUnlessExceptionAsStringWithMessage()
  358. {
  359. $this->expectException(LogicException::class);
  360. $this->expectExceptionMessage('test');
  361. throw_unless(false, LogicException::class, 'test');
  362. }
  363. public function testThrowReturnIfNotThrown()
  364. {
  365. $this->assertSame('foo', throw_unless('foo', new RuntimeException));
  366. }
  367. public function testThrowWithString()
  368. {
  369. $this->expectException(RuntimeException::class);
  370. $this->expectExceptionMessage('Test Message');
  371. throw_if(true, RuntimeException::class, 'Test Message');
  372. }
  373. public function testOptional()
  374. {
  375. $this->assertNull(optional(null)->something());
  376. $this->assertEquals(10, optional(new class
  377. {
  378. public function something()
  379. {
  380. return 10;
  381. }
  382. })->something());
  383. }
  384. public function testOptionalWithCallback()
  385. {
  386. $this->assertNull(optional(null, function () {
  387. throw new RuntimeException(
  388. 'The optional callback should not be called for null'
  389. );
  390. }));
  391. $this->assertEquals(10, optional(5, function ($number) {
  392. return $number * 2;
  393. }));
  394. }
  395. public function testOptionalWithArray()
  396. {
  397. $this->assertSame('here', optional(['present' => 'here'])['present']);
  398. $this->assertNull(optional(null)['missing']);
  399. $this->assertNull(optional(['present' => 'here'])->missing);
  400. }
  401. public function testOptionalReturnsObjectPropertyOrNull()
  402. {
  403. $this->assertSame('bar', optional((object) ['foo' => 'bar'])->foo);
  404. $this->assertNull(optional(['foo' => 'bar'])->foo);
  405. $this->assertNull(optional((object) ['foo' => 'bar'])->bar);
  406. }
  407. public function testOptionalDeterminesWhetherKeyIsSet()
  408. {
  409. $this->assertTrue(isset(optional(['foo' => 'bar'])['foo']));
  410. $this->assertFalse(isset(optional(['foo' => 'bar'])['bar']));
  411. $this->assertFalse(isset(optional()['bar']));
  412. }
  413. public function testOptionalAllowsToSetKey()
  414. {
  415. $optional = optional([]);
  416. $optional['foo'] = 'bar';
  417. $this->assertSame('bar', $optional['foo']);
  418. $optional = optional(null);
  419. $optional['foo'] = 'bar';
  420. $this->assertFalse(isset($optional['foo']));
  421. }
  422. public function testOptionalAllowToUnsetKey()
  423. {
  424. $optional = optional(['foo' => 'bar']);
  425. $this->assertTrue(isset($optional['foo']));
  426. unset($optional['foo']);
  427. $this->assertFalse(isset($optional['foo']));
  428. $optional = optional((object) ['foo' => 'bar']);
  429. $this->assertFalse(isset($optional['foo']));
  430. $optional['foo'] = 'bar';
  431. $this->assertFalse(isset($optional['foo']));
  432. }
  433. public function testOptionalIsMacroable()
  434. {
  435. Optional::macro('present', function () {
  436. if (is_object($this->value)) {
  437. return $this->value->present();
  438. }
  439. return new Optional(null);
  440. });
  441. $this->assertNull(optional(null)->present()->something());
  442. $this->assertSame('$10.00', optional(new class
  443. {
  444. public function present()
  445. {
  446. return new class
  447. {
  448. public function something()
  449. {
  450. return '$10.00';
  451. }
  452. };
  453. }
  454. })->present()->something());
  455. }
  456. public function testRetry()
  457. {
  458. $startTime = microtime(true);
  459. $attempts = retry(2, function ($attempts) {
  460. if ($attempts > 1) {
  461. return $attempts;
  462. }
  463. throw new RuntimeException;
  464. }, 100);
  465. // Make sure we made two attempts
  466. $this->assertEquals(2, $attempts);
  467. // Make sure we waited 100ms for the first attempt
  468. $this->assertEqualsWithDelta(0.1, microtime(true) - $startTime, 0.03);
  469. }
  470. public function testRetryWithPassingSleepCallback()
  471. {
  472. $startTime = microtime(true);
  473. $attempts = retry(3, function ($attempts) {
  474. if ($attempts > 2) {
  475. return $attempts;
  476. }
  477. throw new RuntimeException;
  478. }, function ($attempt) {
  479. return $attempt * 100;
  480. });
  481. // Make sure we made three attempts
  482. $this->assertEquals(3, $attempts);
  483. // Make sure we waited 300ms for the first two attempts
  484. $this->assertEqualsWithDelta(0.3, microtime(true) - $startTime, 0.03);
  485. }
  486. public function testRetryWithPassingWhenCallback()
  487. {
  488. $startTime = microtime(true);
  489. $attempts = retry(2, function ($attempts) {
  490. if ($attempts > 1) {
  491. return $attempts;
  492. }
  493. throw new RuntimeException;
  494. }, 100, function ($ex) {
  495. return true;
  496. });
  497. // Make sure we made two attempts
  498. $this->assertEquals(2, $attempts);
  499. // Make sure we waited 100ms for the first attempt
  500. $this->assertEqualsWithDelta(0.1, microtime(true) - $startTime, 0.03);
  501. }
  502. public function testRetryWithFailingWhenCallback()
  503. {
  504. $this->expectException(RuntimeException::class);
  505. retry(2, function ($attempts) {
  506. if ($attempts > 1) {
  507. return $attempts;
  508. }
  509. throw new RuntimeException;
  510. }, 100, function ($ex) {
  511. return false;
  512. });
  513. }
  514. public function testTransform()
  515. {
  516. $this->assertEquals(10, transform(5, function ($value) {
  517. return $value * 2;
  518. }));
  519. $this->assertNull(transform(null, function () {
  520. return 10;
  521. }));
  522. }
  523. public function testTransformDefaultWhenBlank()
  524. {
  525. $this->assertSame('baz', transform(null, function () {
  526. return 'bar';
  527. }, 'baz'));
  528. $this->assertSame('baz', transform('', function () {
  529. return 'bar';
  530. }, function () {
  531. return 'baz';
  532. }));
  533. }
  534. public function testWith()
  535. {
  536. $this->assertEquals(10, with(10));
  537. $this->assertEquals(10, with(5, function ($five) {
  538. return $five + 5;
  539. }));
  540. }
  541. public function testEnv()
  542. {
  543. $_SERVER['foo'] = 'bar';
  544. $this->assertSame('bar', env('foo'));
  545. $this->assertSame('bar', Env::get('foo'));
  546. }
  547. public function testEnvTrue()
  548. {
  549. $_SERVER['foo'] = 'true';
  550. $this->assertTrue(env('foo'));
  551. $_SERVER['foo'] = '(true)';
  552. $this->assertTrue(env('foo'));
  553. }
  554. public function testEnvFalse()
  555. {
  556. $_SERVER['foo'] = 'false';
  557. $this->assertFalse(env('foo'));
  558. $_SERVER['foo'] = '(false)';
  559. $this->assertFalse(env('foo'));
  560. }
  561. public function testEnvEmpty()
  562. {
  563. $_SERVER['foo'] = '';
  564. $this->assertSame('', env('foo'));
  565. $_SERVER['foo'] = 'empty';
  566. $this->assertSame('', env('foo'));
  567. $_SERVER['foo'] = '(empty)';
  568. $this->assertSame('', env('foo'));
  569. }
  570. public function testEnvNull()
  571. {
  572. $_SERVER['foo'] = 'null';
  573. $this->assertNull(env('foo'));
  574. $_SERVER['foo'] = '(null)';
  575. $this->assertNull(env('foo'));
  576. }
  577. public function testEnvDefault()
  578. {
  579. $_SERVER['foo'] = 'bar';
  580. $this->assertSame('bar', env('foo', 'default'));
  581. $_SERVER['foo'] = '';
  582. $this->assertSame('', env('foo', 'default'));
  583. unset($_SERVER['foo']);
  584. $this->assertSame('default', env('foo', 'default'));
  585. $_SERVER['foo'] = null;
  586. $this->assertSame('default', env('foo', 'default'));
  587. }
  588. public function testEnvEscapedString()
  589. {
  590. $_SERVER['foo'] = '"null"';
  591. $this->assertSame('null', env('foo'));
  592. $_SERVER['foo'] = "'null'";
  593. $this->assertSame('null', env('foo'));
  594. $_SERVER['foo'] = 'x"null"x'; // this should not be unquoted
  595. $this->assertSame('x"null"x', env('foo'));
  596. }
  597. public function testGetFromSERVERFirst()
  598. {
  599. $_ENV['foo'] = 'From $_ENV';
  600. $_SERVER['foo'] = 'From $_SERVER';
  601. $this->assertSame('From $_SERVER', env('foo'));
  602. }
  603. public function providesPregReplaceArrayData()
  604. {
  605. $pointerArray = ['Taylor', 'Otwell'];
  606. next($pointerArray);
  607. return [
  608. ['/:[a-z_]+/', ['8:30', '9:00'], 'The event will take place between :start and :end', 'The event will take place between 8:30 and 9:00'],
  609. ['/%s/', ['Taylor'], 'Hi, %s', 'Hi, Taylor'],
  610. ['/%s/', ['Taylor', 'Otwell'], 'Hi, %s %s', 'Hi, Taylor Otwell'],
  611. ['/%s/', [], 'Hi, %s %s', 'Hi, '],
  612. ['/%s/', ['a', 'b', 'c'], 'Hi', 'Hi'],
  613. ['//', [], '', ''],
  614. ['/%s/', ['a'], '', ''],
  615. // The internal pointer of this array is not at the beginning
  616. ['/%s/', $pointerArray, 'Hi, %s %s', 'Hi, Taylor Otwell'],
  617. ];
  618. }
  619. /**
  620. * @dataProvider providesPregReplaceArrayData
  621. */
  622. public function testPregReplaceArray($pattern, $replacements, $subject, $expectedOutput)
  623. {
  624. $this->assertSame(
  625. $expectedOutput,
  626. preg_replace_array($pattern, $replacements, $subject)
  627. );
  628. }
  629. }
  630. trait SupportTestTraitOne
  631. {
  632. //
  633. }
  634. trait SupportTestTraitTwo
  635. {
  636. use SupportTestTraitOne;
  637. }
  638. class SupportTestClassOne
  639. {
  640. use SupportTestTraitTwo;
  641. }
  642. class SupportTestClassTwo extends SupportTestClassOne
  643. {
  644. //
  645. }
  646. trait SupportTestTraitThree
  647. {
  648. //
  649. }
  650. class SupportTestClassThree extends SupportTestClassTwo
  651. {
  652. use SupportTestTraitThree;
  653. }
  654. class SupportTestArrayAccess implements ArrayAccess
  655. {
  656. protected $attributes = [];
  657. public function __construct($attributes = [])
  658. {
  659. $this->attributes = $attributes;
  660. }
  661. public function offsetExists($offset): bool
  662. {
  663. return array_key_exists($offset, $this->attributes);
  664. }
  665. #[\ReturnTypeWillChange]
  666. public function offsetGet($offset)
  667. {
  668. return $this->attributes[$offset];
  669. }
  670. public function offsetSet($offset, $value): void
  671. {
  672. $this->attributes[$offset] = $value;
  673. }
  674. public function offsetUnset($offset): void
  675. {
  676. unset($this->attributes[$offset]);
  677. }
  678. }