Completed
Push — master ( a0a464...9c0da3 )
by Mr
02:05
created

SQL::update()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 23
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.5906
c 0
b 0
f 0
cc 5
eloc 10
nc 9
nop 2
1
<?php
2
3
namespace DrMVC\Database\Drivers;
4
5
use DrMVC\Database\SQLException;
6
7
abstract class SQL extends Driver implements SQLInterface
8
{
9
    /**
10
     * Initiate connection to database
11
     *
12
     * @return  DriverInterface
13
     */
14
    public function connect(): DriverInterface
15
    {
16
        try {
17
            $connection = new \PDO(
18
                $this->getDsn(),
19
                $this->getParam('username'),
20
                $this->getParam('password')
21
            );
22
            $this->setConnection($connection);
23
24
        } catch (SQLException $e) {
25
            // __construct
26
        }
27
28
        return $this;
29
    }
30
31
    /**
32
     * Generate basic select query
33
     *
34
     * @param   array $where
35
     * @return  string
36
     */
37
    private function getSelect(array $where): string
38
    {
39
        // Current table
40
        $table = $this->getCollection();
41
42
        // Generate where line
43
        $whereDetails = !empty($where)
44
            ? ' WHERE ' . $this->genWhere($where)
45
            : '';
46
47
        return "SELECT * FROM $table $whereDetails";
48
    }
49
50
    /**
51
     * Run a select statement against the database
52
     *
53
     * @param   array $where array with data for filtering
54
     * @return  mixed
55
     */
56
    public function select(array $where = [])
57
    {
58
        // Set statement
59
        $query = $this->getSelect($where);
60
        $statement = $this->getConnection()->prepare($query);
0 ignored issues
show
Bug introduced by
The method prepare() does not exist on MongoDB\Driver\Manager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

60
        $statement = $this->getConnection()->/** @scrutinizer ignore-call */ prepare($query);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
61
62
        // Bind where values
63
        foreach ($where as $key => $value) {
64
            $value_type = \is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
65
            $statement->bindValue(":where_$key", $value, $value_type);
66
        }
67
68
        // Execute operation
69
        $statement->execute();
70
71
        // Return object
72
        return $statement->fetchAll(\PDO::FETCH_OBJ);
73
    }
74
75
    /**
76
     * Execute raw query, without generation, useful for some advanced operations
77
     *
78
     * @param   array $arguments array of arguments
79
     * @return  mixed
80
     */
81
    public function rawSQL(array $arguments)
82
    {
83
        /*
84
         * @param string $query  pure sql query
85
         * @param  array $bind   array with values in [':key' => 'value'] format
86
         * @param   bool $fetch  make fetch and return data?
87
         */
88
        @list($query, $bind, $fetch) = $arguments;  // Notices disabled
89
90
        // Set statement
91
        $statement = $this->getConnection()->prepare($query);
92
93
        // Execute operation
94
        $statement->execute($bind);
95
96
        return (true === $fetch)
97
            // Return object
98
            ? $statement->fetchAll(\PDO::FETCH_OBJ)
99
            // Return count of affected rows
100
            : $statement->rowCount();
101
    }
102
103
    /**
104
     * Generate INSERT query by array
105
     *
106
     * @param   array $data
107
     * @return  string
108
     */
109
    private function genInsert(array $data): string
110
    {
111
        // Current table
112
        $table = $this->getCollection();
113
114
        // Generate array of fields for insert
115
        $fieldNames = implode(',', array_keys($data));
116
117
        // Generate line with data for update
118
        $fieldDetails = ':' . implode(', :', array_keys($data));
119
120
        return "INSERT INTO $table ($fieldNames) VALUES ($fieldDetails)";
121
    }
122
123
    /**
124
     * Insert in database and return of inserted element
125
     *
126
     * @param   array $data array of columns and values
127
     * @param   string $id field name of ID which must be returned
128
     * @return  mixed
129
     */
130
    public function insert(array $data, string $id = null)
131
    {
132
        // Prepare query
133
        $query = $this->genInsert($data);
134
        $statement = $this->getConnection()->prepare($query);
135
136
        // Bind values
137
        foreach ($data as $key => $value) {
138
            $value_type = \is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
139
            $statement->bindValue(":$key", $value, $value_type);
140
        }
141
142
        // Execute operation
143
        $statement->execute();
144
145
        return (null !== $id)
146
            // Return ID of inserted element
147
            ? $this->getConnection()->lastInsertId($id)
0 ignored issues
show
Bug introduced by
The method lastInsertId() does not exist on MongoDB\Driver\Manager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
            ? $this->getConnection()->/** @scrutinizer ignore-call */ lastInsertId($id)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
148
            // Return count of affected rows
149
            : $statement->rowCount();
150
    }
151
152
    /**
153
     * Generate the line by provided keys
154
     *
155
     * @param   array $array array with data
156
     * @param   string $glue by this glue need merge items
157
     * @param   string $name name of field for PDO->bindValue
158
     * @return  string
159
     */
160
    private function genLine(array $array, string $glue, string $name): string
161
    {
162
        $line = '';
163
        $i = 0;
164
        foreach ($array as $key => $value) {
165
            $line .= (($i !== 0) ? null : $glue) . "$key = :${name}_$key";
166
            $i = 1;
167
        }
168
        return $line;
169
    }
170
171
    /**
172
     * Generate set of fields
173
     *
174
     * @param   array $array
175
     * @return  string
176
     */
177
    private function genFields(array $array): string
178
    {
179
        return $this->genLine($array, ', ', 'field');
180
    }
181
182
    /**
183
     * Generate WHERE line
184
     *
185
     * @param   array $array
186
     * @return  string
187
     */
188
    private function genWhere(array $array): string
189
    {
190
        return $this->genLine($array, ' AND ', 'where');
191
    }
192
193
    /**
194
     * Generate update query
195
     *
196
     * @param   array $data
197
     * @param   array $where
198
     * @return  string
199
     */
200
    private function genUpdate(array $data, array $where): string
201
    {
202
        // Current table
203
        $table = $this->getCollection();
204
205
        // Generate line with data for update
206
        $fieldDetails = !empty($data)
207
            ? $this->genFields($data)
208
            : '';
209
210
        // Generate where line
211
        $whereDetails = !empty($where)
212
            ? ' WHERE ' . $this->genWhere($where)
213
            : '';
214
215
        return "UPDATE $table SET $fieldDetails $whereDetails";
216
    }
217
218
    /**
219
     * Update method
220
     *
221
     * @param   array $data array of columns and values
222
     * @param   array $where array with data for filtering
223
     * @return  mixed
224
     */
225
    public function update(array $data, array $where = [])
226
    {
227
        // Prepare query
228
        $query = $this->genUpdate($data, $where);
229
        $statement = $this->getConnection()->prepare($query);
230
231
        // Bind field values
232
        foreach ($data as $key => $value) {
233
            $value_type = \is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
234
            $statement->bindValue(":field_$key", $value, $value_type);
235
        }
236
237
        // Bind where values
238
        foreach ($where as $key => $value) {
239
            $value_type = \is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
240
            $statement->bindValue(":where_$key", $value, $value_type);
241
        }
242
243
        // Execute operation
244
        $statement->execute();
245
246
        // Return count of affected rows
247
        return $statement->rowCount();
248
    }
249
250
    /**
251
     * Delete rows from database
252
     *
253
     * @param   array $where array with data for filtering
254
     * @return  mixed
255
     */
256
    public function delete(array $where)
257
    {
258
        // Current table
259
        $table = $this->getCollection();
260
261
        // Generate where line
262
        $whereDetails = !empty($where)
263
            ? ' WHERE ' . $this->genWhere($where)
264
            : '';
265
266
        // Prepare query
267
        $statement = $this->getConnection()->prepare("DELETE FROM $table $whereDetails");
268
269
        // Bind where values
270
        foreach ($where as $key => $value) {
271
            $value_type = \is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
272
            $statement->bindValue(":where_$key", $value, $value_type);
273
        }
274
275
        // Execute operation
276
        $statement->execute();
277
278
        // Return count of affected rows
279
        return $statement->rowCount();
280
    }
281
282
    /**
283
     * Clean table function
284
     *
285
     * @return mixed
286
     */
287
    public function truncate()
288
    {
289
        // Current table
290
        $table = $this->getConnection();
291
292
        // Exec the truncate command
293
        return $this->rawSQL(["TRUNCATE TABLE $table"]);
294
    }
295
}
296