Completed
Push — readme-redesign ( e2fd40...17eb05 )
by Alexander
108:51 queued 68:52
created

BaseHtml::activeCheckbox()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
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\helpers;
9
10
use Yii;
11
use yii\base\InvalidParamException;
12
use yii\db\ActiveRecordInterface;
13
use yii\validators\StringValidator;
14
use yii\web\Request;
15
use yii\base\Model;
16
17
/**
18
 * BaseHtml provides concrete implementation for [[Html]].
19
 *
20
 * Do not use BaseHtml. Use [[Html]] instead.
21
 *
22
 * @author Qiang Xue <[email protected]>
23
 * @since 2.0
24
 */
25
class BaseHtml
26
{
27
    /**
28
     * @var array list of void elements (element name => 1)
29
     * @see http://www.w3.org/TR/html-markup/syntax.html#void-element
30
     */
31
    public static $voidElements = [
32
        'area' => 1,
33
        'base' => 1,
34
        'br' => 1,
35
        'col' => 1,
36
        'command' => 1,
37
        'embed' => 1,
38
        'hr' => 1,
39
        'img' => 1,
40
        'input' => 1,
41
        'keygen' => 1,
42
        'link' => 1,
43
        'meta' => 1,
44
        'param' => 1,
45
        'source' => 1,
46
        'track' => 1,
47
        'wbr' => 1,
48
    ];
49
    /**
50
     * @var array the preferred order of attributes in a tag. This mainly affects the order of the attributes
51
     * that are rendered by [[renderTagAttributes()]].
52
     */
53
    public static $attributeOrder = [
54
        'type',
55
        'id',
56
        'class',
57
        'name',
58
        'value',
59
60
        'href',
61
        'src',
62
        'srcset',
63
        'form',
64
        'action',
65
        'method',
66
67
        'selected',
68
        'checked',
69
        'readonly',
70
        'disabled',
71
        'multiple',
72
73
        'size',
74
        'maxlength',
75
        'width',
76
        'height',
77
        'rows',
78
        'cols',
79
80
        'alt',
81
        'title',
82
        'rel',
83
        'media',
84
    ];
85
    /**
86
     * @var array list of tag attributes that should be specially handled when their values are of array type.
87
     * In particular, if the value of the `data` attribute is `['name' => 'xyz', 'age' => 13]`, two attributes
88
     * will be generated instead of one: `data-name="xyz" data-age="13"`.
89
     * @since 2.0.3
90
     */
91
    public static $dataAttributes = ['data', 'data-ng', 'ng'];
92
93
94
    /**
95
     * Encodes special characters into HTML entities.
96
     * The [[\yii\base\Application::charset|application charset]] will be used for encoding.
97
     * @param string $content the content to be encoded
98
     * @param bool $doubleEncode whether to encode HTML entities in `$content`. If false,
99
     * HTML entities in `$content` will not be further encoded.
100
     * @return string the encoded content
101
     * @see decode()
102
     * @see http://www.php.net/manual/en/function.htmlspecialchars.php
103
     */
104
    public static function encode($content, $doubleEncode = true)
105
    {
106
        return htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, Yii::$app ? Yii::$app->charset : 'UTF-8', $doubleEncode);
107
    }
108
109
    /**
110
     * Decodes special HTML entities back to the corresponding characters.
111
     * This is the opposite of [[encode()]].
112
     * @param string $content the content to be decoded
113
     * @return string the decoded content
114
     * @see encode()
115
     * @see http://www.php.net/manual/en/function.htmlspecialchars-decode.php
116
     */
117
    public static function decode($content)
118
    {
119
        return htmlspecialchars_decode($content, ENT_QUOTES);
120
    }
121
122
    /**
123
     * Generates a complete HTML tag.
124
     * @param string|bool|null $name the tag name. If $name is `null` or `false`, the corresponding content will be rendered without any tag.
125
     * @param string $content the content to be enclosed between the start and end tags. It will not be HTML-encoded.
126
     * If this is coming from end users, you should consider [[encode()]] it to prevent XSS attacks.
127
     * @param array $options the HTML tag attributes (HTML options) in terms of name-value pairs.
128
     * These will be rendered as the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
129
     * If a value is null, the corresponding attribute will not be rendered.
130
     *
131
     * For example when using `['class' => 'my-class', 'target' => '_blank', 'value' => null]` it will result in the
132
     * html attributes rendered like this: `class="my-class" target="_blank"`.
133
     *
134
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
135
     *
136
     * @return string the generated HTML tag
137
     * @see beginTag()
138
     * @see endTag()
139
     */
140
    public static function tag($name, $content = '', $options = [])
141
    {
142
        if ($name === null || $name === false) {
143
            return $content;
144
        }
145
        $html = "<$name" . static::renderTagAttributes($options) . '>';
146
        return isset(static::$voidElements[strtolower($name)]) ? $html : "$html$content</$name>";
147
    }
148
149
    /**
150
     * Generates a start tag.
151
     * @param string|bool|null $name the tag name. If $name is `null` or `false`, the corresponding content will be rendered without any tag.
152
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
153
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
154
     * If a value is null, the corresponding attribute will not be rendered.
155
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
156
     * @return string the generated start tag
157
     * @see endTag()
158
     * @see tag()
159
     */
160
    public static function beginTag($name, $options = [])
161
    {
162
        if ($name === null || $name === false) {
163
            return '';
164
        }
165
        return "<$name" . static::renderTagAttributes($options) . '>';
166
    }
167
168
    /**
169
     * Generates an end tag.
170
     * @param string|bool|null $name the tag name. If $name is `null` or `false`, the corresponding content will be rendered without any tag.
171
     * @return string the generated end tag
172
     * @see beginTag()
173
     * @see tag()
174
     */
175
    public static function endTag($name)
176
    {
177
        if ($name === null || $name === false) {
178
            return '';
179
        }
180
        return "</$name>";
181
    }
182
183
    /**
184
     * Generates a style tag.
185
     * @param string $content the style content
186
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
187
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
188
     * If a value is null, the corresponding attribute will not be rendered.
189
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
190
     * @return string the generated style tag
191
     */
192
    public static function style($content, $options = [])
193
    {
194
        return static::tag('style', $content, $options);
195
    }
196
197
    /**
198
     * Generates a script tag.
199
     * @param string $content the script content
200
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
201
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
202
     * If a value is null, the corresponding attribute will not be rendered.
203
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
204
     * @return string the generated script tag
205
     */
206
    public static function script($content, $options = [])
207
    {
208
        return static::tag('script', $content, $options);
209
    }
210
211
    /**
212
     * Generates a link tag that refers to an external CSS file.
213
     * @param array|string $url the URL of the external CSS file. This parameter will be processed by [[Url::to()]].
214
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
215
     *
216
     * - condition: specifies the conditional comments for IE, e.g., `lt IE 9`. When this is specified,
217
     *   the generated `link` tag will be enclosed within the conditional comments. This is mainly useful
218
     *   for supporting old versions of IE browsers.
219
     * - noscript: if set to true, `link` tag will be wrapped into `<noscript>` tags.
220
     *
221
     * The rest of the options will be rendered as the attributes of the resulting link tag. The values will
222
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
223
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
224
     * @return string the generated link tag
225
     * @see Url::to()
226
     */
227
    public static function cssFile($url, $options = [])
228
    {
229
        if (!isset($options['rel'])) {
230
            $options['rel'] = 'stylesheet';
231
        }
232
        $options['href'] = Url::to($url);
233
234
        if (isset($options['condition'])) {
235
            $condition = $options['condition'];
236
            unset($options['condition']);
237
            return self::wrapIntoCondition(static::tag('link', '', $options), $condition);
238
        } elseif (isset($options['noscript']) && $options['noscript'] === true) {
239
            unset($options['noscript']);
240
            return '<noscript>' . static::tag('link', '', $options) . '</noscript>';
241
        } else {
242
            return static::tag('link', '', $options);
243
        }
244
    }
245
246
    /**
247
     * Generates a script tag that refers to an external JavaScript file.
248
     * @param string $url the URL of the external JavaScript file. This parameter will be processed by [[Url::to()]].
249
     * @param array $options the tag options in terms of name-value pairs. The following option is specially handled:
250
     *
251
     * - condition: specifies the conditional comments for IE, e.g., `lt IE 9`. When this is specified,
252
     *   the generated `script` tag will be enclosed within the conditional comments. This is mainly useful
253
     *   for supporting old versions of IE browsers.
254
     *
255
     * The rest of the options will be rendered as the attributes of the resulting script tag. The values will
256
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
257
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
258
     * @return string the generated script tag
259
     * @see Url::to()
260
     */
261
    public static function jsFile($url, $options = [])
262
    {
263
        $options['src'] = Url::to($url);
264
        if (isset($options['condition'])) {
265
            $condition = $options['condition'];
266
            unset($options['condition']);
267
            return self::wrapIntoCondition(static::tag('script', '', $options), $condition);
268
        } else {
269
            return static::tag('script', '', $options);
270
        }
271
    }
272
273
    /**
274
     * Wraps given content into conditional comments for IE, e.g., `lt IE 9`.
275
     * @param string $content raw HTML content.
276
     * @param string $condition condition string.
277
     * @return string generated HTML.
278
     */
279
    private static function wrapIntoCondition($content, $condition)
280
    {
281
        if (strpos($condition, '!IE') !== false) {
282
            return "<!--[if $condition]><!-->\n" . $content . "\n<!--<![endif]-->";
283
        }
284
        return "<!--[if $condition]>\n" . $content . "\n<![endif]-->";
285
    }
286
287
    /**
288
     * Generates the meta tags containing CSRF token information.
289
     * @return string the generated meta tags
290
     * @see Request::enableCsrfValidation
291
     */
292
    public static function csrfMetaTags()
293
    {
294
        $request = Yii::$app->getRequest();
295
        if ($request instanceof Request && $request->enableCsrfValidation) {
296
            return static::tag('meta', '', ['name' => 'csrf-param', 'content' => $request->csrfParam]) . "\n    "
297
                . static::tag('meta', '', ['name' => 'csrf-token', 'content' => $request->getCsrfToken()]) . "\n";
298
        } else {
299
            return '';
300
        }
301
    }
302
303
    /**
304
     * Generates a form start tag.
305
     * @param array|string $action the form action URL. This parameter will be processed by [[Url::to()]].
306
     * @param string $method the form submission method, such as "post", "get", "put", "delete" (case-insensitive).
307
     * Since most browsers only support "post" and "get", if other methods are given, they will
308
     * be simulated using "post", and a hidden input will be added which contains the actual method type.
309
     * See [[\yii\web\Request::methodParam]] for more details.
310
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
311
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
312
     * If a value is null, the corresponding attribute will not be rendered.
313
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
314
     *
315
     * Special options:
316
     *
317
     *  - `csrf`: whether to generate the CSRF hidden input. Defaults to true.
318
     *
319
     * @return string the generated form start tag.
320
     * @see endForm()
321
     */
322
    public static function beginForm($action = '', $method = 'post', $options = [])
