Completed
Pull Request — develop (#209)
by Felipe
26:08 queued 36s
created

RowTrait::getRowIdentifier()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 51
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 24
nc 5
nop 1
dl 0
loc 51
rs 8.6588
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.48
5
 */
6
7
namespace PHPPgAdmin\Database\Traits;
8
9
/**
10
 * Common trait for tables manipulation.
11
 */
12
trait RowTrait
13
{
14
    /**
15
     * Returns a recordset of all columns in a table.
16
     *
17
     * @param string $table The name of a table
18
     * @param array  $key   The associative array holding the key to retrieve
19
     *
20
     * @return \PHPPgAdmin\ADORecordSet A recordset
21
     */
22
    public function browseRow($table, $key)
23
    {
24
        $f_schema = $this->_schema;
0 ignored issues
show
Bug introduced by
The property _schema does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
25
        $this->fieldClean($f_schema);
26
        $this->fieldClean($table);
27
28
        $sql = "SELECT * FROM \"{$f_schema}\".\"{$table}\"";
29
        if (is_array($key) && sizeof($key) > 0) {
30
            $sql .= ' WHERE true';
31
            foreach ($key as $k => $v) {
32
                $this->fieldClean($k);
33
                $this->clean($v);
34
                $sql .= " AND \"{$k}\"='{$v}'";
35
            }
36
        }
37
38
        return $this->selectSet($sql);
39
    }
40
41
    /**
42
     * Get the fields for uniquely identifying a row in a table.
43
     *
44
     * @param string $table The table for which to retrieve the identifier
45
     *
46
     * @return array|array<integer,string>|int An array mapping attribute number to attribute name, empty for no identifiers
47
     */
48
    public function getRowIdentifier($table)
49
    {
50
        $oldtable = $table;
51
        $c_schema = $this->_schema;
52
        $this->clean($c_schema);
53
        $this->clean($table);
54
55
        $status = $this->beginTransaction();
56
        if ($status != 0) {
57
            return -1;
58
        }
59
60
        // Get the first primary or unique index (sorting primary keys first) that
61
        // is NOT a partial index.
62
        $sql = "
63
            SELECT indrelid, indkey
64
            FROM pg_catalog.pg_index
65
            WHERE indisunique AND indrelid=(
66
                SELECT oid FROM pg_catalog.pg_class
67
                WHERE relname='{$table}' AND relnamespace=(
68
                    SELECT oid FROM pg_catalog.pg_namespace
69
                    WHERE nspname='{$c_schema}'
70
                )
71
            ) AND indpred IS NULL AND indexprs IS NULL
72
            ORDER BY indisprimary DESC LIMIT 1";
73
        $rs = $this->selectSet($sql);
74
75
        // If none, check for an OID column.  Even though OIDs can be duplicated, the edit and delete row
76
        // functions check that they're only modiying a single row.  Otherwise, return empty array.
77
        if ($rs->RecordCount() == 0) {
78
            // Check for OID column
79
            $temp = [];
80
            if ($this->hasObjectID($table)) {
81
                $temp = ['oid'];
82
            }
83
            $this->endTransaction();
84
85
            return $temp;
86
        } // Otherwise find the names of the keys
87
88
        $attnames = $this->getAttributeNames($oldtable, explode(' ', $rs->fields['indkey']));
89
        if (!is_array($attnames)) {
90
            $this->rollbackTransaction();
91
92
            return -1;
93
        }
94
95
        $this->endTransaction();
96
97
        return $attnames;
98
    }
99
100
    /**
101
     * Adds a new row to a table.
102
     *
103
     * @param string $table  The table in which to insert
104
     * @param array  $fields Array of given field in values
105
     * @param array  $values Array of new values for the row
106
     * @param array  $nulls  An array mapping column => something if it is to be null
107
     * @param array  $format An array of the data type (VALUE or EXPRESSION)
108
     * @param array  $types  An array of field types
109
     *
110
     * @return int 0 if operation was successful
111
     */
112
    public function insertRow($table, $fields, $values, $nulls, $format, $types)
113
    {
114
        if (!is_array($fields) || !is_array($values) || !is_array($nulls)
115
            || !is_array($format) || !is_array($types)
116
            || (count($fields) != count($values))
117
        ) {
118
            return -1;
119
        }
120
121
        // Build clause
122
        if (count($values) > 0) {
123
            // Escape all field names
124
            $fields   = array_map(['\PHPPgAdmin\Database\Postgres', 'fieldClean'], $fields);
125
            $f_schema = $this->_schema;
126
            $this->fieldClean($table);
127
            $this->fieldClean($f_schema);
128
129
            $sql = '';
130
            foreach ($values as $i => $value) {
131
                // Handle NULL values
132
                if (isset($nulls[$i])) {
133
                    $sql .= ',NULL';
134
                } else {
135
                    $sql .= ','.$this->formatValue($types[$i], $format[$i], $value);
136
                }
137
            }
138
139
            $sql = "INSERT INTO \"{$f_schema}\".\"{$table}\" (\"".implode('","', $fields).'")
140
                VALUES ('.substr($sql, 1).')';
141
142
            return $this->execute($sql);
143
        }
144
145
        return -1;
146
    }
147
148
    /**
149
     * Formats a value or expression for sql purposes.
150
     *
151
     * @param string $type   The type of the field
152
     * @param mixed  $format VALUE or EXPRESSION
153
     * @param mixed  $value  The actual value entered in the field.  Can be NULL
154
     *
155
     * @return mixed The suitably quoted and escaped value
156
     */
157
    public function formatValue($type, $format, $value)
158
    {
159
        switch ($type) {
160
            case 'bool':
161
            case 'boolean':
162
                if ($value == 't') {
163
                    return 'TRUE';
164
                }
165
166
                if ($value == 'f') {
167
                    return 'FALSE';
168
                }
169
                if ($value == '') {
170
                    return 'NULL';
171
                }
172
173
                return $value;
174
175
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
176
            default:
177
                // Checking variable fields is difficult as there might be a size
178
                // attribute...
179
                if (strpos($type, 'time') === 0) {
180
                    // Assume it's one of the time types...
181
                    if ($value == '') {
182
                        return "''";
183
                    }
184
185
                    if (strcasecmp($value, 'CURRENT_TIMESTAMP') == 0
186
                        || strcasecmp($value, 'CURRENT_TIME') == 0
187
                        || strcasecmp($value, 'CURRENT_DATE') == 0
188
                        || strcasecmp($value, 'LOCALTIME') == 0
189
                        || strcasecmp($value, 'LOCALTIMESTAMP') == 0) {
190
                        return $value;
191
                    }
192
                    if ($format == 'EXPRESSION') {
193
                        return $value;
194
                    }
195
                    $this->clean($value);
196
197
                    return "'{$value}'";
198
                }
199
                if ($format == 'VALUE') {
200
                    $this->clean($value);
201
202
                    return "'{$value}'";
203
                }
204
205
                return $value;
206
        }
207
    }
208
209
    // View functions
210
211
    /**
212
     * Updates a row in a table.
213
     *
214
     * @param string $table  The table in which to update
215
     * @param array  $vars   An array mapping new values for the row
216
     * @param array  $nulls  An array mapping column => something if it is to be null
217
     * @param array  $format An array of the data type (VALUE or EXPRESSION)
218
     * @param array  $types  An array of field types
219
     * @param array  $keyarr An array mapping column => value to update
220
     *
221
     * @return bool|int 0 success
222
     */
223
    public function editRow($table, $vars, $nulls, $format, $types, $keyarr)
224
    {
225
        if (!is_array($vars) || !is_array($nulls) || !is_array($format) || !is_array($types)) {
226
            return -1;
227
        }
228
229
        $f_schema = $this->_schema;
230
        $this->fieldClean($f_schema);
231
        $this->fieldClean($table);
232
        $sql = '';
233
        // Build clause
234
        if (sizeof($vars) > 0) {
235
            foreach ($vars as $key => $value) {
236
                $this->fieldClean($key);
237
238
                // Handle NULL values
239
                if (isset($nulls[$key])) {
240
                    $tmp = 'NULL';
241
                } else {
242
                    $tmp = $this->formatValue($types[$key], $format[$key], $value);
243
                }
244
245
                if (strlen($sql) > 0) {
246
                    $sql .= ", \"{$key}\"={$tmp}";
247
                } else {
248
                    $sql = "UPDATE \"{$f_schema}\".\"{$table}\" SET \"{$key}\"={$tmp}";
249
                }
250
            }
251
            $first = true;
252
            foreach ($keyarr as $k => $v) {
253
                $this->fieldClean($k);
254
                $this->clean($v);
255
                if ($first) {
256
                    $sql .= " WHERE \"{$k}\"='{$v}'";
257
                    $first = false;
258
                } else {
259
                    $sql .= " AND \"{$k}\"='{$v}'";
260
                }
261
            }
262
        }
263
264
        // Begin transaction.  We do this so that we can ensure only one row is
265
        // edited
266
        $status = $this->beginTransaction();
267
        if ($status != 0) {
268
            $this->rollbackTransaction();
269
270
            return -1;
271
        }
272
        $status = $this->execute($sql);
273
        if ($status != 0) {
274
            // update failed
275
            $this->rollbackTransaction();
276
277
            return -1;
278
        }
279
280
        if ($this->conn->Affected_Rows() != 1) {
0 ignored issues
show
Bug introduced by
The property conn does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
281
            // more than one row could be updated
282
            $this->rollbackTransaction();
283
284
            return -2;
285
        }
286
287
        // End transaction
288
        return $this->endTransaction();
289
    }
290
291
    /**
292
     * Delete a row from a table.
293
     *
294
     * @param string $table  The table from which to delete
295
     * @param array  $key    An array mapping column => value to delete
296
     * @param string $schema the schema of the table
297
     *
298
     * @return bool|int 0 success
299
     */
300
    public function deleteRow($table, $key, $schema = '')
301
    {
302
        if (!is_array($key)) {
303
            return -1;
304
        }
305
306
        // Begin transaction.  We do this so that we can ensure only one row is
307
        // deleted
308
        $status = $this->beginTransaction();
309
        if ($status != 0) {
310
            $this->rollbackTransaction();
311
312
            return -1;
313
        }
314
315
        if ($schema === '') {
316
            $schema = $this->_schema;
317
        }
318
319
        $status = $this->delete($table, $key, $schema);
320
        if ($status != 0 || $this->conn->Affected_Rows() != 1) {
321
            $this->rollbackTransaction();
322
323
            return -2;
324
        }
325
326
        // End transaction
327
        return $this->endTransaction();
328
    }
329
330
    abstract public function fieldClean(&$str);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
331
332
    abstract public function beginTransaction();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
333
334
    abstract public function rollbackTransaction();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
335
336
    abstract public function endTransaction();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
337
338
    abstract public function execute($sql);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
339
340
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
Coding Style Naming introduced by
The parameter $obj_type is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $obj_name is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
341
342
    abstract public function selectSet($sql);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
343
344
    abstract public function clean(&$str);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
345
346
    abstract public function phpBool($parameter);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
347
348
    abstract public function hasCreateTableLikeWithConstraints();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
349
350
    abstract public function hasCreateTableLikeWithIndexes();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
351
352
    abstract public function hasTablespaces();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
353
354
    abstract public function delete($table, $conditions, $schema = '');
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
355
356
    abstract public function fieldArrayClean(&$arr);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
357
358
    abstract public function hasCreateFieldWithConstraints();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
359
360
    abstract public function getAttributeNames($table, $atts);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
361
362
    abstract public function hasObjectID($table);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
363
}
364