Completed
Push — master ( 488702...18fedf )
by Stéphane
22:05
created

TaxonomyTrait::getTaxonomyQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 9.4285
1
<?php
2
3
/**
4
 * Trait used to give Taxonomy abilities to another model.
5
 */
6
namespace Rocket\Taxonomy;
7
8
use Illuminate\Database\Eloquent\Builder;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Facades\Cache;
11
use Rocket\Taxonomy\Model\TermContainer;
12
use Rocket\Taxonomy\Support\Laravel5\Facade as T;
13
14
/**
15
 * This class is the link between a content and its taxonomies
16
 *
17
 * Including this trait in your model will enable it
18
 * to add and remove taxonomies from any vocabulary
19
 */
20
trait TaxonomyTrait
21
{
22
    /**
23
     * Define a polymorphic many-to-many relationship.
24
     *
25
     * @param  string  $related
26
     * @param  string  $name
27
     * @param  string  $table
28
     * @param  string  $foreignPivotKey
29
     * @param  string  $relatedPivotKey
30
     * @param  string  $parentKey
31
     * @param  string  $relatedKey
32
     * @param  bool  $inverse
33
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
34
     */
35
    abstract public function morphToMany(
36
        $related,
37
        $name,
38
        $table = null,
39
        $foreignPivotKey = null,
40
        $relatedPivotKey = null,
41
        $parentKey = null,
42
        $relatedKey = null,
43
        $inverse = false
44
    );
45
46
    /**
47
     * Declared by Eloquent Model
48
     */
49
    abstract public function getTable();
50
51
    /**
52
     * Declared by Eloquent Model
53
     */
54
    abstract public function getKey();
55
56
    /**
57 24
     * The relation configuration
58
     *
59 24
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
60
     */
61 24
    public function taxonomies()
62
    {
63
        return $this->morphToMany(Model\TermContainer::class, 'relationable', 'taxonomy_content', null, 'term_id');
64
    }
65
66
    /**
67
     * Filter the model to return a subset of entries matching the term ID
68
     *
69
     * @param Builder $query
70
     * @param int $term_id
71
     *
72 3
     * @return Builder
73
     */
74
    public function scopeGetAllByTermId(Builder $query, $term_id)
75 3
    {
76 3
        return $query->whereHas('taxonomies', function (Builder $q) use ($term_id) {
77
            $q->where('term_id', $term_id);
78
        });
79
    }
80
81
    /**
82
     * Get the terms from a content
83
     *
84
     * @param  int|string $vocabulary_id
85 6
     * @return Collection
86
     */
87 6
    public function getTerms($vocabulary_id)
88 6
    {
89 6
        if (!$data = Cache::get($this->getTaxonomyCacheKey())) {
90
            $data = $this->cacheTermsForContent();
91 6
        }
92 6
93 6
        if (!is_numeric($vocabulary_id)) {
94
            $vocabulary_id = T::vocabulary($vocabulary_id);
95 6
        }
96 6
97 3
        $results = new Collection();
98 3
        if (array_key_exists($vocabulary_id, $data)) {
99 3
            foreach ($data[$vocabulary_id] as $term) {
100 3
                $results[] = T::getTerm($term);
101
            }
102 6
        }
103
104
        return $results;
105
    }
106
107
    /**
108
     * Link a term to this content
109
     *
110 27
     * @param int $term_id
111
     */
112 27
    public function addTerm($term_id)
113
    {
114
        TermContainer::findOrFail($term_id);
115 24
116 3
        // Cancel if the user wants to add the same term again
117
        if ($this->taxonomies()->where('term_id', $term_id)->count()) {
118
            return;
119 24
        }
120
121 24
        $this->taxonomies()->attach($term_id);
122 24
123
        Cache::forget($this->getTaxonomyCacheKey());
124
    }
125
126
    /**
127
     * Set the terms to a content, removes the old ones (only for one vocabulary if specified)
128
     *
129
     * @param array<integer> $terms
130 24
     * @param int|string $vocabulary_id
131
     */
132 24
    public function setTerms($terms, $vocabulary_id = null)
133
    {
134 24
        $this->removeTerms($vocabulary_id);
135 24
136 24
        foreach ($terms as $term_id) {
137 24
            $this->addTerm($term_id);
138
        }
139
    }
140
141
    /**
142
     * Removes terms specified by a vocabulary, or all
143
     *
144
     * @param int|string $vocabulary_id
145 24
     * @return bool
146
     */
147 24
    public function removeTerms($vocabulary_id = null)
148 24
    {
149
        if ($vocabulary_id === null) {
150
            return $this->taxonomies()->detach();
151 3
        }
152 3
153 3
        if (!is_numeric($vocabulary_id)) {
154
            $vocabulary_id = T::vocabulary($vocabulary_id);
155 3
        }
156 3
157 3
        return $this->taxonomies()->detach(TermContainer::where('vocabulary_id', $vocabulary_id)->pluck('id'));
158
    }
159
160
    /**
161
     * Cache all terms of a content (only ids)
162
     *
163
     * @return array
164
     */
165 6
    private function cacheTermsForContent()
166
    {
167 6
        $term_container = (new TermContainer)->getTable();
168 6
        $terms = $this->taxonomies()
169 6
            ->select("$term_container.id", "$term_container.vocabulary_id")
170 6
            ->get();
171
172 6
        if (!count($terms)) {
173 3
            return [];
174
        }
175
176 3
        $results = [];
177 3
        foreach ($terms as $term) {
178 3
            $results[$term->vocabulary_id][] = $term->id;
179 3
        }
180
181
        // a whole week, because it's automatically recached
182 3
        Cache::put($this->getTaxonomyCacheKey(), $results, 60 * 24 * 7);
183
184 3
        return $results;
185
    }
186
187
    /**
188
     * Get the cache key for this content
189
     *
190
     * @return string
191
     */
192 24
    private function getTaxonomyCacheKey()
193
    {
194 24
        return 'Rocket::Taxonomy::Related::' . $this->getTable() . '::' . $this->getKey();
195
    }
196
}
197