GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 6886d6...1496c8 )
by Robert
15:10
created

ActiveField::checkboxList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 5
cp 0
cc 1
eloc 5
nc 1
nop 2
crap 2
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\widgets;
9
10
use Yii;
11
use yii\base\Component;
12
use yii\base\ErrorHandler;
13
use yii\helpers\ArrayHelper;
14
use yii\helpers\Html;
15
use yii\base\Model;
16
use yii\web\JsExpression;
17
18
/**
19
 * ActiveField represents a form input field within an [[ActiveForm]].
20
 *
21
 * @author Qiang Xue <[email protected]>
22
 * @since 2.0
23
 */
24
class ActiveField extends Component
25
{
26
    /**
27
     * @var ActiveForm the form that this field is associated with.
28
     */
29
    public $form;
30
    /**
31
     * @var Model the data model that this field is associated with.
32
     */
33
    public $model;
34
    /**
35
     * @var string the model attribute that this field is associated with.
36
     */
37
    public $attribute;
38
    /**
39
     * @var array the HTML attributes (name-value pairs) for the field container tag.
40
     * The values will be HTML-encoded using [[Html::encode()]].
41
     * If a value is `null`, the corresponding attribute will not be rendered.
42
     * The following special options are recognized:
43
     *
44
     * - `tag`: the tag name of the container element. Defaults to `div`. Setting it to `false` will not render a container tag.
45
     *   See also [[\yii\helpers\Html::tag()]].
46
     *
47
     * If you set a custom `id` for the container element, you may need to adjust the [[$selectors]] accordingly.
48
     *
49
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
50
     */
51
    public $options = ['class' => 'form-group'];
52
    /**
53
     * @var string the template that is used to arrange the label, the input field, the error message and the hint text.
54
     * The following tokens will be replaced when [[render()]] is called: `{label}`, `{input}`, `{error}` and `{hint}`.
55
     */
56
    public $template = "{label}\n{input}\n{hint}\n{error}";
57
    /**
58
     * @var array the default options for the input tags. The parameter passed to individual input methods
59
     * (e.g. [[textInput()]]) will be merged with this property when rendering the input tag.
60
     *
61
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
62
     *
63
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
64
     */
65
    public $inputOptions = ['class' => 'form-control'];
66
    /**
67
     * @var array the default options for the error tags. The parameter passed to [[error()]] will be
68
     * merged with this property when rendering the error tag.
69
     * The following special options are recognized:
70
     *
71
     * - `tag`: the tag name of the container element. Defaults to `div`. Setting it to `false` will not render a container tag.
72
     *   See also [[\yii\helpers\Html::tag()]].
73
     * - `encode`: whether to encode the error output. Defaults to `true`.
74
     *
75
     * If you set a custom `id` for the error element, you may need to adjust the [[$selectors]] accordingly.
76
     *
77
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
78
     */
79
    public $errorOptions = ['class' => 'help-block'];
80
    /**
81
     * @var array the default options for the label tags. The parameter passed to [[label()]] will be
82
     * merged with this property when rendering the label tag.
83
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
84
     */
85
    public $labelOptions = ['class' => 'control-label'];
86
    /**
87
     * @var array the default options for the hint tags. The parameter passed to [[hint()]] will be
88
     * merged with this property when rendering the hint tag.
89
     * The following special options are recognized:
90
     *
91
     * - `tag`: the tag name of the container element. Defaults to `div`. Setting it to `false` will not render a container tag.
92
     *   See also [[\yii\helpers\Html::tag()]].
93
     *
94
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
95
     */
96
    public $hintOptions = ['class' => 'hint-block'];
97
    /**
98
     * @var boolean whether to enable client-side data validation.
99
     * If not set, it will take the value of [[ActiveForm::enableClientValidation]].
100
     */
101
    public $enableClientValidation;
102
    /**
103
     * @var boolean whether to enable AJAX-based data validation.
104
     * If not set, it will take the value of [[ActiveForm::enableAjaxValidation]].
105
     */
106
    public $enableAjaxValidation;
107
    /**
108
     * @var boolean whether to perform validation when the value of the input field is changed.
109
     * If not set, it will take the value of [[ActiveForm::validateOnChange]].
110
     */
111
    public $validateOnChange;
112
    /**
113
     * @var boolean whether to perform validation when the input field loses focus.
114
     * If not set, it will take the value of [[ActiveForm::validateOnBlur]].
115
     */
116
    public $validateOnBlur;
117
    /**
118
     * @var boolean whether to perform validation while the user is typing in the input field.
119
     * If not set, it will take the value of [[ActiveForm::validateOnType]].
120
     * @see validationDelay
121
     */
122
    public $validateOnType;
123
    /**
124
     * @var integer number of milliseconds that the validation should be delayed when the user types in the field
125
     * and [[validateOnType]] is set `true`.
126
     * If not set, it will take the value of [[ActiveForm::validationDelay]].
127
     */
128
    public $validationDelay;
129
    /**
130
     * @var array the jQuery selectors for selecting the container, input and error tags.
131
     * The array keys should be `container`, `input`, and/or `error`, and the array values
132
     * are the corresponding selectors. For example, `['input' => '#my-input']`.
133
     *
134
     * The container selector is used under the context of the form, while the input and the error
135
     * selectors are used under the context of the container.
136
     *
137
     * You normally do not need to set this property as the default selectors should work well for most cases.
138
     */
139
    public $selectors = [];
140
    /**
141
     * @var array different parts of the field (e.g. input, label). This will be used together with
142
     * [[template]] to generate the final field HTML code. The keys are the token names in [[template]],
143
     * while the values are the corresponding HTML code. Valid tokens include `{input}`, `{label}` and `{error}`.
144
     * Note that you normally don't need to access this property directly as
145
     * it is maintained by various methods of this class.
146
     */
147
    public $parts = [];
148
149
    /**
150
     * @var string this property holds a custom input id if it was set using [[inputOptions]] or in one of the
151
     * `$options` parameters of the `input*` methods.
152
     */
153
    private $_inputId;
154
155
    /**
156
     * @var bool if "for" field label attribute should be skipped.
157
     */
158
    private $_skipLabelFor = false;
159
160
161
    /**
162
     * PHP magic method that returns the string representation of this object.
163
     * @return string the string representation of this object.
164
     */
165 4
    public function __toString()
166
    {
167
        // __toString cannot throw exception
168
        // use trigger_error to bypass this limitation
169
        try {
170 4
            return $this->render();
171
        } catch (\Exception $e) {
172
            ErrorHandler::convertExceptionToError($e);
173
            return '';
174
        }
175
    }
176
177
    /**
178
     * Renders the whole field.
179
     * This method will generate the label, error tag, input tag and hint tag (if any), and
180
     * assemble them into HTML according to [[template]].
181
     * @param string|callable $content the content within the field container.
182
     * If `null` (not set), the default methods will be called to generate the label, error tag and input tag,
183
     * and use them as the content.
184
     * If a callable, it will be called to generate the content. The signature of the callable should be:
185
     *
186
     * ```php
187
     * function ($field) {
188
     *     return $html;
189
     * }
190
     * ```
191
     *
192
     * @return string the rendering result.
193
     */
194 6
    public function render($content = null)
195
    {
196 6
        if ($content === null) {
197 6
            if (!isset($this->parts['{input}'])) {
198 4
                $this->textInput();
199 4
            }
200 6
            if (!isset($this->parts['{label}'])) {
201 6
                $this->label();
202 6
            }
203 6
            if (!isset($this->parts['{error}'])) {
204 6
                $this->error();
205 6
            }
206 6
            if (!isset($this->parts['{hint}'])) {
207 6
                $this->hint(null);
208 6
            }
209 6
            $content = strtr($this->template, $this->parts);
210 6
        } elseif (!is_string($content)) {
211 1
            $content = call_user_func($content, $this);
212 1
        }
213
214 6
        return $this->begin() . "\n" . $content . "\n" . $this->end();
215
    }
216
217
    /**
218
     * Renders the opening tag of the field container.
219
     * @return string the rendering result.
220
     */
221 10
    public function begin()
222
    {
223 10
        if ($this->form->enableClientScript) {
224
            $clientOptions = $this->getClientOptions();
225
            if (!empty($clientOptions)) {
226
                $this->form->attributes[] = $clientOptions;
227
            }
228
        }
229
230 10
        $inputID = $this->getInputId();
231 10
        $attribute = Html::getAttributeName($this->attribute);
232 10
        $options = $this->options;
233 10
        $class = isset($options['class']) ? [$options['class']] : [];
234 10
        $class[] = "field-$inputID";
235 10
        if ($this->model->isAttributeRequired($attribute)) {
236 2
            $class[] = $this->form->requiredCssClass;
237 2
        }
238 10
        if ($this->model->hasErrors($attribute)) {
239 2
            $class[] = $this->form->errorCssClass;
240 2
        }
241 10
        $options['class'] = implode(' ', $class);
242 10
        $tag = ArrayHelper::remove($options, 'tag', 'div');
243
244 10
        return Html::beginTag($tag, $options);
245
    }
246
247
    /**
248
     * Renders the closing tag of the field container.
249
     * @return string the rendering result.
250
     */
251 7
    public function end()
252
    {
253 7
        return Html::endTag(ArrayHelper::keyExists('tag', $this->options) ? $this->options['tag'] : 'div');
254
    }
255
256
    /**
257
     * Generates a label tag for [[attribute]].
258
     * @param null|string|false $label the label to use. If `null`, the label will be generated via [[Model::getAttributeLabel()]].
259
     * If `false`, the generated field will not contain the label part.
260
     * Note that this will NOT be [[Html::encode()|encoded]].
261
     * @param null|array $options the tag options in terms of name-value pairs. It will be merged with [[labelOptions]].
262
     * The options will be rendered as the attributes of the resulting tag. The values will be HTML-encoded
263
     * using [[Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
264
     * @return $this the field object itself.
265
     */
266 8
    public function label($label = null, $options = [])
267
    {
268 8
        if ($label === false) {
269 2
            $this->parts['{label}'] = '';
270 2
            return $this;
271
        }
272
273 8
        $options = array_merge($this->labelOptions, $options);
274 8
        if ($label !== null) {
275 2
            $options['label'] = $label;
276 2
        }
277
278 8
        if ($this->_skipLabelFor) {
279
            $options['for'] = null;
280
        }
281
282 8
        $this->parts['{label}'] = Html::activeLabel($this->model, $this->attribute, $options);
283
284 8
        return $this;
285
    }
286
287
    /**
288
     * Generates a tag that contains the first validation error of [[attribute]].
289
     * Note that even if there is no validation error, this method will still return an empty error tag.
290
     * @param array|false $options the tag options in terms of name-value pairs. It will be merged with [[errorOptions]].
291
     * The options will be rendered as the attributes of the resulting tag. The values will be HTML-encoded
292
     * using [[Html::encode()]]. If this parameter is `false`, no error tag will be rendered.
293
     *
294
     * The following options are specially handled:
295
     *
296
     * - `tag`: this specifies the tag name. If not set, `div` will be used.
297
     *   See also [[\yii\helpers\Html::tag()]].
298
     *
299
     * If you set a custom `id` for the error element, you may need to adjust the [[$selectors]] accordingly.
300
     * @see $errorOptions
301
     * @return $this the field object itself.
302
     */
303 6
    public function error($options = [])
304
    {
305 6
        if ($options === false) {
306
            $this->parts['{error}'] = '';
307
            return $this;
308
        }
309 6
        $options = array_merge($this->errorOptions, $options);
310 6
        $this->parts['{error}'] = Html::error($this->model, $this->attribute, $options);
311
312 6
        return $this;
313
    }
314
315
    /**
316
     * Renders the hint tag.
317
     * @param string|bool $content the hint content.
318
     * If `null`, the hint will be generated via [[Model::getAttributeHint()]].
319
     * If `false`, the generated field will not contain the hint part.
320
     * Note that this will NOT be [[Html::encode()|encoded]].
321
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
322
     * the attributes of the hint tag. The values will be HTML-encoded using [[Html::encode()]].
323
     *
324
     * The following options are specially handled:
325
     *
326
     * - `tag`: this specifies the tag name. If not set, `div` will be used.
327
     *   See also [[\yii\helpers\Html::tag()]].
328
     *
329
     * @return $this the field object itself.
330
     */
331 9
    public function hint($content, $options = [])
332
    {
333 9
        if ($content === false) {
334 1
            $this->parts['{hint}'] = '';
335 1
            return $this;
336
        }
337
338 8
        $options = array_merge($this->hintOptions, $options);
339 8
        if ($content !== null) {
340 1
            $options['hint'] = $content;
341 1
        }
342 8
        $this->parts['{hint}'] = Html::activeHint($this->model, $this->attribute, $options);
343
344 8
        return $this;
345
    }
346
347
    /**
348
     * Renders an input tag.
349
     * @param string $type the input type (e.g. `text`, `password`)
350
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
351
     * the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
352
     *
353
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
354
     *
355
     * @return $this the field object itself.
356
     */
357 2
    public function input($type, $options = [])
358
    {
359 2
        $options = array_merge($this->inputOptions, $options);
360 2
        $this->adjustLabelFor($options);
361 2
        $this->parts['{input}'] = Html::activeInput($type, $this->model, $this->attribute, $options);
362
363 2
        return $this;
364
    }
365
366
    /**
367
     * Renders a text input.
368
     * This method will generate the `name` and `value` tag attributes automatically for the model attribute
369
     * unless they are explicitly specified in `$options`.
370
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
371
     * the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
372
     *
373
     * The following special options are recognized:
374
     *
375
     * - `maxlength`: integer|boolean, when `maxlength` is set `true` and the model attribute is validated
376
     *   by a string validator, the `maxlength` option will take the value of [[\yii\validators\StringValidator::max]].
377
     *   This is available since version 2.0.3.
378
     *
379
     * Note that if you set a custom `id` for the input element, you may need to adjust the value of [[selectors]] accordingly.
380
     *
381
     * @return $this the field object itself.
382
     */
383 6
    public function textInput($options = [])
384
    {
385 6
        $options = array_merge($this->inputOptions, $options);
386 6
        $this->adjustLabelFor($options);
387 6
        $this->parts['{input}'] = Html::activeTextInput($this->model, $this->attribute, $options);
388
389 6
        return $this;
390
    }
391
392
    /**
393
     * Renders a hidden input.
394
     *
395
     * Note that this method is provided for completeness. In most cases because you do not need
396
     * to validate a hidden input, you should not need to use this method. Instead, you should
397
     * use [[\yii\helpers\Html::activeHiddenInput()]].
398
     *
399
     * This method will generate the `name` and `value` tag attributes automatically for the model attribute
400
     * unless they are explicitly specified in `$options`.
401
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
402
     * the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
403
     *
404
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
405
     *
406
     * @return $this the field object itself.
407
     */
408 1
    public function hiddenInput($options = [])
409
    {
410 1
        $options = array_merge($this->inputOptions, $options);
411 1
        $this->adjustLabelFor($options);
412 1
        $this->parts['{input}'] = Html::activeHiddenInput($this->model, $this->attribute, $options);
413
414 1
        return $this;
415
    }
416
417
    /**
418
     * Renders a password input.
419
     * This method will generate the `name` and `value` tag attributes automatically for the model attribute
420
     * unless they are explicitly specified in `$options`.
421
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
422
     * the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
423
     *
424
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
425
     *
426
     * @return $this the field object itself.
427
     */
428
    public function passwordInput($options = [])
429
    {
430
        $options = array_merge($this->inputOptions, $options);
431
        $this->adjustLabelFor($options);
432
        $this->parts['{input}'] = Html::activePasswordInput($this->model, $this->attribute, $options);
433
434
        return $this;
435
    }
436
437
    /**
438
     * Renders a file input.
439
     * This method will generate the `name` and `value` tag attributes automatically for the model attribute
440
     * unless they are explicitly specified in `$options`.
441
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
442
     * the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
443
     *
444
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
445
     *
446
     * @return $this the field object itself.
447
     */
448 1
    public function fileInput($options = [])
449
    {
450
        // https://github.com/yiisoft/yii2/pull/795
451 1
        if ($this->inputOptions !== ['class' => 'form-control']) {
452
            $options = array_merge($this->inputOptions, $options);
453
        }
454
        // https://github.com/yiisoft/yii2/issues/8779
455 1
        if (!isset($this->form->options['enctype'])) {
456 1
            $this->form->options['enctype'] = 'multipart/form-data';
457 1
        }
458 1
        $this->adjustLabelFor($options);
459 1
        $this->parts['{input}'] = Html::activeFileInput($this->model, $this->attribute, $options);
460
461 1
        return $this;
462
    }
463
464
    /**
465
     * Renders a text area.
466
     * The model attribute value will be used as the content in the textarea.
467
     * @param array $options the tag options in terms of name-value pairs. These will be rendered as
468
     * the attributes of the resulting tag. The values will be HTML-encoded using [[Html::encode()]].
469
     *
470
     * If you set a custom `id` for the textarea element, you may need to adjust the [[$selectors]] accordingly.
471
     *
472
     * @return $this the field object itself.
473
     */
474
    public function textarea($options = [])
475
    {
476
        $options = array_merge($this->inputOptions, $options);
477
        $this->adjustLabelFor($options);
478
        $this->parts['{input}'] = Html::activeTextarea($this->model, $this->attribute, $options);
479
480
        return $this;
481
    }
482
483
    /**
484
     * Renders a radio button.
485
     * This method will generate the `checked` tag attribute according to the model attribute value.
486
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
487
     *
488
     * - `uncheck`: string, the value associated with the uncheck state of the radio button. If not set,
489
     *   it will take the default value `0`. This method will render a hidden input so that if the radio button
490
     *   is not checked and is submitted, the value of this attribute will still be submitted to the server
491
     *   via the hidden input. If you do not want any hidden input, you should explicitly set this option as `null`.
492
     * - `label`: string, a label displayed next to the radio button. It will NOT be HTML-encoded. Therefore you can pass
493
     *   in HTML code such as an image tag. If this is coming from end users, you should [[Html::encode()|encode]] it to prevent XSS attacks.
494
     *   When this option is specified, the radio button will be enclosed by a label tag. If you do not want any label, you should
495
     *   explicitly set this option as `null`.
496
     * - `labelOptions`: array, the HTML attributes for the label tag. This is only used when the `label` option is specified.
497
     *
498
     * The rest of the options will be rendered as the attributes of the resulting tag. The values will
499
     * be HTML-encoded using [[Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
500
     *
501
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
502
     *
503
     * @param boolean $enclosedByLabel whether to enclose the radio within the label.
504
     * If `true`, the method will still use [[template]] to layout the radio button and the error message
505
     * except that the radio is enclosed by the label tag.
506
     * @return $this the field object itself.
507
     */
508
    public function radio($options = [], $enclosedByLabel = true)
509
    {
510
        if ($enclosedByLabel) {
511
            $this->parts['{input}'] = Html::activeRadio($this->model, $this->attribute, $options);
512
            $this->parts['{label}'] = '';
513
        } else {
514
            if (isset($options['label']) && !isset($this->parts['{label}'])) {
515
                $this->parts['{label}'] = $options['label'];
516
                if (!empty($options['labelOptions'])) {
517
                    $this->labelOptions = $options['labelOptions'];
518
                }
519
            }
520
            unset($options['labelOptions']);
521
            $options['label'] = null;
522
            $this->parts['{input}'] = Html::activeRadio($this->model, $this->attribute, $options);
523
        }
524
        $this->adjustLabelFor($options);
525
526
        return $this;
527
    }
528
529
    /**
530
     * Renders a checkbox.
531
     * This method will generate the `checked` tag attribute according to the model attribute value.
532
     * @param array $options the tag options in terms of name-value pairs. The following options are specially handled:
533
     *
534
     * - `uncheck`: string, the value associated with the uncheck state of the radio button. If not set,
535
     *   it will take the default value `0`. This method will render a hidden input so that if the radio button
536
     *   is not checked and is submitted, the value of this attribute will still be submitted to the server
537
     *   via the hidden input. If you do not want any hidden input, you should explicitly set this option as `null`.
538
     * - `label`: string, a label displayed next to the checkbox. It will NOT be HTML-encoded. Therefore you can pass
539
     *   in HTML code such as an image tag. If this is coming from end users, you should [[Html::encode()|encode]] it to prevent XSS attacks.
540
     *   When this option is specified, the checkbox will be enclosed by a label tag. If you do not want any label, you should
541
     *   explicitly set this option as `null`.
542
     * - `labelOptions`: array, the HTML attributes for the label tag. This is only used when the `label` option is specified.
543
     *
544
     * The rest of the options will be rendered as the attributes of the resulting tag. The values will
545
     * be HTML-encoded using [[Html::encode()]]. If a value is `null`, the corresponding attribute will not be rendered.
546
     *
547
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
548
     *
549
     * @param boolean $enclosedByLabel whether to enclose the checkbox within the label.
550
     * If `true`, the method will still use [[template]] to layout the checkbox and the error message
551
     * except that the checkbox is enclosed by the label tag.
552
     * @return $this the field object itself.
553
     */
554
    public function checkbox($options = [], $enclosedByLabel = true)
555
    {
556
        if ($enclosedByLabel) {
557
            $this->parts['{input}'] = Html::activeCheckbox($this->model, $this->attribute, $options);
558
            $this->parts['{label}'] = '';
559
        } else {
560
            if (isset($options['label']) && !isset($this->parts['{label}'])) {
561
                $this->parts['{label}'] = $options['label'];
562
                if (!empty($options['labelOptions'])) {
563
                    $this->labelOptions = $options['labelOptions'];
564
                }
565
            }
566
            unset($options['labelOptions']);
567
            $options['label'] = null;
568
            $this->parts['{input}'] = Html::activeCheckbox($this->model, $this->attribute, $options);
569
        }
570
        $this->adjustLabelFor($options);
571
572
        return $this;
573
    }
574
575
    /**
576
     * Renders a drop-down list.
577
     * The selection of the drop-down list is taken from the value of the model attribute.
578
     * @param array $items the option data items. The array keys are option values, and the array values
579
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
580
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
581
     * If you have a list of data models, you may convert them into the format described above using
582
     * [[ArrayHelper::map()]].
583
     *
584
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
585
     * the labels will also be HTML-encoded.
586
     * @param array $options the tag options in terms of name-value pairs.
587
     *
588
     * For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeDropDownList()]].
589
     *
590
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
591
     *
592
     * @return $this the field object itself.
593
     */
594
    public function dropDownList($items, $options = [])
595
    {
596
        $options = array_merge($this->inputOptions, $options);
597
        $this->adjustLabelFor($options);
598
        $this->parts['{input}'] = Html::activeDropDownList($this->model, $this->attribute, $items, $options);
599
600
        return $this;
601
    }
602
603
    /**
604
     * Renders a list box.
605
     * The selection of the list box is taken from the value of the model attribute.
606
     * @param array $items the option data items. The array keys are option values, and the array values
607
     * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
608
     * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
609
     * If you have a list of data models, you may convert them into the format described above using
610
     * [[\yii\helpers\ArrayHelper::map()]].
611
     *
612
     * Note, the values and labels will be automatically HTML-encoded by this method, and the blank spaces in
613
     * the labels will also be HTML-encoded.
614
     * @param array $options the tag options in terms of name-value pairs.
615
     *
616
     * For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeListBox()]].
617
     *
618
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
619
     *
620
     * @return $this the field object itself.
621
     */
622 2
    public function listBox($items, $options = [])
623
    {
624 2
        $options = array_merge($this->inputOptions, $options);
625 2
        $this->adjustLabelFor($options);
626 2
        $this->parts['{input}'] = Html::activeListBox($this->model, $this->attribute, $items, $options);
627
628 2
        return $this;
629
    }
630
631
    /**
632
     * Renders a list of checkboxes.
633
     * A checkbox list allows multiple selection, like [[listBox()]].
634
     * As a result, the corresponding submitted value is an array.
635
     * The selection of the checkbox list is taken from the value of the model attribute.
636
     * @param array $items the data item used to generate the checkboxes.
637
     * The array values are the labels, while the array keys are the corresponding checkbox values.
638
     * @param array $options options (name => config) for the checkbox list.
639
     * For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeCheckboxList()]].
640
     * @return $this the field object itself.
641
     */
642
    public function checkboxList($items, $options = [])
643
    {
644
        $this->adjustLabelFor($options);
645
        $this->_skipLabelFor = true;
646
        $this->parts['{input}'] = Html::activeCheckboxList($this->model, $this->attribute, $items, $options);
647
648
        return $this;
649
    }
650
651
    /**
652
     * Renders a list of radio buttons.
653
     * A radio button list is like a checkbox list, except that it only allows single selection.
654
     * The selection of the radio buttons is taken from the value of the model attribute.
655
     * @param array $items the data item used to generate the radio buttons.
656
     * The array values are the labels, while the array keys are the corresponding radio values.
657
     * @param array $options options (name => config) for the radio button list.
658
     * For the list of available options please refer to the `$options` parameter of [[\yii\helpers\Html::activeRadioList()]].
659
     * @return $this the field object itself.
660
     */
661
    public function radioList($items, $options = [])
662
    {
663
        $this->adjustLabelFor($options);
664
        $this->_skipLabelFor = true;
665
        $this->parts['{input}'] = Html::activeRadioList($this->model, $this->attribute, $items, $options);
666
667
        return $this;
668
    }
669
670
    /**
671
     * Renders a widget as the input of the field.
672
     *
673
     * Note that the widget must have both `model` and `attribute` properties. They will
674
     * be initialized with [[model]] and [[attribute]] of this field, respectively.
675
     *
676
     * If you want to use a widget that does not have `model` and `attribute` properties,
677
     * please use [[render()]] instead.
678
     *
679
     * For example to use the [[MaskedInput]] widget to get some date input, you can use
680
     * the following code, assuming that `$form` is your [[ActiveForm]] instance:
681
     *
682
     * ```php
683
     * $form->field($model, 'date')->widget(\yii\widgets\MaskedInput::className(), [
684
     *     'mask' => '99/99/9999',
685
     * ]);
686
     * ```
687
     *
688
     * If you set a custom `id` for the input element, you may need to adjust the [[$selectors]] accordingly.
689
     *
690
     * @param string $class the widget class name.
691
     * @param array $config name-value pairs that will be used to initialize the widget.
692
     * @return $this the field object itself.
693
     */
694
    public function widget($class, $config = [])
695
    {
696
        /* @var $class \yii\base\Widget */
697
        $config['model'] = $this->model;
698
        $config['attribute'] = $this->attribute;
699
        $config['view'] = $this->form->getView();
700
        if (in_array('yii\widgets\InputWidget', class_parents($class)) && isset($config['options'])) {
701
            $this->adjustLabelFor($config['options']);
0 ignored issues
show
Documentation introduced by
$config['options'] is of type object<yii\base\Model>|s...ng|object<yii\web\View>, but the function expects a array.

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...
702
        }
703
        $this->parts['{input}'] = $class::widget($config);
704
705
        return $this;
706
    }
707
708
    /**
709
     * Adjusts the `for` attribute for the label based on the input options.
710
     * @param array $options the input options.
711
     */
712 12
    protected function adjustLabelFor($options)
713
    {
714 12
        if (!isset($options['id'])) {
715 10
            return;
716
        }
717 2
        $this->_inputId = $options['id'];
718 2
        if (!isset($this->labelOptions['for'])) {
719 2
            $this->labelOptions['for'] = $options['id'];
720 2
        }
721 2
    }
722
723
    /**
724
     * Returns the JS options for the field.
725
     * @return array the JS options.
726
     */
727 5
    protected function getClientOptions()
728
    {
729 5
        $attribute = Html::getAttributeName($this->attribute);
730 5
        if (!in_array($attribute, $this->model->activeAttributes(), true)) {
731 1
            return [];
732
        }
733
734 4
        $enableClientValidation = $this->enableClientValidation || $this->enableClientValidation === null && $this->form->enableClientValidation;
735 4
        $enableAjaxValidation = $this->enableAjaxValidation || $this->enableAjaxValidation === null && $this->form->enableAjaxValidation;
736
737 4
        if ($enableClientValidation) {
738 3
            $validators = [];
739 3
            foreach ($this->model->getActiveValidators($attribute) as $validator) {
740
                /* @var $validator \yii\validators\Validator */
741 3
                $js = $validator->clientValidateAttribute($this->model, $attribute, $this->form->getView());
742 3
                if ($validator->enableClientValidation && $js != '') {
743 3
                    if ($validator->whenClient !== null) {
744 1
                        $js = "if (({$validator->whenClient})(attribute, value)) { $js }";
745 1
                    }
746 3
                    $validators[] = $js;
747 3
                }
748 3
            }
749 3
        }
750
751 4
        if (!$enableAjaxValidation && (!$enableClientValidation || empty($validators))) {
752 1
            return [];
753
        }
754
755 3
        $options = [];
756
757 3
        $inputID = $this->getInputId();
758 3
        $options['id'] = Html::getInputId($this->model, $this->attribute);
759 3
        $options['name'] = $this->attribute;
760
761 3
        $options['container'] = isset($this->selectors['container']) ? $this->selectors['container'] : ".field-$inputID";
762 3
        $options['input'] = isset($this->selectors['input']) ? $this->selectors['input'] : "#$inputID";
763 3
        if (isset($this->selectors['error'])) {
764
            $options['error'] = $this->selectors['error'];
765 3
        } elseif (isset($this->errorOptions['class'])) {
766 3
            $options['error'] = '.' . implode('.', preg_split('/\s+/', $this->errorOptions['class'], -1, PREG_SPLIT_NO_EMPTY));
767 3
        } else {
768
            $options['error'] = isset($this->errorOptions['tag']) ? $this->errorOptions['tag'] : 'span';
769
        }
770
771 3
        $options['encodeError'] = !isset($this->errorOptions['encode']) || $this->errorOptions['encode'];
772 3
        if ($enableAjaxValidation) {
773 2
            $options['enableAjaxValidation'] = true;
774 2
        }
775 3
        foreach (['validateOnChange', 'validateOnBlur', 'validateOnType', 'validationDelay'] as $name) {
776 3
            $options[$name] = $this->$name === null ? $this->form->$name : $this->$name;
777 3
        }
778
779 3
        if (!empty($validators)) {
780 3
            $options['validate'] = new JsExpression("function (attribute, value, messages, deferred, \$form) {" . implode('', $validators) . '}');
781 3
        }
782
783
        // only get the options that are different from the default ones (set in yii.activeForm.js)
784 3
        return array_diff_assoc($options, [
785 3
            'validateOnChange' => true,
786 3
            'validateOnBlur' => true,
787 3
            'validateOnType' => false,
788 3
            'validationDelay' => 500,
789 3
            'encodeError' => true,
790 3
            'error' => '.help-block',
791 3
        ]);
792
    }
793
794
    /**
795
     * Returns the HTML `id` of the input element of this form field.
796
     * @return string the input id.
797
     * @since 2.0.7
798
     */
799 13
    protected function getInputId()
800
    {
801 13
        return $this->_inputId ?: Html::getInputId($this->model, $this->attribute);
802
    }
803
}
804