Completed
Pull Request — master (#37)
by Klochok
11:35
created

ObjectCombo   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 5
dl 0
loc 146
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 13 2
A generateConfigs() 0 7 2
A registerChangerScript() 0 7 1
A applyConfigByType() 0 15 4
A findCurrentAttributes() 0 6 1
A applyDefaultAttributes() 0 6 3
B registerSpecialAssets() 0 58 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
class ObjectCombo 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 $objectsOptions = [];
31
32
    public $currentObjectType;
33
34
    public $currentObjectAttributeName;
35
36
    private $attributes = [];
37
38
    public function init()
39
    {
40
        if (empty($this->objectsOptions)) {
41
            throw new InvalidConfigException('Property `objectsOptions` is required for class ObjectCombo.');
42
        }
43
        $this->inputOptions = ['data-object-selector-field' => true, 'class' => 'object-selector-select'];
44
        $this->registerSpecialAssets();
45
        $this->findCurrentAttributes();
46
        $this->generateConfigs();
47
        parent::init();
48
        $this->registerChangerScript();
49
        $this->applyDefaultAttributes();
50
    }
51
52
    private function generateConfigs()
53
    {
54
        foreach ($this->objectsOptions as $type => $options) {
55
            $this->applyConfigByType($type);
56
        }
57
58
    }
59
60
    private function registerChangerScript()
61
    {
62
        $changerId = Html::getInputId($this->model, $this->currentObjectAttributeName);
63
        $inputId = $this->inputOptions['id'];
64
65
        $this->view->registerJs("initObjectSelectorChanger('{$changerId}', '{$inputId}')");
66
    }
67
68
    private function applyConfigByType($type)
69
    {
70
        $options = $this->objectsOptions[$type];
71
        if ($options['comboOptions']) {
72
            foreach ($this->attributes 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_' . $type;
80
        $id = $this->configId;
81
        $this->view->registerJsVar($varName, $id, View::POS_END);
82
    }
83
84
    private function findCurrentAttributes()
85
    {
86
        $this->attributes = 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
        if ($this->currentObjectType) {
94
            $this->applyConfigByType($this->currentObjectType ?: 'client');
95
        }
96
    }
97
98
    private function registerSpecialAssets()
99
    {
100
        // Fix validation styles
101
        $this->view->registerCss("
102
            .form-group.has-error .select2-selection { border-color: #dd4b39; box-shadow: none; }
103
            .form-group.has-success .select2-selection { border-color: #00a65a; box-shadow: none; }
104
            select.object-selector-select:not([data-select2-id]) { display: none; }
105
        ");
106
        $this->view->registerJs(<<<'JS'
107
            (function( $ ){
108
109
                var originalDynamicForm = $.fn.yiiDynamicForm;
110
                
111
                var methods = {
112
                    addItem : function(widgetOptions, e, elem) { 
113
                        originalDynamicForm('addItem', widgetOptions, e, elem);
114
                        var count = elem.closest('.' + widgetOptions.widgetContainer).find(widgetOptions.widgetItem).length;
115
116
                        // Reinit ObjectSelectorChanger after added new item
117
                        if (count < widgetOptions.limit) {
118
                            var objectSelectorInputs = $($newclone).find('[data-object-selector-field]');
119
                            if (objectSelectorInputs.length > 0) {
120
                                objectSelectorInputs.each(function() {
121
                                    var objectInputId = $(this).attr('id');
122
                                    var changerInputId = $(this).prev('select').attr('id');
123
                                    initObjectSelectorChanger(changerInputId, objectInputId); 
124
                                });
125
                            }
126
                        } 
127
                    }
128
                };
129
                
130
                $.fn.yiiDynamicForm = function(method) {
131
                    if (method === 'addItem') {
132
                        return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
133
                    } else {
134
                        originalDynamicForm.apply(this, arguments);        
135
                    }
136
                }
137
                
138
            })(window.jQuery);
139
JS
140
        );
141
        $this->view->registerJs(<<<JS
142
            function initObjectSelectorChanger(changerInputId, objectInputId) {
143
                $('#' + changerInputId).change(function(e) {
144
                    var regexID = /^(.+?)([-\d-]{1,})(.+)$/i;
145
                    var matches = objectInputId.match(regexID);
146
                    var combo = $('#' + objectInputId).closest('form').combo();
147
                    if (combo) {
148
                        combo.register('#' + objectInputId, window[matches[1] + '_object_id_' + e.target.value]);
149
                        $('#' + objectInputId).val(null).trigger('change');
150
                    }
151
                });
152
            }
153
JS
154
        );
155
    }
156
}
157