|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* @copyright Copyright (c) Flipbox Digital Limited |
|
5
|
|
|
* @license https://flipboxfactory.com/software/patron/license |
|
6
|
|
|
* @link https://www.flipboxfactory.com/software/patron/ |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
namespace flipbox\patron\records\traits; |
|
10
|
|
|
|
|
11
|
|
|
use Craft; |
|
12
|
|
|
use craft\helpers\ArrayHelper; |
|
13
|
|
|
use flipbox\ember\helpers\ObjectHelper; |
|
14
|
|
|
use flipbox\ember\helpers\QueryHelper; |
|
15
|
|
|
use flipbox\ember\records\traits\ActiveRecord as ActiveRecordTrait; |
|
16
|
|
|
use yii\db\ActiveQueryInterface; |
|
17
|
|
|
use yii\db\ActiveRecord; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* @author Flipbox Factory <[email protected]> |
|
21
|
|
|
* @since 1.0.0 |
|
22
|
|
|
*/ |
|
23
|
|
|
trait RelatedEnvironmentsAttribute |
|
24
|
|
|
{ |
|
25
|
|
|
use ActiveRecordTrait; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* @var bool |
|
29
|
|
|
*/ |
|
30
|
|
|
public $autoSaveEnvironments = true; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* Environments that are temporarily set during the save process |
|
34
|
|
|
* |
|
35
|
|
|
* @var null|array |
|
36
|
|
|
*/ |
|
37
|
|
|
private $insertEnvironments; |
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* @return string |
|
41
|
|
|
*/ |
|
42
|
|
|
abstract protected static function environmentRecordClass(): string; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* @param array $config |
|
46
|
|
|
* @return array |
|
47
|
|
|
*/ |
|
48
|
|
|
protected abstract function prepareEnvironmentRecordConfig(array $config = []): array; |
|
49
|
|
|
|
|
50
|
|
|
/** |
|
51
|
|
|
* @return ActiveQueryInterface |
|
52
|
|
|
*/ |
|
53
|
|
|
protected abstract function environmentRelationshipQuery(): ActiveQueryInterface; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* Get all of the associated environments. |
|
57
|
|
|
* |
|
58
|
|
|
* @param array $config |
|
59
|
|
|
* @return \yii\db\ActiveQueryInterface|\yii\db\ActiveQuery |
|
60
|
|
|
*/ |
|
61
|
|
|
public function getEnvironments(array $config = []) |
|
62
|
|
|
{ |
|
63
|
|
|
$query = $this->environmentRelationshipQuery(); |
|
64
|
|
|
|
|
65
|
|
|
if (!empty($config)) { |
|
66
|
|
|
QueryHelper::configure( |
|
67
|
|
|
$query, |
|
68
|
|
|
$config |
|
69
|
|
|
); |
|
70
|
|
|
} |
|
71
|
|
|
|
|
72
|
|
|
return $query; |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* @param array $environments |
|
77
|
|
|
* @return $this |
|
78
|
|
|
*/ |
|
79
|
|
|
public function setEnvironments(array $environments = []) |
|
80
|
|
|
{ |
|
81
|
|
|
$environments = array_filter($environments); |
|
82
|
|
|
|
|
83
|
|
|
// Do nothing |
|
84
|
|
|
if (empty($environments) && !$this->isRelationPopulated('environments')) { |
|
85
|
|
|
return $this; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
$currentEnvironments = ArrayHelper::index($this->environments, 'environment'); |
|
|
|
|
|
|
89
|
|
|
|
|
90
|
|
|
$records = []; |
|
91
|
|
|
foreach ($environments as $key => $environment) { |
|
92
|
|
|
$environment = $this->resolveEnvironmentNEW($environment); |
|
93
|
|
|
|
|
94
|
|
|
// Already set ? |
|
95
|
|
|
if (array_key_exists($environment->getAttribute('environment'), $currentEnvironments)) { |
|
96
|
|
|
continue; |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
$records[] = $environment; |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
$this->populateRelation('environments', $records); |
|
|
|
|
|
|
103
|
|
|
return $this; |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
/** |
|
107
|
|
|
* @param $environment |
|
108
|
|
|
* @return ActiveRecord |
|
109
|
|
|
*/ |
|
110
|
|
|
protected function resolveEnvironmentNEW($environment) |
|
111
|
|
|
{ |
|
112
|
|
|
$class = static::environmentRecordClass(); |
|
113
|
|
|
|
|
114
|
|
|
if (is_subclass_of($environment, $class)) { |
|
115
|
|
|
return $environment; |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
// New record |
|
119
|
|
|
$record = new $class; |
|
120
|
|
|
|
|
121
|
|
|
// Force an array |
|
122
|
|
|
if (is_string($environment)) { |
|
123
|
|
|
$environment = ['environment' => $environment]; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
if (!is_array($environment)) { |
|
127
|
|
|
$environment = ArrayHelper::toArray($environment, [], false); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
/** @noinspection PhpIncompatibleReturnTypeInspection */ |
|
131
|
|
|
return ObjectHelper::populate( |
|
132
|
|
|
$record, |
|
133
|
|
|
$this->prepareEnvironmentRecordConfig($environment) |
|
134
|
|
|
); |
|
135
|
|
|
} |
|
136
|
|
|
|
|
137
|
|
|
/** |
|
138
|
|
|
* @param bool $force |
|
139
|
|
|
* @return bool |
|
140
|
|
|
* @throws \Throwable |
|
141
|
|
|
* @throws \yii\db\StaleObjectException |
|
142
|
|
|
*/ |
|
143
|
|
|
protected function saveEnvironments(bool $force = false): bool |
|
144
|
|
|
{ |
|
145
|
|
|
if ($force === false && $this->autoSaveEnvironments !== true) { |
|
146
|
|
|
return true; |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
$successful = true; |
|
150
|
|
|
|
|
151
|
|
|
/** @var ActiveRecord[] $allRecords */ |
|
152
|
|
|
$allRecords = $this->getEnvironments() |
|
153
|
|
|
->indexBy('environment') |
|
154
|
|
|
->all(); |
|
155
|
|
|
|
|
156
|
|
|
/** @var ActiveRecord $model */ |
|
157
|
|
|
foreach ($this->environments as $model) { |
|
|
|
|
|
|
158
|
|
|
ArrayHelper::remove($allRecords, $model->getAttribute('environment')); |
|
159
|
|
|
|
|
160
|
|
|
if (!$model->save()) { |
|
161
|
|
|
$successful = false; |
|
162
|
|
|
|
|
163
|
|
|
$error = Craft::t( |
|
164
|
|
|
'patron', |
|
165
|
|
|
"Couldn't save environment due to validation errors:" |
|
166
|
|
|
); |
|
167
|
|
|
foreach ($model->getFirstErrors() as $attributeError) { |
|
168
|
|
|
$error .= "\n- " . Craft::t('patron', $attributeError); |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
$this->addError('environments', $error); |
|
|
|
|
|
|
172
|
|
|
} |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
// Delete old records |
|
176
|
|
|
foreach ($allRecords as $record) { |
|
177
|
|
|
$record->delete(); |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
|
|
return $successful; |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
/******************************************* |
|
184
|
|
|
* EVENTS |
|
185
|
|
|
*******************************************/ |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* @inheritdoc |
|
189
|
|
|
*/ |
|
190
|
|
|
protected function beforeSaveEnvironments($insert): bool |
|
191
|
|
|
{ |
|
192
|
|
|
if ($insert !== true || |
|
193
|
|
|
$this->isRelationPopulated('environments') !== true || |
|
194
|
|
|
$this->autoSaveEnvironments !== true |
|
195
|
|
|
) { |
|
196
|
|
|
return true; |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
$this->insertEnvironments = $this->environments; |
|
|
|
|
|
|
200
|
|
|
|
|
201
|
|
|
return true; |
|
202
|
|
|
} |
|
203
|
|
|
|
|
204
|
|
|
/** |
|
205
|
|
|
* We're extracting the environments that may have been explicitly set on the record. When the 'id' |
|
206
|
|
|
* attribute is updated, it removes any associated relationships. |
|
207
|
|
|
* |
|
208
|
|
|
* @inheritdoc |
|
209
|
|
|
* @throws \Throwable |
|
210
|
|
|
*/ |
|
211
|
|
|
protected function insertInternalEnvironments($attributes = null) |
|
212
|
|
|
{ |
|
213
|
|
|
if (null === $this->insertEnvironments) { |
|
214
|
|
|
return true; |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
$this->setEnvironments($this->insertEnvironments); |
|
218
|
|
|
$this->insertEnvironments = null; |
|
219
|
|
|
|
|
220
|
|
|
return $this->upsertInternal($attributes); |
|
|
|
|
|
|
221
|
|
|
} |
|
222
|
|
|
} |
|
223
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.