Completed
Push — master ( fb652a...5a44ae )
by Stéphane
13:32
created

Taxonomy/Repositories/TermHierarchyRepository.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php namespace Rocket\Taxonomy\Repositories;
2
3
use CentralDesktop\Graph\Graph\DirectedGraph;
4
use CentralDesktop\Graph\Vertex;
5
use Illuminate\Support\Facades\DB;
6
use Rocket\Taxonomy\Model\Hierarchy;
7
use Rocket\Taxonomy\Utils\CommonTableExpressionQuery;
8
use Rocket\Taxonomy\Utils\PathResolver;
9
use Rocket\Taxonomy\Utils\RecursiveQuery;
10
11
/**
12
 * Create paths from a term all the way to all the parents.
13
 *
14
 * Everything is calculated upside down so that the DFS search for all paths is easy
15
 */
16
class TermHierarchyRepository implements TermHierarchyRepositoryInterface
17
{
18
    /**
19
     * @var array<Vertex> all Vertices (Current and parents)
20
     */
21
    protected $vertices;
22
23
    /**
24
     * @var \Illuminate\Cache\Repository
25
     */
26
    protected $cache;
27
28
    /**
29
     * @param \Illuminate\Cache\Repository $cache
30
     */
31 192
    public function __construct(\Illuminate\Cache\Repository $cache)
32
    {
33 192
        $this->cache = $cache;
34 192
    }
35
36
    /**
37
     * @param int $term_id
38
     * @param int $parent_id
39
     * @return bool
40
     */
41 111
    public function addParent($term_id, $parent_id)
42
    {
43 111
        return Hierarchy::insert(['term_id' => $term_id, 'parent_id' => $parent_id]);
0 ignored issues
show
The method insert() does not exist on Rocket\Taxonomy\Model\Hierarchy. Did you maybe mean insertAndSetId()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
44
    }
45
46
    /**
47
     * @param int $term_id
48
     * @return bool
49
     */
50 6
    public function unsetParents($term_id)
51
    {
52 6
        return Hierarchy::where('term_id', $term_id)->delete();
53
    }
54
55 9
    protected function supportsCommonTableExpressionQuery()
56
    {
57 9
        $driver = DB::connection()->getDriverName();
58
59 9
        if ($driver == 'mysql') {
60 3
            return true;
61
        }
62
63 6
        if ($driver == 'sqlite' && \SQLite3::version()['versionNumber'] >= 3008003) {
64 3
            return true;
65
        }
66
67 3
        return false;
68
    }
69
70
    /**
71
     * @return \Rocket\Taxonomy\Utils\RecursiveQueryInterface
72
     */
73 9
    protected function getRecursiveRetriever()
74 3
    {
75 9
        if ($this->supportsCommonTableExpressionQuery()) {
76 6
            return new CommonTableExpressionQuery();
77
        }
78
79 3
        return new RecursiveQuery();
80
    }
81
82
    /**
83
     * Get the hierarchy cache key
84
     *
85
     * @param string $direction
86
     * @param int $id
87
     * @return string
88
     */
89 12
    protected function getCacheKey($direction, $id)
90
    {
91 12
        return "Rocket::Taxonomy::TermHierarchy::$direction::$id";
92
    }
93
94
    /**
95
     * Get all parents recursively
96
     *
97
     * @param int $id
98
     * @return \Illuminate\Support\Collection
99
     */
100 12
    public function getAncestry($id)
101
    {
102 12
        $key = $this->getCacheKey('ancestry', $id);
103 12
        if ($results = $this->cache->get($key)) {
104 4
            return $results;
105
        }
106
107 9
        $this->cache->add($key, $results = $this->getRecursiveRetriever()->getAncestry($id), 2);
108
109 9
        return $results;
110
    }
111
112
    /**
113
     * Get all childs recursively
114
     *
115
     * @param int $id
116
     * @return \Illuminate\Support\Collection
117
     */
118 12
    public function getDescent($id)
119
    {
120 12
        $key = $this->getCacheKey('descent', $id);
121 12
        if ($results = $this->cache->get($key)) {
122 4
            return $results;
123
        }
124
125 9
        $this->cache->add($key, $results = $this->getRecursiveRetriever()->getDescent($id), 2);
126
127 9
        return $results;
128
    }
129
130
    /**
131
     * @param \Illuminate\Support\Collection $data
132
     * @return array<Vertex>
133
     */
134 9
    protected function prepareVertices($data)
135
    {
136 9
        $vertices = [];
137 9
        foreach ($data as $content) {
138
            // identifiers must be strings or SplObjectStorage::contains fails
139
            // seems to impact only PHP 5.6
140 9
            $content->term_id = "$content->term_id";
141 9
            $content->parent_id = "$content->parent_id";
142
143 9
            if (!array_key_exists($content->term_id, $vertices)) {
144 9
                $vertices[$content->term_id] = new Vertex($content->term_id);
145 9
            }
146
147 9
            if (!array_key_exists($content->parent_id, $vertices)) {
148 9
                $vertices[$content->parent_id] = new Vertex($content->parent_id);
149 9
            }
150 9
        }
151
152 9
        return $vertices;
153
    }
154
155
    /**
156
     * Get all parents recursively
157
     *
158
     * @return array Vertex, DirectedGraph
159
     */
160 12
    public function getAncestryGraph($id)
161
    {
162 12
        $data = $this->getAncestry($id);
163
164 12
        if (count($data) == 0) {
165 3
            return [null, null];
166
        }
167
168
        // Create Vertices
169 9
        $this->vertices = $this->prepareVertices($data);
170
171
        // Create Graph
172 9
        $graph = new DirectedGraph();
173 9
        foreach ($this->vertices as $vertex) {
174 9
            $graph->add_vertex($vertex);
175 9
        }
176
177
        // Create Relations
178 9
        foreach ($data as $content) {
179 9
            $graph->create_edge($this->vertices[$content->parent_id], $this->vertices[$content->term_id]);
180 9
        }
181
182 9
        return [$this->vertices[$id], $graph];
183
    }
184
185
    /**
186
     * Get all childs recursively
187
     *
188
     * @return array Vertex, DirectedGraph
189
     */
190 12
    public function getDescentGraph($id)
191
    {
192 12
        $data = $this->getDescent($id);
193
194 12
        if (count($data) == 0) {
195 3
            return [null, null];
196
        }
197
198
        // Create Vertices
199 9
        $this->vertices = $this->prepareVertices($data);
200
201
        // Create Graph
202 9
        $graph = new DirectedGraph();
203 9
        foreach ($this->vertices as $vertex) {
204 9
            $graph->add_vertex($vertex);
205 9
        }
206
207
        // Create Relations
208 9
        foreach ($data as $content) {
209 9
            $graph->create_edge($this->vertices[$content->term_id], $this->vertices[$content->parent_id]);
210 9
        }
211
212 9
        return [$this->vertices[$id], $graph];
213
    }
214
215
    /**
216
     * Get all the possible paths from this term
217
     *
218
     * @return array<array<int>>
219
     */
220 12
    public function getAncestryPaths($id)
221
    {
222 12
        list($start_vertex, $graph) = $this->getAncestryGraph($id);
223
224 12
        if (!$graph) {
225 3
            return [];
226
        }
227
228 9
        $resolver = new PathResolver($graph);
229
230 9
        return $resolver->resolvePaths($start_vertex);
231
    }
232
233
    /**
234
     * Get all the possible paths from this term
235
     *
236
     * @return array<array<int>>
237
     */
238 12
    public function getDescentPaths($id)
239
    {
240 12
        list($start_vertex, $graph) = $this->getDescentGraph($id);
241
242 12
        if (!$graph) {
243 3
            return [];
244
        }
245
246 9
        $resolver = new PathResolver($graph);
247
248 9
        return $resolver->resolvePaths($start_vertex);
249
    }
250
}
251