323
    {
324
        $action = Url::to($action);
325
326
        $hiddenInputs = [];
327
328
        $request = Yii::$app->getRequest();
329
        if ($request instanceof Request) {
330
            if (strcasecmp($method, 'get') && strcasecmp($method, 'post')) {
331
                // simulate PUT, DELETE, etc. via POST
332
                $hiddenInputs[] = static::hiddenInput($request->methodParam, $method);
333
                $method = 'post';
334
            }
335
            $csrf = ArrayHelper::remove($options, 'csrf', true);
336
337
            if ($csrf && $request->enableCsrfValidation && strcasecmp($method, 'post') === 0) {
338
                $hiddenInputs[] = static::hiddenInput($request->csrfParam, $request->getCsrfToken());
339
            }
340
        }
341
342
        if (!strcasecmp($method, 'get') && ($pos = strpos($action, '?')) !== false) {
343
            // query parameters in the action are ignored for GET method
344
            // we use hidden fields to add them back
345
            foreach (explode('&', substr($action, $pos + 1)) as $pair) {
346
                if (($pos1 = strpos($pair, '=')) !== false) {
347
                    $hiddenInputs[] = static::hiddenInput(
348
                        urldecode(substr($pair, 0, $pos1)),
349
                        urldecode(substr($pair, $pos1 + 1))
350
                    );
351
                } else {
352
                    $hiddenInputs[] = static::hiddenInput(urldecode($pair), '');
353
                }
354
            }
355
            $action = substr($action, 0, $pos);
356
        }
357
358
        $options['action'] = $action;
359
        $options['method'] = $method;
360
        $form = static::beginTag('form', $options);
361
        if (!empty($hiddenInputs)) {
362
            $form .= "\n" . implode("\n", $hiddenInputs);
363
        }
364
365
        return $form;
366
    }
367
368
    /**
369
     * Generates a form end tag.
370
     * @return string the generated tag
371
     * @see beginForm()
372
     */
373
    public static function endForm()
374
    {
375
        return '</form>';
376
    }
377
378
    /**
379
     * Generates a hyperlink tag.
380
     * @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code
381
     * such as an image tag. If this is coming from end users, you should consider [[encode()]]
382
     * it to prevent XSS attacks.
383
     * @param array|string|null $url the URL for the hyperlink tag. This parameter will be processed by [[Url::to()]]
384
     * and will be used for the "href" attribute of the tag. If this parameter is null, the "href" attribute
385
     * will not be generated.
386
     *
387
     * If you want to use an absolute url you can call [[Url::to()]] yourself, before passing the URL to this method,
388
     * like this:
389
     *
390
     * ```php
391
     * Html::a('link text', Url::to($url, true))
392
     * ```
393
     *
394
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
395
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
396
     * If a value is null, the corresponding attribute will not be rendered.
397
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
398
     * @return string the generated hyperlink
399
     * @see \yii\helpers\Url::to()
400
     */
401
    public static function a($text, $url = null, $options = [])
402
    {
403
        if ($url !== null) {
404
            $options['href'] = Url::to($url);
405
        }
406
        return static::tag('a', $text, $options);
407
    }
408
409
    /**
410
     * Generates a mailto hyperlink.
411
     * @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code
412
     * such as an image tag. If this is coming from end users, you should consider [[encode()]]
413
     * it to prevent XSS attacks.
414
     * @param string $email email address. If this is null, the first parameter (link body) will be treated
415
     * as the email address and used.
416
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
417
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
418
     * If a value is null, the corresponding attribute will not be rendered.
419
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
420
     * @return string the generated mailto link
421
     */
422
    public static function mailto($text, $email = null, $options = [])
423
    {
424
        $options['href'] = 'mailto:' . ($email === null ? $text : $email);
425
        return static::tag('a', $text, $options);
426
    }
427
428
    /**
429
     * Generates an image tag.
430
     * @param array|string $src the image URL. This parameter will be processed by [[Url::to()]].
431
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
432
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
433
     * If a value is null, the corresponding attribute will not be rendered.
434
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
435
     * @since 2.0.12 It is possible to pass the "srcset" option as an array which keys are
436
     * descriptors and values are URLs. All URLs will be processed by [[Url::to()]].
437
     * @return string the generated image tag
438
     */
439
    public static function img($src, $options = [])
440
    {
441
        $options['src'] = Url::to($src);
442
443
        if (isset($options['srcset']) && is_array($options['srcset'])) {
444
            $srcset = [];
445
            foreach ($options['srcset'] as $descriptor => $url) {
446
                $srcset[] = Url::to($url) . ' ' . $descriptor;
447
            }
448
            $options['srcset'] = implode(',', $srcset);
449
        }
450
451
        if (!isset($options['alt'])) {
452
            $options['alt'] = '';
453
        }
454
        return static::tag('img', '', $options);
455
    }
456
457
    /**
458
     * Generates a label tag.
459
     * @param string $content label text. It will NOT be HTML-encoded. Therefore you can pass in HTML code
460
     * such as an image tag. If this is is coming from end users, you should [[encode()]]
461
     * it to prevent XSS attacks.
462
     * @param string $for the ID of the HTML element that this label is associated with.
463
     * If this is null, the "for" attribute will not be generated.
464
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
465
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
466
     * If a value is null, the corresponding attribute will not be rendered.
467
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
468
     * @return string the generated label tag
469
     */
470
    public static function label($content, $for = null, $options = [])
471
    {
472
        $options['for'] = $for;
473
        return static::tag('label', $content, $options);
474
    }
475
476
    /**
477
     * Generates a button tag.
478
     * @param string $content the content enclosed within the button tag. It will NOT be HTML-encoded.
479
     * Therefore you can pass in HTML code such as an image tag. If this is is coming from end users,
480
     * you should consider [[encode()]] it to prevent XSS attacks.
481
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
482
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
483
     * If a value is null, the corresponding attribute will not be rendered.
484
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
485
     * @return string the generated button tag
486
     */
487
    public static function button($content = 'Button', $options = [])
488
    {
489
        if (!isset($options['type'])) {
490
            $options['type'] = 'button';
491
        }
492
        return static::tag('button', $content, $options);
493
    }
494
495
    /**
496
     * Generates a submit button tag.
497
     *
498
     * Be careful when naming form elements such as submit buttons. According to the [jQuery documentation](https://api.jquery.com/submit/) there
499
     * are some reserved names that can cause conflicts, e.g. `submit`, `length`, or `method`.
500
     *
501
     * @param string $content the content enclosed within the button tag. It will NOT be HTML-encoded.
502
     * Therefore you can pass in HTML code such as an image tag. If this is is coming from end users,
503
     * you should consider [[encode()]] it to prevent XSS attacks.
504
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
505
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
506
     * If a value is null, the corresponding attribute will not be rendered.
507
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
508
     * @return string the generated submit button tag
509
     */
510
    public static function submitButton($content = 'Submit', $options = [])
511
    {
512
        $options['type'] = 'submit';
513
        return static::button($content, $options);
514
    }
515
516
    /**
517
     * Generates a reset button tag.
518
     * @param string $content the content enclosed within the button tag. It will NOT be HTML-encoded.
519
     * Therefore you can pass in HTML code such as an image tag. If this is is coming from end users,
520
     * you should consider [[encode()]] it to prevent XSS attacks.
521
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
522
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
523
     * If a value is null, the corresponding attribute will not be rendered.
524
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
525
     * @return string the generated reset button tag
526
     */
527
    public static function resetButton($content = 'Reset', $options = [])
528
    {
529
        $options['type'] = 'reset';
530
        return static::button($content, $options);
531
    }
532
533
    /**
534
     * Generates an input type of the given type.
535
     * @param string $type the type attribute.
536
     * @param string $name the name attribute. If it is null, the name attribute will not be generated.
537
     * @param string $value the value attribute. If it is null, the value attribute will not be generated.
538
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
539
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
540
     * If a value is null, the corresponding attribute will not be rendered.
541
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
542
     * @return string the generated input tag
543
     */
544
    public static function input($type, $name = null, $value = null, $options = [])
545
    {
546
        if (!isset($options['type'])) {
547
            $options['type'] = $type;
548
        }
549
        $options['name'] = $name;
550
        $options['value'] = $value === null ? null : (string) $value;
551
        return static::tag('input', '', $options);
552
    }
553
554
    /**
555
     * Generates an input button.
556
     * @param string $label the value attribute. If it is null, the value attribute will not be generated.
557
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
558
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
559
     * If a value is null, the corresponding attribute will not be rendered.
560
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
561
     * @return string the generated button tag
562
     */
563
    public static function buttonInput($label = 'Button', $options = [])
564
    {
565
        $options['type'] = 'button';
566
        $options['value'] = $label;
567
        return static::tag('input', '', $options);
568
    }
569
570
    /**
571
     * Generates a submit input button.
572
     *
573
     * Be careful when naming form elements such as submit buttons. According to the [jQuery documentation](https://api.jquery.com/submit/) there
574
     * are some reserved names that can cause conflicts, e.g. `submit`, `length`, or `method`.
575
     *
576
     * @param string $label the value attribute. If it is null, the value attribute will not be generated.
577
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
578
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
579
     * If a value is null, the corresponding attribute will not be rendered.
580
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
581
     * @return string the generated button tag
582
     */
583
    public static function submitInput($label = 'Submit', $options = [])
584
    {
585
        $options['type'] = 'submit';
586
        $options['value'] = $label;
587
        return static::tag('input', '', $options);
588
    }
589
590
    /**
591
     * Generates a reset input button.
592
     * @param string $label the value attribute. If it is null, the value attribute will not be generated.
593
     * @param array $options the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
594
     * Attributes whose value is null will be ignored and not put in the tag returned.
595
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
596
     * @return string the generated button tag
597
     */
598
    public static function resetInput($label = 'Reset', $options = [])
599
    {
600
        $options['type'] = 'reset';
601
        $options['value'] = $label;
602
        return static::tag('input', '', $options);
603
    }
604
605
    /**
606
     * Generates a text input field.
607
     * @param string $name the name attribute.
608
     * @param string $value the value attribute. If it is null, the value attribute will not be generated.
609
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
610
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
611
     * If a value is null, the corresponding attribute will not be rendered.
612
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
613
     * @return string the generated text input tag
614
     */
615
    public static function textInput($name, $value = null, $options = [])
616
    {
617
        return static::input('text', $name, $value, $options);
618
    }
619
620
    /**
621
     * Generates a hidden input field.
622
     * @param string $name the name attribute.
623
     * @param string $value the value attribute. If it is null, the value attribute will not be generated.
624
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
625
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
626
     * If a value is null, the corresponding attribute will not be rendered.
627
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
628
     * @return string the generated hidden input tag
629
     */
630
    public static function hiddenInput($name, $value = null, $options = [])
631
    {
632
        return static::input('hidden', $name, $value, $options);
633
    }
634
635
    /**
636
     * Generates a password input field.
637
     * @param string $name the name attribute.
638
     * @param string $value the value attribute. If it is null, the value attribute will not be generated.
639
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
640
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
641
     * If a value is null, the corresponding attribute will not be rendered.
642
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
643
     * @return string the generated password input tag
644
     */
645
    public static function passwordInput($name, $value = null, $options = [])
646
    {
647
        return static::input('password', $name, $value, $options);
648
    }
