1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace NerdsAndCompany\Schematic\Controllers; |
4
|
|
|
|
5
|
|
|
use Craft; |
6
|
|
|
use NerdsAndCompany\Schematic\Models\Data; |
7
|
|
|
use NerdsAndCompany\Schematic\Schematic; |
8
|
|
|
use craft\errors\WrongEditionException; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Schematic Import Command. |
12
|
|
|
* |
13
|
|
|
* Sync Craft Setups. |
14
|
|
|
* |
15
|
|
|
* @author Nerds & Company |
16
|
|
|
* @copyright Copyright (c) 2015-2018, Nerds & Company |
17
|
|
|
* @license MIT |
18
|
|
|
* |
19
|
|
|
* @see http://www.nerds.company |
20
|
|
|
*/ |
21
|
|
|
class ImportController extends Base |
22
|
|
|
{ |
23
|
|
|
public $force = false; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* {@inheritdoc} |
27
|
|
|
* |
28
|
|
|
* @return array |
29
|
|
|
*/ |
30
|
|
|
public function options($actionID): array |
31
|
|
|
{ |
32
|
|
|
return array_merge(parent::options($actionID), ['force']); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Imports the Craft datamodel. |
37
|
|
|
* |
38
|
|
|
* @return int |
39
|
|
|
* @throws \Exception |
40
|
|
|
*/ |
41
|
|
|
public function actionIndex(): int |
42
|
|
|
{ |
43
|
|
|
if (!file_exists($this->path)) { |
44
|
|
|
Schematic::error('Directory not found: ' . $this->path); |
45
|
|
|
|
46
|
|
|
return 1; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
$dataTypes = $this->getDataTypes(); |
50
|
|
|
$this->importFromYaml($dataTypes); |
51
|
|
|
Schematic::info('Loaded schema from '.$this->path); |
52
|
|
|
|
53
|
|
|
return 0; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Import from Yaml file. |
58
|
|
|
* |
59
|
|
|
* @param array $dataTypes The data types to import |
60
|
|
|
* @throws \Exception |
61
|
|
|
*/ |
62
|
|
|
private function importFromYaml(array $dataTypes) |
63
|
|
|
{ |
64
|
|
|
$this->disableLogging(); |
65
|
|
|
|
66
|
|
|
// Parse data in the overrideFile if available. |
67
|
|
|
$overrideData = Data::parseYamlFile($this->overrideFile); |
68
|
|
|
|
69
|
|
|
// Import from single file. |
70
|
|
|
if ($this->getStorageType() === self::SINGLE_FILE) { |
71
|
|
|
$yaml = file_get_contents($this->file); |
72
|
|
|
$yamlOverride = null; |
73
|
|
|
if (file_exists($this->overrideFile)) { |
74
|
|
|
$yamlOverride = file_get_contents($this->overrideFile); |
75
|
|
|
} |
76
|
|
|
$definitions = Data::fromYaml($yaml, $yamlOverride); |
|
|
|
|
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
// Import from multiple files. |
80
|
|
|
if ($this->getStorageType() === self::MULTIPLE_FILES) { |
81
|
|
|
// Grab all yaml files in the schema directory. |
82
|
|
|
$schemaFiles = preg_grep('~\.(yml)$~', scandir($this->path)); |
83
|
|
|
|
84
|
|
|
// Read contents of each file and add it to the definitions. |
85
|
|
|
foreach ($schemaFiles as $fileName) { |
86
|
|
|
$schemaStructure = explode('.', $this->fromSafeFileName($fileName)); |
87
|
|
|
$dataTypeHandle = $schemaStructure[0]; |
88
|
|
|
$recordName = $schemaStructure[1]; |
89
|
|
|
|
90
|
|
|
$definition = Data::fromYaml(file_get_contents($this->path . $fileName)); |
91
|
|
|
|
92
|
|
|
// Check if there is data in the override file for the current record. |
93
|
|
|
if (isset($overrideData[$dataTypeHandle][$recordName])) { |
94
|
|
|
$definition = array_replace_recursive( |
95
|
|
|
$definition, |
96
|
|
|
$overrideData[$dataTypeHandle][$recordName] |
97
|
|
|
); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$definitions[$dataTypeHandle][$recordName] = $definition; |
|
|
|
|
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
foreach ($dataTypes as $dataTypeHandle) { |
105
|
|
|
$dataType = $this->module->getDataType($dataTypeHandle); |
106
|
|
|
if (null == $dataType) { |
107
|
|
|
continue; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$mapper = $dataType->getMapperHandle(); |
111
|
|
|
if (!$this->module->checkMapper($mapper)) { |
112
|
|
|
continue; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
Schematic::info('Importing '.$dataTypeHandle); |
116
|
|
|
Schematic::$force = $this->force; |
117
|
|
|
if (array_key_exists($dataTypeHandle, $definitions) && is_array($definitions[$dataTypeHandle])) { |
118
|
|
|
$records = $dataType->getRecords(); |
119
|
|
|
try { |
120
|
|
|
$this->module->$mapper->import($definitions[$dataTypeHandle], $records); |
121
|
|
|
$dataType->afterImport(); |
122
|
|
|
} catch (WrongEditionException $e) { |
123
|
|
|
Schematic::error('Craft Pro is required for datatype '.$dataTypeHandle); |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.