Passed
Push — develop ( a2c384...cbede7 )
by Andrew
07:23
created

Manifest::__constructStatic()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 11
nc 2
nop 0
dl 0
loc 14
rs 9.9
c 1
b 0
f 0
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 nystudio107\transcoder\assetbundles\transcoder\TranscoderAsset;
15
16
use Craft;
17
use craft\helpers\Json as JsonHelper;
18
use craft\helpers\UrlHelper;
19
20
use yii\base\Exception;
21
use yii\base\InvalidConfigException;
22
use yii\caching\TagDependency;
23
use yii\web\NotFoundHttpException;
24
25
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
26
 * @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...
27
 * @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...
28
 * @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...
29
 */
0 ignored issues
show
Coding Style introduced by
Missing @link tag in class comment
Loading history...
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
30
class Manifest
31
{
32
    // Constants
33
    // =========================================================================
34
35
    const ASSET_CLASS = TranscoderAsset::class;
36
37
    const CACHE_KEY = 'twigpack-' . self::ASSET_CLASS;
38
    const CACHE_TAG = 'twigpack-' . self::ASSET_CLASS;
39
40
    const DEVMODE_CACHE_DURATION = 1;
41
42
    const SUPPRESS_ERRORS_FOR_MODULES = [
43
        'styles.js',
44
        'commons.js',
45
        'vendors.js',
46
        'vendors.css',
47
        'styles.css',
48
    ];
49
50
    // Protected Static Properties
51
    // =========================================================================
52
53
    protected static $config = [
54
        // If `devMode` is on, use webpack-dev-server to all for HMR (hot module reloading)
55
        'useDevServer' => false,
56
        // Manifest names
57
        'manifest' => [
58
            'legacy' => 'manifest.json',
59
            'modern' => 'manifest.json',
60
        ],
61
        // Public server config
62
        'server' => [
63
            'manifestPath' => '/',
64
            'publicPath' => '/',
65
        ],
66
        // webpack-dev-server config
67
        'devServer' => [
68
            'manifestPath' => 'http://127.0.0.1:8080',
69
            'publicPath' => '/',
70
        ],
71
    ];
72
73
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
74
     * @var array
75
     */
76
    protected static $files;
77
78
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
79
     * @var bool
80
     */
81
    protected static $isHot = false;
82
83
    // Public Static Methods
84
    // =========================================================================
85
86
    /**
87
     * Simulate a static constructor
88
     *
89
     * ManifestVariable constructor.
90
     * @noinspection MagicMethodsValidityInspection
0 ignored issues
show
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
91
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
92
    public static function __constructStatic()
0 ignored issues
show
Coding Style introduced by
Public method name "Manifest::__constructStatic" must not be prefixed with an underscore
Loading history...
Coding Style introduced by
Method name "Manifest::__constructStatic" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
93
    {
94
        self::invalidateCaches();
95
        $assetClass = self::ASSET_CLASS;
96
        $bundle = new $assetClass;
97
        $baseAssetsUrl = Craft::$app->assetManager->getPublishedUrl(
98
            $bundle->sourcePath,
99
            true
0 ignored issues
show
Unused Code introduced by
The call to yii\web\AssetManager::getPublishedUrl() has too many arguments starting with true. ( Ignorable by Annotation )

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

99
        /** @scrutinizer ignore-call */ 
100
        $baseAssetsUrl = Craft::$app->assetManager->getPublishedUrl(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
100
        );
101
        self::$config['server']['manifestPath'] = Craft::getAlias($bundle->sourcePath);
102
        self::$config['server']['publicPath'] = $baseAssetsUrl;
103
        $useDevServer = getenv('NYS_PLUGIN_DEVSERVER');
104
        if ($useDevServer !== false) {
105
            self::$config['useDevServer'] = (bool)$useDevServer;
106
        }
107
    }
