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

ViewsMatviewsTrait::doSaveCreateWiz()   F

Complexity

Conditions 25
Paths 1826

Size

Total Lines 111
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 63
nc 1826
nop 1
dl 0
loc 111
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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\Traits;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Common trait for dealing with views or materialized views.
13
 */
14
trait ViewsMatviewsTrait
15
{
16
    public $href = '';
17
    public $misc;
18
    public $view_name;
19
20
    public function doSubTree()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
21
    {
22
        $tabs    = $this->misc->getNavTabs($this->keystring);
0 ignored issues
show
Bug introduced by
The property keystring 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...
23
        $items   = $this->adjustTabsForTree($tabs);
0 ignored issues
show
Bug introduced by
It seems like adjustTabsForTree() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
24
        $reqvars = $this->misc->getRequestVars($this->keystring);
25
26
        $attrs = [
27
            'text'   => Decorator::field('title'),
28
            'icon'   => Decorator::field('icon'),
29
            'action' => Decorator::actionurl(Decorator::field('url'), $reqvars, Decorator::field('urlvars'), [$this->keystring => $_REQUEST[$this->keystring]]),
30
            'branch' => Decorator::ifempty(
31
                Decorator::field('branch'),
32
                '',
33
                Decorator::url(
34
                    Decorator::field('url'),
35
                    Decorator::field('urlvars'),
36
                    $reqvars,
37
                    [
38
                        'action'         => 'tree',
39
                        $this->keystring => $_REQUEST[$this->keystring],
40
                    ]
41
                )
42
            ),
43
        ];
44
45
        return $this->printTree($items, $attrs, $this->keystring);
0 ignored issues
show
Bug introduced by
It seems like printTree() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
46
    }
47
48
    /**
49
     * Ask for select parameters and perform select.
50
     *
51
     * @param mixed $confirm
52
     * @param mixed $msg
53
     */
54
    public function doSelectRows($confirm, $msg = '')
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
55
    {
56
        $data = $this->misc->getDatabaseAccessor();
57
58
        if ($confirm) {
59
            $this->printTrail($this->keystring);
0 ignored issues
show
Bug introduced by
It seems like printTrail() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
60
            $this->printTabs($this->keystring, 'select');
0 ignored issues
show
Bug introduced by
It seems like printTabs() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
61
            $this->printMsg($msg);
0 ignored issues
show
Bug introduced by
It seems like printMsg() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
62
63
            $attrs = $data->getTableAttributes($_REQUEST[$this->keystring]);
64
65
            echo '<form action="'.\SUBFOLDER.'/src/views/'.$this->script.'" method="post" id="selectform">';
0 ignored issues
show
Bug introduced by
The property script 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...
66
            echo PHP_EOL;
67
68 View Code Duplication
            if ($attrs->recordCount() > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
69
                // JavaScript for select all feature
70
                echo '<script type="text/javascript">'.PHP_EOL;
71
                echo "//<![CDATA[\n";
72
                echo "  function selectAll() {\n";
73
                echo "      for (var i=0; i<document.getElementById('selectform').elements.length; i++) {\n";
74
                echo "          var e = document.getElementById('selectform').elements[i];\n";
75
                echo "          if (e.name.indexOf('show') == 0) { \n ";
76
                echo "              e.checked = document.getElementById('selectform').selectall.checked;\n";
77
                echo "          }\n";
78
                echo "      }\n";
79
                echo "  }\n";
80
                echo '//]]>'.PHP_EOL;
81
                echo '</script>'.PHP_EOL;
82
83
                echo '<table>'.PHP_EOL;
84
85
                // Output table header
86
                echo "<tr><th class=\"data\">{$this->lang['strshow']}</th><th class=\"data\">{$this->lang['strcolumn']}</th>";
0 ignored issues
show
Bug introduced by
The property lang 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...
87
                echo "<th class=\"data\">{$this->lang['strtype']}</th><th class=\"data\">{$this->lang['stroperator']}</th>";
88
                echo "<th class=\"data\">{$this->lang['strvalue']}</th></tr>";
89
90
                $i = 0;
91
                while (!$attrs->EOF) {
92
                    $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
93
                    // Set up default value if there isn't one already
94
                    if (!isset($_REQUEST['values'][$attrs->fields['attname']])) {
95
                        $_REQUEST['values'][$attrs->fields['attname']] = null;
96
                    }
97
98
                    if (!isset($_REQUEST['ops'][$attrs->fields['attname']])) {
99
                        $_REQUEST['ops'][$attrs->fields['attname']] = null;
100
                    }
101
102
                    // Continue drawing row
103
                    $id = (0 == ($i % 2) ? '1' : '2');
104
                    echo "<tr class=\"data{$id}\">".PHP_EOL;
105
                    echo '<td style="white-space:nowrap;">';
106
                    echo '<input type="checkbox" name="show[', htmlspecialchars($attrs->fields['attname']), ']"',
107
                    isset($_REQUEST['show'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /></td>';
108
                    echo '<td style="white-space:nowrap;">', $this->misc->printVal($attrs->fields['attname']), '</td>';
109
                    echo '<td style="white-space:nowrap;">', $this->misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod'])), '</td>';
110
                    echo '<td style="white-space:nowrap;">';
111
                    echo "<select name=\"ops[{$attrs->fields['attname']}]\">".PHP_EOL;
112
                    foreach (array_keys($data->selectOps) as $v) {
113
                        echo '<option value="', htmlspecialchars($v), '"', ($_REQUEST['ops'][$attrs->fields['attname']] == $v) ? ' selected="selected"' : '',
114
                        '>', htmlspecialchars($v), '</option>'.PHP_EOL;
115
                    }
116
                    echo '</select></td>'.PHP_EOL;
117
                    echo '<td style="white-space:nowrap;">', $data->printField(
118
                        "values[{$attrs->fields['attname']}]",
119
                        $_REQUEST['values'][$attrs->fields['attname']],
120
                        $attrs->fields['type']
121
                    ), '</td>';
122
                    echo '</tr>'.PHP_EOL;
123
                    ++$i;
124
                    $attrs->moveNext();
125
                }
126
                // Select all checkbox
127
                echo "<tr><td colspan=\"5\"><input type=\"checkbox\" id=\"selectall\" name=\"selectall\" accesskey=\"a\" onclick=\"javascript:selectAll()\" /><label for=\"selectall\">{$this->lang['strselectallfields']}</label></td></tr>";
128
                echo '</table>'.PHP_EOL;
129
            } else {
130
                echo "<p>{$this->lang['strinvalidparam']}</p>".PHP_EOL;
131
            }
132
133
            echo '<p><input type="hidden" name="action" value="selectrows" />'.PHP_EOL;
134
            echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST[$this->keystring]), '" />'.PHP_EOL;
135
            echo '<input type="hidden" name="subject" value="view" />'.PHP_EOL;
136
            echo $this->misc->form;
137
            echo "<input type=\"submit\" name=\"select\" accesskey=\"r\" value=\"{$this->lang['strselect']}\" />".PHP_EOL;
138
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
139
            echo '</form>'.PHP_EOL;
140
141
            return;
142
        }
143
        $this->coalesceArr($_POST, 'show', []);
0 ignored issues
show
Bug introduced by
It seems like coalesceArr() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
144
145
        $this->coalesceArr($_POST, 'values', []);
0 ignored issues
show
Bug introduced by
It seems like coalesceArr() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
146
147
        $this->coalesceArr($_POST, 'nulls', []);
0 ignored issues
show
Bug introduced by
It seems like coalesceArr() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
148
149
        // Verify that they haven't supplied a value for unary operators
150 View Code Duplication
        foreach ($_POST['ops'] as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
151
            if ('p' == $data->selectOps[$v] && $_POST['values'][$k] != '') {
152
                $this->doSelectRows(true, $this->lang['strselectunary']);
153
154
                return;
155
            }
156
        }
157
158
        if (0 == sizeof($_POST['show'])) {
159
            return $this->doSelectRows(true, $this->lang['strselectneedscol']);
160
        }
161
        // Generate query SQL
162
        $query = $data->getSelectSQL($_REQUEST[$this->keystring], array_keys($_POST['show']), $_POST['values'], $_POST['ops']);
163
164
        $_REQUEST['query']  = $query;
165
        $_REQUEST['return'] = 'schema';
166
167
        $this->setNoOutput(true);
0 ignored issues
show
Bug introduced by
It seems like setNoOutput() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
168
169
        $display_controller = new \PHPPgAdmin\Controller\DisplayController($this->getContainer());
0 ignored issues
show
Bug introduced by
It seems like getContainer() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
170
171
        return $display_controller->render();
172
    }
173
174
    /**
175
     * Prints the form wizard to create view or materialized view.
176
     */
177
    public function printWizardCreateForm()
178
    {
179
        $data = $this->misc->getDatabaseAccessor();
180
181
        $tables = $data->getAllTables();
182
183
        echo '<form action="'.\SUBFOLDER."/src/views/{$this->script}\" method=\"post\">".PHP_EOL;
184
        echo '<table>'.PHP_EOL;
185
        echo "<tr><th class=\"data\">{$this->lang['strtables']}</th></tr>";
186
        echo "<tr>\n<td class=\"data1\">".PHP_EOL;
187
188
        $arrTables = [];
189
        while (!$tables->EOF) {
190
            $arrTmp                      = [];
191
            $arrTmp['schemaname']        = $tables->fields['nspname'];
192
            $arrTmp['tablename']         = $tables->fields['relname'];
193
            $schema_and_name             = $tables->fields['nspname'].'.'.$tables->fields['relname'];
194
            $arrTables[$schema_and_name] = serialize($arrTmp);
195
            $tables->moveNext();
196
        }
197
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrTables, 'formTables[]', false, '', true);
198
199
        echo "</td>\n</tr>".PHP_EOL;
200
        echo '</table>'.PHP_EOL;
201
        echo '<p><input type="hidden" name="action" value="set_params_create" />'.PHP_EOL;
202
        echo $this->misc->form;
203
        echo "<input type=\"submit\" value=\"{$this->lang['strnext']}\" />".PHP_EOL;
204
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
205
        echo '</form>'.PHP_EOL;
206
    }
207
208
    /**
209
     * Appends to selected fields.
210
     *
211
     * @param array  $arrTmp    The arr temporary
212
     * @param string $selFields The selected fields
213
     * @param array  $tmpHsh    The temporary hsh
214
     */
215
    private function _appendToSelFields($arrTmp, &$selFields, &$tmpHsh)
216
    {
217
        $field_arr = [$arrTmp['schemaname'], $arrTmp['tablename'], $arrTmp['fieldname']];
218
219
        $field_element = '"'.implode('"."', $field_arr).'"';
220
        if (empty($_POST['dblFldMeth'])) {
221
            // no doublon control
222
            $selFields .= $field_element.', ';
223
        } elseif (empty($tmpHsh[$arrTmp['fieldname']])) {
224
            // field does not exist
225
            $selFields .= $field_element.', ';
226
            $tmpHsh[$arrTmp['fieldname']] = 1;
227
        } elseif ('rename' == $_POST['dblFldMeth']) {
228
            // field exist and must be renamed
229
            ++$tmpHsh[$arrTmp['fieldname']];
230
            $selFields .= $field_element.'  AS  "'.implode('_', $field_arr).'_'.$tmpHsh[$arrTmp['fieldname']].'", ';
231
        }
232
        //  if field already exist, just ignore this one
233
    }
234
235
    private function _getArrLinks()
236
    {
237
        $arrLinks = [];
238
        $count    = 0;
239
        // If we have links, out put the JOIN ... ON statements
240
        if (is_array($_POST['formLink'])) {
241
            // Filter out invalid/blank entries for our links
242
243
            foreach ($_POST['formLink'] as $curLink) {
244
                if (strlen($curLink['leftlink']) && strlen($curLink['rightlink']) && strlen($curLink['operator'])) {
245
                    $arrLinks[] = $curLink;
246
                }
247
            }
248
            // We must perform some magic to make sure that we have a valid join order
249
            $count = sizeof($arrLinks);
250
        }
251
252
        return [$arrLinks, $count];
253
    }
254
255
    /**
256
     * Actually creates the new wizard view in the database.
257
     *
258
     * @param bool $is_materialized true if it's a materialized view, false by default
259
     *
260
     * @return mixed either a sucess message, a redirection, an error message and who knows
261
     */
262
    public function doSaveCreateWiz($is_materialized = false)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $is_materialized 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...
263
    {
264
        $data = $this->misc->getDatabaseAccessor();
265
266
        // Check that they've given a name and fields they want to select
267
268
        if (!strlen($_POST['formView'])) {
269
            return $this->doSetParamsCreate($this->lang['strviewneedsname']);
270
        }
271
        if (!isset($_POST['formFields']) || !count($_POST['formFields'])) {
272
            return $this->doSetParamsCreate($this->lang['strviewneedsfields']);
273
        }
274
        $selFields = '';
275
276
        $tmpHsh = [];
277
278
        foreach ($_POST['formFields'] as $curField) {
279
            $arrTmp = unserialize($curField);
280
            $data->fieldArrayClean($arrTmp);
281
282
            $this->_appendToSelFields($arrTmp, $selFields, $tmpHsh);
283
        }
284
285
        $selFields = substr($selFields, 0, -2);
286
        unset($arrTmp, $tmpHsh);
287
        $linkFields  = '';
288
        $arrJoined   = [];
289
        $arrUsedTbls = [];
290
291
        list($arrLinks, $count) = $this->_getArrLinks();
292
293
        // If we have at least one join condition, output it
294
295
        $j = 0;
296
297
        while ($j < $count) {
298
            foreach ($arrLinks as $curLink) {
299
                $arrLeftLink  = unserialize($curLink['leftlink']);
300
                $arrRightLink = unserialize($curLink['rightlink']);
301
                $data->fieldArrayClean($arrLeftLink);
302
                $data->fieldArrayClean($arrRightLink);
303
304
                $tbl1 = "\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\"";
305
                $tbl2 = "\"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\"";
306
307
                if (!((!in_array($curLink, $arrJoined, true) && in_array($tbl1, $arrUsedTbls, true)) || !count($arrJoined))) {
308
                    continue;
309
                }
310
                // Make sure for multi-column foreign keys that we use a table alias tables joined to more than once
311
                // This can (and should be) more optimized for multi-column foreign keys
312
                $adj_tbl2 = in_array($tbl2, $arrUsedTbls, true) ? "${tbl2} AS alias_ppa_".time() : $tbl2;
313
314
                $clause1 = "{$curLink['operator']} ${adj_tbl2} ON ({$tbl1}.\"{$arrLeftLink['fieldname']}\" = {$tbl2}.\"{$arrRightLink['fieldname']}\") ";
315
                $clause2 = "${tbl1} {$curLink['operator']} ${adj_tbl2} ON ({$tbl1}.\"{$arrLeftLink['fieldname']}\" = {$tbl2}.\"{$arrRightLink['fieldname']}\") ";
316
317
                $linkFields .= strlen($linkFields) ? $clause1 : $clause2;
318
319
                $arrJoined[] = $curLink;
320
                if (!in_array($tbl1, $arrUsedTbls, true)) {
321
                    $arrUsedTbls[] = $tbl1;
322
                }
323
324
                if (!in_array($tbl2, $arrUsedTbls, true)) {
325
                    $arrUsedTbls[] = $tbl2;
326
                }
327
            }
328
            ++$j;
329
        }
330
331
        //if linkFields has no length then either _POST['formLink'] was not set, or there were no join conditions
332
        //just select from all seleted tables - a cartesian join do a
333
        if (!strlen($linkFields)) {
334
            foreach ($_POST['formTables'] as $curTable) {
335
                $arrTmp = unserialize($curTable);
336
                $data->fieldArrayClean($arrTmp);
337
                $linkFields .= (strlen($linkFields) ? ', ' : ' ')."\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"";
338
            }
339
        }
340
341
        $addConditions = '';
342
        if (is_array($_POST['formCondition'])) {
343
            foreach ($_POST['formCondition'] as $curCondition) {
344
                if (strlen($curCondition['field']) && strlen($curCondition['txt'])) {
345
                    $arrTmp = unserialize($curCondition['field']);
346
                    $data->fieldArrayClean($arrTmp);
347
                    $condition = " \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' ";
348
                    $addConditions .= (strlen($addConditions) ? ' AND ' : ' ').$condition;
349
                }
350
            }
351
        }
352
353
        $viewQuery = "SELECT ${selFields} FROM ${linkFields} ";
354
355
        //add where from additional conditions
356
        if (strlen($addConditions)) {
357
            $viewQuery .= ' WHERE '.$addConditions;
358
        }
359
360
        try {
361
            $status = $data->createView($_POST['formView'], $viewQuery, false, $_POST['formComment'], $is_materialized);
362
            if (0 == $status) {
363
                $this->misc->setReloadBrowser(true);
364
365
                return $this->doDefault($this->lang['strviewcreated']);
0 ignored issues
show
Bug introduced by
It seems like doDefault() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
366
            }
367
368
            return $this->doSetParamsCreate($this->lang['strviewcreatedbad']);
369
        } catch (\PHPPgAdmin\ADOdbException $e) {
370
            return $this->halt($e->getMessage());
0 ignored issues
show
Bug introduced by
It seems like halt() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
371
        }
372
    }
373
374
    public function printParamsCreateForm()
375
    {
376
        $data = $this->misc->getDatabaseAccessor();
377
378
        $tblCount     = sizeof($_POST['formTables']);
379
        $arrSelTables = [];
380
        //unserialize our schema/table information and store in arrSelTables
381
        for ($i = 0; $i < $tblCount; ++$i) {
382
            $arrSelTables[] = unserialize($_POST['formTables'][$i]);
383
        }
384
385
        //get linking keys
386
        $rsLinkKeys = $data->getLinkingKeys($arrSelTables);
387
        $linkCount  = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
388
389
        $arrFields = []; //array that will hold all our table/field names
390
391
        //if we have schemas we need to specify the correct schema for each table we're retrieiving
392
        //with getTableAttributes
393
        $curSchema = $data->_schema;
394
        for ($i = 0; $i < $tblCount; ++$i) {
395
            if ($arrSelTables[$i]['schemaname'] != $data->_schema) {
396
                $data->setSchema($arrSelTables[$i]['schemaname']);
397
            }
398
399
            $attrs = $data->getTableAttributes($arrSelTables[$i]['tablename']);
400
            while (!$attrs->EOF) {
401
                $arrFields["{$arrSelTables[$i]['schemaname']}.{$arrSelTables[$i]['tablename']}.{$attrs->fields['attname']}"] = serialize(
402
                    [
403
                        'schemaname' => $arrSelTables[$i]['schemaname'],
404
                        'tablename'  => $arrSelTables[$i]['tablename'],
405
                        'fieldname'  => $attrs->fields['attname'], ]
406
                );
407
                $attrs->moveNext();
408
            }
409
410
            $data->setSchema($curSchema);
411
        }
412
        asort($arrFields);
413
414
        echo '<form action="'.\SUBFOLDER.'/src/views/materializedviews" method="post">'.PHP_EOL;
415
        echo '<table>'.PHP_EOL;
416
        echo "<tr><th class=\"data\">{$this->lang['strviewname']}</th></tr>";
417
        echo "<tr>\n<td class=\"data1\">".PHP_EOL;
418
        // View name
419
        echo '<input name="formView" value="'.htmlspecialchars($_REQUEST['formView'])."\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" />".PHP_EOL;
420
        echo "</td>\n</tr>".PHP_EOL;
421
        echo "<tr><th class=\"data\">{$this->lang['strcomment']}</th></tr>";
422
        echo "<tr>\n<td class=\"data1\">".PHP_EOL;
423
        // View comments
424
        echo '<textarea name="formComment" rows="3" cols="32">'.htmlspecialchars($_REQUEST['formComment']).'</textarea>'.PHP_EOL;
425
        echo "</td>\n</tr>".PHP_EOL;
426
        echo '</table>'.PHP_EOL;
427
428
        // Output selector for fields to be retrieved from view
429
        echo '<table>'.PHP_EOL;
430
        echo "<tr><th class=\"data\">{$this->lang['strcolumns']}</th></tr>";
431
        echo "<tr>\n<td class=\"data1\">".PHP_EOL;
432
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, 'formFields[]', false, '', true);
433
        echo "</td>\n</tr>";
434
        echo '<tr><td>';
435
        echo sprintf('<input type="radio" name="dblFldMeth" id="dblFldMeth1" value="rename" /><label for="dblFldMeth1">%s</label><br>', $this->lang['strrenamedupfields']);
436
        echo sprintf('<input type="radio" name="dblFldMeth" id="dblFldMeth2" value="drop" /><label for="dblFldMeth2">%s</label><br>', $this->lang['strdropdupfields']);
437
        echo sprintf('<input type="radio" name="dblFldMeth" id="dblFldMeth3" value="" checked="checked" /><label for="dblFldMeth3">%s</label>', $this->lang['strerrordupfields']);
438
        echo '</td></tr></table><br />';
439
440
        // Output the Linking keys combo boxes
441
        echo '<table>'.PHP_EOL;
442
        echo "<tr><th class=\"data\">{$this->lang['strviewlink']}</th></tr>";
443
        $rowClass = 'data1';
444
        $formLink = [];
445
        for ($i = 0; $i < $linkCount; ++$i) {
446
            // Initialise variables
447
            $this->coalesceArr($formLink[$i], 'operator', 'INNER JOIN');
0 ignored issues
show
Bug introduced by
It seems like coalesceArr() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
448
449
            echo "<tr>\n<td class=\"{$rowClass}\">".PHP_EOL;
450
451
            if (!$rsLinkKeys->EOF) {
452
                $curLeftLink  = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['p_schema'], 'tablename' => $rsLinkKeys->fields['p_table'], 'fieldname' => $rsLinkKeys->fields['p_field']]));
