diff --git a/.gitattributes b/.gitattributes
index e5239788..1674a083 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,4 @@
+/stubs export-ignore
/tests export-ignore
/.github export-ignore
.doctrine-project.json export-ignore
diff --git a/composer.json b/composer.json
index 4c36229a..960064c6 100644
--- a/composer.json
+++ b/composer.json
@@ -34,7 +34,8 @@
"homepage": "https://www.doctrine-project.org/projects/collections.html",
"require": {
"php": "^8.1",
- "doctrine/deprecations": "^1"
+ "doctrine/deprecations": "^1",
+ "symfony/polyfill-php84": "^1.30"
},
"require-dev": {
"ext-json": "*",
diff --git a/psalm.xml.dist b/psalm.xml.dist
index aaa96c85..da4259fb 100644
--- a/psalm.xml.dist
+++ b/psalm.xml.dist
@@ -16,6 +16,10 @@
+
+
+
+
@@ -40,6 +44,12 @@
+
+
+
+
+
+
diff --git a/src/ArrayCollection.php b/src/ArrayCollection.php
index 4039c5d3..3635cb1e 100644
--- a/src/ArrayCollection.php
+++ b/src/ArrayCollection.php
@@ -10,7 +10,10 @@
use Stringable;
use Traversable;
+use function array_all;
+use function array_any;
use function array_filter;
+use function array_find;
use function array_key_exists;
use function array_keys;
use function array_map;
@@ -201,13 +204,10 @@ public function contains(mixed $element): bool
public function exists(Closure $p): bool
{
- foreach ($this->elements as $key => $element) {
- if ($p($key, $element)) {
- return true;
- }
- }
-
- return false;
+ return array_any(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
/**
@@ -326,24 +326,18 @@ public function filter(Closure $p): Collection
public function findFirst(Closure $p): mixed
{
- foreach ($this->elements as $key => $element) {
- if ($p($key, $element)) {
- return $element;
- }
- }
-
- return null;
+ return array_find(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
public function forAll(Closure $p): bool
{
- foreach ($this->elements as $key => $element) {
- if (! $p($key, $element)) {
- return false;
- }
- }
-
- return true;
+ return array_all(
+ $this->elements,
+ static fn (mixed $element, mixed $key): bool => (bool) $p($key, $element),
+ );
}
/**
diff --git a/src/Expr/ClosureExpressionVisitor.php b/src/Expr/ClosureExpressionVisitor.php
index 0a331785..bb06a106 100644
--- a/src/Expr/ClosureExpressionVisitor.php
+++ b/src/Expr/ClosureExpressionVisitor.php
@@ -8,6 +8,8 @@
use Closure;
use RuntimeException;
+use function array_all;
+use function array_any;
use function explode;
use function in_array;
use function is_array;
@@ -176,29 +178,19 @@ public function walkCompositeExpression(CompositeExpression $expr): Closure
/** @param callable[] $expressions */
private function andExpressions(array $expressions): Closure
{
- return static function ($object) use ($expressions): bool {
- foreach ($expressions as $expression) {
- if (! $expression($object)) {
- return false;
- }
- }
-
- return true;
- };
+ return static fn ($object): bool => array_all(
+ $expressions,
+ static fn (callable $expression): bool => (bool) $expression($object),
+ );
}
/** @param callable[] $expressions */
private function orExpressions(array $expressions): Closure
{
- return static function ($object) use ($expressions): bool {
- foreach ($expressions as $expression) {
- if ($expression($object)) {
- return true;
- }
- }
-
- return false;
- };
+ return static fn ($object): bool => array_any(
+ $expressions,
+ static fn (callable $expression): bool => (bool) $expression($object),
+ );
}
/** @param callable[] $expressions */
diff --git a/stubs/array_find.phpstub b/stubs/array_find.phpstub
new file mode 100644
index 00000000..bbe9341c
--- /dev/null
+++ b/stubs/array_find.phpstub
@@ -0,0 +1,12 @@
+ $array
+ * @param callable(TValue $value, TKey $key): bool $callback
+ *
+ * @return TValue|null
+ *
+ * @template TKey of array-key
+ * @template TValue
+ */
+function array_find(array $array, callable $callback): mixed {}