|
15 | 15 | use MongoDB\Collection;
|
16 | 16 | use MongoDB\Driver\Cursor;
|
17 | 17 | use OutOfRangeException;
|
| 18 | +use TypeError; |
18 | 19 | use function array_map;
|
19 | 20 | use function array_merge;
|
20 | 21 | use function array_unshift;
|
21 | 22 | use function assert;
|
| 23 | +use function func_get_arg; |
| 24 | +use function func_num_args; |
| 25 | +use function gettype; |
22 | 26 | use function is_array;
|
| 27 | +use function is_bool; |
23 | 28 | use function sprintf;
|
24 | 29 |
|
25 | 30 | /**
|
@@ -214,36 +219,63 @@ public function geoNear($x, $y = null) : Stage\GeoNear
|
214 | 219 | return $stage;
|
215 | 220 | }
|
216 | 221 |
|
| 222 | + // phpcs:disable Squiz.Commenting.FunctionComment.ExtraParamComment |
217 | 223 | /**
|
218 | 224 | * Returns the assembled aggregation pipeline
|
219 | 225 | *
|
| 226 | + * @param bool $applyFilters Whether to apply filters on the aggregation |
| 227 | + * pipeline stage |
| 228 | + * |
220 | 229 | * For pipelines where the first stage is a $geoNear stage, it will apply
|
221 | 230 | * the document filters and discriminator queries to the query portion of
|
222 | 231 | * the geoNear operation. For all other pipelines, it prepends a $match stage
|
223 | 232 | * containing the required query.
|
| 233 | + * |
| 234 | + * For aggregation pipelines that will be nested (e.g. in a facet stage), |
| 235 | + * you should not apply filters as this may cause wrong results to be |
| 236 | + * given. |
224 | 237 | */
|
225 |
| - public function getPipeline() : array |
| 238 | + // phpcs:enable Squiz.Commenting.FunctionComment.ExtraParamComment |
| 239 | + public function getPipeline(/* bool $applyFilters = true */) : array |
226 | 240 | {
|
| 241 | + $applyFilters = func_num_args() > 0 ? func_get_arg(0) : true; |
| 242 | + |
| 243 | + if (! is_bool($applyFilters)) { |
| 244 | + throw new TypeError(sprintf( |
| 245 | + 'Argument 1 passed to %s must be of the type bool, %s given', |
| 246 | + __METHOD__, |
| 247 | + gettype($applyFilters) |
| 248 | + )); |
| 249 | + } |
| 250 | + |
227 | 251 | $pipeline = array_map(
|
228 | 252 | static function (Stage $stage) {
|
229 | 253 | return $stage->getExpression();
|
230 | 254 | },
|
231 | 255 | $this->stages
|
232 | 256 | );
|
233 | 257 |
|
234 |
| - if ($this->getStage(0) instanceof Stage\GeoNear) { |
235 |
| - $pipeline[0]['$geoNear']['query'] = $this->applyFilters($pipeline[0]['$geoNear']['query']); |
236 |
| - } elseif ($this->getStage(0) instanceof Stage\IndexStats) { |
| 258 | + if ($this->getStage(0) instanceof Stage\IndexStats) { |
237 | 259 | // Don't apply any filters when using an IndexStats stage: since it
|
238 | 260 | // needs to be the first pipeline stage, prepending a match stage
|
239 | 261 | // with discriminator information will not work
|
240 | 262 |
|
| 263 | + $applyFilters = false; |
| 264 | + } |
| 265 | + |
| 266 | + if (! $applyFilters) { |
241 | 267 | return $pipeline;
|
242 |
| - } else { |
243 |
| - $matchExpression = $this->applyFilters([]); |
244 |
| - if ($matchExpression !== []) { |
245 |
| - array_unshift($pipeline, ['$match' => $matchExpression]); |
246 |
| - } |
| 268 | + } |
| 269 | + |
| 270 | + if ($this->getStage(0) instanceof Stage\GeoNear) { |
| 271 | + $pipeline[0]['$geoNear']['query'] = $this->applyFilters($pipeline[0]['$geoNear']['query']); |
| 272 | + |
| 273 | + return $pipeline; |
| 274 | + } |
| 275 | + |
| 276 | + $matchExpression = $this->applyFilters([]); |
| 277 | + if ($matchExpression !== []) { |
| 278 | + array_unshift($pipeline, ['$match' => $matchExpression]); |
247 | 279 | }
|
248 | 280 |
|
249 | 281 | return $pipeline;
|
|
0 commit comments