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 Complex_Field 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 Complex_Field, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class Complex_Field extends Field { |
||
14 | |||
15 | /** |
||
16 | * Visual layout type constants |
||
17 | */ |
||
18 | const LAYOUT_GRID = 'grid'; // default |
||
19 | |||
20 | const LAYOUT_TABBED_HORIZONTAL = 'tabbed-horizontal'; |
||
21 | |||
22 | const LAYOUT_TABBED_VERTICAL = 'tabbed-vertical'; |
||
23 | |||
24 | const TYPE_PROPERTY = '_type'; |
||
25 | |||
26 | /** |
||
27 | * Default field value |
||
28 | * |
||
29 | * @var array |
||
30 | */ |
||
31 | protected $default_value = array(); |
||
32 | |||
33 | /** |
||
34 | * Complex field layout |
||
35 | * |
||
36 | * @var string static::LAYOUT_* constant |
||
37 | */ |
||
38 | protected $layout = self::LAYOUT_GRID; |
||
39 | |||
40 | /** |
||
41 | * Value tree describing the complex values and all groups with their child fields |
||
42 | * |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $value_tree = array(); |
||
46 | |||
47 | /** |
||
48 | * Array of groups registered for this complex field |
||
49 | * |
||
50 | * @var array |
||
51 | */ |
||
52 | protected $groups = array(); |
||
53 | |||
54 | /** |
||
55 | * Minimum number of entries. -1 for no limit |
||
56 | * |
||
57 | * @var integer |
||
58 | */ |
||
59 | protected $values_min = -1; |
||
60 | |||
61 | /** |
||
62 | * Maximum number of entries. -1 for no limit |
||
63 | * |
||
64 | * @var integer |
||
65 | */ |
||
66 | protected $values_max = -1; |
||
67 | |||
68 | /** |
||
69 | * Default entry state - collapsed or not |
||
70 | * |
||
71 | * @var boolean |
||
72 | */ |
||
73 | protected $collapsed = false; |
||
74 | |||
75 | /** |
||
76 | * Defines whether duplicate groups are allowed or not |
||
77 | * |
||
78 | * @var boolean |
||
79 | */ |
||
80 | protected $duplicate_groups_allowed = true; |
||
81 | |||
82 | /** |
||
83 | * Entry labels |
||
84 | * These are translated in init() |
||
85 | * |
||
86 | * @var array |
||
87 | */ |
||
88 | public $labels = array( |
||
89 | 'singular_name' => 'Entry', |
||
90 | 'plural_name' => 'Entries', |
||
91 | ); |
||
92 | |||
93 | /** |
||
94 | * Create a field from a certain type with the specified label. |
||
95 | * |
||
96 | * @param string $type Field type |
||
97 | * @param string $name Field name |
||
98 | * @param string $label Field label |
||
99 | */ |
||
100 | public function __construct( $type, $name, $label ) { |
||
101 | $this->set_value_set( new Value_Set( Value_Set::TYPE_MULTIPLE_VALUES ) ); |
||
102 | parent::__construct( $type, $name, $label ); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Initialization tasks. |
||
107 | */ |
||
108 | public function init() { |
||
109 | $this->labels = array( |
||
110 | 'singular_name' => __( $this->labels['singular_name'], 'carbon-fields' ), |
||
111 | 'plural_name' => __( $this->labels['plural_name'], 'carbon-fields' ), |
||
112 | ); |
||
113 | parent::init(); |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * Set array of hierarchy field names |
||
118 | * |
||
119 | * @param array $hierarchy |
||
120 | * @return self $this |
||
121 | */ |
||
122 | public function set_hierarchy( $hierarchy ) { |
||
123 | parent::set_hierarchy( $hierarchy ); |
||
124 | $this->update_child_hierarchy(); |
||
125 | return $this; |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Propagate hierarchy to child fields |
||
130 | */ |
||
131 | public function update_child_hierarchy() { |
||
132 | $hierarchy = array_merge( $this->get_hierarchy(), array( $this->get_base_name() ) ); |
||
133 | $fields = $this->get_fields(); |
||
134 | foreach ( $fields as $field ) { |
||
135 | $field->set_hierarchy( $hierarchy ); |
||
136 | } |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Activate the field once the container is attached. |
||
141 | */ |
||
142 | public function activate() { |
||
143 | parent::activate(); |
||
144 | $fields = $this->get_fields(); |
||
145 | foreach ( $fields as $field ) { |
||
146 | $field->activate(); |
||
147 | } |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Set the datastore of this field and propagate it to children |
||
152 | * |
||
153 | * @param Datastore_Interface $datastore |
||
154 | * @param boolean $set_as_default |
||
155 | * @return self $this |
||
156 | */ |
||
157 | View Code Duplication | public function set_datastore( Datastore_Interface $datastore, $set_as_default = false ) { |
|
|
|||
158 | if ( $set_as_default && ! $this->has_default_datastore() ) { |
||
159 | return $this; // datastore has been overriden with a custom one - abort changing to a default one |
||
160 | } |
||
161 | $this->datastore = $datastore; |
||
162 | $this->has_default_datastore = $set_as_default; |
||
163 | |||
164 | $this->update_child_datastore( $this->get_datastore(), true ); |
||
165 | return $this; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Propagate the datastore down the hierarchy |
||
170 | * |
||
171 | * @param Datastore_Interface $datastore |
||
172 | * @param boolean $set_as_default |
||
173 | */ |
||
174 | protected function update_child_datastore( Datastore_Interface $datastore, $set_as_default = false ) { |
||
175 | foreach ( $this->groups as $group ) { |
||
176 | $group->set_datastore( $datastore, $set_as_default ); |
||
177 | } |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Retrieve all groups of fields. |
||
182 | * |
||
183 | * @return array $fields |
||
184 | */ |
||
185 | public function get_fields() { |
||
186 | $fields = array(); |
||
187 | |||
188 | foreach ( $this->groups as $group ) { |
||
189 | $group_fields = $group->get_fields(); |
||
190 | |||
191 | $fields = array_merge( $fields, $group_fields ); |
||
192 | } |
||
193 | |||
194 | return $fields; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Add a set/group of fields. |
||
199 | * |
||
200 | * Accepted param variations: |
||
201 | * - array<Field> $fields |
||
202 | * - string $group_name, array<Field> $fields |
||
203 | * - string $group_name, string $group_label, array<Field> $fields |
||
204 | * |
||
205 | * @return $this |
||
206 | */ |
||
207 | public function add_fields() { |
||
208 | $argv = func_get_args(); |
||
209 | $argc = count( $argv ); |
||
210 | $fields = $argv[ $argc - 1 ]; |
||
211 | $name = ''; |
||
212 | $label = null; |
||
213 | |||
214 | if ( $argc >= 2 ) { |
||
215 | $name = $argv[0]; |
||
216 | } |
||
217 | |||
218 | if ( $argc >= 3 ) { |
||
219 | $label = $argv[1]; |
||
220 | } |
||
221 | |||
222 | $name = ! empty( $name ) ? $name : Group_Field::DEFAULT_GROUP_NAME; |
||
223 | |||
224 | if ( array_key_exists( $name, $this->groups ) ) { |
||
225 | Incorrect_Syntax_Exception::raise( 'Group with name "' . $name . '" in Complex Field "' . $this->get_label() . '" already exists.' ); |
||
226 | return $this; |
||
227 | } |
||
228 | |||
229 | $reserved_names = array( Value_Set::VALUE_PROPERTY, static::TYPE_PROPERTY ); |
||
230 | foreach ( $fields as $field ) { |
||
231 | /** @var Field $field */ |
||
232 | if ( in_array( $field->get_base_name(), $reserved_names ) ) { |
||
233 | Incorrect_Syntax_Exception::raise( '"' . $field->get_base_name() . '" is a reserved keyword for Complex fields and cannot be used for a field name.' ); |
||
234 | return $this; |
||
235 | } |
||
236 | } |
||
237 | |||
238 | $group = new Group_Field( $name, $label, $fields ); |
||
239 | $this->groups[ $group->get_name() ] = $group; |
||
240 | |||
241 | $this->update_child_hierarchy(); |
||
242 | if ( $this->get_datastore() !== null ) { |
||
243 | $this->update_child_datastore( $this->get_datastore(), true ); |
||
244 | } |
||
245 | |||
246 | return $this; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Retrieve the groups of this field. |
||
251 | * |
||
252 | * @return array |
||
253 | */ |
||
254 | public function get_group_names() { |
||
255 | return array_keys( $this->groups ); |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * Retrieve a group by its name. |
||
260 | * |
||
261 | * @param string $group_name Group name |
||
262 | * @return Group_Field $group_object Group object |
||
263 | */ |
||
264 | public function get_group_by_name( $group_name ) { |
||
265 | $group_object = null; |
||
266 | |||
267 | foreach ( $this->groups as $group ) { |
||
268 | if ( $group->get_name() == $group_name ) { |
||
269 | $group_object = $group; |
||
270 | } |
||
271 | } |
||
272 | |||
273 | return $group_object; |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * Set the group label Underscore template. |
||
278 | * |
||
279 | * @param string|callable $template |
||
280 | * @return self $this |
||
281 | */ |
||
282 | public function set_header_template( $template ) { |
||
283 | $template = is_callable( $template ) ? call_user_func( $template ) : $template; |
||
284 | |||
285 | // Assign the template to the group that was added last |
||
286 | $values = array_values( $this->groups ); |
||
287 | $group = end( $values ); |
||
288 | |||
289 | if ( $group ) { |
||
290 | $group->set_label_template( $template ); |
||
291 | |||
292 | $this->groups[ $group->get_name() ] = $group; |
||
293 | } |
||
294 | |||
295 | return $this; |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Set the field labels. |
||
300 | * Currently supported values: |
||
301 | * - singular_name - the singular entry label |
||
302 | * - plural_name - the plural entries label |
||
303 | * |
||
304 | * @param array $labels Labels |
||
305 | * @return Complex_Field |
||
306 | */ |
||
307 | public function setup_labels( $labels ) { |
||
311 | |||
312 | /** |
||
313 | * Return a clone of a field with hierarchy settings applied |
||
314 | * |
||
315 | * @param Field $field |
||
316 | * @param Field $parent_field |
||
317 | * @param int $group_index |
||
318 | * @return Field |
||
319 | */ |
||
320 | public function get_clone_under_field_in_hierarchy( $field, $parent_field, $group_index = 0 ) { |
||
326 | |||
327 | protected function get_prefilled_group_fields( $group_fields, $group_values, $group_index ) { |
||
328 | $fields = array(); |
||
329 | |||
330 | foreach ( $group_fields as $field ) { |
||
331 | $clone = $this->get_clone_under_field_in_hierarchy( $field, $this, $group_index ); |
||
332 | if ( isset( $group_values[ $clone->get_base_name() ] ) ) { |
||
333 | $clone->set_value( $group_values[ $clone->get_base_name() ] ); |
||
334 | } |
||
335 | $fields[] = $clone; |
||
336 | } |
||
337 | |||
338 | return $fields; |
||
339 | } |
||
340 | |||
341 | protected function get_prefilled_groups( $groups, $value_tree ) { |
||
342 | $fields = array(); |
||
343 | |||
344 | foreach ( $value_tree as $group_index => $value ) { |
||
345 | $group_name = $groups[ $group_index ]; |
||
346 | $group = $this->get_group_by_name( $group_name ); |
||
347 | if ( ! $group ) { |
||
348 | // Failed to find group - sombody has been messing with the database or group definitions |
||
349 | continue; |
||
350 | } |
||
351 | $group_fields = $group->get_fields(); |
||
352 | $group_values = array(); |
||
353 | if ( isset( $value_tree[ $group_index ] ) ) { |
||
354 | $group_values = $value_tree[ $group_index ]; |
||
355 | } |
||
356 | $fields[ $group_index ] = array( Value_Set::VALUE_PROPERTY => $group->get_name() ) + $this->get_prefilled_group_fields( $group_fields, $group_values, $group_index ); |
||
357 | } |
||
358 | |||
359 | return $fields; |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Load the field value from an input array based on its name. |
||
364 | * |
||
365 | * @param array $input Array of field names and values. |
||
366 | * @return self $this |
||
367 | */ |
||
368 | public function set_value_from_input( $input ) { |
||
369 | if ( ! isset( $input[ $this->get_name() ] ) ) { |
||
370 | return $this; |
||
371 | } |
||
372 | |||
373 | $value_tree = array(); |
||
374 | $input_groups = $input[ $this->get_name() ]; |
||
375 | $input_group_index = 0; |
||
376 | foreach ( $input_groups as $values ) { |
||
377 | if ( ! isset( $values[ Value_Set::VALUE_PROPERTY ] ) || ! isset( $this->groups[ $values[ Value_Set::VALUE_PROPERTY ] ] ) ) { |
||
378 | continue; |
||
379 | } |
||
380 | |||
381 | $group = $this->get_group_by_name( $values[ Value_Set::VALUE_PROPERTY ] ); |
||
382 | $group_fields = $group->get_fields(); |
||
383 | $group_field_names = array_flip( $group->get_field_names() ); |
||
384 | |||
385 | $value_group = array( Value_Set::VALUE_PROPERTY => $values[ Value_Set::VALUE_PROPERTY ] ); |
||
386 | unset( $values[ Value_Set::VALUE_PROPERTY ] ); |
||
387 | |||
388 | // trim input values to those used by the field |
||
389 | $values = array_intersect_key( $values, $group_field_names ); |
||
390 | |||
391 | foreach ( $group_fields as $field ) { |
||
392 | $tmp_field = $this->get_clone_under_field_in_hierarchy( $field, $this, $input_group_index ); |
||
393 | |||
394 | $tmp_field->set_value_from_input( $values ); |
||
395 | if ( $tmp_field instanceof Complex_Field ) { |
||
396 | $value_group[ $tmp_field->get_base_name() ] = $tmp_field->get_value_tree(); |
||
397 | } else { |
||
398 | $value_group[ $tmp_field->get_base_name() ] = $tmp_field->get_full_value(); |
||
399 | } |
||
400 | } |
||
401 | $value_tree[] = $value_group; |
||
402 | $input_group_index++; |
||
403 | } |
||
404 | |||
405 | $this->set_value( $value_tree ); |
||
406 | return $this; |
||
407 | } |
||
408 | |||
409 | /** |
||
410 | * Save all contained groups of fields. |
||
411 | */ |
||
412 | public function save() { |
||
413 | // Only delete root field values as nested field values should be deleted in a cascading manner by the datastore |
||
414 | $hierarchy = $this->get_hierarchy(); |
||
415 | $delete_on_save = empty( $hierarchy ); |
||
416 | $delete_on_save = apply_filters( 'carbon_fields_should_delete_field_value_on_save', $delete_on_save, $this ); |
||
417 | if ( $delete_on_save ) { |
||
418 | $this->delete(); |
||
419 | } |
||
420 | |||
421 | $save = apply_filters( 'carbon_fields_should_save_field_value', true, $this->get_value(), $this ); |
||
422 | if ( $save ) { |
||
423 | $this->get_datastore()->save( apply_filters( 'carbon_fields_before_complex_field_save', $this ) ); |
||
424 | $field_groups = $this->get_prefilled_groups( $this->get_value(), $this->get_value_tree() ); |
||
425 | foreach ( $field_groups as $group_index => $fields ) { |
||
426 | foreach ( $fields as $field ) { |
||
427 | if ( ! ( $field instanceof Field ) ) { |
||
428 | continue; |
||
429 | } |
||
430 | $field->save(); |
||
431 | } |
||
432 | } |
||
433 | } |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * {@inheritDoc} |
||
438 | */ |
||
439 | public function get_formatted_value() { |
||
440 | $field_groups = $this->get_prefilled_groups( $this->get_value(), $this->get_value_tree() ); |
||
441 | |||
442 | $value = array(); |
||
443 | foreach ( $field_groups as $group_index => $field_group ) { |
||
444 | $value[ $group_index ] = array(); |
||
445 | foreach ( $field_group as $key => $field ) { |
||
446 | if ( $field instanceof Field ) { |
||
447 | $value[ $group_index ][ $field->get_base_name() ] = $field->get_formatted_value(); |
||
448 | } else { |
||
449 | if ( $key === Value_Set::VALUE_PROPERTY ) { |
||
450 | $value[ $group_index ][ static::TYPE_PROPERTY ] = $field; |
||
451 | } else { |
||
452 | $value[ $group_index ][ $key ] = $field; |
||
453 | } |
||
454 | } |
||
455 | } |
||
456 | } |
||
457 | return $value; |
||
458 | } |
||
459 | |||
460 | /** |
||
461 | * Convert an externally-keyed value array ('_type' => ...) |
||
462 | * to an internally-keyed one ('value' => ...) |
||
463 | * |
||
464 | * @param mixed $value |
||
465 | * @return mixed |
||
466 | */ |
||
467 | protected function external_to_internal_value( $value ) { |
||
479 | |||
480 | /** |
||
481 | * {@inheritDoc} |
||
482 | */ |
||
483 | public function set_value( $value ) { |
||
484 | $value = array_map( array( $this, 'external_to_internal_value' ), $value ); |
||
485 | $groups = array(); |
||
486 | foreach ( $value as $values ) { |
||
487 | $groups[] = isset( $values[ Value_Set::VALUE_PROPERTY ] ) ? $values[ Value_Set::VALUE_PROPERTY ] : Group_Field::DEFAULT_GROUP_NAME; |
||
488 | } |
||
489 | parent::set_value( $groups ); |
||
490 | $this->set_value_tree( $value ); |
||
491 | return $this; |
||
492 | } |
||
493 | |||
494 | /** |
||
495 | * {@inheritDoc} |
||
496 | */ |
||
497 | public function set_default_value( $default_value ) { |
||
498 | foreach ( $default_value as $index => $group ) { |
||
499 | if ( ! isset( $group[ static::TYPE_PROPERTY ] ) ) { |
||
500 | $default_value[ $index ][ static::TYPE_PROPERTY ] = Group_Field::DEFAULT_GROUP_NAME; |
||
501 | } |
||
502 | } |
||
503 | $this->default_value = $default_value; |
||
504 | return $this; |
||
505 | } |
||
506 | |||
507 | /** |
||
508 | * Return the full value tree of all groups and their fields |
||
509 | * |
||
510 | * @return mixed |
||
511 | */ |
||
512 | public function get_value_tree() { |
||
515 | |||
516 | /** |
||
517 | * Set the full value tree of all groups and their fields |
||
518 | * |
||
519 | * @see Internal Glossary in DEVELOPMENT.MD |
||
520 | * @param array $value_tree |
||
521 | * @return self $this |
||
522 | */ |
||
523 | public function set_value_tree( $value_tree ) { |
||
524 | $this->value_tree = $value_tree; |
||
525 | return $this; |
||
526 | } |
||
527 | |||
528 | /** |
||
529 | * Returns an array that holds the field data, suitable for JSON representation. |
||
530 | * |
||
531 | * @param bool $load Should the value be loaded from the database or use the value from the current instance. |
||
532 | * @return array |
||
533 | */ |
||
534 | public function to_json( $load ) { |
||
535 | $complex_data = parent::to_json( $load ); |
||
536 | |||
537 | $groups_data = array(); |
||
538 | foreach ( $this->groups as $group ) { |
||
539 | $group_data = $group->to_json( false ); |
||
540 | $group_data['collapsed'] = $this->get_collapsed(); |
||
541 | |||
542 | $groups_data[] = $group_data; |
||
543 | } |
||
544 | |||
545 | $field_groups = $this->get_prefilled_groups( $this->get_value(), $this->get_value_tree() ); |
||
546 | $value_data = array(); |
||
547 | foreach ( $field_groups as $group_index => $fields ) { |
||
548 | $group = $this->get_group_by_name( $fields[ Value_Set::VALUE_PROPERTY ] ); |
||
549 | |||
550 | $data = array( |
||
551 | 'name' => $group->get_name(), |
||
552 | 'label' => $group->get_label(), |
||
553 | 'label_template' => $group->get_label_template(), |
||
554 | 'group_id' => $group->get_group_id(), |
||
555 | 'collapsed' => $this->get_collapsed(), |
||
556 | 'fields' => array(), |
||
557 | ); |
||
558 | |||
559 | foreach ( $fields as $field ) { |
||
560 | if ( ! ( $field instanceof Field ) ) { |
||
561 | continue; |
||
562 | } |
||
563 | $data['fields'][] = $field->to_json( false ); |
||
564 | } |
||
565 | |||
566 | $value_data[] = $data; |
||
567 | } |
||
568 | |||
569 | $group_types = array(); |
||
570 | foreach ( $this->groups as $group ) { |
||
571 | $group_types[] = array( |
||
572 | 'name' => $group->get_name(), |
||
573 | 'label' => $group->get_label(), |
||
574 | ); |
||
575 | } |
||
576 | |||
577 | $complex_data = array_merge( $complex_data, array( |
||
578 | 'duplicate_groups_allowed' => $this->get_duplicate_groups_allowed(), |
||
579 | 'group_types' => $group_types, |
||
580 | 'layout' => $this->layout, |
||
581 | 'labels' => $this->labels, |
||
582 | 'min' => $this->get_min(), |
||
583 | 'max' => $this->get_max(), |
||
584 | 'multiple_groups' => count( $groups_data ) > 1, |
||
585 | 'groups' => $groups_data, |
||
586 | 'value' => $value_data, |
||
587 | 'collapsed' => $this->get_collapsed(), |
||
588 | ) ); |
||
589 | return $complex_data; |
||
590 | } |
||
591 | |||
592 | /** |
||
593 | * Modify the layout of this field. |
||
594 | * |
||
595 | * @param string $layout |
||
596 | * @return self $this |
||
597 | */ |
||
598 | public function set_layout( $layout ) { |
||
599 | $available_layouts = array( |
||
600 | static::LAYOUT_GRID, |
||
601 | static::LAYOUT_TABBED_HORIZONTAL, |
||
602 | static::LAYOUT_TABBED_VERTICAL, |
||
603 | ); |
||
604 | |||
605 | if ( ! in_array( $layout, $available_layouts ) ) { |
||
606 | $error_message = 'Incorrect layout ``' . $layout . '" specified. ' . |
||
607 | 'Available layouts: ' . implode( ', ', $available_layouts ); |
||
608 | |||
609 | Incorrect_Syntax_Exception::raise( $error_message ); |
||
610 | return $this; |
||
611 | } |
||
612 | |||
613 | $this->layout = $layout; |
||
614 | |||
615 | return $this; |
||
616 | } |
||
617 | |||
618 | /** |
||
619 | * Get the minimum number of entries. |
||
620 | * |
||
621 | * @return int $min |
||
622 | */ |
||
623 | public function get_min() { |
||
626 | |||
627 | /** |
||
628 | * Set the minimum number of entries. |
||
629 | * |
||
630 | * @param int $min |
||
631 | * @return self $this |
||
632 | */ |
||
633 | public function set_min( $min ) { |
||
637 | |||
638 | /** |
||
639 | * Get the maximum number of entries. |
||
640 | * |
||
641 | * @return int $max |
||
642 | */ |
||
643 | public function get_max() { |
||
646 | |||
647 | /** |
||
648 | * Set the maximum number of entries. |
||
649 | * |
||
650 | * @param int $max |
||
651 | * @return self $this |
||
652 | */ |
||
653 | public function set_max( $max ) { |
||
657 | |||
658 | /** |
||
659 | * Get collapsed state |
||
660 | * |
||
661 | * @return bool |
||
662 | */ |
||
663 | public function get_collapsed() { |
||
666 | |||
667 | /** |
||
668 | * Change the groups initial collapse state. |
||
669 | * This state relates to the state of which the groups are rendered. |
||
670 | * |
||
671 | * @param bool $collapsed |
||
672 | * @return self $this |
||
673 | */ |
||
674 | public function set_collapsed( $collapsed = true ) { |
||
678 | |||
679 | /** |
||
680 | * Get whether duplicate groups are allowed. |
||
681 | * |
||
682 | * @return bool |
||
683 | */ |
||
684 | public function get_duplicate_groups_allowed() { |
||
687 | |||
688 | /** |
||
689 | * Set whether duplicate groups are allowed. |
||
690 | * |
||
691 | * @param bool $allowed |
||
692 | * @return self $this |
||
693 | */ |
||
694 | public function set_duplicate_groups_allowed( $allowed ) { |
||
698 | } |
||
699 |
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.