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