diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index ce683bee94d1..bfb5cdd81adb 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -195,6 +195,76 @@ public function contains($key, $operator = null, $value = null) return $this->contains($this->operatorForWhere(...func_get_args())); } + /** + * Determine if any of the given items exist in the collection. + * + * @param mixed $values + * @return bool + */ + public function containsAny($values) + { + if ($this->isEmpty()) { + return false; + } + + $values = is_array($values) ? $values : func_get_args(); + + foreach ($values as $value) { + if ($this->useAsCallable($value)) { + $placeholder = new stdClass; + + if ($this->first($value, $placeholder) !== $placeholder) { + return true; + } + } elseif (is_array($value)) { + if ($this->contains(...$value)) { + return true; + } + } elseif (in_array($value, $this->items)) { + return true; + } + } + + return false; + } + + /** + * Determine if all of the given items exist in the collection. + * + * @param mixed $values + * @return bool + */ + public function containsAll($values) + { + $values = is_array($values) ? $values : func_get_args(); + + if (empty($values)) { + return true; + } + + if ($this->isEmpty()) { + return false; + } + + foreach ($values as $value) { + if ($this->useAsCallable($value)) { + $placeholder = new stdClass; + + if ($this->first($value, $placeholder) === $placeholder) { + return false; + } + } elseif (is_array($value)) { + if (! $this->contains(...$value)) { + return false; + } + } elseif (! in_array($value, $this->items)) { + return false; + } + } + + return true; + } + /** * Determine if an item exists, using strict comparison. * diff --git a/src/Illuminate/Collections/Enumerable.php b/src/Illuminate/Collections/Enumerable.php index 78187b785697..a22cebe2b1c2 100644 --- a/src/Illuminate/Collections/Enumerable.php +++ b/src/Illuminate/Collections/Enumerable.php @@ -153,6 +153,22 @@ public function avg($callback = null); */ public function contains($key, $operator = null, $value = null); + /** + * Determine if any of the given items exist in the collection. + * + * @param mixed $values + * @return bool + */ + public function containsAny($values); + + /** + * Determine if all of the given items exist in the collection. + * + * @param mixed $values + * @return bool + */ + public function containsAll($values); + /** * Determine if an item is not contained in the collection. * diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index 14665acd5312..04a6f5523e05 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -248,6 +248,72 @@ public function contains($key, $operator = null, $value = null) return $this->contains($this->operatorForWhere(...func_get_args())); } + /** + * Determine if any of the given items exist in the collection. + * + * @param mixed $values + * @return bool + */ + public function containsAny($values) + { + if ($this->isEmpty()) { + return false; + } + + $values = is_array($values) ? $values : func_get_args(); + + foreach ($values as $value) { + if ($this->useAsCallable($value)) { + if ($this->first($value) !== null) { + return true; + } + } elseif (is_array($value)) { + if ($this->contains(...$value)) { + return true; + } + } elseif ($this->contains($value)) { + return true; + } + } + + return false; + } + + /** + * Determine if all of the given items exist in the collection. + * + * @param mixed $values + * @return bool + */ + public function containsAll($values) + { + $values = is_array($values) ? $values : func_get_args(); + + if (empty($values)) { + return true; + } + + if ($this->isEmpty()) { + return false; + } + + foreach ($values as $value) { + if ($this->useAsCallable($value)) { + if ($this->first($value) === null) { + return false; + } + } elseif (is_array($value)) { + if (! $this->contains(...$value)) { + return false; + } + } elseif (! $this->contains($value)) { + return false; + } + } + + return true; + } + /** * Determine if an item exists, using strict comparison. * diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 211c7be80641..7f8e6a65983b 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -3791,6 +3791,163 @@ public function testContainsWithOperator($collection) $this->assertTrue($c->contains('v', '>', 4)); } + #[DataProvider('collectionClassProvider')] + public function testContainsAny($collection) + { + $c = new $collection([1, 3, 5]); + + $this->assertTrue($c->containsAny([1, 2])); + $this->assertTrue($c->containsAny([2, 3])); + $this->assertFalse($c->containsAny([2, 4])); + $this->assertFalse($c->containsAny([])); + + $this->assertTrue($c->containsAny(1, 2)); + $this->assertTrue($c->containsAny(2, 3)); + $this->assertFalse($c->containsAny(2, 4)); + + $this->assertTrue($c->containsAny(['1', 2])); + $this->assertTrue($c->containsAny([2, '3'])); + + $c = new $collection([null, false, 0, '']); + $this->assertTrue($c->containsAny([null, 'missing'])); + $this->assertTrue($c->containsAny([false, 'missing'])); + $this->assertTrue($c->containsAny([0, 'missing'])); + $this->assertTrue($c->containsAny(['', 'missing'])); + $this->assertFalse($c->containsAny(['missing', 'also_missing'])); + + $c = new $collection([1, 3, 5]); + $this->assertTrue($c->containsAny([ + function ($value) { + return $value < 2; + }, + function ($value) { + return $value > 10; + }, + ])); + $this->assertFalse($c->containsAny([ + function ($value) { + return $value > 10; + }, + function ($value) { + return $value < 0; + }, + ])); + + $c = new $collection([['v' => 1], ['v' => 3], ['v' => 5]]); + $this->assertTrue($c->containsAny([['v', 1], ['v', 2]])); + $this->assertTrue($c->containsAny([['v', 2], ['v', 1]])); + $this->assertTrue($c->containsAny([['v', 2], ['v', 3]])); + $this->assertFalse($c->containsAny([['v', 2], ['v', 4]])); + + $c = new $collection([]); + $this->assertFalse($c->containsAny([1, 2, 3])); + $this->assertFalse($c->containsAny(1, 2, 3)); + } + + #[DataProvider('collectionClassProvider')] + public function testContainsAnyWithOperator($collection) + { + $c = new $collection([['v' => 1], ['v' => 3], ['v' => '4'], ['v' => 5]]); + + $this->assertTrue($c->containsAny([['v', '=', 4], ['v', '=', 6]])); + $this->assertTrue($c->containsAny([['v', '==', 4], ['v', '==', 6]])); + $this->assertFalse($c->containsAny([['v', '===', 4], ['v', '===', 6]])); + $this->assertTrue($c->containsAny([['v', '>', 4], ['v', '<', 0]])); + $this->assertTrue($c->containsAny([['v', '>', 0], ['v', '<', 0]])); + $this->assertFalse($c->containsAny([['v', '>', 10], ['v', '<', 0]])); + + $this->assertTrue($c->containsAny([ + ['v', '>', 10], + ['v', '=', 3], + ])); + } + + #[DataProvider('collectionClassProvider')] + public function testContainsAll($collection) + { + $c = new $collection([1, 3, 5]); + + $this->assertTrue($c->containsAll([1, 3])); + $this->assertTrue($c->containsAll([3, 5])); + $this->assertTrue($c->containsAll([1, 3, 5])); + $this->assertFalse($c->containsAll([1, 2])); + $this->assertFalse($c->containsAll([2, 4])); + $this->assertTrue($c->containsAll([])); + + $this->assertTrue($c->containsAll(1, 3)); + $this->assertTrue($c->containsAll(3, 5)); + $this->assertFalse($c->containsAll(1, 2)); + + $this->assertTrue($c->containsAll(['1', 3])); + $this->assertTrue($c->containsAll([3, '5'])); + + $c = new $collection([null, false, 0, '']); + $this->assertTrue($c->containsAll([null, false])); + $this->assertTrue($c->containsAll([0, ''])); + $this->assertTrue($c->containsAll([null, false, 0, ''])); + $this->assertFalse($c->containsAll([null, 'missing'])); + $this->assertFalse($c->containsAll(['missing', 'also_missing'])); + + $c = new $collection([1, 3, 5]); + $this->assertTrue($c->containsAll([ + function ($value) { + return $value < 2; + }, + function ($value) { + return $value > 4; + }, + ])); + $this->assertFalse($c->containsAll([ + function ($value) { + return $value > 10; + }, + function ($value) { + return $value < 0; + }, + ])); + $this->assertFalse($c->containsAll([ + function ($value) { + return $value < 2; + }, + function ($value) { + return $value > 10; + }, + ])); + + $c = new $collection([['v' => 1], ['v' => 3], ['v' => 5]]); + $this->assertTrue($c->containsAll([['v', 1], ['v', 3]])); + $this->assertTrue($c->containsAll([['v', 3], ['v', 5]])); + $this->assertFalse($c->containsAll([['v', 1], ['v', 2]])); + $this->assertFalse($c->containsAll([['v', 2], ['v', 4]])); + + $c = new $collection([]); + $this->assertTrue($c->containsAll([])); + $this->assertFalse($c->containsAll([1])); + $this->assertFalse($c->containsAll(1, 2, 3)); + } + + #[DataProvider('collectionClassProvider')] + public function testContainsAllWithOperator($collection) + { + $c = new $collection([['v' => 1], ['v' => 3], ['v' => '4'], ['v' => 5]]); + + $this->assertTrue($c->containsAll([['v', '=', 4], ['v', '=', 3]])); + $this->assertTrue($c->containsAll([['v', '==', 4], ['v', '==', 1]])); + $this->assertFalse($c->containsAll([['v', '===', 4], ['v', '===', 3]])); + $this->assertTrue($c->containsAll([['v', '>', 0], ['v', '<', 10]])); + $this->assertTrue($c->containsAll([['v', '>', 4], ['v', '<', 2]])); + $this->assertFalse($c->containsAll([['v', '>', 10], ['v', '<', 0]])); + + $this->assertTrue($c->containsAll([ + ['v', '>', 0], + ['v', '=', 3], + ])); + $this->assertFalse($c->containsAll([ + ['v', '>', 0], + ['v', '=', 99], + ])); + } + #[DataProvider('collectionClassProvider')] public function testGettingSumFromCollection($collection) {