Passed
Push — master ( f0e277...a14668 )
by Rougin
03:58
created

SelectQuery::get()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 22
rs 9.6111
c 0
b 0
f 0
ccs 11
cts 11
cp 1
cc 5
nc 8
nop 0
crap 5
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 99
    public function __construct($parts, AbstractPlatform $platform, $max, $first)
45
    {
46 99
        $this->parts = $parts;
47
48 99
        $this->platform = $platform;
49
50 99
        $this->max = $max;
51
52 99
        $this->first = $first;
53 99
    }
54
55
    /**
56
     * Returns the compiled SQL.
57
     *
58
     * @return string
59
     */
60 99
    public function get()
61
    {
62 99
        $query = 'SELECT ' . (string) implode(', ', (array) $this->parts['select']);
63
64 99
        if ($this->parts['from'])
65
        {
66 99
            $query .= ' FROM ' . (string) implode(', ', $this->clauses());
67
        }
68 99
69
        if ($this->parts['where'] !== null)
70 99
        {
71
            $query .= ' WHERE ' . $this->parts['where'];
72 99
        }
73
74 99
        $query .= $this->group();
75 99
76 9
        if ($this->max !== null || $this->first !== null)
77
        {
78
            return $this->platform->modifyLimitQuery($query, $this->max, $this->first);
79 90
        }
80
81
        return $query;
82
    }
83
84
    /**
85
     * Verifies and returns the clauses specified.
86
     *
87 99
     * @return string[]
88
     */
89 99
    protected function clauses()
90
    {
91
        list($aliases, $clauses) = array(array(), array());
92 99
93
        // Loop through all FROM clauses
94 99
        foreach ($this->parts['from'] as $from)
95
        {
96 99
            $sql = $reference = $from['table'];
97 99
98 12
            if ($from['alias'] !== null)
99
            {
100 12
                $sql = $from['table'] . ' ' . $from['alias'];
101 12
102
                $reference = (string) $from['alias'];
103 99
            }
104
105 99
            $aliases[$reference] = true;
106 99
107
            $clauses[$reference] = $sql . $this->joins($reference, $aliases);
108 99
        }
109
110 99
        $this->verify($aliases);
111
112
        return $clauses;
113
    }
114
115
    /**
116
     * Returns the query for GROUP BY, HAVING, and ORDER BY.
117
     *
118
     * @return string
119
     */
120
    protected function group()
121 99
    {
122
        $query = '';
123 99
124
        if ($this->parts['groupBy'])
125 99
        {
126 99
            $query .= ' GROUP BY ' . implode(', ', $this->parts['groupBy']);
127 99
        }
128
129
        if ($this->parts['having'] !== null)
130 9
        {
131
            $query .= ' HAVING ' . $this->parts['having'];
132 9
        }
133 9
134
        if ($this->parts['orderBy'])
135
        {
136
            $query .= ' ORDER BY ' . implode(', ', $this->parts['orderBy']);
137 9
        }
138
139 9
        return $query;
140
    }
141 9
142 9
    /**
143
     * Creates JOIN queries on specified tables.
144 9
     *
145
     * @param  string $alias
146 9
     * @param  array  $aliases
147 9
     * @return string
148
     * @throws \Doctrine\DBAL\Query\QueryException
149 9
     */
150
    protected function joins($alias, array &$aliases)
151
    {
152
        $sql = '';
153
154
        if (! isset($this->parts['join'][$alias]))
155
        {
156
            return $sql;
157
        }
158 99
159
        foreach ($this->parts['join'][$alias] as $join)
160 99
        {
161
            $sql .= ' ' . strtoupper($join['joinType']) . ' JOIN ' . $join['joinTable'];
162 9
163 9
            $sql .= ' ' . $join['joinAlias'] . ' ON ' . ((string) $join['joinCondition']);
164
165
            $aliases[$join['joinAlias']] = true;
166 99
        }
167 99
168
        foreach ($this->parts['join'][$alias] as $join)
169
        {
170
            $sql .= $this->joins($join['joinAlias'], $aliases);
171
        }
172
173
        return $sql;
174
    }
175
176
    /**
177
     * Verifies the specified aliases.
178
     *
179
     * @param  array $aliases
180
     * @throws \Doctrine\DBAL\Query\QueryException
181
     */
182
    protected function verify(array $aliases)
183
    {
184
        foreach ($this->parts['join'] as $alias => $joins)
185
        {
186
            if (! isset($aliases[$alias]))
187
            {
188
                throw QueryException::unknownAlias($alias, array_keys($aliases));
189
            }
190
        }
191
    }
192
}
193