Completed
Pull Request — master (#8)
by
unknown
02:06
created

CategoryTerm::getTerms()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 2
eloc 9
nc 2
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
    /**
17
     * Add term/s with the ability to make hierarchies.
18
     *
19
     * The object_id can be skipped. In this case a hierarchy will be created without being attached to an object.
20
     *
21
     * $params can be a string or an array:
22
     *  - If string, this is considered to be a root of a hierarchy;
23
     *  - If array, if only filled with values, this means these are all roots of a hierarchy;
24
     *  - If array and key => value is given, the key is the parent, the root is the child.
25
     *
26
     * @param integer $object_id Id to and object. Not mandatory.
27
     * @param string|array $params Terms
28
     */
29
    public function addTerm($object_id, $params)
30
    {
31
        $cachedParents = [];
32
33
        $addTerm = function ($parent, $item) use ($object_id, &$cachedParents, &$addTerm) {
34
            if ($this->detectLoop($parent, $item)) {
35
                throw new InvalidCallException('Loop detected! Cannot add parent as a child!');
36
            }
37
38
            $term = $this->getTaxonomyTerm($item);
39
            if (array_key_exists($parent, $cachedParents)) {
40
                $term->parent_id = $cachedParents[$parent]->id;
0 ignored issues
show
Documentation introduced by
The property parent_id does not exist on object<nkostadinov\taxonomy\models\TaxonomyTerms>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
41
            } else if (is_string($parent)) {
42
                $parentTerm = $this->getTaxonomyTerm($parent);
43
                $cachedParents[$parent] = $parentTerm;
44
                $term->parent_id = $parentTerm->id;
0 ignored issues
show
Documentation introduced by
The property parent_id does not exist on object<nkostadinov\taxonomy\models\TaxonomyTerms>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
45
                $addTerm(null, $parent); // Assign object id to the parent as well!
46
            }
47
48
            if ($term->getDirtyAttributes(['parent_id'])) {
49
                $term->save(false);
50
            }
51
52
            if ($object_id) {
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 (!(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...
57
                    Yii::$app->db->transaction(function() use ($data, $term) {
58
                        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...
59
60
                        $term->updateCounters(['total_count' => 1]);
61
                        TaxonomyDef::updateAllCounters(['total_count' => 1], ['id' => $this->id]);
62
                    });
63
                }
64
            }
65
        };
66
67
        $params = (array) $params;
68
        foreach ($params as $parent => $item) {
69
            if (is_array($item)) {
70
                foreach ($item as $child) {
71
                    $addTerm($parent, $child);
72
                }
73
            } else {
74
                $addTerm($parent, $item);
75
            }
76
        }
77
    }
78
79
    public function getParent($term)
80
    {
81
        $childTerm = $this->getTaxonomyTerm($term);
82
        if (!$childTerm || is_null($childTerm->parent_id)) {
0 ignored issues
show
Documentation introduced by
The property parent_id does not exist on object<nkostadinov\taxonomy\models\TaxonomyTerms>. 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...
83
            return null;
84
        }
85
86
        $parentTerm = (new Query())
87
            ->select('term')
88
            ->from(TaxonomyTerms::tableName())
89
            ->where("id = $childTerm->parent_id")
0 ignored issues
show
Documentation introduced by
The property parent_id does not exist on object<nkostadinov\taxonomy\models\TaxonomyTerms>. 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...
90
            ->one(self::getDb());
91
92
        return $parentTerm ? $parentTerm['term'] : null;
93
    }
94
95
    public function hasParent($term)
96
    {
97
        return $this->getParent($term) != null;
98
    }
99
100
    public function getChildren($term)
101
    {
102
        $parentTerm = $this->getTaxonomyTerm($term);
103
        if (!$parentTerm) {
104
            return [];
105
        }
106
107
        $query = (new Query())
108
            ->select('term')
109
            ->from(TaxonomyTerms::tableName())
110
            ->where("parent_id = $parentTerm->id");
111
112
        $result = [];
113
        foreach ($query->all(self::getDb()) as $row) {
114
            $result[] = $row['term'];
115
        }
116
117
        return $result;
118
    }
119
    
120
    public function hasChildren($term)
121
    {
122
        $parentTerm = $this->getTaxonomyTerm($term);
123
        if (!$parentTerm) {
124
            return false;
125
        }
126
        
127
        return (new Query())
128
            ->from(TaxonomyTerms::tableName())
129
            ->where("parent_id = $parentTerm->id")
130
            ->exists(self::getDb());
131
    }
132
}
133