Completed
Push — master ( 0c0d6d...8a38f5 )
by Nate
09:55 queued 10s
created

Transformers::dbTransformers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
ccs 0
cts 7
cp 0
cc 2
nc 2
nop 0
crap 6
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\flux\events\RegisterTransformersEvent;
14
use flipbox\flux\exceptions\TransformerNotFoundException;
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
     * @event Event an event that is triggered when the class is initialized via [[init()]].
30
     */
31
    const EVENT_INIT = 'init';
32
33
    /**
34
     * @event Event an event that is triggered when the transformers are registered.
35
     */
36
    const EVENT_REGISTER_TRANSFORMERS = 'registerTransformer';
37
38
    /**
39
     * Transformers that have previously been loaded
40
     *
41
     * @var array
42
     */
43
    private $transformers;
44
45
    /**
46
     * The transformers that Event triggers have been executed
47
     *
48
     * @var array
49
     */
50
    private $processed = [];
51
52
    /**
53
     * Initializes the object.
54
     * This method is called at the end of the constructor. The default implementation will trigger
55
     * an [[EVENT_INIT]] event. If you override this method, make sure you call the parent implementation at the end
56
     * to ensure triggering of the event.
57
     */
58
    public function init()
59
    {
60
        parent::init();
61
        $this->trigger(self::EVENT_INIT);
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
        if (null !== ($callable = TransformerHelper::resolve($transformer))) {
78
            return $callable;
79
        }
80
81
        if (is_string($transformer)) {
82
            return $this->find($transformer, $scope, $class, $default);
83
        }
84
85
        return null;
86
    }
87
88
    /**
89
     * @param string $identifier
90
     * @param string $scope
91
     * @param string|null $class
92
     * @param null $default
93
     * @return callable
94
     * @throws TransformerNotFoundException
95
     */
96
    public function get(
97
        string $identifier,
98
        string $scope = Flux::GLOBAL_SCOPE,
99
        string $class = null,
100
        $default = null
101
    ): callable {
102
        if (null === ($transformer = $this->find($identifier, $scope, $class, $default))) {
103
            throw new TransformerNotFoundException(sprintf(
104
                "Unable to find transformer with the following criteria: %s",
105
                Json::encode([
106
                    'identifier' => $identifier,
107
                    'scope' => $scope,
108
                    'class' => $class
109
                ])
110
            ));
111
        }
112
113
        return $transformer;
114
    }
115
116
    /**
117
     * @param string $identifier
118
     * @param string $scope
119
     * @param string|null $class
120
     * @param callable|null $default
121
     * @return callable|null
122
     */
123
    public function find(
124
        string $identifier,
125
        string $scope = Flux::GLOBAL_SCOPE,
126
        string $class = null,
127
        $default = null
128
    ) {
129
        if (!Flux::getInstance()->isValidScope($scope)) {
130
            return null;
131
        }
132
133
        $transformersByScopeAndClass = $this->resolveAllByScopeAndClass($scope, $class);
134
135
        if (null === ($transformer = $transformersByScopeAndClass[$identifier] ?? $default)) {
136
            return null;
137
        }
138
139
        return TransformerHelper::resolve($transformer);
140
    }
141
142
143
    /**
144
     * @param string $scope
145
     * @param string|null $class
146
     * @return array
147
     */
148
    public function resolveAllByScopeAndClass(
149
        string $scope = Flux::GLOBAL_SCOPE,
150
        string $class = null
151
    ): array {
152
        // Default class
153
        if ($class === null) {
154
            $class = Flux::class;
155
        }
156
157
        if (($this->processed[$scope][$class] ?? false) !== true) {
158
            $this->processed[$scope][$class] = true;
159
160
            $this->ensureTransformerConfigs();
161
162
            $event = new RegisterTransformersEvent([
163
                'transformers' => $this->transformers[$scope][$class] ?? []
164
            ]);
165
166
            Event::trigger(
167
                $class,
168
                self::EVENT_REGISTER_TRANSFORMERS . ':' . $scope,
169
                $event
170
            );
171
172
            $this->transformers[$scope][$class] = $event->transformers;
173
        }
174
175
        return $this->transformers[$scope][$class];
176
    }
177
178
    /**
179
     * Ensure the db transformers are loaded
180
     */
181
    protected function ensureTransformerConfigs()
182
    {
183
        if ($this->transformers === null) {
184
            $this->transformers = $this->dbTransformers();
185
        }
186
    }
187
188
    /**
189
     * @return array
190
     */
191
    protected function dbTransformers(): array
192
    {
193
        $query = (new Query())
194
            ->select(['handle', 'scope', 'class', 'config'])
195
            ->from([Transformer::tableName()]);
196
197
        $configs = [];
198
199
        foreach ($query->all() as $result) {
200
            $configs[$result['scope']][$result['class']][$result['handle']] = $this->prepareConfig([$result['config']]);
201
        }
202
203
        return $configs;
204
    }
205
206
    /**
207
     * @param array $config
208
     * @return array
209
     */
210
    protected function prepareConfig(array $config = []): array
211
    {
212
        if (null !== ($settings = ArrayHelper::remove($config, 'config'))) {
213
            if (is_string($settings)) {
214
                $settings = Json::decodeIfJson($settings);
215
            }
216
217
            $config = array_merge(
218
                $config,
219
                $settings
220
            );
221
        }
222
223
        return $config;
224
    }
225
}
226