Completed
Push — after-import-callback ( a80e19...34feb0 )
by Bart
02:32
created

Schematic   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 246
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 97.22%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 0
loc 246
ccs 70
cts 72
cp 0.9722
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 50 1
A getDataType() 0 30 5
A checkMapper() 0 15 3
B getConverter() 0 37 6
A error() 0 4 1
A warning() 0 4 1
A info() 0 4 1
A importError() 0 15 4
1
<?php
2
3
namespace NerdsAndCompany\Schematic;
4
5
use Craft;
6
use craft\base\Model;
7
use craft\base\Plugin;
8
use yii\di\ServiceLocator;
9
use yii\helpers\Console;
10
use NerdsAndCompany\Schematic\DataTypes\AssetTransformDataType;
11
use NerdsAndCompany\Schematic\DataTypes\CategoryGroupDataType;
12
use NerdsAndCompany\Schematic\DataTypes\ElementIndexDataType;
13
use NerdsAndCompany\Schematic\DataTypes\EmailSettingsDataType;
14
use NerdsAndCompany\Schematic\DataTypes\FieldDataType;
15
use NerdsAndCompany\Schematic\DataTypes\GeneralSettingsDataType;
16
use NerdsAndCompany\Schematic\DataTypes\GlobalSetDataType;
17
use NerdsAndCompany\Schematic\DataTypes\PluginDataType;
18
use NerdsAndCompany\Schematic\DataTypes\SectionDataType;
19
use NerdsAndCompany\Schematic\DataTypes\SiteDataType;
20
use NerdsAndCompany\Schematic\DataTypes\TagGroupDataType;
21
use NerdsAndCompany\Schematic\DataTypes\UserGroupDataType;
22
use NerdsAndCompany\Schematic\DataTypes\UserSettingsDataType;
23
use NerdsAndCompany\Schematic\DataTypes\VolumeDataType;
24
use NerdsAndCompany\Schematic\Mappers\ElementIndexMapper;
25
use NerdsAndCompany\Schematic\Mappers\EmailSettingsMapper;
26
use NerdsAndCompany\Schematic\Mappers\GeneralSettingsMapper;
27
use NerdsAndCompany\Schematic\Mappers\ModelMapper;
28
use NerdsAndCompany\Schematic\Mappers\PluginMapper;
29
use NerdsAndCompany\Schematic\Mappers\UserSettingsMapper;
30
use NerdsAndCompany\Schematic\Interfaces\ConverterInterface;
31
use NerdsAndCompany\Schematic\Interfaces\DataTypeInterface;
32
use NerdsAndCompany\Schematic\Interfaces\MapperInterface;
33
use NerdsAndCompany\Schematic\Events\ConverterEvent;
34
35
/**
36
 * Schematic.
37
 *
38
 * Sync Craft Setups.
39
 *
40
 * @author    Nerds & Company
41
 * @copyright Copyright (c) 2015-2018, Nerds & Company
42
 * @license   MIT
43
 *
44
 * @see      http://www.nerds.company
45
 *
46
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
47
 */
