Passed
Push — v1 ( 90d4e1...ac3526 )
by Andrew
19:00 queued 09:31
created

Manifest::getJsonFileFromUri()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 12
rs 10
1
<?php
2
/**
3
 * Twigpack plugin for Craft CMS 3.x
4
 *
5
 * Twigpack is the conduit between Twig and webpack, with manifest.json &
6
 * webpack-dev-server HMR support
7
 *
8
 * @link      https://nystudio107.com/
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
9
 * @copyright Copyright (c) 2018 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
10
 */
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...
11
12
namespace nystudio107\transcoder\helpers;
13
14
use Craft;
15
use craft\helpers\Json as JsonHelper;
16
use craft\helpers\UrlHelper;
17
18
use yii\base\Exception;
19
use yii\caching\TagDependency;
20
use yii\web\NotFoundHttpException;
21
22
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
23
 * @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...
24
 * @package   Twigpack
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
25
 * @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...
26
 */
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...
27
class Manifest
28
{
29
    // Constants
30
    // =========================================================================
31
32
    const CACHE_KEY = 'twigpack-transcoder';
33
    const CACHE_TAG = 'twigpack-transcoder';
34
35
    const DEVMODE_CACHE_DURATION = 1;
36
37
    // Protected Static Properties
38
    // =========================================================================
39
40
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
41
     * @var array
42
     */
43
    protected static $files;
44
45
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
46
     * @var bool
47
     */
48
    protected static $isHot = false;
49
50
    // Public Static Methods
51
    // =========================================================================
52
53
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
54
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
55
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
56
     * @param bool   $async
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
57
     *
58
     * @return string
59
     * @throws NotFoundHttpException
60
     */
61
    public static function getCssModuleTags(array $config, string $moduleName, bool $async): string
62
    {
63
        $legacyModule = self::getModule($config, $moduleName, 'legacy', true);
64
        if ($legacyModule === null) {
65
            return '';
66
        }
67
        $lines = [];
68
        if ($async) {
69
            $lines[] = "<link rel=\"preload\" href=\"{$legacyModule}\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\" />";
70
            $lines[] = "<noscript><link rel=\"stylesheet\" href=\"{$legacyModule}\"></noscript>";
71
        } else {
72
            $lines[] = "<link rel=\"stylesheet\" href=\"{$legacyModule}\" />";
73
        }
74
75
        return implode("\r\n", $lines);
76
    }
77
78
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
79
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
80
     *
81
     * @return string
82
     */
83
    public static function getCssInlineTags(string $path): string
84
    {
85
        $result = self::getFile($path);
86
        if ($result) {
87
            $result = "<style>\r\n".$result."</style>\r\n";
88
            return $result;
89
        }
90
91
        return '';
92
    }
93
94
    /**
95
     * Returns the uglified loadCSS rel=preload Polyfill as per:
96
     * https://github.com/filamentgroup/loadCSS#how-to-use-loadcss-recommended-example
97
     *
98
     * @return string
99
     */
100
    public static function getCssRelPreloadPolyfill(): string
101
    {
102
        return <<<EOT
103
<script>
104
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
105
!function(t){"use strict";t.loadCSS||(t.loadCSS=function(){});var e=loadCSS.relpreload={};if(e.support=function(){var e;try{e=t.document.createElement("link").relList.supports("preload")}catch(t){e=!1}return function(){return e}}(),e.bindMediaToggle=function(t){var e=t.media||"all";function a(){t.media=e}t.addEventListener?t.addEventListener("load",a):t.attachEvent&&t.attachEvent("onload",a),setTimeout(function(){t.rel="stylesheet",t.media="only x"}),setTimeout(a,3e3)},e.poly=function(){if(!e.support())for(var a=t.document.getElementsByTagName("link"),n=0;n<a.length;n++){var o=a[n];"preload"!==o.rel||"style"!==o.getAttribute("as")||o.getAttribute("data-loadcss")||(o.setAttribute("data-loadcss",!0),e.bindMediaToggle(o))}},!e.support()){e.poly();var a=t.setInterval(e.poly,500);t.addEventListener?t.addEventListener("load",function(){e.poly(),t.clearInterval(a)}):t.attachEvent&&t.attachEvent("onload",function(){e.poly(),t.clearInterval(a)})}"undefined"!=typeof exports?exports.loadCSS=loadCSS:t.loadCSS=loadCSS}("undefined"!=typeof global?global:this);
106
</script>
107
EOT;
108
    }
109
110
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
111
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
112
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
113
     * @param bool   $async
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
114
     *
115
     * @return null|string
116
     * @throws NotFoundHttpException
117
     */
118
    public static function getJsModuleTags(array $config, string $moduleName, bool $async)
119
    {
120
        $legacyModule = self::getModule($config, $moduleName, 'legacy');
121
        if ($legacyModule === null) {
122
            return '';
123
        }
124
        if ($async) {
125
            $modernModule = self::getModule($config, $moduleName, 'modern');
126
            if ($modernModule === null) {
127
                return '';
128
            }
129
        }
130
        $lines = [];
131
        if ($async) {
132
            $lines[] = "<script type=\"module\" src=\"{$modernModule}\"></script>";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $modernModule does not seem to be defined for all execution paths leading up to this point.
Loading history...
133
            $lines[] = "<script nomodule src=\"{$legacyModule}\"></script>";
134
        } else {
135
            $lines[] = "<script src=\"{$legacyModule}\"></script>";
136
        }
137
138
        return implode("\r\n", $lines);
139
    }
140
141
    /**
142
     * Safari 10.1 supports modules, but does not support the `nomodule`
143
     * attribute - it will load <script nomodule> anyway. This snippet solve
144
     * this problem, but only for script tags that load external code, e.g.:
145
     * <script nomodule src="nomodule.js"></script>
146
     *
147
     * Again: this will **not* # prevent inline script, e.g.:
148
     * <script nomodule>alert('no modules');</script>.
149
     *
150
     * This workaround is possible because Safari supports the non-standard
151
     * 'beforeload' event. This allows us to trap the module and nomodule load.
152
     *
153
     * Note also that `nomodule` is supported in later versions of Safari -
154
     * it's just 10.1 that omits this attribute.
155
     *
156
     * c.f.: https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc
157
     *
158
     * @return string
159
     */
160
    public static function getSafariNomoduleFix(): string
161
    {
162
        return <<<EOT
163
<script>
164
!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()}}();
165
</script>
166
EOT;
167
    }
