atk4 / data

Data Access PHP Framework for SQL & high-latency databases
https://atk4-data.readthedocs.io
MIT License
270 stars 46 forks source link

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

Open mvorisek opened 3 years ago

mvorisek commented 3 years ago

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

DarkSide666 commented 3 years ago

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.

mvorisek commented 3 years ago

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)

georgehristov commented 3 years ago

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.

mvorisek commented 3 years ago

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?

georgehristov commented 3 years ago

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]);
mvorisek commented 3 years ago

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?

georgehristov commented 3 years ago

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?

mvorisek commented 3 years ago

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:

georgehristov commented 3 years ago

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

mvorisek commented 3 years ago

we can not - scope can be further modified

georgehristov commented 3 years ago

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.

mvorisek commented 3 years ago

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?

georgehristov commented 3 years ago

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)?
mvorisek commented 3 years ago

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 ;-)

georgehristov commented 3 years ago

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

mvorisek commented 3 years ago

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

georgehristov commented 3 years ago

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:

mvorisek commented 3 years ago

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 commented 3 years ago

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 commented 1 year ago

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.