Total Complexity | 73 |
Total Lines | 523 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like ThemeTabForm 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 ThemeTabForm, and based on these observations, apply Extract Interface, too.
1 | <?php declare(strict_types=1); |
||
31 | class ThemeTabForm extends \XoopsForm |
||
32 | { |
||
33 | public $formTabs = []; |
||
34 | /** |
||
35 | * "action" attribute for the html form |
||
36 | * |
||
37 | * @var string |
||
38 | */ |
||
39 | public $action; |
||
40 | /** |
||
41 | * "method" attribute for the form. |
||
42 | * |
||
43 | * @var string |
||
44 | */ |
||
45 | public $method; |
||
46 | /** |
||
47 | * "name" attribute of the form |
||
48 | * |
||
49 | * @var string |
||
50 | */ |
||
51 | public $name; |
||
52 | /** |
||
53 | * title for the form |
||
54 | * |
||
55 | * @var string |
||
56 | */ |
||
57 | public $title; |
||
58 | /** |
||
59 | * summary for the form (WGAC2 Requirement) |
||
60 | * |
||
61 | * @var string |
||
62 | */ |
||
63 | public $summary = ''; |
||
64 | /** |
||
65 | * array of {@link XoopsFormElement} objects |
||
66 | * |
||
67 | * @var array |
||
68 | */ |
||
69 | public $elements = []; |
||
70 | /** |
||
71 | * extra information for the <form> tag |
||
72 | * |
||
73 | * @var array |
||
74 | */ |
||
75 | public $extra = []; |
||
76 | /** |
||
77 | * required elements |
||
78 | * |
||
79 | * @var array |
||
80 | */ |
||
81 | public $required = []; |
||
82 | |||
83 | /** |
||
84 | * @param string $title |
||
85 | * @param string $name |
||
86 | * @param string $action |
||
87 | * @param string $method |
||
88 | * @param bool $addtoken |
||
89 | * @param string $summary |
||
90 | */ |
||
91 | public function __construct($title, $name, $action, $method = 'post', $addtoken = false, $summary = '') |
||
92 | { |
||
93 | // global $xoTheme; |
||
94 | // $GLOBALS['xoTheme']->addScript(PUBLISHER_URL . '/assets/js/ui.core.js'); |
||
95 | // $GLOBALS['xoTheme']->addScript(PUBLISHER_URL . '/assets/js/ui.tabs.js'); |
||
96 | // $GLOBALS['xoTheme']->addStylesheet(PUBLISHER_URL . '/assets/css/jquery-ui-1.7.1.custom.css'); |
||
97 | |||
98 | $GLOBALS['xoTheme']->addScript('browse.php?Frameworks/jquery/plugins/jquery.ui.js'); |
||
99 | $GLOBALS['xoTheme']->addStylesheet(XOOPS_URL . '/modules/system/css/ui/' . \xoops_getModuleOption('jquery_theme', 'system') . '/ui.all.css'); |
||
|
|||
100 | |||
101 | $this->title = $title; |
||
102 | $this->name = $name; |
||
103 | $this->action = $action; |
||
104 | $this->method = $method; |
||
105 | $this->summary = $summary; |
||
106 | if ($addtoken) { |
||
107 | $this->addElement(new \XoopsFormHiddenToken()); |
||
108 | } |
||
109 | } |
||
110 | |||
111 | //function render() {} |
||
112 | |||
113 | public function assign(\XoopsTpl $tpl): void |
||
114 | { |
||
115 | $i = -1; |
||
116 | $tab = -1; |
||
117 | $elements = []; |
||
118 | if (\count($this->getRequired()) > 0) { |
||
119 | $this->elements[] = "<tr class='foot'><td colspan='2'>* = " . \_REQUIRED . '</td></tr>'; |
||
120 | } |
||
121 | foreach ($this->getElements() as $ele) { |
||
122 | ++$i; |
||
123 | if (\is_string($ele) && 'addTab' === $ele) { |
||
124 | ++$tab; |
||
125 | continue; |
||
126 | } |
||
127 | if (\is_string($ele) && 'endTabs' === $ele) { |
||
128 | $tab = -1; |
||
129 | continue; |
||
130 | } |
||
131 | if (\is_string($ele)) { |
||
132 | $elements[$i]['body'] = $ele; |
||
133 | $elements[$i]['tab'] = $tab; |
||
134 | continue; |
||
135 | } |
||
136 | $eleName = $ele->getName(); |
||
137 | $eleDescription = $ele->getDescription(); |
||
138 | $n = $eleName ?: $i; |
||
139 | $elements[$n]['name'] = $eleName; |
||
140 | $elements[$n]['caption'] = $ele->getCaption(); |
||
141 | $elements[$n]['body'] = $ele->render(); |
||
142 | $elements[$n]['hidden'] = (bool)$ele->isHidden(); |
||
143 | $elements[$n]['required'] = $ele->isRequired(); |
||
144 | if ('' != $eleDescription) { |
||
145 | $elements[$n]['description'] = $eleDescription; |
||
146 | } |
||
147 | $elements[$n]['tab'] = $tab; |
||
148 | } |
||
149 | $js = $this->renderValidationJS(); |
||
150 | $tpl->assign( |
||
151 | $this->getName(), |
||
152 | [ |
||
153 | 'title' => $this->getTitle(), |
||
154 | 'id' => 'tab_' . \preg_replace('/[^a-z0-9]+/i', '', $this->getTitle()), |
||
155 | 'name' => $this->getName(), |
||
156 | 'action' => $this->getAction(), |
||
157 | 'method' => $this->getMethod(), |
||
158 | 'extra' => 'onsubmit="return xoopsFormValidate_' . $this->getName() . '();"' . $this->getExtra(), |
||
159 | 'javascript' => $js, |
||
160 | 'tabs' => $this->formTabs, |
||
161 | 'elements' => $elements, |
||
162 | ] |
||
163 | ); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * XoopsThemeTabForm::startTab() |
||
168 | * |
||
169 | * @param mixed $tabText |
||
170 | */ |
||
171 | public function startTab($tabText): void |
||
172 | { |
||
173 | $temp = $this->startFormTabs($tabText); |
||
174 | $this->addElement($temp); |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * XoopsThemeTabForm::endTab() |
||
179 | */ |
||
180 | public function endTabs(): void |
||
181 | { |
||
182 | $temp = $this->endFormTabs(); |
||
183 | $this->addElement($temp); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Creates a tab with title text and starts that tabs page |
||
188 | * |
||
189 | * @param $tabText - This is what is displayed on the tab |
||
190 | * |
||
191 | * @return string |
||
192 | */ |
||
193 | public function startFormTabs($tabText) |
||
194 | { |
||
195 | $this->formTabs[] = $tabText; |
||
196 | $ret = 'addTab'; |
||
197 | |||
198 | return $ret; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Ends a tab page |
||
203 | * |
||
204 | * @return string |
||
205 | */ |
||
206 | public function endFormTabs() |
||
207 | { |
||
208 | $ret = 'endTabs'; |
||
209 | |||
210 | return $ret; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * @param bool $encode |
||
215 | * |
||
216 | * @return string |
||
217 | */ |
||
218 | public function getSummary($encode = false) |
||
219 | { |
||
220 | return $encode ? \htmlspecialchars($this->summary, \ENT_QUOTES | ENT_HTML5) : $this->summary; |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * return the title of the form |
||
225 | * |
||
226 | * @param bool $encode To sanitizer the text? |
||
227 | * |
||
228 | * @return string |
||
229 | */ |
||
230 | public function getTitle($encode = false) |
||
231 | { |
||
232 | return $encode ? \htmlspecialchars($this->title, \ENT_QUOTES | ENT_HTML5) : $this->title; |
||
233 | } |
||
234 | |||
235 | /** |
||
236 | * get the "name" attribute for the <form> tag |
||
237 | * Deprecated, to be refactored |
||
238 | * |
||
239 | * @param bool $encode To sanitizer the text? |
||
240 | * |
||
241 | * @return string |
||
242 | */ |
||
243 | public function getName($encode = true) |
||
244 | { |
||
245 | return $encode ? \htmlspecialchars($this->name, \ENT_QUOTES | ENT_HTML5) : $this->name; |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * get the "action" attribute for the <form> tag |
||
250 | * |
||
251 | * @param bool $encode To sanitizer the text? |
||
252 | * |
||
253 | * @return string |
||
254 | */ |
||
255 | public function getAction($encode = true) |
||
256 | { |
||
257 | // Convert & to & for backward compatibility |
||
258 | return $encode ? \htmlspecialchars(\str_replace('&', '&', $this->action), \ENT_QUOTES | ENT_HTML5) : $this->action; |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * get the "method" attribute for the <form> tag |
||
263 | * |
||
264 | * @return string |
||
265 | */ |
||
266 | public function getMethod() |
||
267 | { |
||
268 | return ('get' === \mb_strtolower($this->method)) ? 'get' : 'post'; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Add an element to the form |
||
273 | * |
||
274 | * @param string|\XoopsFormElement $formElement reference to a {@link XoopsFormElement} |
||
275 | * @param bool $required is this a "required" element? |
||
276 | */ |
||
277 | public function addElement($formElement, $required = false): void |
||
278 | { |
||
279 | if (\is_string($formElement)) { |
||
280 | $this->elements[] = &$formElement; |
||
281 | } elseif (\is_subclass_of($formElement, 'xoopsformelement')) { |
||
282 | $this->elements[] = &$formElement; |
||
283 | if ($required) { |
||
284 | if (\method_exists($formElement, 'setRequired')) { |
||
285 | $formElement->setRequired(true); |
||
286 | } else { |
||
287 | $formElement->required = true; |
||
288 | } |
||
289 | $this->required[] = &$formElement; |
||
290 | } |
||
291 | } |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * get an array of forms elements |
||
296 | * |
||
297 | * @param bool $recurse get elements recursively? |
||
298 | * |
||
299 | * @return array array of {@link XoopsFormElement}s |
||
300 | */ |
||
301 | public function &getElements($recurse = false) |
||
302 | { |
||
303 | if (!$recurse) { |
||
304 | return $this->elements; |
||
305 | } |
||
306 | $ret = []; |
||
307 | foreach ($this->elements as $i => $iValue) { |
||
308 | if (\is_object($this->elements[$i])) { |
||
309 | $ret[] = &$this->elements[$i]; |
||
310 | } |
||
311 | } |
||
312 | |||
313 | return $ret; |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * get an array of "name" attributes of form elements |
||
318 | * |
||
319 | * @return array array of form element names |
||
320 | */ |
||
321 | public function getElementNames() |
||
322 | { |
||
323 | $ret = []; |
||
324 | $elements = &$this->getElements(true); |
||
325 | foreach ($elements as $iValue) { |
||
326 | $ret[] = $iValue->getName(); |
||
327 | } |
||
328 | |||
329 | return $ret; |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * get a reference to a {@link XoopsFormElement} object by its "name" |
||
334 | * |
||
335 | * @param string $name "name" attribute assigned to a {@link XoopsFormElement} |
||
336 | * |
||
337 | * @return bool|\XoopsFormElement reference to a {@link XoopsFormElement}, false if not found |
||
338 | */ |
||
339 | public function &getElementByName($name) |
||
340 | { |
||
341 | $elements = &$this->getElements(true); |
||
342 | foreach ($elements as $i => $iValue) { |
||
343 | if ($name == $iValue->getName(false)) { |
||
344 | return $iValue; |
||
345 | } |
||
346 | } |
||
347 | $elt = null; |
||
348 | |||
349 | return $elt; |
||
350 | } |
||
351 | |||
352 | /** |
||
353 | * Sets the "value" attribute of a form element |
||
354 | * |
||
355 | * @param string $name the "name" attribute of a form element |
||
356 | * @param string $value the "value" attribute of a form element |
||
357 | */ |
||
358 | public function setElementValue($name, $value): void |
||
359 | { |
||
360 | $ele = &$this->getElementByName($name); |
||
361 | if (\is_object($ele) && \method_exists($ele, 'setValue')) { |
||
362 | $ele->setValue($value); |
||
363 | } |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * Sets the "value" attribute of form elements in a batch |
||
368 | * |
||
369 | * @param array $values array of name/value pairs to be assigned to form elements |
||
370 | */ |
||
371 | public function setElementValues($values): void |
||
372 | { |
||
373 | if (\is_array($values) && !empty($values)) { |
||
374 | // will not use getElementByName() for performance.. |
||
375 | $elements = &$this->getElements(true); |
||
376 | foreach ($elements as $i => $iValue) { |
||
377 | $name = $iValue->getName(false); |
||
378 | if ($name && isset($values[$name]) && \method_exists($iValue, 'setValue')) { |
||
379 | $iValue->setValue($values[$name]); |
||
380 | } |
||
381 | } |
||
382 | } |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * Gets the "value" attribute of a form element |
||
387 | * |
||
388 | * @param string $name the "name" attribute of a form element |
||
389 | * @param bool $encode To sanitizer the text? |
||
390 | * |
||
391 | * @return string the "value" attribute assigned to a form element, null if not set |
||
392 | */ |
||
393 | public function getElementValue($name, $encode = false) |
||
394 | { |
||
395 | $ele = &$this->getElementByName($name); |
||
396 | if (\is_object($ele) && \method_exists($ele, 'getValue')) { |
||
397 | return $ele->getValue($encode); |
||
398 | } |
||
399 | |||
400 | return null; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * gets the "value" attribute of all form elements |
||
405 | * |
||
406 | * @param bool $encode To sanitizer the text? |
||
407 | * |
||
408 | * @return array array of name/value pairs assigned to form elements |
||
409 | */ |
||
410 | public function getElementValues($encode = false) |
||
411 | { |
||
412 | // will not use getElementByName() for performance.. |
||
413 | $elements = &$this->getElements(true); |
||
414 | $values = []; |
||
415 | foreach ($elements as $i => $iValue) { |
||
416 | $name = $iValue->getName(false); |
||
417 | if ($name && \method_exists($iValue, 'getValue')) { |
||
418 | $values[$name] = $iValue->getValue($encode); |
||
419 | } |
||
420 | } |
||
421 | |||
422 | return $values; |
||
423 | } |
||
424 | |||
425 | /** |
||
426 | * set the extra attributes for the <form> tag |
||
427 | * |
||
428 | * @param string $extra extra attributes for the <form> tag |
||
429 | * @return string|void |
||
430 | */ |
||
431 | public function setExtra($extra) |
||
432 | { |
||
433 | if (!empty($extra)) { |
||
434 | $this->extra[] = $extra; |
||
435 | } |
||
436 | } |
||
437 | |||
438 | /** |
||
439 | * set the summary tag for the <form> tag |
||
440 | * |
||
441 | * @param string $summary |
||
442 | */ |
||
443 | public function setSummary($summary): void |
||
447 | } |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * get the extra attributes for the <form> tag |
||
452 | * |
||
453 | * @return string |
||
454 | */ |
||
455 | public function &getExtra() |
||
456 | { |
||
457 | $extra = empty($this->extra) ? '' : ' ' . \implode(' ', $this->extra); |
||
458 | |||
459 | return $extra; |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * make an element "required" |
||
464 | * |
||
465 | * @param \XoopsFormElement $formElement reference to a {@link XoopsFormElement} |
||
466 | */ |
||
467 | public function setRequired(\XoopsFormElement $formElement): void |
||
468 | { |
||
469 | $this->required[] = &$formElement; |
||
470 | } |
||
471 | |||
472 | /** |
||
473 | * get an array of "required" form elements |
||
474 | * |
||
475 | * @return array array of {@link XoopsFormElement}s |
||
476 | */ |
||
477 | public function &getRequired() |
||
478 | { |
||
479 | return $this->required; |
||
480 | } |
||
481 | |||
482 | /** |
||
483 | * insert a break in the form |
||
484 | * This method is abstract. It must be overwritten in the child classes. |
||
485 | * |
||
486 | * @param string|null $extra extra information for the break |
||
487 | * |
||
488 | * @abstract |
||
489 | */ |
||
490 | public function insertBreak($extra = null): void |
||
491 | { |
||
492 | } |
||
493 | |||
494 | /** |
||
495 | * returns renderered form |
||
496 | * This method is abstract. It must be overwritten in the child classes. |
||
497 | * |
||
498 | * @abstract |
||
499 | */ |
||
500 | public function render() |
||
501 | { |
||
502 | return ''; |
||
503 | } |
||
504 | |||
505 | /** |
||
506 | * displays rendered form |
||
507 | */ |
||
508 | public function display(): void |
||
509 | { |
||
510 | echo $this->render(); |
||
511 | } |
||
512 | |||
513 | /** |
||
514 | * Renders the Javascript function needed for client-side for validation |
||
515 | * Form elements that have been declared "required" and not set will prevent the form from being |
||
516 | * submitted. Additionally, each element class may provide its own "renderValidationJS" method |
||
517 | * that is supposed to return custom validation code for the element. |
||
518 | * The element validation code can assume that the JS "myform" variable points to the form, and must |
||
519 | * execute <i>return false</i> if validation fails. |
||
520 | * A basic element validation method may contain something like this: |
||
521 | * <code> |
||
522 | * function renderValidationJS() { |
||
523 | * $name = $this->getName(); |
||
524 | * return "if (myform.{$name}.value != 'valid') { " . |
||
525 | * "myform.{$name}.focus(); window.alert( '$name is invalid' ); return false;" . |
||
526 | * " }"; |
||
527 | * } |
||
528 | * </code> |
||
529 | * |
||
530 | * @param bool $withtags Include the < javascript > tags in the returned string |
||
531 | * |
||
532 | * @return string |
||
533 | */ |
||
534 | public function renderValidationJS($withtags = true) |
||
554 | } |
||
555 | } |
||
556 |