Completed
Pull Request — master (#37)
by Klochok
40:07 queued 17:47
created

InternalObjectCombo::generateConfigs()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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