BaseWidget::isBehaviorIncluded()   A
last analyzed

Complexity

Conditions 6
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 15
rs 9.2222
c 0
b 0
f 0
cc 6
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.'));
0 ignored issues
show
Deprecated Code introduced by
The class yii\base\InvalidParamException has been deprecated: since 2.0.14. Use [[InvalidArgumentException]] instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

121
            throw /** @scrutinizer ignore-deprecated */ new InvalidParamException(Yii::t('vote', 'Entity and model must be set.'));
Loading history...
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']);
0 ignored issues
show
Documentation Bug introduced by
It seems like IssetNode ?: Yii::app->g...y('vote/default/vote')) can also be of type true. However, the property $voteUrl is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
139
        $this->targetId = isset($this->targetId) ?: $this->model->getPrimaryKey();
0 ignored issues
show
Bug introduced by
The method getPrimaryKey() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

139
        $this->targetId = isset($this->targetId) ?: $this->model->/** @scrutinizer ignore-call */ getPrimaryKey();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
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').off('click', '[data-rel=\"{$this->jsCodeKey}\"] button').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