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