Passed
Push — master ( 7050ea...169181 )
by Rougin
03:00
created

SelectQuery::get()   B

Complexity

Conditions 8
Paths 64

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 8.4444
c 0
b 0
f 0
cc 8
nc 64
nop 0
crap 8
1
<?php
2
3
namespace Rougin\Windstorm\Doctrine\Builder;
4
5
use Doctrine\DBAL\Platforms\AbstractPlatform;
6
use Doctrine\DBAL\Query\QueryException;
7
8
/**
9
 * Select Query
10
 *
11
 * @package Windstorm
12
 * @author  Rougin Gutib <[email protected]>
13
 */
14
class SelectQuery
15
{
16
    /**
17
     * @var array
18
     */
19
    protected $parts = array();
20
21
    /**
22
     * @var \Doctrine\DBAL\Platforms\AbstractPlatform
23
     */
24
    protected $platform;
25
26
    /**
27
     * @var integer|null
28
     */
29
    protected $max = null;
30
31
    /**
32
     * @var integer|null
33
     */
34
    protected $first = null;
35
36
    /**
37
     * Initializes the query instance.
38
     *
39
     * @param array                                     $parts
40
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
41
     * @param integer|null                              $max
42
     * @param integer|null                              $first
43
     */
44 96
    public function __construct($parts, AbstractPlatform $platform, $max, $first)
45
    {
46 96
        $this->parts = $parts;
47
48 96
        $this->platform = $platform;
49
50 96
        $this->max = $max;
51
52 96
        $this->first = $first;
53 96
    }
54
55
    /**
56
     * Returns the compiled SQL.
57
     *
58
     * @return string
59
     */
60 96
    public function get()
61
    {
62 96
        $query = 'SELECT ' . (string) implode(', ', (array) $this->parts['select']);
63
64 96
        $query .= $this->parts['from'] ? ' FROM ' . (string) implode(', ', $this->clauses()) : '';
65
66 96
        $query .= $this->parts['where'] !== null ? ' WHERE ' . $this->parts['where'] : '';
67
68 96
        $query .= $this->parts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->parts['groupBy']) : '';
69
70 96
        $query .= $this->parts['having'] !== null ? ' HAVING ' . $this->parts['having'] : '';
71
72 96
        $query .= $this->parts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->parts['orderBy']) : '';
73
74 96
        if ($this->max !== null || $this->first !== null)
75 96
        {
76 9
            return $this->platform->modifyLimitQuery($query, $this->max, $this->first);
77
        }
78
79 87
        return $query;
80
    }
81
82
    /**
83
     * Verifies and returns the clauses specified.
84
     *
85
     * @return string[]
86
     */
87 96
    protected function clauses()
88
    {
89 96
        list($aliases, $clauses) = array(array(), array());
90
91
        // Loop through all FROM clauses
92 96
        foreach ($this->parts['from'] as $from)
93
        {
94 96
            $sql = $reference = $from['table'];
95
96 96
            if ($from['alias'] !== null)
97 96
            {
98 96
                $sql = $from['table'] . ' ' . $from['alias'];
99
100 96
                $reference = (string) $from['alias'];
101 96
            }
102
103 96
            $aliases[$reference] = true;
104
105 96
            $clauses[$reference] = $sql . $this->joins($reference, $aliases);
106 96
        }
107
108 96
        $this->verify($aliases);
109
110 96
        return $clauses;
111
    }
112
113
    /**
114
     * Creates JOIN queries on specified tables.
115
     *
116
     * @param  string $alias
117
     * @param  array  $aliases
118
     * @return string
119
     * @throws \Doctrine\DBAL\Query\QueryException
120
     */
121 96
    protected function joins($alias, array &$aliases)
122
    {
123 96
        $sql = '';
124
125 96
        if (! isset($this->parts['join'][$alias]))
126 96
        {
127 96
            return $sql;
128
        }
129
130 9
        foreach ($this->parts['join'][$alias] as $join)
131
        {
132 9
            if (array_key_exists($join['joinAlias'], $aliases))
133 9
            {
134
                throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($aliases));
135
            }
136
137 9
            $sql .= ' ' . strtoupper($join['joinType']) . ' JOIN ' . $join['joinTable'];
138
139 9
            $sql .= ' ' . $join['joinAlias'] . ' ON ' . ((string) $join['joinCondition']);
140
141 9
            $aliases[$join['joinAlias']] = true;
142 9
        }
143
144 9
        foreach ($this->parts['join'][$alias] as $join)
145
        {
146 9
            $sql .= $this->joins($join['joinAlias'], $aliases);
147 9
        }
148
149 9
        return $sql;
150
    }
151
152
    /**
153
     * Verifies the specified aliases.
154
     *
155
     * @param  array $aliases
156
     * @throws \Doctrine\DBAL\Query\QueryException
157
     */
158 96
    protected function verify(array $aliases)
159
    {
160 96
        foreach ($this->parts['join'] as $alias => $joins)
161
        {
162 9
            if (! isset($aliases[$alias]))
163 9
            {
164
                throw QueryException::unknownAlias($alias, array_keys($aliases));
165
            }
166 96
        }
167 96
    }
168
}
169