649
650
    /**
651
     * Generates a file input field.
652
     * To use a file input field, you should set the enclosing form's "enctype" attribute to
653
     * be "multipart/form-data". After the form is submitted, the uploaded file information
654
     * can be obtained via $_FILES[$name] (see PHP documentation).
655
     * @param string $name the name attribute.
656
     * @param string $value the value attribute. If it is null, the value attribute will not be generated.
657
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
658
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
659
     * If a value is null, the corresponding attribute will not be rendered.
660
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
661
     * @return string the generated file input tag
662
     */
663
    public static function fileInput($name, $value = null, $options = [])
664
    {
665
        return static::input('file', $name, $value, $options);
666
    }
667
668
    /**
669
     * Generates a text area input.
670
     * @param string $name the input name
671
     * @param string $value the input value. Note that it will be encoded using [[encode()]].
672
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
673
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
674
     * If a value is null, the corresponding attribute will not be rendered.
675
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
676
     * The following special options are recognized:
677
     *
678
     * - `doubleEncode`: whether to double encode HTML entities in `$value`. If `false`, HTML entities in `$value` will not
679
     *   be further encoded. This option is available since version 2.0.11.
680
     *
681
     * @return string the generated text area tag
682
     */
683
    public static function textarea($name, $value = '', $options = [])
684
    {
685
        $options['name'] = $name;
686
        $doubleEncode = ArrayHelper::remove($options, 'doubleEncode', true);
687
        return static::tag('textarea', static::encode($value, $doubleEncode), $options);
688
    }
689
690
    /**
691
     * Generates a radio button input.
692
     * @param string $name the name attribute.
693
     * @param bool $checked whether the radio button should be checked.
694
     * @param array $options the tag options in terms of name-value pairs.
695
     * See [[booleanInput()]] for details about accepted attributes.
696
     *
697
     * @return string the generated radio button tag
698
     */
699
    public static function radio($name, $checked = false, $options = [])
700
    {
701
        return static::booleanInput('radio', $name, $checked, $options);
702
    }
703
704
    /**
705
     * Generates a checkbox input.
706
     * @param string $name the name attribute.
707
     * @param bool $checked whether the checkbox should be checked.
708
     * @param array $options the tag options in terms of name-value pairs.
709
     * See [[booleanInput()]] for details about accepted attributes.
710
     *
711
     * @return string the generated checkbox tag
712
     */
713
    public static function checkbox($name, $checked = false, $options = [])
714
    {
715
        return static::booleanInput('checkbox', $name, $checked, $options);
716
    }
717
718
    /**
719
     * Generates a boolean input.
720
     * @param string $type the input type. This can be either `radio` or `checkbox`.
721
     * @param string $name the name attribute.
722
     * @param bool $checked whether the checkbox should be checked.
723
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
724
     *
725
     * - uncheck: string, the value associated with the uncheck state of the checkbox. When this attribute
726
     *   is present, a hidden input will be generated so that if the checkbox is not checked and is submitted,
727
     *   the value of this attribute will still be submitted to the server via the hidden input.
728
     * - label: string, a label displayed next to the checkbox.  It will NOT be HTML-encoded. Therefore you can pass
729
     *   in HTML code such as an image tag. If this is is coming from end users, you should [[encode()]] it to prevent XSS attacks.
730
     *   When this option is specified, the checkbox will be enclosed by a label tag.
731
     * - labelOptions: array, the HTML attributes for the label tag. Do not set this option unless you set the "label" option.
732
     *
733
     * The rest of the options will be rendered as the attributes of the resulting checkbox tag. The values will
734
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
735
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
736
     *
737
     * @return string the generated checkbox tag
738
     * @since 2.0.9
739
     */
740
    protected static function booleanInput($type, $name, $checked = false, $options = [])
