Transformers::resolveAllByScopeAndClass()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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