Completed
Branch feature/pre-split (b025f2)
by Anton
03:30
created

QueryBuilder::fetchIdentifiers()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 3
nop 1
dl 0
loc 12
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Database\Builders;
10
11
use Spiral\Database\Entities\Driver;
12
use Spiral\Database\Entities\QueryCompiler;
13
use Spiral\Database\Exceptions\BuilderException;
14
use Spiral\Database\Helpers\QueryInterpolator;
15
use Spiral\Database\Injections\ExpressionInterface;
16
use Spiral\Database\Injections\ParameterInterface;
17
18
/**
19
 * QueryBuilder classes generate set of control tokens for query compilers, this is query level
20
 * abstraction.
21
 */
22
abstract class QueryBuilder implements ExpressionInterface
23
{
24
    /**
25
     * @invisible
26
     *
27
     * @var Driver
28
     */
29
    protected $driver = null;
30
31
    /**
32
     * @invisible
33
     *
34
     * @var QueryCompiler
35
     */
36
    protected $compiler = null;
37
38
    /**
39
     * @param Driver        $driver   Associated driver.
40
     * @param QueryCompiler $compiler Driver specific QueryCompiler instance (one per builder).
41
     */
42
    public function __construct(Driver $driver, QueryCompiler $compiler)
43
    {
44
        $this->driver = $driver;
45
        $this->compiler = $compiler;
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     *
51
     * @param QueryCompiler $compiler Associated compiled to be used by default.
52
     */
53
    abstract public function sqlStatement(QueryCompiler $compiler = null): string;
54
55
    /**
56
     * Get ordered list of builder parameters in a form of ParameterInterface array.
57
     *
58
     * @param QueryCompiler $compiler Compiler is needed to validly sort parameters from different
59
     *                                query parts (potentially deprecated). Associated compiled to
60
     *                                be used by default.
61
     *
62
     * @return array|ParameterInterface[]
63
     *
64
     * @throws BuilderException
65
     */
66
    abstract public function getParameters(QueryCompiler $compiler = null): array;
67
68
    /**
69
     * Get interpolated (populated with parameters) SQL which will be run against database, please
70
     * use this method for debugging purposes only.
71
     *
72
     * @return string
73
     */
74
    public function queryString(): string
75
    {
76
        return QueryInterpolator::interpolate($this->sqlStatement(), $this->getParameters());
77
    }
78
79
    /**
80
     * @return string
81
     */
82
    public function __toString(): string
83
    {
84
        return $this->sqlStatement();
85
    }
86
87
    /**
88
     * @return array
89
     */
90
    public function __debugInfo()
91
    {
92
        try {
93
            $queryString = $this->queryString();
94
        } catch (\Exception $e) {
95
            $queryString = "[ERROR: {$e->getMessage()}]";
96
        }
97
98
        $debugInfo = [
99
            'statement' => $queryString,
100
            'compiler'  => $this->compiler,
101
            'driver'    => $this->driver,
102
        ];
103
104
        return $debugInfo;
105
    }
106
107
    /**
108
     * Helper methods used to correctly fetch and split identifiers provided by function
109
     * parameters.
110
     * It support array list, string or comma separated list. Attention, this method will not work
111
     * with complex parameters (such as functions) provided as one comma separated string, please
112
     * use arrays in this case.
113
     *
114
     * @param array $identifiers
115
     *
116
     * @return array
117
     */
118
    protected function fetchIdentifiers(array $identifiers): array
119
    {
120
        if (count($identifiers) == 1 && is_string($identifiers[0])) {
121
            return array_map('trim', explode(',', $identifiers[0]));
122
        }
123
124
        if (count($identifiers) == 1 && is_array($identifiers[0])) {
125
            return $identifiers[0];
126
        }
127
128
        return $identifiers;
129
    }
130
131
    /**
132
     * Expand all QueryBuilder parameters to create flatten list.
133
     *
134
     * @param array $parameters
135
     *
136
     * @return array
137
     */
138
    protected function flattenParameters(array $parameters): array
139
    {
140
        $result = [];
141
        foreach ($parameters as $parameter) {
142
            if ($parameter instanceof self) {
143
                $result = array_merge($result, $parameter->getParameters());
144
                continue;
145
            }
146
147
            $result[] = $parameter;
148
        }
149
150
        return $result;
151
    }
152
153
    /**
154
     * Generate PDO statement based on generated sql and parameters.
155
     *
156
     * @return \PDOStatement
157
     */
158
    protected function pdoStatement(): \PDOStatement
159
    {
160
        return $this->driver->statement($this->sqlStatement(), $this->getParameters());
161
    }
162
}
163