SupportArrTest.php 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. <?php
  2. namespace Illuminate\Tests\Support;
  3. use ArrayObject;
  4. use Illuminate\Support\Arr;
  5. use Illuminate\Support\Carbon;
  6. use Illuminate\Support\Collection;
  7. use InvalidArgumentException;
  8. use PHPUnit\Framework\TestCase;
  9. use stdClass;
  10. class SupportArrTest extends TestCase
  11. {
  12. public function testAccessible()
  13. {
  14. $this->assertTrue(Arr::accessible([]));
  15. $this->assertTrue(Arr::accessible([1, 2]));
  16. $this->assertTrue(Arr::accessible(['a' => 1, 'b' => 2]));
  17. $this->assertTrue(Arr::accessible(new Collection));
  18. $this->assertFalse(Arr::accessible(null));
  19. $this->assertFalse(Arr::accessible('abc'));
  20. $this->assertFalse(Arr::accessible(new stdClass));
  21. $this->assertFalse(Arr::accessible((object) ['a' => 1, 'b' => 2]));
  22. }
  23. public function testAdd()
  24. {
  25. $array = Arr::add(['name' => 'Desk'], 'price', 100);
  26. $this->assertEquals(['name' => 'Desk', 'price' => 100], $array);
  27. $this->assertEquals(['surname' => 'Mövsümov'], Arr::add([], 'surname', 'Mövsümov'));
  28. $this->assertEquals(['developer' => ['name' => 'Ferid']], Arr::add([], 'developer.name', 'Ferid'));
  29. }
  30. public function testCollapse()
  31. {
  32. $data = [['foo', 'bar'], ['baz']];
  33. $this->assertEquals(['foo', 'bar', 'baz'], Arr::collapse($data));
  34. $array = [[1], [2], [3], ['foo', 'bar'], collect(['baz', 'boom'])];
  35. $this->assertEquals([1, 2, 3, 'foo', 'bar', 'baz', 'boom'], Arr::collapse($array));
  36. }
  37. public function testCrossJoin()
  38. {
  39. // Single dimension
  40. $this->assertSame(
  41. [[1, 'a'], [1, 'b'], [1, 'c']],
  42. Arr::crossJoin([1], ['a', 'b', 'c'])
  43. );
  44. // Square matrix
  45. $this->assertSame(
  46. [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']],
  47. Arr::crossJoin([1, 2], ['a', 'b'])
  48. );
  49. // Rectangular matrix
  50. $this->assertSame(
  51. [[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']],
  52. Arr::crossJoin([1, 2], ['a', 'b', 'c'])
  53. );
  54. // 3D matrix
  55. $this->assertSame(
  56. [
  57. [1, 'a', 'I'], [1, 'a', 'II'], [1, 'a', 'III'],
  58. [1, 'b', 'I'], [1, 'b', 'II'], [1, 'b', 'III'],
  59. [2, 'a', 'I'], [2, 'a', 'II'], [2, 'a', 'III'],
  60. [2, 'b', 'I'], [2, 'b', 'II'], [2, 'b', 'III'],
  61. ],
  62. Arr::crossJoin([1, 2], ['a', 'b'], ['I', 'II', 'III'])
  63. );
  64. // With 1 empty dimension
  65. $this->assertEmpty(Arr::crossJoin([], ['a', 'b'], ['I', 'II', 'III']));
  66. $this->assertEmpty(Arr::crossJoin([1, 2], [], ['I', 'II', 'III']));
  67. $this->assertEmpty(Arr::crossJoin([1, 2], ['a', 'b'], []));
  68. // With empty arrays
  69. $this->assertEmpty(Arr::crossJoin([], [], []));
  70. $this->assertEmpty(Arr::crossJoin([], []));
  71. $this->assertEmpty(Arr::crossJoin([]));
  72. // Not really a proper usage, still, test for preserving BC
  73. $this->assertSame([[]], Arr::crossJoin());
  74. }
  75. public function testDivide()
  76. {
  77. [$keys, $values] = Arr::divide(['name' => 'Desk']);
  78. $this->assertEquals(['name'], $keys);
  79. $this->assertEquals(['Desk'], $values);
  80. }
  81. public function testDot()
  82. {
  83. $array = Arr::dot(['foo' => ['bar' => 'baz']]);
  84. $this->assertEquals(['foo.bar' => 'baz'], $array);
  85. $array = Arr::dot([]);
  86. $this->assertEquals([], $array);
  87. $array = Arr::dot(['foo' => []]);
  88. $this->assertEquals(['foo' => []], $array);
  89. $array = Arr::dot(['foo' => ['bar' => []]]);
  90. $this->assertEquals(['foo.bar' => []], $array);
  91. $array = Arr::dot(['name' => 'taylor', 'languages' => ['php' => true]]);
  92. $this->assertEquals(['name' => 'taylor', 'languages.php' => true], $array);
  93. }
  94. public function testUndot()
  95. {
  96. $array = Arr::undot([
  97. 'user.name' => 'Taylor',
  98. 'user.age' => 25,
  99. 'user.languages.0' => 'PHP',
  100. 'user.languages.1' => 'C#',
  101. ]);
  102. $this->assertEquals(['user' => ['name' => 'Taylor', 'age' => 25, 'languages' => ['PHP', 'C#']]], $array);
  103. $array = Arr::undot([
  104. 'pagination.previous' => '<<',
  105. 'pagination.next' => '>>',
  106. ]);
  107. $this->assertEquals(['pagination' => ['previous' => '<<', 'next' => '>>']], $array);
  108. $array = Arr::undot([
  109. 'foo',
  110. 'foo.bar' => 'baz',
  111. 'foo.baz' => ['a' => 'b'],
  112. ]);
  113. $this->assertEquals(['foo', 'foo' => ['bar' => 'baz', 'baz' => ['a' => 'b']]], $array);
  114. }
  115. public function testExcept()
  116. {
  117. $array = ['name' => 'taylor', 'age' => 26];
  118. $this->assertEquals(['age' => 26], Arr::except($array, ['name']));
  119. $this->assertEquals(['age' => 26], Arr::except($array, 'name'));
  120. $array = ['name' => 'taylor', 'framework' => ['language' => 'PHP', 'name' => 'Laravel']];
  121. $this->assertEquals(['name' => 'taylor'], Arr::except($array, 'framework'));
  122. $this->assertEquals(['name' => 'taylor', 'framework' => ['name' => 'Laravel']], Arr::except($array, 'framework.language'));
  123. $this->assertEquals(['framework' => ['language' => 'PHP']], Arr::except($array, ['name', 'framework.name']));
  124. }
  125. public function testExists()
  126. {
  127. $this->assertTrue(Arr::exists([1], 0));
  128. $this->assertTrue(Arr::exists([null], 0));
  129. $this->assertTrue(Arr::exists(['a' => 1], 'a'));
  130. $this->assertTrue(Arr::exists(['a' => null], 'a'));
  131. $this->assertTrue(Arr::exists(new Collection(['a' => null]), 'a'));
  132. $this->assertFalse(Arr::exists([1], 1));
  133. $this->assertFalse(Arr::exists([null], 1));
  134. $this->assertFalse(Arr::exists(['a' => 1], 0));
  135. $this->assertFalse(Arr::exists(new Collection(['a' => null]), 'b'));
  136. }
  137. public function testWhereNotNull()
  138. {
  139. $array = array_values(Arr::whereNotNull([null, 0, false, '', null, []]));
  140. $this->assertEquals([0, false, '', []], $array);
  141. }
  142. public function testFirst()
  143. {
  144. $array = [100, 200, 300];
  145. // Callback is null and array is empty
  146. $this->assertNull(Arr::first([], null));
  147. $this->assertSame('foo', Arr::first([], null, 'foo'));
  148. $this->assertSame('bar', Arr::first([], null, function () {
  149. return 'bar';
  150. }));
  151. // Callback is null and array is not empty
  152. $this->assertEquals(100, Arr::first($array));
  153. // Callback is not null and array is not empty
  154. $value = Arr::first($array, function ($value) {
  155. return $value >= 150;
  156. });
  157. $this->assertEquals(200, $value);
  158. // Callback is not null, array is not empty but no satisfied item
  159. $value2 = Arr::first($array, function ($value) {
  160. return $value > 300;
  161. });
  162. $value3 = Arr::first($array, function ($value) {
  163. return $value > 300;
  164. }, 'bar');
  165. $value4 = Arr::first($array, function ($value) {
  166. return $value > 300;
  167. }, function () {
  168. return 'baz';
  169. });
  170. $this->assertNull($value2);
  171. $this->assertSame('bar', $value3);
  172. $this->assertSame('baz', $value4);
  173. }
  174. public function testLast()
  175. {
  176. $array = [100, 200, 300];
  177. $last = Arr::last($array, function ($value) {
  178. return $value < 250;
  179. });
  180. $this->assertEquals(200, $last);
  181. $last = Arr::last($array, function ($value, $key) {
  182. return $key < 2;
  183. });
  184. $this->assertEquals(200, $last);
  185. $this->assertEquals(300, Arr::last($array));
  186. }
  187. public function testFlatten()
  188. {
  189. // Flat arrays are unaffected
  190. $array = ['#foo', '#bar', '#baz'];
  191. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  192. // Nested arrays are flattened with existing flat items
  193. $array = [['#foo', '#bar'], '#baz'];
  194. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  195. // Flattened array includes "null" items
  196. $array = [['#foo', null], '#baz', null];
  197. $this->assertEquals(['#foo', null, '#baz', null], Arr::flatten($array));
  198. // Sets of nested arrays are flattened
  199. $array = [['#foo', '#bar'], ['#baz']];
  200. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  201. // Deeply nested arrays are flattened
  202. $array = [['#foo', ['#bar']], ['#baz']];
  203. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  204. // Nested arrays are flattened alongside arrays
  205. $array = [new Collection(['#foo', '#bar']), ['#baz']];
  206. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  207. // Nested arrays containing plain arrays are flattened
  208. $array = [new Collection(['#foo', ['#bar']]), ['#baz']];
  209. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  210. // Nested arrays containing arrays are flattened
  211. $array = [['#foo', new Collection(['#bar'])], ['#baz']];
  212. $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array));
  213. // Nested arrays containing arrays containing arrays are flattened
  214. $array = [['#foo', new Collection(['#bar', ['#zap']])], ['#baz']];
  215. $this->assertEquals(['#foo', '#bar', '#zap', '#baz'], Arr::flatten($array));
  216. }
  217. public function testFlattenWithDepth()
  218. {
  219. // No depth flattens recursively
  220. $array = [['#foo', ['#bar', ['#baz']]], '#zap'];
  221. $this->assertEquals(['#foo', '#bar', '#baz', '#zap'], Arr::flatten($array));
  222. // Specifying a depth only flattens to that depth
  223. $array = [['#foo', ['#bar', ['#baz']]], '#zap'];
  224. $this->assertEquals(['#foo', ['#bar', ['#baz']], '#zap'], Arr::flatten($array, 1));
  225. $array = [['#foo', ['#bar', ['#baz']]], '#zap'];
  226. $this->assertEquals(['#foo', '#bar', ['#baz'], '#zap'], Arr::flatten($array, 2));
  227. }
  228. public function testGet()
  229. {
  230. $array = ['products.desk' => ['price' => 100]];
  231. $this->assertEquals(['price' => 100], Arr::get($array, 'products.desk'));
  232. $array = ['products' => ['desk' => ['price' => 100]]];
  233. $value = Arr::get($array, 'products.desk');
  234. $this->assertEquals(['price' => 100], $value);
  235. // Test null array values
  236. $array = ['foo' => null, 'bar' => ['baz' => null]];
  237. $this->assertNull(Arr::get($array, 'foo', 'default'));
  238. $this->assertNull(Arr::get($array, 'bar.baz', 'default'));
  239. // Test direct ArrayAccess object
  240. $array = ['products' => ['desk' => ['price' => 100]]];
  241. $arrayAccessObject = new ArrayObject($array);
  242. $value = Arr::get($arrayAccessObject, 'products.desk');
  243. $this->assertEquals(['price' => 100], $value);
  244. // Test array containing ArrayAccess object
  245. $arrayAccessChild = new ArrayObject(['products' => ['desk' => ['price' => 100]]]);
  246. $array = ['child' => $arrayAccessChild];
  247. $value = Arr::get($array, 'child.products.desk');
  248. $this->assertEquals(['price' => 100], $value);
  249. // Test array containing multiple nested ArrayAccess objects
  250. $arrayAccessChild = new ArrayObject(['products' => ['desk' => ['price' => 100]]]);
  251. $arrayAccessParent = new ArrayObject(['child' => $arrayAccessChild]);
  252. $array = ['parent' => $arrayAccessParent];
  253. $value = Arr::get($array, 'parent.child.products.desk');
  254. $this->assertEquals(['price' => 100], $value);
  255. // Test missing ArrayAccess object field
  256. $arrayAccessChild = new ArrayObject(['products' => ['desk' => ['price' => 100]]]);
  257. $arrayAccessParent = new ArrayObject(['child' => $arrayAccessChild]);
  258. $array = ['parent' => $arrayAccessParent];
  259. $value = Arr::get($array, 'parent.child.desk');
  260. $this->assertNull($value);
  261. // Test missing ArrayAccess object field
  262. $arrayAccessObject = new ArrayObject(['products' => ['desk' => null]]);
  263. $array = ['parent' => $arrayAccessObject];
  264. $value = Arr::get($array, 'parent.products.desk.price');
  265. $this->assertNull($value);
  266. // Test null ArrayAccess object fields
  267. $array = new ArrayObject(['foo' => null, 'bar' => new ArrayObject(['baz' => null])]);
  268. $this->assertNull(Arr::get($array, 'foo', 'default'));
  269. $this->assertNull(Arr::get($array, 'bar.baz', 'default'));
  270. // Test null key returns the whole array
  271. $array = ['foo', 'bar'];
  272. $this->assertEquals($array, Arr::get($array, null));
  273. // Test $array not an array
  274. $this->assertSame('default', Arr::get(null, 'foo', 'default'));
  275. $this->assertSame('default', Arr::get(false, 'foo', 'default'));
  276. // Test $array not an array and key is null
  277. $this->assertSame('default', Arr::get(null, null, 'default'));
  278. // Test $array is empty and key is null
  279. $this->assertEmpty(Arr::get([], null));
  280. $this->assertEmpty(Arr::get([], null, 'default'));
  281. // Test numeric keys
  282. $array = [
  283. 'products' => [
  284. ['name' => 'desk'],
  285. ['name' => 'chair'],
  286. ],
  287. ];
  288. $this->assertSame('desk', Arr::get($array, 'products.0.name'));
  289. $this->assertSame('chair', Arr::get($array, 'products.1.name'));
  290. // Test return default value for non-existing key.
  291. $array = ['names' => ['developer' => 'taylor']];
  292. $this->assertSame('dayle', Arr::get($array, 'names.otherDeveloper', 'dayle'));
  293. $this->assertSame('dayle', Arr::get($array, 'names.otherDeveloper', function () {
  294. return 'dayle';
  295. }));
  296. }
  297. public function testHas()
  298. {
  299. $array = ['products.desk' => ['price' => 100]];
  300. $this->assertTrue(Arr::has($array, 'products.desk'));
  301. $array = ['products' => ['desk' => ['price' => 100]]];
  302. $this->assertTrue(Arr::has($array, 'products.desk'));
  303. $this->assertTrue(Arr::has($array, 'products.desk.price'));
  304. $this->assertFalse(Arr::has($array, 'products.foo'));
  305. $this->assertFalse(Arr::has($array, 'products.desk.foo'));
  306. $array = ['foo' => null, 'bar' => ['baz' => null]];
  307. $this->assertTrue(Arr::has($array, 'foo'));
  308. $this->assertTrue(Arr::has($array, 'bar.baz'));
  309. $array = new ArrayObject(['foo' => 10, 'bar' => new ArrayObject(['baz' => 10])]);
  310. $this->assertTrue(Arr::has($array, 'foo'));
  311. $this->assertTrue(Arr::has($array, 'bar'));
  312. $this->assertTrue(Arr::has($array, 'bar.baz'));
  313. $this->assertFalse(Arr::has($array, 'xxx'));
  314. $this->assertFalse(Arr::has($array, 'xxx.yyy'));
  315. $this->assertFalse(Arr::has($array, 'foo.xxx'));
  316. $this->assertFalse(Arr::has($array, 'bar.xxx'));
  317. $array = new ArrayObject(['foo' => null, 'bar' => new ArrayObject(['baz' => null])]);
  318. $this->assertTrue(Arr::has($array, 'foo'));
  319. $this->assertTrue(Arr::has($array, 'bar.baz'));
  320. $array = ['foo', 'bar'];
  321. $this->assertFalse(Arr::has($array, null));
  322. $this->assertFalse(Arr::has(null, 'foo'));
  323. $this->assertFalse(Arr::has(false, 'foo'));
  324. $this->assertFalse(Arr::has(null, null));
  325. $this->assertFalse(Arr::has([], null));
  326. $array = ['products' => ['desk' => ['price' => 100]]];
  327. $this->assertTrue(Arr::has($array, ['products.desk']));
  328. $this->assertTrue(Arr::has($array, ['products.desk', 'products.desk.price']));
  329. $this->assertTrue(Arr::has($array, ['products', 'products']));
  330. $this->assertFalse(Arr::has($array, ['foo']));
  331. $this->assertFalse(Arr::has($array, []));
  332. $this->assertFalse(Arr::has($array, ['products.desk', 'products.price']));
  333. $array = [
  334. 'products' => [
  335. ['name' => 'desk'],
  336. ],
  337. ];
  338. $this->assertTrue(Arr::has($array, 'products.0.name'));
  339. $this->assertFalse(Arr::has($array, 'products.0.price'));
  340. $this->assertFalse(Arr::has([], [null]));
  341. $this->assertFalse(Arr::has(null, [null]));
  342. $this->assertTrue(Arr::has(['' => 'some'], ''));
  343. $this->assertTrue(Arr::has(['' => 'some'], ['']));
  344. $this->assertFalse(Arr::has([''], ''));
  345. $this->assertFalse(Arr::has([], ''));
  346. $this->assertFalse(Arr::has([], ['']));
  347. }
  348. public function testHasAnyMethod()
  349. {
  350. $array = ['name' => 'Taylor', 'age' => '', 'city' => null];
  351. $this->assertTrue(Arr::hasAny($array, 'name'));
  352. $this->assertTrue(Arr::hasAny($array, 'age'));
  353. $this->assertTrue(Arr::hasAny($array, 'city'));
  354. $this->assertFalse(Arr::hasAny($array, 'foo'));
  355. $this->assertTrue(Arr::hasAny($array, 'name', 'email'));
  356. $this->assertTrue(Arr::hasAny($array, ['name', 'email']));
  357. $array = ['name' => 'Taylor', 'email' => 'foo'];
  358. $this->assertTrue(Arr::hasAny($array, 'name', 'email'));
  359. $this->assertFalse(Arr::hasAny($array, 'surname', 'password'));
  360. $this->assertFalse(Arr::hasAny($array, ['surname', 'password']));
  361. $array = ['foo' => ['bar' => null, 'baz' => '']];
  362. $this->assertTrue(Arr::hasAny($array, 'foo.bar'));
  363. $this->assertTrue(Arr::hasAny($array, 'foo.baz'));
  364. $this->assertFalse(Arr::hasAny($array, 'foo.bax'));
  365. $this->assertTrue(Arr::hasAny($array, ['foo.bax', 'foo.baz']));
  366. }
  367. public function testIsAssoc()
  368. {
  369. $this->assertTrue(Arr::isAssoc(['a' => 'a', 0 => 'b']));
  370. $this->assertTrue(Arr::isAssoc([1 => 'a', 0 => 'b']));
  371. $this->assertTrue(Arr::isAssoc([1 => 'a', 2 => 'b']));
  372. $this->assertFalse(Arr::isAssoc([0 => 'a', 1 => 'b']));
  373. $this->assertFalse(Arr::isAssoc(['a', 'b']));
  374. }
  375. public function testIsList()
  376. {
  377. $this->assertTrue(Arr::isList([]));
  378. $this->assertTrue(Arr::isList([1, 2, 3]));
  379. $this->assertTrue(Arr::isList(['foo', 2, 3]));
  380. $this->assertTrue(Arr::isList(['foo', 'bar']));
  381. $this->assertTrue(Arr::isList([0 => 'foo', 'bar']));
  382. $this->assertTrue(Arr::isList([0 => 'foo', 1 => 'bar']));
  383. $this->assertFalse(Arr::isList([1 => 'foo', 'bar']));
  384. $this->assertFalse(Arr::isList([1 => 'foo', 0 => 'bar']));
  385. $this->assertFalse(Arr::isList([0 => 'foo', 'bar' => 'baz']));
  386. $this->assertFalse(Arr::isList([0 => 'foo', 2 => 'bar']));
  387. $this->assertFalse(Arr::isList(['foo' => 'bar', 'baz' => 'qux']));
  388. }
  389. public function testOnly()
  390. {
  391. $array = ['name' => 'Desk', 'price' => 100, 'orders' => 10];
  392. $array = Arr::only($array, ['name', 'price']);
  393. $this->assertEquals(['name' => 'Desk', 'price' => 100], $array);
  394. $this->assertEmpty(Arr::only($array, ['nonExistingKey']));
  395. }
  396. public function testPluck()
  397. {
  398. $data = [
  399. 'post-1' => [
  400. 'comments' => [
  401. 'tags' => [
  402. '#foo', '#bar',
  403. ],
  404. ],
  405. ],
  406. 'post-2' => [
  407. 'comments' => [
  408. 'tags' => [
  409. '#baz',
  410. ],
  411. ],
  412. ],
  413. ];
  414. $this->assertEquals([
  415. 0 => [
  416. 'tags' => [
  417. '#foo', '#bar',
  418. ],
  419. ],
  420. 1 => [
  421. 'tags' => [
  422. '#baz',
  423. ],
  424. ],
  425. ], Arr::pluck($data, 'comments'));
  426. $this->assertEquals([['#foo', '#bar'], ['#baz']], Arr::pluck($data, 'comments.tags'));
  427. $this->assertEquals([null, null], Arr::pluck($data, 'foo'));
  428. $this->assertEquals([null, null], Arr::pluck($data, 'foo.bar'));
  429. $array = [
  430. ['developer' => ['name' => 'Taylor']],
  431. ['developer' => ['name' => 'Abigail']],
  432. ];
  433. $array = Arr::pluck($array, 'developer.name');
  434. $this->assertEquals(['Taylor', 'Abigail'], $array);
  435. }
  436. public function testPluckWithArrayValue()
  437. {
  438. $array = [
  439. ['developer' => ['name' => 'Taylor']],
  440. ['developer' => ['name' => 'Abigail']],
  441. ];
  442. $array = Arr::pluck($array, ['developer', 'name']);
  443. $this->assertEquals(['Taylor', 'Abigail'], $array);
  444. }
  445. public function testPluckWithKeys()
  446. {
  447. $array = [
  448. ['name' => 'Taylor', 'role' => 'developer'],
  449. ['name' => 'Abigail', 'role' => 'developer'],
  450. ];
  451. $test1 = Arr::pluck($array, 'role', 'name');
  452. $test2 = Arr::pluck($array, null, 'name');
  453. $this->assertEquals([
  454. 'Taylor' => 'developer',
  455. 'Abigail' => 'developer',
  456. ], $test1);
  457. $this->assertEquals([
  458. 'Taylor' => ['name' => 'Taylor', 'role' => 'developer'],
  459. 'Abigail' => ['name' => 'Abigail', 'role' => 'developer'],
  460. ], $test2);
  461. }
  462. public function testPluckWithCarbonKeys()
  463. {
  464. $array = [
  465. ['start' => new Carbon('2017-07-25 00:00:00'), 'end' => new Carbon('2017-07-30 00:00:00')],
  466. ];
  467. $array = Arr::pluck($array, 'end', 'start');
  468. $this->assertEquals(['2017-07-25 00:00:00' => '2017-07-30 00:00:00'], $array);
  469. }
  470. public function testArrayPluckWithArrayAndObjectValues()
  471. {
  472. $array = [(object) ['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']];
  473. $this->assertEquals(['taylor', 'dayle'], Arr::pluck($array, 'name'));
  474. $this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], Arr::pluck($array, 'email', 'name'));
  475. }
  476. public function testArrayPluckWithNestedKeys()
  477. {
  478. $array = [['user' => ['taylor', 'otwell']], ['user' => ['dayle', 'rees']]];
  479. $this->assertEquals(['taylor', 'dayle'], Arr::pluck($array, 'user.0'));
  480. $this->assertEquals(['taylor', 'dayle'], Arr::pluck($array, ['user', 0]));
  481. $this->assertEquals(['taylor' => 'otwell', 'dayle' => 'rees'], Arr::pluck($array, 'user.1', 'user.0'));
  482. $this->assertEquals(['taylor' => 'otwell', 'dayle' => 'rees'], Arr::pluck($array, ['user', 1], ['user', 0]));
  483. }
  484. public function testArrayPluckWithNestedArrays()
  485. {
  486. $array = [
  487. [
  488. 'account' => 'a',
  489. 'users' => [
  490. ['first' => 'taylor', 'last' => 'otwell', 'email' => 'taylorotwell@gmail.com'],
  491. ],
  492. ],
  493. [
  494. 'account' => 'b',
  495. 'users' => [
  496. ['first' => 'abigail', 'last' => 'otwell'],
  497. ['first' => 'dayle', 'last' => 'rees'],
  498. ],
  499. ],
  500. ];
  501. $this->assertEquals([['taylor'], ['abigail', 'dayle']], Arr::pluck($array, 'users.*.first'));
  502. $this->assertEquals(['a' => ['taylor'], 'b' => ['abigail', 'dayle']], Arr::pluck($array, 'users.*.first', 'account'));
  503. $this->assertEquals([['taylorotwell@gmail.com'], [null, null]], Arr::pluck($array, 'users.*.email'));
  504. }
  505. public function testPrepend()
  506. {
  507. $array = Arr::prepend(['one', 'two', 'three', 'four'], 'zero');
  508. $this->assertEquals(['zero', 'one', 'two', 'three', 'four'], $array);
  509. $array = Arr::prepend(['one' => 1, 'two' => 2], 0, 'zero');
  510. $this->assertEquals(['zero' => 0, 'one' => 1, 'two' => 2], $array);
  511. $array = Arr::prepend(['one' => 1, 'two' => 2], 0, null);
  512. $this->assertEquals([null => 0, 'one' => 1, 'two' => 2], $array);
  513. }
  514. public function testPull()
  515. {
  516. $array = ['name' => 'Desk', 'price' => 100];
  517. $name = Arr::pull($array, 'name');
  518. $this->assertSame('Desk', $name);
  519. $this->assertSame(['price' => 100], $array);
  520. // Only works on first level keys
  521. $array = ['joe@example.com' => 'Joe', 'jane@localhost' => 'Jane'];
  522. $name = Arr::pull($array, 'joe@example.com');
  523. $this->assertSame('Joe', $name);
  524. $this->assertSame(['jane@localhost' => 'Jane'], $array);
  525. // Does not work for nested keys
  526. $array = ['emails' => ['joe@example.com' => 'Joe', 'jane@localhost' => 'Jane']];
  527. $name = Arr::pull($array, 'emails.joe@example.com');
  528. $this->assertNull($name);
  529. $this->assertSame(['emails' => ['joe@example.com' => 'Joe', 'jane@localhost' => 'Jane']], $array);
  530. // Works with int keys
  531. $array = ['First', 'Second'];
  532. $first = Arr::pull($array, 0);
  533. $this->assertSame('First', $first);
  534. $this->assertSame([1 => 'Second'], $array);
  535. }
  536. public function testQuery()
  537. {
  538. $this->assertSame('', Arr::query([]));
  539. $this->assertSame('foo=bar', Arr::query(['foo' => 'bar']));
  540. $this->assertSame('foo=bar&bar=baz', Arr::query(['foo' => 'bar', 'bar' => 'baz']));
  541. $this->assertSame('foo=bar&bar=1', Arr::query(['foo' => 'bar', 'bar' => true]));
  542. $this->assertSame('foo=bar', Arr::query(['foo' => 'bar', 'bar' => null]));
  543. $this->assertSame('foo=bar&bar=', Arr::query(['foo' => 'bar', 'bar' => '']));
  544. }
  545. public function testRandom()
  546. {
  547. $random = Arr::random(['foo', 'bar', 'baz']);
  548. $this->assertContains($random, ['foo', 'bar', 'baz']);
  549. $random = Arr::random(['foo', 'bar', 'baz'], 0);
  550. $this->assertIsArray($random);
  551. $this->assertCount(0, $random);
  552. $random = Arr::random(['foo', 'bar', 'baz'], 1);
  553. $this->assertIsArray($random);
  554. $this->assertCount(1, $random);
  555. $this->assertContains($random[0], ['foo', 'bar', 'baz']);
  556. $random = Arr::random(['foo', 'bar', 'baz'], 2);
  557. $this->assertIsArray($random);
  558. $this->assertCount(2, $random);
  559. $this->assertContains($random[0], ['foo', 'bar', 'baz']);
  560. $this->assertContains($random[1], ['foo', 'bar', 'baz']);
  561. $random = Arr::random(['foo', 'bar', 'baz'], '0');
  562. $this->assertIsArray($random);
  563. $this->assertCount(0, $random);
  564. $random = Arr::random(['foo', 'bar', 'baz'], '1');
  565. $this->assertIsArray($random);
  566. $this->assertCount(1, $random);
  567. $this->assertContains($random[0], ['foo', 'bar', 'baz']);
  568. $random = Arr::random(['foo', 'bar', 'baz'], '2');
  569. $this->assertIsArray($random);
  570. $this->assertCount(2, $random);
  571. $this->assertContains($random[0], ['foo', 'bar', 'baz']);
  572. $this->assertContains($random[1], ['foo', 'bar', 'baz']);
  573. // preserve keys
  574. $random = Arr::random(['one' => 'foo', 'two' => 'bar', 'three' => 'baz'], 2, true);
  575. $this->assertIsArray($random);
  576. $this->assertCount(2, $random);
  577. $this->assertCount(2, array_intersect_assoc(['one' => 'foo', 'two' => 'bar', 'three' => 'baz'], $random));
  578. }
  579. public function testRandomOnEmptyArray()
  580. {
  581. $random = Arr::random([], 0);
  582. $this->assertIsArray($random);
  583. $this->assertCount(0, $random);
  584. $random = Arr::random([], '0');
  585. $this->assertIsArray($random);
  586. $this->assertCount(0, $random);
  587. }
  588. public function testRandomThrowsAnErrorWhenRequestingMoreItemsThanAreAvailable()
  589. {
  590. $exceptions = 0;
  591. try {
  592. Arr::random([]);
  593. } catch (InvalidArgumentException $e) {
  594. $exceptions++;
  595. }
  596. try {
  597. Arr::random([], 1);
  598. } catch (InvalidArgumentException $e) {
  599. $exceptions++;
  600. }
  601. try {
  602. Arr::random([], 2);
  603. } catch (InvalidArgumentException $e) {
  604. $exceptions++;
  605. }
  606. $this->assertSame(3, $exceptions);
  607. }
  608. public function testSet()
  609. {
  610. $array = ['products' => ['desk' => ['price' => 100]]];
  611. Arr::set($array, 'products.desk.price', 200);
  612. $this->assertEquals(['products' => ['desk' => ['price' => 200]]], $array);
  613. // No key is given
  614. $array = ['products' => ['desk' => ['price' => 100]]];
  615. Arr::set($array, null, ['price' => 300]);
  616. $this->assertSame(['price' => 300], $array);
  617. // The key doesn't exist at the depth
  618. $array = ['products' => 'desk'];
  619. Arr::set($array, 'products.desk.price', 200);
  620. $this->assertSame(['products' => ['desk' => ['price' => 200]]], $array);
  621. // No corresponding key exists
  622. $array = ['products'];
  623. Arr::set($array, 'products.desk.price', 200);
  624. $this->assertSame(['products', 'products' => ['desk' => ['price' => 200]]], $array);
  625. $array = ['products' => ['desk' => ['price' => 100]]];
  626. Arr::set($array, 'table', 500);
  627. $this->assertSame(['products' => ['desk' => ['price' => 100]], 'table' => 500], $array);
  628. $array = ['products' => ['desk' => ['price' => 100]]];
  629. Arr::set($array, 'table.price', 350);
  630. $this->assertSame(['products' => ['desk' => ['price' => 100]], 'table' => ['price' => 350]], $array);
  631. $array = [];
  632. Arr::set($array, 'products.desk.price', 200);
  633. $this->assertSame(['products' => ['desk' => ['price' => 200]]], $array);
  634. // Override
  635. $array = ['products' => 'table'];
  636. Arr::set($array, 'products.desk.price', 300);
  637. $this->assertSame(['products' => ['desk' => ['price' => 300]]], $array);
  638. }
  639. public function testShuffleWithSeed()
  640. {
  641. $this->assertEquals(
  642. Arr::shuffle(range(0, 100, 10), 1234),
  643. Arr::shuffle(range(0, 100, 10), 1234)
  644. );
  645. }
  646. public function testSort()
  647. {
  648. $unsorted = [
  649. ['name' => 'Desk'],
  650. ['name' => 'Chair'],
  651. ];
  652. $expected = [
  653. ['name' => 'Chair'],
  654. ['name' => 'Desk'],
  655. ];
  656. $sorted = array_values(Arr::sort($unsorted));
  657. $this->assertEquals($expected, $sorted);
  658. // sort with closure
  659. $sortedWithClosure = array_values(Arr::sort($unsorted, function ($value) {
  660. return $value['name'];
  661. }));
  662. $this->assertEquals($expected, $sortedWithClosure);
  663. // sort with dot notation
  664. $sortedWithDotNotation = array_values(Arr::sort($unsorted, 'name'));
  665. $this->assertEquals($expected, $sortedWithDotNotation);
  666. }
  667. public function testSortRecursive()
  668. {
  669. $array = [
  670. 'users' => [
  671. [
  672. // should sort associative arrays by keys
  673. 'name' => 'joe',
  674. 'mail' => 'joe@example.com',
  675. // should sort deeply nested arrays
  676. 'numbers' => [2, 1, 0],
  677. ],
  678. [
  679. 'name' => 'jane',
  680. 'age' => 25,
  681. ],
  682. ],
  683. 'repositories' => [
  684. // should use weird `sort()` behavior on arrays of arrays
  685. ['id' => 1],
  686. ['id' => 0],
  687. ],
  688. // should sort non-associative arrays by value
  689. 20 => [2, 1, 0],
  690. 30 => [
  691. // should sort non-incrementing numerical keys by keys
  692. 2 => 'a',
  693. 1 => 'b',
  694. 0 => 'c',
  695. ],
  696. ];
  697. $expect = [
  698. 20 => [0, 1, 2],
  699. 30 => [
  700. 0 => 'c',
  701. 1 => 'b',
  702. 2 => 'a',
  703. ],
  704. 'repositories' => [
  705. ['id' => 0],
  706. ['id' => 1],
  707. ],
  708. 'users' => [
  709. [
  710. 'age' => 25,
  711. 'name' => 'jane',
  712. ],
  713. [
  714. 'mail' => 'joe@example.com',
  715. 'name' => 'joe',
  716. 'numbers' => [0, 1, 2],
  717. ],
  718. ],
  719. ];
  720. $this->assertEquals($expect, Arr::sortRecursive($array));
  721. }
  722. public function testToCssClasses()
  723. {
  724. $classes = Arr::toCssClasses([
  725. 'font-bold',
  726. 'mt-4',
  727. ]);
  728. $this->assertEquals('font-bold mt-4', $classes);
  729. $classes = Arr::toCssClasses([
  730. 'font-bold',
  731. 'mt-4',
  732. 'ml-2' => true,
  733. 'mr-2' => false,
  734. ]);
  735. $this->assertEquals('font-bold mt-4 ml-2', $classes);
  736. }
  737. public function testWhere()
  738. {
  739. $array = [100, '200', 300, '400', 500];
  740. $array = Arr::where($array, function ($value, $key) {
  741. return is_string($value);
  742. });
  743. $this->assertEquals([1 => '200', 3 => '400'], $array);
  744. }
  745. public function testWhereKey()
  746. {
  747. $array = ['10' => 1, 'foo' => 3, 20 => 2];
  748. $array = Arr::where($array, function ($value, $key) {
  749. return is_numeric($key);
  750. });
  751. $this->assertEquals(['10' => 1, 20 => 2], $array);
  752. }
  753. public function testForget()
  754. {
  755. $array = ['products' => ['desk' => ['price' => 100]]];
  756. Arr::forget($array, null);
  757. $this->assertEquals(['products' => ['desk' => ['price' => 100]]], $array);
  758. $array = ['products' => ['desk' => ['price' => 100]]];
  759. Arr::forget($array, []);
  760. $this->assertEquals(['products' => ['desk' => ['price' => 100]]], $array);
  761. $array = ['products' => ['desk' => ['price' => 100]]];
  762. Arr::forget($array, 'products.desk');
  763. $this->assertEquals(['products' => []], $array);
  764. $array = ['products' => ['desk' => ['price' => 100]]];
  765. Arr::forget($array, 'products.desk.price');
  766. $this->assertEquals(['products' => ['desk' => []]], $array);
  767. $array = ['products' => ['desk' => ['price' => 100]]];
  768. Arr::forget($array, 'products.final.price');
  769. $this->assertEquals(['products' => ['desk' => ['price' => 100]]], $array);
  770. $array = ['shop' => ['cart' => [150 => 0]]];
  771. Arr::forget($array, 'shop.final.cart');
  772. $this->assertEquals(['shop' => ['cart' => [150 => 0]]], $array);
  773. $array = ['products' => ['desk' => ['price' => ['original' => 50, 'taxes' => 60]]]];
  774. Arr::forget($array, 'products.desk.price.taxes');
  775. $this->assertEquals(['products' => ['desk' => ['price' => ['original' => 50]]]], $array);
  776. $array = ['products' => ['desk' => ['price' => ['original' => 50, 'taxes' => 60]]]];
  777. Arr::forget($array, 'products.desk.final.taxes');
  778. $this->assertEquals(['products' => ['desk' => ['price' => ['original' => 50, 'taxes' => 60]]]], $array);
  779. $array = ['products' => ['desk' => ['price' => 50], null => 'something']];
  780. Arr::forget($array, ['products.amount.all', 'products.desk.price']);
  781. $this->assertEquals(['products' => ['desk' => [], null => 'something']], $array);
  782. // Only works on first level keys
  783. $array = ['joe@example.com' => 'Joe', 'jane@example.com' => 'Jane'];
  784. Arr::forget($array, 'joe@example.com');
  785. $this->assertEquals(['jane@example.com' => 'Jane'], $array);
  786. // Does not work for nested keys
  787. $array = ['emails' => ['joe@example.com' => ['name' => 'Joe'], 'jane@localhost' => ['name' => 'Jane']]];
  788. Arr::forget($array, ['emails.joe@example.com', 'emails.jane@localhost']);
  789. $this->assertEquals(['emails' => ['joe@example.com' => ['name' => 'Joe']]], $array);
  790. }
  791. public function testWrap()
  792. {
  793. $string = 'a';
  794. $array = ['a'];
  795. $object = new stdClass;
  796. $object->value = 'a';
  797. $this->assertEquals(['a'], Arr::wrap($string));
  798. $this->assertEquals($array, Arr::wrap($array));
  799. $this->assertEquals([$object], Arr::wrap($object));
  800. $this->assertEquals([], Arr::wrap(null));
  801. $this->assertEquals([null], Arr::wrap([null]));
  802. $this->assertEquals([null, null], Arr::wrap([null, null]));
  803. $this->assertEquals([''], Arr::wrap(''));
  804. $this->assertEquals([''], Arr::wrap(['']));
  805. $this->assertEquals([false], Arr::wrap(false));
  806. $this->assertEquals([false], Arr::wrap([false]));
  807. $this->assertEquals([0], Arr::wrap(0));
  808. $obj = new stdClass;
  809. $obj->value = 'a';
  810. $obj = unserialize(serialize($obj));
  811. $this->assertEquals([$obj], Arr::wrap($obj));
  812. $this->assertSame($obj, Arr::wrap($obj)[0]);
  813. }
  814. public function testSortByMany()
  815. {
  816. $unsorted = [
  817. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
  818. ['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
  819. ['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
  820. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
  821. ];
  822. // sort using keys
  823. $sorted = array_values(Arr::sort($unsorted, [
  824. 'name',
  825. 'age',
  826. 'meta.key',
  827. ]));
  828. $this->assertEquals([
  829. ['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
  830. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
  831. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
  832. ['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
  833. ], $sorted);
  834. // sort with order
  835. $sortedWithOrder = array_values(Arr::sort($unsorted, [
  836. 'name',
  837. ['age', false],
  838. ['meta.key', true],
  839. ]));
  840. $this->assertEquals([
  841. ['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
  842. ['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
  843. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
  844. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
  845. ], $sortedWithOrder);
  846. // sort using callable
  847. $sortedWithCallable = array_values(Arr::sort($unsorted, [
  848. function ($a, $b) {
  849. return $a['name'] <=> $b['name'];
  850. },
  851. function ($a, $b) {
  852. return $b['age'] <=> $a['age'];
  853. },
  854. ['meta.key', true],
  855. ]));
  856. $this->assertEquals([
  857. ['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
  858. ['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
  859. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
  860. ['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
  861. ], $sortedWithCallable);
  862. }
  863. }