data icon indicating copy to clipboard operation
data copied to clipboard

Do not mutate Field::default/system property in scope condition

Open mvorisek opened this issue 4 years ago • 20 comments

see https://github.com/atk4/data/pull/660/files/e1e0ae7947f60c268245e51ca12eafa5a45810dd#diff-d11d2f7d35e15c2e79f43737267e1c00

and related code: https://github.com/atk4/data/blob/2f89724cfd4fd8c923ffc1761a96ac218591e9ca/src/Model/Scope/Condition.php#L101-L115

mvorisek avatar Jul 23 '20 18:07 mvorisek

It's how it was before - BC way of doing things. But of course we should revise that and see if that's still good approach or need to move that somehow to UI only. In case of nested conditions this start to look less usable.

DarkSide666 avatar Jul 23 '20 20:07 DarkSide666

you are right, this is actually hide field (because of system) with nested conditons like (a > 5 or (a = 5)) (the code will trigger becauseof = - but in whole complex it is not only one possible value)

mvorisek avatar Jul 23 '20 21:07 mvorisek

It can be implemented to be set to the value only when the condition is definitive - all parent scopes up to root scope have AND junction.

We have to look into alternatives to set it as well.

georgehristov avatar Jul 24 '20 13:07 georgehristov

one possibility, but this can imply default arguments for API etc., which is not fully correct (too implicit)

I think we should drop it - what code relies on it?

mvorisek avatar Jul 24 '20 13:07 mvorisek

The issue is that this functionality is used on model references. E.g if removed this line (among many others) fails.

$a = new Account($this->db);

$a->save(['name' => 'AIB']);
$a->ref('Payment')->save(['amount' => 10]);

georgehristov avatar Jul 25 '20 12:07 georgehristov

please post PR to discuss more concrete - save() works on either loaded row/ID or a new one, right?

so if this is only a ref issue, we should be addresses there - you mean the issue is that you will otherwise have to set payment_id on a new row?

mvorisek avatar Jul 25 '20 12:07 mvorisek

The issue comes from sub-scoping models like here. So new entries are expected to have the value assigned permanently. The only way I come up is to introduce a separate method on Model to set a condition and default field value. Other ideas?

georgehristov avatar Jul 25 '20 17:07 georgehristov

sub-scoping model

This is quite legit argument - only in this case it can be changed to system

But = equal condition definitely does not imply that.

I think, we have only two options:

  • leave this to the user, so he can set system/default manually (in model init)
  • add protected method addEqualToSystemCondition($field, $value) which will allow only this input and a) call setConditon($field, '=', $value) and b) set the system/default. Name is for discussion.

mvorisek avatar Jul 25 '20 17:07 mvorisek

What we can do is check if condition is definite (all parents have AND junction) and only then set the value as deault and lock the field. This is in the spirit of implemented functionality already.

Quite easy to implement and BC

georgehristov avatar Jul 26 '20 11:07 georgehristov

we can not - scope can be further modified

mvorisek avatar Jul 26 '20 11:07 mvorisek

Question is if that changes the definitiveness of the condition. When adding conditions definitiveness does not change. Only negation can change definitiveness and we can disable negation once scope assigned to a model. Then we dont need RootScope at all. Model can be assigned to owner property.

georgehristov avatar Jul 26 '20 12:07 georgehristov

The only usecase I see is strictly "helpful/simplified logic for conditions creation in model setup"

so I stay firm behind my "two options" - drop completely or allow to define condition with full control - like proposed addEqualToSystemCondition - as to be available at Model level only, it will always add a AND conditon to the whole resulting where.

my question is - what does this approach NOT solve?

mvorisek avatar Jul 26 '20 12:07 mvorisek

to be available at Model level only The logic is for sub-scoping and this devs should be able to achieve inline as well.

$invoice = (clone $document)->addCondition('type', 'invoice');
$invoice->{do whatever};

When adding it should save type invoice as it is now.

what does this approach NOT solve?

  • huge BC-break
  • introduces second slightly different way of sub-scoping which will cause confusion. How to define the difference between addCondition when it is definite and addEqualToSystemCondition (or however we call it)?

georgehristov avatar Jul 26 '20 12:07 georgehristov

How to define the difference between addCondition when it is definite and addEqualToSystemCondition (or however we call it)?

as addEqualToSystemCondition will call addCondition, it behaves 1:1, only with addEqualToSystemCondition there will be side effect of system/default on related field

everything other stays, conditions are not definitive, like now, do basically whatever you want ;-)

mvorisek avatar Jul 26 '20 13:07 mvorisek

I agree with you. We can add BC support purely in Model::addCondition method. Question remains about the name. I would say Model::addSystemCondition

georgehristov avatar Jul 27 '20 10:07 georgehristov

We can add BC support purely in Model::addCondition method.

this and the sensetence below are two different things, right? :) addCondition should not support this, you have to explictly use the special method

Question remains about the name. I would say Model::addSystemCondition

Something liek that, I tried to stress is MUST ALWAYS BE with = operator and we will support only $field, $value signature

for data/ui, we can dump first which functions/usages were using this

mvorisek avatar Jul 27 '20 10:07 mvorisek

Solution with a method in Model does not work as this needs to be triggered on model change (in case of clones or copying of scopes).

I believe the best and cleanest solution is:

  • lock negation on scopes once model assigned
  • on change of model check if condition is definitive (has '=' scalar value + all parent scopes are AND) and then set field default value and as system field
  • remove RootScope class as it will not be needed

georgehristov avatar Jul 27 '20 14:07 georgehristov

Model does not work as this needs to be triggered on model change

absolutely not - you use addEqualsToSystemCondition and it sets immediatelly, very predictable and fully controlled

mvorisek avatar Jul 27 '20 14:07 mvorisek

I understand the idea of this, for modelling, if and only if a condition is definitive (is always valid), default value can be set, but:

a) PK/ID should never be set (fixed in https://github.com/atk4/data/pull/862/commits/b24d858a2583d382617dd4ee5896ed1a90782959) b) it must never mutate another modelling chain - we probably must support model of model

mvorisek avatar Apr 29 '21 17:04 mvorisek

as mentioned in https://github.com/atk4/data/issues/662#issuecomment-663545433, we need to check if definitive definitely :)

the current design seems to work well, but the problem is when a condition is removed, is this is wanted to be fully supported, we should track the default/system changes from definitive conditions and revert if the conditions are removed. Complicated, but removed conditions should revert the model state completely.

Another issue is removed conditions but model used before for traversal /w materialized conditions. But I belive this is fine, as the traversal does not store the originating model.

mvorisek avatar Oct 01 '22 09:10 mvorisek