Issues (54)

src/Install/ModuleManager/Module.php (6 issues)

1
<?php
2
3
namespace BFW\Install\ModuleManager;
4
5
use Exception;
6
use bultonFr\Utils\Files\FileManager;
7
8
class Module
9
{
10
    /**
11
     * @const EXCEP_DELETE_ENABLED_MODULE Exception code if the user want
12
     * delete a module which is always enabled.
13
     */
14
    const EXCEP_DELETE_ENABLED_MODULE = 1702001;
15
    
16
    /**
17
     * The monolog logger instance
18
     *
19
     * @var \Monolog\Logger $logger
20
     */
21
    protected $logger;
22
23
    /**
24
     * The FileManager instance used to do action on files
25
     *
26
     * @var \bultonFr\Utils\Files\FileManager $fileManager
27
     */
28
    protected $fileManager;
29
    
30
    /**
31
     * The module's name
32
     *
33
     * @var string
34
     */
35
    protected $name;
36
    
37
    /**
38
     * The path to the source of the module in the vendor directory
39
     * The value is set by a setter only, so is possible the value is not
40
     * into the vendor directory if the user not send that.
41
     *
42
     * Used only with the add action.
43
     *
44
     * @var string
45
     */
46
    protected $vendorPath = '';
47
    
48
    /**
49
     * The path of the module into /app/modules/available folder
50
     *
51
     * @var string
52
     */
53
    protected $availablePath = '';
54
    
55
    /**
56
     * The path of the module into /app/modules/enabled folder
57
     *
58
     * @var string
59
     */
60
    protected $enabledPath = '';
61
    
62
    /**
63
     * The path of the config module into /app/config folder
64
     *
65
     * @var string
66
     */
67
    protected $configPath = '';
68
    
69
    /**
70
     * The class which contain info abouts the module
71
     *
72
     * @var \BFW\Install\ModuleManager\ModulesInfo|null
0 ignored issues
show
The type BFW\Install\ModuleManager\ModulesInfo was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
73
     */
74
    protected $info;
75
    
76
    /**
77
     * Constructor
78
     *
79
     * Obtain the logger instance.
80
     * Instanciate the FileManager.
81
     * Define paths into /app/modules/* and /app/config.
82
     *
83
     * @param string $name The module's name
84
     */
85
    public function __construct(string $name)
86
    {
87
        $this->logger = \BFW\Application::getInstance()
88
            ->getMonolog()
89
            ->getLogger()
90
        ;
91
92
        $this->fileManager = new FileManager($this->logger);
93
        
94
        $this->name          = $name;
95
        $this->availablePath = MODULES_AVAILABLE_DIR.$name;
0 ignored issues
show
The constant BFW\Install\ModuleManager\MODULES_AVAILABLE_DIR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
96
        $this->enabledPath   = MODULES_ENABLED_DIR.$name;
0 ignored issues
show
The constant BFW\Install\ModuleManager\MODULES_ENABLED_DIR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
97
        $this->configPath    = CONFIG_DIR.$name;
0 ignored issues
show
The constant BFW\Install\ModuleManager\CONFIG_DIR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
98
    }
99
100
    /**
101
     * Get the value of logger
102
     *
103
     * @return \Monolog\Logger
104
     */
105
    public function getLogger(): \Monolog\Logger
106
    {
107
        return $this->logger;
108
    }
109
110
    /**
111
     * Get the value of fileManager
112
     *
113
     * @return \bultonFr\Utils\Files\FileManager
114
     */
115
    public function getFileManager(): FileManager
116
    {
117
        return $this->fileManager;
118
    }
119
    
120
    /**
121
     * Get the value of name
122
     *
123
     * @return string
124
     */
125
    public function getName(): string
126
    {
127
        return $this->name;
128
    }
129
130
    /**
131
     * Get the value of vendorPath
132
     *
133
     * @return string
134
     */
135
    public function getVendorPath(): string
136
    {
137
        return $this->vendorPath;
138
    }
139
    
140
    /**
141
     * Set the value of vendorPath
142
     *
143
     * @param string $path The path of the module into vendor
144
     *
145
     * @return $this
146
     */
147
    public function setVendorPath(string $path): self
148
    {
149
        $this->vendorPath = $path;
150
151
        return $this;
152
    }
153
154
    /**
155
     * Get the value of availablePath
156
     *
157
     * @return string
158
     */
159
    public function getAvailablePath(): string
160
    {
161
        return $this->availablePath;
162
    }
163
164
    /**
165
     * Get the value of enabledPath
166
     *
167
     * @return string
168
     */
169
    public function getEnabledPath(): string
170
    {
171
        return $this->enabledPath;
172
    }
173
174
    /**
175
     * Get the value of configPath
176
     *
177
     * @return string
178
     */
179
    public function getConfigPath(): string
180
    {
181
        return $this->configPath;
182
    }
183
184
    /**
185
     * Get the value of info
186
     *
187
     * @return \BFW\Install\ModuleManager\ModulesInfo|null
188
     */
189
    public function getInfo()
190
    {
191
        return $this->info;
192
    }
193
    
194
    /**
195
     * Execute the installation action
196
     * * Create a symlink from module in vendor into /app/modules/available
197
     * * Create config directory for the module
198
     * * Copy configs files
199
     *
200
     * @return void
201
     */
202
    public function doAdd()
203
    {
204
        $this->readModuleInfo($this->vendorPath);
205
        $this->fileManager->createSymLink(
206
            $this->vendorPath,
207
            $this->availablePath
208
        );
209
        $this->copyAllConfigFiles();
210
    }
211
    
212
    /**
213
     * Execute the enable action
214
     * * Create the symlink from module in /app/modules/available into
215
     *   /app/modules/enabled
216
     *
217
     * @return void
218
     */
219
    public function doEnable()
220
    {
221
        $this->readModuleInfo($this->availablePath);
222
        $srcPath = $this->info->getSrcPath();
223
        
224
        $this->fileManager->createSymLink(
225
            $this->availablePath.'/'.$srcPath,
226
            $this->enabledPath
227
        );
228
    }
229
    
230
    /**
231
     * Execute the disable action
232
     * * Remove the symlink into /app/modules/enabled
233
     *
234
     * @return void
235
     */
236
    public function doDisable()
237
    {
238
        $this->readModuleInfo($this->availablePath);
239
        $this->fileManager->removeSymLink($this->enabledPath);
240
    }
241
    
242
    /**
243
     * Execute the delete action
244
     * * Remove the module's directory into /app/modules/available
245
     * * Remove module's config files
246
     *
247
     * @return void
248
     */
249
    public function doDelete()
250
    {
251
        $this->readModuleInfo($this->availablePath);
252
        
253
        if (file_exists($this->enabledPath)) {
254
            throw new Exception(
255
                'Module '.$this->name.' is always enabled. Please disable it before delete',
256
                static::EXCEP_DELETE_ENABLED_MODULE
257
            );
258
        }
259
        
260
        if (is_link($this->availablePath)) {
261
            $this->fileManager->removeSymLink($this->availablePath);
262
        } else {
263
            $this->fileManager->removeRecursiveDirectory($this->availablePath);
264
        }
265
266
        $this->deleteConfigFiles();
267
    }
268
    
269
    /**
270
     * Instanciate the moduleInfo class.
271
     *
272
     * @param string $modulePath The module's path
273
     *
274
     * @return void
275
     */
276
    protected function readModuleInfo(string $modulePath)
277
    {
278
        $this->logger->debug(
279
            'Module - Read module info',
280
            ['name' => $this->name, 'path' => $modulePath]
281
        );
282
        
283
        $moduleInfo = \BFW\Module::installInfo($modulePath);
284
        $this->info = new ModuleInfo($moduleInfo);
0 ignored issues
show
Documentation Bug introduced by
It seems like new BFW\Install\ModuleMa...ModuleInfo($moduleInfo) of type BFW\Install\ModuleManager\ModuleInfo is incompatible with the declared type BFW\Install\ModuleManager\ModulesInfo|null of property $info.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
285
    }
286
    
287
    /**
288
     * Copy all module's declared config files.
289
     *
290
     * @return void
291
     */
292
    protected function copyAllConfigFiles()
293
    {
294
        $sourceConfigPath = $this->availablePath.'/'.$this->info->getConfigPath();
0 ignored issues
show
The method getConfigPath() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

294
        $sourceConfigPath = $this->availablePath.'/'.$this->info->/** @scrutinizer ignore-call */ getConfigPath();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
295
        
296
        $this->logger->debug(
297
            'Module - Copy config files',
298
            [
299
                'name'             => $this->name,
300
                'configPath'       => $this->configPath,
301
                'sourceConfigPath' => $sourceConfigPath,
302
                'configFiles'      => $this->info->getConfigFiles()
303
            ]
304
        );
305
        
306
        $configFileList = $this->info->getConfigFiles(); //Need tmp var for empty()
307
        if (empty($configFileList)) {
308
            return;
309
        }
310
        
311
        if (file_exists($this->configPath) === false) {
312
            $this->fileManager->createDirectory($this->configPath);
313
        }
314
315
        $this->copyConfigFile(
316
            $sourceConfigPath.'manifest.json',
317
            $this->configPath.'/manifest.json'
318
        );
319
320
        foreach ($configFileList as $configFilename) {
321
            $this->copyConfigFile(
322
                $sourceConfigPath.$configFilename,
323
                $this->configPath.'/'.$configFilename
324
            );
325
        }
326
    }
327
328
    /**
329
     * Copy a config file.
330
     *
331
     * @param string $sourcePath The source file path
332
     * @param string $destPath the destination file path
333
     *
334
     * @return void
335
     */
336
    protected function copyConfigFile(string $sourcePath, string $destPath)
337
    {
338
        try {
339
            $this->fileManager->copyFile($sourcePath, $destPath);
340
        } catch (Exception $e) {
341
            if ($e->getCode() !== FileManager::EXCEP_FILE_EXIST) {
342
                throw $e;
343
            }
344
        }
345
    }
346
    
347
    /**
348
     * Delete all module's config files and the module's directory in /app/config
349
     *
350
     * @return void
351
     */
352
    protected function deleteConfigFiles()
353
    {
354
        $this->logger->debug(
355
            'Module - Delete config files',
356
            ['name' => $this->name, 'configPath' => $this->configPath]
357
        );
358
        
359
        if (file_exists($this->configPath) === false) {
360
            return;
361
        }
362
        
363
        $this->fileManager->removeRecursiveDirectory($this->configPath);
364
    }
365
    
366
    /**
367
     * Check if the module has a installation script.
368
     *
369
     * @return boolean
370
     */
371
    public function hasInstallScript(): bool
372
    {
373
        $installScript = $this->info->getInstallScript(); //For empty()
374
375
        if (empty($installScript)) {
376
            return false;
377
        }
378
        
379
        return true;
380
    }
381
    
382
    /**
383
     * Execute the module installation script into the scope of the method.
384
     *
385
     * @return void
386
     */
387
    public function runInstallScript()
388
    {
389
        if ($this->hasInstallScript() === false) {
390
            return;
391
        }
392
        
393
        $this->logger->debug(
394
            'Module - Run install script',
395
            [
396
                'name'          => $this->name,
397
                'installScript' => $this->info->getInstallScript()
398
            ]
399
        );
400
        
401
        require_once($this->availablePath.'/'.$this->info->getInstallScript());
402
    }
403
}
404