Completed
Push — master ( e3199e...dd66f1 )
by Nate
08:31 queued 06:54
created

ModelSave::save()   B

Complexity

Conditions 6
Paths 14

Size

Total Lines 55
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 55
ccs 0
cts 38
cp 0
rs 8.7752
c 0
b 0
f 0
cc 6
eloc 29
nc 14
nop 4
crap 42

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipboxfactory/craft-ember/blob/master/LICENSE
6
 * @link       https://github.com/flipboxfactory/craft-ember
7
 */
8
9
namespace flipbox\ember\services\traits;
10
11
use Craft;
12
use craft\events\ModelEvent;
13
use flipbox\ember\interfaces\IdAttributeInterface;
14
use flipbox\ember\models\Model;
15
use yii\db\ActiveRecord as Record;
16
17
/**
18
 * @author Flipbox Factory <[email protected]>
19
 * @since 1.0.0
20
 */
21
trait ModelSave
22
{
23
    /*******************************************
24
     * ABSTRACTS
25
     *******************************************/
26
27
    /**
28
     * @param Model $model
29
     * @param bool $mirrorScenario
30
     * @return Record
31
     */
32
    abstract protected function modelToRecord(Model $model, bool $mirrorScenario = true): Record;
33
34
    /**
35
     * @param Model $model
36
     * @return bool
37
     */
38
    abstract protected function isNew(Model $model): bool;
39
40
    /*******************************************
41
     * SAVE
42
     *******************************************/
43
44
    /**
45
     * @param Model $model
46
     * @param bool $runValidation
47
     * @param null $attributes
48
     * @param bool $mirrorScenario
49
     * @return bool
50
     * @throws \Exception
51
     */
52
    public function save(Model $model, bool $runValidation = true, $attributes = null, bool $mirrorScenario = true)
53
    {
54
        $isNew = $this->isNew($model);
55
56
        // a 'beforeSave' event
57
        if (!$this->beforeSave($model, $isNew)) {
58
            return false;
59
        }
60
61
        // Create event
62
        $event = new ModelEvent([
63
            'isNew' => $isNew
64
        ]);
65
66
        // Db transaction
67
        $transaction = Craft::$app->getDb()->beginTransaction();
68
69
        try {
70
            // The 'before' event
71
            if (!$model->beforeSave($event)) {
72
                $transaction->rollBack();
73
                return false;
74
            }
75
76
            $record = $this->modelToRecord($model, $mirrorScenario);
77
78
            // Insert record
79
            if (!$record->save($runValidation, $attributes)) {
80
                $model->addErrors($record->getErrors());
81
                $transaction->rollBack();
82
                return false;
83
            }
84
85
            // Transfer attributes to model
86
            $this->transferFromRecord(
87
                $model,
88
                $record,
89
                $isNew
90
            );
91
92
            // The 'after' event
93
            if (!$model->afterSave($event)) {
94
                $transaction->rollBack();
95
                return false;
96
            }
97
        } catch (\Exception $e) {
98
            $transaction->rollBack();
99
100
            throw $e;
101
        }
102
103
        $transaction->commit();
104
        $this->afterSave($model, $isNew);
105
        return true;
106
    }
107
108
    /**
109
     * @param Model $model
110
     * @param bool $isNew
111
     * @return bool
112
     */
113
    protected function beforeSave(Model $model, bool $isNew): bool
114
    {
115
        return true;
116
    }
117
118
    /**
119
     * @param Model $model
120
     * @param bool $isNew
121
     */
122
    protected function afterSave(Model $model, bool $isNew)
123
    {
124
125
        Craft::info(sprintf(
126
            "Model '%s' was saved successfully.",
127
            (string)get_class($model)
128
        ), __METHOD__);
129
    }
130
131
    /**
132
     * @param Model $model
133
     * @param Record $record
134
     * @param bool $isNew
135
     * @return void
136
     */
137
    protected function transferFromRecord(Model $model, Record $record, bool $isNew)
138
    {
139
        if ($isNew) {
140
            if ($model instanceof IdAttributeInterface && $record instanceof IdAttributeInterface) {
141
                $model->setId($record->getId());
142
            }
143
        }
144
145
        $this->transferAuditAttributes($model, $record, $isNew);
146
    }
147
148
    /**
149
     * @param Model $model
150
     * @param Record $record
151
     * @param bool $isNew
152
     */
153
    protected function transferAuditAttributes(Model $model, Record $record, bool $isNew)
154
    {
155
        if ($isNew) {
156
            if ($record->hasAttribute('dateCreated')) {
157
                $model->setDateCreated($record->getAttribute('dateCreated'));
158
            }
159
160
            if ($record->hasAttribute('uid')) {
161
                $model->uid = $record->getAttribute('uid');
162
            }
163
        }
164
165
        if ($record->hasAttribute('dateUpdated')) {
166
            $model->setDateUpdated($record->getAttribute('dateUpdated'));
167
        }
168
    }
169
}
170