Completed
Push — master ( 7f4e3a...f96930 )
by Bob Olde
04:50
created

Schematic::importFromYaml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
ccs 7
cts 7
cp 1
cc 1
eloc 7
nc 1
nop 3
crap 1
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Services;
4
5
use Craft\Craft;
6
use Craft\BaseApplicationComponent as BaseApplication;
7
use Craft\Exception;
8
use Craft\IOHelper;
9
use NerdsAndCompany\Schematic\Models\Data;
10
use NerdsAndCompany\Schematic\Models\Result;
11
12
/**
13
 * Schematic Service.
14
 *
15
 * Sync Craft Setups.
16
 *
17
 * @author    Nerds & Company
18
 * @copyright Copyright (c) 2015-2017, Nerds & Company
19
 * @license   MIT
20
 *
21
 * @link      http://www.nerds.company
22
 */
23
class Schematic extends BaseApplication
24
{
25
    const SCHEMATIC_METHOD_IMPORT = 'import';
26
    const SCHEMATIC_METHOD_EXPORT = 'export';
27
28
    protected static $exportableDataTypes = [
29
        'locales',
30
        'assetSources',
31
        'fields',
32
        'plugins',
33
        'sections',
34
        'globalSets',
35
        'userGroups',
36
        'users',
37
        'categoryGroups',
38
        'tagGroups',
39
        'elementIndexSettings',
40
        'pluginData',
41
    ];
42
43
    public static function getExportableDataTypes()
44
    {
45
        return self::$exportableDataTypes;
46
    }
47
48
    /**
49
     * Returns data from import model or default.
50
     *
51
     * @param array  $data
52
     * @param string $handle
53
     * @param array  $default
54
     *
55
     * @return array
56
     */
57 1
    private function getPluginData(array $data, $handle, array $default = [])
58
    {
59 1
        return (array_key_exists($handle, $data) && !is_null($data[$handle])) ? $data[$handle] : $default;
60
    }
61
62
    /**
63
     * Import from Yaml file.
64
     *
65
     * @param string $file
66
     * @param string $override
67
     * @param bool   $force    if set to true items not included in import will be deleted
68
     *
69
     * @return Result
70
     */
71 1
    public function importFromYaml($file, $override = null, $force = false)
72
    {
73 1
        Craft::app()->config->maxPowerCaptain();
74 1
        Craft::app()->setComponent('userSession', $this);
75
76 1
        $yaml = IOHelper::getFileContents($file);
77 1
        $yaml_override = IOHelper::getFileContents($override);
78 1
        $dataModel = Data::fromYaml($yaml, $yaml_override);
79
80 1
        return $this->importDataModel($dataModel, $force);
81
    }
82
83
    /**
84
     * Export to Yaml file.
85
     *
86
     * @param string $file
87
     * @param bool   $autoCreate
88
     *
89
     * @return Result
90
     */
91 3
    public function exportToYaml($file, $dataTypes = 'all', $autoCreate = true)
92
    {
93 3
        Craft::app()->config->maxPowerCaptain();
94 3
        Craft::app()->setComponent('userSession', $this);
95
96 3
        $result = new Result();
97 3
        $dataModel = $this->exportDataModel($dataTypes);
98 3
        $yaml = Data::toYaml($dataModel);
99
100 3
        if (!IOHelper::writeToFile($file, $yaml, $autoCreate)) { // Do not auto create
101 1
            $result->addError('errors', "Failed to write contents to \"$file\"");
102 1
        }
103
104 3
        return $result;
105
    }
106
107
    /**
108
     * Import data model.
109
     *
110
     * @param Data $model
111
     * @param bool $force if set to true items not in the import will be deleted
112
     *
113
     * @return Result
114
     */
115 4
    private function importDataModel(Data $model, $force)
116
    {
117
        // Import schema
118 1
        $locales = $model->getAttribute('locales', $force);
119 1
        $localesImportResult = Craft::app()->schematic_locales->import($locales);
120
121 1
        $plugins = $model->getAttribute('plugins', $force);
122 1
        $pluginImportResult = Craft::app()->schematic_plugins->import($plugins);
123
124 1
        $fields = $model->getAttribute('fields');
125 4
        $fieldImportResult = Craft::app()->schematic_fields->import($fields, $force);
126
127 1
        $assetSources = $model->getAttribute('assetSources');
128 1
        $assetSourcesImportResult = Craft::app()->schematic_assetSources->import($assetSources, $force);
129
130 1
        $globalSets = $model->getAttribute('globalSets');
131 1
        $globalSetsImportResult = Craft::app()->schematic_globalSets->import($globalSets, $force);
132
133 1
        $sections = $model->getAttribute('sections');
134 1
        $sectionImportResult = Craft::app()->schematic_sections->import($sections, $force);
135
136 1
        $categoryGroups = $model->getAttribute('categoryGroups');
137 1
        $categoryGroupImportResult = Craft::app()->schematic_categoryGroups->import($categoryGroups, $force);
138
139 1
        $tagGroups = $model->getAttribute('tagGroups');
140 1
        $tagGroupImportResult = Craft::app()->schematic_tagGroups->import($tagGroups, $force);
141
142 1
        $userGroups = $model->getAttribute('userGroups');
143 1
        $userGroupImportResult = Craft::app()->schematic_userGroups->import($userGroups, $force);
144
145 1
        $users = $model->getAttribute('users');
146 1
        $userImportResult = Craft::app()->schematic_users->import($users, true);
147
148 1
        $fields = $model->getAttribute('fields');
149 1
        $fieldImportResultFinal = Craft::app()->schematic_fields->import($fields, $force);
150
151
        // Element index settings are supported from Craft 2.5
152 1
        if (version_compare(CRAFT_VERSION, '2.5', '>=')) {
153 1
            $elementIndexSettingsImportResult = Craft::app()->schematic_elementIndexSettings->import(
154 1
                $model->getAttribute('elementIndexSettings'),
155
                $force
156 1
            );
157 1
        }
158
159
        // Verify results
160 1
        $result = new Result();
161 1
        $result->consume($localesImportResult);
162 1
        $result->consume($pluginImportResult);
163 1
        $result->consume($fieldImportResult);
164 1
        $result->consume($assetSourcesImportResult);
165 1
        $result->consume($globalSetsImportResult);
166 1
        $result->consume($sectionImportResult);
167 1
        $result->consume($categoryGroupImportResult);
168 1
        $result->consume($tagGroupImportResult);
169 1
        $result->consume($userGroupImportResult);
170 1
        $result->consume($userImportResult);
171 1
        $result->consume($fieldImportResultFinal);
172
173
        // Element index settings are supported from Craft 2.5
174 1
        if (version_compare(CRAFT_VERSION, '2.5', '>=')) {
175 1
            $result->consume($elementIndexSettingsImportResult);
0 ignored issues
show
Bug introduced by
The variable $elementIndexSettingsImportResult does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
176 1
        }
177
178 1
        $services = Craft::app()->plugins->call('registerMigrationService');
179 1
        $this->doImport($result, $model->pluginData, $services, $force);
180
181 1
        return $result;
182
    }
183
184
    /**
185
     * Handles importing.
186
     *
187
     * @param Result       $result
188
     * @param array        $data
189
     * @param array|Base[] $services
190
     * @param bool         $force
191
     */
192 1
    private function doImport(Result $result, array $data, $services, $force)
193
    {
194 1
        foreach ($services as $handle => $service) {
195 1
            if (is_array($service)) {
196 1
                $this->doImport($result, $data, $service, $force);
197 1
            } elseif ($service instanceof Base) {
198 1
                $pluginData = $this->getPluginData($data, $handle);
199 1
                $hookResult = $service->import($pluginData, $force);
200 1
                $result->consume($hookResult);
201 1
            }
202 1
        }
203 1
    }
204
205
    /**
206
     * Export data model.
207
     *
208
     * @param string|array $dataTypes The data types to export
209
     *
210
     * @return array
211
     *
212
     * @throws Exception
213
     */
214 3
    private function exportDataModel($dataTypes = 'all')
215
    {
216
        // If all data types should be exported, get all the available data types that can be exported.
217 3
        if (is_array($dataTypes)) {
218
            // Validate that each data type specified to be exported is reconized.
219 1
            foreach ($dataTypes as $dataType) {
220 1
                if (!in_array($dataType, $this->exportableDataTypes)) {
221
                    $errorMessage = 'Invalid export type "'.$dataType.'". Accepted types are '
222
                        .implode(', ', $this->exportableDataTypes);
223
                    throw new Exception($errorMessage);
224
                }
225 1
            }
226 1
        } else {
227 2
            $dataTypes = $this->exportableDataTypes;
228
        }
229
230 3
        $assetSources = Craft::app()->assetSources->getAllSources();
231 3
        $categoryGroups = Craft::app()->categories->getAllGroups();
232 3
        $tagGroups = Craft::app()->tags->getAllTagGroups();
233
234 3
        $export = [];
235
236 3
        if (in_array('locales', $dataTypes)) {
237 3
            $export['locales'] = Craft::app()->schematic_locales->export();
238 3
        }
239
240 3
        if (in_array('assetSources', $dataTypes)) {
241 3
            $export['assetSources'] = Craft::app()->schematic_assetSources->export($assetSources);
242 3
        }
243
244 3
        if (in_array('fields', $dataTypes)) {
245 3
            $fieldGroups = Craft::app()->fields->getAllGroups();
246 3
            $export['fields'] = Craft::app()->schematic_fields->export($fieldGroups);
247 3
        }
248
249 3
        if (in_array('plugins', $dataTypes)) {
250 3
            $export['plugins'] = Craft::app()->schematic_plugins->export();
251 3
        }
252
253 3
        if (in_array('sections', $dataTypes)) {
254 3
            $sections = Craft::app()->sections->getAllSections();
255 3
            $export['sections'] = Craft::app()->schematic_sections->export($sections);
256 3
        }
257
258 3
        if (in_array('globalSets', $dataTypes)) {
259 3
            $globals = Craft::app()->globals->getAllSets();
260 3
            $export['globalSets'] = Craft::app()->schematic_globalSets->export($globals);
261 3
        }
262
263 3
        if (in_array('userGroups', $dataTypes)) {
264 3
            $userGroups = Craft::app()->userGroups->getAllGroups();
265 3
            $export['userGroups'] = Craft::app()->schematic_userGroups->export($userGroups);
266 3
        }
267
268 3
        if (in_array('users', $dataTypes)) {
269 3
            $export['users'] = Craft::app()->schematic_users->export();
270 3
        }
271
272 3
        if (in_array('categoryGroups', $dataTypes)) {
273 3
            $export['categoryGroups'] = Craft::app()->schematic_categoryGroups->export($categoryGroups);
274 3
        }
275
276 3
        if (in_array('tagGroups', $dataTypes)) {
277 3
            $export['tagGroups'] = Craft::app()->schematic_tagGroups->export($tagGroups);
278 3
        }
279
280
        // Element index settings are supported from Craft 2.5
281 3
        if (in_array('elementIndexSettings', $dataTypes) && version_compare(CRAFT_VERSION, '2.5', '>=')) {
282 3
            $export['elementIndexSettings'] = Craft::app()->schematic_elementIndexSettings->export();
283 3
        }
284
285 3
        if (in_array('pluginData', $dataTypes)) {
286 2
            $export['pluginData'] = [];
287 2
            $services = Craft::app()->plugins->call('registerMigrationService');
288 2
            $this->doExport($services, $export['pluginData']);
289 2
        }
290
291 3
        return $export;
292
    }
293
294
    /**
295
     * Handles exporting.
296
     *
297
     * @param array $services
298
     * @param array $data
299
     */
300 2
    private function doExport(array $services, array &$data)
301
    {
302 2
        foreach ($services as $handle => $service) {
303 2
            if (is_array($service)) {
304 2
                $this->doExport($service, $data);
305 2
            } elseif ($service instanceof Base) {
306 2
                if ($service instanceof Base) {
307 2
                    $data[$handle] = $service->export();
308 2
                }
309 2
            }
310 2
        }
311 2
    }
312
313
    /**
314
     * Always return the super user.
315
     *
316
     * @return Craft\UserModel
317
     */
318
    public function getUser()
319
    {
320
        return Craft::app()->users->getUserById(1);
321
    }
322
323
    /**
324
     * Assume schematic can do anything.
325
     *
326
     * @return bool
327
     */
328
    public function checkPermission()
329
    {
330
        return true;
331
    }
332
}
333