453
                $curRightLink = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['f_schema'], 'tablename' => $rsLinkKeys->fields['f_table'], 'fieldname' => $rsLinkKeys->fields['f_field']]));
454
                $rsLinkKeys->moveNext();
455
            } else {
456
                $curLeftLink  = '';
457
                $curRightLink = '';
458
            }
459
460
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[${i}][leftlink]", true, $curLeftLink, false);
461
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($data->joinOps, "formLink[${i}][operator]", true, $formLink[$i]['operator']);
462
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[${i}][rightlink]", true, $curRightLink, false);
463
            echo "</td>\n</tr>".PHP_EOL;
464
            $rowClass = 'data1' == $rowClass ? 'data2' : 'data1';
465
        }
466
        echo "</table>\n<br />".PHP_EOL;
467
468
        // Build list of available operators (infix only)
469
        $arrOperators = [];
470
        foreach ($data->selectOps as $k => $v) {
471
            if ('i' == $v) {
472
                $arrOperators[$k] = $k;
473
            }
474
        }
475
476
        // Output additional conditions, note that this portion of the wizard treats the right hand side as literal values
477
        //(not as database objects) so field names will be treated as strings, use the above linking keys section to perform joins
478
        echo '<table>'.PHP_EOL;
479
        echo "<tr><th class=\"data\">{$this->lang['strviewconditions']}</th></tr>";
480
        $rowClass = 'data1';
481
        for ($i = 0; $i < $linkCount; ++$i) {
482
            echo "<tr>\n<td class=\"${rowClass}\">".PHP_EOL;
483
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formCondition[${i}][field]");
484
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrOperators, "formCondition[${i}][operator]", false, '', false);
485
            echo "<input type=\"text\" name=\"formCondition[${i}][txt]\" />".PHP_EOL;
486
            echo "</td>\n</tr>".PHP_EOL;
487
            $rowClass = 'data1' == $rowClass ? 'data2' : 'data1';
488
        }
489
        echo '</table>'.PHP_EOL;
490
        echo '<p><input type="hidden" name="action" value="save_create_wiz" />'.PHP_EOL;
491
492
        foreach ($arrSelTables as $curTable) {
493
            echo '<input type="hidden" name="formTables[]" value="'.htmlspecialchars(serialize($curTable)).'" />'.PHP_EOL;
494
        }
495
496
        echo $this->misc->form;
497
        echo "<input type=\"submit\" value=\"{$this->lang['strcreate']}\" />".PHP_EOL;
498
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
499
        echo '</form>'.PHP_EOL;
500
    }
501
502
    abstract public function doSetParamsCreate($msg = '');
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...
503
}
504