108
109
    /**
110
     * Get the passed in JS modules from the manifest, and register them in the current Craft view
111
     *
112
     * @param array $modules
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...
113
     * @throws NotFoundHttpException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
114
     * @throws InvalidConfigException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
115
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
116
    public static function registerJsModules(array $modules)
117
    {
118
        $view = Craft::$app->getView();
119
        foreach($modules as $module) {
0 ignored issues
show
Coding Style introduced by
Expected "foreach (...) {\n"; found "foreach(...) {\n"
Loading history...
120
            $jsModule = self::getModule(self::$config, $module, 'modern');
121
            if ($jsModule) {
122
                $view->registerJsFile($jsModule, [
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...
123
                    'depends' => self::ASSET_CLASS
124
                ]);
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...
125
            }
126
        }
127
    }
128
129
    /**
130
     * Get the passed in CS modules from the manifest, and register them in the current Craft view
131
     *
132
     * @param array $modules
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
133
     * @throws NotFoundHttpException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
134
     * @throws InvalidConfigException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
135
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
136
    public static function registerCssModules(array $modules)
137
    {
138
        $view = Craft::$app->getView();
139
        foreach($modules as $module) {
0 ignored issues
show
Coding Style introduced by
Expected "foreach (...) {\n"; found "foreach(...) {\n"
Loading history...
140
            $cssModule = self::getModule(self::$config, $module, 'legacy');
141
            if ($cssModule) {
142
                $view->registerCssFile($cssModule, [
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...
143
                    'depends' => self::ASSET_CLASS
144
                ]);
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...
145
            }
146
        }
147
    }
148
149
    /**
150
     * Get the passed in JS module from the manifest, then output a `<script src="">` tag for it in the HTML
151
     *
152
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
153
     * @param bool   $async
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
154
     *
155
     * @return null|string
156
     * @throws NotFoundHttpException
157
     */
158
    public static function includeJsModule(string $moduleName, bool $async)
159
    {
160
        $legacyModule = self::getModule(self::$config, $moduleName, 'legacy');
161
        if ($legacyModule === null) {
162
            return '';
163
        }
164
        if ($async) {
165
            $modernModule = self::getModule(self::$config, $moduleName, 'modern');
166
            if ($modernModule === null) {
167
                return '';
168
            }
169
        }
170
        $lines = [];
171
        if ($async) {
172
            $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...
173
            $lines[] = "<script nomodule src=\"{$legacyModule}\"></script>";
174
        } else {
175
            $lines[] = "<script src=\"{$legacyModule}\"></script>";
176
        }
177
178
        return implode("\r\n", $lines);
179
    }
180
181
    /**
182
     * Get the passed in CS module from the manifest, then output a `<link>` tag for it in the HTML
183
     *
184
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
185
     * @param bool   $async
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
186
     *
187
     * @return string
188
     * @throws NotFoundHttpException
189
     */
190
    public static function includeCssModule(string $moduleName, bool $async): string
191
    {
192
        $legacyModule = self::getModule(self::$config, $moduleName, 'legacy', true);
193
        if ($legacyModule === null) {
194
            return '';
195
        }
196
        $lines = [];
197
        if ($async) {
198
            $lines[] = "<link rel=\"preload\" href=\"{$legacyModule}\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\" />";
199
            $lines[] = "<noscript><link rel=\"stylesheet\" href=\"{$legacyModule}\"></noscript>";
200
        } else {
201
            $lines[] = "<link rel=\"stylesheet\" href=\"{$legacyModule}\" />";
202
        }
203
204
        return implode("\r\n", $lines);
205
    }
206
207
    // Protected Static Methods
208
    // =========================================================================
