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 ( 560332...66e815 )
by Robert
11:59
created

ActiveField::textInput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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