1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace luya\console\commands; |
4
|
|
|
|
5
|
|
|
use Yii; |
6
|
|
|
use yii\console\widgets\Table; |
7
|
|
|
use luya\Boot; |
8
|
|
|
use luya\admin\models\Config; |
9
|
|
|
use luya\console\Command; |
10
|
|
|
use luya\console\interfaces\ImportControllerInterface; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Import controller runs the module defined importer classes. |
14
|
|
|
* |
15
|
|
|
* The importer classes are defined inthe modules `import()` methods which inherits this class. |
16
|
|
|
* |
17
|
|
|
* ```sh |
18
|
|
|
* ./vendor/bin/luya import |
19
|
|
|
* ``` |
20
|
|
|
* |
21
|
|
|
* Each of the importer classes must extend the {{\luya\console\Importer}} class. |
22
|
|
|
* |
23
|
|
|
* @author Basil Suter <[email protected]> |
24
|
|
|
* @since 1.0.0 |
25
|
|
|
*/ |
26
|
|
|
class ImportController extends Command implements ImportControllerInterface |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* @var array An array with all folder names inside an application/module to scan for files. |
30
|
|
|
*/ |
31
|
|
|
protected $scanFolders = ['blocks', 'filters', 'properties', 'blockgroups']; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @inheritdoc |
35
|
|
|
*/ |
36
|
|
|
public function init() |
37
|
|
|
{ |
38
|
|
|
parent::init(); |
39
|
|
|
|
40
|
|
|
// foreach scanFolders of all modules |
41
|
|
|
foreach (Yii::$app->getApplicationModules() as $id => $module) { |
42
|
|
|
foreach ($this->scanFolders as $folderName) { |
43
|
|
|
$this->addToDirectory($module->getBasePath().DIRECTORY_SEPARATOR.$folderName, $folderName, '\\'.$module->getNamespace().'\\'.$folderName, $module->id); |
44
|
|
|
} |
45
|
|
|
} |
46
|
|
|
// foreach scanFolder inside the app namespace |
47
|
|
|
foreach ($this->scanFolders as $folderName) { |
48
|
|
|
$this->addToDirectory(Yii::getAlias("@app/$folderName"), $folderName, '\\app\\'.$folderName, '@app'); |
|
|
|
|
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
private $_dirs = []; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Add a given directory to the list of folders. |
56
|
|
|
* |
57
|
|
|
* @param string $path |
58
|
|
|
* @param string $folderName |
59
|
|
|
* @param string $ns |
60
|
|
|
* @param string $module The name/id of the module. |
61
|
|
|
*/ |
62
|
|
|
protected function addToDirectory($path, $folderName, $ns, $module) |
63
|
|
|
{ |
64
|
|
|
if (file_exists($path)) { |
65
|
|
|
$this->_dirs[$folderName][] = [ |
66
|
|
|
'ns' => $ns, |
67
|
|
|
'module' => $module, |
68
|
|
|
'folderPath' => $path.DIRECTORY_SEPARATOR, |
69
|
|
|
'files' => $this->scanDirectoryFiles($path, $ns, $module), |
70
|
|
|
]; |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Scan a given directory path and return an array with namespace, module and file. |
76
|
|
|
* |
77
|
|
|
* @param string $path |
78
|
|
|
* @param string $ns |
79
|
|
|
* @param string $module The name/id of the module. |
80
|
|
|
* @return array |
81
|
|
|
*/ |
82
|
|
|
protected function scanDirectoryFiles($path, $ns, $module) |
83
|
|
|
{ |
84
|
|
|
$files = []; |
85
|
|
|
foreach (scandir($path) as $file) { |
86
|
|
|
if (substr($file, 0, 1) !== '.') { |
87
|
|
|
$files[] = [ |
88
|
|
|
'file' => $file, |
89
|
|
|
'module' => $module, |
90
|
|
|
'ns' => $ns.'\\'.pathinfo($file, PATHINFO_FILENAME), |
91
|
|
|
]; |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
return $files; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @inheritdoc |
100
|
|
|
*/ |
101
|
|
|
public function getDirectoryFiles($folderName) |
102
|
|
|
{ |
103
|
|
|
$files = []; |
104
|
|
|
if (array_key_exists($folderName, $this->_dirs)) { |
105
|
|
|
foreach ($this->_dirs[$folderName] as $folder) { |
106
|
|
|
foreach ($folder['files'] as $file) { |
107
|
|
|
$files[] = $file; |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
return $files; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
private $_log = []; |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @inheritdoc |
119
|
|
|
*/ |
120
|
|
|
public function addLog($section, $value) |
121
|
|
|
{ |
122
|
|
|
$this->_log[$section][] = $value; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Get all log data. |
127
|
|
|
* |
128
|
|
|
* @return array |
129
|
|
|
*/ |
130
|
|
|
public function getLog() |
131
|
|
|
{ |
132
|
|
|
return $this->_log; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Get all importer objects with the assigned queue position. |
137
|
|
|
* |
138
|
|
|
* @return array If no importer objects are provided the array will is returned empty. |
139
|
|
|
*/ |
140
|
|
|
public function buildImporterQueue() |
141
|
|
|
{ |
142
|
|
|
$queue = []; |
143
|
|
|
foreach (Yii::$app->getApplicationModules() as $id => $module) { |
144
|
|
|
$response = $module->import($this); |
145
|
|
|
// if there response is an array, the it will be added to the queue |
146
|
|
|
if (is_array($response)) { |
147
|
|
|
foreach ($response as $class) { |
148
|
|
|
$object = Yii::createObject($class, [$this, $module]); |
149
|
|
|
$position = $object->queueListPosition; |
150
|
|
|
while (true) { |
151
|
|
|
if (!array_key_exists($position, $queue)) { |
152
|
|
|
break; |
153
|
|
|
} |
154
|
|
|
++$position; |
155
|
|
|
} |
156
|
|
|
$queue[$position] = $object; |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
ksort($queue); |
162
|
|
|
return $queue; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Run the import process. |
167
|
|
|
* |
168
|
|
|
* @return number |
169
|
|
|
*/ |
170
|
|
|
public function actionIndex() |
171
|
|
|
{ |
172
|
|
|
$queue = $this->buildImporterQueue(); |
173
|
|
|
|
174
|
|
|
foreach ($queue as $pos => $object) { |
175
|
|
|
$this->verbosePrint("Run importer object '{$object->className()}' on position '{$pos}'.", __METHOD__); |
176
|
|
|
$this->verbosePrint('Module context id: ' . $object->module->id); |
177
|
|
|
$object->run(); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
if (Yii::$app->hasModule('admin')) { |
181
|
|
|
Config::set(Config::CONFIG_LAST_IMPORT_TIMESTAMP, time()); |
182
|
|
|
Config::set(Config::CONFIG_INSTALLER_VENDOR_TIMESTAMP, Yii::$app->packageInstaller->timestamp); |
183
|
|
|
Yii::$app->db->createCommand()->update('admin_user', ['force_reload' => 1])->execute(); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
$this->output('LUYA import command (based on LUYA ' . Boot::VERSION . ')'); |
187
|
|
|
|
188
|
|
|
foreach ($this->getLog() as $section => $value) { |
189
|
|
|
$this->outputInfo(PHP_EOL . $section . ":"); |
190
|
|
|
$this->logValueToTable($value); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return $this->outputSuccess("Importer run successful."); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Print the log values as a table. |
198
|
|
|
* |
199
|
|
|
* @param array $logs |
200
|
|
|
* @since 1.0.8 |
201
|
|
|
*/ |
202
|
|
|
private function logValueToTable(array $logs) |
203
|
|
|
{ |
204
|
|
|
$table = new Table(); |
205
|
|
|
$table->setHeaders(['Key', 'Value']); |
206
|
|
|
$rows = []; |
207
|
|
|
|
208
|
|
|
foreach ($logs as $key => $value) { |
209
|
|
|
if (is_array($value)) { |
210
|
|
|
foreach ($value as $kk => $kv) { |
211
|
|
|
$rows[] = [$kk, $kv]; |
212
|
|
|
} |
213
|
|
|
} else { |
214
|
|
|
$rows[] = [$key, $value]; |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
$table->setRows($rows); |
218
|
|
|
echo $table->run(); |
219
|
|
|
} |
220
|
|
|
} |
221
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.