209
210
    /**
211
     * Return the URI to a module
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
    protected static function getModule(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
222
    {
223
        // Get the module entry
224
        $module = self::getModuleEntry($config, $moduleName, $type, $soft);
225
        if ($module !== null) {
226
            $prefix = self::$isHot
227
                ? $config['devServer']['publicPath']
228
                : $config['server']['publicPath'];
229
            // If the module isn't a full URL, prefix it
230
            if (!UrlHelper::isAbsoluteUrl($module)) {
231
                $module = self::combinePaths($prefix, $module);
232
            }
233
            // Resolve any aliases
234
            $alias = Craft::getAlias($module, false);
235
            if ($alias) {
236
                $module = $alias;
237
            }
238
            // Make sure it's a full URL
239
            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

239
            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

239
            if (!UrlHelper::isAbsoluteUrl(/** @scrutinizer ignore-type */ $module) && !is_file($module)) {
Loading history...
240
                try {
241
                    $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

241
                    $module = UrlHelper::siteUrl(/** @scrutinizer ignore-type */ $module);
Loading history...
242
                } catch (Exception $e) {
243
                    Craft::error($e->getMessage(), __METHOD__);
244
                }
245
            }
246
        }
247
248
        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...
249
    }
250
251
    /**
252
     * Return a module's raw entry from the manifest
253
     *
254
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
255
     * @param string $moduleName
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
256
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
257
     * @param bool   $soft
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
258
     *
259
     * @return null|string
260
     * @throws NotFoundHttpException
261
     */
262
    protected static function getModuleEntry(array $config, string $moduleName, string $type = 'modern', bool $soft = false)
263
    {
264
        $module = null;
265
        // Get the manifest file
266
        $manifest = self::getManifestFile($config, $type);
267
        if ($manifest !== null) {
268
            // Make sure it exists in the manifest
269
            if (empty($manifest[$moduleName])) {
270
                // Don't report errors for any files in SUPPRESS_ERRORS_FOR_MODULES
271
                if (!in_array($moduleName, self::SUPPRESS_ERRORS_FOR_MODULES)) {
272
                    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...
273
                        'transcoder',
274
                        'Module does not exist in the manifest: {moduleName}',
275
                        ['moduleName' => $moduleName]
276
                    ), $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...
277
                }
278
279
                return null;
280
            }
281
            $module = $manifest[$moduleName];
282
        }
283
284
        return $module;
285
    }
286
287
    /**
288
     * Return a JSON-decoded manifest file
289
     *
290
     * @param array  $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
291
     * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
292
     *
293
     * @return null|array
294
     * @throws NotFoundHttpException
295
     */
296
    protected static function getManifestFile(array $config, string $type = 'modern')
297
    {
298
        $manifest = null;
299
        // Determine whether we should use the devServer for HMR or not
300
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
301
        self::$isHot = ($devMode && $config['useDevServer']);
302
        // Try to get the manifest
303
        while ($manifest === null) {
304
            $manifestPath = self::$isHot
305
                ? $config['devServer']['manifestPath']
306
                : $config['server']['manifestPath'];
307
            // Normalize the path
308
            $path = self::combinePaths($manifestPath, $config['manifest'][$type]);
309
            $manifest = self::getJsonFile($path);
310
            // If the manifest isn't found, and it was hot, fall back on non-hot
311
            if ($manifest === null) {
312
                // We couldn't find a manifest; throw an error
313
                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...
314
                    'transcoder',
315
                    'Manifest file not found at: {manifestPath}',
316
                    ['manifestPath' => $manifestPath]
317
                ), 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...
318
                if (self::$isHot) {
319
                    // Try again, but not with home module replacement
320
                    self::$isHot = false;
321
                } else {
322
                    // Give up and return null
323
                    return null;
324
                }
325
            }
326
        }
327
328
        return $manifest;
329
    }
330
331
    /**
332
     * Return the contents of a JSON file from a URI path
333
     *
334
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
335
     *
336
     * @return null|array
337
     */
338
    protected static function getJsonFile(string $path)
339
    {
340
        return self::getFileFromUri($path, [JsonHelper::class, 'decodeIfJson']);
341
    }
