Test Failed
Push — master ( 34dd7c...325a03 )
by Felipe
11:17 queued 06:14
created

FunctionTrait::createFunction()   F

Complexity

Conditions 13
Paths 865

Size

Total Lines 86
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 86
rs 2.4575
c 0
b 0
f 0
cc 13
eloc 48
nc 865
nop 11

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.43
5
 */
6
7
namespace PHPPgAdmin\Traits;
8
9
/**
10
 * Common trait for full text search manipulation.
11
 */
12
trait FunctionTrait
13
{
14
15
    /**
16
     * Returns an array containing a function's properties.
17
     *
18
     * @param array $f The array of data for the function
19
     *
20
     * @return array An array containing the properties
21
     */
22
    public function getFunctionProperties($f)
23
    {
24
        $temp = [];
25
26
        // Volatility
27
        if ($f['provolatile'] == 'v') {
28
            $temp[] = 'VOLATILE';
29
        } elseif ($f['provolatile'] == 'i') {
30
            $temp[] = 'IMMUTABLE';
31
        } elseif ($f['provolatile'] == 's') {
32
            $temp[] = 'STABLE';
33
        } else {
34
            return -1;
0 ignored issues
show
Bug Best Practice introduced by
The expression return -1 returns the type integer which is incompatible with the documented return type array.
Loading history...
35
        }
36
37
        // Null handling
38
        $f['proisstrict'] = $this->phpBool($f['proisstrict']);
0 ignored issues
show
Bug introduced by
It seems like phpBool() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

38
        /** @scrutinizer ignore-call */ 
39
        $f['proisstrict'] = $this->phpBool($f['proisstrict']);
Loading history...
39
        if ($f['proisstrict']) {
40
            $temp[] = 'RETURNS NULL ON NULL INPUT';
41
        } else {
42
            $temp[] = 'CALLED ON NULL INPUT';
43
        }
44
45
        // Security
46
        $f['prosecdef'] = $this->phpBool($f['prosecdef']);
47
        if ($f['prosecdef']) {
48
            $temp[] = 'SECURITY DEFINER';
49
        } else {
50
            $temp[] = 'SECURITY INVOKER';
51
        }
52
53
        return $temp;
54
    }
55
56
    /**
57
     * Updates (replaces) a function.
58
     *
59
     * @param string $funcname     The name of the function to create
60
     * @param string $newname      The new name for the function
61
     * @param string  $args        imploded array of argument types
62
     * @param string $returns      The return type
63
     * @param string $definition   The definition for the new function
64
     * @param string $language     The language the function is written for
65
     * @param array  $flags        An array of optional flags
66
     * @param bool   $setof        True if returns a set, false otherwise
67
     * @param string $funcown
68
     * @param string $newown
69
     * @param string $funcschema
70
     * @param string $newschema
71
     * @param float  $cost
72
     * @param int    $rows
73
     * @param string $comment      The comment on the function
74
     *
75
     * @return bool|int 0 success
76
     */
77
    public function setFunction(
78
        $funcname,
79
        $newname,
80
        $args,
81
        $returns,
82
        $definition,
83
        $language,
84
        $flags,
85
        $setof,
86
        $funcown,
87
        $newown,
88
        $funcschema,
89
        $newschema,
90
        $cost,
91
        $rows,
92
        $comment
93
    ) {
94
        // Begin a transaction
95
        $status = $this->beginTransaction();
96
        if ($status != 0) {
97
            $this->rollbackTransaction();
98
99
            return -1;
100
        }
101
102
        // Replace the existing function
103
        $status = $this->createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, true);
104
        if ($status != 0) {
105
            $this->rollbackTransaction();
106
107
            return $status;
108
        }
109
110
        $f_schema = $this->_schema;
111
        $this->fieldClean($f_schema);
112
113
        // Rename the function, if necessary
114
        $this->fieldClean($newname);
115
        /* $funcname is escaped in createFunction */
116
        if ($funcname != $newname) {
117
            $sql    = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) RENAME TO \"{$newname}\"";
118
            $status = $this->execute($sql);
119
            if ($status != 0) {
120
                $this->rollbackTransaction();
121
122
                return -5;
123
            }
124
125
            $funcname = $newname;
126
        }
