CommonTableExpressionQuery   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 78
ccs 23
cts 23
cp 1
rs 10
wmc 5
lcom 1
cbo 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
A runQuery() 0 14 1
A assembleQuery() 0 13 2
A getAncestry() 0 9 1
A getDescent() 0 9 1
1
<?php
2
3
/**
4
 * This class will use the Common Table Expression
5
 * technique to make a recursive request on the database.
6
 * On mysql it will fallback to a stored procedure doing the same.
7
 *
8
 * The choice of a Common Table Expression or a standard query is done automatically
9
 */
10
namespace Rocket\Taxonomy\Utils;
11
12
use Illuminate\Support\Facades\DB;
13
14
/**
15
 * Class using the DB's internal Recursive query mechanism to query term hierarchies.
16
 */
17
class CommonTableExpressionQuery extends RecursiveQuery implements RecursiveQueryInterface
18
{
19
    /**
20
     * Execute the query with the current PDO connection.
21
     * Will log the time taken manually
22
     *
23
     * @param string $raw_query
24
     * @param int $id
25
     * @return \Illuminate\Support\Collection
26
     */
27 54
    protected function runQuery($raw_query, $id)
28
    {
29 54
        $query = str_replace(':id', $id, $raw_query);
30
31 54
        $start = microtime(true);
32
33
        // Does not work as a prepared statement; we have to execute it directly
34 54
        $results = DB::getReadPdo()->query($query)->fetchAll(\PDO::FETCH_OBJ);
35
36
        // Log the query manually
37 54
        DB::logQuery($raw_query, [$id], round((microtime(true) - $start) * 1000, 2));
38
39 54
        return $results;
40
    }
41
42
    /**
43
     * Prepare the complete query to run on the DB to get the data recursively.
44
     *
45
     * @param string $initial The initial query bootstrapping the recursive query
46
     * @param string $recursive The query to dig deeper in the hierarchy
47
     * @return string
48
     */
49 54
    protected function assembleQuery($initial, $recursive)
50
    {
51 54
        $tmp_tbl = 'name_tree';
52 54
        $recursive = str_replace(':tmp_tbl', $tmp_tbl, $recursive);
53
54 54
        $final = "select distinct * from $tmp_tbl";
55
56 54
        if (DB::connection()->getDriverName() == 'mysql') {
57 19
            return "Call WITH_EMULATOR('$tmp_tbl', '$initial', '$recursive', '$final', 0, 'ENGINE=MEMORY');";
58
        }
59
60 35
        return "WITH RECURSIVE $tmp_tbl AS ($initial UNION ALL $recursive) $final;";
61
    }
62
63
    /**
64
     * Get all ancestors of a term
65
     *
66
     * @param int $id The term ID
67
     * @return \Illuminate\Support\Collection
68
     */
69 30
    public function getAncestry($id)
70
    {
71 30
        $tbl = $this->hierarchyTable;
72 30
        $recursive = "SELECT c.term_id, c.parent_id from $tbl as c join :tmp_tbl as p on p.parent_id = c.term_id";
73
74 30
        $raw_query = $this->assembleQuery($this->getAncestryInitialQuery(), $recursive);
75
76 30
        return $this->runQuery($raw_query, $id);
77
    }
78
79
    /**
80
     * Get all descendants of a term.
81
     *
82
     * @param int $id The term ID
83
     * @return \Illuminate\Support\Collection
84
     */
85 30
    public function getDescent($id)
86
    {
87 30
        $tbl = $this->hierarchyTable;
88 30
        $recursive = "SELECT c.term_id, c.parent_id from $tbl as c join :tmp_tbl as p on c.parent_id = p.term_id";
89
90 30
        $raw_query = $this->assembleQuery($this->getDescentInitialQuery(), $recursive);
91
92 30
        return $this->runQuery($raw_query, $id);
93
    }
94
}
95