342
343
    /**
344
     * Invalidate all of the manifest caches
345
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
346
    public static function invalidateCaches()
347
    {
348
        $cache = Craft::$app->getCache();
349
        TagDependency::invalidate($cache, self::CACHE_TAG);
350
        Craft::info('All manifest caches cleared', __METHOD__);
351
    }
352
353
    /**
354
     * Return the contents of a file from a URI path
355
     *
356
     * @param string        $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
357
     * @param callable|null $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
358
     *
359
     * @return null|mixed
360
     */
361
    protected static function getFileFromUri(string $path, callable $callback = null)
362
    {
363
        // Resolve any aliases
364
        $alias = Craft::getAlias($path, false);
365
        if ($alias) {
366
            $path = (string)$alias;
367
        }
368
        // Make sure it's a full URL
369
        if (!UrlHelper::isAbsoluteUrl($path) && !is_file($path)) {
370
            try {
371
                $path = UrlHelper::siteUrl($path);
372
            } catch (Exception $e) {
373
                Craft::error($e->getMessage(), __METHOD__);
374
            }
375
        }
376
377
        return self::getFileContents($path, $callback);
378
    }
379
380
    /**
381
     * Return the contents of a file from the passed in path
382
     *
383
     * @param string   $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
384
     * @param callable $callback
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
385
     *
386
     * @return null|mixed
387
     */
388
    protected static function getFileContents(string $path, callable $callback = null)
389
    {
390
        // Return the memoized manifest if it exists
391
        if (!empty(self::$files[$path])) {
392
            return self::$files[$path];
393
        }
394
        // Create the dependency tags
395
        $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...
396
            'tags' => [
397
                self::CACHE_TAG,
398
                self::CACHE_TAG.$path,
399
            ],
400
        ]);
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...
401
        // Set the cache duration based on devMode
402
        $cacheDuration = Craft::$app->getConfig()->getGeneral()->devMode
403
            ? self::DEVMODE_CACHE_DURATION
404
            : null;
405
        // Get the result from the cache, or parse the file
406
        $cache = Craft::$app->getCache();
407
        $file = $cache->getOrSet(
408
            self::CACHE_KEY.$path,
409
            function () use ($path, $callback) {
410
                $result = null;
411
                $contents = @file_get_contents($path);
412
                if ($contents) {
413
                    $result = $contents;
414
                    if ($callback) {
415
                        $result = $callback($result);
416
                    }
417
                }
418
419
                return $result;
420
            },
421
            $cacheDuration,
422
            $dependency
423
        );
424
        self::$files[$path] = $file;
425
426
        return $file;
427
    }
428
429
    /**
430
     * Combined the passed in paths, whether file system or URL
431
     *
432
     * @param string ...$paths
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
433
     *
434
     * @return string
435
     */
436
    protected static function combinePaths(string ...$paths): string
437
    {
438
        $last_key = count($paths) - 1;
439
        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...
440
            switch ($key) {
441
                case 0:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
442
                    $val = rtrim($val, '/ ');
443
                    break;
444
                case $last_key:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
445
                    $val = ltrim($val, '/ ');
446
                    break;
447
                default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
448
                    $val = trim($val, '/ ');
449
                    break;
450
            }
451
        });
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...
452
453
        $first = array_shift($paths);
454
        $last = array_pop($paths);
455
        $paths = array_filter($paths);
456
        array_unshift($paths, $first);
457
        $paths[] = $last;
458
459
        return implode('/', $paths);
460
    }
461
462
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
463
     * @param string $error
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
464
     * @param bool   $soft
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
465
     *
466
     * @throws NotFoundHttpException
467
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
468
    protected static function reportError(string $error, $soft = false)
469
    {
470
        $devMode = Craft::$app->getConfig()->getGeneral()->devMode;
471
        if ($devMode && !$soft) {
472
            throw new NotFoundHttpException($error);
473
        }
474
        Craft::error($error, __METHOD__);
475
    }
476
}
477
478
// Simulate a static constructor
479
Manifest::__constructStatic();
480