Test Failed
Push — develop ( c5c862...2def8e )
by nguereza
02:43
created

VendorPublishCommand::publishLanguage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 0
dl 0
loc 14
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
/**
33
 *  @file VendorPublishCommand.php
34
 *
35
 *  The Composer vendor publish command class
36
 *
37
 *  @package    Platine\Framework\Console\Command
38
 *  @author Platine Developers team
39
 *  @copyright  Copyright (c) 2020
40
 *  @license    http://opensource.org/licenses/MIT  MIT License
41
 *  @link   http://www.iacademy.cf
42
 *  @version 1.0.0
43
 *  @filesource
44
 */
45
46
declare(strict_types=1);
47
48
namespace Platine\Framework\Console\Command;
49
50
use Platine\Config\Config;
51
use Platine\Console\Command\Command;
52
use Platine\Filesystem\DirectoryInterface;
53
use Platine\Filesystem\FileInterface;
54
use Platine\Filesystem\Filesystem;
55
use Platine\Framework\App\Application;
56
use Platine\Stdlib\Helper\Composer;
57
use Platine\Stdlib\Helper\Path;
58
59
/**
60
 * @class VendorPublishCommand
61
 * @package Platine\Framework\Console\Command
62
 * @template T
63
 */
64
class VendorPublishCommand extends Command
65
{
66
67
    /**
68
     * Application instance
69
     * @var Application
70
     */
71
    protected Application $application;
72
73
    /**
74
     * The vendor path
75
     * @var string
76
     */
77
    protected string $vendorPath;
78
79
    /**
80
     * The package installation path
81
     * @var string
82
     */
83
    protected string $packagePath = '';
84
85
    /**
86
     * The file system to use
87
     * @var Filesystem
88
     */
89
    protected Filesystem $filesystem;
90
91
    /**
92
     * Package manifest information
93
     * @var array<string, mixed>
94
     */
95
    protected array $manifest = [];
96
97
    /**
98
     * The configuration to use
99
     * @var Config<T>
100
     */
101
    protected Config $config;
102
103
    /**
104
     * Create new instance
105
     * @param Application $app
106
     * @param Filesystem $filesystem
107
     * @param Config<T> $config
108
     */
109
    public function __construct(
110
        Application $app,
111
        Filesystem $filesystem,
112
        Config $config
113
    ) {
114
        parent::__construct(
115
            'vendor:publish',
116
            'Command to publish composer vendor configuration, migration, language etc.'
117
        );
118
        $this->addArgument('name', 'The package name', null, true);
119
        $this->addOption('-o|--overwrite', 'Overwrite existing files.', false, false);
120
        $this->addOption('-c|--config', 'Publish only the configuration.', false, false);
121
        $this->addOption('-m|--migration', 'Publish only the migrations.', false, false);
122
        $this->addOption('-l|--lang', 'Publish only the languages.', false, false);
123
        $this->addOption('-a|--all', 'Publish all files.', false, false);
124
125
        $this->config = $config;
126
        $this->filesystem = $filesystem;
127
        $this->application = $app;
128
        $this->vendorPath = Path::normalizePathDS($app->getVendorPath(), true);
129
    }
130
131
    /**
132
     * {@inheritodc}
133
     */
134
    public function execute()
135
    {
136
        $writer = $this->io()->writer();
137
        $name = $this->getArgumentValue('name');
138
        $writer->boldGreen(sprintf('PUBLISH OF PACKAGE [%s]', $name), true)->eol();
139
140
        $package = $this->getPackageInfo($name);
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type null; however, parameter $name of Platine\Framework\Consol...mmand::getPackageInfo() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

140
        $package = $this->getPackageInfo(/** @scrutinizer ignore-type */ $name);
Loading history...
141
        if (empty($package)) {
142
            $writer->red(sprintf(
143
                'Can not find the composer package [%s].',
144
                $name
145
            ), true);
146
            return;
147
        }
148
149
        $packagePath = $this->vendorPath . $name;
150
        $packagePath = Path::convert2Absolute($packagePath);
151
152
        $this->packagePath = $packagePath;
153
154
        $writer->bold('Name: ');
155
        $writer->boldBlueBgBlack($package['name'], true);
156
157
        $writer->bold('Description: ');
158
        $writer->boldBlueBgBlack($package['description'], true);
159
160
        $writer->bold('Version: ');
161
        $writer->boldBlueBgBlack($package['version'], true);
162
163
        $writer->bold('Type: ');
164
        $writer->boldBlueBgBlack($package['type'], true);
165
166
        $writer->bold('Path: ');
167
        $writer->boldBlueBgBlack($packagePath, true)->eol();
168
169
        $extras = $package['extra'] ?? [];
170
        $manifest = $extras['platine'] ?? [];
171
172
        if (empty($manifest)) {
173
            $writer->boldGreen('NOTHING TO PUBLISH, COMMAND ENDED!', true);
174
            return;
175
        }
176
177
        $this->manifest = $manifest;
178
179
        $this->publishPackage();
180
181
        $writer->eol();
182
        $writer->boldGreen('Command finished successfully')->eol();
183
    }
184
185
    /**
186
     * Package publication
187
     * @return void
188
     */
189
    protected function publishPackage(): void
190
    {
191
        $all = $this->getOptionValue('all');
192
        if ($all) {
193
            $this->publishAll();
194
            return;
195
        }
196
197
        $config = $this->getOptionValue('config');
198
        if ($config) {
199
            $this->publishConfiguration();
200
        }
201
202
        $migration = $this->getOptionValue('migration');
203
        if ($migration) {
204
            $this->publishMigration();
205
        }
206
207
        $lang = $this->getOptionValue('lang');
208
        if ($lang) {
209
            $this->publishLanguage();
210
        }
211
    }
212
213
    /**
214
     * Publish all assets for this package
215
     * @return void
216
     */
217
    protected function publishAll(): void
218
    {
219
        $this->publishConfiguration();
220
        $this->publishMigration();
221
        $this->publishLanguage();
222
    }
223
224
    /**
225
     * Publish the configuration
226
     * @return void
227
     */
228
    protected function publishConfiguration(): void
229
    {
230
        $writer = $this->io()->writer();
231
        $writer->boldYellow('Publish of package coniguration', true);
232
233
        $manifest = $this->manifest;
234
        $config = $manifest['config'] ?? [];
235
        $destinationPath = Path::normalizePathDS(
236
            $this->application->getConfigPath(),
237
            true
238
        );
239
        foreach ($config as $cfg) {
240
            $this->publishItem($cfg, $destinationPath, 'configuration');
241
        }
242
    }
243
244
    /**
245
     * Publish the language
246
     * @return void
247
     */
248
    protected function publishLanguage(): void
249
    {
250
        $writer = $this->io()->writer();
251
        $writer->boldYellow('Publish of package language', true);
252
253
        $path = Path::convert2Absolute(
254
            $this->config->get('lang.translation_path')
0 ignored issues
show
Bug introduced by
It seems like $this->config->get('lang.translation_path') can also be of type null; however, parameter $path of Platine\Stdlib\Helper\Path::convert2Absolute() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

254
            /** @scrutinizer ignore-type */ $this->config->get('lang.translation_path')
Loading history...
255
        );
256
        $destinationPath = Path::normalizePathDS($path, true);
257
258
        $manifest = $this->manifest;
259
        $languages = $manifest['lang'] ?? [];
260
        foreach ($languages as $language) {
261
            $this->publishItem($language, $destinationPath, 'language');
262
        }
263
    }
264
265
    /**
266
     * Publish the migration
267
     * @return void
268
     */
269
    protected function publishMigration(): void
270
    {
271
        $writer = $this->io()->writer();
272
        $writer->boldYellow('Publish of package migration', true);
273
274
275
        $path = Path::convert2Absolute(
276
            $this->config->get('migration.path', 'migrations')
277
        );
278
        $destinationPath = Path::normalizePathDS($path, true);
279
280
        $manifest = $this->manifest;
281
        $migrations = $manifest['migration'] ?? [];
282
        foreach ($migrations as $migration) {
283
            $this->publishItem($migration, $destinationPath, 'migration');
284
        }
285
    }
286
287
    /**
288
     * Publish asset
289
     * @param string $src
290
     * @param string $dest
291
     * @param string $type
292
     * @return void
293
     */
294
    protected function publishItem(string $src, string $dest, string $type): void
295
    {
296
        $writer = $this->io()->writer();
297
298
        $sourcePath = $this->packagePath . '/' . $src;
299
        $asset = $this->filesystem->get($sourcePath);
300
        if ($asset === null || !$asset->exists()) {
301
            $writer->red(sprintf(
302
                'Can not find the package file %s [%s].',
303
                $type,
304
                $asset->getPath()
305
            ), true);
306
            return;
307
        }
308
309
        if ($asset->isDir()) {
310
            $this->publishDirectory($asset, $dest);
0 ignored issues
show
Bug introduced by
It seems like $asset can also be of type Platine\Filesystem\FileInterface; however, parameter $directory of Platine\Framework\Consol...and::publishDirectory() does only seem to accept Platine\Filesystem\DirectoryInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

310
            $this->publishDirectory(/** @scrutinizer ignore-type */ $asset, $dest);
Loading history...
311
        } elseif ($asset->isFile()) {
312
            $this->publishFile($asset, $dest);
0 ignored issues
show
Bug introduced by
It seems like $asset can also be of type Platine\Filesystem\DirectoryInterface; however, parameter $file of Platine\Framework\Consol...hCommand::publishFile() does only seem to accept Platine\Filesystem\FileInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

312
            $this->publishFile(/** @scrutinizer ignore-type */ $asset, $dest);
Loading history...
313
        }
314
315
        $writer->boldGreen(
316
            sprintf(
317
                'Package %s [%s] publish successfully',
318
                $type,
319
                $src
320
            ),
321
            true
322
        );
323
    }
324
325
    /**
326
     * Copy file to the destination
327
     * @param FileInterface $file
328
     * @param string $dest
329
     * @return void
330
     */
331
    protected function publishFile(FileInterface $file, string $dest): void
332
    {
333
        $sourceFilename = $file->getName();
334
        $destFile = $this->filesystem->file(
335
            $dest . $sourceFilename
336
        );
337
338
        $overwrite = $this->getOptionValue('overwrite');
339
340
        $writer = $this->io()->writer();
341
        if ($destFile->exists() && !$overwrite) {
342
            $writer->red(sprintf(
343
                "File \n[%s]\n already exist, if you want to overwrite"
344
                    . ' use option "--overwrite".',
345
                $destFile->getPath()
346
            ), true);
347
        } else {
348
            $file->copyTo($dest);
349
        }
350
    }
351
352
    /**
353
     * Publish directory
354
     * @param DirectoryInterface $directory
355
     * @param string $dest
356
     * @return void
357
     */
358
    protected function publishDirectory(DirectoryInterface $directory, string $dest): void
359
    {
360
        $directory->copyTo($dest);
361
    }
362
363
    /**
364
     * Return the information for given package
365
     * @param string $name
366
     * @return array<string, mixed>
367
     */
368
    protected function getPackageInfo(string $name): array
369
    {
370
        $packages = Composer::parseLockFile($this->application->getAppPath());
371
        foreach ($packages as $package) {
372
            $packageName = $package['name'] ?? '';
373
            if ($name === $packageName) {
374
                return $package;
375
            }
376
        }
377
378
        return [];
379
    }
380
}
381