Passed
Push — main ( 095ef5...91e9ab )
by Glynn
11:28 queued 09:54
created

ManifestParser::getEntryScriptUri()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 11
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Vite Manifest Parser
7
 *
8
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
 *
20
 * @author Glynn Quelch <[email protected]>
21
 * @license http://www.opensource.org/licenses/mit-license.html  MIT License
22
 * @package Gin0115\Vite Manifest Parser
23
 * @since 0.0.1
24
 */
25
26
namespace Gin0115\ViteManifestParser;
27
28
/**
29
 * @template ManifestFile array{
30
 *     file: string,
31
 *     src: string,
32
 *     isEntry?: bool,
33
 *     isDynamicEntry?: bool,
34
 *     dynamicImports?: string[],
35
 *     css?: string[],
36
 *     assets?: string[],
37
 *     imports?: string[],
38
 *  }
39
 */
40
class ManifestParser
41
{
42
    /**
43
     * The URI to where the built assets will be stored.
44
     *
45
     * @var string
46
     */
47
    private $assetsUri;
48
49
    /**
50
     * The PATH to where the manifest file is located.
51
     *
52
     * @var string
53
     */
54
    private $manifestPath;
55
56
    /**
57
     * Create an instance of the parser
58
     *
59
     * @param string $assetsUri The URI to where the built assets will be stored.
60
     * @param string $manifestPath The PATH to where the manifest file is located.
61
     */
62
    public function __construct(string $assetsUri, string $manifestPath)
63
    {
64
        // Set the assets URI, but remove any trailing slashes.
65
        $this->assetsUri = rtrim($assetsUri, '/');
66
        $this->manifestPath = $manifestPath;
67
    }
68
69
    /**
70
     * Returns the base uri for the compiled assets.
71
     *
72
     * @return string
73
     */
74
    public function getAssetsUri(): string
75
    {
76
        return $this->assetsUri;
77
    }
78
79
    /**
80
     * Parse the manifest file and return an object of assets.
81
     *
82
     * @return array<string, ManifestFile>
83
     * @throws \Exception - Manifest file does not exist.
84
     * @throws \Exception - Manifest file is not valid JSON.
85
     * @throws \Exception - Manifest file is empty or invalid.
86
     */
87
    private function decodeManifest(): array
88
    {
89
        // Ensure manifest file exists.
90
        if (!file_exists($this->manifestPath)) {
91
            throw new \Exception('Manifest file does not exist.');
92
        }
93
94
        // Decode manifest file.
95
        $manifest = json_decode(file_get_contents($this->manifestPath), true); // @phpstan-ignore-line, checked in following if statement.
96
97
        // Ensure manifest file is valid.
98
        if (json_last_error() !== JSON_ERROR_NONE) {
99
            throw new \Exception('Manifest file is not valid JSON.');
100
        }
101
102
        // Ensure manifest file is an array.
103
        if (!is_array($manifest) || empty($manifest)) {
104
            throw new \Exception('Manifest file is empty or invalid.');
105
        }
106
107
        return $manifest;
108
    }
109
110
    /**
111
     * Get the assets for a vue file.
112
     *
113
     * @param string $file The path to the vue file.
114
     * @return array<string, ManifestFile>
115
     * @throws \Exception - File does not exist in manifest.
116
     * @throws \Exception - File assets are empty or invalid.
117
     */
118
    public function getAssetsForVueFile(string $file): array
119
    {
120
        // Get the manifest.
121
        $manifest = $this->decodeManifest();
122
123
        // Check the file exists.
124
        if (!isset($manifest[$file])) {
125
            throw new \Exception('File does not exist in manifest.');
126
        }
127
128
        // Get the assets for the file.
129
        $assets = $manifest[$file];
130
131
        // Ensure assets are valid.
132
        if (!is_array($assets) || empty($assets)) {
133
            throw new \Exception('File assets are empty or invalid.');
134
        }
135
136
        return $assets;
137
    }
138
139
    /**
140
     * Returns the entry script URI based on the assets url and file name.
141
     *
142
     * @param string $file
143
     * @return string|null
144
     */
145
    public function getEntryScriptUri(string $file): ?string
146
    {
147
        try {
148
            $assets = $this->getAssetsForVueFile($file);
149
        } catch (\Exception $e) {
150
            return null;
151
        }
152
153
        return \array_key_exists('file', $assets)
154
            ? sprintf('%s%s%s', $this->assetsUri, '/', $assets['file'])
155
            : null;
156
    }
157
158
    /**
159
     * Returns the entry scripts css files URI based on the assets url and file name.
160
     *
161
     * @param string $file
162
     * @return string[]
163
     */
164
    public function getEntryCssUris(string $file): array
165
    {
166
        try {
167
            $assets = $this->getAssetsForVueFile($file);
168
        } catch (\Exception $e) {
169
            return [];
170
        }
171
172
        return \array_key_exists('css', $assets)
173
            ? \array_map(function ($css) {
174
                return sprintf('%s%s%s', $this->assetsUri, '/', $css);
175
            }, $assets['css'])
176
            : [];
177
    }
178
}
179