Passed
Push — v1 ( 4c751d...5017f9 )
by Andrew
49:44 queued 11:22
created

ManifestHelper::extractAssetFiles()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 16
nc 5
nop 0
dl 0
loc 26
rs 9.4222
c 0
b 0
f 0
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
Missing @package tag in file comment
Loading history...
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 @license tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
10
11
namespace nystudio107\pluginvite\helpers;
12
13
use Craft;
14
use craft\helpers\Json as JsonHelper;
15
16
17
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
18
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
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...
19
 * @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...
20
 * @since     1.0.5
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...
21
 */
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...
22
class ManifestHelper
23
{
24
    // Constants
25
    // =========================================================================
26
27
    const LEGACY_EXTENSION = '-legacy.';
28
29
    // Protected Static Properties
30
    // =========================================================================
31
32
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
33
     * @var array|null
34
     */
35
    protected static $manifest;
36
37
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
38
     * @var array|null
39
     */
40
    protected static $assetFiles;
41
42
    // Public Static Methods
43
    // =========================================================================
44
45
    /**
46
     * Fetch and memoize the manifest file
47
     *
48
     * @param string $manifestPath
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
49
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
50
    public static function fetchManifest(string $manifestPath)
51
    {
52
        // Grab the manifest
53
        $pathOrUrl = (string)Craft::parseEnv($manifestPath);
54
        $manifest = FileHelper::fetch($pathOrUrl, [JsonHelper::class, 'decodeIfJson']);
55
        // If no manifest file is found, log it
56
        if ($manifest === null) {
57
            Craft::error('Manifest not found at ' . $manifestPath, __METHOD__);
58
        }
59
        // Ensure we're dealing with an array
60
        self::$manifest = (array)$manifest;
61
    }
62
63
    /**
64
     * Return an array of tags from the manifest, for both modern and legacy builds
65
     *
66
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
67
     * @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...
68
     * @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...
69
     * @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...
70
     *
71
     * @return array
72
     */
73
    public static function manifestTags(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = []): array
74
    {
75
        // Get the modern tags for this $path
76
        return self::extractManifestTags($path, $asyncCss, $scriptTagAttrs, $cssTagAttrs);
77
    }
78
79
    /**
80
     * Return an array of tags from the manifest, for both modern and legacy builds
81
     *
82
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
83
     * @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...
84
     * @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...
85
     * @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...
86
     *
87
     * @return array
88
     */
89
    public static function legacyManifestTags(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = []): array
90
    {
91
        // Get the legacy tags for this $path
92
        $parts = pathinfo($path);
93
        $legacyPath = $parts['dirname']
94
            . '/'
95
            . $parts['filename']
96
            . self::LEGACY_EXTENSION
97
            . $parts['extension'];
98
99
        return self::extractManifestTags($legacyPath, $asyncCss, $scriptTagAttrs, $cssTagAttrs, true);
100
    }
101
102
    /**
103
     * Return an array of data describing the  script, module link, and CSS link tags for the
104
     * script from the manifest.json file
105
     *
106
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
107
     * @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...
108
     * @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...
109
     * @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...
110
     * @param bool $legacy
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...
111
     *
112
     * @return array
113
     */
114
    public static function extractManifestTags(string $path, bool $asyncCss = true, array $scriptTagAttrs = [], array $cssTagAttrs = [], bool $legacy = false): array
115
    {
116
        if (self::$manifest === null) {
117
            return [];
118
        }
119
        $tags = [];
120
        // Set the async CSS args
121
        $asyncCssOptions = [];
122
        if ($asyncCss) {
123
            $asyncCssOptions = [
124
                'media' => 'print',
125
                'onload' => "this.media='all'",
126
            ];
127
        }
128
        // Set the script args
129
        $scriptOptions = [
130
            'type' => 'module',
131
            'crossorigin' => true,
132
        ];
133
        if ($legacy) {
134
            $scriptOptions = [
135
                'nomodule' => true,
136
            ];
137
        }
138
        // Iterate through the manifest
139
        foreach (self::$manifest as $manifestKey => $entry) {
140
            // If it's not an entry, skip it
141
            if (!isset($entry['isEntry']) || !$entry['isEntry']) {
142
                continue;
143
            }
144
            // If there's no file, skip it
145
            if (!isset($entry['file'])) {
146
                continue;
147
            }
148
            // If the $path isn't in the $manifestKey, skip it
149
            if (strpos($path, $manifestKey) === false) {
150
                continue;
151
            }
152
            // Include the entry script
153
            $tagOptions = array_merge($scriptOptions, $scriptTagAttrs);
154
            $tags[] = [
155
                'type' => 'file',
156
                'url' => $entry['file'],
157
                'options' => $tagOptions
158
            ];
159
            // Include any imports
160
            $importFiles = [];
161
            // Only include import tags for the non-legacy scripts
162
            if (!$legacy) {
163
                self::extractImportFiles(self::$manifest, $manifestKey, $importFiles);
164
                foreach ($importFiles as $importFile) {
165
                    $tags[] = [
166
                        'crossorigin' => $tagOptions['crossorigin'] ?? true,
167
                        'type' => 'import',
168
                        'url' => $importFile,
169
                    ];
170
                }
171
            }
172
            // Include any CSS tags
173
            $cssFiles = [];
174
            self::extractCssFiles(self::$manifest, $manifestKey, $cssFiles);
175
            foreach ($cssFiles as $cssFile) {
176
                $tags[] = [
177
                    'type' => 'css',
178
                    'url' => $cssFile,
179
                    '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...
180
                        'rel' => 'stylesheet',
181
                    ], $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...
182
                ];
183
            }
184
        }
185
186
        return $tags;
187
    }
