Complex classes like FrmCSVExportHelper 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 FrmCSVExportHelper, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 6 | class FrmCSVExportHelper { |
||
| 7 | |||
| 8 | protected static $separator = ', '; |
||
| 9 | protected static $column_separator = ','; |
||
| 10 | protected static $line_break = 'return'; |
||
| 11 | protected static $charset = 'UTF-8'; |
||
| 12 | protected static $to_encoding = 'UTF-8'; |
||
| 13 | protected static $wp_date_format = 'Y-m-d H:i:s'; |
||
| 14 | protected static $comment_count = 0; |
||
| 15 | protected static $form_id = 0; |
||
| 16 | protected static $headings = array(); |
||
| 17 | protected static $fields = array(); |
||
| 18 | protected static $entry; |
||
| 19 | protected static $has_parent_id; |
||
| 20 | |||
| 21 | public static function csv_format_options() { |
||
| 22 | $formats = array( 'UTF-8', 'ISO-8859-1', 'windows-1256', 'windows-1251', 'macintosh' ); |
||
| 23 | $formats = apply_filters( 'frm_csv_format_options', $formats ); |
||
| 24 | |||
| 25 | return $formats; |
||
| 26 | } |
||
| 27 | |||
| 28 | public static function generate_csv( $atts ) { |
||
| 29 | global $frm_vars; |
||
| 30 | $frm_vars['prevent_caching'] = true; |
||
| 31 | |||
| 32 | self::$fields = $atts['form_cols']; |
||
| 33 | self::$form_id = $atts['form']->id; |
||
| 34 | self::set_class_paramters(); |
||
| 35 | self::set_has_parent_id( $atts['form'] ); |
||
| 36 | |||
| 37 | $filename = apply_filters( 'frm_csv_filename', gmdate( 'ymdHis', time() ) . '_' . sanitize_title_with_dashes( $atts['form']->name ) . '_formidable_entries.csv', $atts['form'] ); |
||
| 38 | unset( $atts['form'], $atts['form_cols'] ); |
||
| 39 | |||
| 40 | self::print_file_headers( $filename ); |
||
| 41 | unset( $filename ); |
||
| 42 | |||
| 43 | $comment_count = FrmDb::get_count( |
||
| 44 | 'frm_item_metas', |
||
| 45 | array( |
||
| 46 | 'item_id' => $atts['entry_ids'], |
||
| 47 | 'field_id' => 0, |
||
| 48 | 'meta_value like' => '{', |
||
| 49 | ), |
||
| 50 | array( |
||
| 51 | 'group_by' => 'item_id', |
||
| 52 | 'order_by' => 'count(*) DESC', |
||
| 53 | 'limit' => 1, |
||
| 54 | ) |
||
| 55 | ); |
||
| 56 | self::$comment_count = $comment_count; |
||
| 57 | |||
| 58 | self::prepare_csv_headings(); |
||
| 59 | |||
| 60 | // fetch 20 posts at a time rather than loading the entire table into memory |
||
| 61 | while ( $next_set = array_splice( $atts['entry_ids'], 0, 20 ) ) { |
||
| 62 | self::prepare_next_csv_rows( $next_set ); |
||
| 63 | } |
||
| 64 | } |
||
| 65 | |||
| 66 | private static function set_class_paramters() { |
||
| 77 | |||
| 78 | private static function set_has_parent_id( $form ) { |
||
| 81 | |||
| 82 | private static function print_file_headers( $filename ) { |
||
| 99 | |||
| 100 | public static function get_csv_format() { |
||
| 105 | |||
| 106 | private static function prepare_csv_headings() { |
||
| 107 | $headings = array(); |
||
| 121 | |||
| 122 | private static function field_headings( $col ) { |
||
| 140 | |||
| 141 | private static function csv_headings( &$headings ) { |
||
| 142 | $fields_by_repeater_id = array(); |
||
| 143 | $repeater_ids = array(); |
||
| 144 | |||
| 145 | foreach ( self::$fields as $col ) { |
||
| 146 | if ( $col->form_id === self::$form_id || ! $col->field_options['in_section'] ) { |
||
| 147 | $headings += self::field_headings( $col ); |
||
| 148 | } else { |
||
| 149 | $repeater_id = $col->field_options['in_section']; |
||
| 150 | $section = FrmField::getOne( $repeater_id ); |
||
| 151 | |||
| 152 | if ( $section && FrmField::is_repeating_field( $section ) ) { |
||
| 153 | $headings[ 'repeater' . $repeater_id ] = array(); // set a placeholder to maintain order for repeater fields |
||
| 154 | |||
| 155 | if ( ! isset( $fields_by_repeater_id[ $repeater_id ] ) ) { |
||
| 156 | $fields_by_repeater_id[ $repeater_id ] = array(); |
||
| 157 | $repeater_ids[] = $repeater_id; |
||
| 158 | } |
||
| 159 | |||
| 160 | $fields_by_repeater_id[ $repeater_id ][] = $col; |
||
| 161 | } |
||
| 162 | } |
||
| 163 | } |
||
| 164 | unset( $repeater_id, $col ); |
||
| 165 | |||
| 166 | if ( $repeater_ids ) { |
||
|
|
|||
| 167 | $where = array( 'field_id' => $repeater_ids ); |
||
| 168 | $repeater_meta = FrmDb::get_results( 'frm_item_metas', $where, 'field_id, meta_value' ); |
||
| 169 | $max = array_fill_keys( $repeater_ids, 0 ); |
||
| 170 | |||
| 171 | foreach ( $repeater_meta as $row ) { |
||
| 172 | $start = strpos( $row->meta_value, 'a:' ) + 2; |
||
| 173 | $end = strpos( $row->meta_value, ':{' ); |
||
| 174 | $length = substr( $row->meta_value, $start, $end - $start ); |
||
| 175 | |||
| 176 | if ( $length > $max[ $row->field_id ] ) { |
||
| 177 | $max[ $row->field_id ] = $length; |
||
| 178 | } |
||
| 179 | } |
||
| 180 | unset( $start, $end, $length, $row, $repeater_meta, $where ); |
||
| 181 | |||
| 182 | $flat = array(); |
||
| 183 | foreach ( $headings as $key => $heading ) { |
||
| 184 | if ( is_array( $heading ) ) { |
||
| 185 | $repeater_id = str_replace( 'repeater', '', $key ); |
||
| 186 | |||
| 187 | $repeater_headings = array(); |
||
| 188 | foreach ( $fields_by_repeater_id[ $repeater_id ] as $col ) { |
||
| 189 | $repeater_headings += self::field_headings( $col ); |
||
| 190 | } |
||
| 191 | |||
| 192 | for ( $i = 0; $i < $max[ $repeater_id ]; $i ++ ) { |
||
| 193 | foreach ( $repeater_headings as $repeater_key => $repeater_name ) { |
||
| 194 | $flat[ $repeater_key . '[' . $i . ']' ] = $repeater_name; |
||
| 195 | } |
||
| 196 | } |
||
| 197 | } else { |
||
| 198 | $flat[ $key ] = $heading; |
||
| 199 | } |
||
| 200 | } |
||
| 201 | unset( $key, $heading, $max, $repeater_headings, $repeater_id ); |
||
| 202 | |||
| 203 | $headings = $flat; |
||
| 204 | unset( $flat ); |
||
| 205 | } |
||
| 206 | |||
| 207 | if ( self::$comment_count ) { |
||
| 208 | for ( $i = 0; $i < self::$comment_count; $i ++ ) { |
||
| 209 | $headings[ 'comment' . $i ] = __( 'Comment', 'formidable' ); |
||
| 210 | $headings[ 'comment_user_id' . $i ] = __( 'Comment User', 'formidable' ); |
||
| 211 | $headings[ 'comment_created_at' . $i ] = __( 'Comment Date', 'formidable' ); |
||
| 212 | } |
||
| 213 | unset( $i ); |
||
| 214 | } |
||
| 215 | |||
| 216 | $headings['created_at'] = __( 'Timestamp', 'formidable' ); |
||
| 217 | $headings['updated_at'] = __( 'Last Updated', 'formidable' ); |
||
| 218 | $headings['user_id'] = __( 'Created By', 'formidable' ); |
||
| 219 | $headings['updated_by'] = __( 'Updated By', 'formidable' ); |
||
| 220 | $headings['is_draft'] = __( 'Draft', 'formidable' ); |
||
| 221 | $headings['ip'] = __( 'IP', 'formidable' ); |
||
| 222 | $headings['id'] = __( 'ID', 'formidable' ); |
||
| 223 | $headings['item_key'] = __( 'Key', 'formidable' ); |
||
| 224 | if ( self::has_parent_id() ) { |
||
| 225 | $headings['parent_id'] = __( 'Parent ID', 'formidable' ); |
||
| 226 | } |
||
| 227 | } |
||
| 228 | |||
| 229 | private static function has_parent_id() { |
||
| 232 | |||
| 233 | private static function prepare_next_csv_rows( $next_set ) { |
||
| 253 | |||
| 254 | private static function prepare_csv_row() { |
||
| 269 | |||
| 270 | private static function add_repeat_field_values_to_csv( &$entries ) { |
||
| 300 | |||
| 301 | private static function add_field_values_to_csv( &$row ) { |
||
| 341 | |||
| 342 | /** |
||
| 343 | * @since 2.0.23 |
||
| 344 | */ |
||
| 345 | private static function add_array_values_to_columns( &$row, $atts ) { |
||
| 355 | |||
| 356 | private static function add_entry_data_to_csv( &$row ) { |
||
| 369 | |||
| 370 | private static function print_csv_row( $rows ) { |
||
| 409 | |||
| 410 | public static function encode_value( $line ) { |
||
| 438 | |||
| 439 | /** |
||
| 440 | * Escape a " in a csv with another " |
||
| 441 | * |
||
| 442 | * @since 2.0 |
||
| 443 | */ |
||
| 444 | public static function escape_csv( $value ) { |
||
| 453 | } |
||
| 454 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)or! empty(...)instead.