Passed
Push — master ( cf2b67...b6f4b7 )
by Igor
02:25
created

Bindings::compile_binds()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 9
c 0
b 0
f 0
ccs 5
cts 5
cp 1
rs 10
cc 2
nc 1
nop 3
crap 2
1
<?php
2
3
namespace ClickHouseDB\Query\Degeneration;
4
5
use DateTimeInterface;
6
use function array_map;
7
use function implode;
8
use function is_array;
9
use function is_float;
10
use function is_int;
11
use function is_string;
12
use function sprintf;
13
use function str_ireplace;
14
15
class Bindings implements \ClickHouseDB\Query\Degeneration
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $bindings = [];
21
22
23
    /**
24
     * @param array $bindings
25
     */
26 49
    public function bindParams(array $bindings)
27
    {
28 49
        $this->bindings = [];
29 49
        foreach ($bindings as $column => $value) {
30 19
            $this->bindParam($column, $value);
31
        }
32 49
    }
33
34
    /**
35
     * @param string $column
36
     * @param mixed  $value
37
     */
38 19
    public function bindParam($column, $value)
39
    {
40 19
        if ($value instanceof DateTimeInterface) {
41
            $value = $value->format('Y-m-d H:i:s');
42
        }
43
44 19
        $this->bindings[$column] = $value;
45 19
    }
46
47
    /**
48
     * Escape an string
49
     *
50
     * @param string $value
51
     * @return string
52
     */
53 13
    private function escapeString($value)
54
    {
55
        // return str_replace("'", "''", remove_invisible_characters($str, FALSE));
56 13
        return addslashes($value);
57
    }
58
59
    /**
60
     * Escape an array
61
     *
62
     * @param array $values
63
     * @return array
64
     */
65 6
    private function escapeArray($values)
66
    {
67 6
        $escapedValues = [];
68 6
        foreach ($values as $value) {
69 6
            if (is_numeric($value)) {
70 5
                $escapedValues[] = $value;
71 3
            } elseif (is_string($value)) {
72 3
                $escapedValues[] = $this->escapeString($value);
73
            } elseif (is_array($value)) {
74 6
                $escapedValues[] = $this->escapeArray($value);
75
            }
76
        }
77
78 6
        return $escapedValues;
79
    }
80
81
    /**
82
     * Binds a list of values to the corresponding parameters.
83
     * This is similar to [[bindValue()]] except that it binds multiple values at a time.
84
     *
85
     * @param string $sql
86
     * @param array $binds
87
     * @param string $pattern
88
     * @return string
89
     */
90 49
    public function compile_binds($sql, $binds,$pattern)
91
    {
92
        return preg_replace_callback($pattern, function($m) use ($binds){
93 19
            if(isset($binds[$m[1]])){ // If it exists in our array
94 19
                return $binds[$m[1]]; // Then replace it from our array
95
            }else{
96 3
                return $m[0]; // Otherwise return the whole match (basically we won't change it)
97
            }
98 49
        }, $sql);
99
    }
100
101
102
    /**
103
     * Compile Bindings
104
     *
105
     * @param string $sql
106
     * @return mixed
107
     */
108 49
    public function process($sql)
109
    {
110 49
        arsort($this->bindings);
111
112 49
        $bindFormatted=[];
113 49
        $bindRaw=[];
114 49
        foreach ($this->bindings as $key => $value) {
115 19
            $valueSet           = null;
116 19
            $formattedParameter = null;
117
118 19
            if ($value === null || $value === false) {
119 1
                $formattedParameter = '';
120
            }
121
122 19
            if (is_array($value)) {
123 6
                $escapedValues = $this->escapeArray($value);
124
125 6
                $escapedValues = array_map(
126
                    function ($escapedValue) {
127 6
                        if (is_string($escapedValue)) {
128 5
                            return $this->formatStringParameter($escapedValue);
129
                        }
130
131 3
                        return $escapedValue;
132 6
                    },
133 6
                    $escapedValues
134
                );
135
136 6
                $formattedParameter = implode(',', $escapedValues);
137 6
                $valueSet           = implode(', ', $escapedValues);
138
            }
139
140 19
            if (is_float($value) || is_int($value)) {
141 7
                $formattedParameter = $value;
142 7
                $valueSet           = $value;
143
            }
144
145 19
            if (is_string($value)) {
146 12
                $valueSet           = $value;
147 12
                $formattedParameter = $this->formatStringParameter($this->escapeString($value));
148
            }
149
150 19
            if ($formattedParameter !== null) {
151 19
                $bindFormatted[$key]=$formattedParameter;
152
            }
153
154 19
            if ($valueSet !== null) {
155 19
                $bindRaw[$key]=$valueSet;
156
            }
157
        }
158
159 49
        for ($loop=0;$loop<2;$loop++)
160
        {
161
            // dipping in binds
162
            // example ['A' => '{B}' , 'B'=>':C','C'=>123]
163 49
            $sql=$this->compile_binds($sql,$bindRaw,'#{([\w+]+)}#');
164
        }
165 49
        $sql=$this->compile_binds($sql,$bindFormatted,'#:([\w+]+)#');
166
167 49
        return $sql;
168
    }
169
170
    /**
171
     * @return string
172
     */
173 15
    private function formatStringParameter($value)
174
    {
175 15
        return sprintf("'%s'", $value);
176
    }
177
}
178