ArrTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <?php
  2. namespace Tests;
  3. use stdClass;
  4. use think\Collection;
  5. use think\helper\Arr;
  6. class ArrTest extends TestCase
  7. {
  8. public function testAdd()
  9. {
  10. $array = Arr::add(['name' => 'ThinkPHP'], 'price', 100);
  11. $this->assertSame(['name' => 'ThinkPHP', 'price' => 100], $array);
  12. }
  13. public function testCrossJoin()
  14. {
  15. // Single dimension
  16. $this->assertSame(
  17. [[1, 'a'], [1, 'b'], [1, 'c']],
  18. Arr::crossJoin([1], ['a', 'b', 'c'])
  19. );
  20. // Square matrix
  21. $this->assertSame(
  22. [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']],
  23. Arr::crossJoin([1, 2], ['a', 'b'])
  24. );
  25. // Rectangular matrix
  26. $this->assertSame(
  27. [[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']],
  28. Arr::crossJoin([1, 2], ['a', 'b', 'c'])
  29. );
  30. // 3D matrix
  31. $this->assertSame(
  32. [
  33. [1, 'a', 'I'], [1, 'a', 'II'], [1, 'a', 'III'],
  34. [1, 'b', 'I'], [1, 'b', 'II'], [1, 'b', 'III'],
  35. [2, 'a', 'I'], [2, 'a', 'II'], [2, 'a', 'III'],
  36. [2, 'b', 'I'], [2, 'b', 'II'], [2, 'b', 'III'],
  37. ],
  38. Arr::crossJoin([1, 2], ['a', 'b'], ['I', 'II', 'III'])
  39. );
  40. // With 1 empty dimension
  41. $this->assertSame([], Arr::crossJoin([], ['a', 'b'], ['I', 'II', 'III']));
  42. $this->assertSame([], Arr::crossJoin([1, 2], [], ['I', 'II', 'III']));
  43. $this->assertSame([], Arr::crossJoin([1, 2], ['a', 'b'], []));
  44. // With empty arrays
  45. $this->assertSame([], Arr::crossJoin([], [], []));
  46. $this->assertSame([], Arr::crossJoin([], []));
  47. $this->assertSame([], Arr::crossJoin([]));
  48. // Not really a proper usage, still, test for preserving BC
  49. $this->assertSame([[]], Arr::crossJoin());
  50. }
  51. public function testDivide()
  52. {
  53. list($keys, $values) = Arr::divide(['name' => 'ThinkPHP']);
  54. $this->assertSame(['name'], $keys);
  55. $this->assertSame(['ThinkPHP'], $values);
  56. }
  57. public function testDot()
  58. {
  59. $array = Arr::dot(['foo' => ['bar' => 'baz']]);
  60. $this->assertSame(['foo.bar' => 'baz'], $array);
  61. $array = Arr::dot([]);
  62. $this->assertSame([], $array);
  63. $array = Arr::dot(['foo' => []]);
  64. $this->assertSame(['foo' => []], $array);
  65. $array = Arr::dot(['foo' => ['bar' => []]]);
  66. $this->assertSame(['foo.bar' => []], $array);
  67. }
  68. public function testExcept()
  69. {
  70. $array = ['name' => 'ThinkPHP', 'price' => 100];
  71. $array = Arr::except($array, ['price']);
  72. $this->assertSame(['name' => 'ThinkPHP'], $array);
  73. }
  74. public function testExists()
  75. {
  76. $this->assertTrue(Arr::exists([1], 0));
  77. $this->assertTrue(Arr::exists([null], 0));
  78. $this->assertTrue(Arr::exists(['a' => 1], 'a'));
  79. $this->assertTrue(Arr::exists(['a' => null], 'a'));
  80. $this->assertFalse(Arr::exists([1], 1));
  81. $this->assertFalse(Arr::exists([null], 1));
  82. $this->assertFalse(Arr::exists(['a' => 1], 0));
  83. }
  84. public function testFirst()
  85. {
  86. $array = [100, 200, 300];
  87. $value = Arr::first($array, function ($value) {
  88. return $value >= 150;
  89. });
  90. $this->assertSame(200, $value);
  91. $this->assertSame(100, Arr::first($array));
  92. $this->assertSame('default', Arr::first([], null, 'default'));
  93. $this->assertSame('default', Arr::first([], function () {
  94. return false;
  95. }, 'default'));
  96. }
  97. public function testLast()
  98. {
  99. $array = [100, 200, 300];
  100. $last = Arr::last($array, function ($value) {
  101. return $value < 250;
  102. });
  103. $this->assertSame(200, $last);
  104. $last = Arr::last($array, function ($value, $key) {
  105. return $key < 2;
  106. });
  107. $this->assertSame(200, $last);
  108. $this->assertSame(300, Arr::last($array));
  109. }
  110. public function testFlatten()
  111. {
  112. // Flat arrays are unaffected
  113. $array = ['#foo', '#bar', '#baz'];
  114. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten(['#foo', '#bar', '#baz']));
  115. // Nested arrays are flattened with existing flat items
  116. $array = [['#foo', '#bar'], '#baz'];
  117. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
  118. // Flattened array includes "null" items
  119. $array = [['#foo', null], '#baz', null];
  120. $this->assertSame(['#foo', null, '#baz', null], Arr::flatten($array));
  121. // Sets of nested arrays are flattened
  122. $array = [['#foo', '#bar'], ['#baz']];
  123. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
  124. // Deeply nested arrays are flattened
  125. $array = [['#foo', ['#bar']], ['#baz']];
  126. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
  127. // Nested arrays are flattened alongside arrays
  128. $array = [new Collection(['#foo', '#bar']), ['#baz']];
  129. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
  130. // Nested arrays containing plain arrays are flattened
  131. $array = [new Collection(['#foo', ['#bar']]), ['#baz']];
  132. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
  133. // Nested arrays containing arrays are flattened
  134. $array = [['#foo', new Collection(['#bar'])], ['#baz']];
  135. $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
  136. // Nested arrays containing arrays containing arrays are flattened
  137. $array = [['#foo', new Collection(['#bar', ['#zap']])], ['#baz']];
  138. $this->assertSame(['#foo', '#bar', '#zap', '#baz'], Arr::flatten($array));
  139. }
  140. public function testFlattenWithDepth()
  141. {
  142. // No depth flattens recursively
  143. $array = [['#foo', ['#bar', ['#baz']]], '#zap'];
  144. $this->assertSame(['#foo', '#bar', '#baz', '#zap'], Arr::flatten($array));
  145. // Specifying a depth only flattens to that depth
  146. $array = [['#foo', ['#bar', ['#baz']]], '#zap'];
  147. $this->assertSame(['#foo', ['#bar', ['#baz']], '#zap'], Arr::flatten($array, 1));
  148. $array = [['#foo', ['#bar', ['#baz']]], '#zap'];
  149. $this->assertSame(['#foo', '#bar', ['#baz'], '#zap'], Arr::flatten($array, 2));
  150. }
  151. public function testGet()
  152. {
  153. $array = ['products.item' => ['price' => 100]];
  154. $this->assertSame(['price' => 100], Arr::get($array, 'products.item'));
  155. $array = ['products' => ['item' => ['price' => 100]]];
  156. $value = Arr::get($array, 'products.item');
  157. $this->assertSame(['price' => 100], $value);
  158. // Test null array values
  159. $array = ['foo' => null, 'bar' => ['baz' => null]];
  160. $this->assertNull(Arr::get($array, 'foo', 'default'));
  161. $this->assertNull(Arr::get($array, 'bar.baz', 'default'));
  162. // Test null key returns the whole array
  163. $array = ['foo', 'bar'];
  164. $this->assertSame($array, Arr::get($array, null));
  165. // Test $array is empty and key is null
  166. $this->assertSame([], Arr::get([], null));
  167. $this->assertSame([], Arr::get([], null, 'default'));
  168. }
  169. public function testHas()
  170. {
  171. $array = ['products.item' => ['price' => 100]];
  172. $this->assertTrue(Arr::has($array, 'products.item'));
  173. $array = ['products' => ['item' => ['price' => 100]]];
  174. $this->assertTrue(Arr::has($array, 'products.item'));
  175. $this->assertTrue(Arr::has($array, 'products.item.price'));
  176. $this->assertFalse(Arr::has($array, 'products.foo'));
  177. $this->assertFalse(Arr::has($array, 'products.item.foo'));
  178. $array = ['foo' => null, 'bar' => ['baz' => null]];
  179. $this->assertTrue(Arr::has($array, 'foo'));
  180. $this->assertTrue(Arr::has($array, 'bar.baz'));
  181. $array = ['foo', 'bar'];
  182. $this->assertFalse(Arr::has($array, null));
  183. $this->assertFalse(Arr::has([], null));
  184. $array = ['products' => ['item' => ['price' => 100]]];
  185. $this->assertTrue(Arr::has($array, ['products.item']));
  186. $this->assertTrue(Arr::has($array, ['products.item', 'products.item.price']));
  187. $this->assertTrue(Arr::has($array, ['products', 'products']));
  188. $this->assertFalse(Arr::has($array, ['foo']));
  189. $this->assertFalse(Arr::has($array, []));
  190. $this->assertFalse(Arr::has($array, ['products.item', 'products.price']));
  191. $this->assertFalse(Arr::has([], [null]));
  192. }
  193. public function testIsAssoc()
  194. {
  195. $this->assertTrue(Arr::isAssoc(['a' => 'a', 0 => 'b']));
  196. $this->assertTrue(Arr::isAssoc([1 => 'a', 0 => 'b']));
  197. $this->assertTrue(Arr::isAssoc([1 => 'a', 2 => 'b']));
  198. $this->assertFalse(Arr::isAssoc([0 => 'a', 1 => 'b']));
  199. $this->assertFalse(Arr::isAssoc(['a', 'b']));
  200. }
  201. public function testOnly()
  202. {
  203. $array = ['name' => 'ThinkPHP', 'price' => 100, 'orders' => 10];
  204. $array = Arr::only($array, ['name', 'price']);
  205. $this->assertSame(['name' => 'ThinkPHP', 'price' => 100], $array);
  206. }
  207. public function testPrepend()
  208. {
  209. $array = Arr::prepend(['one', 'two', 'three', 'four'], 'zero');
  210. $this->assertSame(['zero', 'one', 'two', 'three', 'four'], $array);
  211. $array = Arr::prepend(['one' => 1, 'two' => 2], 0, 'zero');
  212. $this->assertSame(['zero' => 0, 'one' => 1, 'two' => 2], $array);
  213. }
  214. public function testPull()
  215. {
  216. $array = ['name' => 'ThinkPHP', 'price' => 100];
  217. $name = Arr::pull($array, 'name');
  218. $this->assertSame('ThinkPHP', $name);
  219. $this->assertSame(['price' => 100], $array);
  220. // Only works on first level keys
  221. $array = ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane'];
  222. $name = Arr::pull($array, 'i@example.com');
  223. $this->assertSame('Joe', $name);
  224. $this->assertSame(['jack@localhost' => 'Jane'], $array);
  225. // Does not work for nested keys
  226. $array = ['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']];
  227. $name = Arr::pull($array, 'emails.i@example.com');
  228. $this->assertNull($name);
  229. $this->assertSame(['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']], $array);
  230. }
  231. public function testRandom()
  232. {
  233. $randomValue = Arr::random(['foo', 'bar', 'baz']);
  234. $this->assertContains($randomValue, ['foo', 'bar', 'baz']);
  235. $randomValues = Arr::random(['foo', 'bar', 'baz'], 1);
  236. $this->assertIsArray($randomValues);
  237. $this->assertCount(1, $randomValues);
  238. $this->assertContains($randomValues[0], ['foo', 'bar', 'baz']);
  239. $randomValues = Arr::random(['foo', 'bar', 'baz'], 2);
  240. $this->assertIsArray($randomValues);
  241. $this->assertCount(2, $randomValues);
  242. $this->assertContains($randomValues[0], ['foo', 'bar', 'baz']);
  243. $this->assertContains($randomValues[1], ['foo', 'bar', 'baz']);
  244. }
  245. public function testSet()
  246. {
  247. $array = ['products' => ['item' => ['price' => 100]]];
  248. Arr::set($array, 'products.item.price', 200);
  249. Arr::set($array, 'goods.item.price', 200);
  250. $this->assertSame(['products' => ['item' => ['price' => 200]], 'goods' => ['item' => ['price' => 200]]], $array);
  251. }
  252. public function testWhere()
  253. {
  254. $array = [100, '200', 300, '400', 500];
  255. $array = Arr::where($array, function ($value, $key) {
  256. return is_string($value);
  257. });
  258. $this->assertSame([1 => '200', 3 => '400'], $array);
  259. }
  260. public function testWhereKey()
  261. {
  262. $array = ['10' => 1, 'foo' => 3, 20 => 2];
  263. $array = Arr::where($array, function ($value, $key) {
  264. return is_numeric($key);
  265. });
  266. $this->assertSame(['10' => 1, 20 => 2], $array);
  267. }
  268. public function testForget()
  269. {
  270. $array = ['products' => ['item' => ['price' => 100]]];
  271. Arr::forget($array, null);
  272. $this->assertSame(['products' => ['item' => ['price' => 100]]], $array);
  273. $array = ['products' => ['item' => ['price' => 100]]];
  274. Arr::forget($array, []);
  275. $this->assertSame(['products' => ['item' => ['price' => 100]]], $array);
  276. $array = ['products' => ['item' => ['price' => 100]]];
  277. Arr::forget($array, 'products.item');
  278. $this->assertSame(['products' => []], $array);
  279. $array = ['products' => ['item' => ['price' => 100]]];
  280. Arr::forget($array, 'products.item.price');
  281. $this->assertSame(['products' => ['item' => []]], $array);
  282. $array = ['products' => ['item' => ['price' => 100]]];
  283. Arr::forget($array, 'products.final.price');
  284. $this->assertSame(['products' => ['item' => ['price' => 100]]], $array);
  285. $array = ['shop' => ['cart' => [150 => 0]]];
  286. Arr::forget($array, 'shop.final.cart');
  287. $this->assertSame(['shop' => ['cart' => [150 => 0]]], $array);
  288. $array = ['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]];
  289. Arr::forget($array, 'products.item.price.taxes');
  290. $this->assertSame(['products' => ['item' => ['price' => ['original' => 50]]]], $array);
  291. $array = ['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]];
  292. Arr::forget($array, 'products.item.final.taxes');
  293. $this->assertSame(['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]], $array);
  294. $array = ['products' => ['item' => ['price' => 50], null => 'something']];
  295. Arr::forget($array, ['products.amount.all', 'products.item.price']);
  296. $this->assertSame(['products' => ['item' => [], null => 'something']], $array);
  297. // Only works on first level keys
  298. $array = ['i@example.com' => 'Joe', 'i@thinkphp.com' => 'Jane'];
  299. Arr::forget($array, 'i@example.com');
  300. $this->assertSame(['i@thinkphp.com' => 'Jane'], $array);
  301. // Does not work for nested keys
  302. $array = ['emails' => ['i@example.com' => ['name' => 'Joe'], 'jack@localhost' => ['name' => 'Jane']]];
  303. Arr::forget($array, ['emails.i@example.com', 'emails.jack@localhost']);
  304. $this->assertSame(['emails' => ['i@example.com' => ['name' => 'Joe']]], $array);
  305. }
  306. public function testWrap()
  307. {
  308. $string = 'a';
  309. $array = ['a'];
  310. $object = new stdClass();
  311. $object->value = 'a';
  312. $this->assertSame(['a'], Arr::wrap($string));
  313. $this->assertSame($array, Arr::wrap($array));
  314. $this->assertSame([$object], Arr::wrap($object));
  315. }
  316. }