Skip to content

[12.x] Add containsAny() and containsAll() methods to Support Collection #56555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions src/Illuminate/Collections/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
16 changes: 16 additions & 0 deletions src/Illuminate/Collections/Enumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
66 changes: 66 additions & 0 deletions src/Illuminate/Collections/LazyCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
157 changes: 157 additions & 0 deletions tests/Support/SupportCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Loading