View::registerJs()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 2
nop 3
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\web;
9
10
use Yii;
11
use yii\base\InvalidConfigException;
12
use yii\helpers\ArrayHelper;
13
use yii\helpers\Html;
14
use yii\helpers\Url;
15
16
/**
17
 * View represents a view object in the MVC pattern.
18
 *
19
 * View provides a set of methods (e.g. [[render()]]) for rendering purpose.
20
 *
21
 * View is configured as an application component in [[\yii\base\Application]] by default.
22
 * You can access that instance via `Yii::$app->view`.
23
 *
24
 * You can modify its configuration by adding an array to your application config under `components`
25
 * as it is shown in the following example:
26
 *
27
 * ```php
28
 * 'view' => [
29
 *     'theme' => 'app\themes\MyTheme',
30
 *     'renderers' => [
31
 *         // you may add Smarty or Twig renderer here
32
 *     ]
33
 *     // ...
34
 * ]
35
 * ```
36
 *
37
 * For more details and usage information on View, see the [guide article on views](guide:structure-views).
38
 *
39
 * @property \yii\web\AssetManager $assetManager The asset manager. Defaults to the "assetManager" application
40
 * component.
41
 *
42
 * @author Qiang Xue <[email protected]>
43
 * @since 2.0
44
 */
45
class View extends \yii\base\View
46
{
47
    /**
48
     * @event Event an event that is triggered by [[beginBody()]].
49
     */
50
    const EVENT_BEGIN_BODY = 'beginBody';
51
    /**
52
     * @event Event an event that is triggered by [[endBody()]].
53
     */
54
    const EVENT_END_BODY = 'endBody';
55
    /**
56
     * The location of registered JavaScript code block or files.
57
     * This means the location is in the head section.
58
     */
59
    const POS_HEAD = 1;
60
    /**
61
     * The location of registered JavaScript code block or files.
62
     * This means the location is at the beginning of the body section.
63
     */
64
    const POS_BEGIN = 2;
65
    /**
66
     * The location of registered JavaScript code block or files.
67
     * This means the location is at the end of the body section.
68
     */
69
    const POS_END = 3;
70
    /**
71
     * The location of registered JavaScript code block.
72
     * This means the JavaScript code block will be enclosed within `jQuery(document).ready()`.
73
     */
74
    const POS_READY = 4;
75
    /**
76
     * The location of registered JavaScript code block.
77
     * This means the JavaScript code block will be enclosed within `jQuery(window).load()`.
78
     */
79
    const POS_LOAD = 5;
80
    /**
81
     * This is internally used as the placeholder for receiving the content registered for the head section.
82
     */
83
    const PH_HEAD = '<![CDATA[YII-BLOCK-HEAD]]>';
84
    /**
85
     * This is internally used as the placeholder for receiving the content registered for the beginning of the body section.
86
     */
87
    const PH_BODY_BEGIN = '<![CDATA[YII-BLOCK-BODY-BEGIN]]>';
88
    /**
89
     * This is internally used as the placeholder for receiving the content registered for the end of the body section.
90
     */
91
    const PH_BODY_END = '<![CDATA[YII-BLOCK-BODY-END]]>';
92
93
    /**
94
     * @var AssetBundle[] list of the registered asset bundles. The keys are the bundle names, and the values
95
     * are the registered [[AssetBundle]] objects.
96
     * @see registerAssetBundle()
97
     */
98
    public $assetBundles = [];
99
    /**
100
     * @var string the page title
101
     */
102
    public $title;
103
    /**
104
     * @var array the registered meta tags.
105
     * @see registerMetaTag()
106
     */
107
    public $metaTags = [];
108
    /**
109
     * @var array the registered link tags.
110
     * @see registerLinkTag()
111
     */
112
    public $linkTags = [];
113
    /**
114
     * @var array the registered CSS code blocks.
115
     * @see registerCss()
116
     */
117
    public $css = [];
118
    /**
119
     * @var array the registered CSS files.
120
     * @see registerCssFile()
121
     */
122
    public $cssFiles = [];
123
    /**
124
     * @var array the registered JS code blocks
125
     * @see registerJs()
126
     */
127
    public $js = [];
128
    /**
129
     * @var array the registered JS files.
130
     * @see registerJsFile()
131
     */
132
    public $jsFiles = [];
133
    /**
134
     * @since 2.0.50
135
     * @var array the script tag options.
136
     */
137
    public $scriptOptions = [];
138
139
    private $_assetManager;
140
141
142
    /**
143
     * Whether [[endPage()]] has been called and all files have been registered
144
     * @var bool
145
     * @since 2.0.44
146
     */
147
    protected $isPageEnded = false;
148
149
    /**
150
     * Marks the position of an HTML head section.
151
     */
152 52
    public function head()
153
    {
154 52
        echo self::PH_HEAD;
155
    }
156
157
    /**
158
     * Marks the beginning of an HTML body section.
159
     */
160 52
    public function beginBody()
161
    {
162 52
        echo self::PH_BODY_BEGIN;
163 52
        $this->trigger(self::EVENT_BEGIN_BODY);
164
    }
165
166
    /**
167
     * Marks the ending of an HTML body section.
168
     */
169 56
    public function endBody()
170
    {
171 56
        $this->trigger(self::EVENT_END_BODY);
172 56
        echo self::PH_BODY_END;
173
174 56
        foreach (array_keys($this->assetBundles) as $bundle) {
175 15
            $this->registerAssetFiles($bundle);
176
        }
177
    }
178
179
    /**
180
     * Marks the ending of an HTML page.
181
     * @param bool $ajaxMode whether the view is rendering in AJAX mode.
182
     * If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
183
     * will be rendered at the end of the view like normal scripts.
184
     */
185 56
    public function endPage($ajaxMode = false)
186
    {
187 56
        $this->trigger(self::EVENT_END_PAGE);
188
189 56
        $this->isPageEnded = true;
190
191 56
        $content = ob_get_clean();
192
193 56
        echo strtr($content, [
194 56
            self::PH_HEAD => $this->renderHeadHtml(),
195 56
            self::PH_BODY_BEGIN => $this->renderBodyBeginHtml(),
196 56
            self::PH_BODY_END => $this->renderBodyEndHtml($ajaxMode),
197 56
        ]);
198
199 56
        $this->clear();
200
    }
201
202
    /**
203
     * Renders a view in response to an AJAX request.
204
     *
205
     * This method is similar to [[render()]] except that it will surround the view being rendered
206
     * with the calls of [[beginPage()]], [[head()]], [[beginBody()]], [[endBody()]] and [[endPage()]].
207
     * By doing so, the method is able to inject into the rendering result with JS/CSS scripts and files
208
     * that are registered with the view.
209
     *
210
     * @param string $view the view name. Please refer to [[render()]] on how to specify this parameter.
211
     * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
212
     * @param object|null $context the context that the view should use for rendering the view. If null,
213
     * existing [[context]] will be used.
214
     * @return string the rendering result
215
     * @see render()
216
     */
217
    public function renderAjax($view, $params = [], $context = null)
218
    {
219
        $viewFile = $this->findViewFile($view, $context);
220
221
        ob_start();
222
        ob_implicit_flush(false);
223
224
        $this->beginPage();
225
        $this->head();
226
        $this->beginBody();
227
        echo $this->renderFile($viewFile, $params, $context);
228
        $this->endBody();
229
        $this->endPage(true);
230
231
        return ob_get_clean();
232
    }
233
234
    /**
235
     * Registers the asset manager being used by this view object.
236
     * @return \yii\web\AssetManager the asset manager. Defaults to the "assetManager" application component.
237
     */
238 59
    public function getAssetManager()
239
    {
240 59
        return $this->_assetManager ?: Yii::$app->getAssetManager();
241
    }
242
243
    /**
244
     * Sets the asset manager.
245
     * @param \yii\web\AssetManager $value the asset manager
246
     */
247 82
    public function setAssetManager($value)
248
    {
249 82
        $this->_assetManager = $value;
250
    }
251
252
    /**
253
     * Clears up the registered meta tags, link tags, css/js scripts and files.
254
     */
255 58
    public function clear()
256
    {
257 58
        $this->metaTags = [];
258 58
        $this->linkTags = [];
259 58
        $this->css = [];
260 58
        $this->cssFiles = [];
261 58
        $this->js = [];
262 58
        $this->jsFiles = [];
263 58
        $this->assetBundles = [];
264
    }
265
266
    /**
267
     * Registers all files provided by an asset bundle including depending bundles files.
268
     * Removes a bundle from [[assetBundles]] once files are registered.
269
     * @param string $name name of the bundle to register
270
     */
271 15
    protected function registerAssetFiles($name)
272
    {
273 15
        if (!isset($this->assetBundles[$name])) {
274 12
            return;
275
        }
276 15
        $bundle = $this->assetBundles[$name];
277 15
        if ($bundle) {
0 ignored issues
show
introduced by
$bundle is of type yii\web\AssetBundle, thus it always evaluated to true.
Loading history...
278 15
            foreach ($bundle->depends as $dep) {
279 12
                $this->registerAssetFiles($dep);
280
            }
281 15
            $bundle->registerAssetFiles($this);
282
        }
283 15
        unset($this->assetBundles[$name]);
284
    }
285
286
    /**
287
     * Registers the named asset bundle.
288
     * All dependent asset bundles will be registered.
289
     * @param string $name the class name of the asset bundle (without the leading backslash)
290
     * @param int|null $position if set, this forces a minimum position for javascript files.
291
     * This will adjust depending assets javascript file position or fail if requirement can not be met.
292
     * If this is null, asset bundles position settings will not be changed.
293
     * See [[registerJsFile]] for more details on javascript position.
294
     * @return AssetBundle the registered asset bundle instance
295
     * @throws InvalidConfigException if the asset bundle does not exist or a circular dependency is detected
296
     */
297 35
    public function registerAssetBundle($name, $position = null)
298
    {
299 35
        if (!isset($this->assetBundles[$name])) {
300 34
            $am = $this->getAssetManager();
301 34
            $bundle = $am->getBundle($name);
302 34
            $this->assetBundles[$name] = false;
303
            // register dependencies
304 34
            $pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
305 34
            foreach ($bundle->depends as $dep) {
306 24
                $this->registerAssetBundle($dep, $pos);
307
            }
308 33
            $this->assetBundles[$name] = $bundle;
309 19
        } elseif ($this->assetBundles[$name] === false) {
0 ignored issues
show
introduced by
The condition $this->assetBundles[$name] === false is always false.
Loading history...
310 1
            throw new InvalidConfigException("A circular dependency is detected for bundle '$name'.");
311
        } else {
312 18
            $bundle = $this->assetBundles[$name];
313
        }
314
315 34
        if ($position !== null) {
316 12
            $pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
317 12
            if ($pos === null) {
318 12
                $bundle->jsOptions['position'] = $pos = $position;
319 6
            } elseif ($pos > $position) {
320 6
                throw new InvalidConfigException("An asset bundle that depends on '$name' has a higher javascript file position configured than '$name'.");
321
            }
322
            // update position for all dependencies
323 12
            foreach ($bundle->depends as $dep) {
324 6
                $this->registerAssetBundle($dep, $pos);
325
            }
326
        }
327
328 34
        return $bundle;
329
    }
330
331
    /**
332
     * Registers a meta tag.
333
     *
334
     * For example, a description meta tag can be added like the following:
335
     *
336
     * ```php
337
     * $view->registerMetaTag([
338
     *     'name' => 'description',
339
     *     'content' => 'This website is about funny raccoons.'
340
     * ]);
341
     * ```
342
     *
343
     * will result in the meta tag `<meta name="description" content="This website is about funny raccoons.">`.
344
     *
345
     * @param array $options the HTML attributes for the meta tag.
346
     * @param string|null $key the key that identifies the meta tag. If two meta tags are registered
347
     * with the same key, the latter will overwrite the former. If this is null, the new meta tag
348
     * will be appended to the existing ones.
349
     */
350
    public function registerMetaTag($options, $key = null)
351
    {
352
        if ($key === null) {
353
            $this->metaTags[] = Html::tag('meta', '', $options);
354
        } else {
355
            $this->metaTags[$key] = Html::tag('meta', '', $options);
356
        }
357
    }
358
359
    /**
360
     * Registers CSRF meta tags.
361
     * They are rendered dynamically to retrieve a new CSRF token for each request.
362
     *
363
     * ```php
364
     * $view->registerCsrfMetaTags();
365
     * ```
366
     *
367
     * The above code will result in `<meta name="csrf-param" content="[yii\web\Request::$csrfParam]">`
368
     * and `<meta name="csrf-token" content="tTNpWKpdy-bx8ZmIq9R72...K1y8IP3XGkzZA==">` added to the page.
369
     *
370
     * Note: Hidden CSRF input of ActiveForm will be automatically refreshed by calling `window.yii.refreshCsrfToken()`
371
     * from `yii.js`.
372
     *
373
     * @since 2.0.13
374
     */
375 1
    public function registerCsrfMetaTags()
376
    {
377 1
        $this->metaTags['csrf_meta_tags'] = $this->renderDynamic('return yii\helpers\Html::csrfMetaTags();');
378
    }
379
380
    /**
381
     * Registers a link tag.
382
     *
383
     * For example, a link tag for a custom [favicon](https://www.w3.org/2005/10/howto-favicon)
384
     * can be added like the following:
385
     *
386
     * ```php
387
     * $view->registerLinkTag(['rel' => 'icon', 'type' => 'image/png', 'href' => '/myicon.png']);
388
     * ```
389
     *
390
     * which will result in the following HTML: `<link rel="icon" type="image/png" href="/myicon.png">`.
391
     *
392
     * **Note:** To register link tags for CSS stylesheets, use [[registerCssFile()]] instead, which
393
     * has more options for this kind of link tag.
394
     *
395
     * @param array $options the HTML attributes for the link tag.
396
     * @param string|null $key the key that identifies the link tag. If two link tags are registered
397
     * with the same key, the latter will overwrite the former. If this is null, the new link tag
398
     * will be appended to the existing ones.
399
     */
400
    public function registerLinkTag($options, $key = null)
401
    {
402
        if ($key === null) {
403
            $this->linkTags[] = Html::tag('link', '', $options);
404
        } else {
405
            $this->linkTags[$key] = Html::tag('link', '', $options);
406
        }
407
    }
408
409
    /**
410
     * Registers a CSS code block.
411
     * @param string $css the content of the CSS code block to be registered
412
     * @param array $options the HTML attributes for the `<style>`-tag.
413
     * @param string|null $key the key that identifies the CSS code block. If null, it will use
414
     * $css as the key. If two CSS code blocks are registered with the same key, the latter
415
     * will overwrite the former.
416
     */
417
    public function registerCss($css, $options = [], $key = null)
418
    {
419
        $key = $key ?: md5($css);
420
        $this->css[$key] = Html::style($css, $options);
421
    }
422
423
    /**
424
     * Registers a CSS file.
425
     *
426
     * This method should be used for simple registration of CSS files. If you want to use features of
427
     * [[AssetManager]] like appending timestamps to the URL and file publishing options, use [[AssetBundle]]
428
     * and [[registerAssetBundle()]] instead.
429
     *
430
     * @param string $url the CSS file to be registered.
431
     * @param array $options the HTML attributes for the link tag. Please refer to [[Html::cssFile()]] for
432
     * the supported options. The following options are specially handled and are not treated as HTML attributes:
433
     *
434
     * - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
435
     * - `appendTimestamp`: bool whether to append a timestamp to the URL.
436
     *
437
     * @param string|null $key the key that identifies the CSS script file. If null, it will use
438
     * $url as the key. If two CSS files are registered with the same key, the latter
439
     * will overwrite the former.
440
     * @throws InvalidConfigException
441
     */
442 20
    public function registerCssFile($url, $options = [], $key = null)
443
    {
444 20
        $this->registerFile('css', $url, $options, $key);
445
    }
446
447
    /**
448
     * Registers a JS code block.
449
     * @param string $js the JS code block to be registered
450
     * @param int $position the position at which the JS script tag should be inserted
451
     * in a page. The possible values are:
452
     *
453
     * - [[POS_HEAD]]: in the head section
454
     * - [[POS_BEGIN]]: at the beginning of the body section
455
     * - [[POS_END]]: at the end of the body section
456
     * - [[POS_LOAD]]: enclosed within jQuery(window).load().
457
     *   Note that by using this position, the method will automatically register the jQuery js file.
458
     * - [[POS_READY]]: enclosed within jQuery(document).ready(). This is the default value.
459
     *   Note that by using this position, the method will automatically register the jQuery js file.
460
     *
461
     * @param string|null $key the key that identifies the JS code block. If null, it will use
462
     * $js as the key. If two JS code blocks are registered with the same key, the latter
463
     * will overwrite the former.
464
     */
465 10
    public function registerJs($js, $position = self::POS_READY, $key = null)
466
    {
467 10
        $key = $key ?: md5($js);
468 10
        $this->js[$position][$key] = $js;
469 10
        if ($position === self::POS_READY || $position === self::POS_LOAD) {
470 8
            JqueryAsset::register($this);
471
        }
472
    }
473
474
    /**
475
     * Registers a JS or CSS file.
476
     *
477
     * @param string $url the JS file to be registered.
478
     * @param string $type type (js or css) of the file.
479
     * @param array $options the HTML attributes for the script tag. The following options are specially handled
480
     * and are not treated as HTML attributes:
481
     *
482
     * - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
483
     * - `appendTimestamp`: bool whether to append a timestamp to the URL.
484
     *
485
     * @param string|null $key the key that identifies the JS script file. If null, it will use
486
     * $url as the key. If two JS files are registered with the same key at the same position, the latter
487
     * will overwrite the former. Note that position option takes precedence, thus files registered with the same key,
488
     * but different position option will not override each other.
489
     * @throws InvalidConfigException
490
     */
491 36
    private function registerFile($type, $url, $options = [], $key = null)
492
    {
493 36
        $url = Yii::getAlias($url);
494 36
        $key = $key ?: $url;
495 36
        $depends = ArrayHelper::remove($options, 'depends', []);
496 36
        $originalOptions = $options;
497 36
        $position = ArrayHelper::remove($options, 'position', self::POS_END);
498
499
        try {
500 36
            $assetManagerAppendTimestamp = $this->getAssetManager()->appendTimestamp;
501
        } catch (InvalidConfigException $e) {
502
            $depends = null; // the AssetManager is not available
503
            $assetManagerAppendTimestamp = false;
504
        }
505 36
        $appendTimestamp = ArrayHelper::remove($options, 'appendTimestamp', $assetManagerAppendTimestamp);
506
507 36
        if ($this->isPageEnded) {
508
            Yii::warning('You\'re trying to register a file after View::endPage() has been called.');
509
        }
510
511 36
        if (empty($depends)) {
512
            // register directly without AssetManager
513 36
            if ($appendTimestamp && Url::isRelative($url)) {
0 ignored issues
show
Bug introduced by
It seems like $url can also be of type false; however, parameter $url of yii\helpers\BaseUrl::isRelative() 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

513
            if ($appendTimestamp && Url::isRelative(/** @scrutinizer ignore-type */ $url)) {
Loading history...
514 5
                $prefix = Yii::getAlias('@web');
515 5
                $prefixLength = strlen($prefix);
0 ignored issues
show
Bug introduced by
It seems like $prefix can also be of type false; however, parameter $string of strlen() 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

515
                $prefixLength = strlen(/** @scrutinizer ignore-type */ $prefix);
Loading history...
516 5
                $trimmedUrl = ltrim((substr($url, 0, $prefixLength) === $prefix) ? substr($url, $prefixLength) : $url, '/');
0 ignored issues
show
Bug introduced by
It seems like substr($url, 0, $prefixL..., $prefixLength) : $url can also be of type false; however, parameter $string of ltrim() 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

516
                $trimmedUrl = ltrim(/** @scrutinizer ignore-type */ (substr($url, 0, $prefixLength) === $prefix) ? substr($url, $prefixLength) : $url, '/');
Loading history...
Bug introduced by
It seems like $url can also be of type false; however, parameter $string of substr() 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

516
                $trimmedUrl = ltrim((substr(/** @scrutinizer ignore-type */ $url, 0, $prefixLength) === $prefix) ? substr($url, $prefixLength) : $url, '/');
Loading history...
517 5
                $timestamp = @filemtime(Yii::getAlias('@webroot/' . $trimmedUrl, false));
0 ignored issues
show
Bug introduced by
It seems like Yii::getAlias('@webroot/' . $trimmedUrl, false) can also be of type false; however, parameter $filename of filemtime() 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

517
                $timestamp = @filemtime(/** @scrutinizer ignore-type */ Yii::getAlias('@webroot/' . $trimmedUrl, false));
Loading history...
518 5
                if ($timestamp > 0) {
519 2
                    $url = $timestamp ? "$url?v=$timestamp" : $url;
520
                }
521
            }
522 36
            if ($type === 'js') {
523 24
                $this->jsFiles[$position][$key] = Html::jsFile($url, $options);
0 ignored issues
show
Bug introduced by
It seems like $url can also be of type false; however, parameter $url of yii\helpers\BaseHtml::jsFile() 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

523
                $this->jsFiles[$position][$key] = Html::jsFile(/** @scrutinizer ignore-type */ $url, $options);
Loading history...
524
            } else {
525 36
                $this->cssFiles[$key] = Html::cssFile($url, $options);
0 ignored issues
show
Bug introduced by
It seems like $url can also be of type false; however, parameter $url of yii\helpers\BaseHtml::cssFile() does only seem to accept array|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

525
                $this->cssFiles[$key] = Html::cssFile(/** @scrutinizer ignore-type */ $url, $options);
Loading history...
526
            }
527
        } else {
528 4
            $this->getAssetManager()->bundles[$key] = Yii::createObject([
529 4
                'class' => AssetBundle::className(),
0 ignored issues
show
Deprecated Code introduced by
The function yii\base\BaseObject::className() has been deprecated: since 2.0.14. On PHP >=5.5, use `::class` instead. ( Ignorable by Annotation )

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

529
                'class' => /** @scrutinizer ignore-deprecated */ AssetBundle::className(),

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
530 4
                'baseUrl' => '',
531 4
                'basePath' => '@webroot',
532 4
                (string)$type => [ArrayHelper::merge([!Url::isRelative($url) ? $url : ltrim($url, '/')], $originalOptions)],
533 4
                "{$type}Options" => $options,
534 4
                'depends' => (array)$depends,
535 4
            ]);
536 4
            $this->registerAssetBundle($key);
0 ignored issues
show
Bug introduced by
It seems like $key can also be of type false; however, parameter $name of yii\web\View::registerAssetBundle() 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

536
            $this->registerAssetBundle(/** @scrutinizer ignore-type */ $key);
Loading history...
537
        }
538
    }
539
540
    /**
541
     * Registers a JS file.
542
     *
543
     * This method should be used for simple registration of JS files. If you want to use features of
544
     * [[AssetManager]] like appending timestamps to the URL and file publishing options, use [[AssetBundle]]
545
     * and [[registerAssetBundle()]] instead.
546
     *
547
     * @param string $url the JS file to be registered.
548
     * @param array $options the HTML attributes for the script tag. The following options are specially handled
549
     * and are not treated as HTML attributes:
550
     *
551
     * - `depends`: array, specifies the names of the asset bundles that this JS file depends on.
552
     * - `position`: specifies where the JS script tag should be inserted in a page. The possible values are:
553
     *     * [[POS_HEAD]]: in the head section
554
     *     * [[POS_BEGIN]]: at the beginning of the body section
555
     *     * [[POS_END]]: at the end of the body section. This is the default value.
556
     * - `appendTimestamp`: bool whether to append a timestamp to the URL.
557
     *
558
     * Please refer to [[Html::jsFile()]] for other supported options.
559
     *
560
     * @param string|null $key the key that identifies the JS script file. If null, it will use
561
     * $url as the key. If two JS files are registered with the same key at the same position, the latter
562
     * will overwrite the former. Note that position option takes precedence, thus files registered with the same key,
563
     * but different position option will not override each other.
564
     * @throws InvalidConfigException
565
     */
566 24
    public function registerJsFile($url, $options = [], $key = null)
567
    {
568 24
        $this->registerFile('js', $url, $options, $key);
569
    }
570
571
    /**
572
     * Registers a JS code block defining a variable. The name of variable will be
573
     * used as key, preventing duplicated variable names.
574
     *
575
     * @param string $name Name of the variable
576
     * @param array|string $value Value of the variable
577
     * @param int $position the position in a page at which the JavaScript variable should be inserted.
578
     * The possible values are:
579
     *
580
     * - [[POS_HEAD]]: in the head section. This is the default value.
581
     * - [[POS_BEGIN]]: at the beginning of the body section.
582
     * - [[POS_END]]: at the end of the body section.
583
     * - [[POS_LOAD]]: enclosed within jQuery(window).load().
584
     *   Note that by using this position, the method will automatically register the jQuery js file.
585
     * - [[POS_READY]]: enclosed within jQuery(document).ready().
586
     *   Note that by using this position, the method will automatically register the jQuery js file.
587
     *
588
     * @since 2.0.14
589
     */
590 1
    public function registerJsVar($name, $value, $position = self::POS_HEAD)
591
    {
592 1
        $js = sprintf('var %s = %s;', $name, \yii\helpers\Json::htmlEncode($value));
593 1
        $this->registerJs($js, $position, $name);
594
    }
595
596
    /**
597
     * Renders the content to be inserted in the head section.
598
     * The content is rendered using the registered meta tags, link tags, CSS/JS code blocks and files.
599
     * @return string the rendered content
600
     */
601 56
    protected function renderHeadHtml()
602
    {
603 56
        $lines = [];
604 56
        if (!empty($this->metaTags)) {
605 1
            $lines[] = implode("\n", $this->metaTags);
606
        }
607
608 56
        if (!empty($this->linkTags)) {
609
            $lines[] = implode("\n", $this->linkTags);
610
        }
611 56
        if (!empty($this->cssFiles)) {
612 20
            $lines[] = implode("\n", $this->cssFiles);
613
        }
614 56
        if (!empty($this->css)) {
615
            $lines[] = implode("\n", $this->css);
616
        }
617 56
        if (!empty($this->jsFiles[self::POS_HEAD])) {
618 3
            $lines[] = implode("\n", $this->jsFiles[self::POS_HEAD]);
619
        }
620 56
        if (!empty($this->js[self::POS_HEAD])) {
621 1
            $lines[] = Html::script(implode("\n", $this->js[self::POS_HEAD]));
622
        }
623
624 56
        return empty($lines) ? '' : implode("\n", $lines);
625
    }
626
627
    /**
628
     * Renders the content to be inserted at the beginning of the body section.
629
     * The content is rendered using the registered JS code blocks and files.
630
     * @return string the rendered content
631
     */
632 56
    protected function renderBodyBeginHtml()
633
    {
634 56
        $lines = [];
635 56
        if (!empty($this->jsFiles[self::POS_BEGIN])) {
636 3
            $lines[] = implode("\n", $this->jsFiles[self::POS_BEGIN]);
637
        }
638 56
        if (!empty($this->js[self::POS_BEGIN])) {
639
            $lines[] = Html::script(implode("\n", $this->js[self::POS_BEGIN]));
640
        }
641
642 56
        return empty($lines) ? '' : implode("\n", $lines);
643
    }
644
645
    /**
646
     * Renders the content to be inserted at the end of the body section.
647
     * The content is rendered using the registered JS code blocks and files.
648
     * @param bool $ajaxMode whether the view is rendering in AJAX mode.
649
     * If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
650
     * will be rendered at the end of the view like normal scripts.
651
     * @return string the rendered content
652
     */
653 56
    protected function renderBodyEndHtml($ajaxMode)
654
    {
655 56
        $lines = [];
656
657 56
        if (!empty($this->jsFiles[self::POS_END])) {
658 19
            $lines[] = implode("\n", $this->jsFiles[self::POS_END]);
659
        }
660
661 56
        if ($ajaxMode) {
662
            $scripts = [];
663
            if (!empty($this->js[self::POS_END])) {
664
                $scripts[] = implode("\n", $this->js[self::POS_END]);
665
            }
666
            if (!empty($this->js[self::POS_READY])) {
667
                $scripts[] = implode("\n", $this->js[self::POS_READY]);
668
            }
669
            if (!empty($this->js[self::POS_LOAD])) {
670
                $scripts[] = implode("\n", $this->js[self::POS_LOAD]);
671
            }
672
            if (!empty($scripts)) {
673
                $lines[] = Html::script(implode("\n", $scripts));
674
            }
675
        } else {
676 56
            if (!empty($this->js[self::POS_END])) {
677
                $lines[] = Html::script(implode("\n", $this->js[self::POS_END]));
678
            }
679 56
            if (!empty($this->js[self::POS_READY])) {
680
                $js = "jQuery(function ($) {\n" . implode("\n", $this->js[self::POS_READY]) . "\n});";
681
                $lines[] = Html::script($js);
682
            }
683 56
            if (!empty($this->js[self::POS_LOAD])) {
684
                $js = "jQuery(window).on('load', function () {\n" . implode("\n", $this->js[self::POS_LOAD]) . "\n});";
685
                $lines[] = Html::script($js);
686
            }
687
        }
688
689 56
        return empty($lines) ? '' : implode("\n", $lines);
690
    }
691
}
692