127
128
        // Alter the owner, if necessary
129
        if ($this->hasFunctionAlterOwner()) {
0 ignored issues
show
Bug introduced by
It seems like hasFunctionAlterOwner() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

129
        if ($this->/** @scrutinizer ignore-call */ hasFunctionAlterOwner()) {
Loading history...
130
            $this->fieldClean($newown);
131
            if ($funcown != $newown) {
132
                $sql    = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) OWNER TO \"{$newown}\"";
133
                $status = $this->execute($sql);
134
                if ($status != 0) {
135
                    $this->rollbackTransaction();
136
137
                    return -6;
138
                }
139
            }
140
        }
141
142
        // Alter the schema, if necessary
143
        if ($this->hasFunctionAlterSchema()) {
0 ignored issues
show
Bug introduced by
It seems like hasFunctionAlterSchema() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

143
        if ($this->/** @scrutinizer ignore-call */ hasFunctionAlterSchema()) {
Loading history...
144
            $this->fieldClean($newschema);
145
            /* $funcschema is escaped in createFunction */
146
            if ($funcschema != $newschema) {
147
                $sql    = "ALTER FUNCTION \"{$f_schema}\".\"{$funcname}\"({$args}) SET SCHEMA \"{$newschema}\"";
148
                $status = $this->execute($sql);
149
                if ($status != 0) {
150
                    $this->rollbackTransaction();
151
152
                    return -7;
153
                }
154
            }
155
        }
156
157
        return $this->endTransaction();
158
    }
159
160
    /**
161
     * Creates a new function.
162
     *
163
     * @param string $funcname   The name of the function to create
164
     * @param string $args       A comma separated string of types
165
     * @param string $returns    The return type
166
     * @param string $definition The definition for the new function
167
     * @param string $language   The language the function is written for
168
     * @param array  $flags      An array of optional flags
169
     * @param bool   $setof      True if it returns a set, false otherwise
170
     * @param string $cost       cost the planner should use in the function  execution step
171
     * @param int    $rows       number of rows planner should estimate will be returned
172
     * @param string $comment    Comment for the function
173
     * @param bool   $replace    (optional) True if OR REPLACE, false for
174
     *                           normal
175
     *
176
     * @return bool|int 0 success
177
     */
178
    public function createFunction($funcname, $args, $returns, $definition, $language, $flags, $setof, $cost, $rows, $comment, $replace = false)
179
    {
180
        // Begin a transaction
181
        $status = $this->beginTransaction();
182
        if ($status != 0) {
183
            $this->rollbackTransaction();
184
185
            return -1;
186
        }
187
188
        $this->fieldClean($funcname);
189
        $this->clean($args);
190
        $this->fieldClean($language);
191
        $this->arrayClean($flags);
0 ignored issues
show
Bug introduced by
It seems like arrayClean() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

191
        $this->/** @scrutinizer ignore-call */ 
192
               arrayClean($flags);
Loading history...
192
        $this->clean($cost);
193
        $this->clean($rows);
194
        $f_schema = $this->_schema;
195
        $this->fieldClean($f_schema);
196
197
        $sql = 'CREATE';
198
        if ($replace) {
199
            $sql .= ' OR REPLACE';
200
        }
201
202
        $sql .= " FUNCTION \"{$f_schema}\".\"{$funcname}\" (";
203
204
        if ($args != '') {
205
            $sql .= $args;
206
        }
207
208
        // For some reason, the returns field cannot have quotes...
209
        $sql .= ') RETURNS ';
210
        if ($setof) {
211
            $sql .= 'SETOF ';
212
        }
213
214
        $sql .= "{$returns} AS ";
215
216
        if (is_array($definition)) {
1 ignored issue
show
introduced by
The condition is_array($definition) is always false.
Loading history...
217
            $this->arrayClean($definition);
218
            $sql .= "'" . $definition[0] . "'";
219
            if ($definition[1]) {
220
                $sql .= ",'" . $definition[1] . "'";
221
            }
222
        } else {
223
            $this->clean($definition);
224
            $sql .= "'" . $definition . "'";
225
        }
226
227
        $sql .= " LANGUAGE \"{$language}\"";
228
229
        // Add costs
230
        if (!empty($cost)) {
231
            $sql .= " COST {$cost}";
232
        }
233
234
        if ($rows != 0) {
235
            $sql .= " ROWS {$rows}";
236
        }
237
238
        // Add flags
239
        foreach ($flags as $v) {
240
            // Skip default flags
241
            if ($v == '') {
242
                continue;
243
            }
244
245
            $sql .= "\n{$v}";
246
        }
247
248
        $status = $this->execute($sql);
249
        if ($status != 0) {
250
            $this->rollbackTransaction();
251
252
            return -3;
253
        }
254
255
        /* set the comment */
256
        $status = $this->setComment('FUNCTION', "\"{$funcname}\"({$args})", null, $comment);
257
        if ($status != 0) {
258
            $this->rollbackTransaction();
259
260
            return -4;
261
        }
262
263
        return $this->endTransaction();
264
    }
