Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7c3375d

Browse files
authored
Allow to merge an array of stages into a pipeline (mongodb#57)
* Allow to merge an array of stages into a pipeline * Improve types * Add test to create pipeline from array
1 parent fe8f353 commit 7c3375d

File tree

3 files changed

+83
-49
lines changed

3 files changed

+83
-49
lines changed

‎psalm-baseline.xml‎

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="5.21.1@8c473e2437be8b6a8fd8f630f0f11a16b114c494">
2+
<files psalm-version="5.22.2@d768d914152dbbf3486c36398802f74e80cfde48">
33
<file src="src/Builder/Encoder/AbstractExpressionEncoder.php">
44
<MixedAssignment>
5-
<code>$val</code>
6-
<code>$val</code>
7-
<code>$value[$key]</code>
5+
<code><![CDATA[$val]]></code>
6+
<code><![CDATA[$val]]></code>
7+
<code><![CDATA[$value[$key]]]></code>
88
</MixedAssignment>
99
</file>
1010
<file src="src/Builder/Encoder/CombinedFieldQueryEncoder.php">
1111
<MixedAssignment>
12-
<code>$filter</code>
13-
<code>$filterValue</code>
12+
<code><![CDATA[$filter]]></code>
13+
<code><![CDATA[$filterValue]]></code>
1414
</MixedAssignment>
1515
</file>
1616
<file src="src/Builder/Encoder/FieldPathEncoder.php">
@@ -20,105 +20,111 @@
2020
</file>
2121
<file src="src/Builder/Encoder/OperatorEncoder.php">
2222
<MixedAssignment>
23-
<code>$result</code>
24-
<code>$result[]</code>
25-
<code>$val</code>
26-
<code>$val</code>
27-
<code>$val</code>
28-
<code>$val</code>
29-
<code>$val</code>
23+
<code><![CDATA[$result]]></code>
24+
<code><![CDATA[$result[]]]></code>
25+
<code><![CDATA[$val]]></code>
26+
<code><![CDATA[$val]]></code>
27+
<code><![CDATA[$val]]></code>
28+
<code><![CDATA[$val]]></code>
29+
<code><![CDATA[$val]]></code>
3030
</MixedAssignment>
3131
</file>
3232
<file src="src/Builder/Encoder/OutputWindowEncoder.php">
3333
<MixedArgument>
34-
<code>$result</code>
34+
<code><![CDATA[$result]]></code>
3535
</MixedArgument>
3636
</file>
37+
<file src="src/Builder/Encoder/PipelineEncoder.php">
38+
<MixedAssignment>
39+
<code><![CDATA[$encoded[]]]></code>
40+
<code><![CDATA[$stage]]></code>
41+
</MixedAssignment>
42+
</file>
3743
<file src="src/Builder/Encoder/QueryEncoder.php">
3844
<MixedArgument>
3945
<code><![CDATA[$this->recursiveEncode($value)]]></code>
4046
</MixedArgument>
4147
<MixedAssignment>
42-
<code>$subValue</code>
43-
<code>$value</code>
48+
<code><![CDATA[$subValue]]></code>
49+
<code><![CDATA[$value]]></code>
4450
</MixedAssignment>
4551
</file>
4652
<file src="src/Builder/Projection/ElemMatchOperator.php">
4753
<MixedArgumentTypeCoercion>
48-
<code>$query</code>
54+
<code><![CDATA[$query]]></code>
4955
</MixedArgumentTypeCoercion>
5056
</file>
5157
<file src="src/Builder/Query.php">
5258
<ArgumentTypeCoercion>
53-
<code>$query</code>
59+
<code><![CDATA[$query]]></code>
5460
</ArgumentTypeCoercion>
5561
</file>
5662
<file src="src/Builder/Query/ElemMatchOperator.php">
5763
<MixedArgumentTypeCoercion>
58-
<code>$query</code>
64+
<code><![CDATA[$query]]></code>
5965
</MixedArgumentTypeCoercion>
6066
</file>
6167
<file src="src/Builder/Stage/AddFieldsStage.php">
6268
<PropertyTypeCoercion>
63-
<code>$expression</code>
69+
<code><![CDATA[$expression]]></code>
6470
</PropertyTypeCoercion>
6571
<TooManyTemplateParams>
66-
<code>stdClass</code>
72+
<code><![CDATA[stdClass]]></code>
6773
</TooManyTemplateParams>
6874
</file>
6975
<file src="src/Builder/Stage/FacetStage.php">
7076
<PropertyTypeCoercion>
71-
<code>$facet</code>
77+
<code><![CDATA[$facet]]></code>
7278
</PropertyTypeCoercion>
7379
<TooManyTemplateParams>
74-
<code>stdClass</code>
80+
<code><![CDATA[stdClass]]></code>
7581
</TooManyTemplateParams>
7682
</file>
7783
<file src="src/Builder/Stage/GeoNearStage.php">
7884
<MixedArgumentTypeCoercion>
79-
<code>$query</code>
85+
<code><![CDATA[$query]]></code>
8086
</MixedArgumentTypeCoercion>
8187
</file>
8288
<file src="src/Builder/Stage/GraphLookupStage.php">
8389
<MixedArgumentTypeCoercion>
84-
<code>$restrictSearchWithMatch</code>
90+
<code><![CDATA[$restrictSearchWithMatch]]></code>
8591
</MixedArgumentTypeCoercion>
8692
</file>
8793
<file src="src/Builder/Stage/GroupStage.php">
8894
<PropertyTypeCoercion>
89-
<code>$field</code>
95+
<code><![CDATA[$field]]></code>
9096
</PropertyTypeCoercion>
9197
<TooManyTemplateParams>
92-
<code>stdClass</code>
98+
<code><![CDATA[stdClass]]></code>
9399
</TooManyTemplateParams>
94100
</file>
95101
<file src="src/Builder/Stage/MatchStage.php">
96102
<MixedArgumentTypeCoercion>
97-
<code>$query</code>
103+
<code><![CDATA[$query]]></code>
98104
</MixedArgumentTypeCoercion>
99105
</file>
100106
<file src="src/Builder/Stage/ProjectStage.php">
101107
<PropertyTypeCoercion>
102-
<code>$specification</code>
108+
<code><![CDATA[$specification]]></code>
103109
</PropertyTypeCoercion>
104110
<TooManyTemplateParams>
105-
<code>stdClass</code>
111+
<code><![CDATA[stdClass]]></code>
106112
</TooManyTemplateParams>
107113
</file>
108114
<file src="src/Builder/Stage/SetStage.php">
109115
<PropertyTypeCoercion>
110-
<code>$field</code>
116+
<code><![CDATA[$field]]></code>
111117
</PropertyTypeCoercion>
112118
<TooManyTemplateParams>
113-
<code>stdClass</code>
119+
<code><![CDATA[stdClass]]></code>
114120
</TooManyTemplateParams>
115121
</file>
116122
<file src="src/Builder/Stage/SortStage.php">
117123
<PropertyTypeCoercion>
118-
<code>$sort</code>
124+
<code><![CDATA[$sort]]></code>
119125
</PropertyTypeCoercion>
120126
<TooManyTemplateParams>
121-
<code>stdClass</code>
127+
<code><![CDATA[stdClass]]></code>
122128
</TooManyTemplateParams>
123129
</file>
124130
<file src="src/Builder/Type/OutputWindow.php">
@@ -129,8 +135,8 @@
129135
</file>
130136
<file src="src/Builder/Type/QueryObject.php">
131137
<MixedAssignment>
132-
<code>$queries[$fieldPath]</code>
133-
<code>$query</code>
138+
<code><![CDATA[$queries[$fieldPath]]]></code>
139+
<code><![CDATA[$query]]></code>
134140
</MixedAssignment>
135141
<RedundantConditionGivenDocblockType>
136142
<code><![CDATA[count($queriesOrArrayOfQueries) === 1 &&

‎src/Builder/Pipeline.php‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,31 @@
88
use IteratorAggregate;
99
use MongoDB\Builder\Type\StageInterface;
1010
use MongoDB\Exception\InvalidArgumentException;
11-
use Traversable;
11+
use stdClass;
1212

1313
use function array_is_list;
1414
use function array_merge;
15+
use function is_array;
1516

1617
/**
1718
* An aggregation pipeline consists of one or more stages that process documents.
1819
*
1920
* @see https://www.mongodb.com/docs/manual/core/aggregation-pipeline/
2021
*
2122
* @psalm-immutable
22-
* @implements IteratorAggregate<StageInterface>
23+
* @psalm-type stage = StageInterface|array<string,mixed>|stdClass
24+
* @implements IteratorAggregate<stage>
2325
*/
24-
class Pipeline implements IteratorAggregate
26+
finalclass Pipeline implements IteratorAggregate
2527
{
26-
/** @var StageInterface[] */
2728
private readonly array $stages;
2829

29-
/** @no-named-arguments */
30-
public function __construct(StageInterface|Pipeline ...$stagesOrPipelines)
30+
/**
31+
* @psalm-param stage|list<stage> ...$stagesOrPipelines
32+
*
33+
* @no-named-arguments
34+
*/
35+
public function __construct(StageInterface|Pipeline|array|stdClass ...$stagesOrPipelines)
3136
{
3237
if (! array_is_list($stagesOrPipelines)) {
3338
throw new InvalidArgumentException('Named arguments are not supported for pipelines');
@@ -36,7 +41,9 @@ public function __construct(StageInterface|Pipeline ...$stagesOrPipelines)
3641
$stages = [];
3742

3843
foreach ($stagesOrPipelines as $stageOrPipeline) {
39-
if ($stageOrPipeline instanceof Pipeline) {
44+
if (is_array($stageOrPipeline) && array_is_list($stageOrPipeline)) {
45+
$stages = array_merge($stages, $stageOrPipeline);
46+
} elseif ($stageOrPipeline instanceof Pipeline) {
4047
$stages = array_merge($stages, $stageOrPipeline->stages);
4148
} else {
4249
$stages[] = $stageOrPipeline;
@@ -46,8 +53,7 @@ public function __construct(StageInterface|Pipeline ...$stagesOrPipelines)
4653
$this->stages = $stages;
4754
}
4855

49-
/** @return Traversable<StageInterface> */
50-
public function getIterator(): Traversable
56+
public function getIterator(): ArrayIterator
5157
{
5258
return new ArrayIterator($this->stages);
5359
}

‎tests/Builder/PipelineTest.php‎

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,46 @@ class PipelineTest extends TestCase
1717
{
1818
public function testEmptyPipeline(): void
1919
{
20-
$pipeline = new Pipeline();
20+
$pipeline = new Pipeline([]);
2121

2222
$this->assertSame([], iterator_to_array($pipeline));
2323
}
2424

25+
public function testFromArray(): void
26+
{
27+
$pipeline = new Pipeline(
28+
['$match' => ['tag' => 'foo']],
29+
[
30+
['$sort' => ['_id' => 1]],
31+
['$skip' => 10],
32+
],
33+
['$limit' => 5],
34+
);
35+
36+
$expected = [
37+
['$match' => ['tag' => 'foo']],
38+
['$sort' => ['_id' => 1]],
39+
['$skip' => 10],
40+
['$limit' => 5],
41+
];
42+
43+
$this->assertSame($expected, iterator_to_array($pipeline));
44+
}
45+
2546
public function testMergingPipeline(): void
2647
{
2748
$stages = array_map(
2849
fn (int $i) => $this->createMock(StageInterface::class),
29-
range(0, 5),
50+
range(0, 7),
3051
);
3152

3253
$pipeline = new Pipeline(
3354
$stages[0],
3455
$stages[1],
3556
new Pipeline($stages[2], $stages[3]),
36-
$stages[4],
37-
new Pipeline($stages[5]),
57+
[$stages[4], $stages[5]],
58+
new Pipeline($stages[6]),
59+
[$stages[7]],
3860
);
3961

4062
$this->assertSame($stages, iterator_to_array($pipeline));

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /