Passed
Push — v1 ( 974e3b...6f7629 )
by Andrew
04:28 queued 13s
created

ViteService::devServerRunning()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 4
b 0
f 0
nc 3
nop 0
dl 0
loc 14
rs 10
1
<?php
2
/**
3
 * Vite plugin for Craft CMS 3.x
4
 *
5
 * Allows the use of the Vite.js next generation frontend tooling with Craft CMS
6
 *
7
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) 2021 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\pluginvite\services;
12
13
use Craft;
14
use craft\base\Component;
15
use craft\helpers\Html as HtmlHelper;
16
use craft\helpers\Json as JsonHelper;
17
use craft\helpers\UrlHelper;
18
19
use yii\base\InvalidConfigException;
20
use yii\caching\ChainedDependency;
21
use yii\caching\FileDependency;
22
use yii\caching\TagDependency;
23
24
use GuzzleHttp\Client;
25
use GuzzleHttp\RequestOptions;
26
27
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
28
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
29
 * @package   Vite
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
30
 * @since     1.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
31
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
32
class ViteService extends Component
33
{
34
    // Constants
35
    // =========================================================================
36
37
    const VITE_CLIENT = '@vite/client.js';
38
    const LEGACY_EXTENSION = '-legacy.';
39
    const LEGACY_POLYFILLS = 'vite/legacy-polyfills';
40
41
    const CACHE_KEY = 'vite';
42
    const CACHE_TAG = 'vite';
43
44
    const DEVMODE_CACHE_DURATION = 1;
45
46
    const USER_AGENT_STRING = 'User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13';
47
48
    const SAFARI_NOMODULE_FIX = '!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()},!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();';
49
50
    // Public Properties
51
    // =========================================================================
52
53
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
54
     * @var bool Should the dev server be used for?
55
     */
56
    public $useDevServer;
57
58
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
59
     * @var string File system path (or URL) to the Vite-built manifest.json
60
     */
61
    public $manifestPath;
62
63
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
64
     * @var string The public URL to the dev server (what appears in `<script src="">` tags
65
     */
66
    public $devServerPublic;
67
68
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
69
     * @var string The public URL to use when not using the dev server
70
     */
71
    public $serverPublic;
72
73
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
74
     * @var string String to be appended to the cache key
75
     */
76
    public $cacheKeySuffix = '';
77
78
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
79
     * @var string The internal URL to the dev server, when accessed from the environment in which PHP is executing
80
     *              This can be the same as `$devServerPublic`, but may be different in containerized or VM setups.
81
     *              ONLY used if $checkDevServer = true
82
     */
83
    public $devServerInternal;
84
85
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
86
     * @var bool Should we check for the presence of the dev server by pinging $devServerInternal to make sure it's running?
87
     */
88
    public $checkDevServer = false;
89
90
    // Protected Properties
91
    // =========================================================================
92
93
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
94
     * @var bool Whether any legacy tags were found in this request
95
     */
96
    protected $hasLegacyTags = false;
97
98
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
99
     * @var bool Whether the legacy polyfill has been included yet or not
100
     */
101
    protected $legacyPolyfillIncluded = false;
102
103
    // Public Methods
104
    // =========================================================================
105
106
    /**
107
     * Return the appropriate tags to load the Vite script, either via the dev server or
108
     * extracting it from the manifest.json file
109
     *
110
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
111
     * @param bool $asyncCss
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
112
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
113
     * @param array $cssTagAttrs
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
114
     *
115
     * @return string
116
     */
117
    public function script(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = []): string
118
    {
119
        if ($this->devServerRunning()) {
120
            return $this->devServerScript($path, $scriptTagAttrs);
121
        }
122
123
        return $this->manifestScript($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
124
    }
125
126
    /**
127
     * Return the script tag to load the script from the Vite dev server
128
     *
129
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
130
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
131
     *
132
     * @return string
133
     */
134
    public function devServerScript(string $path, array $scriptTagAttrs = []): string
135
    {
136
        $lines = [];
137
        // Include the entry script
138
        $url = $this->createUrl($this->devServerPublic, $path);
139
        $lines[] = HtmlHelper::jsFile($url, array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
140
            'type' => 'module',
141
        ], $scriptTagAttrs));
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
142
143
        return implode("\r\n", $lines);
144
    }
145
146
    /**
147
     * Return the script, module link, and CSS link tags for the script from the manifest.json file
148
     *
149
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
150
     * @param bool $asyncCss
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
151
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
152
     * @param array $cssTagAttrs
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
153
     *
154
     * @return string
155
     */
156
    public function manifestScript(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = []): string
157
    {
158
        $lines = [];
159
        $tags = $this->manifestTags($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
160
        // Handle any legacy polyfills
161
        if ($this->hasLegacyTags && !$this->legacyPolyfillIncluded) {
162
            $lines[] = HtmlHelper::script(self::SAFARI_NOMODULE_FIX, []);
163
            $legacyPolyfillTags = $this->extractManifestTags(self::LEGACY_POLYFILLS, $asyncCss, $scriptTagAttrs, $cssTagAttrs, true);
164
            $tags = array_merge($legacyPolyfillTags, $tags);
165
            $this->legacyPolyfillIncluded = true;
166
        }
167
        foreach($tags as $tag) {
0 ignored issues
show
Coding Style introduced by
Expected "foreach (...) {\n"; found "foreach(...) {\n"
Loading history...
168
            if (!empty($tag)) {
169
                switch ($tag['type']) {
170
                    case 'file':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
171
                        $lines[] = HtmlHelper::jsFile($tag['url'], $tag['options']);
172
                        break;
173
                    case 'css':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
174
                        $lines[] = HtmlHelper::cssFile($tag['url'], $tag['options']);
175
                        break;
176
                    default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
177
                        break;
178
                }
179
            }
180
        }
181
182
        return implode("\r\n", $lines);
183
    }
184
185
    /**
186
     * Register the appropriate tags to the Craft View to load the Vite script, either via the dev server or
187
     * extracting it from the manifest.json file
188
     *
189
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
190
     * @param bool $asyncCss
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
191
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
192
     * @param array $cssTagAttrs
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
193
     *
194
     * @return void
195
     * @throws InvalidConfigException
196
     */
197
    public function register(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = [])
198
    {
199
        if ($this->devServerRunning()) {
200
            $this->devServerRegister($path, $scriptTagAttrs);
201
202
            return;
203
        }
204
205
        $this->manifestRegister($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
206
    }
207
208
    /**
209
     * Register the script tag to the Craft View to load the script from the Vite dev server
210
     *
211
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
212
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
213
     *
214
     * @return void
215
     */
216
    public function devServerRegister(string $path, array $scriptTagAttrs = [])
217
    {
218
        $view = Craft::$app->getView();
219
        // Include the entry script
220
        $url = $this->createUrl($this->devServerPublic, $path);
221
        $view->registerScript('', $view::POS_HEAD, array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
222
            'type' => 'module',
223
            'src' => $url,
224
            ], $scriptTagAttrs));
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
225
    }
226
227
    /**
228
     * Register the script, module link, and CSS link tags to the Craft View for the script from the manifest.json file
229
     *
230
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
231
     * @param bool $asyncCss
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
232
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
233
     * @param array $cssTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
234
     *
235
     * @return void
236
     * @throws InvalidConfigException
237
     */
238
    public function manifestRegister(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = [])
239
    {
240
        $view = Craft::$app->getView();
241
        $tags = $this->manifestTags($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
242
        // Handle any legacy polyfills
243
        if ($this->hasLegacyTags && !$this->legacyPolyfillIncluded) {
244
            $view->registerScript(self::SAFARI_NOMODULE_FIX, $view::POS_HEAD, [], 'SAFARI_NOMODULE_FIX');
245
            $legacyPolyfillTags = $this->extractManifestTags(self::LEGACY_POLYFILLS, $asyncCss, $scriptTagAttrs, $cssTagAttrs, true);
246
            $tags = array_merge($legacyPolyfillTags, $tags);
247
            $this->legacyPolyfillIncluded = true;
248
        }
249
        foreach($tags as $tag) {
0 ignored issues
show
Coding Style introduced by
Expected "foreach (...) {\n"; found "foreach(...) {\n"
Loading history...
250
            if (!empty($tag)) {
251
                switch ($tag['type']) {
252
                    case 'file':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
253
                        $view->registerScript(
254
                            '',
255
                            $view::POS_HEAD,
256
                            array_merge(['src' => $tag['url']], $tag['options']),
257
                            md5($tag['url'] . json_encode($tag['options']))
258
                        );
259
                        break;
260
                    case 'css':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
261
                        $view->registerCssFile($tag['url'], $tag['options']);
262
                        break;
263
                    default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
264
                        break;
265
                }
266
            }
267
        }
268
    }
269
270
    /**
271
     * Determine whether the Vite dev server is running
272
     *
273
     * @return bool
274
     */
275
    public function devServerRunning(): bool
276
    {
277
        // If the dev server is turned off via config, say it's not running
278
        if (!$this->useDevServer) {
279
            return false;
280
        }
281
        // If we're not supposed to check that the dev server is actually running, just assume it is
282
        if (!$this->checkDevServer) {
283
            return true;
284
        }
285
        // Check to see if the dev server is actually running by pinging it
286
        $url = $this->createUrl($this->devServerInternal, self::VITE_CLIENT);
287
288
        return !($this->fetchFile($url) === null);
289
    }
290
291
    /**
292
     * Invalidate all of the Vite caches
293
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
294
    public function invalidateCaches()
295
    {
296
        $cache = Craft::$app->getCache();
297
        TagDependency::invalidate($cache, self::CACHE_TAG . $this->cacheKeySuffix);
298
        Craft::info('All Vite caches cleared', __METHOD__);
299
    }
300
301
    // Protected Methods
302
    // =========================================================================
303
304
    /**
305
     * Return an array of tags from the manifest, for both modern and legacy builds
306
     *
307
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
308
     * @param bool $asyncCss
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
309
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
310
     * @param array $cssTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
311
     *
312
     * @return array
313
     */
314
    protected function manifestTags(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = []): array
315
    {
316
        // Get the modern tags for this $path
317
        $tags = $this->extractManifestTags($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs, false);
318
        // Look for a legacy version of this $path too
319
        $parts = pathinfo($path);
320
        $legacyPath = $parts['dirname']
321
            . '/'
322
            . $parts['filename']
323
            . self::LEGACY_EXTENSION
324
            . $parts['extension'];
325
        $legacyTags = $this->extractManifestTags($legacyPath, $asyncCss, $scriptTagAttrs, $cssTagAttrs, true);
326
        // Set a flag to indicate the some legacy gets were found
327
        $legacyPolyfillTags = [];
328
        if (!empty($legacyTags)) {
329
            $this->hasLegacyTags = true;
330
        }
331
        return array_merge(
332
            $legacyPolyfillTags,
333
            $tags,
334
            $legacyTags
335
        );
336
    }
337
338
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $legacy should have a doc-comment as per coding-style.
Loading history...
339
     * Return an array of data describing the  script, module link, and CSS link tags for the
340
     * script from the manifest.json file
341
     *
342
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
343
     * @param bool $asyncCss
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
344
     * @param array $scriptTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
345
     * @param array $cssTagAttrs
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
346
     *
347
     * @return array
348
     */
349
    protected function extractManifestTags(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = [], $legacy = false): array
350
    {
351
        $tags = [];
352
        // Grab the manifest
353
        $pathOrUrl = (string)Craft::parseEnv($this->manifestPath);
354
        $manifest = $this->fetchFile($pathOrUrl, [JsonHelper::class, 'decodeIfJson']);
355
        // If no manifest file is found, bail
356
        if ($manifest === null) {
357
            Craft::error('Manifest not found at ' . $this->manifestPath, __METHOD__);
358
359
            return [];
360
        }
361
        // Set the async CSS args
362
        $asyncCssOptions = [];
363
        if ($asyncCss) {
364
            $asyncCssOptions = [
365
                'media' => 'print',
366
                'onload' => "this.media='all'",
367
            ];
368
        }
369
        // Set the script args
370
        $scriptOptions = [
371
            'type' => 'module',
372
            'crossorigin' => true,
373
        ];
374
        if ($legacy) {
375
            $scriptOptions = [
376
                'type' => 'nomodule',
377
            ];
378
        }
379
        // Iterate through the manifest
380
        foreach ($manifest as $manifestKey => $entry) {
381
            if (isset($entry['isEntry']) && $entry['isEntry']) {
382
                // Include the entry script
383
                if (isset($entry['file']) && strpos($path, $manifestKey) !== false) {
384
                    $tags[] = [
385
                        'type' => 'file',
386
                        'url' => $this->createUrl($this->serverPublic, $entry['file']),
387
                        'options' => array_merge($scriptOptions, $scriptTagAttrs)
388
                    ];
389
                    // Include any CSS tags
390
                    $cssFiles = [];
391
                    $this->extractCssFiles($manifest, $manifestKey, $cssFiles);
392
                    foreach ($cssFiles as $cssFile) {
393
                        $tags[] = [
394
                            'type' => 'css',
395
                            'url' => $this->createUrl($this->serverPublic, $cssFile),
396
                            'options' => array_merge([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
397
                                'rel' => 'stylesheet',
398
                            ], $asyncCssOptions, $cssTagAttrs)
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
399
                        ];
400
                    }
401
                }
402
            }
403
        }
404
405
        return $tags;
406
    }
407
408
    /**
409
     * Extract any CSS files from entries recursively
410
     *
411
     * @param array $manifest
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
412
     * @param string $manifestKey
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
413
     * @param array $cssFiles
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
414
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
415
    protected function extractCssFiles(array $manifest, string $manifestKey, array &$cssFiles): array
416
    {
417
        $entry = $manifest[$manifestKey] ?? null;
418
        if (!$entry) {
419
            return [];
420
        }
421
        $cssFiles = array_merge($cssFiles, $entry['css'] ?? []);
422
        $imports = array_merge($entry['imports'] ?? [], $entry['dynamicImport'] ?? []);
423
        foreach ($imports as $import) {
424
            $this->extractCssFiles($manifest, $import, $cssFiles);
425
        }
426
427
        return $cssFiles;
428
    }
429
430
    /**
431
     * Combine a path with a URL to create a URL
432
     *
433
     * @param string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
434
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
435
     *
436
     * @return string
437
     */
438
    protected function createUrl(string $url, string $path): string
439
    {
440
        $url = (string)Craft::parseEnv($url);
441
        return rtrim($url, '/') . '/' . trim($path, '/');
442
    }
443
444
    /**
445
     * Return the contents of a local or remote file, or null
446
     *
447
     * @param string $pathOrUrl
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
448
     * @param callable|null $callback
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
449
     * @return mixed
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
450
     */
451
    protected function fetchFile(string $pathOrUrl, callable $callback = null)
452
    {
453
        // Create the dependency tags
454
        $dependency = new TagDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
455
            'tags' => [
456
                self::CACHE_TAG . $this->cacheKeySuffix,
457
                self::CACHE_TAG . $this->cacheKeySuffix . $pathOrUrl,
458
            ],
459
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
460
        // If this is a file path such as for the `manifest.json`, add a FileDependency so it's cache bust if the file changes
461
        if (!UrlHelper::isAbsoluteUrl($pathOrUrl)) {
462
            $dependency = new ChainedDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
463
                'dependencies' => [
464
                    new FileDependency([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
465
                        'fileName' => $pathOrUrl
466
                    ]),
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
467
                    $dependency
468
                ]
469
            ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
470
        }
471
        // Set the cache duration based on devMode
472
        $cacheDuration = Craft::$app->getConfig()->getGeneral()->devMode
473
            ? self::DEVMODE_CACHE_DURATION
474
            : null;
475
        // Get the result from the cache, or parse the file
476
        $cache = Craft::$app->getCache();
477
        $file = $cache->getOrSet(
478
            self::CACHE_KEY . $this->cacheKeySuffix . $pathOrUrl,
479
            function () use ($pathOrUrl, $callback) {
480
                $contents = null;
481
                $result = null;
482
                if (UrlHelper::isAbsoluteUrl($pathOrUrl)) {
483
                    // See if we can connect to the server
484
                    $clientOptions = [
485
                        RequestOptions::HTTP_ERRORS => false,
486
                        RequestOptions::CONNECT_TIMEOUT => 3,
487
                        RequestOptions::VERIFY => false,
488
                        RequestOptions::TIMEOUT => 5,
489
                    ];
490
                    $client = new Client($clientOptions);
491
                    try {
492
                        $response = $client->request('GET', $pathOrUrl, [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
493
                            RequestOptions::HEADERS => [
494
                                'User-Agent' => self::USER_AGENT_STRING,
495
                                'Accept' => '*/*',
496
                            ],
497
                        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
498
                        if ($response->getStatusCode() === 200) {
499
                            $contents = $response->getBody()->getContents();
500
                        }
501
                    } catch (\Throwable $e) {
502
                        Craft::error($e, __METHOD__);
503
                    }
504
                } else {
505
                    $contents = @file_get_contents($pathOrUrl);
506
                }
507
                if ($contents) {
508
                    $result = $contents;
509
                    if ($callback) {
510
                        $result = $callback($result);
511
                    }
512
                }
513
514
                return $result;
515
            },
516
            $cacheDuration,
517
            $dependency
518
        );
519
520
        return $file;
521
    }
522
}
523