Completed
Pull Request — master (#37)
by Klochok
03:49
created

applyConfigByObjectClassName()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 4
nc 2
nop 1
1
<?php
2
3
namespace hipanel\widgets\combo;
4
5
use hiqdev\combo\Combo;
6
use ReflectionClass;
7
use yii\base\InvalidConfigException;
8
use yii\bootstrap\Html;
9
use yii\web\View;
10
11
/**
12
 * Class InternalObjectCombo
13
 */
14
class InternalObjectCombo extends Combo
15
{
16
    /** {@inheritdoc} */
17
    public $type = 'hipanel/object';
18
19
    /** {@inheritdoc} */
20
    public $name;
21
22
    /** {@inheritdoc} */
23
    public $url;
24
25
    /** {@inheritdoc} */
26
    public $_return;
27
28
    /** {@inheritdoc} */
29
    public $_rename;
30
31
    /** {@inheritdoc} */
32
    public $_primaryFilter;
33
34
    /**
35
     * @var array
36
     */
37
    public $classes = [];
38
39
    /**
40
     * @var string
41
     */
42
    public $class_attribute;
43
44
    /**
45
     * @var string
46
     */
47
    public $class_attribute_name;
48
49
    /**
50
     * @var array
51
     */
52
    private $requiredAttributes = [];
53
54
    /** {@inheritdoc} */
55
    public function init()
56
    {
57
        if (empty($this->classes)) {
58
            throw new InvalidConfigException('Property `classes` is required for class InternalObjectCombo.');
59
        }
60
        $this->inputOptions = ['data-object-selector-field' => true, 'class' => 'object-selector-select'];
61
        $this->registerSpecialAssets();
62
        $this->fillRequiredAttributes();
63
        $this->generateConfigs();
64
        parent::init();
65
        $this->registerChangerScript();
66
        $this->applyDefaultAttributes();
67
    }
68
69
    private function generateConfigs()
70
    {
71
        foreach ($this->classes as $className => $options) {
72
            $this->applyConfigByObjectClassName($className);
73
        }
74
75
    }
76
77
    private function registerChangerScript()
78
    {
79
        $changerId = Html::getInputId($this->model, $this->class_attribute_name);
80
        $inputId = $this->inputOptions['id'];
81
82
        $this->view->registerJs("initObjectSelectorChanger('{$changerId}', '{$inputId}')");
83
    }
84
85
    private function applyConfigByObjectClassName($className)
86
    {
87
        $options = $this->classes[$className];
88
        if ($options['comboOptions']) {
89
            foreach ($this->requiredAttributes as $attribute) {
90
                if (isset($options['comboOptions'][$attribute->name])) {
91
                    $this->{$attribute->name} = $options['comboOptions'][$attribute->name];
92
                }
93
            }
94
        }
95
        $this->registerClientConfig();
96
        $varName = strtolower($this->model->formName()) . '_object_id_' . $className;
97
        $this->view->registerJsVar($varName, $this->configId, View::POS_END);
98
    }
99
100
    private function fillRequiredAttributes()
101
    {
102
        $this->requiredAttributes = array_filter((new ReflectionClass(get_class($this)))->getProperties(), function ($attr) {
103
            return $attr->class === get_class($this);
104
        });
105
    }
106
107
    private function applyDefaultAttributes()
108
    {
109
        $this->applyConfigByObjectClassName($this->class_attribute ?: 'client');
110
    }
111
112
    private function registerSpecialAssets()
113
    {
114
        // Fix validation styles
115
        $this->view->registerCss("
116
            .form-group.has-error .select2-selection { border-color: #dd4b39; box-shadow: none; }
117
            .form-group.has-success .select2-selection { border-color: #00a65a; box-shadow: none; }
118
            select.object-selector-select:not([data-select2-id]) { display: none; }
119
        ");
120
        $this->view->registerJs(<<<'JS'
121
            (function( $ ){
122
123
                var originalDynamicForm = $.fn.yiiDynamicForm;
124
                
125
                var methods = {
126
                    addItem : function(widgetOptions, e, elem) { 
127
                        originalDynamicForm('addItem', widgetOptions, e, elem);
128
                        var count = elem.closest('.' + widgetOptions.widgetContainer).find(widgetOptions.widgetItem).length;
129
130
                        // Reinit ObjectSelectorChanger after added new item
131
                        if (count < widgetOptions.limit) {
132
                            var objectSelectorInputs = $($newclone).find('[data-object-selector-field]');
133
                            objectSelectorInputs.each(function() {
134
                                var objectInputId = $(this).attr('id');
135
                                var changerInputId = $(this).prev('select').attr('id');
136
                                initObjectSelectorChanger(changerInputId, objectInputId);
137
                            });
138
                        } 
139
                    }
140
                };
141
                
142
                $.fn.yiiDynamicForm = function(method) {
143
                    if (method === 'addItem') {
144
                        return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
145
                    }
146
                    originalDynamicForm.apply(this, arguments);
147
                }
148
                
149
            })(window.jQuery);
150
JS
151
        );
152
        $this->view->registerJs(<<<JS
153
            function initObjectSelectorChanger(changerInputId, objectInputId) {
154
                $('#' + changerInputId).change(function(e) {
155
                    var regexID = /^(.+?)([-\d-]{1,})(.+)$/i;
156
                    var matches = objectInputId.match(regexID);
157
                    var combo = $('#' + objectInputId).closest('form').combo();
158
                    if (combo) {
159
                        combo.register('#' + objectInputId, window[matches[1] + '_object_id_' + e.target.value]);
160
                        $('#' + objectInputId).val(null).trigger('change');
161
                    }
162
                });
163
            }
164
JS
165
        );
166
    }
167
}
168