Completed
Pull Request — master (#6)
by
unknown
02:27
created

CategoryTerm::addTerm()   D

Complexity

Conditions 9
Paths 3

Size

Total Lines 45
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 45
rs 4.909
cc 9
eloc 28
nc 3
nop 2
1
<?php
2
3
namespace nkostadinov\taxonomy\components\terms;
4
5
use nkostadinov\taxonomy\models\TaxonomyDef;
6
use nkostadinov\taxonomy\models\TaxonomyTerms;
7
use Yii;
8
use yii\base\InvalidCallException;
9
use yii\db\Query;
10
use yii\helpers\ArrayHelper;
11
12
class CategoryTerm extends HierarchicalTerm
13
{
14
    public $templateFile = '@nkostadinov/taxonomy/migrations/template/category.php';
15
16
    public function getTerms($object_id, $name = [])
17
    {
18
        $query = TaxonomyTerms::find()
19
            ->select(TaxonomyTerms::tableName() . '.term')
20
            ->innerJoin($this->table, $this->table . '.term_id = taxonomy_terms.id')
0 ignored issues
show
Documentation introduced by
The property table does not exist on object<nkostadinov\taxon...nts\terms\CategoryTerm>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
21
            ->andFilterWhere(['taxonomy_terms.term' => $name]);
22
23
        if ($object_id) {
24
            $query->onCondition("$this->table.object_id = $object_id");
0 ignored issues
show
Documentation introduced by
The property table does not exist on object<nkostadinov\taxon...nts\terms\CategoryTerm>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
25
        }
26
27
        return ArrayHelper::getColumn($query->all(), 'term');
28
    }
29
30
    /**
31
     * Add term/s with the ability to make hierarchies.
32
     *
33
     * The object_id can be skipped. In this case a hierarchy will be created without being attached to an object.
34
     *
35
     * $params can be a string or an array:
36
     *  - If string, this is considered to be a root of a hierarchy;
37
     *  - If array, if only filled with values, this means these are all roots of a hierarchy;
38
     *  - If array and key => value is given, the key is the parent, the root is the child.
39
     *
40
     * @param integer $object_id Id to and object. Not mandatory.
41
     * @param string|array $params Terms
42
     */
43
    public function addTerm($object_id, $params)
44
    {
45
        $cachedParents = [];
46
47
        $addTerm = function ($parent, $item) use ($object_id, &$cachedParents) {
48
            if ($this->detectLoop($parent, $item)) {
49
                throw new InvalidCallException('Loop detected! Cannot add parent as a child!');
50
            }
51
52
            $term = $this->getTaxonomyTerm($item);
53
            $data['term_id'] = $term->id;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
54
            $data['object_id'] = $object_id;
55
56
            if (array_key_exists($parent, $cachedParents)) {
57
                $term->parent_id = $cachedParents[$parent]->id;
58
            } else if (is_string($parent)) {
59
                $parentTerm = $this->getTaxonomyTerm($parent);
60
                $cachedParents[$parent] = $parentTerm;
61
                $term->parent_id = $parentTerm->id;
62
            }
63
64
            if (!(new Query())->from($this->table)->where($data)->exists(CategoryTerm::getDb())) {
0 ignored issues
show
Documentation introduced by
The property table does not exist on object<nkostadinov\taxon...nts\terms\CategoryTerm>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
65
                Yii::$app->db->transaction(function() use ($data, $term) {
66
                    if ($term->getDirtyAttributes(['parent_id'])) {
67
                        $term->save(false);
68
                    }
69
                    CategoryTerm::getDb()->createCommand()->insert($this->table, $data)->execute();
0 ignored issues
show
Documentation introduced by
The property table does not exist on object<nkostadinov\taxon...nts\terms\CategoryTerm>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
70
71
                    $term->updateCounters(['total_count' => 1]);
72
                    TaxonomyDef::updateAllCounters(['total_count' => 1], ['id' => $this->id]);
73
                });
74
            }
75
        };
76
77
        $params = (array) $params;
78
        foreach ($params as $parent => $item) {
79
            if (is_array($item)) {
80
                foreach ($item as $child) {
81
                    $addTerm($parent, $child);
82
                }
83
            } else {
84
                $addTerm($parent, $item);
85
            }
86
        }
87
    }
88
89
    public function getParent($term)
90
    {
91
        $childTerm = $this->getTaxonomyTerm($term);
92
        if (!$childTerm || is_null($childTerm->parent_id)) {
93
            return null;
94
        }
95
96
        $parentTerm = (new Query())
97
            ->select('term')
98
            ->from(TaxonomyTerms::tableName())
99
            ->where("id = $childTerm->parent_id")
100
            ->one(self::getDb());
101
102
        return $parentTerm ? $parentTerm['term'] : null;
103
    }
104
105
    public function hasParent($term)
106
    {
107
        return $this->getParent($term) != null;
108
    }
109
110
    public function getChildren($term)
111
    {
112
        $parentTerm = $this->getTaxonomyTerm($term);
113
        if (!$parentTerm) {
114
            return [];
115
        }
116
117
        $query = (new Query())
118
            ->select('term')
119
            ->from(TaxonomyTerms::tableName())
120
            ->where("parent_id = $parentTerm->id");
121
122
        $result = [];
123
        foreach ($query->all(self::getDb()) as $row) {
124
            $result[] = $row['term'];
125
        }
126
127
        return $result;
128
    }
129
    
130
    public function hasChildren($term)
131
    {
132
        $parentTerm = $this->getTaxonomyTerm($term);
133
        if (!$parentTerm) {
134
            return false;
135
        }
136
        
137
        return (new Query())
138
            ->from(TaxonomyTerms::tableName())
139
            ->where("parent_id = $parentTerm->id")
140
            ->exists(self::getDb());
141
    }
142
}
143