188
189
    /**
190
     * Extract any asset files from all of the entries in the manifest
191
     *
192
     * @return array
193
     */
194
    public static function extractAssetFiles(): array
195
    {
196
        // Used the memoized version if available
197
        if (self::$assetFiles !== null) {
198
            return self::$assetFiles;
199
        }
200
        $assetFiles = [];
201
        foreach (self::$manifest as $entry) {
202
            $assets = $entry['assets'] ?? [];
203
            foreach ($assets as $asset) {
204
                // Get just the file name
205
                $assetKeyParts = explode('/', $asset);
206
                $assetKey = end($assetKeyParts);
207
                // If there is a version hash, remove it
208
                $assetKeyParts = explode('.', $assetKey);
209
                $dotSegments = count($assetKeyParts);
210
                if ($dotSegments > 2) {
211
                    unset($assetKeyParts[$dotSegments - 2]);
212
                    $assetKey = implode('.', $assetKeyParts);
213
                }
214
                $assetFiles[$assetKey] = $asset;
215
            }
216
        }
217
        self::$assetFiles = $assetFiles;
218
219
        return $assetFiles;
220
    }
221
222
    // Protected Static Methods
223
    // =========================================================================
224
225
    /**
226
     * Extract any import files from entries recursively
227
     *
228
     * @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...
229
     * @param string $manifestKey
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
230
     * @param array $importFiles
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...
231
     *
232
     * @return array
233
     */
234
    protected static function extractImportFiles(array $manifest, string $manifestKey, array &$importFiles): array
235
    {
236
        $entry = $manifest[$manifestKey] ?? null;
237
        if (!$entry) {
238
            return [];
239
        }
240
241
        $imports = $entry['imports'] ?? [];
242
        foreach ($imports as $import) {
243
            $importFiles[] = $manifest[$import]['file'];
244
            self::extractImportFiles($manifest, $import, $importFiles);
245
        }
246
247
        return $importFiles;
248
    }
249
250
    /**
251
     * Extract any CSS files from entries recursively
252
     *
253
     * @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...
254
     * @param string $manifestKey
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
255
     * @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...
256
     *
257
     * @return array
258
     */
259
    protected static function extractCssFiles(array $manifest, string $manifestKey, array &$cssFiles): array
260
    {
261
        $entry = $manifest[$manifestKey] ?? null;
262
        if (!$entry) {
263
            return [];
264
        }
265
        $cssFiles = array_merge($cssFiles, $entry['css'] ?? []);
266
        $imports = array_merge($entry['imports'] ?? [], $entry['dynamicImport'] ?? []);
267
        foreach ($imports as $import) {
268
            self::extractCssFiles($manifest, $import, $cssFiles);
269
        }
270
271
        return $cssFiles;
272
    }
273
}
274