Completed
Push — master ( 014e8e...109000 )
by Paweł
9s
created

Query::parseSelect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Xsolve\SalesforceClient\QueryBuilder;
4
5
use Xsolve\SalesforceClient\QueryBuilder\Expr\Compare\AbstractCompare;
6
use Xsolve\SalesforceClient\QueryBuilder\Expr\ExprInterface;
7
use Xsolve\SalesforceClient\QueryBuilder\Expr\From\AbstractFrom;
8
use Xsolve\SalesforceClient\QueryBuilder\Expr\GroupBy\AbstractGroupBy;
9
use Xsolve\SalesforceClient\QueryBuilder\Expr\OrderBy\AbstractOrderBy;
10
use Xsolve\SalesforceClient\QueryBuilder\Expr\Select\AbstractSelect;
11
use Xsolve\SalesforceClient\QueryBuilder\Visitor\Parameters\ParametersReplacingVisitor;
12
use Xsolve\SalesforceClient\QueryBuilder\Visitor\VisiteeInterface;
13
use Xsolve\SalesforceClient\QueryBuilder\Visitor\VisitorInterface;
14
15
class Query
16
{
17
    /**
18
     * @var AbstractSelect[]
19
     */
20
    private $selects = [];
21
22
    /**
23
     * @var AbstractFrom|null
24
     */
25
    private $from;
26
27
    /**
28
     * @var AbstractCompare|null
29
     */
30
    private $where;
31
32
    /**
33
     * @var AbstractGroupBy|null
34
     */
35
    private $groupBy;
36
37
    /**
38
     * @var AbstractCompare|null
39
     */
40
    private $having;
41
42
    /**
43
     * @var AbstractOrderBy|null
44
     */
45
    private $orderBy;
46
47
    /**
48
     * @var int|null
49
     */
50
    private $limit;
51
52
    /**
53
     * @var int|null
54
     */
55
    private $offset;
56
57
    /**
58
     * @var VisitorInterface[]
59
     */
60
    private $visitors;
61
62
    /**
63
     * @param VisitorInterface[] $visitors
64
     */
65 53
    public function __construct(array $visitors = [])
66
    {
67 53
        $this->visitors = $visitors;
68 53
    }
69
70 53
    public function addSelect(AbstractSelect $select)
71
    {
72 53
        $this->selects[] = $select;
73 53
    }
74
75 53
    public function setFrom(AbstractFrom $from)
76
    {
77 53
        $this->from = $from;
78 53
    }
79
80 19
    public function setWhere(AbstractCompare $where)
81
    {
82 19
        $this->where = $where;
83 19
    }
84
85 4
    public function setGroupBy(AbstractGroupBy $groupBy)
86
    {
87 4
        $this->groupBy = $groupBy;
88 4
    }
89
90 19
    public function setHaving(AbstractCompare $having)
91
    {
92 19
        $this->having = $having;
93 19
    }
94
95
    /**
96
     * @return AbstractCompare|null
97
     */
98 1
    public function getWhere()
99
    {
100 1
        return $this->where;
101
    }
102
103
    /**
104
     * @return AbstractCompare|null
105
     */
106 1
    public function getHaving()
107
    {
108 1
        return $this->having;
109
    }
110
111 4
    public function setOrderBy(AbstractOrderBy $orderBy)
112
    {
113 4
        $this->orderBy = $orderBy;
114 4
    }
115
116 2
    public function setLimit(int $limit)
117
    {
118 2
        $this->limit = $limit;
119 2
    }
120
121 2
    public function setOffset(int $offset)
122
    {
123 2
        $this->offset = $offset;
124 2
    }
125
126 19
    public function setParameters(array $parameters)
127
    {
128 19
        $this->visitors[] = new ParametersReplacingVisitor($parameters);
129 19
    }
130
131 53
    public function parse(): string
132
    {
133 53
        $this->validate();
134 53
        $this->visitQueryParts();
135
136 53
        return $this->parseSelect()
137 53
            .$this->parseWhere()
138 53
            .$this->parseGroupBy()
139 53
            .$this->parseHaving()
140 53
            .$this->parseOrderBy()
141 53
            .$this->parseLimit()
142 53
            .$this->parseOffset();
143
    }
144
145 53
    private function validate()
146
    {
147 53
        if (empty($this->selects) || null === $this->from) {
148
            throw new \LogicException('At least SELECT and FROM must be defined');
149
        }
150 53
    }
151
152 53
    private function visitQueryParts()
153
    {
154 53
        foreach ($this->visitors as $visitor) {
155 19
            foreach ($this->getQueryParts() as $queryPart) {
156 19
                if ($queryPart instanceof VisiteeInterface) {
157 19
                    $queryPart->accept($visitor);
158
                }
159
            }
160
        }
161 53
    }
162
163
    /**
164
     * @return ExprInterface[]
165
     */
166 19
    private function getQueryParts(): array
167
    {
168 19
        return array_merge(
169 19
            $this->selects,
170 19
            [$this->from],
171 19
            [$this->where],
172 19
            [$this->groupBy],
173 19
            [$this->having],
174 19
            [$this->orderBy]
175
        );
176
    }
177
178 53
    private function parseSelect(): string
179
    {
180 53
        $selects = implode(', ', array_map(
181 53
            function (AbstractSelect $select): string {
182 53
                return $select->asSOQL();
183 53
            },
184 53
            $this->selects
185
        ));
186
187 53
        return sprintf('SELECT %s FROM %s', $selects, $this->from->asSOQL());
188
    }
189
190 53
    private function parseWhere(): string
191
    {
192 53
        if (!$this->where) {
193 35
            return '';
194
        }
195
196 19
        return sprintf(' WHERE %s', $this->where->asSOQL());
197
    }
198
199 53
    private function parseGroupBy(): string
200
    {
201 53
        if (!$this->groupBy) {
202 50
            return '';
203
        }
204
205 4
        return sprintf(' GROUP BY %s', $this->groupBy->asSOQL());
206
    }
207
208 53
    private function parseHaving(): string
209
    {
210 53
        if (!$this->having) {
211 35
            return '';
212
        }
213
214 19
        return sprintf(' HAVING %s', $this->having->asSOQL());
215
    }
216
217 53
    private function parseOrderBy(): string
218
    {
219 53
        if (!$this->orderBy) {
220 50
            return '';
221
        }
222
223 4
        return sprintf(' ORDER BY %s', $this->orderBy->asSOQL());
224
    }
225
226 53
    private function parseLimit(): string
227
    {
228 53
        if (!is_int($this->limit)) {
229 52
            return '';
230
        }
231
232 2
        return sprintf(' LIMIT %d', $this->limit);
233
    }
234
235 53
    private function parseOffset(): string
236
    {
237 53
        if (!is_int($this->offset)) {
238 52
            return '';
239
        }
240
241 2
        return sprintf(' OFFSET %d', $this->offset);
242
    }
243
}
244