Completed
Push — master ( d1f44d...2f7083 )
by Kamil
02:59
created

Query::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 0
cts 6
cp 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
crap 2
1
<?php
2
3
namespace Dazzle\MySQL\Protocol;
4
5
use Dazzle\Throwable\Exception\LogicException;
6
7
class Query implements QueryInterface
8
{
9
    /**
10
     * @var string
11
     */
12
    protected $sql;
13
14
    /**
15
     * @var string
16
     */
17
    protected $sqlPrepared;
18
19
    /**
20
     * @var mixed[]
21
     */
22
    protected $params = [];
23
24
    /**
25
     * @var string[]
26
     */
27
    private $escapeChars = [
28
        "\x00" => "\\0",
29
        "\r"   => "\\r",
30
        "\n"   => "\\n",
31
        "\t"   => "\\t",
32
        "'"    => "\'",
33
        '"'    => '\"',
34
        "\\"   => "\\\\",
35
    ];
36
37
    /**
38
     * @param string $sql
39
     * @param mixed[] $sqlParams
40
     */
41
    public function __construct($sql, $sqlParams = [])
42
    {
43
        $this->sql = $sql;
44
        $this->sqlPrepared = null;
45
        $this->params = $sqlParams;
46
    }
47
48
    /**
49
     * @override
50
     * @inheritDoc
51
     */
52
    public function bindParams(...$args)
53
    {
54
        $this->sqlPrepared = null;
55
        $this->params = $args;
56
57
        return $this;
58
    }
59
60
    /**
61
     * @override
62
     * @inheritDoc
63
     */
64
    public function bindParamsFromArray(array $params = [])
65
    {
66
        $this->sqlPrepared = null;
67
        $this->params = $params;
68
69
        return $this;
70
    }
71
72
    /**
73
     * @override
74
     * @inheritDoc
75
     */
76
    public function getSQL()
77
    {
78
        return $this->sqlPrepared === null ? $this->buildSQL() : $this->sqlPrepared;
79
    }
80
81
    /**
82
     * Escape string.
83
     *
84
     * @param string $str
85
     * @return string
86
     */
87
    protected function escape($str)
88
    {
89
        return strtr($str, $this->escapeChars);
90
    }
91
92
    /**
93
     * Resolve value for SQL.
94
     *
95
     * @param  mixed $value
96
     * @return string
97
     */
98
    protected function resolveValueForSql($value)
99
    {
100
        $type = gettype($value);
101
102
        switch ($type)
103
        {
104
            case 'boolean':
105
                $value = (int) $value;
106
                break;
107
            case 'double':
108
            case 'integer':
109
                break;
110
            case 'string':
111
                $value = "'" . $this->escape($value) . "'";
112
                break;
113
            case 'array':
114
                $nvalue = [];
115
                foreach ($value as $v) {
116
                    $nvalue[] = $this->resolveValueForSql($v);
117
                }
118
                $value = implode(',', $nvalue);
119
                break;
120
            case 'null':
121
                $value = 'null';
122
                break;
123
            default:
124
                throw new \InvalidArgumentException(sprintf('Not supportted value type of %s.', $type));
125
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
126
        }
127
128
        return $value;
129
    }
130
131
    /**
132
     * Build sql query replacing and escaping characters.
133
     *
134
     * @return string
135
     * @throws LogicException
136
     */
137
    protected function buildSQL()
138
    {
139
        $sql = $this->sql;
140
        $offset = strpos($sql, '?');
141
142
        foreach ($this->params as $param)
143
        {
144
            $replacement = $this->resolveValueForSql($param);
145
            $sql = substr_replace($sql, $replacement, $offset, 1);
146
            $offset = strpos($sql, '?', $offset + strlen($replacement));
147
        }
148
149
        if ($offset !== false)
150
        {
151
            throw new LogicException('Params not enough to build valid SQL!');
152
        }
153
154
        return $sql;
155
    }
156
}
157