Passed
Push — master ( 385631...9fe296 )
by Alexander
02:24
created

BaseWidget::isBehaviorIncluded()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
rs 8.8571
cc 6
eloc 8
nc 4
nop 0
1
<?php
2
3
namespace hauntd\vote\widgets;
4
5
use Yii;
6
use hauntd\vote\assets\VoteAsset;
7
use hauntd\vote\behaviors\VoteBehavior;
8
use hauntd\vote\models\VoteAggregate;
9
use hauntd\vote\traits\ModuleTrait;
10
use yii\base\InvalidParamException;
11
use yii\base\Widget;
12
use yii\web\JsExpression;
13
use yii\web\View;
14
15
/**
16
 * @author Alexander Kononenko <[email protected]>
17
 * @package hauntd\vote\widgets
18
 */
19
abstract class BaseWidget extends Widget
20
{
21
    use ModuleTrait;
22
23
    /**
24
     * @var string
25
     */
26
    public $entity;
27
28
    /**
29
     * @var null|\yii\db\ActiveRecord
30
     */
31
    public $model;
32
33
    /**
34
     * @var null|integer;
35
     */
36
    public $targetId;
37
38
    /**
39
     * @var string
40
     */
41
    public $voteUrl;
42
43
    /**
44
     * @var null|\hauntd\vote\models\VoteAggregate
45
     */
46
    public $aggregateModel;
47
48
    /**
49
     * @var null|integer
50
     */
51
    public $userValue;
52
53
    /**
54
     * @var string
55
     */
56
    public $jsBeforeVote;
57
58
    /**
59
     * @var string
60
     */
61
    public $jsAfterVote;
62
63
    /**
64
     * @var string
65
     */
66
    public $jsCodeKey = 'vote';
67
68
    /**
69
     * @var string
70
     */
71
    public $jsErrorVote;
72
73
    /**
74
     * @var string
75
     */
76
    public $jsShowMessage;
77
78
    /**
79
     * @var string
80
     */
81
    public $jsChangeCounters;
82
83
    /**
84
     * @var array
85
     */
86
    public $options = [];
87
88
    /**
89
     * @var string
90
     */
91
    public $viewFile = 'vote';
92
93
    /**
94
     * @var array
95
     */
96
    public $viewParams = [];
97
98
    /**
99
     * @var bool
100
     */
101
    protected $_behaviorIncluded;
102
103
    /**
104
     * @return string
105
     */
106
    public function getSelector()
107
    {
108
        $classes = str_replace(' ', '.', $this->options['class']);
109
        return ".{$classes}[data-entity=\"' + entity + '\"][data-target-id=\"' + target  + '\"]";
110
    }
111
112
    /**
113
     * @inheritdoc
114
     * @throws \yii\base\InvalidConfigException
115
     */
116
    public function init()
117
    {
118
        parent::init();
119
120
        if (!isset($this->entity) || !isset($this->model)) {
121
            throw new InvalidParamException(Yii::t('vote', 'Entity and model must be set.'));
122
        }
123
124
        $this->initDefaults();
125
126
        if ($this->getModule()->registerAsset) {
127
            $this->view->registerAssetBundle(VoteAsset::class);
128
        }
129
    }
130
131
    /**
132
     * Initialize widget with default options.
133
     *
134
     * @throws \yii\base\InvalidConfigException
135
     */
136
    public function initDefaults()
137
    {
138
        $this->voteUrl = isset($this->voteUrl) ?: Yii::$app->getUrlManager()->createUrl(['vote/default/vote']);
139
        $this->targetId = isset($this->targetId) ?: $this->model->getPrimaryKey();
140
141
        if (!isset($this->aggregateModel)) {
142
            $this->aggregateModel = $this->isBehaviorIncluded() ?
143
                $this->model->getVoteAggregate($this->entity) :
144
                VoteAggregate::findOne([
145
                    'entity' => $this->getModule()->encodeEntity($this->entity),
146
                    'target_id' => $this->targetId,
147
                ]);
148
        }
149
150
        if (!isset($this->userValue)) {
151
            $this->userValue = $this->isBehaviorIncluded() ? $this->model->getUserValue($this->entity) : null;
152
        }
153
    }
154
155
    /**
156
     * Registers jQuery handler.
157
     */
158
    protected function registerJs()
159
    {
160
        $jsCode = new JsExpression("
161
            $('body').on('click', '[data-rel=\"{$this->jsCodeKey}\"] button', function(event) {
162
                var vote = $(this).closest('[data-rel=\"{$this->jsCodeKey}\"]'),
163
                    button = $(this),
164
                    action = button.attr('data-action'),
165
                    entity = vote.attr('data-entity'),
166
                    target = vote.attr('data-target-id');
167
                jQuery.ajax({
168
                    url: '$this->voteUrl', type: 'POST', dataType: 'json', cache: false,
169
                    data: { 'VoteForm[entity]': entity, 'VoteForm[targetId]': target, 'VoteForm[action]': action },
170
                    beforeSend: function(jqXHR, settings) { $this->jsBeforeVote },
171
                    success: function(data, textStatus, jqXHR) { $this->jsChangeCounters $this->jsShowMessage },
172
                    complete: function(jqXHR, textStatus) { $this->jsAfterVote },
173
                    error: function(jqXHR, textStatus, errorThrown) { $this->jsErrorVote }
174
                });
175
            });
176
        ");
177
        $this->view->registerJs($jsCode, View::POS_END, $this->jsCodeKey);
178
    }
179
180
    /**
181
     * @param array $params
182
     * @return array
183
     */
184
    protected function getViewParams(array $params)
185
    {
186
        return array_merge($this->viewParams, $params);
187
    }
188
189
    /**
190
     * @return bool
191
     */
192
    protected function isBehaviorIncluded()
193
    {
194
        if (isset($this->_behaviorIncluded)) {
195
            return $this->_behaviorIncluded;
196
        }
197
198
        if (!isset($this->aggregateModel) || !isset($this->userValue)) {
199
            foreach ($this->model->getBehaviors() as $behavior) {
200
                if ($behavior instanceof VoteBehavior) {
201
                    return $this->_behaviorIncluded = true;
202
                }
203
            }
204
        }
205
206
        return $this->_behaviorIncluded = false;
207
    }
208
}
209