SelectWriter::writeSelectOrderBy()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 20
c 1
b 0
f 1
rs 9.4286
cc 2
eloc 12
nc 2
nop 2
1
<?php
2
/**
3
 * Author: Nil Portugués Calderó <[email protected]>
4
 * Date: 6/11/14
5
 * Time: 1:50 AM.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace NilPortugues\Sql\QueryBuilder\Builder\Syntax;
12
13
use NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder;
14
use NilPortugues\Sql\QueryBuilder\Manipulation\Select;
15
use NilPortugues\Sql\QueryBuilder\Syntax\Column;
16
use NilPortugues\Sql\QueryBuilder\Syntax\OrderBy;
17
use NilPortugues\Sql\QueryBuilder\Syntax\SyntaxFactory;
18
19
/**
20
 * Class SelectWriter.
21
 */
22
class SelectWriter extends AbstractBaseWriter
23
{
24
    /**
25
     * @param        $alias
26
     * @param Select $select
27
     *
28
     * @return Column
29
     */
30
    public function selectToColumn($alias, Select $select)
31
    {
32
        $selectAsColumn = $this->write($select);
33
34
        if (!empty($selectAsColumn)) {
35
            $selectAsColumn = '('.$selectAsColumn.')';
36
        }
37
38
        $column = array($alias => $selectAsColumn);
39
40
        return SyntaxFactory::createColumn($column, null);
41
    }
42
43
    /**
44
     * @param Select $select
45
     *
46
     * @return string
47
     */
48
    public function write(Select $select)
49
    {
50
        if ($select->isJoinSelect()) {
51
            return $this->writer->writeJoin($select);
52
        }
53
54
        return $this->writeSelectQuery($select);
55
    }
56
57
    /**
58
     * @param Select $select
59
     *
60
     * @return string
61
     */
62
    protected function writeSelectQuery(Select $select)
63
    {
64
        $parts = ['SELECT'];
65
66
        if ($select->isDistinct()) {
67
            $parts[] = 'DISTINCT';
68
        }
69
70
        $this->writeSelectColumns($select, $parts);
71
        $this->writeSelectFrom($select, $parts);
72
        $this->writeSelectJoins($select, $parts);
73
        $this->writeSelectWhere($select, $parts);
74
        $this->writeSelectGroupBy($select, $parts);
75
        $this->writeSelectHaving($select, $parts);
76
        $this->writeSelectOrderBy($select, $parts);
77
        $this->writeSelectLimit($select, $parts);
78
79
        return AbstractBaseWriter::writeQueryComment($select).implode(' ', \array_filter($parts));
80
    }
81
82
    /**
83
     * @param Select   $select
84
     * @param string[] $parts
85
     *
86
     * @return $this
87
     */
88
    public function writeSelectColumns(Select $select, array &$parts)
89
    {
90
        if ($select->isCount() === false) {
91
            $columns = $this->writeColumnAlias(
92
                $select->getAllColumns(),
93
                $this->columnWriter->writeSelectsAsColumns($select),
94
                $this->columnWriter->writeValueAsColumns($select),
95
                $this->columnWriter->writeFuncAsColumns($select)
96
            );
97
98
            $parts = \array_merge($parts, [implode(', ', $columns)]);
99
100
            return $this;
101
        }
102
103
        $columns = $select->getColumns();
104
        $column = \array_pop($columns);
105
        $columnList = $column->getName();
106
107
        $parts = \array_merge($parts, [$columnList]);
108
109
        return $this;
110
    }
111
112
    /**
113
     * @param $tableColumns
114
     * @param $selectAsColumns
115
     * @param $valueAsColumns
116
     * @param $funcAsColumns
117
     *
118
     * @return array
119
     */
120
    protected function writeColumnAlias($tableColumns, $selectAsColumns, $valueAsColumns, $funcAsColumns)
121
    {
122
        $columns = \array_merge($tableColumns, $selectAsColumns, $valueAsColumns, $funcAsColumns);
123
124
        \array_walk(
125
            $columns,
126
            function (&$column) {
127
                $column = $this->columnWriter->writeColumnWithAlias($column);
128
            }
129
        );
130
131
        return $columns;
132
    }
133
134
    /**
135
     * @param Select   $select
136
     * @param string[] $parts
137
     *
138
     * @return $this
139
     */
140
    public function writeSelectFrom(Select $select, array &$parts)
141
    {
142
        $parts = \array_merge(
143
            $parts,
144
            ['FROM '.$this->writer->writeTableWithAlias($select->getTable())]
145
        );
146
147
        return $this;
148
    }
149
150
    /**
151
     * @param Select $select
152
     * @param array  $parts
153
     *
154
     * @return $this
155
     */
156
    public function writeSelectJoins(Select $select, array &$parts)
157
    {
158
        $parts = \array_merge(
159
            $parts,
160
            [$this->writeSelectAggrupation($select, $this->writer, 'getAllJoins', 'writeJoin', ' ')]
161
        );
162
163
        return $this;
164
    }
165
166
    /**
167
     * @param Select $select
168
     * @param        $writer
169
     * @param string $getMethod
170
     * @param string $writeMethod
171
     * @param string $glue
172
     * @param string $prepend
173
     *
174
     * @return string
175
     */
176
    protected function writeSelectAggrupation(Select $select, $writer, $getMethod, $writeMethod, $glue, $prepend = '')
177
    {
178
        $str = '';
179
        $joins = $select->$getMethod();
180
181
        if (!empty($joins)) {
182
            \array_walk(
183
                $joins,
184
                function (&$join) use ($writer, $writeMethod) {
185
                    $join = $writer->$writeMethod($join);
186
                }
187
            );
188
189
            $str = $prepend.implode($glue, $joins);
190
        }
191
192
        return $str;
193
    }
194
195
    /**
196
     * @param Select $select
197
     * @param array  $parts
198
     *
199
     * @return $this
200
     */
201
    public function writeSelectWhere(Select $select, array &$parts)
202
    {
203
        $str = '';
204
        $wheres = $this->writeSelectWheres($select->getAllWheres());
205
        $wheres = \array_filter($wheres);
206
207
        if (\count($wheres) > 0) {
208
            $str = 'WHERE ';
209
            $separator = ' '.$this->writer->writeConjunction($select->getWhereOperator()).' ';
210
211
            $str .= \implode($separator, $wheres);
212
        }
213
214
        $parts = \array_merge($parts, [$str]);
215
216
        return $this;
217
    }
218
219
    /**
220
     * @param array $wheres
221
     *
222
     * @return array
223
     */
224
    protected function writeSelectWheres(array $wheres)
225
    {
226
        $whereWriter = WriterFactory::createWhereWriter($this->writer, $this->placeholderWriter);
227
228
        \array_walk(
229
            $wheres,
230
            function (&$where) use (&$whereWriter) {
231
232
                $where = $whereWriter->writeWhere($where);
233
            }
234
        );
235
236
        return $wheres;
237
    }
238
239
    /**
240
     * @param Select $select
241
     * @param array  $parts
242
     *
243
     * @return $this
244
     */
245
    public function writeSelectGroupBy(Select $select, array &$parts)
246
    {
247
        $groupBy = $this->writeSelectAggrupation(
248
            $select,
249
            $this->columnWriter,
250
            'getGroupBy',
251
            'writeColumn',
252
            ', ',
253
            'GROUP BY '
254
        );
255
256
        $parts = \array_merge($parts, [$groupBy]);
257
258
        return $this;
259
    }
260
261
    /**
262
     * @param Select $select
263
     * @param array  $parts
264
     *
265
     * @return $this
266
     */
267
    public function writeSelectHaving(Select $select, array &$parts)
268
    {
269
        $str = '';
270
        $havingArray = $select->getAllHavings();
271
272
        if (\count($havingArray) > 0) {
273
            $placeholder = $this->placeholderWriter;
274
            $writer = $this->writer;
275
276
            $str = 'HAVING ';
277
            $separator = ' '.$select->getHavingOperator().' ';
278
            $havingArray = $this->getHavingConditions($havingArray, $select, $writer, $placeholder);
279
280
            $str .= \implode($separator, $havingArray);
281
        }
282
283
        $parts = \array_merge($parts, [$str]);
284
285
        return $this;
286
    }
287
288
    /**
289
     * @param array             $havingArray
290
     * @param Select            $select
291
     * @param GenericBuilder    $writer
292
     * @param PlaceholderWriter $placeholder
293
     *
294
     * @return mixed
295
     */
296
    protected function getHavingConditions(
297
        array &$havingArray,
298
        Select $select,
299
        GenericBuilder $writer,
300
        PlaceholderWriter $placeholder
301
    ) {
302
        \array_walk(
303
            $havingArray,
304
            function (&$having) use ($select, $writer, $placeholder) {
305
306
                $whereWriter = WriterFactory::createWhereWriter($writer, $placeholder);
307
                $clauses = $whereWriter->writeWhereClauses($having);
308
                $having = \implode($this->writer->writeConjunction($select->getHavingOperator()), $clauses);
309
            }
310
        );
311
312
        return $havingArray;
313
    }
314
315
    /**
316
     * @param Select $select
317
     * @param array  $parts
318
     *
319
     * @return $this
320
     */
321
    protected function writeSelectOrderBy(Select $select, array &$parts)
322
    {
323
        $str = '';
324
        if (\count($select->getAllOrderBy())) {
325
            $orderByArray = $select->getAllOrderBy();
326
            \array_walk(
327
                $orderByArray,
328
                function (&$orderBy) {
329
                    $orderBy = $this->writeOrderBy($orderBy);
330
                }
331
            );
332
333
            $str = 'ORDER BY ';
334
            $str .= \implode(', ', $orderByArray);
335
        }
336
337
        $parts = \array_merge($parts, [$str]);
338
339
        return $this;
340
    }
341
342
    /**
343
     * @param OrderBy $orderBy
344
     *
345
     * @return string
346
     */
347
    public function writeOrderBy(OrderBy $orderBy)
348
    {
349
        $column = $this->columnWriter->writeColumn($orderBy->getColumn());
350
351
        return $column.' '.$orderBy->getDirection();
352
    }
353
354
    /**
355
     * @param Select $select
356
     * @param array  $parts
357
     *
358
     * @return $this
359
     */
360
    protected function writeSelectLimit(Select $select, array &$parts)
361
    {
362
        $mask = $this->getStartingLimit($select).$this->getLimitCount($select);
363
364
        $limit = '';
365
366
        if ($mask !== '00') {
367
            $start = $this->placeholderWriter->add($select->getLimitStart());
368
            $count = $this->placeholderWriter->add($select->getLimitCount());
369
370
            $limit = "LIMIT {$start}, {$count}";
371
        }
372
373
        $parts = \array_merge($parts, [$limit]);
374
375
        return $this;
376
    }
377
378
    /**
379
     * @param Select $select
380
     *
381
     * @return string
382
     */
383
    protected function getStartingLimit(Select $select)
384
    {
385
        return (null === $select->getLimitStart() || 0 == $select->getLimitStart()) ? '0' : '1';
386
    }
387
388
    /**
389
     * @param Select $select
390
     *
391
     * @return string
392
     */
393
    protected function getLimitCount(Select $select)
394
    {
395
        return (null === $select->getLimitCount()) ? '0' : '1';
396
    }
397
}
398