Completed
Pull Request — master (#152)
by
unknown
07:09 queued 05:43
created

ModelMapper   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 5

Test Coverage

Coverage 95.45%

Importance

Changes 0
Metric Value
wmc 15
lcom 0
cbo 5
dl 0
loc 97
ccs 42
cts 44
cp 0.9545
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A export() 0 14 3
B import() 0 41 9
A findOrNewRecord() 0 15 3
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Mappers;
4
5
use Craft;
6
use craft\base\Model;
7
use craft\helpers\ArrayHelper;
8
use yii\base\Component as BaseComponent;
9
use NerdsAndCompany\Schematic\Schematic;
10
use NerdsAndCompany\Schematic\Interfaces\MapperInterface;
11
12
/**
13
 * Schematic Model Mapper.
14
 *
15
 * Sync Craft Setups.
16
 *
17
 * @author    Nerds & Company
18
 * @copyright Copyright (c) 2015-2018, Nerds & Company
19
 * @license   MIT
20
 *
21
 * @see      http://www.nerds.company
22
 */
23
class ModelMapper extends BaseComponent implements MapperInterface
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28 3
    public function export(array $records): array
29
    {
30 3
        $result = [];
31 3
        foreach ($records as $record) {
32 2
            $modelClass = get_class($record);
33 2
            $converter = Craft::$app->controller->module->getConverter($modelClass);
34 2
            if ($converter) {
35 2
                $handle = $converter->handle;
36 2
                $result[$record->$handle] = $converter->getRecordDefinition($record);
37
            }
38
        }
39
40 3
        return $result;
41
    }
42
43
    /**
44
     * Import records.
45
     *
46
     * @param array $definitions
47
     * @param Model $records           The existing records
48
     * @param array $defaultAttributes Default attributes to use for each record
49
     * @param bool  $persist           Whether to persist the parsed records
50
     *
51
     * @return array
52
     */
53 12
    public function import(array $definitions, array $records, array $defaultAttributes = [], $persist = true): array
54
    {
55 12
        $imported = [];
56 12
        foreach ($definitions as $handle => $definition) {
57 4
            $modelClass = $definition['class'];
58 4
            $converter = Craft::$app->controller->module->getConverter($modelClass);
59 4
            if ($converter) {
60 4
                $recordsWithHandle = ArrayHelper::filterByValue($records, $converter->handle, $handle);
61 4
                $recordsByHandle = ArrayHelper::index($recordsWithHandle, $converter->handle);
62 4
                $record = $this->findOrNewRecord($recordsByHandle, $definition, $handle);
63
64 4
                if ($converter->getRecordDefinition($record) === $definition) {
65 4
                    Schematic::info('- Skipping '.get_class($record).' '.$handle);
66
                } else {
67 4
                    $converter->setRecordAttributes($record, $definition, $defaultAttributes);
68 4
                    if ($persist) {
69 4
                        Schematic::info('- Saving '.get_class($record).' '.$handle);
70 4
                        if (!$converter->saveRecord($record, $definition)) {
71 2
                            Schematic::importError($record, $handle);
72
                        }
73
                    }
74
                }
75
76 4
                $imported[] = $record;
77
            }
78 4
            unset($recordsByHandle[$handle]);
79
        }
80
81 12
        if (Schematic::$force && $persist) {
82
            // Delete records not in definitions
83 6
            foreach ($records as $record) {
84 4
                $modelClass = get_class($record);
85 4
                $converter = Craft::$app->controller->module->getConverter($modelClass);
86 2
                $handle = $converter->handle;
87 2
                Schematic::info('- Deleting '.get_class($record).' '.$handle);
88 2
                $converter->deleteRecord($record);
89
            }
90
        }
91
92 10
        return $imported;
93
    }
94
95
    /**
96
     * Find record from records by handle or new record.
97
     *
98
     * @param Model[] $recordsByHandle
99
     * @param array   $definition
100
     * @param string  $handle
101
     *
102
     * @return Model
103
     */
104 4
    private function findOrNewRecord(array $recordsByHandle, array $definition, string $handle): Model
105
    {
106 4
        $record = new $definition['class']();
107 4
        if (array_key_exists($handle, $recordsByHandle)) {
108 4
            $existing = $recordsByHandle[$handle];
109 4
            if (get_class($record) == get_class($existing)) {
110 4
                $record = $existing;
111
            } else {
112
                $record->id = $existing->id;
113
                $record->setAttributes($existing->getAttributes());
114
            }
115
        }
116
117 4
        return $record;
118
    }
119
}
120