48
class Schematic extends Plugin
49
{
50
    const EVENT_RESOLVE_CONVERTER = 'resolve_converter';
51
52
    /**
53
     * @var string
54
     */
55
    public $controllerNamespace = 'NerdsAndCompany\Schematic\Controllers';
56
57
    /**
58
     * @var array
59
     */
60
    public $dataTypes = [];
61
62
    /**
63
     * @var ServiceLocator
64
     */
65
    private $converterLocator;
66
67
    /**
68
     * @var ServiceLocator
69
     */
70
    private $datatypeLocator;
71
72
    /**
73
     * Initialize the module.
74
     */
75 10
    public function init()
76
    {
77 10
        Craft::setAlias('@NerdsAndCompany/Schematic', __DIR__);
78
79 10
        $this->converterLocator = new ServiceLocator();
80 10
        $this->datatypeLocator = new ServiceLocator();
81
82
        $config = [
83 10
            'components' => [
84
                'elementIndexMapper' => [
85
                    'class' => ElementIndexMapper::class,
86
                ],
87
                'emailSettingsMapper' => [
88
                    'class' => EmailSettingsMapper::class,
89
                ],
90
                'generalSettingsMapper' => [
91
                    'class' => GeneralSettingsMapper::class,
92
                ],
93
                'modelMapper' => [
94
                    'class' => ModelMapper::class,
95
                ],
96
                'pluginMapper' => [
97
                    'class' => PluginMapper::class,
98
                ],
99
                'userSettingsMapper' => [
100
                    'class' => UserSettingsMapper::class,
101
                ],
102
            ],
103
            'dataTypes' => [
104
                'plugins' => PluginDataType::class,
105
                'sites' => SiteDataType::class,
106
                'volumes' => VolumeDataType::class,
107
                'assetTransforms' => AssetTransformDataType::class,
108
                'emailSettings' => EmailSettingsDataType::class,
109
                'fields' => FieldDataType::class,
110
                'generalSettings' => GeneralSettingsDataType::class,
111
                'sections' => SectionDataType::class,
112
                'globalSets' => GlobalSetDataType::class,
113
                'categoryGroups' => CategoryGroupDataType::class,
114
                'tagGroups' => TagGroupDataType::class,
115
                'userGroups' => UserGroupDataType::class,
116
                'userSettings' => UserSettingsDataType::class,
117
                'elementIndexSettings' => ElementIndexDataType::class,
118
            ],
119
        ];
120
121 10
        Craft::configure($this, $config);
122
123 10
        parent::init();
124 10
    }
125
126
    /**
127
     * Get datatype by handle.
128
     *
129
     * @param string $dataTypeHandle
130
     *
131
     * @return DateTypeInterface|null
132
     */
133 4
    public function getDataType(string $dataTypeHandle)
134
    {
135 4
        if ($this->datatypeLocator->has($dataTypeHandle)) {
136
            return $this->datatypeLocator->get($dataTypeHandle);
137
        }
138
139 4
        if (!isset($this->dataTypes[$dataTypeHandle])) {
140 1
            Schematic::error('DataType '.$dataTypeHandle.' is not registered');
141
142 1
            return null;
143
        }
144
145 3
        $dataTypeClass = $this->dataTypes[$dataTypeHandle];
146 3
        if (!class_exists($dataTypeClass)) {
147 1
            Schematic::error('Class '.$dataTypeClass.' does not exist');
148
149 1
            return null;
150
        }
151
152 2
        $dataType = new $dataTypeClass();
153 2
        if (!$dataType instanceof DataTypeInterface) {
154 1
            Schematic::error($dataTypeClass.' does not implement DataTypeInterface');
155
156 1
            return null;
157
        }
158
159 1
        $this->datatypeLocator->set($dataTypeHandle, $dataType);
160
161 1
        return $dataType;
162
    }
163
164
    /**
165
     * Check mapper handle is valid.
166
     *
167
     * @param string $mapper
168
     *
169
     * @return bool
170
     */
171 3
    public function checkMapper(string $mapper): bool
172
    {
173 3
        if (!isset($this->$mapper)) {
174 1
            Schematic::error('Mapper '.$mapper.' not found');
175
176 1
            return false;
177
        }
178 2
        if (!$this->$mapper instanceof MapperInterface) {
179 1
            Schematic::error(get_class($this->$mapper).' does not implement MapperInterface');
180
181 1
            return false;
182
        }
183
184 1
        return true;
185
    }
186
187
    /**
188
     * Find converter for model class.
189
     *
190
     * @param string $modelClass
191
     *
192
     * @return ConverterInterface|null
193
     */
194 3
    public function getConverter(string $modelClass, string $originalClass = '')
195
    {
196 3
        if ('' === $originalClass) {
197 3
            $originalClass = $modelClass;
198
        }
199
200 3
        if ($this->converterLocator->has($originalClass)) {
201
            return $this->converterLocator->get($originalClass);
202
        }
203
204 3
        $converterClass = 'NerdsAndCompany\\Schematic\\Converters\\'.ucfirst(str_replace('craft\\', '', $modelClass));
205 3
        $event = new ConverterEvent([
206 3
            'modelClass' => $modelClass,
207 3
            'converterClass' => $converterClass,
208
        ]);
209
210 3
        $this->trigger(self::EVENT_RESOLVE_CONVERTER, $event);
211 3
        $converterClass = $event->converterClass;
212
213 3
        if (class_exists($converterClass)) {
214 2
            $converter = new $converterClass();
215 2
            if ($converter instanceof ConverterInterface) {
216 2
                $this->converterLocator->set($originalClass, $converter);
217
218 2
                return $converter;
219
            }
220
        }
221
222 2
        $parentClass = get_parent_class($modelClass);
223 2
        if (!$parentClass) {
224 1
            Schematic::error('No converter found for '.$originalClass);
225
226 1
            return null;
227
        }
228
229 2
        return $this->getConverter($parentClass, $originalClass);
230
    }
231
232
    /**
233
     * Is force enabled?
234
     *
235
     * @var bool
236
     */
237
    public static $force = false;
238
239
    /**
240
     * Logs an error message.
241
     *
242
     * @param string|array $message the message to be logged. This can be a simple string or a more
243
     *                              complex data structure, such as array.
244
     */
245 12
    public static function error($message)
246
    {
247 12
        Craft::$app->controller->stdout($message.PHP_EOL, Console::FG_RED);
248 12
    }
249
250
    /**
251
     * Logs a warning message.
252
     *
253
     * @param string|array $message the message to be logged. This can be a simple string or a more
254
     *                              complex data structure, such as array.
255
     */
256 12
    public static function warning($message)
257
    {
258 12
        Craft::$app->controller->stdout($message.PHP_EOL, Console::FG_YELLOW);
259 12
    }
260
261
    /**
262
     * Logs an info message.
263
     *
264
     * @param string|array $message the message to be logged. This can be a simple string or a more
265
     *                              complex data structure, such as array.
266
     */
267 14
    public static function info($message)
268
    {
269 14
        Craft::$app->controller->stdout($message.PHP_EOL);
270 14
    }
271
272
    /**
273
     * Log an import error.
274
     *
275
     * @param Model  $record
276
     * @param string $handle
277
     */
278 7
    public static function importError(Model $record, string $handle)
279
    {
280 7
        static::warning('- Error importing '.get_class($record).' '.$handle);
281 7
        $errors = $record->getErrors();
282 7
        if (!is_array($errors)) {
283 2
            static::error('   - An unknown error has occurred');
284
285 2
            return;
286
        }
287 5
        foreach ($errors as $subErrors) {
288 1
            foreach ($subErrors as $error) {
289 1
                static::error('   - '.$error);
290
            }
291
        }
292 5
    }
293
}
294