VendorPublishCommand::publishDirectory()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 2
b 0
f 0
nc 2
nop 2
dl 0
loc 4
rs 10
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   https://www.platine-php.com
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
     * The vendor path
68
     * @var string
69
     */
70
    protected string $vendorPath;
71
72
    /**
73
     * The package installation path
74
     * @var string
75
     */
76
    protected string $packagePath = '';
77
78
    /**
79
     * Package manifest information
80
     * @var array<string, mixed>
81
     */
82
    protected array $manifest = [];
83
84
85
    /**
86
     * Create new instance
87
     * @param Application $application
88
     * @param Filesystem $filesystem
89
     * @param Config<T> $config
90
     */
91
    public function __construct(
92
        protected Application $application,
93
        protected Filesystem $filesystem,
94
        protected Config $config
95
    ) {
96
        parent::__construct(
97
            'vendor:publish',
98
            'Command to publish composer vendor configuration, migration, language etc.'
99
        );
100
101
        $this->addArgument('name', 'The package name', null, true);
102
        $this->addOption('-o|--overwrite', 'Overwrite existing files.', false, false);
103
        $this->addOption('-c|--config', 'Publish only the configuration.', false, false);
104
        $this->addOption('-m|--migration', 'Publish only the migrations.', false, false);
105
        $this->addOption('-l|--lang', 'Publish only the languages.', false, false);
106
        $this->addOption('-t|--template', 'Publish only the templates.', false, false);
107
        $this->addOption('-a|--all', 'Publish all files.', false, false);
108
109
        $this->vendorPath = Path::normalizePathDS($application->getVendorPath(), true);
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115
    public function execute(): mixed
116
    {
117
        $writer = $this->io()->writer();
118
        $name = $this->getArgumentValue('name');
119
        $writer->boldGreen(sprintf('PUBLISH OF PACKAGE [%s]', $name), true)->eol();
120
121
        $package = $this->getPackageInfo($name);
122
        if (count($package) === 0) {
123
            $writer->red(sprintf(
124
                'Can not find the composer package [%s].',
125
                $name
126
            ), true);
127
            return true;
128
        }
129
130
        $packagePath = $this->vendorPath . $name;
131
        $packagePath = Path::convert2Absolute($packagePath);
132
        $this->packagePath = $packagePath;
133
134
        $writer->bold('Name: ');
135
        $writer->boldBlueBgBlack($package['name'], true);
136
137
        $writer->bold('Description: ');
138
        $writer->boldBlueBgBlack($package['description'], true);
139
140
        $writer->bold('Version: ');
141
        $writer->boldBlueBgBlack($package['version'], true);
142
143
        $writer->bold('Type: ');
144
        $writer->boldBlueBgBlack($package['type'], true);
145
146
        $writer->bold('Path: ');
147
        $writer->boldBlueBgBlack($packagePath, true)->eol();
148
149
        $extras = $package['extra'] ?? [];
150
        $manifest = $extras['platine'] ?? [];
151
152
        if (count($manifest) === 0) {
153
            $writer->boldGreen('NOTHING TO PUBLISH, COMMAND ENDED!', true);
154
            return true;
155
        }
156
        $this->manifest = $manifest;
157
158
        $this->publishPackage();
159
160
        $writer->eol();
161
        $writer->boldGreen('Command finished successfully')->eol();
162
163
        return true;
164
    }
165
166
    /**
167
     * Package publication
168
     * @return void
169
     */
170
    protected function publishPackage(): void
171
    {
172
        $all = $this->getOptionValue('all');
173
        if ($all) {
174
            $this->publishAll();
175
            return;
176
        }
177
178
        $config = $this->getOptionValue('config');
179
        if ($config) {
180
            $this->publishConfiguration();
181
        }
182
183
        $migration = $this->getOptionValue('migration');
184
        if ($migration) {
185
            $this->publishMigration();
186
        }
187
188
        $lang = $this->getOptionValue('lang');
189
        if ($lang) {
190
            $this->publishLanguage();
191
        }
192
193
        $template = $this->getOptionValue('template');
194
        if ($template) {
195
            $this->publishTemplate();
196
        }
197
    }
198
199
    /**
200
     * Publish all assets for this package
201
     * @return void
202
     */
203
    protected function publishAll(): void
204
    {
205
        $this->publishConfiguration();
206
        $this->publishMigration();
207
        $this->publishLanguage();
208
        $this->publishTemplate();
209
    }
210
211
    /**
212
     * Publish the configuration
213
     * @return void
214
     */
215
    protected function publishConfiguration(): void
216
    {
217
        $writer = $this->io()->writer();
218
        $writer->boldYellow('Publish of package configuration', true);
219
220
        $manifest = $this->manifest;
221
        $config = $manifest['config'] ?? [];
222
        $destinationPath = Path::normalizePathDS(
223
            $this->application->getConfigPath(),
224
            true
225
        );
226
        foreach ($config as $cfg) {
227
            $this->publishItem($cfg, $destinationPath, 'configuration');
228
        }
229
    }
230
231
    /**
232
     * Publish the language
233
     * @return void
234
     */
235
    protected function publishLanguage(): void
236
    {
237
        $writer = $this->io()->writer();
238
        $writer->boldYellow('Publish of package language', true);
239
240
        $path = Path::convert2Absolute(
241
            $this->config->get('lang.translation_path')
242
        );
243
        $destinationPath = Path::normalizePathDS($path, true);
244
245
        $manifest = $this->manifest;
246
        $languages = $manifest['lang'] ?? [];
247
        foreach ($languages as $language) {
248
            $this->publishItem($language, $destinationPath, 'language');
249
        }
250
    }
251
252
    /**
253
     * Publish the migration
254
     * @return void
255
     */
256
    protected function publishMigration(): void
257
    {
258
        $writer = $this->io()->writer();
259
        $writer->boldYellow('Publish of package migration', true);
260
261
        $path = Path::convert2Absolute(
262
            $this->config->get('database.migration.path', 'migrations')
263
        );
264
        $destinationPath = Path::normalizePathDS($path, true);
265
266
        $manifest = $this->manifest;
267
        $migrations = $manifest['migration'] ?? [];
268
        foreach ($migrations as $migration) {
269
            $this->publishItem($migration, $destinationPath, 'migration');
270
        }
271
    }
272
273
    /**
274
     * Publish the template
275
     * @return void
276
     */
277
    protected function publishTemplate(): void
278
    {
279
        $writer = $this->io()->writer();
280
        $writer->boldYellow('Publish of package template', true);
281
282
        $path = Path::convert2Absolute(
283
            $this->config->get('template.template_dir', 'templates')
284
        );
285
        $destinationPath = Path::normalizePathDS($path, true);
286
287
        $manifest = $this->manifest;
288
        $templates = $manifest['template'] ?? [];
289
        foreach ($templates as $template) {
290
            $this->publishItem($template, $destinationPath, 'template');
291
        }
292
    }
293
294
    /**
295
     * Publish asset
296
     * @param string $src
297
     * @param string $dest
298
     * @param string $type
299
     * @return void
300
     */
301
    protected function publishItem(string $src, string $dest, string $type): void
302
    {
303
        $writer = $this->io()->writer();
304
        $sourcePath = $this->packagePath . '/' . $src;
305
        $asset = $this->filesystem->get($sourcePath);
306
        if ($asset === null) {
307
            $writer->red(sprintf(
308
                'Can not find the package file %s [%s].',
309
                $type,
310
                $sourcePath
311
            ), true);
312
            return;
313
        }
314
315
        if ($asset instanceof DirectoryInterface) {
316
            $this->publishDirectory($asset, $dest);
317
        } elseif ($asset instanceof FileInterface) {
0 ignored issues
show
introduced by
$asset is always a sub-type of Platine\Filesystem\FileInterface.
Loading history...
318
            $this->publishFile($asset, $dest);
319
        }
320
321
        $writer->boldGreen(
322
            sprintf(
323
                'Package %s [%s] publish successfully',
324
                $type,
325
                $src
326
            ),
327
            true
328
        );
329
    }
330
331
    /**
332
     * Copy file to the destination
333
     * @param FileInterface $file
334
     * @param string $dest
335
     * @return void
336
     */
337
    protected function publishFile(FileInterface $file, string $dest): void
338
    {
339
        $sourceFilename = $file->getName();
340
        $destFile = $this->filesystem->file(
341
            $dest . $sourceFilename
342
        );
343
344
        $overwrite = $this->getOptionValue('overwrite');
345
        $writer = $this->io()->writer();
346
        if ($destFile->exists() && !$overwrite) {
347
            $writer->red(sprintf(
348
                "File [%s] already exist, if you want to overwrite"
349
                    . ' use option "--overwrite".',
350
                $destFile->getPath()
351
            ), true);
352
        } else {
353
            $file->copyTo($dest);
354
        }
355
    }
356
357
    /**
358
     * Publish directory
359
     * @param DirectoryInterface $directory
360
     * @param string $dest
361
     * @return void
362
     */
363
    protected function publishDirectory(DirectoryInterface $directory, string $dest): void
364
    {
365
        foreach ($directory->read() as $item) {
366
            $item->copyTo($dest);
367
        }
368
    }
369
370
    /**
371
     * Return the information for given package
372
     * @param string $name
373
     * @return array<string, mixed>
374
     */
375
    protected function getPackageInfo(string $name): array
376
    {
377
        $packages = Composer::parseLockFile($this->application->getRootPath());
378
        foreach ($packages as $package) {
379
            $packageName = $package['name'] ?? '';
380
            if ($name === $packageName) {
381
                return $package;
382
            }
383
        }
384
385
        return [];
386
    }
387
}
388