Completed
Push — master ( f04a1d...4a48e8 )
by
unknown
10s
created

ModelMapper::getRecordsByHandle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

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