Skip to content

Commit 231547f

Browse files
authored
Fix HasOneSql their field update hook (#1037)
1 parent f31722f commit 231547f

File tree

1 file changed

+50
-62
lines changed

1 file changed

+50
-62
lines changed

src/Reference/HasOneSql.php

+50-62
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,50 @@
99

1010
class HasOneSql extends HasOne
1111
{
12+
/**
13+
* @param ($theirFieldIsTitle is true ? null : string) $theirFieldName
14+
*/
15+
private function _addField(string $fieldName, bool $theirFieldIsTitle, ?string $theirFieldName, array $defaults): SqlExpressionField
16+
{
17+
$ourModel = $this->getOurModel(null);
18+
19+
$fieldExpression = $ourModel->addExpression($fieldName, array_merge([
20+
'expr' => function (Model $ourModel) use ($theirFieldIsTitle, $theirFieldName) {
21+
$theirModel = $ourModel->refLink($this->link);
22+
if ($theirFieldIsTitle) {
23+
$theirFieldName = $theirModel->title_field;
24+
}
25+
26+
// remove order if we just select one field from hasOne model, needed for Oracle
27+
return $theirModel->action('field', [$theirFieldName])->reset('order');
28+
},
29+
], $defaults, [
30+
// to be able to change field, but not save it
31+
// afterSave hook will take care of the rest
32+
'read_only' => false,
33+
'never_save' => true,
34+
]));
35+
36+
$this->onHookToOurModel($ourModel, Model::HOOK_BEFORE_SAVE, function (Model $ourModel) use ($fieldName, $theirFieldIsTitle, $theirFieldName) {
37+
// if field is changed, but reference ID field (our_field)
38+
// is not changed, then update reference ID field value
39+
if ($ourModel->isDirty($fieldName) && !$ourModel->isDirty($this->our_field)) {
40+
$theirModel = $this->createTheirModel();
41+
if ($theirFieldIsTitle) {
42+
$theirFieldName = $theirModel->title_field;
43+
}
44+
45+
$theirModel->addCondition($theirFieldName, $ourModel->get($fieldName));
46+
$ourModel->set($this->getOurFieldName(), $theirModel->loadOne()->getId());
47+
if (!$theirFieldIsTitle) { // why for non-title only?
48+
$ourModel->_unset($fieldName);
49+
}
50+
}
51+
}, [], 20);
52+
53+
return $fieldExpression;
54+
}
55+
1256
/**
1357
* Creates expression which sub-selects a field inside related model.
1458
*/
@@ -28,35 +72,7 @@ public function addField(string $fieldName, string $theirFieldName = null, array
2872
$defaults['caption'] ??= $refModelField->caption;
2973
$defaults['ui'] ??= $refModelField->ui;
3074

31-
$fieldExpression = $ourModel->addExpression($fieldName, array_merge(
32-
[
33-
'expr' => function (Model $ourModel) use ($theirFieldName) {
34-
// remove order if we just select one field from hasOne model
35-
// that is mandatory for Oracle
36-
return $ourModel->refLink($this->link)->action('field', [$theirFieldName])->reset('order');
37-
},
38-
],
39-
$defaults,
40-
[
41-
// to be able to change field, but not save it
42-
// afterSave hook will take care of the rest
43-
'read_only' => false,
44-
'never_save' => true,
45-
]
46-
));
47-
48-
// Will try to execute last
49-
$this->onHookToOurModel($ourModel, Model::HOOK_BEFORE_SAVE, function (Model $ourModel) use ($fieldName, $theirFieldName) {
50-
// if field is changed, but reference ID field (our_field)
51-
// is not changed, then update reference ID field value
52-
if ($ourModel->isDirty($fieldName) && !$ourModel->isDirty($this->our_field)) {
53-
$theirModel = $this->createTheirModel();
54-
55-
$theirModel->addCondition($theirFieldName, $ourModel->get($fieldName));
56-
$ourModel->set($this->getOurFieldName(), $theirModel->action('field', [$theirModel->id_field]));
57-
$ourModel->_unset($fieldName);
58-
}
59-
}, [], 20);
75+
$fieldExpression = $this->_addField($fieldName, false, $theirFieldName, $defaults);
6076

6177
return $fieldExpression;
6278
}
@@ -127,47 +143,19 @@ public function ref(Model $ourModel, array $defaults = []): Model
127143
* $order->hasOne('user_id', 'User')->addTitle();
128144
*
129145
* This will add expression 'user' equal to ref('user_id')['name'];
130-
*
131-
* This method returns newly created expression field.
132146
*/
133147
public function addTitle(array $defaults = []): SqlExpressionField
134148
{
135149
$ourModel = $this->getOurModel(null);
136150

137151
$fieldName = $defaults['field'] ?? preg_replace('~_(' . preg_quote($ourModel->id_field, '~') . '|id)$~', '', $this->link);
138152

139-
$fieldExpression = $ourModel->addExpression($fieldName, array_replace_recursive(
140-
[
141-
'expr' => function (Model $ourModel) {
142-
$theirModel = $ourModel->refLink($this->link);
143-
144-
return $theirModel->action('field', [$theirModel->title_field])->reset('order');
145-
},
146-
'type' => null,
147-
'ui' => ['editable' => false, 'visible' => true],
148-
],
149-
$defaults,
150-
[
151-
// to be able to change title field, but not save it
152-
// afterSave hook will take care of the rest
153-
'read_only' => false,
154-
'never_save' => true,
155-
]
156-
));
157-
158-
// Will try to execute last
159-
$this->onHookToOurModel($ourModel, Model::HOOK_BEFORE_SAVE, function (Model $ourModel) use ($fieldName) {
160-
// if title field is changed, but reference ID field (our_field)
161-
// is not changed, then update reference ID field value
162-
if ($ourModel->isDirty($fieldName) && !$ourModel->isDirty($this->our_field)) {
163-
$theirModel = $this->createTheirModel();
164-
165-
$theirModel->addCondition($theirModel->title_field, $ourModel->get($fieldName));
166-
$ourModel->set($this->getOurFieldName(), $theirModel->action('field', [$theirModel->id_field]));
167-
}
168-
}, [], 20);
153+
$fieldExpression = $this->_addField($fieldName, true, null, array_merge_recursive([
154+
'type' => null,
155+
'ui' => ['editable' => false, 'visible' => true],
156+
], $defaults));
169157

170-
// Set ID field as not visible in grid by default
158+
// set ID field as not visible in grid by default
171159
if (!array_key_exists('visible', $this->getOurField()->ui)) {
172160
$this->getOurField()->ui['visible'] = false;
173161
}

0 commit comments

Comments
 (0)