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 FrmEntryValidate 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 FrmEntryValidate, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
3 | class FrmEntryValidate { |
||
4 | public static function validate( $values, $exclude = false ) { |
||
48 | |||
49 | public static function validate_field( $posted_field, &$errors, $values, $args = array() ) { |
||
50 | $defaults = array( |
||
51 | 'id' => $posted_field->id, |
||
52 | 'parent_field_id' => '', // the id of the repeat or embed form |
||
53 | 'key_pointer' => '', // the pointer in the posted array |
||
54 | 'exclude' => array(), // exclude these field types from validation |
||
55 | ); |
||
56 | $args = wp_parse_args( $args, $defaults ); |
||
57 | |||
58 | if ( empty($args['parent_field_id']) ) { |
||
59 | $value = isset( $values['item_meta'][ $args['id'] ] ) ? $values['item_meta'][ $args['id'] ] : ''; |
||
60 | } else { |
||
61 | // value is from a nested form |
||
62 | $value = $values; |
||
63 | } |
||
64 | |||
65 | // Check for values in "Other" fields |
||
66 | FrmEntriesHelper::maybe_set_other_validation( $posted_field, $value, $args ); |
||
67 | |||
68 | self::maybe_clear_value_for_default_blank_setting( $posted_field, $value ); |
||
69 | |||
70 | // Reset arrays with only one value if it's not a field where array keys need to be preserved |
||
71 | View Code Duplication | if ( is_array($value) && count( $value ) == 1 && isset( $value[0] ) ) { |
|
72 | $value = reset($value); |
||
73 | } |
||
74 | |||
75 | if ( $posted_field->required == '1' && ! is_array( $value ) && trim( $value ) == '' ) { |
||
76 | $errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $posted_field, 'blank' ); |
||
77 | } else if ( $posted_field->type == 'text' && ! isset( $_POST['item_name'] ) ) { |
||
78 | $_POST['item_name'] = $value; |
||
79 | } |
||
80 | |||
81 | if ( $value != '' ) { |
||
82 | self::validate_url_field( $errors, $posted_field, $value, $args ); |
||
83 | self::validate_email_field( $errors, $posted_field, $value, $args ); |
||
84 | self::validate_number_field( $errors, $posted_field, $value, $args ); |
||
85 | self::validate_phone_field( $errors, $posted_field, $value, $args ); |
||
86 | } |
||
87 | |||
88 | FrmEntriesHelper::set_posted_value($posted_field, $value, $args); |
||
89 | |||
90 | self::validate_recaptcha($errors, $posted_field, $args); |
||
91 | |||
92 | $errors = apply_filters( 'frm_validate_' . $posted_field->type . '_field_entry', $errors, $posted_field, $value, $args ); |
||
93 | $errors = apply_filters( 'frm_validate_field_entry', $errors, $posted_field, $value, $args ); |
||
94 | } |
||
95 | |||
96 | private static function maybe_clear_value_for_default_blank_setting( $field, &$value ) { |
||
97 | if ( FrmField::is_option_true_in_object( $field, 'default_blank' ) && $value == $field->default_value ) { |
||
98 | $value = ''; |
||
99 | } |
||
100 | } |
||
101 | |||
102 | public static function validate_url_field( &$errors, $field, &$value, $args ) { |
||
119 | |||
120 | public static function validate_email_field( &$errors, $field, $value, $args ) { |
||
130 | |||
131 | public static function validate_number_field( &$errors, $field, $value, $args ) { |
||
132 | //validate the number format |
||
133 | if ( $field->type != 'number' ) { |
||
134 | return; |
||
135 | } |
||
136 | |||
137 | View Code Duplication | if ( ! is_numeric( $value) ) { |
|
138 | $errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $field, 'invalid' ); |
||
139 | } |
||
140 | |||
141 | // validate number settings |
||
142 | if ( $value != '' ) { |
||
143 | $frm_settings = FrmAppHelper::get_settings(); |
||
144 | // only check if options are available in settings |
||
145 | if ( $frm_settings->use_html && isset( $field->field_options['minnum'] ) && isset( $field->field_options['maxnum'] ) ) { |
||
146 | //minnum maxnum |
||
147 | if ( (float) $value < $field->field_options['minnum'] ) { |
||
148 | $errors[ 'field' . $args['id'] ] = __( 'Please select a higher number', 'formidable' ); |
||
149 | } else if ( (float) $value > $field->field_options['maxnum'] ) { |
||
150 | $errors[ 'field' . $args['id'] ] = __( 'Please select a lower number', 'formidable' ); |
||
151 | } |
||
152 | } |
||
153 | } |
||
154 | } |
||
155 | |||
156 | public static function validate_phone_field( &$errors, $field, $value, $args ) { |
||
157 | if ( $field->type == 'phone' || ( $field->type == 'text' && FrmField::is_option_true_in_object( $field, 'format' ) ) ) { |
||
158 | |||
159 | $pattern = self::phone_format( $field ); |
||
160 | |||
161 | View Code Duplication | if ( ! preg_match( $pattern, $value ) ) { |
|
162 | $errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $field, 'invalid' ); |
||
163 | } |
||
164 | } |
||
165 | } |
||
166 | |||
167 | public static function phone_format( $field ) { |
||
168 | $default_format = '^((\+\d{1,3}(-|.| )?\(?\d\)?(-| |.)?\d{1,5})|(\(?\d{2,6}\)?))(-|.| )?(\d{3,4})(-|.| )?(\d{4})(( x| ext)\d{1,5}){0,1}$'; |
||
169 | if ( FrmField::is_option_empty( $field, 'format' ) ) { |
||
170 | $pattern = $default_format; |
||
171 | } else { |
||
172 | $pattern = FrmField::get_option( $field, 'format' ); |
||
173 | } |
||
174 | |||
175 | $pattern = apply_filters( 'frm_phone_pattern', $pattern, $field ); |
||
176 | |||
177 | // Create a regexp if format is not already a regexp |
||
178 | if ( strpos( $pattern, '^' ) !== 0 ) { |
||
179 | $pattern = self::create_regular_expression_from_format( $pattern ); |
||
180 | } |
||
181 | |||
182 | $pattern = '/' . $pattern . '/'; |
||
183 | return $pattern; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Create a regular expression from a phone number format |
||
188 | * |
||
189 | * @since 2.02.02 |
||
190 | * @param string $pattern |
||
191 | * @return string |
||
192 | */ |
||
193 | private static function create_regular_expression_from_format( $pattern ) { |
||
194 | $pattern = preg_quote( $pattern ); |
||
195 | |||
196 | // Firefox doesn't like escaped dashes or colons |
||
197 | $pattern = str_replace( array( '\-', '\:' ), array( '-', ':' ), $pattern ); |
||
198 | |||
199 | // Switch generic values out for their regular expression |
||
200 | $pattern = preg_replace( '/\d/', '\d', $pattern ); |
||
201 | $pattern = str_replace( 'a', '[a-z]', $pattern ); |
||
202 | $pattern = str_replace( 'A', '[A-Z]', $pattern ); |
||
203 | $pattern = str_replace( '*', 'w', $pattern ); |
||
204 | $pattern = str_replace( '/', '\/', $pattern ); |
||
205 | |||
206 | if ( strpos( $pattern, '\?' ) !== false ) { |
||
207 | $parts = explode( '\?', $pattern ); |
||
208 | $pattern = ''; |
||
209 | foreach ( $parts as $part ) { |
||
210 | if ( empty( $pattern ) ) { |
||
211 | $pattern .= $part; |
||
212 | } else { |
||
213 | $pattern .= '(' . $part . ')?'; |
||
214 | } |
||
215 | } |
||
216 | } |
||
217 | $pattern = '^' . $pattern . '$'; |
||
218 | |||
219 | return $pattern; |
||
220 | } |
||
221 | |||
222 | public static function validate_recaptcha( &$errors, $field, $args ) { |
||
261 | |||
262 | /** |
||
263 | * check for spam |
||
264 | * @param boolean $exclude |
||
265 | * @param array $values |
||
266 | * @param array $errors by reference |
||
267 | */ |
||
268 | public static function spam_check( $exclude, $values, &$errors ) { |
||
284 | |||
285 | private static function is_akismet_spam( $values ) { |
||
289 | |||
290 | private static function is_akismet_enabled_for_user( $form_id ) { |
||
294 | |||
295 | public static function blacklist_check( $values ) { |
||
296 | if ( ! apply_filters('frm_check_blacklist', true, $values) ) { |
||
297 | return false; |
||
298 | } |
||
341 | |||
342 | /** |
||
343 | * Check entries for spam |
||
344 | * |
||
345 | * @return boolean true if is spam |
||
346 | */ |
||
347 | public static function akismet( $values ) { |
||
367 | |||
368 | /** |
||
369 | * @since 2.0 |
||
370 | * @param string $content |
||
371 | */ |
||
372 | private static function parse_akismet_array( &$datas, $content ) { |
||
394 | } |
||
395 |
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.