741
    {
742
        $options['checked'] = (bool) $checked;
743
        $value = array_key_exists('value', $options) ? $options['value'] : '1';
744
        if (isset($options['uncheck'])) {
745
            // add a hidden field so that if the checkbox is not selected, it still submits a value
746
            $hiddenOptions = [];
747
            if (isset($options['form'])) {
748
                $hiddenOptions['form'] = $options['form'];
749
            }
750
            $hidden = static::hiddenInput($name, $options['uncheck'], $hiddenOptions);
0 ignored issues
show
Documentation introduced by
$options['uncheck'] is of type boolean, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
751
            unset($options['uncheck']);
752
        } else {
753
            $hidden = '';
754
        }
755
        if (isset($options['label'])) {
756
            $label = $options['label'];
757
            $labelOptions = isset($options['labelOptions']) ? $options['labelOptions'] : [];
758
            unset($options['label'], $options['labelOptions']);
759
            $content = static::label(static::input($type, $name, $value, $options) . ' ' . $label, null, $labelOptions);
0 ignored issues
show
Bug introduced by
It seems like $labelOptions defined by isset($options['labelOpt...abelOptions'] : array() on line 757 can also be of type boolean; however, yii\helpers\BaseHtml::label() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
760
            return $hidden . $content;
761
        } else {
762
            return $hidden . static::input($type, $name, $value, $options);
763
        }
764
    }
765
766
    /**
767
     * Generates a drop-down list.
768
     * @param string $name the input name
769
     * @param string|array|null $selection the selected value(s). String for single or array for multiple selection(s).
770
     * @param array $items the option data items. The array keys are option values, and the array values
771
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
772
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
773
     * If you have a list of data models, you may convert them into the format described above using
774
     * [[\yii\helpers\ArrayHelper::map()]].
775
     *
776
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
777
     * the labels will also be HTML-encoded.
778
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
779
     *
780
     * - prompt: string, a prompt text to be displayed as the first option. Since version 2.0.11 you can use an array
781
     *   to override the value and to set other tag attributes:
782
     *
783
     *   ```php
784
     *   ['text' => 'Please select', 'options' => ['value' => 'none', 'class' => 'prompt', 'label' => 'Select']],
785
     *   ```
786
     *
787
     * - options: array, the attributes for the select option tags. The array keys must be valid option values,
788
     *   and the array values are the extra attributes for the corresponding option tags. For example,
789
     *
790
     *   ```php
791
     *   [
792
     *       'value1' => ['disabled' => true],
793
     *       'value2' => ['label' => 'value 2'],
794
     *   ];
795
     *   ```
796
     *
797
     * - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
798
     *   except that the array keys represent the optgroup labels specified in $items.
799
     * - encodeSpaces: bool, whether to encode spaces in option prompt and option value with `&nbsp;` character.
800
     *   Defaults to false.
801
     * - encode: bool, whether to encode option prompt and option value characters.
802
     *   Defaults to `true`. This option is available since 2.0.3.
803
     *
804
     * The rest of the options will be rendered as the attributes of the resulting tag. The values will
805
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
806
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
807
     *
808
     * @return string the generated drop-down list tag
809
     */
810
    public static function dropDownList($name, $selection = null, $items = [], $options = [])
811
    {
812
        if (!empty($options['multiple'])) {
813
            return static::listBox($name, $selection, $items, $options);
814
        }
815
        $options['name'] = $name;
816
        unset($options['unselect']);
817
        $selectOptions = static::renderSelectOptions($selection, $items, $options);
818
        return static::tag('select', "\n" . $selectOptions . "\n", $options);
819
    }
820
821
    /**
822
     * Generates a list box.
823
     * @param string $name the input name
824
     * @param string|array|null $selection the selected value(s). String for single or array for multiple selection(s).
825
     * @param array $items the option data items. The array keys are option values, and the array values
826
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
827
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
828
     * If you have a list of data models, you may convert them into the format described above using
829
     * [[\yii\helpers\ArrayHelper::map()]].
830
     *
831
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
832
     * the labels will also be HTML-encoded.
833
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
834
     *
835
     * - prompt: string, a prompt text to be displayed as the first option. Since version 2.0.11 you can use an array
836
     *   to override the value and to set other tag attributes:
837
     *
838
     *   ```php
839
     *   ['text' => 'Please select', 'options' => ['value' => 'none', 'class' => 'prompt', 'label' => 'Select']],
840
     *   ```
841
     *
842
     * - options: array, the attributes for the select option tags. The array keys must be valid option values,
843
     *   and the array values are the extra attributes for the corresponding option tags. For example,
844
     *
845
     *   ```php
846
     *   [
847
     *       'value1' => ['disabled' => true],
848
     *       'value2' => ['label' => 'value 2'],
849
     *   ];
850
     *   ```
851
     *
852
     * - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
853
     *   except that the array keys represent the optgroup labels specified in $items.
854
     * - unselect: string, the value that will be submitted when no option is selected.
855
     *   When this attribute is set, a hidden field will be generated so that if no option is selected in multiple
856
     *   mode, we can still obtain the posted unselect value.
857
     * - encodeSpaces: bool, whether to encode spaces in option prompt and option value with `&nbsp;` character.
858
     *   Defaults to false.
859
     * - encode: bool, whether to encode option prompt and option value characters.
860
     *   Defaults to `true`. This option is available since 2.0.3.
861
     *
862
     * The rest of the options will be rendered as the attributes of the resulting tag. The values will
863
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
864
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
865
     *
866
     * @return string the generated list box tag
867
     */
868
    public static function listBox($name, $selection = null, $items = [], $options = [])
869
    {
870
        if (!array_key_exists('size', $options)) {
871
            $options['size'] = 4;
872
        }
873
        if (!empty($options['multiple']) && !empty($name) && substr_compare($name, '[]', -2, 2)) {
874
            $name .= '[]';
875
        }
876
        $options['name'] = $name;
877
        if (isset($options['unselect'])) {
878
            // add a hidden field so that if the list box has no option being selected, it still submits a value
879
            if (!empty($name) && substr_compare($name, '[]', -2, 2) === 0) {
880
                $name = substr($name, 0, -2);
881
            }
882
            $hidden = static::hiddenInput($name, $options['unselect']);
883
            unset($options['unselect']);
884
        } else {
885
            $hidden = '';
886
        }
887
        $selectOptions = static::renderSelectOptions($selection, $items, $options);
888
        return $hidden . static::tag('select', "\n" . $selectOptions . "\n", $options);
889
    }
890
891
    /**
892
     * Generates a list of checkboxes.
893
     * A checkbox list allows multiple selection, like [[listBox()]].
894
     * As a result, the corresponding submitted value is an array.
895
     * @param string $name the name attribute of each checkbox.
896
     * @param string|array|null $selection the selected value(s). String for single or array for multiple selection(s).
897
     * @param array $items the data item used to generate the checkboxes.
898
     * The array keys are the checkbox values, while the array values are the corresponding labels.
899
     * @param array $options options (name => config) for the checkbox list container tag.
900
     * The following options are specially handled:
901
     *
902
     * - tag: string|false, the tag name of the container element. False to render checkbox without container.
903
     *   See also [[tag()]].
904
     * - unselect: string, the value that should be submitted when none of the checkboxes is selected.
905
     *   By setting this option, a hidden input will be generated.
906
     * - encode: boolean, whether to HTML-encode the checkbox labels. Defaults to true.
907
     *   This option is ignored if `item` option is set.
908
     * - separator: string, the HTML code that separates items.
909
     * - itemOptions: array, the options for generating the checkbox tag using [[checkbox()]].
910
     * - item: callable, a callback that can be used to customize the generation of the HTML code
911
     *   corresponding to a single item in $items. The signature of this callback must be:
912
     *
913
     *   ```php
914
     *   function ($index, $label, $name, $checked, $value)
915
     *   ```
916
     *
917
     *   where $index is the zero-based index of the checkbox in the whole list; $label
918
     *   is the label for the checkbox; and $name, $value and $checked represent the name,
919
     *   value and the checked status of the checkbox input, respectively.
920
     *
921
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
922
     *
923
     * @return string the generated checkbox list
924
     */
925
    public static function checkboxList($name, $selection = null, $items = [], $options = [])
926
    {
927
        if (substr($name, -2) !== '[]') {
928
            $name .= '[]';
929
        }
930
931
        $formatter = ArrayHelper::remove($options, 'item');
932
        $itemOptions = ArrayHelper::remove($options, 'itemOptions', []);
933
        $encode = ArrayHelper::remove($options, 'encode', true);
934
        $separator = ArrayHelper::remove($options, 'separator', "\n");
935
        $tag = ArrayHelper::remove($options, 'tag', 'div');
936
937
        $lines = [];
938
        $index = 0;
939
        foreach ($items as $value => $label) {
940
            $checked = $selection !== null &&
941
                (!ArrayHelper::isTraversable($selection) && !strcmp($value, $selection)
942
                    || ArrayHelper::isTraversable($selection) && ArrayHelper::isIn($value, $selection));
0 ignored issues
show
Bug introduced by
It seems like $selection defined by parameter $selection on line 925 can also be of type string; however, yii\helpers\BaseArrayHelper::isIn() does only seem to accept array|object<Traversable>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
943
            if ($formatter !== null) {
944
                $lines[] = call_user_func($formatter, $index, $label, $name, $checked, $value);
945
            } else {
946
                $lines[] = static::checkbox($name, $checked, array_merge($itemOptions, [
947
                    'value' => $value,
948
                    'label' => $encode ? static::encode($label) : $label,
949
                ]));
950
            }
951
            $index++;
952
        }
953
954
        if (isset($options['unselect'])) {
955
            // add a hidden field so that if the list box has no option being selected, it still submits a value
956
            $name2 = substr($name, -2) === '[]' ? substr($name, 0, -2) : $name;
957
            $hidden = static::hiddenInput($name2, $options['unselect']);
958
            unset($options['unselect']);
959
        } else {
960
            $hidden = '';
961
        }
962
963
        $visibleContent = implode($separator, $lines);
964
965
        if ($tag === false) {
966
            return $hidden . $visibleContent;
967
        }
968
969
        return $hidden . static::tag($tag, $visibleContent, $options);
970
    }
971
972
    /**
973
     * Generates a list of radio buttons.
974
     * A radio button list is like a checkbox list, except that it only allows single selection.
975
     * @param string $name the name attribute of each radio button.
976
     * @param string|array|null $selection the selected value(s). String for single or array for multiple selection(s).
977
     * @param array $items the data item used to generate the radio buttons.
978
     * The array keys are the radio button values, while the array values are the corresponding labels.
979
     * @param array $options options (name => config) for the radio button list container tag.
980
     * The following options are specially handled:
981
     *
982
     * - tag: string|false, the tag name of the container element. False to render radio buttons without container.
983
     *   See also [[tag()]].
984
     * - unselect: string, the value that should be submitted when none of the radio buttons is selected.
985
     *   By setting this option, a hidden input will be generated.
986
     * - encode: boolean, whether to HTML-encode the checkbox labels. Defaults to true.
987
     *   This option is ignored if `item` option is set.
988
     * - separator: string, the HTML code that separates items.
989
     * - itemOptions: array, the options for generating the radio button tag using [[radio()]].
990
     * - item: callable, a callback that can be used to customize the generation of the HTML code
991
     *   corresponding to a single item in $items. The signature of this callback must be:
992
     *
993
     *   ```php
994
     *   function ($index, $label, $name, $checked, $value)
995
     *   ```
996
     *
997
     *   where $index is the zero-based index of the radio button in the whole list; $label
998
     *   is the label for the radio button; and $name, $value and $checked represent the name,
999
     *   value and the checked status of the radio button input, respectively.
1000
     *
1001
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1002
     *
1003
     * @return string the generated radio button list
1004
     */
1005
    public static function radioList($name, $selection = null, $items = [], $options = [])
1006
    {
1007
        $formatter = ArrayHelper::remove($options, 'item');
1008
        $itemOptions = ArrayHelper::remove($options, 'itemOptions', []);
1009
        $encode = ArrayHelper::remove($options, 'encode', true);
1010
        $separator = ArrayHelper::remove($options, 'separator', "\n");
1011
        $tag = ArrayHelper::remove($options, 'tag', 'div');
1012
        // add a hidden field so that if the list box has no option being selected, it still submits a value
1013
        $hidden = isset($options['unselect']) ? static::hiddenInput($name, $options['unselect']) : '';
1014
        unset($options['unselect']);
1015
1016
        $lines = [];
1017
        $index = 0;
1018
        foreach ($items as $value => $label) {
1019
            $checked = $selection !== null &&
1020
                (!ArrayHelper::isTraversable($selection) && !strcmp($value, $selection)
1021
                    || ArrayHelper::isTraversable($selection) && ArrayHelper::isIn($value, $selection));
0 ignored issues
show
Bug introduced by
It seems like $selection defined by parameter $selection on line 1005 can also be of type string; however, yii\helpers\BaseArrayHelper::isIn() does only seem to accept array|object<Traversable>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
1022
            if ($formatter !== null) {
1023
                $lines[] = call_user_func($formatter, $index, $label, $name, $checked, $value);
1024
            } else {
1025
                $lines[] = static::radio($name, $checked, array_merge($itemOptions, [
1026
                    'value' => $value,
1027
                    'label' => $encode ? static::encode($label) : $label,
1028
                ]));
1029
            }
1030
            $index++;
1031
        }
1032
        $visibleContent = implode($separator, $lines);
1033
1034
        if ($tag === false) {
1035
            return $hidden . $visibleContent;
1036
        }
1037
1038
        return $hidden . static::tag($tag, $visibleContent, $options);
1039
    }
1040
1041
    /**
1042
     * Generates an unordered list.
1043
     * @param array|\Traversable $items the items for generating the list. Each item generates a single list item.
1044
     * Note that items will be automatically HTML encoded if `$options['encode']` is not set or true.
1045
     * @param array $options options (name => config) for the radio button list. The following options are supported:
1046
     *
1047
     * - encode: boolean, whether to HTML-encode the items. Defaults to true.
1048
     *   This option is ignored if the `item` option is specified.
1049
     * - separator: string, the HTML code that separates items. Defaults to a simple newline (`"\n"`).
1050
     *   This option is available since version 2.0.7.
1051
     * - itemOptions: array, the HTML attributes for the `li` tags. This option is ignored if the `item` option is specified.
1052
     * - item: callable, a callback that is used to generate each individual list item.
1053
     *   The signature of this callback must be:
1054
     *
1055
     *   ```php
1056
     *   function ($item, $index)
1057
     *   ```
1058
     *
1059
     *   where $index is the array key corresponding to `$item` in `$items`. The callback should return
1060
     *   the whole list item tag.
1061
     *
1062
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1063
     *
1064
     * @return string the generated unordered list. An empty list tag will be returned if `$items` is empty.
1065
     */
1066
    public static function ul($items, $options = [])
1067
    {
1068
        $tag = ArrayHelper::remove($options, 'tag', 'ul');
1069
        $encode = ArrayHelper::remove($options, 'encode', true);
1070
        $formatter = ArrayHelper::remove($options, 'item');
1071
        $separator = ArrayHelper::remove($options, 'separator', "\n");
1072
        $itemOptions = ArrayHelper::remove($options, 'itemOptions', []);
1073
1074
        if (empty($items)) {
1075
            return static::tag($tag, '', $options);
1076
        }
1077
1078
        $results = [];
1079
        foreach ($items as $index => $item) {
1080
            if ($formatter !== null) {
1081
                $results[] = call_user_func($formatter, $item, $index);
1082
            } else {
1083
                $results[] = static::tag('li', $encode ? static::encode($item) : $item, $itemOptions);
1084
            }
1085
        }
1086
1087
        return static::tag(
1088
            $tag,
1089
            $separator . implode($separator, $results) . $separator,
1090
            $options
1091
        );
1092
    }
1093
1094
    /**
1095
     * Generates an ordered list.
1096
     * @param array|\Traversable $items the items for generating the list. Each item generates a single list item.
1097
     * Note that items will be automatically HTML encoded if `$options['encode']` is not set or true.
1098
     * @param array $options options (name => config) for the radio button list. The following options are supported:
1099
     *
1100
     * - encode: boolean, whether to HTML-encode the items. Defaults to true.
1101
     *   This option is ignored if the `item` option is specified.
1102
     * - itemOptions: array, the HTML attributes for the `li` tags. This option is ignored if the `item` option is specified.
1103
     * - item: callable, a callback that is used to generate each individual list item.
1104
     *   The signature of this callback must be:
1105
     *
1106
     *   ```php
1107
     *   function ($item, $index)
1108
     *   ```
1109
     *
1110
     *   where $index is the array key corresponding to `$item` in `$items`. The callback should return
1111
     *   the whole list item tag.
1112
     *
1113
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1114
     *
1115
     * @return string the generated ordered list. An empty string is returned if `$items` is empty.
1116
     */
1117
    public static function ol($items, $options = [])
1118
    {
1119
        $options['tag'] = 'ol';
1120
        return static::ul($items, $options);
1121
    }
1122
1123
    /**
1124
     * Generates a label tag for the given model attribute.
1125
     * The label text is the label associated with the attribute, obtained via [[Model::getAttributeLabel()]].
1126
     * @param Model $model the model object
1127
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1128
     * about attribute expression.
1129
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1130
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1131
     * If a value is null, the corresponding attribute will not be rendered.
1132
     * The following options are specially handled:
1133
     *
1134
     * - label: this specifies the label to be displayed. Note that this will NOT be [[encode()|encoded]].
1135
     *   If this is not set, [[Model::getAttributeLabel()]] will be called to get the label for display
1136
     *   (after encoding).
1137
     *
1138
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1139
     *
1140
     * @return string the generated label tag
1141
     */
1142
    public static function activeLabel($model, $attribute, $options = [])
1143
    {
1144
        $for = ArrayHelper::remove($options, 'for', static::getInputId($model, $attribute));
1145
        $attribute = static::getAttributeName($attribute);
1146
        $label = ArrayHelper::remove($options, 'label', static::encode($model->getAttributeLabel($attribute)));
1147
        return static::label($label, $for, $options);
1148
    }
1149
1150
    /**
1151
     * Generates a hint tag for the given model attribute.
1152
     * The hint text is the hint associated with the attribute, obtained via [[Model::getAttributeHint()]].
1153
     * If no hint content can be obtained, method will return an empty string.
1154
     * @param Model $model the model object
1155
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1156
     * about attribute expression.
1157
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1158
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1159
     * If a value is null, the corresponding attribute will not be rendered.
1160
     * The following options are specially handled:
1161
     *
1162
     * - hint: this specifies the hint to be displayed. Note that this will NOT be [[encode()|encoded]].
1163
     *   If this is not set, [[Model::getAttributeHint()]] will be called to get the hint for display
1164
     *   (without encoding).
1165
     *
1166
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1167
     *
1168
     * @return string the generated hint tag
1169
     * @since 2.0.4
1170
     */
1171
    public static function activeHint($model, $attribute, $options = [])
1172
    {
1173
        $attribute = static::getAttributeName($attribute);
1174
        $hint = isset($options['hint']) ? $options['hint'] : $model->getAttributeHint($attribute);
1175
        if (empty($hint)) {
1176
            return '';
1177
        }
1178
        $tag = ArrayHelper::remove($options, 'tag', 'div');
1179
        unset($options['hint']);
1180
        return static::tag($tag, $hint, $options);
1181
    }
1182
1183
    /**
1184
     * Generates a summary of the validation errors.
1185
     * If there is no validation error, an empty error summary markup will still be generated, but it will be hidden.
1186
     * @param Model|Model[] $models the model(s) whose validation errors are to be displayed.
1187
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
1188
     *
1189
     * - header: string, the header HTML for the error summary. If not set, a default prompt string will be used.
1190
     * - footer: string, the footer HTML for the error summary. Defaults to empty string.
1191
     * - encode: boolean, if set to false then the error messages won't be encoded. Defaults to `true`.
1192
     * - showAllErrors: boolean, if set to true every error message for each attribute will be shown otherwise
1193
     *   only the first error message for each attribute will be shown. Defaults to `false`.
1194
     *   Option is available since 2.0.10.
1195
     *
1196
     * The rest of the options will be rendered as the attributes of the container tag.
1197
     *
1198
     * @return string the generated error summary
1199
     */
1200
    public static function errorSummary($models, $options = [])
1201
    {
1202
        $header = isset($options['header']) ? $options['header'] : '<p>' . Yii::t('yii', 'Please fix the following errors:') . '</p>';
1203
        $footer = ArrayHelper::remove($options, 'footer', '');
1204
        $encode = ArrayHelper::remove($options, 'encode', true);
1205
        $showAllErrors = ArrayHelper::remove($options, 'showAllErrors', false);
1206
        unset($options['header']);
1207
1208
        $lines = [];
1209
        if (!is_array($models)) {
1210
            $models = [$models];
1211
        }
1212
        foreach ($models as $model) {
1213
            /* @var $model Model */
1214
            foreach ($model->getErrors() as $errors) {
1215
                foreach ($errors as $error) {
1216
                    $line = $encode ? Html::encode($error) : $error;
1217
                    if (array_search($line, $lines) === false) {
1218
                        $lines[] = $line;
1219
                    }
1220
                    if (!$showAllErrors) {
1221
                        break;
1222
                    }
1223
                }
1224
            }
1225
        }
1226
1227
        if (empty($lines)) {
1228
            // still render the placeholder for client-side validation use
1229
            $content = '<ul></ul>';
1230
            $options['style'] = isset($options['style']) ? rtrim($options['style'], ';') . '; display:none' : 'display:none';
1231
        } else {
1232
            $content = '<ul><li>' . implode("</li>\n<li>", $lines) . '</li></ul>';
1233
        }
1234
        return Html::tag('div', $header . $content . $footer, $options);
1235
    }
1236
1237
    /**
1238
     * Generates a tag that contains the first validation error of the specified model attribute.
1239
     * Note that even if there is no validation error, this method will still return an empty error tag.
1240
     * @param Model $model the model object
1241
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1242
     * about attribute expression.
1243
     * @param array $options the tag options in terms of name-value pairs. The values will be HTML-encoded
1244
     * using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
1245
     *
1246
     * The following options are specially handled:
1247
     *
1248
     * - tag: this specifies the tag name. If not set, "div" will be used.
1249
     *   See also [[tag()]].
1250
     * - encode: boolean, if set to false then the error message won't be encoded.
1251
     *
1252
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1253
     *
1254
     * @return string the generated label tag
1255
     */
1256
    public static function error($model, $attribute, $options = [])
1257
    {
1258
        $attribute = static::getAttributeName($attribute);
1259
        $error = $model->getFirstError($attribute);
1260
        $tag = ArrayHelper::remove($options, 'tag', 'div');
1261
        $encode = ArrayHelper::remove($options, 'encode', true);
1262
        return Html::tag($tag, $encode ? Html::encode($error) : $error, $options);
1263
    }
1264
1265
    /**
1266
     * Generates an input tag for the given model attribute.
1267
     * This method will generate the "name" and "value" tag attributes automatically for the model attribute
1268
     * unless they are explicitly specified in `$options`.
1269
     * @param string $type the input type (e.g. 'text', 'password')
1270
     * @param Model $model the model object
1271
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1272
     * about attribute expression.
1273
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1274
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1275
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1276
     * @return string the generated input tag
1277
     */
1278
    public static function activeInput($type, $model, $attribute, $options = [])
1279
    {
1280
        $name = isset($options['name']) ? $options['name'] : static::getInputName($model, $attribute);
1281
        $value = isset($options['value']) ? $options['value'] : static::getAttributeValue($model, $attribute);
1282
        if (!array_key_exists('id', $options)) {
1283
            $options['id'] = static::getInputId($model, $attribute);
1284
        }
1285
        return static::input($type, $name, $value, $options);
1286
    }
1287
1288
    /**
1289
     * If `maxlength` option is set true and the model attribute is validated by a string validator,
1290
     * the `maxlength` option will take the value of [[\yii\validators\StringValidator::max]].
1291
     * @param Model $model the model object
1292
     * @param string $attribute the attribute name or expression.
1293
     * @param array $options the tag options in terms of name-value pairs.
1294
     */
1295
    private static function normalizeMaxLength($model, $attribute, &$options)
1296
    {
1297
        if (isset($options['maxlength']) && $options['maxlength'] === true) {
1298
            unset($options['maxlength']);
1299
            $attrName = static::getAttributeName($attribute);
1300
            foreach ($model->getActiveValidators($attrName) as $validator) {
1301
                if ($validator instanceof StringValidator && $validator->max !== null) {
1302
                    $options['maxlength'] = $validator->max;
1303
                    break;
1304
                }
1305
            }
1306
        }
1307
    }
1308
1309
    /**
1310
     * Generates a text input tag for the given model attribute.
1311
     * This method will generate the "name" and "value" tag attributes automatically for the model attribute
1312
     * unless they are explicitly specified in `$options`.
1313
     * @param Model $model the model object
1314
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1315
     * about attribute expression.
1316
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1317
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1318
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1319
     * The following special options are recognized:
1320
     *
1321
     * - maxlength: integer|boolean, when `maxlength` is set true and the model attribute is validated
1322
     *   by a string validator, the `maxlength` option will take the value of [[\yii\validators\StringValidator::max]].
1323
     *   This is available since version 2.0.3.
1324
     *
1325
     * @return string the generated input tag
1326
     */
1327
    public static function activeTextInput($model, $attribute, $options = [])
1328
    {
1329
        self::normalizeMaxLength($model, $attribute, $options);
1330
        return static::activeInput('text', $model, $attribute, $options);
1331
    }
1332
1333
    /**
1334
     * Generates a hidden input tag for the given model attribute.
1335
     * This method will generate the "name" and "value" tag attributes automatically for the model attribute
1336
     * unless they are explicitly specified in `$options`.
1337
     * @param Model $model the model object
1338
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1339
     * about attribute expression.
1340
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1341
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1342
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1343
     * @return string the generated input tag
1344
     */
1345
    public static function activeHiddenInput($model, $attribute, $options = [])
1346
    {
1347
        return static::activeInput('hidden', $model, $attribute, $options);
1348
    }
1349
1350
    /**
1351
     * Generates a password input tag for the given model attribute.
1352
     * This method will generate the "name" and "value" tag attributes automatically for the model attribute
1353
     * unless they are explicitly specified in `$options`.
1354
     * @param Model $model the model object
1355
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1356
     * about attribute expression.
1357
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1358
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1359
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1360
     * The following special options are recognized:
1361
     *
1362
     * - maxlength: integer|boolean, when `maxlength` is set true and the model attribute is validated
1363
     *   by a string validator, the `maxlength` option will take the value of [[\yii\validators\StringValidator::max]].
1364
     *   This option is available since version 2.0.6.
1365
     *
1366
     * @return string the generated input tag
1367
     */
1368
    public static function activePasswordInput($model, $attribute, $options = [])
1369
    {
1370
        self::normalizeMaxLength($model, $attribute, $options);
1371
        return static::activeInput('password', $model, $attribute, $options);
1372
    }
1373
1374
    /**
1375
     * Generates a file input tag for the given model attribute.
1376
     * This method will generate the "name" and "value" tag attributes automatically for the model attribute
1377
     * unless they are explicitly specified in `$options`.
1378
     * @param Model $model the model object
1379
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1380
     * about attribute expression.
1381
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1382
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1383
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1384
     * @return string the generated input tag
1385
     */
1386
    public static function activeFileInput($model, $attribute, $options = [])
1387
    {
1388
        // add a hidden field so that if a model only has a file field, we can
1389
        // still use isset($_POST[$modelClass]) to detect if the input is submitted
1390
        $hiddenOptions = ['id' => null, 'value' => ''];
1391
        if (isset($options['name'])) {
1392
            $hiddenOptions['name'] = $options['name'];
1393
        }
1394
        return static::activeHiddenInput($model, $attribute, $hiddenOptions)
1395
            . static::activeInput('file', $model, $attribute, $options);
1396
    }
1397
1398
    /**
1399
     * Generates a textarea tag for the given model attribute.
1400
     * The model attribute value will be used as the content in the textarea.
1401
     * @param Model $model the model object
1402
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1403
     * about attribute expression.
1404
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
1405
     * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
1406
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1407
     * The following special options are recognized:
1408
     *
1409
     * - maxlength: integer|boolean, when `maxlength` is set true and the model attribute is validated
1410
     *   by a string validator, the `maxlength` option will take the value of [[\yii\validators\StringValidator::max]].
1411
     *   This option is available since version 2.0.6.
1412
     *
1413
     * @return string the generated textarea tag
1414
     */
1415
    public static function activeTextarea($model, $attribute, $options = [])
1416
    {
1417
        $name = isset($options['name']) ? $options['name'] : static::getInputName($model, $attribute);
1418
        if (isset($options['value'])) {
1419
            $value = $options['value'];
1420
            unset($options['value']);
1421
        } else {
1422
            $value = static::getAttributeValue($model, $attribute);
1423
        }
1424
        if (!array_key_exists('id', $options)) {
1425
            $options['id'] = static::getInputId($model, $attribute);
1426
        }
1427
        self::normalizeMaxLength($model, $attribute, $options);
1428
        return static::textarea($name, $value, $options);
1429
    }
1430
1431
    /**
1432
     * Generates a radio button tag together with a label for the given model attribute.
1433
     * This method will generate the "checked" tag attribute according to the model attribute value.
1434
     * @param Model $model the model object
1435
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1436
     * about attribute expression.
1437
     * @param array $options the tag options in terms of name-value pairs.
1438
     * See [[booleanInput()]] for details about accepted attributes.
1439
     *
1440
     * @return string the generated radio button tag
1441
     */
1442
    public static function activeRadio($model, $attribute, $options = [])
1443
    {
1444
        return static::activeBooleanInput('radio', $model, $attribute, $options);
1445
    }
1446
1447
    /**
1448
     * Generates a checkbox tag together with a label for the given model attribute.
1449
     * This method will generate the "checked" tag attribute according to the model attribute value.
1450
     * @param Model $model the model object
1451
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1452
     * about attribute expression.
1453
     * @param array $options the tag options in terms of name-value pairs.
1454
     * See [[booleanInput()]] for details about accepted attributes.
1455
     *
1456
     * @return string the generated checkbox tag
1457
     */
1458
    public static function activeCheckbox($model, $attribute, $options = [])
1459
    {
1460
        return static::activeBooleanInput('checkbox', $model, $attribute, $options);
1461
    }
1462
1463
    /**
1464
     * Generates a boolean input
1465
     * This method is mainly called by [[activeCheckbox()]] and [[activeRadio()]].
1466
     * @param string $type the input type. This can be either `radio` or `checkbox`.
1467
     * @param Model $model the model object
1468
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1469
     * about attribute expression.
1470
     * @param array $options the tag options in terms of name-value pairs.
1471
     * See [[booleanInput()]] for details about accepted attributes.
1472
     * @return string the generated input element
1473
     * @since 2.0.9
1474
     */
1475
    protected static function activeBooleanInput($type, $model, $attribute, $options = [])
1476
    {
1477
        $name = isset($options['name']) ? $options['name'] : static::getInputName($model, $attribute);
1478
        $value = static::getAttributeValue($model, $attribute);
1479
1480
        if (!array_key_exists('value', $options)) {
1481
            $options['value'] = '1';
1482
        }
1483
        if (!array_key_exists('uncheck', $options)) {
1484
            $options['uncheck'] = '0';
1485
        } elseif ($options['uncheck'] === false) {
1486
            unset($options['uncheck']);
1487
        }
1488
        if (!array_key_exists('label', $options)) {
1489
            $options['label'] = static::encode($model->getAttributeLabel(static::getAttributeName($attribute)));
1490
        } elseif ($options['label'] === false) {
1491
            unset($options['label']);
1492
        }
1493
1494
        $checked = "$value" === "{$options['value']}";
1495
1496
        if (!array_key_exists('id', $options)) {
1497
            $options['id'] = static::getInputId($model, $attribute);
1498
        }
1499
1500
        return static::$type($name, $checked, $options);
1501
    }
1502
1503
    /**
1504
     * Generates a drop-down list for the given model attribute.
1505
     * The selection of the drop-down list is taken from the value of the model attribute.
1506
     * @param Model $model the model object
1507
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1508
     * about attribute expression.
1509
     * @param array $items the option data items. The array keys are option values, and the array values
1510
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
1511
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
1512
     * If you have a list of data models, you may convert them into the format described above using
1513
     * [[\yii\helpers\ArrayHelper::map()]].
1514
     *
1515
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
1516
     * the labels will also be HTML-encoded.
1517
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
1518
     *
1519
     * - prompt: string, a prompt text to be displayed as the first option. Since version 2.0.11 you can use an array
1520
     *   to override the value and to set other tag attributes:
1521
     *
1522
     *   ```php
1523
     *   ['text' => 'Please select', 'options' => ['value' => 'none', 'class' => 'prompt', 'label' => 'Select']],
1524
     *   ```
1525
     *
1526
     * - options: array, the attributes for the select option tags. The array keys must be valid option values,
1527
     *   and the array values are the extra attributes for the corresponding option tags. For example,
1528
     *
1529
     *   ```php
1530
     *   [
1531
     *       'value1' => ['disabled' => true],
1532
     *       'value2' => ['label' => 'value 2'],
1533
     *   ];
1534
     *   ```
1535
     *
1536
     * - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
1537
     *   except that the array keys represent the optgroup labels specified in $items.
1538
     * - encodeSpaces: bool, whether to encode spaces in option prompt and option value with `&nbsp;` character.
1539
     *   Defaults to false.
1540
     * - encode: bool, whether to encode option prompt and option value characters.
1541
     *   Defaults to `true`. This option is available since 2.0.3.
1542
     *
1543
     * The rest of the options will be rendered as the attributes of the resulting tag. The values will
1544
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
1545
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1546
     *
1547
     * @return string the generated drop-down list tag
1548
     */
1549
    public static function activeDropDownList($model, $attribute, $items, $options = [])
1550
    {
1551
        if (empty($options['multiple'])) {
1552
            return static::activeListInput('dropDownList', $model, $attribute, $items, $options);
1553
        } else {
1554
            return static::activeListBox($model, $attribute, $items, $options);
1555
        }
1556
    }
1557
1558
    /**
1559
     * Generates a list box.
1560
     * The selection of the list box is taken from the value of the model attribute.
1561
     * @param Model $model the model object
1562
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1563
     * about attribute expression.
1564
     * @param array $items the option data items. The array keys are option values, and the array values
1565
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
1566
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
1567
     * If you have a list of data models, you may convert them into the format described above using
1568
     * [[\yii\helpers\ArrayHelper::map()]].
1569
     *
1570
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
1571
     * the labels will also be HTML-encoded.
1572
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
1573
     *
1574
     * - prompt: string, a prompt text to be displayed as the first option. Since version 2.0.11 you can use an array
1575
     *   to override the value and to set other tag attributes:
1576
     *
1577
     *   ```php
1578
     *   ['text' => 'Please select', 'options' => ['value' => 'none', 'class' => 'prompt', 'label' => 'Select']],
1579
     *   ```
1580
     *
1581
     * - options: array, the attributes for the select option tags. The array keys must be valid option values,
1582
     *   and the array values are the extra attributes for the corresponding option tags. For example,
1583
     *
1584
     *   ```php
1585
     *   [
1586
     *       'value1' => ['disabled' => true],
1587
     *       'value2' => ['label' => 'value 2'],
1588
     *   ];
1589
     *   ```
1590
     *
1591
     * - groups: array, the attributes for the optgroup tags. The structure of this is similar to that of 'options',
1592
     *   except that the array keys represent the optgroup labels specified in $items.
1593
     * - unselect: string, the value that will be submitted when no option is selected.
1594
     *   When this attribute is set, a hidden field will be generated so that if no option is selected in multiple
1595
     *   mode, we can still obtain the posted unselect value.
1596
     * - encodeSpaces: bool, whether to encode spaces in option prompt and option value with `&nbsp;` character.
1597
     *   Defaults to false.
1598
     * - encode: bool, whether to encode option prompt and option value characters.
1599
     *   Defaults to `true`. This option is available since 2.0.3.
1600
     *
1601
     * The rest of the options will be rendered as the attributes of the resulting tag. The values will
1602
     * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
1603
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1604
     *
1605
     * @return string the generated list box tag
1606
     */
1607
    public static function activeListBox($model, $attribute, $items, $options = [])
1608
    {
1609
        return static::activeListInput('listBox', $model, $attribute, $items, $options);
1610
    }
1611
1612
    /**
1613
     * Generates a list of checkboxes.
1614
     * A checkbox list allows multiple selection, like [[listBox()]].
1615
     * As a result, the corresponding submitted value is an array.
1616
     * The selection of the checkbox list is taken from the value of the model attribute.
1617
     * @param Model $model the model object
1618
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1619
     * about attribute expression.
1620
     * @param array $items the data item used to generate the checkboxes.
1621
     * The array keys are the checkbox values, and the array values are the corresponding labels.
1622
     * Note that the labels will NOT be HTML-encoded, while the values will.
1623
     * @param array $options options (name => config) for the checkbox list container tag.
1624
     * The following options are specially handled:
1625
     *
1626
     * - tag: string|false, the tag name of the container element. False to render checkbox without container.
1627
     *   See also [[tag()]].
1628
     * - unselect: string, the value that should be submitted when none of the checkboxes is selected.
1629
     *   You may set this option to be null to prevent default value submission.
1630
     *   If this option is not set, an empty string will be submitted.
1631
     * - encode: boolean, whether to HTML-encode the checkbox labels. Defaults to true.
1632
     *   This option is ignored if `item` option is set.
1633
     * - separator: string, the HTML code that separates items.
1634
     * - itemOptions: array, the options for generating the checkbox tag using [[checkbox()]].
1635
     * - item: callable, a callback that can be used to customize the generation of the HTML code
1636
     *   corresponding to a single item in $items. The signature of this callback must be:
1637
     *
1638
     *   ```php
1639
     *   function ($index, $label, $name, $checked, $value)
1640
     *   ```
1641
     *
1642
     *   where $index is the zero-based index of the checkbox in the whole list; $label
1643
     *   is the label for the checkbox; and $name, $value and $checked represent the name,
1644
     *   value and the checked status of the checkbox input.
1645
     *
1646
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1647
     *
1648
     * @return string the generated checkbox list
1649
     */
1650
    public static function activeCheckboxList($model, $attribute, $items, $options = [])
1651
    {
1652
        return static::activeListInput('checkboxList', $model, $attribute, $items, $options);
1653
    }
1654
1655
    /**
1656
     * Generates a list of radio buttons.
1657
     * A radio button list is like a checkbox list, except that it only allows single selection.
1658
     * The selection of the radio buttons is taken from the value of the model attribute.
1659
     * @param Model $model the model object
1660
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1661
     * about attribute expression.
1662
     * @param array $items the data item used to generate the radio buttons.
1663
     * The array keys are the radio values, and the array values are the corresponding labels.
1664
     * Note that the labels will NOT be HTML-encoded, while the values will.
1665
     * @param array $options options (name => config) for the radio button list container tag.
1666
     * The following options are specially handled:
1667
     *
1668
     * - tag: string|false, the tag name of the container element. False to render radio button without container.
1669
     *   See also [[tag()]].
1670
     * - unselect: string, the value that should be submitted when none of the radio buttons is selected.
1671
     *   You may set this option to be null to prevent default value submission.
1672
     *   If this option is not set, an empty string will be submitted.
1673
     * - encode: boolean, whether to HTML-encode the checkbox labels. Defaults to true.
1674
     *   This option is ignored if `item` option is set.
1675
     * - separator: string, the HTML code that separates items.
1676
     * - itemOptions: array, the options for generating the radio button tag using [[radio()]].
1677
     * - item: callable, a callback that can be used to customize the generation of the HTML code
1678
     *   corresponding to a single item in $items. The signature of this callback must be:
1679
     *
1680
     *   ```php
1681
     *   function ($index, $label, $name, $checked, $value)
1682
     *   ```
1683
     *
1684
     *   where $index is the zero-based index of the radio button in the whole list; $label
1685
     *   is the label for the radio button; and $name, $value and $checked represent the name,
1686
     *   value and the checked status of the radio button input.
1687
     *
1688
     * See [[renderTagAttributes()]] for details on how attributes are being rendered.
1689
     *
1690
     * @return string the generated radio button list
1691
     */
1692
    public static function activeRadioList($model, $attribute, $items, $options = [])
1693
    {
1694
        return static::activeListInput('radioList', $model, $attribute, $items, $options);
1695
    }
1696
1697
    /**
1698
     * Generates a list of input fields.
1699
     * This method is mainly called by [[activeListBox()]], [[activeRadioList()]] and [[activeCheckboxList()]].
1700
     * @param string $type the input type. This can be 'listBox', 'radioList', or 'checkBoxList'.
1701
     * @param Model $model the model object
1702
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for the format
1703
     * about attribute expression.
1704
     * @param array $items the data item used to generate the input fields.
1705
     * The array keys are the input values, and the array values are the corresponding labels.
1706
     * Note that the labels will NOT be HTML-encoded, while the values will.
1707
     * @param array $options options (name => config) for the input list. The supported special options
1708
     * depend on the input type specified by `$type`.
1709
     * @return string the generated input list
1710
     */
1711
    protected static function activeListInput($type, $model, $attribute, $items, $options = [])
1712
    {
1713
        $name = isset($options['name']) ? $options['name'] : static::getInputName($model, $attribute);
1714
        $selection = isset($options['value']) ? $options['value'] : static::getAttributeValue($model, $attribute);
1715
        if (!array_key_exists('unselect', $options)) {
1716
            $options['unselect'] = '';
1717
        }
1718
        if (!array_key_exists('id', $options)) {
1719
            $options['id'] = static::getInputId($model, $attribute);
1720
        }
1721
        return static::$type($name, $selection, $items, $options);
1722
    }
1723
1724
    /**
1725
     * Renders the option tags that can be used by [[dropDownList()]] and [[listBox()]].
1726
     * @param string|array|null $selection the selected value(s). String for single or array for multiple selection(s).
1727
     * @param array $items the option data items. The array keys are option values, and the array values
1728
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
1729
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
1730
     * If you have a list of data models, you may convert them into the format described above using
1731
     * [[\yii\helpers\ArrayHelper::map()]].
1732
     *
1733
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
1734
     * the labels will also be HTML-encoded.
1735
     * @param array $tagOptions the $options parameter that is passed to the [[dropDownList()]] or [[listBox()]] call.
1736
     * This method will take out these elements, if any: "prompt", "options" and "groups". See more details
1737
     * in [[dropDownList()]] for the explanation of these elements.
1738
     *
1739
     * @return string the generated list options
1740
     */
1741
    public static function renderSelectOptions($selection, $items, &$tagOptions = [])
1742
    {
1743
        $lines = [];
1744
        $encodeSpaces = ArrayHelper::remove($tagOptions, 'encodeSpaces', false);
1745
        $encode = ArrayHelper::remove($tagOptions, 'encode', true);
1746
        if (isset($tagOptions['prompt'])) {
1747
            $promptOptions = ['value' => ''];
1748
            if (is_string($tagOptions['prompt'])) {
1749
                $promptText = $tagOptions['prompt'];
1750
            } else {
1751
                $promptText = $tagOptions['prompt']['text'];
1752
                $promptOptions = array_merge($promptOptions, $tagOptions['prompt']['options']);
1753
            }
1754
            $promptText = $encode ? static::encode($promptText) : $promptText;
1755
            if ($encodeSpaces) {
1756
                $promptText = str_replace(' ', '&nbsp;', $promptText);
1757
            }
1758
            $lines[] = static::tag('option', $promptText, $promptOptions);
1759
        }
1760
1761
        $options = isset($tagOptions['options']) ? $tagOptions['options'] : [];
1762
        $groups = isset($tagOptions['groups']) ? $tagOptions['groups'] : [];
1763
        unset($tagOptions['prompt'], $tagOptions['options'], $tagOptions['groups']);
1764
        $options['encodeSpaces'] = ArrayHelper::getValue($options, 'encodeSpaces', $encodeSpaces);
1765
        $options['encode'] = ArrayHelper::getValue($options, 'encode', $encode);
1766
1767
        foreach ($items as $key => $value) {
1768
            if (is_array($value)) {
1769
                $groupAttrs = isset($groups[$key]) ? $groups[$key] : [];
1770
                if (!isset($groupAttrs['label'])) {
1771
                    $groupAttrs['label'] = $key;
1772
                }
1773
                $attrs = ['options' => $options, 'groups' => $groups, 'encodeSpaces' => $encodeSpaces, 'encode' => $encode];
1774
                $content = static::renderSelectOptions($selection, $value, $attrs);
1775
                $lines[] = static::tag('optgroup', "\n" . $content . "\n", $groupAttrs);
1776
            } else {
1777
                $attrs = isset($options[$key]) ? $options[$key] : [];
1778
                $attrs['value'] = (string) $key;
1779
                if (!array_key_exists('selected', $attrs)) {
1780
                    $attrs['selected'] = $selection !== null &&
1781
                        (!ArrayHelper::isTraversable($selection) && !strcmp($key, $selection)
1782
                        || ArrayHelper::isTraversable($selection) && ArrayHelper::isIn($key, $selection));
0 ignored issues
show
Bug introduced by
It seems like $selection defined by parameter $selection on line 1741 can also be of type string; however, yii\helpers\BaseArrayHelper::isIn() does only seem to accept array|object<Traversable>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
1783
                }
1784
                $text = $encode ? static::encode($value) : $value;
1785
                if ($encodeSpaces) {
1786
                    $text = str_replace(' ', '&nbsp;', $text);
1787
                }
1788
                $lines[] = static::tag('option', $text, $attrs);
1789
            }
1790
        }
1791
1792
        return implode("\n", $lines);
1793
    }
1794
1795
    /**
1796
     * Renders the HTML tag attributes.
1797
     *
1798
     * Attributes whose values are of boolean type will be treated as
1799
     * [boolean attributes](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes).
1800
     *
1801
     * Attributes whose values are null will not be rendered.
1802
     *
1803
     * The values of attributes will be HTML-encoded using [[encode()]].
1804
     *
1805
     * The "data" attribute is specially handled when it is receiving an array value. In this case,
1806
     * the array will be "expanded" and a list data attributes will be rendered. For example,
1807
     * if `'data' => ['id' => 1, 'name' => 'yii']`, then this will be rendered:
1808
     * `data-id="1" data-name="yii"`.
1809
     * Additionally `'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` will be rendered as:
1810
     * `data-params='{"id":1,"name":"yii"}' data-status="ok"`.
1811
     *
1812
     * @param array $attributes attributes to be rendered. The attribute values will be HTML-encoded using [[encode()]].
1813
     * @return string the rendering result. If the attributes are not empty, they will be rendered
1814
     * into a string with a leading white space (so that it can be directly appended to the tag name
1815
     * in a tag. If there is no attribute, an empty string will be returned.
1816
     */
1817
    public static function renderTagAttributes($attributes)
1818
    {
1819
        if (count($attributes) > 1) {
1820
            $sorted = [];
1821
            foreach (static::$attributeOrder as $name) {
1822
                if (isset($attributes[$name])) {
1823
                    $sorted[$name] = $attributes[$name];
1824
                }
1825
            }
1826
            $attributes = array_merge($sorted, $attributes);
1827
        }
1828
1829
        $html = '';
1830
        foreach ($attributes as $name => $value) {
1831
            if (is_bool($value)) {
1832
                if ($value) {
1833
                    $html .= " $name";
1834
                }
1835
            } elseif (is_array($value)) {
1836
                if (in_array($name, static::$dataAttributes)) {
1837
                    foreach ($value as $n => $v) {
1838
                        if (is_array($v)) {
1839
                            $html .= " $name-$n='" . Json::htmlEncode($v) . "'";
1840
                        } else {
1841
                            $html .= " $name-$n=\"" . static::encode($v) . '"';
1842
                        }
1843
                    }
1844
                } elseif ($name === 'class') {
1845
                    if (empty($value)) {
1846
                        continue;
1847
                    }
1848
                    $html .= " $name=\"" . static::encode(implode(' ', $value)) . '"';
1849
                } elseif ($name === 'style') {
1850
                    if (empty($value)) {
1851
                        continue;
1852
                    }
1853
                    $html .= " $name=\"" . static::encode(static::cssStyleFromArray($value)) . '"';
1854
                } else {
1855
                    $html .= " $name='" . Json::htmlEncode($value) . "'";
1856
                }
1857
            } elseif ($value !== null) {
1858
                $html .= " $name=\"" . static::encode($value) . '"';
1859
            }
1860
        }
1861
1862
        return $html;
1863
    }
1864
1865
    /**
1866
     * Adds a CSS class (or several classes) to the specified options.
1867
     * If the CSS class is already in the options, it will not be added again.
1868
     * If class specification at given options is an array, and some class placed there with the named (string) key,
1869
     * overriding of such key will have no effect. For example:
1870
     *
1871
     * ```php
1872
     * $options = ['class' => ['persistent' => 'initial']];
1873
     * Html::addCssClass($options, ['persistent' => 'override']);
1874
     * var_dump($options['class']); // outputs: array('persistent' => 'initial');
1875
     * ```
1876
     *
1877
     * @param array $options the options to be modified.
1878
     * @param string|array $class the CSS class(es) to be added
1879
     */
1880
    public static function addCssClass(&$options, $class)
1881
    {
1882
        if (isset($options['class'])) {
1883
            if (is_array($options['class'])) {
1884
                $options['class'] = self::mergeCssClasses($options['class'], (array) $class);
1885
            } else {
1886
                $classes = preg_split('/\s+/', $options['class'], -1, PREG_SPLIT_NO_EMPTY);
1887
                $options['class'] = implode(' ', self::mergeCssClasses($classes, (array) $class));
1888
            }
1889
        } else {
1890
            $options['class'] = $class;
1891
        }
1892
    }
1893
1894
    /**
1895
     * Merges already existing CSS classes with new one.
1896
     * This method provides the priority for named existing classes over additional.
1897
     * @param array $existingClasses already existing CSS classes.
1898
     * @param array $additionalClasses CSS classes to be added.
1899
     * @return array merge result.
1900
     */
1901
    private static function mergeCssClasses(array $existingClasses, array $additionalClasses)
1902
    {
1903
        foreach ($additionalClasses as $key => $class) {
1904
            if (is_int($key) && !in_array($class, $existingClasses)) {
1905
                $existingClasses[] = $class;
1906
            } elseif (!isset($existingClasses[$key])) {
1907
                $existingClasses[$key] = $class;
1908
            }
1909
        }
1910
        return array_unique($existingClasses);
1911
    }
1912
1913
    /**
1914
     * Removes a CSS class from the specified options.
1915
     * @param array $options the options to be modified.
1916
     * @param string|array $class the CSS class(es) to be removed
1917
     */
1918
    public static function removeCssClass(&$options, $class)
1919
    {
1920
        if (isset($options['class'])) {
1921
            if (is_array($options['class'])) {
1922
                $classes = array_diff($options['class'], (array) $class);
1923
                if (empty($classes)) {
1924
                    unset($options['class']);
1925
                } else {
1926
                    $options['class'] = $classes;
1927
                }
1928
            } else {
1929
                $classes = preg_split('/\s+/', $options['class'], -1, PREG_SPLIT_NO_EMPTY);
1930
                $classes = array_diff($classes, (array) $class);
1931
                if (empty($classes)) {
1932
                    unset($options['class']);
1933
                } else {
1934
                    $options['class'] = implode(' ', $classes);
1935
                }
1936
            }
1937
        }
1938
    }
1939
1940
    /**
1941
     * Adds the specified CSS style to the HTML options.
1942
     *
1943
     * If the options already contain a `style` element, the new style will be merged
1944
     * with the existing one. If a CSS property exists in both the new and the old styles,
1945
     * the old one may be overwritten if `$overwrite` is true.
1946
     *
1947
     * For example,
1948
     *
1949
     * ```php
1950
     * Html::addCssStyle($options, 'width: 100px; height: 200px');
1951
     * ```
1952
     *
1953
     * @param array $options the HTML options to be modified.
1954
     * @param string|array $style the new style string (e.g. `'width: 100px; height: 200px'`) or
1955
     * array (e.g. `['width' => '100px', 'height' => '200px']`).
1956
     * @param bool $overwrite whether to overwrite existing CSS properties if the new style
1957
     * contain them too.
1958
     * @see removeCssStyle()
1959
     * @see cssStyleFromArray()
1960
     * @see cssStyleToArray()
1961
     */
1962
    public static function addCssStyle(&$options, $style, $overwrite = true)
1963
    {
1964
        if (!empty($options['style'])) {
1965
            $oldStyle = is_array($options['style']) ? $options['style'] : static::cssStyleToArray($options['style']);
1966
            $newStyle = is_array($style) ? $style : static::cssStyleToArray($style);
1967
            if (!$overwrite) {
1968
                foreach ($newStyle as $property => $value) {
1969
                    if (isset($oldStyle[$property])) {
1970
                        unset($newStyle[$property]);
1971
                    }
1972
                }
1973
            }
1974
            $style = array_merge($oldStyle, $newStyle);
1975
        }
1976
        $options['style'] = is_array($style) ? static::cssStyleFromArray($style) : $style;
1977
    }
1978
1979
    /**
1980
     * Removes the specified CSS style from the HTML options.
1981
     *
1982
     * For example,
1983
     *
1984
     * ```php
1985
     * Html::removeCssStyle($options, ['width', 'height']);
1986
     * ```
1987
     *
1988
     * @param array $options the HTML options to be modified.
1989
     * @param string|array $properties the CSS properties to be removed. You may use a string
1990
     * if you are removing a single property.
1991
     * @see addCssStyle()
1992
     */
1993
    public static function removeCssStyle(&$options, $properties)
1994
    {
1995
        if (!empty($options['style'])) {
1996
            $style = is_array($options['style']) ? $options['style'] : static::cssStyleToArray($options['style']);
1997
            foreach ((array) $properties as $property) {
1998
                unset($style[$property]);
1999
            }
2000
            $options['style'] = static::cssStyleFromArray($style);
2001
        }
2002
    }
2003
2004
    /**
2005
     * Converts a CSS style array into a string representation.
2006
     *
2007
     * For example,
2008
     *
2009
     * ```php
2010
     * print_r(Html::cssStyleFromArray(['width' => '100px', 'height' => '200px']));
2011
     * // will display: 'width: 100px; height: 200px;'
2012
     * ```
2013
     *
2014
     * @param array $style the CSS style array. The array keys are the CSS property names,
2015
     * and the array values are the corresponding CSS property values.
2016
     * @return string the CSS style string. If the CSS style is empty, a null will be returned.
2017
     */
2018
    public static function cssStyleFromArray(array $style)
2019
    {
2020
        $result = '';
2021
        foreach ($style as $name => $value) {
2022
            $result .= "$name: $value; ";
2023
        }
2024
        // return null if empty to avoid rendering the "style" attribute
2025
        return $result === '' ? null : rtrim($result);
2026
    }
2027
2028
    /**
2029
     * Converts a CSS style string into an array representation.
2030
     *
2031
     * The array keys are the CSS property names, and the array values
2032
     * are the corresponding CSS property values.
2033
     *
2034
     * For example,
2035
     *
2036
     * ```php
2037
     * print_r(Html::cssStyleToArray('width: 100px; height: 200px;'));
2038
     * // will display: ['width' => '100px', 'height' => '200px']
2039
     * ```
2040
     *
2041
     * @param string $style the CSS style string
2042
     * @return array the array representation of the CSS style
2043
     */
2044
    public static function cssStyleToArray($style)
2045
    {
2046
        $result = [];
2047
        foreach (explode(';', $style) as $property) {
2048
            $property = explode(':', $property);
2049
            if (count($property) > 1) {
2050
                $result[trim($property[0])] = trim($property[1]);
2051
            }
2052
        }
2053
        return $result;
2054
    }
2055
2056
    /**
2057
     * Returns the real attribute name from the given attribute expression.
2058
     *
2059
     * An attribute expression is an attribute name prefixed and/or suffixed with array indexes.
2060
     * It is mainly used in tabular data input and/or input of array type. Below are some examples:
2061
     *
2062
     * - `[0]content` is used in tabular data input to represent the "content" attribute
2063
     *   for the first model in tabular input;
2064
     * - `dates[0]` represents the first array element of the "dates" attribute;
2065
     * - `[0]dates[0]` represents the first array element of the "dates" attribute
2066
     *   for the first model in tabular input.
2067
     *
2068
     * If `$attribute` has neither prefix nor suffix, it will be returned back without change.
2069
     * @param string $attribute the attribute name or expression
2070
     * @return string the attribute name without prefix and suffix.
2071
     * @throws InvalidParamException if the attribute name contains non-word characters.
2072
     */
2073
    public static function getAttributeName($attribute)
2074
    {
2075
        if (preg_match('/(^|.*\])([\w\.]+)(\[.*|$)/', $attribute, $matches)) {
2076
            return $matches[2];
2077
        } else {
2078
            throw new InvalidParamException('Attribute name must contain word characters only.');
2079
        }
2080
    }
2081
2082
    /**
2083
     * Returns the value of the specified attribute name or expression.
2084
     *
2085
     * For an attribute expression like `[0]dates[0]`, this method will return the value of `$model->dates[0]`.
2086
     * See [[getAttributeName()]] for more details about attribute expression.
2087
     *
2088
     * If an attribute value is an instance of [[ActiveRecordInterface]] or an array of such instances,
2089
     * the primary value(s) of the AR instance(s) will be returned instead.
2090
     *
2091
     * @param Model $model the model object
2092
     * @param string $attribute the attribute name or expression
2093
     * @return string|array the corresponding attribute value
2094
     * @throws InvalidParamException if the attribute name contains non-word characters.
2095
     */
2096
    public static function getAttributeValue($model, $attribute)
2097
    {
2098
        if (!preg_match('/(^|.*\])([\w\.]+)(\[.*|$)/', $attribute, $matches)) {
2099
            throw new InvalidParamException('Attribute name must contain word characters only.');
2100
        }
2101
        $attribute = $matches[2];
2102
        $value = $model->$attribute;
2103
        if ($matches[3] !== '') {
2104
            foreach (explode('][', trim($matches[3], '[]')) as $id) {
2105
                if ((is_array($value) || $value instanceof \ArrayAccess) && isset($value[$id])) {
2106
                    $value = $value[$id];
2107
                } else {
2108
                    return null;
2109
                }
2110
            }
2111
        }
2112
2113
        // https://github.com/yiisoft/yii2/issues/1457
2114
        if (is_array($value)) {
2115
            foreach ($value as $i => $v) {
2116
                if ($v instanceof ActiveRecordInterface) {
2117
                    $v = $v->getPrimaryKey(false);
2118
                    $value[$i] = is_array($v) ? json_encode($v) : $v;
2119
                }
2120
            }
2121
        } elseif ($value instanceof ActiveRecordInterface) {
2122
            $value = $value->getPrimaryKey(false);
2123
2124
            return is_array($value) ? json_encode($value) : $value;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return is_array($value) ...ncode($value) : $value; (object|integer|double|string|null|boolean) is incompatible with the return type documented by yii\helpers\BaseHtml::getAttributeValue of type string|array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
2125
        }
2126
2127
        return $value;
2128
    }
2129
2130
    /**
2131
     * Generates an appropriate input name for the specified attribute name or expression.
2132
     *
2133
     * This method generates a name that can be used as the input name to collect user input
2134
     * for the specified attribute. The name is generated according to the [[Model::formName|form name]]
2135
     * of the model and the given attribute name. For example, if the form name of the `Post` model
2136
     * is `Post`, then the input name generated for the `content` attribute would be `Post[content]`.
2137
     *
2138
     * See [[getAttributeName()]] for explanation of attribute expression.
2139
     *
2140
     * @param Model $model the model object
2141
     * @param string $attribute the attribute name or expression
2142
     * @return string the generated input name
2143
     * @throws InvalidParamException if the attribute name contains non-word characters.
2144
     */
2145
    public static function getInputName($model, $attribute)
2146
    {
2147
        $formName = $model->formName();
2148
        if (!preg_match('/(^|.*\])([\w\.]+)(\[.*|$)/', $attribute, $matches)) {
2149
            throw new InvalidParamException('Attribute name must contain word characters only.');
2150
        }
2151
        $prefix = $matches[1];
2152
        $attribute = $matches[2];
2153
        $suffix = $matches[3];
2154
        if ($formName === '' && $prefix === '') {
2155
            return $attribute . $suffix;
2156
        } elseif ($formName !== '') {
2157
            return $formName . $prefix . "[$attribute]" . $suffix;
2158
        } else {
2159
            throw new InvalidParamException(get_class($model) . '::formName() cannot be empty for tabular inputs.');
2160
        }
2161
    }
2162
2163
    /**
2164
     * Generates an appropriate input ID for the specified attribute name or expression.
2165
     *
2166
     * This method converts the result [[getInputName()]] into a valid input ID.
2167
     * For example, if [[getInputName()]] returns `Post[content]`, this method will return `post-content`.
2168
     * @param Model $model the model object
2169
     * @param string $attribute the attribute name or expression. See [[getAttributeName()]] for explanation of attribute expression.
2170
     * @return string the generated input ID
2171
     * @throws InvalidParamException if the attribute name contains non-word characters.
2172
     */
2173
    public static function getInputId($model, $attribute)
2174
    {
2175
        $name = strtolower(static::getInputName($model, $attribute));
2176
        return str_replace(['[]', '][', '[', ']', ' ', '.'], ['', '-', '-', '', '-', '-'], $name);
2177
    }
2178
2179
    /**
2180
     * Escapes regular expression to use in JavaScript
2181
     * @param string $regexp the regular expression to be escaped.
2182
     * @return string the escaped result.
2183
     * @since 2.0.6
2184
     */
2185
    public static function escapeJsRegularExpression($regexp)
2186
    {
2187
        $pattern = preg_replace('/\\\\x\{?([0-9a-fA-F]+)\}?/', '\u$1', $regexp);
2188
        $deliminator = substr($pattern, 0, 1);
2189
        $pos = strrpos($pattern, $deliminator, 1);
2190
        $flag = substr($pattern, $pos + 1);
2191
        if ($deliminator !== '/') {
2192
            $pattern = '/' . str_replace('/', '\\/', substr($pattern, 1, $pos - 1)) . '/';
2193
        } else {
2194
            $pattern = substr($pattern, 0, $pos + 1);
2195
        }
2196
        if (!empty($flag)) {
2197
            $pattern .= preg_replace('/[^igm]/', '', $flag);
2198
        }
2199
2200
        return $pattern;
2201
    }
2202
}
2203