Completed
Push — develop ( 0c0d6d...6a2a65 )
by Nate
61:06
created

Transformers::resolveAllByScopeAndClass()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 23
cp 0
rs 9.424
c 0
b 0
f 0
cc 3
nc 4
nop 2
crap 12
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/flux/license
6
 * @link       https://www.flipboxfactory.com/software/flux/
7
 */
8
9
namespace flipbox\flux\services;
10
11
use craft\helpers\ArrayHelper;
12
use craft\helpers\Json;
13
use flipbox\ember\exceptions\ObjectNotFoundException;
14
use flipbox\flux\events\RegisterTransformersEvent;
15
use flipbox\flux\Flux;
16
use flipbox\flux\helpers\TransformerHelper;
17
use flipbox\flux\records\Transformer;
18
use yii\base\Component;
19
use yii\base\Event;
20
use yii\db\Query;
21
22
/**
23
 * @author Flipbox Factory <[email protected]>
24
 * @since 1.0.0
25
 */
26
class Transformers extends Component
27
{
28
29
    /**
30
     * @event Event an event that is triggered when the query is initialized via [[init()]].
31
     */
32
    const EVENT_INIT = 'init';
33
34
    /**
35
     *
36
     */
37
    const EVENT_REGISTER_TRANSFORMERS = 'registerTransformer';
38
39
    /**
40
     * @var array
41
     */
42
    private $transformers;
43
44
    /**
45
     * The transformers that Event triggers have been executed
46
     *
47
     * @var array
48
     */
49
    private $processed = [];
50
51
    /**
52
     * Initializes the object.
53
     * This method is called at the end of the constructor. The default implementation will trigger
54
     * an [[EVENT_INIT]] event. If you override this method, make sure you call the parent implementation at the end
55
     * to ensure triggering of the event.
56
     */
57
    public function init()
58
    {
59
        parent::init();
60
        $this->trigger(self::EVENT_INIT);
61
    }
62
63
64
    /**
65
     * @param $transformer
66
     * @param string $scope
67
     * @param string|null $class
68
     * @param callable|null $default
69
     * @return callable|null
70
     */
71
    public function resolve(
72
        $transformer,
73
        string $scope = Flux::GLOBAL_SCOPE,
74
        string $class = null,
75
        $default = null
76
    )
77
    {
78
        if (null !== ($callable = TransformerHelper::resolve($transformer))) {
79
            return $callable;
80
        }
81
82
        if (is_string($transformer)) {
83
            return $this->find($transformer, $scope, $class, $default);
84
        }
85
86
        return null;
87
    }
88
89
    /**
90
     * @param string $identifier
91
     * @param string $scope
92
     * @param string|null $class
93
     * @param callable|null $default
94
     * @return callable
95
     * @throws ObjectNotFoundException
96
     */
97
    public function get(
98
        string $identifier,
99
        string $scope = Flux::GLOBAL_SCOPE,
100
        string $class = null,
101
        $default = null
102
    ): callable
103
    {
104
        if (null === ($transformer = $this->find($identifier, $scope, $class, $default))) {
105
            $this->notFoundException();
106
        }
107
108
        return $transformer;
109
    }
110
111
    /**
112
     * @param string $identifier
113
     * @param string $scope
114
     * @param string|null $class
115
     * @param callable|null $default
116
     * @return callable|null
117
     */
118
    public function find(
119
        string $identifier,
120
        string $scope = Flux::GLOBAL_SCOPE,
121
        string $class = null,
122
        $default = null
123
    )
124
    {
125
        if (!Flux::getInstance()->isValidScope($scope)) {
126
            return null;
127
        }
128
129
        $transformersByScopeAndClass = $this->resolveAllByScopeAndClass($scope, $class);
130
131
        if (null === ($transformer = $transformersByScopeAndClass[$identifier] ?? $default)) {
132
            return null;
133
        }
134
135
        return TransformerHelper::resolve($transformer);
136
    }
137
138
139
    /**
140
     * @param string $scope
141
     * @param string|null $class
142
     * @return array
143
     */
144
    public function resolveAllByScopeAndClass(
145
        string $scope = Flux::GLOBAL_SCOPE,
146
        string $class = null
147
    ): array
148
    {
149
150
        // Default class
151
        if ($class === null) {
152
            $class = Flux::class;
153
        }
154
155
        if (($this->processed[$scope][$class] ?? false) !== true) {
156
            $this->processed[$scope][$class] = true;
157
158
            $this->ensureTransformerConfigs();
159
160
            $event = new RegisterTransformersEvent([
161
                'transformers' => $this->transformers[$scope][$class] ?? []
162
            ]);
163
164
            Event::trigger(
165
                $class,
166
                self::EVENT_REGISTER_TRANSFORMERS . ':' . $scope,
167
                $event
168
            );
169
170
            $this->transformers[$scope][$class] = $event->transformers;
171
        }
172
173
        return $this->transformers[$scope][$class];
174
    }
175
176
    /**
177
     * Ensure the db transformers are loaded
178
     */
179
    protected function ensureTransformerConfigs()
180
    {
181
        if ($this->transformers === null) {
182
            $this->transformers = $this->dbTransformers();
183
        }
184
    }
185
186
    /**
187
     * @return array
188
     */
189
    protected function dbTransformers(): array
190
    {
191
        $query = (new Query())
192
            ->select(['handle', 'scope', 'class', 'config'])
193
            ->from([Transformer::tableName()]);
194
195
        $configs = [];
196
197
        foreach ($query->all() as $result) {
198
            $configs[$result['scope']][$result['class']][$result['handle']] = $this->prepareConfig([$result['config']]);
199
        }
200
201
        return $configs;
202
    }
203
204
    /**
205
     * @param array $config
206
     * @return array
207
     */
208
    protected function prepareConfig(array $config = []): array
209
    {
210
        if (null !== ($settings = ArrayHelper::remove($config, 'config'))) {
211
            if (is_string($settings)) {
212
                $settings = Json::decodeIfJson($settings);
213
            }
214
215
            $config = array_merge(
216
                $config,
217
                $settings
218
            );
219
        }
220
221
        return $config;
222
    }
223
224
225
    /*******************************************
226
     * EXCEPTIONS
227
     *******************************************/
228
229
    /**
230
     * @throws ObjectNotFoundException
231
     */
232
    protected function notFoundException()
233
    {
234
        throw new ObjectNotFoundException(
235
            sprintf(
236
                "Transformer not found."
237
            )
238
        );
239
    }
240
241
}
242