Passed
Push — master ( a14668...23f3c2 )
by Rougin
02:42
created

SelectQuery::joins()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 24
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

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