Completed
Push — work-fleets ( bf14b2...c62b27 )
by SuperNova.WS
06:15
created

DbQuery::oneRow()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 9.4285
ccs 0
cts 4
cp 0
crap 2
1
<?php
2
/**
3
 * Created by Gorlum 07.08.2016 2:36
4
 */
5
6
namespace DBAL;
7
8
use \HelperArray;
9
use \db_mysql;
10
use \classSupernova;
11
12
/**
13
 * Class DbQuery
14
 *
15
 * New replacement for DbQueryConstructor
16
 * Simplified version
17
 * Chained calls - "Fluid interface"
18
 *
19
 * @package DBAL
20
 */
21
class DbQuery {
22
23
  const SELECT = 'SELECT';
24
  const INSERT = 'INSERT';
25
  const UPDATE = 'UPDATE';
26
  const DELETE = 'DELETE';
27
  const REPLACE = 'REPLACE';
28
29
  /**
30
   * @var db_mysql
31
   */
32
  protected $db;
33
34
  /**
35
   * Which command would be performed
36
   *
37
   * @var string $command
38
   */
39
  protected $command;
40
41
  protected $table = '';
42
  protected $fields = array();
43
  protected $where = array();
44
  protected $whereDanger = array();
45
46
  /**
47
   * Variable for increment query build
48
   *
49
   * @var string[] $build
50
   */
51
  protected $build = array();
52
53
  protected $isOneRow = false;
54
55
  /**
56
   * @param null|db_mysql $db
57
   *
58
   * @return static
59
   */
60
  public static function build($db = null) {
61
    return new static($db);
62
  }
63
64
  /**
65
   * DbQuery constructor.
66
   *
67
   * @param  null|\db_mysql $db
68
   */
69
  // TODO - $db should be supplied externally
70
  public function __construct($db = null) {
71
    $this->db = empty($db) ? classSupernova::$gc->db : $db;
72
  }
73
74
  /**
75
   * Wrapper for db_escape()
76
   *
77
   * @param $string
78
   *
79
   * @return string
80
   */
81
  protected function escape($string) {
82
    return $this->db->db_escape($string);
83
  }
84
85
  /**
86
   * Wrapper for db_escape()
87
   *
88
   * @param mixed $value
89
   *
90
   * @return string
91
   */
92
  protected function stringValue($value) {
93
    return "'" . $this->escape((string)$value) . "'";
94
  }
95
96
  /**
97
   * Quote mysql DB identifier
98
   *
99
   * @param mixed $fieldName
100
   *
101
   * @return string
102
   */
103
  protected function quote($fieldName) {
104
    return "`" . $this->escape((string)$fieldName) . "`";
105
  }
106
107
  /**
108
   * Quote table name with {{ }}
109
   *
110
   * @param mixed $tableName
111
   *
112
   * @return string
113
   */
114
  protected function quoteTable($tableName) {
115
    return "`{{" . $this->escape((string)$tableName) . "}}`";
116
  }
117
118
  public function table($table) {
119
    $this->table = $table;
120
121
    return $this;
122
  }
123
124
  /**
125
   * @param bool $oneRow - DB_RECORDS_ALL || DB_RECORD_ONE
126
   *
127
   * @return $this
128
   */
129
  public function oneRow($oneRow = DB_RECORDS_ALL) {
130
    $this->isOneRow = ($oneRow == DB_RECORD_ONE);
131
132
    return $this;
133
  }
134
135
  /**
136
   * Merges WHERE array as array_merge()
137
   *
138
   * @param array $whereArray
139
   */
140
  public function whereArray($whereArray = array()) {
141
    HelperArray::merge($this->where, $whereArray, HelperArray::MERGE_PHP);
142
143
    return $this;
144
  }
145
146
  /**
147
   * Merges WHERE array as array_merge()
148
   *
149
   * @param array $whereArrayDanger
150
   * @deprecated
151
   */
152
  public function whereArrayDanger($whereArrayDanger = array()) {
153
    HelperArray::merge($this->whereDanger, $whereArrayDanger, HelperArray::MERGE_PHP);
154
155
    return $this;
156
  }
157
158 View Code Duplication
  protected function castAsDbValue($value) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
159
    switch (gettype($value)) {
160
      case TYPE_INTEGER:
161
      case TYPE_DOUBLE:
162
        // do nothing
163
      break;
164
165
      case TYPE_BOOLEAN:
166
        $value = $value ? 1 : 0;
167
      break;
168
169
      case TYPE_NULL:
170
        $value = 'NULL';
171
      break;
172
173
      case TYPE_EMPTY:
174
        // No-type defaults to string
175
        /** @noinspection PhpMissingBreakStatementInspection */
176
      case TYPE_ARRAY:
177
        $value = serialize($value);
178
      // Continuing with serialized array value
179
      case TYPE_STRING:
180
      default:
181
        $value = $this->stringValue($value);
182
      break;
183
    }
184
185
    return $value;
186
  }
187
188
  /**
189
   * Make list of DANGER where clauses
190
   *
191
   * This function is DANGER! It takes numeric indexes which translate to direct SQL string which can lead to SQL injection!
192
   *
193
   * @param array $where - array WHERE clauses which will not pass through SAFE filter
194
   *
195
   * @return array
196
   */
197
  protected function dangerWhere($where) {
198
    $result = array();
199
200
    if (!is_array($where) || empty($where)) {
201
      return $result;
202
    }
203
204
    foreach ($where as $fieldName => $fieldValue) {
205
      // Integer $fieldName means "leave as is" - for expressions and already processed fields
206
      if (is_int($fieldName)) {
207
        $result[] = $fieldValue;
208
      }
209
    }
210
211
    return $result;
212
  }
213
214
  /**
215
   * Make field list safe. NOT DANGER
216
   *
217
   * This function is NOT DANGER
218
   * Make SQL-safe assignment/equal compare string from (field => value) pair
219
   *
220
   * @param array $fieldValues - array of pair $fieldName => $fieldValue
221
   *
222
   * @return array
223
   */
224
  protected function fieldEqValue($fieldValues) {
225
    $result = array();
226
227
    if (!is_array($fieldValues) || empty($fieldValues)) {
228
      return $result;
229
    }
230
231
    foreach ($fieldValues as $fieldName => $fieldValue) {
232
      // Integer $fieldName is DANGER! They skipped there!
233
      if (!is_int($fieldName)) {
234
        $result[$fieldName] = $this->quote($fieldName) . " = " . $this->castAsDbValue($fieldValue);
235
      }
236
    }
237
238
    return $result;
239
  }
240
241
  protected function buildCommand() {
242
    switch ($this->command) {
243
      case static::DELETE:
244
        $this->build[] = static::DELETE . " FROM " . $this->quoteTable($this->table) . ' ';
245
      break;
246
    }
247
  }
248
249
  protected function buildWhere() {
250
    $safeWhere = implode(
251
      ' AND ',
252
      $this->dangerWhere($this->whereDanger) + $this->dangerWhere($this->where) + $this->fieldEqValue($this->where)
253
    );
254
255
    if (!empty($safeWhere)) {
256
      $this->build[] = " WHERE {$safeWhere}";
257
    }
258
  }
259
260
  protected function buildLimit() {
261
    if ($this->isOneRow) {
262
      $this->build[] = ' LIMIT 1';
263
    }
264
  }
265
266
267
  public function delete() {
268
    $this->build = array();
269
270
    $this->command = static::DELETE;
271
    $this->buildCommand();
272
    $this->buildWhere();
273
    $this->buildLimit();
274
275
    return implode('', $this->build);
276
  }
277
278
}
279