Total Complexity | 112 |
Total Lines | 881 |
Duplicated Lines | 100 % |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like MaterializedviewsController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use MaterializedviewsController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | View Code Duplication | class MaterializedviewsController extends BaseController |
|
|
|||
11 | { |
||
12 | public $script = 'materializedviews.php'; |
||
13 | public $_name = 'MaterializedviewsController'; |
||
14 | public $table_place = 'matviews-matviews'; |
||
15 | |||
16 | public function render() |
||
17 | { |
||
18 | $conf = $this->conf; |
||
19 | $misc = $this->misc; |
||
20 | $lang = $this->lang; |
||
21 | $action = $this->action; |
||
22 | |||
23 | if ($action == 'tree') { |
||
24 | return $this->doTree(); |
||
25 | } elseif ($action == 'subtree') { |
||
26 | return $this->doSubTree(); |
||
27 | } |
||
28 | |||
29 | $data = $misc->getDatabaseAccessor(); |
||
30 | |||
31 | $this->printHeader('M ' . $lang['strviews']); |
||
32 | $this->printBody(); |
||
33 | |||
34 | switch ($action) { |
||
35 | case 'selectrows': |
||
36 | if (!isset($_REQUEST['cancel'])) { |
||
37 | $this->doSelectRows(false); |
||
38 | } else { |
||
39 | $this->doDefault(); |
||
40 | } |
||
41 | |||
42 | break; |
||
43 | case 'confselectrows': |
||
44 | $this->doSelectRows(true); |
||
45 | break; |
||
46 | case 'save_create_wiz': |
||
47 | if (isset($_REQUEST['cancel'])) { |
||
48 | $this->doDefault(); |
||
49 | } else { |
||
50 | $this->doSaveCreateWiz(); |
||
51 | } |
||
52 | |||
53 | break; |
||
54 | case 'wiz_create': |
||
55 | $this->doWizardCreate(); |
||
56 | break; |
||
57 | case 'set_params_create': |
||
58 | if (isset($_POST['cancel'])) { |
||
59 | $this->doDefault(); |
||
60 | } else { |
||
61 | $this->doSetParamsCreate(); |
||
62 | } |
||
63 | |||
64 | break; |
||
65 | case 'save_create': |
||
66 | if (isset($_REQUEST['cancel'])) { |
||
67 | $this->doDefault(); |
||
68 | } else { |
||
69 | $this->doSaveCreate(); |
||
70 | } |
||
71 | |||
72 | break; |
||
73 | case 'create': |
||
74 | $this->doCreate(); |
||
75 | break; |
||
76 | case 'drop': |
||
77 | if (isset($_POST['drop'])) { |
||
78 | $this->doDrop(false); |
||
79 | } else { |
||
80 | $this->doDefault(); |
||
81 | } |
||
82 | |||
83 | break; |
||
84 | case 'confirm_drop': |
||
85 | $this->doDrop(true); |
||
86 | break; |
||
87 | default: |
||
88 | $this->doDefault(); |
||
89 | break; |
||
90 | } |
||
91 | |||
92 | $this->printFooter(); |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * Show default list of views in the database |
||
97 | */ |
||
98 | public function doDefault($msg = '') |
||
99 | { |
||
100 | $conf = $this->conf; |
||
101 | $misc = $this->misc; |
||
102 | $lang = $this->lang; |
||
103 | $data = $misc->getDatabaseAccessor(); |
||
104 | |||
105 | $this->printTrail('schema'); |
||
106 | $this->printTabs('schema', 'matviews'); |
||
107 | $this->printMsg($msg); |
||
108 | |||
109 | //$matviews = $data->getViews(); |
||
110 | $matviews = $data->getMaterializedViews(); |
||
111 | |||
112 | $columns = [ |
||
113 | 'matview' => [ |
||
114 | 'title' => 'M ' . $lang['strview'], |
||
115 | 'field' => Decorator::field('relname'), |
||
116 | 'url' => SUBFOLDER . "/redirect/matview?{$misc->href}&", |
||
117 | 'vars' => ['matview' => 'relname'], |
||
118 | ], |
||
119 | 'owner' => [ |
||
120 | 'title' => $lang['strowner'], |
||
121 | 'field' => Decorator::field('relowner'), |
||
122 | ], |
||
123 | 'actions' => [ |
||
124 | 'title' => $lang['stractions'], |
||
125 | ], |
||
126 | 'comment' => [ |
||
127 | 'title' => $lang['strcomment'], |
||
128 | 'field' => Decorator::field('relcomment'), |
||
129 | ], |
||
130 | ]; |
||
131 | |||
132 | $actions = [ |
||
133 | 'multiactions' => [ |
||
134 | 'keycols' => ['matview' => 'relname'], |
||
135 | 'url' => 'materializedviews.php', |
||
136 | ], |
||
137 | 'browse' => [ |
||
138 | 'content' => $lang['strbrowse'], |
||
139 | 'attr' => [ |
||
140 | 'href' => [ |
||
141 | 'url' => 'display.php', |
||
142 | 'urlvars' => [ |
||
143 | 'action' => 'confselectrows', |
||
144 | 'subject' => 'matview', |
||
145 | 'return' => 'schema', |
||
146 | 'matview' => Decorator::field('relname'), |
||
147 | ], |
||
148 | ], |
||
149 | ], |
||
150 | ], |
||
151 | 'select' => [ |
||
152 | 'content' => $lang['strselect'], |
||
153 | 'attr' => [ |
||
154 | 'href' => [ |
||
155 | 'url' => 'materializedviews.php', |
||
156 | 'urlvars' => [ |
||
157 | 'action' => 'confselectrows', |
||
158 | 'matview' => Decorator::field('relname'), |
||
159 | ], |
||
160 | ], |
||
161 | ], |
||
162 | ], |
||
163 | |||
164 | // Insert is possible if the relevant rule for the view has been created. |
||
165 | // 'insert' => array( |
||
166 | // 'title' => $lang['strinsert'], |
||
167 | // 'url' => "materializedviews.php?action=confinsertrow&{$misc->href}&", |
||
168 | // 'vars' => array('view' => 'relname'), |
||
169 | // ), |
||
170 | |||
171 | 'alter' => [ |
||
172 | 'content' => $lang['stralter'], |
||
173 | 'attr' => [ |
||
174 | 'href' => [ |
||
175 | 'url' => 'materializedviewproperties.php', |
||
176 | 'urlvars' => [ |
||
177 | 'action' => 'confirm_alter', |
||
178 | 'matview' => Decorator::field('relname'), |
||
179 | ], |
||
180 | ], |
||
181 | ], |
||
182 | ], |
||
183 | 'drop' => [ |
||
184 | 'multiaction' => 'confirm_drop', |
||
185 | 'content' => $lang['strdrop'], |
||
186 | 'attr' => [ |
||
187 | 'href' => [ |
||
188 | 'url' => 'materializedviews.php', |
||
189 | 'urlvars' => [ |
||
190 | 'action' => 'confirm_drop', |
||
191 | 'matview' => Decorator::field('relname'), |
||
192 | ], |
||
193 | ], |
||
194 | ], |
||
195 | ], |
||
196 | ]; |
||
197 | |||
198 | echo $this->printTable($matviews, $columns, $actions, $this->table_place, $lang['strnoviews']); |
||
199 | |||
200 | $navlinks = [ |
||
201 | 'create' => [ |
||
202 | 'attr' => [ |
||
203 | 'href' => [ |
||
204 | 'url' => 'materializedviews.php', |
||
205 | 'urlvars' => [ |
||
206 | 'action' => 'create', |
||
207 | 'server' => $_REQUEST['server'], |
||
208 | 'database' => $_REQUEST['database'], |
||
209 | 'schema' => $_REQUEST['schema'], |
||
210 | ], |
||
211 | ], |
||
212 | ], |
||
213 | 'content' => $lang['strcreateview'], |
||
214 | ], |
||
215 | 'createwiz' => [ |
||
216 | 'attr' => [ |
||
217 | 'href' => [ |
||
218 | 'url' => 'materializedviews.php', |
||
219 | 'urlvars' => [ |
||
220 | 'action' => 'wiz_create', |
||
221 | 'server' => $_REQUEST['server'], |
||
222 | 'database' => $_REQUEST['database'], |
||
223 | 'schema' => $_REQUEST['schema'], |
||
224 | ], |
||
225 | ], |
||
226 | ], |
||
227 | 'content' => $lang['strcreateviewwiz'], |
||
228 | ], |
||
229 | ]; |
||
230 | $this->printNavLinks($navlinks, $this->table_place, get_defined_vars()); |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Generate XML for the browser tree. |
||
235 | */ |
||
236 | public function doTree() |
||
237 | { |
||
238 | $conf = $this->conf; |
||
239 | $misc = $this->misc; |
||
240 | $lang = $this->lang; |
||
241 | $data = $misc->getDatabaseAccessor(); |
||
242 | |||
243 | $matviews = $data->getMaterializedViews(); |
||
244 | |||
245 | $reqvars = $misc->getRequestVars('matview'); |
||
246 | |||
247 | $attrs = [ |
||
248 | 'text' => Decorator::field('relname'), |
||
249 | 'icon' => 'MView', |
||
250 | 'iconAction' => Decorator::url('display.php', $reqvars, ['matview' => Decorator::field('relname')]), |
||
251 | 'toolTip' => Decorator::field('relcomment'), |
||
252 | 'action' => Decorator::redirecturl('redirect.php', $reqvars, ['matview' => Decorator::field('relname')]), |
||
253 | 'branch' => Decorator::url('materializedviews.php', $reqvars, ['action' => 'subtree', 'matview' => Decorator::field('relname')]), |
||
254 | ]; |
||
255 | |||
256 | return $this->printTree($matviews, $attrs, 'matviews'); |
||
257 | } |
||
258 | |||
259 | public function doSubTree() |
||
260 | { |
||
261 | $conf = $this->conf; |
||
262 | $misc = $this->misc; |
||
263 | $lang = $this->lang; |
||
264 | $data = $misc->getDatabaseAccessor(); |
||
265 | |||
266 | $tabs = $misc->getNavTabs('matview'); |
||
267 | $items = $this->adjustTabsForTree($tabs); |
||
268 | $reqvars = $misc->getRequestVars('matview'); |
||
269 | |||
270 | $attrs = [ |
||
271 | 'text' => Decorator::field('title'), |
||
272 | 'icon' => Decorator::field('icon'), |
||
273 | 'action' => Decorator::actionurl(Decorator::field('url'), $reqvars, Decorator::field('urlvars'), ['matview' => $_REQUEST['matview']]), |
||
274 | 'branch' => Decorator::ifempty( |
||
275 | Decorator::field('branch'), '', Decorator::url(Decorator::field('url'), Decorator::field('urlvars'), $reqvars, |
||
276 | [ |
||
277 | 'action' => 'tree', |
||
278 | 'matview' => $_REQUEST['matview'], |
||
279 | ] |
||
280 | ) |
||
281 | ), |
||
282 | ]; |
||
283 | |||
284 | return $this->printTree($items, $attrs, 'matviews'); |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Ask for select parameters and perform select |
||
289 | */ |
||
290 | public function doSelectRows($confirm, $msg = '') |
||
291 | { |
||
292 | $conf = $this->conf; |
||
293 | $misc = $this->misc; |
||
294 | $lang = $this->lang; |
||
295 | $data = $misc->getDatabaseAccessor(); |
||
296 | |||
297 | if ($confirm) { |
||
298 | $this->printTrail('view'); |
||
299 | $this->printTabs('matview', 'select'); |
||
300 | $this->printMsg($msg); |
||
301 | |||
302 | $attrs = $data->getTableAttributes($_REQUEST['matview']); |
||
303 | |||
304 | echo '<form action="' . SUBFOLDER . '/src/views/' . $this->script . '" method="post" id="selectform">'; |
||
305 | echo "\n"; |
||
306 | |||
307 | if ($attrs->recordCount() > 0) { |
||
308 | // JavaScript for select all feature |
||
309 | echo "<script type=\"text/javascript\">\n"; |
||
310 | echo "//<![CDATA[\n"; |
||
311 | echo " function selectAll() {\n"; |
||
312 | echo " for (var i=0; i<document.getElementById('selectform').elements.length; i++) {\n"; |
||
313 | echo " var e = document.getElementById('selectform').elements[i];\n"; |
||
314 | echo " if (e.name.indexOf('show') == 0) { \n "; |
||
315 | echo " e.checked = document.getElementById('selectform').selectall.checked;\n"; |
||
316 | echo " }\n"; |
||
317 | echo " }\n"; |
||
318 | echo " }\n"; |
||
319 | echo "//]]>\n"; |
||
320 | echo "</script>\n"; |
||
321 | |||
322 | echo "<table>\n"; |
||
323 | |||
324 | // Output table header |
||
325 | echo "<tr><th class=\"data\">{$lang['strshow']}</th><th class=\"data\">{$lang['strcolumn']}</th>"; |
||
326 | echo "<th class=\"data\">{$lang['strtype']}</th><th class=\"data\">{$lang['stroperator']}</th>"; |
||
327 | echo "<th class=\"data\">{$lang['strvalue']}</th></tr>"; |
||
328 | |||
329 | $i = 0; |
||
330 | while (!$attrs->EOF) { |
||
331 | $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']); |
||
332 | // Set up default value if there isn't one already |
||
333 | if (!isset($_REQUEST['values'][$attrs->fields['attname']])) { |
||
334 | $_REQUEST['values'][$attrs->fields['attname']] = null; |
||
335 | } |
||
336 | |||
337 | if (!isset($_REQUEST['ops'][$attrs->fields['attname']])) { |
||
338 | $_REQUEST['ops'][$attrs->fields['attname']] = null; |
||
339 | } |
||
340 | |||
341 | // Continue drawing row |
||
342 | $id = (($i % 2) == 0 ? '1' : '2'); |
||
343 | echo "<tr class=\"data{$id}\">\n"; |
||
344 | echo '<td style="white-space:nowrap;">'; |
||
345 | echo '<input type="checkbox" name="show[', htmlspecialchars($attrs->fields['attname']), ']"', |
||
346 | isset($_REQUEST['show'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /></td>'; |
||
347 | echo '<td style="white-space:nowrap;">', $misc->printVal($attrs->fields['attname']), '</td>'; |
||
348 | echo '<td style="white-space:nowrap;">', $misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod'])), '</td>'; |
||
349 | echo '<td style="white-space:nowrap;">'; |
||
350 | echo "<select name=\"ops[{$attrs->fields['attname']}]\">\n"; |
||
351 | foreach (array_keys($data->selectOps) as $v) { |
||
352 | echo '<option value="', htmlspecialchars($v), '"', ($v == $_REQUEST['ops'][$attrs->fields['attname']]) ? ' selected="selected"' : '', |
||
353 | '>', htmlspecialchars($v), "</option>\n"; |
||
354 | } |
||
355 | echo "</select></td>\n"; |
||
356 | echo '<td style="white-space:nowrap;">', $data->printField("values[{$attrs->fields['attname']}]", |
||
357 | $_REQUEST['values'][$attrs->fields['attname']], $attrs->fields['type']), '</td>'; |
||
358 | echo "</tr>\n"; |
||
359 | $i++; |
||
360 | $attrs->moveNext(); |
||
361 | } |
||
362 | // Select all checkbox |
||
363 | echo "<tr><td colspan=\"5\"><input type=\"checkbox\" id=\"selectall\" name=\"selectall\" accesskey=\"a\" onclick=\"javascript:selectAll()\" /><label for=\"selectall\">{$lang['strselectallfields']}</label></td></tr>"; |
||
364 | echo "</table>\n"; |
||
365 | } else { |
||
366 | echo "<p>{$lang['strinvalidparam']}</p>\n"; |
||
367 | } |
||
368 | |||
369 | echo "<p><input type=\"hidden\" name=\"action\" value=\"selectrows\" />\n"; |
||
370 | echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['matview']), "\" />\n"; |
||
371 | echo "<input type=\"hidden\" name=\"subject\" value=\"view\" />\n"; |
||
372 | echo $misc->form; |
||
373 | echo "<input type=\"submit\" name=\"select\" accesskey=\"r\" value=\"{$lang['strselect']}\" />\n"; |
||
374 | echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n"; |
||
375 | echo "</form>\n"; |
||
376 | return; |
||
377 | } else { |
||
378 | if (!isset($_POST['show'])) { |
||
379 | $_POST['show'] = []; |
||
380 | } |
||
381 | |||
382 | if (!isset($_POST['values'])) { |
||
383 | $_POST['values'] = []; |
||
384 | } |
||
385 | |||
386 | if (!isset($_POST['nulls'])) { |
||
387 | $_POST['nulls'] = []; |
||
388 | } |
||
389 | |||
390 | // Verify that they haven't supplied a value for unary operators |
||
391 | foreach ($_POST['ops'] as $k => $v) { |
||
392 | if ($data->selectOps[$v] == 'p' && $_POST['values'][$k] != '') { |
||
393 | $this->doSelectRows(true, $lang['strselectunary']); |
||
394 | return; |
||
395 | } |
||
396 | } |
||
397 | |||
398 | if (sizeof($_POST['show']) == 0) { |
||
399 | return $this->doSelectRows(true, $lang['strselectneedscol']); |
||
400 | } else { |
||
401 | // Generate query SQL |
||
402 | $query = $data->getSelectSQL($_REQUEST['matview'], array_keys($_POST['show']), $_POST['values'], $_POST['ops']); |
||
403 | |||
404 | $_REQUEST['query'] = $query; |
||
405 | $_REQUEST['return'] = 'schema'; |
||
406 | |||
407 | $this->setNoOutput(true); |
||
408 | |||
409 | $display_controller = new DisplayController($this->getContainer()); |
||
410 | |||
411 | return $display_controller->render(); |
||
412 | } |
||
413 | } |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * Show confirmation of drop and perform actual drop |
||
418 | */ |
||
419 | public function doDrop($confirm) |
||
486 | } |
||
487 | } |
||
488 | } |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Sets up choices for table linkage, and which fields to select for the view we're creating |
||
493 | */ |
||
494 | public function doSetParamsCreate($msg = '') |
||
640 | } |
||
641 | } |
||
642 | |||
643 | /** |
||
644 | * Display a wizard where they can enter a new view |
||
645 | */ |
||
646 | public function doWizardCreate($msg = '') |
||
681 | } |
||
682 | |||
683 | /** |
||
684 | * Displays a screen where they can enter a new view |
||
685 | */ |
||
686 | public function doCreate($msg = '') |
||
687 | { |
||
688 | $conf = $this->conf; |
||
689 | $misc = $this->misc; |
||
690 | $lang = $this->lang; |
||
691 | $data = $misc->getDatabaseAccessor(); |
||
692 | |||
693 | if (!isset($_REQUEST['formView'])) { |
||
694 | $_REQUEST['formView'] = ''; |
||
695 | } |
||
696 | |||
697 | if (!isset($_REQUEST['formDefinition'])) { |
||
698 | if (isset($_SESSION['sqlquery'])) { |
||
699 | $_REQUEST['formDefinition'] = $_SESSION['sqlquery']; |
||
700 | } else { |
||
701 | $_REQUEST['formDefinition'] = 'SELECT '; |
||
702 | } |
||
703 | } |
||
704 | if (!isset($_REQUEST['formComment'])) { |
||
705 | $_REQUEST['formComment'] = ''; |
||
706 | } |
||
707 | |||
708 | $this->printTrail('schema'); |
||
709 | $this->printTitle($lang['strcreateview'], 'pg.matview.create'); |
||
710 | $this->printMsg($msg); |
||
711 | |||
712 | echo '<form action="' . SUBFOLDER . "/src/views/materializedviews.php\" method=\"post\">\n"; |
||
713 | echo "<table style=\"width: 100%\">\n"; |
||
714 | echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n"; |
||
715 | echo "\t<td class=\"data1\"><input name=\"formView\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"", |
||
716 | htmlspecialchars($_REQUEST['formView']), "\" /></td>\n\t</tr>\n"; |
||
717 | echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strdefinition']}</th>\n"; |
||
718 | echo "\t<td class=\"data1\"><textarea style=\"width:100%;\" rows=\"10\" cols=\"50\" name=\"formDefinition\">", |
||
719 | htmlspecialchars($_REQUEST['formDefinition']), "</textarea></td>\n\t</tr>\n"; |
||
720 | echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n"; |
||
721 | echo "\t\t<td class=\"data1\"><textarea name=\"formComment\" rows=\"3\" cols=\"32\">", |
||
722 | htmlspecialchars($_REQUEST['formComment']), "</textarea></td>\n\t</tr>\n"; |
||
723 | echo "</table>\n"; |
||
724 | echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n"; |
||
725 | echo $misc->form; |
||
726 | echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n"; |
||
727 | echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n"; |
||
728 | echo "</form>\n"; |
||
729 | } |
||
730 | |||
731 | /** |
||
732 | * Actually creates the new view in the database |
||
733 | */ |
||
734 | public function doSaveCreate() |
||
753 | } |
||
754 | } |
||
755 | } |
||
756 | |||
757 | /** |
||
758 | * Actually creates the new wizard view in the database |
||
759 | */ |
||
760 | public function doSaveCreateWiz() |
||
895 |
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.