Completed
Push — master ( 974993...96cd8b )
by Alexander
25:35
created

View::registerFile()   B

Complexity

Conditions 10
Paths 14

Size

Total Lines 35
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 10

Importance

Changes 0
Metric Value
cc 10
eloc 26
nc 14
nop 4
dl 0
loc 35
ccs 24
cts 24
cp 1
crap 10
rs 7.6666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://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
    private $_assetManager;
135
136
137
    /**
138
     * Marks the position of an HTML head section.
139
     */
140 49
    public function head()
141
    {
142 49
        echo self::PH_HEAD;
143 49
    }
144
145
    /**
146
     * Marks the beginning of an HTML body section.
147
     */
148 49
    public function beginBody()
149
    {
150 49
        echo self::PH_BODY_BEGIN;
151 49
        $this->trigger(self::EVENT_BEGIN_BODY);
152 49
    }
153
154
    /**
155
     * Marks the ending of an HTML body section.
156
     */
157 53
    public function endBody()
158
    {
159 53
        $this->trigger(self::EVENT_END_BODY);
160 53
        echo self::PH_BODY_END;
161
162 53
        foreach (array_keys($this->assetBundles) as $bundle) {
163 12
            $this->registerAssetFiles($bundle);
164
        }
165 53
    }
166
167
    /**
168
     * Marks the ending of an HTML page.
169
     * @param bool $ajaxMode whether the view is rendering in AJAX mode.
170
     * If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
171
     * will be rendered at the end of the view like normal scripts.
172
     */
173 53
    public function endPage($ajaxMode = false)
174
    {
175 53
        $this->trigger(self::EVENT_END_PAGE);
176
177 53
        $content = ob_get_clean();
178
179 53
        echo strtr($content, [
180 53
            self::PH_HEAD => $this->renderHeadHtml(),
181 53
            self::PH_BODY_BEGIN => $this->renderBodyBeginHtml(),
182 53
            self::PH_BODY_END => $this->renderBodyEndHtml($ajaxMode),
183
        ]);
184
185 53
        $this->clear();
186 53
    }
187
188
    /**
189
     * Renders a view in response to an AJAX request.
190
     *
191
     * This method is similar to [[render()]] except that it will surround the view being rendered
192
     * with the calls of [[beginPage()]], [[head()]], [[beginBody()]], [[endBody()]] and [[endPage()]].
193
     * By doing so, the method is able to inject into the rendering result with JS/CSS scripts and files
194
     * that are registered with the view.
195
     *
196
     * @param string $view the view name. Please refer to [[render()]] on how to specify this parameter.
197
     * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
198
     * @param object $context the context that the view should use for rendering the view. If null,
199
     * existing [[context]] will be used.
200
     * @return string the rendering result
201
     * @see render()
202
     */
203
    public function renderAjax($view, $params = [], $context = null)
