Passed
Push — develop ( 2d5edd...a33225 )
by Felipe
05:40
created

TypeTrait::createCompositeType()   F

Complexity

Conditions 21
Paths 739

Size

Total Lines 108
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 108
rs 2.3015
c 0
b 0
f 0
cc 21
eloc 65
nc 739
nop 8

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.47
5
 */
6
7
namespace PHPPgAdmin\Traits;
8
9
/**
10
 * Common trait for types manipulation.
11
 */
12
trait TypeTrait
13
{
14
    /**
15
     * Formats a type correctly for display.  Postgres 7.0 had no 'format_type'
16
     * built-in function, and hence we need to do it manually.
17
     *
18
     * @param string $typname The name of the type
19
     * @param string $typmod  The contents of the typmod field
20
     *
21
     * @return bool|string
22
     */
23
    public function formatType($typname, $typmod)
24
    {
25
        // This is a specific constant in the 7.0 source
26
        $varhdrsz = 4;
27
28
        // If the first character is an underscore, it's an array type
29
        $is_array = false;
30
        if (substr($typname, 0, 1) == '_') {
31
            $is_array = true;
32
            $typname  = substr($typname, 1);
33
        }
34
35
        // Show lengths on bpchar and varchar
36
        if ($typname == 'bpchar') {
37
            $len  = $typmod - $varhdrsz;
38
            $temp = 'character';
39
            if ($len > 1) {
40
                $temp .= "({$len})";
41
            }
42
        } elseif ($typname == 'varchar') {
43
            $temp = 'character varying';
44
            if ($typmod != -1) {
45
                $temp .= '('.($typmod - $varhdrsz).')';
46
            }
47
        } elseif ($typname == 'numeric') {
48
            $temp = 'numeric';
49
            if ($typmod != -1) {
50
                $tmp_typmod = $typmod - $varhdrsz;
51
                $precision  = ($tmp_typmod >> 16) & 0xffff;
52
                $scale      = $tmp_typmod & 0xffff;
53
                $temp .= "({$precision}, {$scale})";
54
            }
55
        } else {
56
            $temp = $typname;
57
        }
58
59
        // Add array qualifier if it's an array
60
        if ($is_array) {
61
            $temp .= '[]';
62
        }
63
64
        return $temp;
65
    }
66
67
    /**
68
     * Returns all details for a particular type.
69
     *
70
     * @param string $typname The name of the view to retrieve
71
     *
72
     * @return \PHPPgAdmin\ADORecordSet type info
73
     */
74
    public function getType($typname)
75
    {
76
        $this->clean($typname);
77
78
        $sql = "SELECT typtype, typbyval, typname, typinput AS typin, typoutput AS typout, typlen, typalign
79
            FROM pg_type WHERE typname='{$typname}'";
80
81
        return $this->selectSet($sql);
82
    }
83
84
    /**
85
     * Returns a list of all types in the database.
86
     *
87
     * @param bool $all        If true, will find all available types, if false just those in search path
88
     * @param bool $tabletypes If true, will include table types
89
     * @param bool $domains    If true, will include domains
90
     *
91
     * @return \PHPPgAdmin\ADORecordSet A recordset
92
     */
93
    public function getTypes($all = false, $tabletypes = false, $domains = false)
94
    {
95
        if ($all) {
96
            $where = '1 = 1';
97
        } else {
98
            $c_schema = $this->_schema;
99
            $this->clean($c_schema);
100
            $where = "n.nspname = '{$c_schema}'";
101
        }
102
        // Never show system table types
103
        $where2 = "AND c.relnamespace NOT IN (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname LIKE 'pg@_%' ESCAPE '@')";
104
105
        // Create type filter
106
        $tqry = "'c'";
107
        if ($tabletypes) {
108
            $tqry .= ", 'r', 'v'";
109
        }
110
111
        // Create domain filter
112
        if (!$domains) {
113
            $where .= " AND t.typtype != 'd'";
114
        }
115
116
        $sql = "SELECT
117
                t.typname AS basename,
118
                pg_catalog.format_type(t.oid, NULL) AS typname,
119
                pu.usename AS typowner,
120
                t.typtype,
121
                pg_catalog.obj_description(t.oid, 'pg_type') AS typcomment
122
            FROM (pg_catalog.pg_type t
123
                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace)
124
                LEFT JOIN pg_catalog.pg_user pu ON t.typowner = pu.usesysid
125
            WHERE (t.typrelid = 0 OR (SELECT c.relkind IN ({$tqry}) FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid {$where2}))
126
            AND t.typname !~ '^_'
127
            AND {$where}
128
            ORDER BY typname
129
        ";
130
131
        return $this->selectSet($sql);
132
    }
133
134
    /**
135
     * Creates a new type.
136
     *
137
     * @param string $typname
138
     * @param string $typin
139
     * @param string $typout
140
     * @param string $typlen
141
     * @param string $typdef
142
     * @param string $typelem
143
     * @param string $typdelim
144
     * @param string $typbyval
145
     * @param string $typalign
146
     * @param string $typstorage
147
     *
148
     * @return int 0 if operation was successful
149
     *
150
     * @internal param $ ...
151
     */
152
    public function createType(
153
        $typname,
154
        $typin,
155
        $typout,
156
        $typlen,
157
        $typdef,
158
        $typelem,
159
        $typdelim,
160
        $typbyval,
161
        $typalign,
162
        $typstorage
163
    ) {
164
        $f_schema = $this->_schema;
165
        $this->fieldClean($f_schema);
166
        $this->fieldClean($typname);
167
        $this->fieldClean($typin);
168
        $this->fieldClean($typout);
169
170
        $sql = "
171
            CREATE TYPE \"{$f_schema}\".\"{$typname}\" (
172
                INPUT = \"{$typin}\",
173
                OUTPUT = \"{$typout}\",
174
                INTERNALLENGTH = {$typlen}";
175
        if ($typdef != '') {
176
            $sql .= ", DEFAULT = {$typdef}";
177
        }
178
179
        if ($typelem != '') {
180
            $sql .= ", ELEMENT = {$typelem}";
181
        }
182
183
        if ($typdelim != '') {
184
            $sql .= ", DELIMITER = {$typdelim}";
185
        }
186
187
        if ($typbyval) {
188
            $sql .= ', PASSEDBYVALUE, ';
189
        }
190
191
        if ($typalign != '') {
192
            $sql .= ", ALIGNMENT = {$typalign}";
193
        }
194
195
        if ($typstorage != '') {
196
            $sql .= ", STORAGE = {$typstorage}";
197
        }
198
199
        $sql .= ')';
200
201
        return $this->execute($sql);
202
    }
203
204
    /**
205
     * Drops a type.
206
     *
207
     * @param string $typname The name of the type to drop
208
     * @param bool   $cascade True to cascade drop, false to restrict
209
     *
210
     * @return int 0 if operation was successful
211
     */
212
    public function dropType($typname, $cascade)
213
    {
214
        $f_schema = $this->_schema;
215
        $this->fieldClean($f_schema);
216
        $this->fieldClean($typname);
217
218
        $sql = "DROP TYPE \"{$f_schema}\".\"{$typname}\"";
219
        if ($cascade) {
220
            $sql .= ' CASCADE';
221
        }
222
223
        return $this->execute($sql);
224
    }
225
226
    /**
227
     * Creates a new enum type in the database.
228
     *
229
     * @param string $name       The name of the type
230
     * @param array  $values     An array of values
231
     * @param string $typcomment Type comment
232
     *
233
     * @return bool|int 0 success
234
     */
235
    public function createEnumType($name, $values, $typcomment)
236
    {
237
        $f_schema = $this->_schema;
238
        $this->fieldClean($f_schema);
239
        $this->fieldClean($name);
240
241
        if (empty($values)) {
242
            return -2;
243
        }
244
245
        $status = $this->beginTransaction();
246
        if ($status != 0) {
247
            return -1;
248
        }
249
250
        $values = array_unique($values);
251
252
        $nbval = count($values);
253
254
        for ($i = 0; $i < $nbval; ++$i) {
255
            $this->clean($values[$i]);
256
        }
257
258
        $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS ENUM ('";
259
        $sql .= implode("','", $values);
260
        $sql .= "')";
261
262
        $status = $this->execute($sql);
263
        if ($status) {
264
            $this->rollbackTransaction();
265
266
            return -1;
267
        }
268
269
        if ($typcomment != '') {
270
            $status = $this->setComment('TYPE', $name, '', $typcomment, true);
271
            if ($status) {
272
                $this->rollbackTransaction();
273
274
                return -1;
275
            }
276
        }
277
278
        return $this->endTransaction();
279
    }
280
281
    /**
282
     * Get defined values for a given enum.
283
     *
284
     * @param string $name
285
     *
286
     * @return \PHPPgAdmin\ADORecordSet A recordset
287
     */
288
    public function getEnumValues($name)
289
    {
290
        $this->clean($name);
291
292
        $sql = "SELECT enumlabel AS enumval
293
        FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON (t.oid=e.enumtypid)
294
        WHERE t.typname = '{$name}' ORDER BY e.oid";
295
296
        return $this->selectSet($sql);
297
    }
298
299
    // Operator functions
300
301
    /**
302
     * Creates a new composite type in the database.
303
     *
304
     * @param string $name       The name of the type
305
     * @param int    $fields     The number of fields
306
     * @param array  $field      An array of field names
307
     * @param array  $type       An array of field types
308
     * @param array  $array      An array of '' or '[]' for each type if it's an array or not
309
     * @param array  $length     An array of field lengths
310
     * @param array  $colcomment An array of comments
311
     * @param string $typcomment Type comment
312
     *
313
     * @return bool|int 0 success
314
     */
315
    public function createCompositeType($name, $fields, $field, $type, $array, $length, $colcomment, $typcomment)
316
    {
317
        $f_schema = $this->_schema;
318
        $this->fieldClean($f_schema);
319
        $this->fieldClean($name);
320
321
        $status = $this->beginTransaction();
322
        if ($status != 0) {
323
            return -1;
324
        }
325
326
        $found       = false;
327
        $first       = true;
328
        $comment_sql = ''; // Accumulate comments for the columns
329
        $sql         = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS (";
330
        for ($i = 0; $i < $fields; ++$i) {
331
            $this->fieldClean($field[$i]);
332
            $this->clean($type[$i]);
333
            $this->clean($length[$i]);
334
            $this->clean($colcomment[$i]);
335
336
            // Skip blank columns - for user convenience
337
            if ($field[$i] == '' || $type[$i] == '') {
338
                continue;
339
            }
340
341
            // If not the first column, add a comma
342
            if (!$first) {
343
                $sql .= ', ';
344
            } else {
345
                $first = false;
346
            }
347
348
            switch ($type[$i]) {
349
                // Have to account for weird placing of length for with/without
350
                // time zone types
351
                case 'timestamp with time zone':
352
                case 'timestamp without time zone':
353
                    $qual = substr($type[$i], 9);
354
                    $sql .= "\"{$field[$i]}\" timestamp";
355
                    if ($length[$i] != '') {
356
                        $sql .= "({$length[$i]})";
357
                    }
358
359
                    $sql .= $qual;
360
361
                    break;
362
                case 'time with time zone':
363
                case 'time without time zone':
364
                    $qual = substr($type[$i], 4);
365
                    $sql .= "\"{$field[$i]}\" time";
366
                    if ($length[$i] != '') {
367
                        $sql .= "({$length[$i]})";
368
                    }
369
370
                    $sql .= $qual;
371
372
                    break;
373
                default:
374
                    $sql .= "\"{$field[$i]}\" {$type[$i]}";
375
                    if ($length[$i] != '') {
376
                        $sql .= "({$length[$i]})";
377
                    }
378
            }
379
            // Add array qualifier if necessary
380
            if ($array[$i] == '[]') {
381
                $sql .= '[]';
382
            }
383
384
            if ($colcomment[$i] != '') {
385
                $comment_sql .= "COMMENT ON COLUMN \"{$f_schema}\".\"{$name}\".\"{$field[$i]}\" IS '{$colcomment[$i]}';\n";
386
            }
387
388
            $found = true;
389
        }
390
391
        if (!$found) {
0 ignored issues
show
introduced by
The condition $found is always false.
Loading history...
392
            return -1;
393
        }
394
395
        $sql .= ')';
396
397
        $status = $this->execute($sql);
398
        if ($status) {
399
            $this->rollbackTransaction();
400
401
            return -1;
402
        }
403
404
        if ($typcomment != '') {
405
            $status = $this->setComment('TYPE', $name, '', $typcomment, true);
406
            if ($status) {
407
                $this->rollbackTransaction();
408
409
                return -1;
410
            }
411
        }
412
413
        if ($comment_sql != '') {
414
            $status = $this->execute($comment_sql);
415
            if ($status) {
416
                $this->rollbackTransaction();
417
418
                return -1;
419
            }
420
        }
421
422
        return $this->endTransaction();
423
    }
424
425
    /**
426
     * Returns a list of all casts in the database.
427
     *
428
     * @return \PHPPgAdmin\ADORecordSet All casts
429
     */
430
    public function getCasts()
431
    {
432
        $conf = $this->conf;
433
434
        if ($conf['show_system']) {
435
            $where = '';
436
        } else {
437
            $where = '
438
                AND n1.nspname NOT LIKE $$pg\_%$$
439
                AND n2.nspname NOT LIKE $$pg\_%$$
440
                AND n3.nspname NOT LIKE $$pg\_%$$
441
            ';
442
        }
443
444
        $sql = "
445
            SELECT
446
                c.castsource::pg_catalog.regtype AS castsource,
447
                c.casttarget::pg_catalog.regtype AS casttarget,
448
                CASE WHEN c.castfunc=0 THEN NULL
449
                ELSE c.castfunc::pg_catalog.regprocedure END AS castfunc,
450
                c.castcontext,
451
                obj_description(c.oid, 'pg_cast') as castcomment
452
            FROM
453
                (pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p ON c.castfunc=p.oid JOIN pg_catalog.pg_namespace n3 ON p.pronamespace=n3.oid),
454
                pg_catalog.pg_type t1,
455
                pg_catalog.pg_type t2,
456
                pg_catalog.pg_namespace n1,
457
                pg_catalog.pg_namespace n2
458
            WHERE
459
                c.castsource=t1.oid
460
                AND c.casttarget=t2.oid
461
                AND t1.typnamespace=n1.oid
462
                AND t2.typnamespace=n2.oid
463
                {$where}
464
            ORDER BY 1, 2
465
        ";
466
467
        return $this->selectSet($sql);
468
    }
469
470
    /**
471
     * Returns a list of all conversions in the database.
472
     *
473
     * @return \PHPPgAdmin\ADORecordSet All conversions
474
     */
475
    public function getConversions()
476
    {
477
        $c_schema = $this->_schema;
478
        $this->clean($c_schema);
479
        $sql = "
480
            SELECT
481
                   c.conname,
482
                   pg_catalog.pg_encoding_to_char(c.conforencoding) AS conforencoding,
483
                   pg_catalog.pg_encoding_to_char(c.contoencoding) AS contoencoding,
484
                   c.condefault,
485
                   pg_catalog.obj_description(c.oid, 'pg_conversion') AS concomment
486
            FROM pg_catalog.pg_conversion c, pg_catalog.pg_namespace n
487
            WHERE n.oid = c.connamespace
488
                  AND n.nspname='{$c_schema}'
489
            ORDER BY 1;
490
        ";
491
492
        return $this->selectSet($sql);
493
    }
494
495
    abstract public function fieldClean(&$str);
496
497
    abstract public function beginTransaction();
498
499
    abstract public function rollbackTransaction();
500
501
    abstract public function endTransaction();
502
503
    abstract public function execute($sql);
504
505
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
506
507
    abstract public function selectSet($sql);
508
509
    abstract public function clean(&$str);
510
511
    abstract public function phpBool($parameter);
512
513
    abstract public function hasCreateTableLikeWithConstraints();
514
515
    abstract public function hasCreateTableLikeWithIndexes();
516
517
    abstract public function hasTablespaces();
518
519
    abstract public function delete($table, $conditions, $schema = '');
520
521
    abstract public function fieldArrayClean(&$arr);
522
523
    abstract public function hasCreateFieldWithConstraints();
524
525
    abstract public function getAttributeNames($table, $atts);
526
}
527