Completed
Branch barista-prod (8f1757)
by
unknown
38:38 queued 29:41
created

AssetManifest::getAssetsPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\assets;
4
5
use EventEspresso\core\domain\DomainInterface;
6
7
/**
8
 * Class for loading parsing and retrieving data from an asset manifest file
9
 *
10
 * @package EventEspresso\core\services\assets
11
 * @author  Brent Christensen
12
 * @since   $VID:$
13
 */
14
class AssetManifest implements AssetManifestInterface
15
{
16
17
    const ASSET_EXT_CSS      = '.css';
18
19
    const ASSET_EXT_JS      = '.js';
20
21
    const ASSET_EXT_PHP     = '.php';
22
23
    const FILE_NAME         = 'asset-manifest.json';
24
25
    const KEY_DEPENDENCIES  = 'dependencies';
26
27
    const KEY_ENTRY_POINTS  = 'entrypoints';
28
29
    const KEY_FILES         = 'files';
30
31
    const KEY_VERSION       = 'version';
32
33
34
    /**
35
     * @var array
36
     */
37
    private $asset_files;
38
39
    /**
40
     * @var string
41
     */
42
    private $assets_namespace;
43
44
    /**
45
     * @var string
46
     */
47
    private $assets_path;
48
49
    /**
50
     * @var DomainInterface
51
     */
52
    protected $domain;
53
54
    /**
55
     * @var array
56
     */
57
    private $entry_points;
58
59
    /**
60
     * @var array
61
     */
62
    private $manifest;
63
64
    /**
65
     * @var string
66
     */
67
    private $manifest_path;
68
69
    /**
70
     * This is a list of known handles that are used for css.
71
     * @var array
72
     */
73
    private $wp_css_handle_dependencies = [
74
        'wp-components',
75
        'wp-block-editor',
76
        'wp-block-library',
77
        'wp-edit-post',
78
        'wp-edit-widgets',
79
        'wp-editor',
80
        'wp-format-library',
81
        'wp-list-reusable-blocks',
82
        'wp-nux',
83
    ];
84
85
86
    /**
87
     * AssetManifest constructor.
88
     *
89
     * @param DomainInterface $domain
90
     */
91
    public function __construct(DomainInterface $domain)
92
    {
93
        $this->domain = $domain;
94
        $this->initialize();
95
    }
96
97
98
    /**
99
     * @return void
100
     */
101
    public function initialize()
102
    {
103
        if (! $this->manifest) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->manifest of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
104
            $this->assets_namespace = $this->domain->assetNamespace();
105
            $assets_path = $this->domain->distributionAssetsPath();
106
            $this->assets_path = trailingslashit($assets_path);
107
            $this->setManifestFilepath();
108
            $this->loadManifest();
109
            $this->getAssetFiles();
110
            $this->getEntryPoints();
111
        }
112
    }
113
114
115
    /**
116
     * @param string $manifest_path
117
     */
118
    public function setManifestFilepath($manifest_path = '')
119
    {
120
        $manifest_path = $manifest_path ? $manifest_path : $this->assets_path . AssetManifest::FILE_NAME;
121
        if (! is_readable($manifest_path)) {
122
            throw new AssetManifestException(
123
                $manifest_path,
124
                '',
125
                sprintf(
126
                    esc_html__(
127
                        'The "%1$s" file was not found or is not readable. Please verify that the file exists and has appropriate permissions.',
128
                        'event_espresso'
129
                    ),
130
                    $manifest_path
131
                )
132
            );
133
        }
134
        $this->manifest_path = $manifest_path;
135
    }
136
137
138
    /**
139
     * @return void
140
     */
141
    private function loadManifest()
142
    {
143
        if (! $this->manifest) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->manifest of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
144
            // TODO May be use WP File system? ¯\_(ツ)_/¯
145
            $manifest_json  = file_get_contents($this->manifest_path);
146
            $this->manifest = json_decode($manifest_json, true);
147
        }
148
    }
149
150
151
    /**
152
     * @param string $file_name
153
     * @return string
154
     */
155
    private function trimAssetFilename($file_name)
156
    {
157
        return ltrim($file_name, '/');
158
    }
159
160
161
    /**
162
     * @return array
163
     */
164 View Code Duplication
    public function getAssetFiles()
165
    {
166
        if (! $this->asset_files) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->asset_files of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
167
            if (empty($this->manifest[ AssetManifest::KEY_FILES ])) {
168
                if (WP_DEBUG) {
169
                    throw new AssetManifestException(AssetManifest::KEY_FILES, $this->manifest_path);
170
                }
171
                return [];
172
            }
173
            $this->asset_files = $this->manifest[ AssetManifest::KEY_FILES ];
174
        }
175
        return $this->asset_files;
176
    }
177
178
179
    /**
180
     * @return array
181
     */
182 View Code Duplication
    public function getEntryPoints()
