Completed
Push — master ( b4d6a5...352f6d )
by Basil
02:42
created

ImportController   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
wmc 29
lcom 2
cbo 4
dl 0
loc 196
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getLog() 0 4 1
B buildImporterQueue() 0 24 6
A logValueToTable() 0 18 4
A init() 0 15 4
A addToDirectory() 0 11 2
A scanDirectoryFiles() 0 16 3
A getDirectoryFiles() 0 13 4
A addLog() 0 4 1
A actionIndex() 0 25 4
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');
0 ignored issues
show
Bug introduced by
It seems like \Yii::getAlias("@app/{$folderName}") targeting yii\BaseYii::getAlias() can also be of type boolean; however, luya\console\commands\Im...oller::addToDirectory() does only seem to accept string, maybe add an additional type check?

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.

Loading history...
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