Taggable::events()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * @link https://github.com/2amigos/yii2-taggable-behavior
4
 * @copyright Copyright (c) 2013-2016 2amigOS! Consulting Group LLC
5
 * @license http://opensource.org/licenses/BSD-3-Clause
6
 */
7
8
namespace dosamigos\taggable;
9
10
use yii\base\Behavior;
11
use yii\base\Event;
12
use yii\db\ActiveRecord;
13
use yii\db\Query;
14
15
/**
16
 * @author Alexander Kochetov <[email protected]>
17
 * @author Antonio Ramirez <[email protected]>
18
 */
19
class Taggable extends Behavior
20
{
21
    /**
22
     * @var ActiveRecord the owner of this behavior.
23
     */
24
    public $owner;
25
    /**
26
     * @var string
27
     */
28
    public $attribute = 'tagNames';
29
    /**
30
     * @var string
31
     */
32
    public $name = 'name';
33
    /**
34
     * @var string
35
     */
36
    public $frequency = 'frequency';
37
    /**
38
     * @var bool
39
     */
40
    public $removeUnusedTags = false;
41
    /**
42
     * @var string
43
     */
44
    public $relation = 'tags';
45
    /**
46
     * Tag values
47
     * @var array|string
48
     */
49
    public $tagValues;
50
    /**
51
     * @var bool
52
     */
53
    public $asArray = false;
54
55
    /**
56
     * @inheritdoc
57
     */
58
    public function events()
59
    {
60
        return [
61
            ActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
62
            ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
63
            ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete',
64
        ];
65
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function canGetProperty($name, $checkVars = true)
71
    {
72
        if ($name === $this->attribute) {
73
            return true;
74
        }
75
76
        return parent::canGetProperty($name, $checkVars);
77
    }
78
79
    /**
80
     * @inheritdoc
81
     */
82
    public function __get($name)
83
    {
84
        return $this->getTagNames();
85
    }
86
87
    /**
88
     * @inheritdoc
89
     */
90
    public function canSetProperty($name, $checkVars = true)
91
    {
92
        if ($name === $this->attribute) {
93
            return true;
94
        }
95
96
        return parent::canSetProperty($name, $checkVars);
97
    }
98
99
    /**
100
     * @inheritdoc
101
     */
102
    public function __set($name, $value)
103
    {
104
        $this->tagValues = $value;
105
    }
106
107
    /**
108
     * @inheritdoc
109
     */
110
    private function getTagNames()
111
    {
112
        $items = [];
113
114
        $tags=$this->owner->{$this->relation};
115
116
        if (is_array($tags)){
117
            foreach ($tags as $tag) {
118
                $items[] = $tag->{$this->name};
119
            }
120
        }
121
122
        return $this->asArray ? $items : implode(',', $items);
123
    }
124
125
    /**
126
     * @param Event $event
127
     */
128
    public function afterSave($event)
129
    {
130
        if ($this->tagValues === null) {
131
            $this->tagValues = $this->owner->{$this->attribute};
132
        }
133
134
        if (!$this->owner->getIsNewRecord()) {
135
            $this->beforeDelete($event);
136
        }
137
138
        $names = array_unique(preg_split(
139
            '/\s*,\s*/u',
140
            preg_replace(
141
                '/\s+/u',
142
                ' ',
143
                is_array($this->tagValues)
144
                    ? implode(',', $this->tagValues)
145
                    : $this->tagValues
146
            ),
147
            -1,
148
            PREG_SPLIT_NO_EMPTY
149
        ));
150
151
        $relation = $this->owner->getRelation($this->relation);
152
        $pivot = $relation->via->from[0];
0 ignored issues
show
Bug introduced by
Accessing via on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
153
        /** @var ActiveRecord $class */
154
        $class = $relation->modelClass;
0 ignored issues
show
Bug introduced by
Accessing modelClass on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
155
        $rows = [];
156
        $updatedTags = [];
157
158
        foreach ($names as $name) {
159
            $tag = $class::findOne([$this->name => $name]);
160
161
            if ($tag === null) {
162
                $tag = new $class();
163
                $tag->{$this->name} = $name;
164
            }
165
166
            if ($this->frequency) {
167
                $tag->{$this->frequency}++;
168
            }
169
170
            if ($tag->save()) {
171
                $updatedTags[] = $tag;
172
                $rows[] = [$this->owner->getPrimaryKey(), $tag->getPrimaryKey()];
173
            }
174
        }
175
176
        if (!empty($rows)) {
177
            $this->owner->getDb()
178
                ->createCommand()
179
                ->batchInsert($pivot, [key($relation->via->link), current($relation->link)], $rows)
0 ignored issues
show
Bug introduced by
Accessing via on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing link on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
180
                ->execute();
181
        }
182
183
        $this->owner->populateRelation($this->relation, $updatedTags);
184
    }
185
186
    /**
187
     * @param Event $event
188
     */
189
    public function beforeDelete($event)
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
190
    {
191
        if (!$this->frequency) {
192
            return;
193
        }
194
195
        $relation = $this->owner->getRelation($this->relation);
196
        $pivot = $relation->via->from[0];
0 ignored issues
show
Bug introduced by
Accessing via on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
197
        /** @var ActiveRecord $class */
198
        $class = $relation->modelClass;
0 ignored issues
show
Bug introduced by
Accessing modelClass on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
199
        $query = new Query();
200
        $pks = $query
201
            ->select(current($relation->link))
0 ignored issues
show
Bug introduced by
Accessing link on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
202
            ->from($pivot)
203
            ->where([key($relation->via->link) => $this->owner->getPrimaryKey()])
0 ignored issues
show
Bug introduced by
Accessing via on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
204
            ->column($this->owner->getDb());
205
206
        if (!empty($pks)) {
207
            $class::updateAllCounters([$this->frequency => -1], ['in', $class::primaryKey(), $pks]);
208
        }
209
210
        $this->owner->getDb()
211
            ->createCommand()
212
            ->delete($pivot, [key($relation->via->link) => $this->owner->getPrimaryKey()])
0 ignored issues
show
Bug introduced by
Accessing via on the interface yii\db\ActiveQueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
213
            ->execute();
214
215
        if ($this->removeUnusedTags)
216
        {
217
            $class::deleteAll([$this->frequency => 0]);
218
        }
219
    }
220
}
221