Complex classes like Form 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 Form, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | class Form extends Element { |
||
12 | |||
13 | /** |
||
14 | * @var array name value pairs for hidden values |
||
15 | */ |
||
16 | protected $hidden = array(); |
||
17 | |||
18 | /** |
||
19 | * @var Element[] the elements of the form |
||
20 | */ |
||
21 | protected $elements = array(); |
||
22 | |||
23 | /** |
||
24 | * Creates a new, empty form with some default attributes |
||
25 | * |
||
26 | * @param array $attributes |
||
27 | */ |
||
28 | public function __construct($attributes = array()) { |
||
57 | |||
58 | /** |
||
59 | * Sets a hidden field |
||
60 | * |
||
61 | * @param string $name |
||
62 | * @param string $value |
||
63 | * @return $this |
||
64 | */ |
||
65 | public function setHiddenField($name, $value) { |
||
69 | |||
70 | #region element query function |
||
71 | |||
72 | /** |
||
73 | * Returns the numbers of elements in the form |
||
74 | * |
||
75 | * @return int |
||
76 | */ |
||
77 | public function elementCount() { |
||
80 | |||
81 | /** |
||
82 | * Get the position of the element in the form or false if it is not in the form |
||
83 | * |
||
84 | * Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the return value of this function. |
||
85 | * |
||
86 | * @param Element $element |
||
87 | * |
||
88 | * @return false|int |
||
89 | */ |
||
90 | public function getElementPosition(Element $element) |
||
94 | |||
95 | /** |
||
96 | * Returns a reference to the element at a position. |
||
97 | * A position out-of-bounds will return either the |
||
98 | * first (underflow) or last (overflow) element. |
||
99 | * |
||
100 | * @param int $pos |
||
101 | * @return Element |
||
102 | */ |
||
103 | public function getElementAt($pos) { |
||
109 | |||
110 | /** |
||
111 | * Gets the position of the first of a type of element |
||
112 | * |
||
113 | * @param string $type Element type to look for. |
||
114 | * @param int $offset search from this position onward |
||
115 | * @return false|int position of element if found, otherwise false |
||
116 | */ |
||
117 | public function findPositionByType($type, $offset = 0) { |
||
126 | |||
127 | /** |
||
128 | * Gets the position of the first element matching the attribute |
||
129 | * |
||
130 | * @param string $name Name of the attribute |
||
131 | * @param string $value Value the attribute should have |
||
132 | * @param int $offset search from this position onward |
||
133 | * @return false|int position of element if found, otherwise false |
||
134 | */ |
||
135 | public function findPositionByAttribute($name, $value, $offset = 0) { |
||
144 | |||
145 | #endregion |
||
146 | |||
147 | #region Element positioning functions |
||
148 | |||
149 | /** |
||
150 | * Adds or inserts an element to the form |
||
151 | * |
||
152 | * @param Element $element |
||
153 | * @param int $pos 0-based position in the form, -1 for at the end |
||
154 | * @return Element |
||
155 | */ |
||
156 | public function addElement(Element $element, $pos = -1) { |
||
165 | |||
166 | /** |
||
167 | * Replaces an existing element with a new one |
||
168 | * |
||
169 | * @param Element $element the new element |
||
170 | * @param int $pos 0-based position of the element to replace |
||
171 | */ |
||
172 | public function replaceElement(Element $element, $pos) { |
||
176 | |||
177 | /** |
||
178 | * Remove an element from the form completely |
||
179 | * |
||
180 | * @param int $pos 0-based position of the element to remove |
||
181 | */ |
||
182 | public function removeElement($pos) { |
||
185 | |||
186 | #endregion |
||
187 | |||
188 | #region Element adding functions |
||
189 | |||
190 | /** |
||
191 | * Adds a text input field |
||
192 | * |
||
193 | * @param string $name |
||
194 | * @param string $label |
||
195 | * @param int $pos |
||
196 | * @return InputElement |
||
197 | */ |
||
198 | public function addTextInput($name, $label = '', $pos = -1) { |
||
201 | |||
202 | /** |
||
203 | * Adds a password input field |
||
204 | * |
||
205 | * @param string $name |
||
206 | * @param string $label |
||
207 | * @param int $pos |
||
208 | * @return InputElement |
||
209 | */ |
||
210 | public function addPasswordInput($name, $label = '', $pos = -1) { |
||
213 | |||
214 | /** |
||
215 | * Adds a radio button field |
||
216 | * |
||
217 | * @param string $name |
||
218 | * @param string $label |
||
219 | * @param int $pos |
||
220 | * @return CheckableElement |
||
221 | */ |
||
222 | public function addRadioButton($name, $label = '', $pos = -1) { |
||
225 | |||
226 | /** |
||
227 | * Adds a checkbox field |
||
228 | * |
||
229 | * @param string $name |
||
230 | * @param string $label |
||
231 | * @param int $pos |
||
232 | * @return CheckableElement |
||
233 | */ |
||
234 | public function addCheckbox($name, $label = '', $pos = -1) { |
||
237 | |||
238 | /** |
||
239 | * Adds a dropdown field |
||
240 | * |
||
241 | * @param string $name |
||
242 | * @param array $options |
||
243 | * @param string $label |
||
244 | * @param int $pos |
||
245 | * @return DropdownElement |
||
246 | */ |
||
247 | public function addDropdown($name, $options, $label = '', $pos = -1) { |
||
250 | |||
251 | /** |
||
252 | * Adds a textarea field |
||
253 | * |
||
254 | * @param string $name |
||
255 | * @param string $label |
||
256 | * @param int $pos |
||
257 | * @return TextareaElement |
||
258 | */ |
||
259 | public function addTextarea($name, $label = '', $pos = -1) { |
||
262 | |||
263 | /** |
||
264 | * Adds a simple button, escapes the content for you |
||
265 | * |
||
266 | * @param string $name |
||
267 | * @param string $content |
||
268 | * @param int $pos |
||
269 | * @return Element |
||
270 | */ |
||
271 | public function addButton($name, $content, $pos = -1) { |
||
274 | |||
275 | /** |
||
276 | * Adds a simple button, allows HTML for content |
||
277 | * |
||
278 | * @param string $name |
||
279 | * @param string $html |
||
280 | * @param int $pos |
||
281 | * @return Element |
||
282 | */ |
||
283 | public function addButtonHTML($name, $html, $pos = -1) { |
||
286 | |||
287 | /** |
||
288 | * Adds a label referencing another input element, escapes the label for you |
||
289 | * |
||
290 | * @param string $label |
||
291 | * @param string $for |
||
292 | * @param int $pos |
||
293 | * @return Element |
||
294 | */ |
||
295 | public function addLabel($label, $for='', $pos = -1) { |
||
298 | |||
299 | /** |
||
300 | * Adds a label referencing another input element, allows HTML for content |
||
301 | * |
||
302 | * @param string $content |
||
303 | * @param string|Element $for |
||
304 | * @param int $pos |
||
305 | * @return Element |
||
306 | */ |
||
307 | public function addLabelHTML($content, $for='', $pos = -1) { |
||
321 | |||
322 | /** |
||
323 | * Add fixed HTML to the form |
||
324 | * |
||
325 | * @param string $html |
||
326 | * @param int $pos |
||
327 | * @return HTMLElement |
||
328 | */ |
||
329 | public function addHTML($html, $pos = -1) { |
||
332 | |||
333 | /** |
||
334 | * Add a closed HTML tag to the form |
||
335 | * |
||
336 | * @param string $tag |
||
337 | * @param int $pos |
||
338 | * @return TagElement |
||
339 | */ |
||
340 | public function addTag($tag, $pos = -1) { |
||
343 | |||
344 | /** |
||
345 | * Add an open HTML tag to the form |
||
346 | * |
||
347 | * Be sure to close it again! |
||
348 | * |
||
349 | * @param string $tag |
||
350 | * @param int $pos |
||
351 | * @return TagOpenElement |
||
352 | */ |
||
353 | public function addTagOpen($tag, $pos = -1) { |
||
356 | |||
357 | /** |
||
358 | * Add a closing HTML tag to the form |
||
359 | * |
||
360 | * Be sure it had been opened before |
||
361 | * |
||
362 | * @param string $tag |
||
363 | * @param int $pos |
||
364 | * @return TagCloseElement |
||
365 | */ |
||
366 | public function addTagClose($tag, $pos = -1) { |
||
369 | |||
370 | /** |
||
371 | * Open a Fieldset |
||
372 | * |
||
373 | * @param string $legend |
||
374 | * @param int $pos |
||
375 | * @return FieldsetOpenElement |
||
376 | */ |
||
377 | public function addFieldsetOpen($legend = '', $pos = -1) { |
||
380 | |||
381 | /** |
||
382 | * Close a fieldset |
||
383 | * |
||
384 | * @param int $pos |
||
385 | * @return TagCloseElement |
||
386 | */ |
||
387 | public function addFieldsetClose($pos = -1) { |
||
390 | |||
391 | #endregion |
||
392 | |||
393 | /** |
||
394 | * Adjust the elements so that fieldset open and closes are matching |
||
395 | */ |
||
396 | protected function balanceFieldsets() { |
||
430 | |||
431 | /** |
||
432 | * The HTML representation of the whole form |
||
433 | * |
||
434 | * @return string |
||
435 | */ |
||
436 | public function toHTML() { |
||
453 | } |
||
454 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.