Completed
Push — 2.1 ( 0cb910...fafa40 )
by
unknown
40:37 queued 36:49
created

ActiveFormClientScript::getFieldClientOptions()   F

Complexity

Conditions 22
Paths 1539

Size

Total Lines 70
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 506

Importance

Changes 0
Metric Value
dl 0
loc 70
ccs 0
cts 57
cp 0
rs 2.6107
c 0
b 0
f 0
cc 22
eloc 42
nc 1539
nop 1
crap 506

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\widgets;
9
10
use Yii;
11
use yii\base\Behavior;
12
use yii\base\Widget;
13
use yii\helpers\Html;
14
use yii\helpers\Url;
15
use yii\web\JsExpression;
16
17
/**
18
 * ActiveFormClientScript is a base behavior for [[ActiveForm]], which allows composition of the client-side form validation.
19
 * Particular JavaScript-associated library should provide extension of this class, implementing [[registerClientScript()]] method.
20
 *
21
 * @property ActiveForm $owner the owner of this behavior.
22
 *
23
 * @author Paul Klimov <[email protected]>
24
 * @since 2.1
25
 */
26
abstract class ActiveFormClientScript extends Behavior
27
{
28
    /**
29
     * @var array client validator class map in format: `[server-side-validator-class => client-side-validator]`.
30
     * Client side validator should be specified as an instance of [[\yii\validators\client\ClientValidator]] or
31
     * its DI compatible configuration.
32
     *
33
     * Class map respects validators inheritance, e.g. if you specify map for `ParentValidator` it will be used for
34
     * `ChildValidator` in case it extends `ParentValidator`. In case maps for both `ParentValidator` and `ChildValidator`
35
     * are specified the first value will take precedence.
36
     *
37
     * Result of [[defaultClientValidatorMap()]] method will be merged into this field at behavior initialization.
38
     * In order to disable mapping for pre-defined validator use `false` value.
39
     *
40
     * For example:
41
     *
42
     * ```php
43
     * [
44
     *     \yii\validators\BooleanValidator::class => \yii\jquery\validators\client\BooleanValidator::class,
45
     *     \yii\validators\ImageValidator::class => \yii\jquery\validators\client\ImageValidator::class,
46
     *     \yii\validators\FileValidator::class => false, // disable client validation for `FileValidator`
47
     * ]
48
     * ```
49
     *
50
     * You should use this field only in case particular client script does not provide any default mapping or
51
     * in case you wish to override this mapping.
52
     */
53
    public $clientValidatorMap = [];
54
55
    /**
56
     * @var array the client validation options for individual attributes. Each element of the array
57
     * represents the validation options for a particular attribute.
58
     */
59
    protected $attributes = [];
60
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function init()
66
    {
67
        parent::init();
68
69
        $this->clientValidatorMap = array_merge(
70
            $this->defaultClientValidatorMap(),
71
            $this->clientValidatorMap
72
        );
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function events()
79
    {
80
        return [
81
            Widget::EVENT_AFTER_RUN => 'afterRun',
82
            ActiveForm::EVENT_BEFORE_FIELD_RENDER => 'beforeFieldRender',
83
        ];
84
    }
85
86
    /**
87
     * Handles [[Widget::EVENT_AFTER_RUN]] event, registering related client script.
88
     * @param \yii\base\Event $event event instance.
89
     */
90
    public function afterRun($event)
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
    {
92
        $this->registerClientScript();
93
    }
94
95
    /**
96
     * Handles [[ActiveForm::EVENT_BEFORE_FIELD_RENDER]] event.
97
     * @param ActiveFieldEvent $event event instance.
98
     */
99
    public function beforeFieldRender($event)
100
    {
101
        $clientOptions = $this->getFieldClientOptions($event->field);
102
        if (!empty($clientOptions)) {
103
            $this->attributes[] = $clientOptions;
104
        }
105
    }
106
107
    /**
108
     * Registers underlying client script including JavaScript code, which supports form validation.
109
     */
110
    abstract protected function registerClientScript();
111
112
    /**
113
     * Returns the JS options for the field.
114
     * @param ActiveField $field active field instance.
115
     * @return array the JS options.
116
     */
117
    protected function getFieldClientOptions($field)
118
    {
119
        $attribute = Html::getAttributeName($field->attribute);
120
        if (!in_array($attribute, $field->model->activeAttributes(), true)) {
121
            return [];
122
        }
123
124
        $clientValidation = $field->isClientValidationEnabled();
125
        $ajaxValidation = $field->isAjaxValidationEnabled();
126
127
        if ($clientValidation) {
128
            $validators = [];
129
            foreach ($field->model->getActiveValidators($attribute) as $validator) {
130
                /* @var $validator \yii\validators\Validator */
131
                if (!$validator->enableClientValidation) {
132
                    continue;
133
                }
134
135
                $js = $validator->clientValidateAttribute($field->model, $attribute, $field->form->getView());
136
                if ($js == '') {
137
                    $js = $this->buildClientValidator($validator, $field->model, $attribute, $field->form->getView());
138
                }
139
140
                if ($js != '') {
141
                    if ($validator->whenClient !== null) {
142
                        $js = "if (({$validator->whenClient})(attribute, value)) { $js }";
143
                    }
144
                    $validators[] = $js;
145
                }
146
            }
147
        }
148
149
        if (!$ajaxValidation && (!$clientValidation || empty($validators))) {
150
            return [];
151
        }
152
153
        $options = [];
154
155
        $inputID = $field->getInputId();
156
        $options['id'] = Html::getInputId($field->model, $field->attribute);
157
        $options['name'] = $field->attribute;
158
159
        $options['container'] = isset($field->selectors['container']) ? $field->selectors['container'] : ".field-$inputID";
160
        $options['input'] = isset($field->selectors['input']) ? $field->selectors['input'] : "#$inputID";
161
        if (isset($field->selectors['error'])) {
162
            $options['error'] = $field->selectors['error'];
163
        } elseif (isset($field->errorOptions['class'])) {
164
            $options['error'] = '.' . implode('.', preg_split('/\s+/', $field->errorOptions['class'], -1, PREG_SPLIT_NO_EMPTY));
165
        } else {
166
            $options['error'] = isset($field->errorOptions['tag']) ? $field->errorOptions['tag'] : 'span';
167
        }
168
169
        $options['encodeError'] = !isset($field->errorOptions['encode']) || $field->errorOptions['encode'];
170
        if ($ajaxValidation) {
171
            $options['enableAjaxValidation'] = true;
172
        }
173
        foreach (['validateOnChange', 'validateOnBlur', 'validateOnType', 'validationDelay'] as $name) {
174
            $options[$name] = $field->$name === null ? $field->form->$name : $field->$name;
175
        }
176
177
        if (!empty($validators)) {
178
            $options['validate'] = new JsExpression("function (attribute, value, messages, deferred, \$form) {" . implode('', $validators) . '}');
179
        }
180
181
        if ($field->addAriaAttributes === false) {
182
            $options['updateAriaInvalid'] = false;
183
        }
184
185
        return $options;
186
    }
187
188
    /**
189
     * Returns the options for the form JS widget.
190
     * @return array the options.
191
     */
192
    protected function getClientOptions()
193
    {
194
        $options = [
195
            'encodeErrorSummary' => $this->owner->encodeErrorSummary,
196
            'errorSummary' => '.' . implode('.', preg_split('/\s+/', $this->owner->errorSummaryCssClass, -1, PREG_SPLIT_NO_EMPTY)),
197
            'validateOnSubmit' => $this->owner->validateOnSubmit,
198
            'errorCssClass' => $this->owner->errorCssClass,
199
            'successCssClass' => $this->owner->successCssClass,
200
            'validatingCssClass' => $this->owner->validatingCssClass,
201
            'ajaxParam' => $this->owner->ajaxParam,
202
            'ajaxDataType' => $this->owner->ajaxDataType,
203
            'scrollToError' => $this->owner->scrollToError,
204
            'scrollToErrorOffset' => $this->owner->scrollToErrorOffset,
205
        ];
206
        if ($this->owner->validationUrl !== null) {
207
            $options['validationUrl'] = Url::to($this->owner->validationUrl);
208
        }
209
210
        return $options;
211
    }
212
213
    /**
214
     * Builds the JavaScript needed for performing client-side validation for given validator.
215
     * @param \yii\validators\Validator $validator validator to be built.
216
     * @param \yii\base\Model $model the data model being validated.
217
     * @param string $attribute the name of the attribute to be validated.
218
     * @param \yii\web\View $view the view object that is going to be used to render views or view files
219
     * containing a model form with validator applied.
220
     * @return string|null client-side validation JavaScript code, `null` - if given validator is not supported.
221
     */
222
    protected function buildClientValidator($validator, $model, $attribute, $view)
223
    {
224
        foreach ($this->clientValidatorMap as $serverSideValidatorClass => $clientSideValidator) {
225
            if ($clientSideValidator !== false && $validator instanceof $serverSideValidatorClass) {
226
                /* @var $clientValidator \yii\validators\client\ClientValidator */
227
                $clientValidator = Yii::createObject($clientSideValidator);
228
                return $clientValidator->build($validator, $model, $attribute, $view);
229
            }
230
        }
231
        return null;
232
    }
233
234
    /**
235
     * Returns default client validator map, which will be merged with [[clientValidatorMap]] at [[init()]].
236
     * Child class may override this method providing validator map specific for particular client script.
237
     * @return array client validator class map in format: `[server-side-validator-class => client-side-validator]`.
238
     */
239
    protected function defaultClientValidatorMap()
240
    {
241
        return [];
242
    }
243
}