204
    {
205
        $viewFile = $this->findViewFile($view, $context);
206
207
        ob_start();
208
        ob_implicit_flush(false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $flag of ob_implicit_flush(). ( Ignorable by Annotation )

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

208
        ob_implicit_flush(/** @scrutinizer ignore-type */ false);
Loading history...
209
210
        $this->beginPage();
211
        $this->head();
212
        $this->beginBody();
213
        echo $this->renderFile($viewFile, $params, $context);
214
        $this->endBody();
215
        $this->endPage(true);
216
217
        return ob_get_clean();
218
    }
219
220
    /**
221
     * Registers the asset manager being used by this view object.
222
     * @return \yii\web\AssetManager the asset manager. Defaults to the "assetManager" application component.
223
     */
224 58
    public function getAssetManager()
225
    {
226 58
        return $this->_assetManager ?: Yii::$app->getAssetManager();
227
    }
228
229
    /**
230
     * Sets the asset manager.
231
     * @param \yii\web\AssetManager $value the asset manager
232
     */
233 78
    public function setAssetManager($value)
234
    {
235 78
        $this->_assetManager = $value;
236 78
    }
237
238
    /**
239
     * Clears up the registered meta tags, link tags, css/js scripts and files.
240
     */
241 55
    public function clear()
242
    {
243 55
        $this->metaTags = [];
244 55
        $this->linkTags = [];
245 55
        $this->css = [];
246 55
        $this->cssFiles = [];
247 55
        $this->js = [];
248 55
        $this->jsFiles = [];
249 55
        $this->assetBundles = [];
250 55
    }
251
252
    /**
253
     * Registers all files provided by an asset bundle including depending bundles files.
254
     * Removes a bundle from [[assetBundles]] once files are registered.
255
     * @param string $name name of the bundle to register
256
     */
257 12
    protected function registerAssetFiles($name)
258
    {
259 12
        if (!isset($this->assetBundles[$name])) {
260 10
            return;
261
        }
262 12
        $bundle = $this->assetBundles[$name];
263 12
        if ($bundle) {
0 ignored issues
show
introduced by
$bundle is of type yii\web\AssetBundle, thus it always evaluated to true.
Loading history...
264 12
            foreach ($bundle->depends as $dep) {
265 10
                $this->registerAssetFiles($dep);
266
            }
267 12
            $bundle->registerAssetFiles($this);
268
        }
269 12
        unset($this->assetBundles[$name]);
270 12
    }
271
272
    /**
273
     * Registers the named asset bundle.
274
     * All dependent asset bundles will be registered.
275
     * @param string $name the class name of the asset bundle (without the leading backslash)
276
     * @param int|null $position if set, this forces a minimum position for javascript files.
277
     * This will adjust depending assets javascript file position or fail if requirement can not be met.
278
     * If this is null, asset bundles position settings will not be changed.
279
     * See [[registerJsFile]] for more details on javascript position.
280
     * @return AssetBundle the registered asset bundle instance
281
     * @throws InvalidConfigException if the asset bundle does not exist or a circular dependency is detected
282
     */
283 32
    public function registerAssetBundle($name, $position = null)
284
    {
285 32
        if (!isset($this->assetBundles[$name])) {
286 31
            $am = $this->getAssetManager();
287 31
            $bundle = $am->getBundle($name);
288 31
            $this->assetBundles[$name] = false;
289
            // register dependencies
290 31
            $pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
291 31
            foreach ($bundle->depends as $dep) {
292 18
                $this->registerAssetBundle($dep, $pos);
293
            }
294 30
            $this->assetBundles[$name] = $bundle;
295 16
        } elseif ($this->assetBundles[$name] === false) {
0 ignored issues
show
introduced by
The condition $this->assetBundles[$name] === false is always false.
Loading history...
296 1
            throw new InvalidConfigException("A circular dependency is detected for bundle '$name'.");
297
        } else {
298 15
            $bundle = $this->assetBundles[$name];
299
        }
300
301 31
        if ($position !== null) {
302 12
            $pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
303 12
            if ($pos === null) {
304 12
                $bundle->jsOptions['position'] = $pos = $position;
305 6
            } elseif ($pos > $position) {
306 6
                throw new InvalidConfigException("An asset bundle that depends on '$name' has a higher javascript file position configured than '$name'.");
307
            }
308
            // update position for all dependencies
309 12
            foreach ($bundle->depends as $dep) {
310 6
                $this->registerAssetBundle($dep, $pos);
311
            }
312
        }
313
314 31
        return $bundle;
315
    }
316
317
    /**
318
     * Registers a meta tag.
319
     *
320
     * For example, a description meta tag can be added like the following:
321
     *
322
     * ```php
323
     * $view->registerMetaTag([
324
     *     'name' => 'description',
325
     *     'content' => 'This website is about funny raccoons.'
326
     * ]);
327
     * ```
328
     *
329
     * will result in the meta tag `<meta name="description" content="This website is about funny raccoons.">`.
330
     *
331
     * @param array $options the HTML attributes for the meta tag.
332
     * @param string $key the key that identifies the meta tag. If two meta tags are registered
333
     * with the same key, the latter will overwrite the former. If this is null, the new meta tag
334
     * will be appended to the existing ones.
335
     */
336
    public function registerMetaTag($options, $key = null)
337
    {
338
        if ($key === null) {
339
            $this->metaTags[] = Html::tag('meta', '', $options);
340
        } else {
341
            $this->metaTags[$key] = Html::tag('meta', '', $options);
342
        }
343
    }
344
345
    /**
346
     * Registers CSRF meta tags.
347
     * They are rendered dynamically to retrieve a new CSRF token for each request.
348
     *
349
     * ```php
350
     * $view->registerCsrfMetaTags();
351
     * ```
352
     *
353
     * The above code will result in `<meta name="csrf-param" content="[yii\web\Request::$csrfParam]">`
354
     * and `<meta name="csrf-token" content="tTNpWKpdy-bx8ZmIq9R72...K1y8IP3XGkzZA==">` added to the page.
355
     *
356
     * Note: Hidden CSRF input of ActiveForm will be automatically refreshed by calling `window.yii.refreshCsrfToken()`
357
     * from `yii.js`.
358
     *
359
     * @since 2.0.13
360
     */
361 1
    public function registerCsrfMetaTags()
362
    {
363 1
        $this->metaTags['csrf_meta_tags'] = $this->renderDynamic('return yii\helpers\Html::csrfMetaTags();');
364 1
    }
365
366
    /**
367
     * Registers a link tag.
368
     *
369
     * For example, a link tag for a custom [favicon](http://www.w3.org/2005/10/howto-favicon)
370
     * can be added like the following:
371
     *
372
     * ```php
373
     * $view->registerLinkTag(['rel' => 'icon', 'type' => 'image/png', 'href' => '/myicon.png']);
374
     * ```
375
     *
376
     * which will result in the following HTML: `<link rel="icon" type="image/png" href="/myicon.png">`.
377
     *
378
     * **Note:** To register link tags for CSS stylesheets, use [[registerCssFile()]] instead, which
379
     * has more options for this kind of link tag.
380
     *
381
     * @param array $options the HTML attributes for the link tag.
382
     * @param string $key the key that identifies the link tag. If two link tags are registered
383
     * with the same key, the latter will overwrite the former. If this is null, the new link tag
384
     * will be appended to the existing ones.
385
     */
386
    public function registerLinkTag($options, $key = null)
387
    {
388
        if ($key === null) {
389
            $this->linkTags[] = Html::tag('link', '', $options);
390
        } else {
391
            $this->linkTags[$key] = Html::tag('link', '', $options);
392
        }
393
    }
394
395
    /**
396
     * Registers a CSS code block.
397
     * @param string $css the content of the CSS code block to be registered
398
     * @param array $options the HTML attributes for the `<style>`-tag.
399
     * @param string $key the key that identifies the CSS code block. If null, it will use
400
     * $css as the key. If two CSS code blocks are registered with the same key, the latter
401
     * will overwrite the former.
402
     */
403
    public function registerCss($css, $options = [], $key = null)
404
    {
405
        $key = $key ?: md5($css);
406
        $this->css[$key] = Html::style($css, $options);
407
    }
408
409
    /**
410
     * Registers a CSS file.
411
     *
412
     * This method should be used for simple registration of CSS files. If you want to use features of
413
     * [[AssetManager]] like appending timestamps to the URL and file publishing options, use [[AssetBundle]]
414
     * and [[registerAssetBundle()]] instead.
415
     *
416
     * @param string $url the CSS file to be registered.
417
     * @param array $options the HTML attributes for the link tag. Please refer to [[Html::cssFile()]] for
418
     * the supported options. The following options are specially handled and are not treated as HTML attributes:
419
     *
420
     * - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
421
     * - `appendTimestamp`: bool whether to append a timestamp to the URL.
422
     *
423
     * @param string $key the key that identifies the CSS script file. If null, it will use
424
     * $url as the key. If two CSS files are registered with the same key, the latter
425
     * will overwrite the former.
426
     * @throws InvalidConfigException
427
     */
428 20
    public function registerCssFile($url, $options = [], $key = null)
429
    {
430 20
        $this->registerFile('css', $url, $options, $key);
431 20
    }
432
433
    /**
434
     * Registers a JS code block.
435
     * @param string $js the JS code block to be registered
436
     * @param int $position the position at which the JS script tag should be inserted
437
     * in a page. The possible values are:
438
     *
439
     * - [[POS_HEAD]]: in the head section
440
     * - [[POS_BEGIN]]: at the beginning of the body section
441
     * - [[POS_END]]: at the end of the body section
442
     * - [[POS_LOAD]]: enclosed within jQuery(window).load().
443
     *   Note that by using this position, the method will automatically register the jQuery js file.
444
     * - [[POS_READY]]: enclosed within jQuery(document).ready(). This is the default value.
445
     *   Note that by using this position, the method will automatically register the jQuery js file.
446
     *
447
     * @param string $key the key that identifies the JS code block. If null, it will use
448
     * $js as the key. If two JS code blocks are registered with the same key, the latter
449
     * will overwrite the former.
450
     */
451 9
    public function registerJs($js, $position = self::POS_READY, $key = null)
452
    {
453 9
        $key = $key ?: md5($js);
454 9
        $this->js[$position][$key] = $js;
455 9
        if ($position === self::POS_READY || $position === self::POS_LOAD) {
456 8
            JqueryAsset::register($this);
457
        }
458 9
    }
459
460
    /**
461
     * Registers a JS or CSS file.
462
     *
463
     * @param string $url the JS file to be registered.
464
     * @param string $type type (js or css) of the file.
465
     * @param array $options the HTML attributes for the script tag. The following options are specially handled
466
     * and are not treated as HTML attributes:
467
     *
468
     * - `depends`: array, specifies the names of the asset bundles that this CSS file depends on.
469
     * - `appendTimestamp`: bool whether to append a timestamp to the URL.
470
     *
471
     * @param string $key the key that identifies the JS script file. If null, it will use
472
     * $url as the key. If two JS files are registered with the same key at the same position, the latter
473
     * will overwrite the former. Note that position option takes precedence, thus files registered with the same key,
474
     * but different position option will not override each other.
475
     * @throws InvalidConfigException
476
     */
477 35
    private function registerFile($type, $url, $options = [], $key = null)
478
    {
479 35
        $url = Yii::getAlias($url);
480 35
        $key = $key ?: $url;
481 35
        $depends = ArrayHelper::remove($options, 'depends', []);
482 35
        $position = ArrayHelper::remove($options, 'position', self::POS_END);
483
484
        try {
485 35
            $asssetManagerAppendTimestamp = $this->getAssetManager()->appendTimestamp;
486 2
        } catch (InvalidConfigException $e) {
487 2
            $depends = null; // the AssetManager is not available
488 2
            $asssetManagerAppendTimestamp = false;
489
        }
490 35
        $appendTimestamp = ArrayHelper::remove($options, 'appendTimestamp', $asssetManagerAppendTimestamp);
491
492 35
        if (empty($depends)) {
493
            // register directly without AssetManager
494 35
            if ($appendTimestamp && Url::isRelative($url) && ($timestamp = @filemtime(Yii::getAlias('@webroot/' . ltrim($url, '/'), false))) > 0) {
495 2
                $url = $timestamp ? "$url?v=$timestamp" : $url;
496
            }
497 35
            if ($type === 'js') {
498 23
                $this->jsFiles[$position][$key] = Html::jsFile($url, $options);
499
            } else {
500 35
                $this->cssFiles[$key] = Html::cssFile($url, $options);
501
            }
502
        } else {
503 2
            $this->getAssetManager()->bundles[$key] = Yii::createObject([
504 2
                '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

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