343 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			343 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?php | ||
|  | 
 | ||
|  | namespace Tests; | ||
|  | 
 | ||
|  | use stdClass; | ||
|  | use think\Collection; | ||
|  | use think\helper\Arr; | ||
|  | 
 | ||
|  | class ArrTest extends TestCase | ||
|  | { | ||
|  |     public function testAdd() | ||
|  |     { | ||
|  |         $array = Arr::add(['name' => 'ThinkPHP'], 'price', 100); | ||
|  |         $this->assertSame(['name' => 'ThinkPHP', 'price' => 100], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testCrossJoin() | ||
|  |     { | ||
|  |         // Single dimension
 | ||
|  |         $this->assertSame( | ||
|  |             [[1, 'a'], [1, 'b'], [1, 'c']], | ||
|  |             Arr::crossJoin([1], ['a', 'b', 'c']) | ||
|  |         ); | ||
|  |         // Square matrix
 | ||
|  |         $this->assertSame( | ||
|  |             [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']], | ||
|  |             Arr::crossJoin([1, 2], ['a', 'b']) | ||
|  |         ); | ||
|  |         // Rectangular matrix
 | ||
|  |         $this->assertSame( | ||
|  |             [[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']], | ||
|  |             Arr::crossJoin([1, 2], ['a', 'b', 'c']) | ||
|  |         ); | ||
|  |         // 3D matrix
 | ||
|  |         $this->assertSame( | ||
|  |             [ | ||
|  |                 [1, 'a', 'I'], [1, 'a', 'II'], [1, 'a', 'III'], | ||
|  |                 [1, 'b', 'I'], [1, 'b', 'II'], [1, 'b', 'III'], | ||
|  |                 [2, 'a', 'I'], [2, 'a', 'II'], [2, 'a', 'III'], | ||
|  |                 [2, 'b', 'I'], [2, 'b', 'II'], [2, 'b', 'III'], | ||
|  |             ], | ||
|  |             Arr::crossJoin([1, 2], ['a', 'b'], ['I', 'II', 'III']) | ||
|  |         ); | ||
|  |         // With 1 empty dimension
 | ||
|  |         $this->assertSame([], Arr::crossJoin([], ['a', 'b'], ['I', 'II', 'III'])); | ||
|  |         $this->assertSame([], Arr::crossJoin([1, 2], [], ['I', 'II', 'III'])); | ||
|  |         $this->assertSame([], Arr::crossJoin([1, 2], ['a', 'b'], [])); | ||
|  |         // With empty arrays
 | ||
|  |         $this->assertSame([], Arr::crossJoin([], [], [])); | ||
|  |         $this->assertSame([], Arr::crossJoin([], [])); | ||
|  |         $this->assertSame([], Arr::crossJoin([])); | ||
|  |         // Not really a proper usage, still, test for preserving BC
 | ||
|  |         $this->assertSame([[]], Arr::crossJoin()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testDivide() | ||
|  |     { | ||
|  |         list($keys, $values) = Arr::divide(['name' => 'ThinkPHP']); | ||
|  |         $this->assertSame(['name'], $keys); | ||
|  |         $this->assertSame(['ThinkPHP'], $values); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testDot() | ||
|  |     { | ||
|  |         $array = Arr::dot(['foo' => ['bar' => 'baz']]); | ||
|  |         $this->assertSame(['foo.bar' => 'baz'], $array); | ||
|  |         $array = Arr::dot([]); | ||
|  |         $this->assertSame([], $array); | ||
|  |         $array = Arr::dot(['foo' => []]); | ||
|  |         $this->assertSame(['foo' => []], $array); | ||
|  |         $array = Arr::dot(['foo' => ['bar' => []]]); | ||
|  |         $this->assertSame(['foo.bar' => []], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testExcept() | ||
|  |     { | ||
|  |         $array = ['name' => 'ThinkPHP', 'price' => 100]; | ||
|  |         $array = Arr::except($array, ['price']); | ||
|  |         $this->assertSame(['name' => 'ThinkPHP'], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testExists() | ||
|  |     { | ||
|  |         $this->assertTrue(Arr::exists([1], 0)); | ||
|  |         $this->assertTrue(Arr::exists([null], 0)); | ||
|  |         $this->assertTrue(Arr::exists(['a' => 1], 'a')); | ||
|  |         $this->assertTrue(Arr::exists(['a' => null], 'a')); | ||
|  |         $this->assertFalse(Arr::exists([1], 1)); | ||
|  |         $this->assertFalse(Arr::exists([null], 1)); | ||
|  |         $this->assertFalse(Arr::exists(['a' => 1], 0)); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testFirst() | ||
|  |     { | ||
|  |         $array = [100, 200, 300]; | ||
|  |         $value = Arr::first($array, function ($value) { | ||
|  |             return $value >= 150; | ||
|  |         }); | ||
|  |         $this->assertSame(200, $value); | ||
|  |         $this->assertSame(100, Arr::first($array)); | ||
|  | 
 | ||
|  |         $this->assertSame('default', Arr::first([], null, 'default')); | ||
|  | 
 | ||
|  |         $this->assertSame('default', Arr::first([], function () { | ||
|  |             return false; | ||
|  |         }, 'default')); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testLast() | ||
|  |     { | ||
|  |         $array = [100, 200, 300]; | ||
|  |         $last = Arr::last($array, function ($value) { | ||
|  |             return $value < 250; | ||
|  |         }); | ||
|  |         $this->assertSame(200, $last); | ||
|  |         $last = Arr::last($array, function ($value, $key) { | ||
|  |             return $key < 2; | ||
|  |         }); | ||
|  |         $this->assertSame(200, $last); | ||
|  |         $this->assertSame(300, Arr::last($array)); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testFlatten() | ||
|  |     { | ||
|  |         // Flat arrays are unaffected
 | ||
|  |         $array = ['#foo', '#bar', '#baz']; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten(['#foo', '#bar', '#baz'])); | ||
|  |         // Nested arrays are flattened with existing flat items
 | ||
|  |         $array = [['#foo', '#bar'], '#baz']; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array)); | ||
|  |         // Flattened array includes "null" items
 | ||
|  |         $array = [['#foo', null], '#baz', null]; | ||
|  |         $this->assertSame(['#foo', null, '#baz', null], Arr::flatten($array)); | ||
|  |         // Sets of nested arrays are flattened
 | ||
|  |         $array = [['#foo', '#bar'], ['#baz']]; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array)); | ||
|  |         // Deeply nested arrays are flattened
 | ||
|  |         $array = [['#foo', ['#bar']], ['#baz']]; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array)); | ||
|  |         // Nested arrays are flattened alongside arrays
 | ||
|  |         $array = [new Collection(['#foo', '#bar']), ['#baz']]; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array)); | ||
|  |         // Nested arrays containing plain arrays are flattened
 | ||
|  |         $array = [new Collection(['#foo', ['#bar']]), ['#baz']]; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array)); | ||
|  |         // Nested arrays containing arrays are flattened
 | ||
|  |         $array = [['#foo', new Collection(['#bar'])], ['#baz']]; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array)); | ||
|  |         // Nested arrays containing arrays containing arrays are flattened
 | ||
|  |         $array = [['#foo', new Collection(['#bar', ['#zap']])], ['#baz']]; | ||
|  |         $this->assertSame(['#foo', '#bar', '#zap', '#baz'], Arr::flatten($array)); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testFlattenWithDepth() | ||
|  |     { | ||
|  |         // No depth flattens recursively
 | ||
|  |         $array = [['#foo', ['#bar', ['#baz']]], '#zap']; | ||
|  |         $this->assertSame(['#foo', '#bar', '#baz', '#zap'], Arr::flatten($array)); | ||
|  |         // Specifying a depth only flattens to that depth
 | ||
|  |         $array = [['#foo', ['#bar', ['#baz']]], '#zap']; | ||
|  |         $this->assertSame(['#foo', ['#bar', ['#baz']], '#zap'], Arr::flatten($array, 1)); | ||
|  |         $array = [['#foo', ['#bar', ['#baz']]], '#zap']; | ||
|  |         $this->assertSame(['#foo', '#bar', ['#baz'], '#zap'], Arr::flatten($array, 2)); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testGet() | ||
|  |     { | ||
|  |         $array = ['products.item' => ['price' => 100]]; | ||
|  |         $this->assertSame(['price' => 100], Arr::get($array, 'products.item')); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         $value = Arr::get($array, 'products.item'); | ||
|  |         $this->assertSame(['price' => 100], $value); | ||
|  |         // Test null array values
 | ||
|  |         $array = ['foo' => null, 'bar' => ['baz' => null]]; | ||
|  |         $this->assertNull(Arr::get($array, 'foo', 'default')); | ||
|  |         $this->assertNull(Arr::get($array, 'bar.baz', 'default')); | ||
|  |         // Test null key returns the whole array
 | ||
|  |         $array = ['foo', 'bar']; | ||
|  |         $this->assertSame($array, Arr::get($array, null)); | ||
|  |         // Test $array is empty and key is null
 | ||
|  |         $this->assertSame([], Arr::get([], null)); | ||
|  |         $this->assertSame([], Arr::get([], null, 'default')); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testHas() | ||
|  |     { | ||
|  |         $array = ['products.item' => ['price' => 100]]; | ||
|  |         $this->assertTrue(Arr::has($array, 'products.item')); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         $this->assertTrue(Arr::has($array, 'products.item')); | ||
|  |         $this->assertTrue(Arr::has($array, 'products.item.price')); | ||
|  |         $this->assertFalse(Arr::has($array, 'products.foo')); | ||
|  |         $this->assertFalse(Arr::has($array, 'products.item.foo')); | ||
|  |         $array = ['foo' => null, 'bar' => ['baz' => null]]; | ||
|  |         $this->assertTrue(Arr::has($array, 'foo')); | ||
|  |         $this->assertTrue(Arr::has($array, 'bar.baz')); | ||
|  |         $array = ['foo', 'bar']; | ||
|  |         $this->assertFalse(Arr::has($array, null)); | ||
|  |         $this->assertFalse(Arr::has([], null)); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         $this->assertTrue(Arr::has($array, ['products.item'])); | ||
|  |         $this->assertTrue(Arr::has($array, ['products.item', 'products.item.price'])); | ||
|  |         $this->assertTrue(Arr::has($array, ['products', 'products'])); | ||
|  |         $this->assertFalse(Arr::has($array, ['foo'])); | ||
|  |         $this->assertFalse(Arr::has($array, [])); | ||
|  |         $this->assertFalse(Arr::has($array, ['products.item', 'products.price'])); | ||
|  |         $this->assertFalse(Arr::has([], [null])); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testIsAssoc() | ||
|  |     { | ||
|  |         $this->assertTrue(Arr::isAssoc(['a' => 'a', 0 => 'b'])); | ||
|  |         $this->assertTrue(Arr::isAssoc([1 => 'a', 0 => 'b'])); | ||
|  |         $this->assertTrue(Arr::isAssoc([1 => 'a', 2 => 'b'])); | ||
|  |         $this->assertFalse(Arr::isAssoc([0 => 'a', 1 => 'b'])); | ||
|  |         $this->assertFalse(Arr::isAssoc(['a', 'b'])); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testOnly() | ||
|  |     { | ||
|  |         $array = ['name' => 'ThinkPHP', 'price' => 100, 'orders' => 10]; | ||
|  |         $array = Arr::only($array, ['name', 'price']); | ||
|  |         $this->assertSame(['name' => 'ThinkPHP', 'price' => 100], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testPrepend() | ||
|  |     { | ||
|  |         $array = Arr::prepend(['one', 'two', 'three', 'four'], 'zero'); | ||
|  |         $this->assertSame(['zero', 'one', 'two', 'three', 'four'], $array); | ||
|  |         $array = Arr::prepend(['one' => 1, 'two' => 2], 0, 'zero'); | ||
|  |         $this->assertSame(['zero' => 0, 'one' => 1, 'two' => 2], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testPull() | ||
|  |     { | ||
|  |         $array = ['name' => 'ThinkPHP', 'price' => 100]; | ||
|  |         $name = Arr::pull($array, 'name'); | ||
|  |         $this->assertSame('ThinkPHP', $name); | ||
|  |         $this->assertSame(['price' => 100], $array); | ||
|  |         // Only works on first level keys
 | ||
|  |         $array = ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']; | ||
|  |         $name = Arr::pull($array, 'i@example.com'); | ||
|  |         $this->assertSame('Joe', $name); | ||
|  |         $this->assertSame(['jack@localhost' => 'Jane'], $array); | ||
|  |         // Does not work for nested keys
 | ||
|  |         $array = ['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']]; | ||
|  |         $name = Arr::pull($array, 'emails.i@example.com'); | ||
|  |         $this->assertNull($name); | ||
|  |         $this->assertSame(['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testRandom() | ||
|  |     { | ||
|  |         $randomValue = Arr::random(['foo', 'bar', 'baz']); | ||
|  |         $this->assertContains($randomValue, ['foo', 'bar', 'baz']); | ||
|  |         $randomValues = Arr::random(['foo', 'bar', 'baz'], 1); | ||
|  |         $this->assertIsArray($randomValues); | ||
|  |         $this->assertCount(1, $randomValues); | ||
|  |         $this->assertContains($randomValues[0], ['foo', 'bar', 'baz']); | ||
|  |         $randomValues = Arr::random(['foo', 'bar', 'baz'], 2); | ||
|  |         $this->assertIsArray($randomValues); | ||
|  |         $this->assertCount(2, $randomValues); | ||
|  |         $this->assertContains($randomValues[0], ['foo', 'bar', 'baz']); | ||
|  |         $this->assertContains($randomValues[1], ['foo', 'bar', 'baz']); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testSet() | ||
|  |     { | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         Arr::set($array, 'products.item.price', 200); | ||
|  |         Arr::set($array, 'goods.item.price', 200); | ||
|  |         $this->assertSame(['products' => ['item' => ['price' => 200]], 'goods' => ['item' => ['price' => 200]]], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testWhere() | ||
|  |     { | ||
|  |         $array = [100, '200', 300, '400', 500]; | ||
|  |         $array = Arr::where($array, function ($value, $key) { | ||
|  |             return is_string($value); | ||
|  |         }); | ||
|  |         $this->assertSame([1 => '200', 3 => '400'], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testWhereKey() | ||
|  |     { | ||
|  |         $array = ['10' => 1, 'foo' => 3, 20 => 2]; | ||
|  |         $array = Arr::where($array, function ($value, $key) { | ||
|  |             return is_numeric($key); | ||
|  |         }); | ||
|  |         $this->assertSame(['10' => 1, 20 => 2], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testForget() | ||
|  |     { | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         Arr::forget($array, null); | ||
|  |         $this->assertSame(['products' => ['item' => ['price' => 100]]], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         Arr::forget($array, []); | ||
|  |         $this->assertSame(['products' => ['item' => ['price' => 100]]], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         Arr::forget($array, 'products.item'); | ||
|  |         $this->assertSame(['products' => []], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         Arr::forget($array, 'products.item.price'); | ||
|  |         $this->assertSame(['products' => ['item' => []]], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => 100]]]; | ||
|  |         Arr::forget($array, 'products.final.price'); | ||
|  |         $this->assertSame(['products' => ['item' => ['price' => 100]]], $array); | ||
|  |         $array = ['shop' => ['cart' => [150 => 0]]]; | ||
|  |         Arr::forget($array, 'shop.final.cart'); | ||
|  |         $this->assertSame(['shop' => ['cart' => [150 => 0]]], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]]; | ||
|  |         Arr::forget($array, 'products.item.price.taxes'); | ||
|  |         $this->assertSame(['products' => ['item' => ['price' => ['original' => 50]]]], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]]; | ||
|  |         Arr::forget($array, 'products.item.final.taxes'); | ||
|  |         $this->assertSame(['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]], $array); | ||
|  |         $array = ['products' => ['item' => ['price' => 50], null => 'something']]; | ||
|  |         Arr::forget($array, ['products.amount.all', 'products.item.price']); | ||
|  |         $this->assertSame(['products' => ['item' => [], null => 'something']], $array); | ||
|  |         // Only works on first level keys
 | ||
|  |         $array = ['i@example.com' => 'Joe', 'i@thinkphp.com' => 'Jane']; | ||
|  |         Arr::forget($array, 'i@example.com'); | ||
|  |         $this->assertSame(['i@thinkphp.com' => 'Jane'], $array); | ||
|  |         // Does not work for nested keys
 | ||
|  |         $array = ['emails' => ['i@example.com' => ['name' => 'Joe'], 'jack@localhost' => ['name' => 'Jane']]]; | ||
|  |         Arr::forget($array, ['emails.i@example.com', 'emails.jack@localhost']); | ||
|  |         $this->assertSame(['emails' => ['i@example.com' => ['name' => 'Joe']]], $array); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testWrap() | ||
|  |     { | ||
|  |         $string = 'a'; | ||
|  |         $array = ['a']; | ||
|  |         $object = new stdClass(); | ||
|  |         $object->value = 'a'; | ||
|  |         $this->assertSame(['a'], Arr::wrap($string)); | ||
|  |         $this->assertSame($array, Arr::wrap($array)); | ||
|  |         $this->assertSame([$object], Arr::wrap($object)); | ||
|  |     } | ||
|  | } |