Completed
Branch feature/wip (503827)
by Nate
04:34
created

Transformers::notFoundException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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