265
266
    /**
267
     * Drops a function.
268
     *
269
     * @param int  $function_oid The OID of the function to drop
270
     * @param bool $cascade      True to cascade drop, false to restrict
271
     *
272
     * @return int 0 if operation was successful
273
     */
274
    public function dropFunction($function_oid, $cascade)
275
    {
276
        // Function comes in with $object as function OID
277
        $fn       = $this->getFunction($function_oid);
278
        $f_schema = $this->_schema;
279
        $this->fieldClean($f_schema);
280
        $this->fieldClean($fn->fields['proname']);
281
282
        $sql = "DROP FUNCTION \"{$f_schema}\".\"{$fn->fields['proname']}\"({$fn->fields['proarguments']})";
283
        if ($cascade) {
284
            $sql .= ' CASCADE';
285
        }
286
287
        return $this->execute($sql);
288
    }
289
290
    /**
291
     * Returns all details for a particular function.
292
     *
293
     * @param int $function_oid
294
     *
295
     * @return \PHPPgAdmin\ADORecordSet Function info
296
     *
297
     * @internal param string The $func name of the function to retrieve
298
     */
299
    public function getFunction($function_oid)
300
    {
301
        $this->clean($function_oid);
302
303
        $sql = "
304
            SELECT
305
                pc.oid AS prooid, proname,
306
                pg_catalog.pg_get_userbyid(proowner) AS proowner,
307
                nspname as proschema, lanname as prolanguage, procost, prorows,
308
                pg_catalog.format_type(prorettype, NULL) as proresult, prosrc,
309
                probin, proretset, proisstrict, provolatile, prosecdef,
310
                pg_catalog.oidvectortypes(pc.proargtypes) AS proarguments,
311
                proargnames AS proargnames,
312
                pg_catalog.obj_description(pc.oid, 'pg_proc') AS procomment,
313
                proconfig,
314
                (select array_agg( (select typname from pg_type pt
315
                    where pt.oid = p.oid) ) from unnest(proallargtypes) p)
316
                AS proallarguments,
317
                proargmodes
318
            FROM
319
                pg_catalog.pg_proc pc, pg_catalog.pg_language pl,
320
                pg_catalog.pg_namespace pn
321
            WHERE
322
                pc.oid = '{$function_oid}'::oid AND pc.prolang = pl.oid
323
                AND pc.pronamespace = pn.oid
324
            ";
325
326
        return $this->selectSet($sql);
327
    }
328
329
    abstract public function fieldClean(&$str);
330
331
    abstract public function beginTransaction();
332
333
    abstract public function rollbackTransaction();
334
335
    abstract public function endTransaction();
336
337
    abstract public function execute($sql);
338
339
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
340
341
    abstract public function selectSet($sql);
342
343
    abstract public function clean(&$str);
344
}
345