Skip to content

Commit 2cc821a

Browse files
committed
Fix scope application logic
1 parent 7283a1e commit 2cc821a

1 file changed

Lines changed: 48 additions & 14 deletions

File tree

src/Query/Model/Builder.php

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,17 @@ protected function callScope(callable $scope, array $parameters = []): static
133133
{
134134
array_unshift($parameters, $this);
135135

136-
return $scope(...array_values($parameters)) ?? $this;
136+
$result = null;
137+
138+
$scopeFilter = $this->captureScopeFilters(function () use ($scope, $parameters, &$result) {
139+
$result = $scope(...$parameters) ?? $this;
140+
});
141+
142+
if ($scopeFilter) {
143+
$this->query->addFilter($scopeFilter);
144+
}
145+
146+
return $result;
137147
}
138148

139149
/**
@@ -477,25 +487,49 @@ public function applyScopes(): static
477487
return $this;
478488
}
479489

480-
// Scopes should not be escapable, so we will wrap the
481-
// application of the scopes within a nested query.
482-
$this->where(function (self $query) {
483-
foreach ($this->scopes as $identifier => $scope) {
484-
if (isset($this->appliedScopes[$identifier])) {
485-
continue;
490+
$builder = clone $this;
491+
492+
foreach ($this->scopes as $identifier => $scope) {
493+
if (! isset($builder->scopes[$identifier])) {
494+
continue;
495+
}
496+
497+
if (isset($builder->appliedScopes[$identifier])) {
498+
continue;
499+
}
500+
501+
$builder->callScope(function (self $builder) use ($scope) {
502+
if ($scope instanceof Closure) {
503+
$scope($builder);
486504
}
487505

488506
if ($scope instanceof Scope) {
489-
$scope->apply($query, $this->getModel());
490-
} else {
491-
$scope($this);
507+
$scope->apply($builder, $this->getModel());
492508
}
509+
});
493510

494-
$this->appliedScopes[$identifier] = $scope;
495-
}
496-
});
511+
$builder->appliedScopes[$identifier] = $scope;
512+
}
497513

498-
return $this;
514+
return $builder;
515+
}
516+
517+
/**
518+
* Capture the filters applied while executing the callback.
519+
*/
520+
protected function captureScopeFilters(Closure $callback): ?Filter
521+
{
522+
$originalFilter = $this->query->filter;
523+
524+
$this->query->filter = null;
525+
526+
try {
527+
$callback();
528+
529+
return $this->query->filter;
530+
} finally {
531+
$this->query->filter = $originalFilter;
532+
}
499533
}
500534

501535
/**

0 commit comments

Comments
 (0)