183
    {
184
        if (! $this->entry_points) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->entry_points of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
185
            if (empty($this->manifest[ AssetManifest::KEY_ENTRY_POINTS ])) {
186
                if (WP_DEBUG) {
187
                    throw new AssetManifestException(AssetManifest::KEY_ENTRY_POINTS, $this->manifest_path);
188
                }
189
                return [];
190
            }
191
            $this->entry_points = array_keys($this->manifest[ AssetManifest::KEY_ENTRY_POINTS ]);
192
        }
193
        return $this->entry_points;
194
    }
195
196
197
    /**
198
     * @param string $entry_point
199
     * @param string $type
200
     * @return string
201
     */
202
    private function getAsset($entry_point, $type = AssetManifest::ASSET_EXT_JS)
203
    {
204
        return $this->hasAsset($entry_point, $type)
205
            ? $this->trimAssetFilename($this->asset_files[ $entry_point . $type ])
206
            : '';
207
    }
208
209
210
    /**
211
     * @param string $entry_point
212
     * @param string $type
213
     * @return array
214
     */
215
    public function getAssetDependencies($entry_point, $type = AssetManifest::ASSET_EXT_JS)
216
    {
217
        $asset = $this->getAssetDetails($entry_point);
218
        if (! isset($asset[AssetManifest::KEY_DEPENDENCIES])) {
219
            return [];
220
        }
221
        $dependencies = $asset[AssetManifest::KEY_DEPENDENCIES];
222
        // remove cyclical dependencies, if any
223
        if (($key = array_search($this->assets_namespace . '-' . $entry_point, $dependencies, true)) !== false) {
224
            unset($dependencies[ $key ]);
225
        }
226
        // currently need to derive dependencies for CSS from the JS dependencies
227
        if ($type === AssetManifest::ASSET_EXT_CSS) {
228
            $css_dependencies = [];
229
            foreach ($dependencies as $handle) {
230
                $dependency_style = $this->getEntryPointFromHandle($handle) . AssetManifest::ASSET_EXT_CSS;
231
                if (isset($this->asset_files[ $dependency_style ])
232
                    || in_array($handle, $this->wp_css_handle_dependencies)
233
                ) {
234
                    $css_dependencies[] = $handle;
235
                }
236
            }
237
            return $css_dependencies;
238
        }
239
        return $dependencies;
240
    }
241
242
243
    /**
244
     * @param string $entry_point
245
     * @return array
246
     */
247
    public function getAssetDetails($entry_point)
248
    {
249
        $file_name = $this->getAsset($entry_point, AssetManifest::ASSET_EXT_PHP);
250
        if (! $file_name) {
251
            return [];
252
        }
253
        $full_path = $this->assets_path . $file_name;
254
        if (! is_readable($full_path)) {
255
            if (WP_DEBUG) {
256
                throw new AssetManifestException(AssetManifest::KEY_DEPENDENCIES, $full_path);
257
            }
258
            return [];
259
        }
260
        return require($full_path);
261
    }
262
263
264
    /**
265
     * @param string $entry_point
266
     * @return string|int|false
267
     */
268
    public function getAssetHandle($entry_point)
269
    {
270
        return $this->assets_namespace . '-' . $entry_point;
271
    }
272
273
274
    /**
275
     * @return string
276
     */
277
    public function getAssetsPath()
278
    {
279
        return $this->assets_path;
280
    }
281
282
283
    /**
284
     * @param string $handle
285
     * @return string|int|false
286
     */
287
    private function getEntryPointFromHandle($handle)
288
    {   $find = $this->assets_namespace . '-';
289
        return str_replace($find, '', $handle);
290
    }
291
292
293
    /**
294
     * @param string $entry_point
295
     * @param string $type
296
     * @return string
297
     */
298
    public function getAssetPath($entry_point, $type = AssetManifest::ASSET_EXT_JS)
299
    {
300
        $file_name = $this->getAsset($entry_point, $type);
301
        return $file_name ? $this->domain->distributionAssetsPath($file_name) : '';
302
    }
303
304
305
    /**
306
     * @param string $entry_point
307
     * @param string $type
308
     * @return string
309
     */
310
    public function getAssetUrl($entry_point, $type = AssetManifest::ASSET_EXT_JS)
311
    {
312
        $file_name = $this->getAsset($entry_point, $type);
313
        return $file_name ? $this->domain->distributionAssetsUrl($file_name) : '';
314
    }
315
316
317
    /**
318
     * @param string $entry_point
319
     * @param string $type
320
     * @return string|int|false
321
     */
322
    public function getAssetVersion($entry_point, $type = AssetManifest::ASSET_EXT_JS)
323
    {
324
        $asset = $this->getAssetDetails($entry_point);
325
        return $type === AssetManifest::ASSET_EXT_JS && isset($asset[AssetManifest::KEY_VERSION])
326
            ? $asset[AssetManifest::KEY_VERSION]
327
            : filemtime($this->getAssetPath($entry_point, $type));
328
    }
329
330
331
    /**
332
     * @param string $entry_point
333
     * @param string $type
334
     * @return string
335
     */
336
    public function hasAsset($entry_point, $type = AssetManifest::ASSET_EXT_JS)
337
    {
338
        $file_name = $entry_point . $type;
339
        return ! empty($this->asset_files[ $file_name ]);
340
    }
341
}
342