Issues (426)

src/Commands/Build.php (2 issues)

Labels
Severity
1
<?php
2
3
namespace A17\Twill\Commands;
4
5
use Illuminate\Filesystem\Filesystem;
6
use Symfony\Component\Process\Process;
7
8
class Build extends Command
9
{
10
    /**
11
     * The name and signature of the console command.
12
     *
13
     * @var string
14
     */
15
    protected $signature = 'twill:build {--noInstall} {--hot} {--watch} {--copyOnly}';
16
17
    /**
18
     * The console command description.
19
     *
20
     * @var string
21
     */
22
    protected $description = "Build Twill assets with custom Vue components/blocks";
23
24
    /**
25
     * @var Filesystem
26
     */
27
    protected $filesystem;
28
29
    /**
30
     * @param Filesystem $filesystem
31
     */
32 69
    public function __construct(Filesystem $filesystem)
33
    {
34 69
        parent::__construct();
35
36 69
        $this->filesystem = $filesystem;
37 69
    }
38
39
    /*
40
     * Executes the console command.
41
     *
42
     * @return mixed
43
     */
44
    public function handle()
45
    {
46
        if ($this->option("copyOnly")) {
47
            return $this->copyCustoms();
0 ignored issues
show
Are you sure the usage of $this->copyCustoms() targeting A17\Twill\Commands\Build::copyCustoms() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
48
        }
49
50
        return $this->fullBuild();
0 ignored issues
show
Are you sure the usage of $this->fullBuild() targeting A17\Twill\Commands\Build::fullBuild() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
51
    }
52
53
    /*
54
     * @return void
55
     */
56
    private function fullBuild()
57
    {
58
        $progressBar = $this->output->createProgressBar(5);
59
        $progressBar->setFormat("%current%/%max% [%bar%] %message%");
60
61
        $npmInstall = !$this->option('noInstall');
62
63
        $progressBar->setMessage(($npmInstall ? "Installing" : "Reusing") . " npm dependencies...\n\n");
64
65
        $progressBar->start();
66
67
        if ($npmInstall) {
68
            $this->runProcessInTwill(['npm', 'ci']);
69
        } else {
70
            sleep(1);
71
        }
72
73
        $this->info('');
74
        $progressBar->setMessage("Copying custom blocks...\n\n");
75
        $progressBar->advance();
76
77
        $this->copyBlocks();
78
        sleep(1);
79
80
        $this->info('');
81
        $progressBar->setMessage("Copying custom components...\n\n");
82
        $progressBar->advance();
83
84
        $this->copyComponents();
85
        sleep(1);
86
87
        $this->info('');
88
        $progressBar->setMessage("Building assets...\n\n");
89
        $progressBar->advance();
90
91
        if ($this->option('hot')) {
92
            $this->startWatcher(resource_path('assets/js/**/*.vue'), 'php artisan twill:build --copyOnly');
93
            $this->runProcessInTwill(['npm', 'run', 'serve', '--', "--port={$this->getDevPort()}"], true);
94
        } elseif ($this->option('watch')) {
95
            $this->startWatcher(resource_path('assets/js/**/*.vue'), 'php artisan twill:build --copyOnly');
96
            $this->runProcessInTwill(['npm', 'run', 'watch'], true);
97
        } else {
98
            $this->runProcessInTwill(['npm', 'run', 'build']);
99
100
            $this->info('');
101
            $progressBar->setMessage("Publishing assets...\n\n");
102
            $progressBar->advance();
103
            $this->call('twill:update');
104
105
            $this->info('');
106
            $progressBar->setMessage("Done.");
107
            $progressBar->finish();
108
        }
109
    }
110
111
    /**
112
     * @return string
113
     */
114
    private function getDevPort()
115
    {
116
        preg_match('/^.*:(\d+)/', config('twill.dev_mode_url'), $matches);
117
118
        return $matches[1] ?? '8080';
119
    }
120
121
    /**
122
     * @return void
123
     */
124
    private function startWatcher($pattern, $command)
125
    {
126
        if (empty($this->filesystem->glob($pattern))) {
127
            return;
128
        }
129
130
        $chokidarPath = base_path(config('twill.vendor_path')) . '/node_modules/.bin/chokidar';
131
        $chokidarCommand = [$chokidarPath, $pattern, "-c", $command];
132
133
        if ($this->filesystem->exists($chokidarPath)) {
134
            $process = new Process($chokidarCommand, base_path());
135
            $process->setTty(Process::isTtySupported());
136
            $process->setTimeout(null);
137
138
            try {
139
                $process->start();
140
            } catch(\Exception $e) {
141
                $this->warn("Could not start the chokidar watcher ({$e->getMessage()})\n");
142
            }
143
        } else {
144
            $this->warn("The `chokidar-cli` package was not found. It is required to watch custom blocks & components in development. You can install it by running:\n");
145
            $this->warn("    php artisan twill:dev\n");
146
            $this->warn("without the `--noInstall` option.\n");
147
            sleep(2);
148
        }
149
    }
150
151
    /**
152
     * @return void
153
     */
154
    private function runProcessInTwill(array $command, $disableTimeout = false)
155
    {
156
        $process = new Process($command, base_path(config('twill.vendor_path')));
157
        $process->setTty(Process::isTtySupported());
158
159
        if ($disableTimeout) {
160
            $process->setTimeout(null);
161
        } else {
162
            $process->setTimeout(config('twill.build_timeout', 300));
163
        }
164
165
        $process->mustRun();
166
    }
167
168
    /*
169
     * @return void
170
     */
171
    private function copyCustoms()
172
    {
173
        $this->info("Copying custom blocks & components...");
174
        $this->copyBlocks();
175
        $this->copyComponents();
176
        $this->info("Done.");
177
    }
178
179
    /**
180
     * @return void
181
     */
182
    private function copyBlocks()
183
    {
184
        $localCustomBlocksPath = resource_path(config('twill.block_editor.custom_vue_blocks_resource_path', 'assets/js/blocks'));
185
        $twillCustomBlocksPath = base_path(config('twill.vendor_path')) . '/frontend/js/components/blocks/customs';
186
187
        if (!$this->filesystem->exists($twillCustomBlocksPath)) {
188
            $this->filesystem->makeDirectory($twillCustomBlocksPath, 0755, true);
189
        }
190
191
        $this->filesystem->cleanDirectory($twillCustomBlocksPath);
192
193
        if ($this->filesystem->exists($localCustomBlocksPath)) {
194
            $this->filesystem->copyDirectory($localCustomBlocksPath, $twillCustomBlocksPath);
195
        }
196
    }
197
198
    /**
199
     * @return void
200
     */
201
    private function copyComponents()
202
    {
203
        $localCustomComponentsPath = resource_path(config('twill.custom_components_resource_path', 'assets/js/components'));
204
        $twillCustomComponentsPath = base_path(config('twill.vendor_path')) . '/frontend/js/components/customs';
205
206
        if (!$this->filesystem->exists($twillCustomComponentsPath)) {
207
            $this->filesystem->makeDirectory($twillCustomComponentsPath, 0755, true);
208
        }
209
210
        $this->filesystem->cleanDirectory($twillCustomComponentsPath);
211
212
        if ($this->filesystem->exists($localCustomComponentsPath)) {
213
            $this->filesystem->copyDirectory($localCustomComponentsPath, $twillCustomComponentsPath);
214
        }
215
    }
216
}
217