168
169
    /**
170
     * Return the URI to a module
171
     *
172
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
173
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
174
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
175
     * @param bool   $soft
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
176
     *
177
     * @return null|string
178
     * @throws NotFoundHttpException
179
     */
180
    public static function getModule(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
181
    {
182
        // Get the module entry
183
        $module = self::getModuleEntry($config, $moduleName, $type, $soft);
184
        if ($module !== null) {
185
            $prefix = self::$isHot
186
                ? $config['devServer']['publicPath']
187
                : $config['server']['publicPath'];
188
            // If the module isn't a full URL, prefix it
189
            if (!UrlHelper::isAbsoluteUrl($module)) {
190
                $module = self::combinePaths($prefix, $module);
191
            }
192
            // Resolve any aliases
193
            $alias = Craft::getAlias($module, false);
194
            if ($alias) {
195
                $module = $alias;
196
            }
197
            // Make sure it's a full URL
198
            if (!UrlHelper::isAbsoluteUrl($module) && !is_file($module)) {
0 ignored issues
show
Bug introduced by
It seems like $module can also be of type true; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
            if (!UrlHelper::isAbsoluteUrl($module) && !is_file(/** @scrutinizer ignore-type */ $module)) {
Loading history...
Bug introduced by
It seems like $module can also be of type true; however, parameter $url of craft\helpers\UrlHelper::isAbsoluteUrl() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
            if (!UrlHelper::isAbsoluteUrl(/** @scrutinizer ignore-type */ $module) && !is_file($module)) {
Loading history...
199
                try {
200
                    $module = UrlHelper::siteUrl($module);
0 ignored issues
show
Bug introduced by
It seems like $module can also be of type true; however, parameter $path of craft\helpers\UrlHelper::siteUrl() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

200
                    $module = UrlHelper::siteUrl(/** @scrutinizer ignore-type */ $module);
Loading history...
201
                } catch (Exception $e) {
202
                    Craft::error($e->getMessage(), __METHOD__);
203
                }
204
            }
205
        }
206
207
        return $module;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $module also could return the type true which is incompatible with the documented return type null|string.
Loading history...
208
    }
209
210
    /**
211
     * Return a module's raw entry from the manifest
212
     *
213
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
214
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
215
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
216
     * @param bool   $soft
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
217
     *
218
     * @return null|string
219
     * @throws NotFoundHttpException
220
     */
221
    public static function getModuleEntry(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
222
    {
223
        $module = null;
224
        // Get the manifest file
225
        $manifest = self::getManifestFile($config, $type);
226
        if ($manifest !== null) {
227
            // Make sure it exists in the manifest
228
            if (empty($manifest[$moduleName])) {
229
                self::reportError(Craft::t(
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...
230
                    'transcoder',
231
                    'Module does not exist in the manifest: {moduleName}',
232
                    ['moduleName' => $moduleName]
233
                ), $soft);
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...
234
235
                return null;
236
            }
237
            $module = $manifest[$moduleName];
238
        }
239
240
        return $module;
241
    }
242
243
    /**
244
     * Return a JSON-decoded manifest file
245
     *
246
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
247
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
248
     *
249
     * @return null|array
250
     * @throws NotFoundHttpException
251
     */
252
    public static function getManifestFile(array $config, string $type = 'modern')
253
    {
254
        $manifest = null;
255
        // Determine whether we should use the devServer for HMR or not
256
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
257
        self::$isHot = ($devMode && $config['useDevServer']);
258
        // Try to get the manifest
259
        while ($manifest === null) {
260
            $manifestPath = self::$isHot
261
                ? $config['devServer']['manifestPath']
262
                : $config['server']['manifestPath'];
263
            // Normalize the path
264
            $path = self::combinePaths($manifestPath, $config['manifest'][$type]);
265
            $manifest = self::getJsonFile($path);
266
            // If the manifest isn't found, and it was hot, fall back on non-hot
267
            if ($manifest === null) {
268
                // We couldn't find a manifest; throw an error
269
                self::reportError(Craft::t(
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...
270
                    'transcoder',
271
                    'Manifest file not found at: {manifestPath}',
272
                    ['manifestPath' => $manifestPath]
273
                ), true);
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...
274
                if (self::$isHot) {
275
                    // Try again, but not with home module replacement
276
                    self::$isHot = false;
277
                } else {
278
                    // Give up and return null
279
                    return null;
280
                }
281
            }
282
        }
283
284
        return $manifest;
285
    }
286
287
    /**
288
     * Returns the contents of a file from a URI path
289
     *
290
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
291
     *
292
     * @return string
293
     */
294
    public static function getFile(string $path): string
295
    {
296
        return self::getFileFromUri($path, null) ?? '';
297
    }
298
299
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
300
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
301
     * @param string $fileName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
302
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
303
     *
304
     * @return string
305
     */
306
    public static function getFileFromManifest(array $config, string $fileName, string $type = 'legacy'): string
307
    {
308
        try {
309
            $path = self::getModuleEntry($config, $fileName, $type, true);
310
        } catch (NotFoundHttpException $e) {
311
            Craft::error($e->getMessage(), __METHOD__);
312
        }
313
        if ($path !== null) {
314
            $path = self::combinePaths(
315
                $config['localFiles']['basePath'],
316
                $path
317
            );
318
319
            return self::getFileFromUri($path, null) ?? '';
320
        }
321
322
        return '';
323
    }
324
325
    /**
326
     * Return the contents of a JSON file from a URI path
327
     *
328
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
329
     *
330
     * @return null|array
331
     */
332
    protected static function getJsonFile(string $path)
333
    {
334
        return self::getFileFromUri($path, [self::class, 'jsonFileDecode']);
335
    }
336
337
    /**
338
     * Invalidate all of the manifest caches
339
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
340
    public static function invalidateCaches()
341
    {
342
        $cache = Craft::$app->getCache();
343
        TagDependency::invalidate($cache, self::CACHE_TAG);
344
        Craft::info('All manifest caches cleared', __METHOD__);
345
    }
346
347
    // Protected Static Methods
348
    // =========================================================================
349
350
    /**
351
     * Return the contents of a file from a URI path
352
     *
353
     * @param string        $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
354
     * @param callable|null $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
355
     *
356
     * @return null|mixed
357
     */
358
    protected static function getFileFromUri(string $path, callable $callback = null)
359
    {
360
        // Resolve any aliases
361
        $alias = Craft::getAlias($path, false);
362
        if ($alias) {
363
            $path = $alias;
364
        }
365
        // Make sure it's a full URL
366
        if (!UrlHelper::isAbsoluteUrl($path) && !is_file($path)) {
0 ignored issues
show
Bug introduced by
It seems like $path can also be of type true; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

366
        if (!UrlHelper::isAbsoluteUrl($path) && !is_file(/** @scrutinizer ignore-type */ $path)) {
Loading history...
Bug introduced by
It seems like $path can also be of type true; however, parameter $url of craft\helpers\UrlHelper::isAbsoluteUrl() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

366
        if (!UrlHelper::isAbsoluteUrl(/** @scrutinizer ignore-type */ $path) && !is_file($path)) {
Loading history...
367
            try {
368
                $path = UrlHelper::siteUrl($path);
0 ignored issues
show
Bug introduced by
It seems like $path can also be of type true; however, parameter $path of craft\helpers\UrlHelper::siteUrl() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

368
                $path = UrlHelper::siteUrl(/** @scrutinizer ignore-type */ $path);
Loading history...
369
            } catch (Exception $e) {
370
                Craft::error($e->getMessage(), __METHOD__);
371
            }
372
        }
373
374
        return self::getFileContents($path, $callback);
0 ignored issues
show
Bug introduced by
It seems like $path can also be of type true; however, parameter $path of nystudio107\transcoder\h...fest::getFileContents() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

374
        return self::getFileContents(/** @scrutinizer ignore-type */ $path, $callback);
Loading history...
375
    }
376
377
    /**
378
     * Return the contents of a file from the passed in path
379
     *
380
     * @param string   $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
381
     * @param callable $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
382
     *
383
     * @return null|mixed
384
     */
385
    protected static function getFileContents(string $path, callable $callback = null)
386
    {
387
        // Return the memoized manifest if it exists
388
        if (!empty(self::$files[$path])) {
389
            return self::$files[$path];
390
        }
391
        // Create the dependency tags
392
        $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...
393
            'tags' => [
394
                self::CACHE_TAG,
395
                self::CACHE_TAG.$path,
396
            ],
397
        ]);
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...
398
        // Set the cache duration based on devMode
399
        $cacheDuration = Craft::$app->getConfig()->getGeneral()->devMode
400
            ? self::DEVMODE_CACHE_DURATION
401
            : null;
402
        // Get the result from the cache, or parse the file
403
        $cache = Craft::$app->getCache();
404
        $file = $cache->getOrSet(
405
            self::CACHE_KEY.$path,
406
            function () use ($path, $callback) {
407
                $result = null;
408
                $contents = @file_get_contents($path);
409
                if ($contents) {
410
                    $result = $contents;
411
                    if ($callback) {
412
                        $result = $callback($result);
413
                    }
414
                }
415
416
                return $result;
417
            },
418
            $cacheDuration,
419
            $dependency
420
        );
421
        self::$files[$path] = $file;
422
423
        return $file;
424
    }
425
426
    /**
427
     * Combined the passed in paths, whether file system or URL
428
     *
429
     * @param string ...$paths
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
430
     *
431
     * @return string
432
     */
433
    protected static function combinePaths(string ...$paths): string
434
    {
435
        $last_key = \count($paths) - 1;
436
        array_walk($paths, function (&$val, $key) use ($last_key) {
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...
437
            switch ($key) {
438
                case 0:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
439
                    $val = rtrim($val, '/ ');
440
                    break;
441
                case $last_key:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
442
                    $val = ltrim($val, '/ ');
443
                    break;
444
                default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
445
                    $val = trim($val, '/ ');
446
                    break;
447
            }
448
        });
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...
449
450
        $first = array_shift($paths);
451
        $last = array_pop($paths);
452
        $paths = array_filter($paths);
453
        array_unshift($paths, $first);
454
        $paths[] = $last;
455
456
        return implode('/', $paths);
457
    }
458
459
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
460
     * @param string $error
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
461
     * @param bool   $soft
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
462
     *
463
     * @throws NotFoundHttpException
464
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
465
    protected static function reportError(string $error, $soft = false)
466
    {
467
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
468
        if ($devMode && !$soft) {
469
            throw new NotFoundHttpException($error);
470
        }
471
        Craft::error($error, __METHOD__);
472
    }
473
474
    // Private Static Methods
475
    // =========================================================================
476
477
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
478
     * @param $string
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
479
     *
480
     * @return mixed
481
     */
482
    private static function jsonFileDecode($string)
0 ignored issues
show
Coding Style introduced by
Private method name "Manifest::jsonFileDecode" must be prefixed with an underscore
Loading history...
483
    {
484
        return JsonHelper::decodeIfJson($string);
485
    }
486
}
487