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

ProviderInstance::beforeSave()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 6
cp 0
rs 9.8666
c 0
b 0
f 0
cc 3
nc 4
nop 1
crap 12
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;
10
11
use Craft;
12
use flipbox\ember\helpers\ModelHelper;
13
use flipbox\ember\records\ActiveRecordWithId;
14
use flipbox\patron\db\ProviderInstanceActiveQuery;
15
use flipbox\patron\helpers\ProviderHelper;
16
use flipbox\patron\Patron;
17
use flipbox\patron\providers\SettingsInterface;
18
use flipbox\patron\validators\ProviderSettings as ProviderSettingsValidator;
19
use yii\db\ActiveQueryInterface;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.0.0
24
 *
25
 * @property string $clientId
26
 * @property string $clientSecret
27
 * @property array $settings
28
 * @property int $providerId
29
 * @property Provider $provider
30
 * @property ProviderEnvironment[] $environments
31
 */
32
class ProviderInstance extends ActiveRecordWithId
33
{
34
    use traits\ProviderAttribute,
35
        traits\RelatedEnvironmentsAttribute;
36
37
    /**
38
     * The table alias
39
     */
40
    const TABLE_ALIAS = 'patron_provider_instances';
41
42
    /**
43
     * The length of the identifier
44
     */
45
    const CLIENT_ID_LENGTH = 100;
46
47
    /**
48
     * The length of the secret
49
     */
50
    const CLIENT_SECRET_LENGTH = 255;
51
52
    /**
53
     * @var SettingsInterface
54
     */
55
    private $providerSettings;
56
57
    /**
58
     * @inheritdoc
59
     */
60
    protected $getterPriorityAttributes = [
61
        'providerId'
62
    ];
63
64
    /**
65
     * @inheritdoc
66
     * @return ProviderInstanceActiveQuery
67
     * @throws \yii\base\InvalidConfigException
68
     */
69
    public static function find()
70
    {
71
        /** @noinspection PhpIncompatibleReturnTypeInspection */
72
        return Craft::createObject(ProviderInstanceActiveQuery::class, [get_called_class()]);
73
    }
74
75
    /**
76
     * @inheritdoc
77
     */
78
    public function rules()
79
    {
80
        return array_merge(
81
            parent::rules(),
82
            $this->providerRules(),
83
            [
84
                [
85
                    [
86
                        'clientId'
87
                    ],
88
                    'string',
89
                    'max' => static::CLIENT_ID_LENGTH
90
                ],
91
                [
92
                    [
93
                        'clientSecret'
94
                    ],
95
                    'string',
96
                    'max' => static::CLIENT_SECRET_LENGTH
97
                ],
98
                [
99
                    [
100
                        'providerId',
101
                        'clientId'
102
                    ],
103
                    'required'
104
                ],
105
                [
106
                    [
107
                        'settings'
108
                    ],
109
                    ProviderSettingsValidator::class
110
                ],
111
                [
112
                    [
113
                        'clientId',
114
                        'clientSecret',
115
                        'settings'
116
                    ],
117
                    'safe',
118
                    'on' => [
119
                        ModelHelper::SCENARIO_DEFAULT
120
                    ]
121
                ]
122
            ]
123
        );
124
    }
125
126
127
    /*******************************************
128
     * EVENTS
129
     *******************************************/
130
131
    /**
132
     * @inheritdoc
133
     */
134
    public function afterFind()
135
    {
136
        if ($this->clientSecret) {
137
            $this->clientSecret = ProviderHelper::decryptClientSecret($this->clientSecret);
138
        }
139
140
        parent::afterFind();
141
    }
142
143
    /**
144
     * @inheritdoc
145
     */
146
    public function beforeSave($insert)
147
    {
148
        if ($this->clientSecret) {
149
            $this->clientSecret = ProviderHelper::encryptClientSecret($this->clientSecret);
150
        }
151
152
        if (!parent::beforeSave($insert)) {
153
            return false;
154
        }
155
156
        return $this->beforeSaveEnvironments($insert);
157
    }
158
159
    /**
160
     * @inheritdoc
161
     * @throws \Throwable
162
     */
163
    public function afterSave($insert, $changedAttributes)
164
    {
165
        if ($this->clientSecret) {
166
            $this->clientSecret = ProviderHelper::decryptClientSecret($this->clientSecret);
167
        }
168
169
        parent::afterSave($insert, $changedAttributes);
170
    }
171
172
173
    /*******************************************
174
     * UPDATE / INSERT
175
     *******************************************/
176
177
    /**
178
     * @inheritdoc
179
     * @throws \Throwable
180
     */
181
    protected function insertInternal($attributes = null)
182
    {
183
        if (!parent::insertInternal($attributes)) {
184
            return false;
185
        }
186
187
        return $this->insertInternalEnvironments($attributes);
188
    }
189
190
    /**
191
     * @inheritdoc
192
     * @throws \Throwable
193
     */
194
    protected function updateInternal($attributes = null)
195
    {
196
        if (!parent::updateInternal($attributes)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression parent::updateInternal($attributes) of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
197
            return false;
198
        }
199
200
        return $this->upsertInternal($attributes);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->upsertInternal($attributes); (boolean) is incompatible with the return type of the parent method yii\db\BaseActiveRecord::updateInternal of type false|integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
201
    }
202
203
    /**
204
     * @param null $attributes
205
     * @return bool
206
     * @throws \Throwable
207
     * @throws \yii\db\StaleObjectException
208
     */
209
    protected function upsertInternal($attributes = null): bool
210
    {
211
        if (empty($attributes)) {
212
            return $this->saveEnvironments();
213
        }
214
215
        if (array_key_exists('environments', $attributes)) {
216
            return $this->saveEnvironments(true);
217
        }
218
219
        return true;
220
    }
221
222
223
    /*******************************************
224
     * ENVIRONMENTS
225
     *******************************************/
226
227
    /**
228
     * @inheritdoc
229
     */
230
    protected static function environmentRecordClass(): string
231
    {
232
        return ProviderEnvironment::class;
233
    }
234
235
    /**
236
     * @inheritdoc
237
     */
238
    protected function prepareEnvironmentRecordConfig(array $config = []): array
239
    {
240
        $config['instance'] = $this;
241
        return $config;
242
    }
243
244
    /**
245
     * @inheritdoc
246
     */
247
    protected function environmentRelationshipQuery(): ActiveQueryInterface
248
    {
249
        return $this->hasMany(
250
            static::environmentRecordClass(),
251
            ['instanceId' => 'id']
252
        );
253
    }
254
255
    /**
256
     * @return string
257
     * @throws \yii\base\InvalidConfigException
258
     */
259
    public function getHtml(): string
260
    {
261
        return $this->getProviderSettings()->inputHtml();
262
    }
263
264
    /**
265
     * @return SettingsInterface
266
     * @throws \yii\base\InvalidConfigException
267
     */
268
    public function getProviderSettings(): SettingsInterface
269
    {
270
        if (!$this->providerSettings instanceof SettingsInterface) {
271
            $this->providerSettings = Patron::getInstance()->getProviderSettings()->resolveSettings(
272
                $this->getProvider(),
273
                $this->settings
274
            );
275
        }
276
277
        return $this->providerSettings;
278
    }
279
}
280