| Total Complexity | 44 |
| Total Lines | 371 |
| Duplicated Lines | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Complex classes like FormGenerator 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 FormGenerator, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 18 | class FormGenerator extends FormElement |
||
| 19 | { |
||
| 20 | use FormHelperFromSQL; |
||
| 21 | |||
| 22 | /** save/submit button */ |
||
| 23 | const BTN_SAVE = 'save'; |
||
| 24 | /** cancel/discard button */ |
||
| 25 | const BTN_CANCEL = 'cancel'; |
||
| 26 | /** close button */ |
||
| 27 | const BTN_CLOSE = 'close'; |
||
| 28 | |||
| 29 | /** JS code to close dialog */ |
||
| 30 | const CMD_CLOSE_DLG = "parent.document.getElementById('dialog').innerHTML = '';"; |
||
| 31 | |||
| 32 | /** @var int last tab position in the form */ |
||
| 33 | protected int $iLastTab = 0; |
||
| 34 | /** @var string timestamp of last modification */ |
||
| 35 | protected ?string $tsModified = null; |
||
| 36 | /** @var string user of last modification */ |
||
| 37 | protected ?string $strUserModified = null; |
||
| 38 | /** @var bool set the whole form to readonly */ |
||
| 39 | protected bool $bReadOnly = false; |
||
| 40 | /** @var string JS handler for onsubmit */ |
||
| 41 | protected string $strOnSubmit = ''; |
||
| 42 | /** @var string JS handler for oncancel */ |
||
| 43 | protected string $strOnCancel = ''; |
||
| 44 | /** @var int explicit width of the form in pixel */ |
||
| 45 | protected int $iWidth = -1; |
||
| 46 | /** @var int global flags for all form elements */ |
||
| 47 | protected int $wGlobalFlags = 0; |
||
| 48 | /** @var array elements that creates dynamic script */ |
||
| 49 | protected array $aScriptElements = []; |
||
| 50 | /** @var array elements that creates dynamic CSS styles */ |
||
| 51 | protected array $aStyleElements = []; |
||
| 52 | /** @var string path to the images */ |
||
| 53 | protected string $strImgPath; |
||
| 54 | /** @var string receiver of the form-action */ |
||
| 55 | protected string $strActionReceiver; |
||
| 56 | /** @var string URL params for the form action */ |
||
| 57 | protected string $strAction; |
||
| 58 | /** @var string form target */ |
||
| 59 | protected string $strFormTarget = ''; |
||
| 60 | /** @var FormElement hidden element containing the referer of this form */ |
||
| 61 | protected ?FormElement $oReferer = null; |
||
| 62 | /** @var bool hide the submit/cancel/close buttons */ |
||
| 63 | protected bool $bHideButtons = false; |
||
| 64 | /** @var array text for the submit/cancel/close buttons */ |
||
| 65 | protected array $aBtnText; |
||
| 66 | /** @var array array to hold elements for validation */ |
||
| 67 | protected array $aValidate; |
||
| 68 | |||
| 69 | /** |
||
| 70 | * Create a FormGenerator. |
||
| 71 | * Set some values to default. |
||
| 72 | */ |
||
| 73 | public function __construct() |
||
| 74 | { |
||
| 75 | $this->oFG = $this; |
||
| 76 | $this->strID = 'auto_form'; |
||
| 77 | $this->aValidate = array('aMand' => array(), 'aEdit' => array(), 'aDate' => array(), 'aInt' => array(), 'aCur' => array(), 'aTime' => array()); |
||
| 78 | $this->aBtnText = array('save' => 'Speichern', 'cancel' => 'Abbrechen', 'close' => 'Schließen'); |
||
| 79 | $this->strOnSubmit = "ValidateForm();"; |
||
| 80 | $this->strOnCancel = "javascript:history.back();"; |
||
| 81 | $this->strImgPath = '../images/'; |
||
| 82 | $this->strAction = $_SERVER['QUERY_STRING']; |
||
| 83 | $this->strActionReceiver = $_SERVER['PHP_SELF'] . '?'; |
||
| 84 | $strReferer = $_SERVER['HTTP_REFERER'] ?? ''; |
||
| 85 | $this->oReferer = $this->add(new FormInput('urlReferer', $strReferer, -1, self::HIDDEN)); |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Set the action executed when submit the form. |
||
| 90 | * If not changed here, <i><b>$_SERVER['QUERY_STRING']</b></i> is used. |
||
| 91 | * @param string $strAction (default = '') |
||
| 92 | */ |
||
| 93 | public function setAction(string $strAction) : void |
||
| 94 | { |
||
| 95 | $this->strAction = $strAction; |
||
| 96 | } |
||
| 97 | |||
| 98 | /** |
||
| 99 | * Set the receiver of the formaction. |
||
| 100 | * If not changed here, the current script ($_SERVER['PHP_SELF']) will |
||
| 101 | * receive the form action. |
||
| 102 | * @param string $strActionReceiver |
||
| 103 | */ |
||
| 104 | public function setActionReceiver(string $strActionReceiver) : void |
||
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * Set the path to images. |
||
| 119 | * @param string $strPath |
||
| 120 | */ |
||
| 121 | public function setImagePath(string $strPath) : void |
||
| 124 | } |
||
| 125 | |||
| 126 | /** |
||
| 127 | * @return string current image path |
||
| 128 | */ |
||
| 129 | public function getImagePath() : string |
||
| 132 | } |
||
| 133 | |||
| 134 | /** |
||
| 135 | * Get the global flags. |
||
| 136 | * @return int |
||
| 137 | */ |
||
| 138 | public function getGlobalFlags() : int |
||
| 139 | { |
||
| 140 | return $this->wGlobalFlags; |
||
| 141 | } |
||
| 142 | |||
| 143 | /** |
||
| 144 | * Set the target |
||
| 145 | * @param string $strFormTarget |
||
| 146 | */ |
||
| 147 | public function setTarget(string $strFormTarget) : void |
||
| 148 | { |
||
| 149 | $this->strFormTarget = $strFormTarget; |
||
| 150 | } |
||
| 151 | |||
| 152 | /** |
||
| 153 | * Set explicit width of the form. |
||
| 154 | * @param int $iWidth width (-1 for default) |
||
| 155 | */ |
||
| 156 | public function setFormWidth(int $iWidth) : void |
||
| 157 | { |
||
| 158 | $this->iWidth = $iWidth; |
||
| 159 | } |
||
| 160 | |||
| 161 | /** |
||
| 162 | * Sets the whole form to readonly. |
||
| 163 | * All elements of the form set to disabled, Save/Cancel-Buttons are replaced |
||
| 164 | * with Close-Button |
||
| 165 | * @param bool $bReadOnly |
||
| 166 | */ |
||
| 167 | public function setReadOnly(bool $bReadOnly) : void |
||
| 168 | { |
||
| 169 | $this->bReadOnly = $bReadOnly; |
||
| 170 | $bReadOnly ? $this->wGlobalFlags |= self::DISABLED : $this->wGlobalFlags &= ~self::DISABLED; |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Don't create formbuttons save/cancel/close |
||
| 175 | * @param bool $bHideButtons |
||
| 176 | */ |
||
| 177 | public function hideButtons($bHideButtons = true) : void |
||
| 178 | { |
||
| 179 | $this->bHideButtons = $bHideButtons; |
||
| 180 | } |
||
| 181 | |||
| 182 | /** |
||
| 183 | * Set timestamp and user of last modification |
||
| 184 | * @param string $tsModified timestamp from database |
||
| 185 | * @param string $strUserModified |
||
| 186 | */ |
||
| 187 | public function setLastModified(string $tsModified, string $strUserModified) : void |
||
| 188 | { |
||
| 189 | $this->tsModified = $tsModified; |
||
| 190 | $this->strUserModified = $strUserModified; |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * Specify the form as an 'Dialog'. |
||
| 195 | * Dialog means, the form runs inside of an dynamic iframe created in the |
||
| 196 | * dialog - DIV of the parent. <br/> |
||
| 197 | * The cancel can easy be done by clear the content of that dialog-DIV. |
||
| 198 | */ |
||
| 199 | public function setDialog() : void |
||
| 200 | { |
||
| 201 | $this->setOnCancel(self::CMD_CLOSE_DLG); |
||
| 202 | } |
||
| 203 | |||
| 204 | /** |
||
| 205 | * Changes default text for selected button |
||
| 206 | * defaults: |
||
| 207 | * - 'save' => 'Speichern' |
||
| 208 | * - 'cancel' => 'Abbrechen' |
||
| 209 | * - 'close' => 'Schließen' |
||
| 210 | * |
||
| 211 | * @param string $strBtn FormGenerator::BTN_SAVE, FormGenerator::BTN_CANCEL or FormGenerator::BTN_CLOSE |
||
| 212 | * @param string $strText |
||
| 213 | */ |
||
| 214 | public function setBtnText(string $strBtn, string $strText) : void |
||
| 215 | { |
||
| 216 | if (isset($this->aBtnText[$strBtn])) { |
||
| 217 | $this->aBtnText[$strBtn] = $strText; |
||
| 218 | } else { |
||
| 219 | trigger_error('invalid Button specified!', E_USER_WARNING); |
||
| 220 | } |
||
| 221 | } |
||
| 222 | |||
| 223 | /** |
||
| 224 | * Change JS handler for form submit from default "ValidateForm();";<br/><br/> |
||
| 225 | * Hide button, if set to empty string.<br/><br/> |
||
| 226 | * <b>!! Attention !!</b> |
||
| 227 | * don't use double quotes in function! |
||
| 228 | * @param string $strOnSubmit |
||
| 229 | */ |
||
| 230 | public function setOnSubmit(string $strOnSubmit) : void |
||
| 233 | } |
||
| 234 | |||
| 235 | /** |
||
| 236 | * Change JS handler for cancel/close - button from default "javascript:history.back();";<br/><br/> |
||
| 237 | * Hide button, if set to empty string.<br/><br/> |
||
| 238 | * <b>!! Attention !!</b> |
||
| 239 | * don't use double quotes in function! |
||
| 240 | * @param string $strOnCancel |
||
| 241 | */ |
||
| 242 | public function setOnCancel(string $strOnCancel) : void |
||
| 243 | { |
||
| 244 | $this->strOnCancel = $strOnCancel; |
||
| 245 | } |
||
| 246 | |||
| 247 | /** |
||
| 248 | * Add any element to the form. |
||
| 249 | * @param FormElement $oElement |
||
| 250 | */ |
||
| 251 | public function addElement(FormElement $oElement) : void |
||
| 252 | { |
||
| 253 | if ($oElement->hasTab()) { |
||
| 254 | $oElement->setTab(++$this->iLastTab); |
||
| 255 | } |
||
| 256 | if (!empty($oElement->strValidate) && ($oElement->wFlags & FE::HIDDEN) == 0) { |
||
| 257 | array_push($this->aValidate[$oElement->strValidate], $oElement->strName); |
||
| 258 | if (($oElement->wFlags & FE::MANDATORY) != 0) { |
||
| 259 | array_push($this->aValidate['aMand'], $oElement->strName); |
||
| 260 | } |
||
| 261 | } |
||
| 262 | if ($oElement->bCreateScript) { |
||
| 263 | $this->aScriptElements[] = $oElement; |
||
| 264 | } |
||
| 265 | if ($oElement->bCreateStyle) { |
||
| 266 | $this->aStyleElements[] = $oElement; |
||
| 267 | } |
||
| 268 | } |
||
| 269 | |||
| 270 | /** |
||
| 271 | * Create HTML for defined form. |
||
| 272 | * @return string |
||
| 273 | */ |
||
| 274 | public function getForm() : string |
||
| 321 | } |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Build infos for last modification (if $this->tsModified set) |
||
| 325 | * @return string |
||
| 326 | */ |
||
| 327 | protected function showLastModified() : string |
||
| 328 | { |
||
| 329 | $strHTML = ''; |
||
| 330 | if (!empty($this->tsModified)) { |
||
| 331 | $strHTML .= '<h4>letzte Änderung am <span class="lastmodified">'; |
||
| 332 | $strHTML .= $this->tsFromSQL('d.m.Y H:i', $this->tsModified); |
||
| 333 | $strHTML .= '</span> von <span class="lastmodified">'; |
||
| 334 | $strHTML .= $this->strUserModified; |
||
| 335 | $strHTML .= '</span></h4>' . PHP_EOL; |
||
| 336 | } |
||
| 337 | return $strHTML; |
||
| 338 | } |
||
| 339 | |||
| 340 | /** |
||
| 341 | * Build needed JS script. |
||
| 342 | * - for validation |
||
| 343 | * - scripts of all childs that have own script |
||
| 344 | * @return string |
||
| 345 | */ |
||
| 346 | public function getScript() : string |
||
| 371 | } |
||
| 372 | |||
| 373 | /** |
||
| 374 | * Build needed CSS styles. |
||
| 375 | * - body, if form width defined (TODO: better set width of form-element??) |
||
| 376 | * - styles of all childs that have own styles |
||
| 377 | * @return string |
||
| 378 | */ |
||
| 379 | public function getStyle() : string |
||
| 389 | } |
||
| 390 | } |
||
| 391 |