Schematic   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 222
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 4
dl 0
loc 222
ccs 64
cts 64
cp 1
rs 10
c 0
b 0
f 0

8 Methods

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