Completed
Push — develop ( 45ab37...1fc05f )
by Nate
16:44
created

prepareEnvironmentRecordConfig()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
c 0
b 0
f 0
nc 1
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');
0 ignored issues
show
Bug introduced by
The property environments does not seem to exist. Did you mean autoSaveEnvironments?

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.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like populateRelation() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The property environments does not seem to exist. Did you mean autoSaveEnvironments?

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.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like addError() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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;
0 ignored issues
show
Bug introduced by
The property environments does not seem to exist. Did you mean autoSaveEnvironments?

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.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like upsertInternal() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
221
    }
222
}
223