diff --git a/src/Model/Scope.php b/src/Model/Scope.php index 04d974720..3a13f751b 100644 --- a/src/Model/Scope.php +++ b/src/Model/Scope.php @@ -89,6 +89,15 @@ public function addCondition($field, $operator = null, $value = null) return $this; } + protected function setSystem(bool $system = true) + { + foreach ($this->elements as $nestedCondition) { + $nestedCondition->setSystem($system && $this->isAnd()); + } + + return $this; + } + /** * Return array of nested conditions. * diff --git a/src/Model/Scope/AbstractScope.php b/src/Model/Scope/AbstractScope.php index 0e3bca34e..2257e2ce5 100644 --- a/src/Model/Scope/AbstractScope.php +++ b/src/Model/Scope/AbstractScope.php @@ -33,11 +33,19 @@ protected function init(): void $this->_init(); + // always set system flag if condition added to another condition + $this->setSystem($owner instanceof RootScope); + $this->onChangeModel(); } abstract protected function onChangeModel(): void; + /** + * @return $this + */ + abstract protected function setSystem(bool $system = true); + /** * Get the model this condition is associated with. */ diff --git a/src/Model/Scope/Condition.php b/src/Model/Scope/Condition.php index 6b32133cc..dfeaf6ffe 100644 --- a/src/Model/Scope/Condition.php +++ b/src/Model/Scope/Condition.php @@ -26,6 +26,8 @@ class Condition extends AbstractScope /** @var mixed */ public $value; + protected bool $system = false; + public const OPERATOR_EQUALS = '='; public const OPERATOR_DOESNOT_EQUAL = '!='; public const OPERATOR_GREATER = '>'; @@ -149,6 +151,13 @@ public function __construct($key, $operator = null, $value = null) } } + protected function setSystem(bool $system = true) + { + $this->system = $system; + + return $this; + } + protected function onChangeModel(): void { $model = $this->getModel(); @@ -156,10 +165,7 @@ protected function onChangeModel(): void // if we have a definitive equal condition set the value as default value for field // new records will automatically get this value assigned for the field // TODO: fix when condition is part of OR scope - if ($this->operator === self::OPERATOR_EQUALS && !is_array($this->value) - && !$this->value instanceof Expressionable - && !$this->value instanceof Persistence\Array_\Action // needed to pass hintable tests - ) { + if ($this->system && $this->isDefiniteValue()) { // key containing '/' means chained references and it is handled in toQueryArguments method $field = $this->key; if (is_string($field) && !str_contains($field, '/')) { @@ -262,6 +268,16 @@ public function isEmpty(): bool return array_filter([$this->key, $this->operator, $this->value]) ? false : true; } + /** + * Checks if condition sets a definitive scalar value for a field. + */ + protected function isDefiniteValue(): bool + { + return $this->operator === self::OPERATOR_EQUALS && !is_array($this->value) + && !$this->value instanceof Expressionable + && !$this->value instanceof Persistence\Array_\Action; // needed to pass hintable tests + } + public function clear() { $this->key = null; // @phpstan-ignore-line