Completed
Push — master ( 5d951f...f67c03 )
by Nate
13:58 queued 11:06
created

Records::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 7
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/organization/license
6
 * @link       https://www.flipboxfactory.com/software/organization/
7
 */
8
9
namespace flipbox\organizations\services;
10
11
use Craft;
12
use flipbox\ember\services\traits\records\Accessor;
13
use flipbox\organizations\events\ChangeStateEvent;
14
use flipbox\organizations\Organizations as OrganizationPlugin;
15
use flipbox\organizations\records\Organization as OrganizationRecord;
16
use yii\base\Component;
17
18
/**
19
 * @author Flipbox Factory <[email protected]>
20
 * @since 1.0.0
21
 *
22
 * @method OrganizationRecord create(array $attributes = [])
23
 * @method OrganizationRecord find($identifier)
24
 * @method OrganizationRecord get($identifier)
25
 * @method OrganizationRecord findByCondition($condition = [])
26
 * @method OrganizationRecord getByCondition($condition = [])
27
 * @method OrganizationRecord findByCriteria($criteria = [])
28
 * @method OrganizationRecord getByCriteria($criteria = [])
29
 * @method OrganizationRecord[] findAllByCondition($condition = [])
30
 * @method OrganizationRecord[] getAllByCondition($condition = [])
31
 * @method OrganizationRecord[] findAllByCriteria($criteria = [])
32
 * @method OrganizationRecord[] getAllByCriteria($criteria = [])
33
 */
34
class Records extends Component
35
{
36
    use Accessor;
37
38
    /**
39
     * @event ChangeStateEvent The event that is triggered before a organization has a custom status change.
40
     *
41
     * You may set [[ChangeStateEvent::isValid]] to `false` to prevent the organization changing the status.
42
     */
43
    const EVENT_BEFORE_STATE_CHANGE = 'beforeStateChange';
44
45
    /**
46
     * @event ChangeStateEvent The event that is triggered after a organization has a custom status change.
47
     *
48
     * You may set [[ChangeStateEvent::isValid]] to `false` to prevent the organization changing the status.
49
     */
50
    const EVENT_AFTER_STATE_CHANGE = 'afterStateChange';
51
52
    /**
53
     * @inheritdoc
54
     */
55
    public function init()
56
    {
57
        $settings = OrganizationPlugin::getInstance()->getSettings();
58
        $this->cacheDuration = $settings->recordsCacheDuration;
59
        $this->cacheDependency = $settings->recordsCacheDependency;
60
61
        parent::init();
62
    }
63
64
    /**
65
     * @inheritdoc
66
     */
67
    public static function recordClass(): string
68
    {
69
        return OrganizationRecord::class;
70
    }
71
72
    /**
73
     * @param OrganizationRecord $record
74
     * @return bool
75
     * @throws \Exception
76
     * @throws \yii\db\Exception
77
     */
78
    public function save(OrganizationRecord $record): bool
79
    {
80
        // Change state w/ events (see below)
81
        $changedState = $this->hasStateChanged($record);
82
83
        $transaction = Craft::$app->getDb()->beginTransaction();
84
        try {
85
            if (!$record->save()) {
86
                $transaction->rollBack();
87
                return false;
88
            }
89
90
            if (false !== $changedState &&
91
                true !== $this->changeState($record, $changedState)
92
            ) {
93
                $transaction->rollBack();
94
                return false;
95
            }
96
        } catch (\Exception $e) {
97
            $transaction->rollBack();
98
            throw $e;
99
        }
100
101
        $transaction->commit();
102
        return true;
103
    }
104
105
    /**
106
     * @param OrganizationRecord $record
107
     * @return false|string|null
108
     */
109
    private function hasStateChanged(OrganizationRecord $record)
110
    {
111
        if ($record->getIsNewRecord()) {
112
            return false;
113
        }
114
115
        if (!$record->isAttributeChanged('state', false)) {
116
            return false;
117
        }
118
119
        $oldState = $record->getOldAttribute('state');
120
        $newState = $record->getAttribute('state');
121
122
        // Revert record to old
123
        $record->setAttribute('state', $oldState);
124
125
        return $newState;
126
    }
127
128
129
    /**
130
     * @param OrganizationRecord $record
131
     * @param string|null $state
132
     * @return bool
133
     * @throws \Exception
134
     * @throws \yii\db\Exception
135
     */
136
    public function changeState(
137
        OrganizationRecord $record,
138
        string $state = null
139
    ): bool {
140
        $event = new ChangeStateEvent([
141
            'organization' => $record,
142
            'to' => $state
143
        ]);
144
145
        $this->trigger(
146
            static::EVENT_BEFORE_STATE_CHANGE,
147
            $event
148
        );
149
150
        if (!$event->isValid) {
151
            return false;
152
        }
153
154
        $transaction = Craft::$app->getDb()->beginTransaction();
155
        try {
156
            $record->state = $event->to;
157
158
            // Organization Record (status only)
159
            if (!$record->save(true, ['state'])) {
160
                $transaction->rollBack();
161
                return false;
162
            }
163
164
            // Trigger event
165
            $this->trigger(
166
                static::EVENT_AFTER_STATE_CHANGE,
167
                $event
168
            );
169
        } catch (\Exception $e) {
170
            $transaction->rollBack();
171
            throw $e;
172
        }
173
174
        $transaction->commit();
175
        return true;
176
    }
177
}
178