Completed
Push — master ( 43ef23...13c1c6 )
by Stephanie
02:35
created

FrmXMLController   C

Complexity

Total Complexity 66

Size/Duplication

Total Lines 420
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 0
loc 420
rs 5.7474
c 0
b 0
f 0
wmc 66
lcom 1
cbo 8

12 Methods

Rating   Name   Duplication   Size   Complexity  
A menu() 0 3 1
B add_default_templates() 0 27 3
B route() 0 11 5
B form() 0 26 1
C import_xml() 0 63 10
B export_xml() 0 25 6
D generate_xml() 0 116 17
B prepare_types_array() 0 12 5
A generate_csv() 0 7 2
B csv() 0 54 7
B get_fields_for_csv_export() 0 36 6
A allow_mime() 0 13 3

How to fix   Complexity   

Complex Class

Complex classes like FrmXMLController 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 FrmXMLController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
class FrmXMLController {
4
5
	public static function menu() {
6
		add_submenu_page( 'formidable', 'Formidable | ' . __( 'Import/Export', 'formidable' ), __( 'Import/Export', 'formidable' ), 'frm_edit_forms', 'formidable-import', 'FrmXMLController::route' );
7
	}
8
9
	public static function add_default_templates() {
10
		if ( ! function_exists( 'libxml_disable_entity_loader' ) ) {
11
			// XML import is not enabled on your server
12
			return;
13
		}
14
15
		$set_err = libxml_use_internal_errors( true );
16
		$loader = libxml_disable_entity_loader( true );
17
18
		$files = apply_filters( 'frm_default_templates_files', array( FrmAppHelper::plugin_path() . '/classes/views/xml/default-templates.xml' ) );
19
20
		foreach ( (array) $files as $file ) {
21
			FrmXMLHelper::import_xml( $file );
22
			unset( $file );
23
		}
24
		/*
25
		if(is_wp_error($result))
26
			$errors[] = $result->get_error_message();
27
		else if($result)
28
			$message = $result;
29
		*/
30
31
		unset( $files );
32
33
		libxml_use_internal_errors( $set_err );
34
		libxml_disable_entity_loader( $loader );
35
	}
36
37
	public static function route() {
38
		$action = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action';
39
		$action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
40
		if ( 'import_xml' === $action ) {
41
			return self::import_xml();
42
		} elseif ( 'export_xml' === $action ) {
43
			return self::export_xml();
44
		} elseif ( apply_filters( 'frm_xml_route', true, $action ) ) {
45
			return self::form();
46
		}
47
	}
48
49
	public static function form( $errors = array(), $message = '' ) {
50
		$where = array(
51
			'status' => array( null, '', 'published' ),
52
		);
53
		$forms = FrmForm::getAll( $where, 'name' );
54
55
		$export_types = apply_filters( 'frm_xml_export_types', array(
56
			'forms' => __( 'Forms', 'formidable' ),
57
			'items' => __( 'Entries', 'formidable' ),
58
		) );
59
60
		$export_format = apply_filters( 'frm_export_formats', array(
61
			'xml' => array(
62
				'name'    => 'XML',
63
				'support' => 'forms',
64
				'count'   => 'multiple',
65
			),
66
			'csv' => array(
67
				'name'    => 'CSV',
68
				'support' => 'items',
69
				'count'   => 'single',
70
			),
71
		) );
72
73
		include( FrmAppHelper::plugin_path() . '/classes/views/xml/import_form.php' );
74
	}
75
76
	public static function import_xml() {
77
		$errors = array();
78
		$message = '';
79
80
		$permission_error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'import-xml', 'import-xml-nonce' );
81
		if ( false !== $permission_error ) {
82
			$errors[] = $permission_error;
83
			self::form( $errors );
84
			return;
85
		}
86
87
		if ( ! isset( $_FILES ) || ! isset( $_FILES['frm_import_file'] ) || empty( $_FILES['frm_import_file']['name'] ) || (int) $_FILES['frm_import_file']['size'] < 1 ) {
88
			$errors[] = __( 'Oops, you didn\'t select a file.', 'formidable' );
89
			self::form( $errors );
90
			return;
91
		}
92
93
		$file = $_FILES['frm_import_file']['tmp_name'];
94
95
		if ( ! is_uploaded_file( $file ) ) {
96
			unset( $file );
97
			$errors[] = __( 'The file does not exist, please try again.', 'formidable' );
98
			self::form( $errors );
99
			return;
100
		}
101
102
		//add_filter('upload_mimes', 'FrmXMLController::allow_mime');
103
104
		$export_format = apply_filters( 'frm_export_formats', array(
105
			'xml' => array(
106
				'name'    => 'XML',
107
				'support' => 'forms',
108
				'count'   => 'multiple',
109
			),
110
		) );
111
112
		$file_type = strtolower( pathinfo( $_FILES['frm_import_file']['name'], PATHINFO_EXTENSION ) );
113
		if ( 'xml' !== $file_type && isset( $export_format[ $file_type ] ) ) {
114
			// allow other file types to be imported
115
			do_action( 'frm_before_import_' . $file_type );
116
			return;
117
		}
118
		unset( $file_type );
119
120
		if ( ! function_exists( 'libxml_disable_entity_loader' ) ) {
121
			$errors[] = __( 'XML import is not enabled on your server.', 'formidable' );
122
			self::form( $errors );
123
			return;
124
		}
125
126
		$set_err = libxml_use_internal_errors( true );
127
		$loader = libxml_disable_entity_loader( true );
128
129
		$result = FrmXMLHelper::import_xml( $file );
130
		FrmXMLHelper::parse_message( $result, $message, $errors );
131
132
		unset( $file );
133
134
		libxml_use_internal_errors( $set_err );
135
		libxml_disable_entity_loader( $loader );
136
137
		self::form( $errors, $message );
138
	}
139
140
	public static function export_xml() {
141
		$error = FrmAppHelper::permission_nonce_error( 'frm_edit_forms', 'export-xml', 'export-xml-nonce' );
142
		if ( ! empty( $error ) ) {
143
			wp_die( esc_html( $error ) );
144
		}
145
146
		$ids = FrmAppHelper::get_post_param( 'frm_export_forms', array() );
147
		$type = FrmAppHelper::get_post_param( 'type', array() );
148
		$format = FrmAppHelper::get_post_param( 'format', 'xml', 'sanitize_title' );
149
150
		if ( ! headers_sent() && ! $type ) {
151
			wp_redirect( esc_url_raw( admin_url( 'admin.php?page=formidable-import' ) ) );
152
			die();
153
		}
154
155
		if ( 'xml' === $format ) {
156
			self::generate_xml( $type, compact( 'ids' ) );
157
		} elseif ( 'csv' === $format ) {
158
			self::generate_csv( compact( 'ids' ) );
159
		} else {
160
			do_action( 'frm_export_format_' . $format, compact( 'ids' ) );
161
		}
162
163
		wp_die();
164
	}
165
166
	public static function generate_xml( $type, $args = array() ) {
167
		global $wpdb;
168
169
		self::prepare_types_array( $type );
170
171
		$tables = array(
172
			'items'     => $wpdb->prefix . 'frm_items',
173
			'forms'     => $wpdb->prefix . 'frm_forms',
174
			'posts'     => $wpdb->posts,
175
			'styles'    => $wpdb->posts,
176
			'actions'   => $wpdb->posts,
177
		);
178
179
		$defaults = array(
180
			'ids' => false,
181
		);
182
		$args = wp_parse_args( $args, $defaults );
183
184
		$sitename = sanitize_key( get_bloginfo( 'name' ) );
185
186
		if ( ! empty( $sitename ) ) {
187
			$sitename .= '.';
188
		}
189
		$filename = $sitename . 'formidable.' . date( 'Y-m-d' ) . '.xml';
190
191
		header( 'Content-Description: File Transfer' );
192
		header( 'Content-Disposition: attachment; filename=' . $filename );
193
		header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
194
195
		//make sure ids are numeric
196
		if ( is_array( $args['ids'] ) && ! empty( $args['ids'] ) ) {
197
			$args['ids'] = array_filter( $args['ids'], 'is_numeric' );
198
		}
199
200
		$records = array();
201
202
		foreach ( $type as $tb_type ) {
203
			$where = array();
204
			$join = '';
205
			$table = $tables[ $tb_type ];
206
207
			$select = $table . '.id';
208
			$query_vars = array();
209
210
			switch ( $tb_type ) {
211
				case 'forms':
212
					//add forms
213
					if ( $args['ids'] ) {
214
						$where[] = array(
215
							'or'           => 1,
216
							$table . '.id' => $args['ids'],
217
							$table . '.parent_form_id' => $args['ids'],
218
						);
219
					} else {
220
						$where[ $table . '.status !' ] = 'draft';
221
					}
222
				break;
223
				case 'actions':
224
					$select = $table . '.ID';
225
					$where['post_type'] = FrmFormActionsController::$action_post_type;
226
					if ( ! empty( $args['ids'] ) ) {
227
						$where['menu_order'] = $args['ids'];
228
					}
229
				break;
230
				case 'items':
231
					//$join = "INNER JOIN {$wpdb->prefix}frm_item_metas im ON ($table.id = im.item_id)";
232
					if ( $args['ids'] ) {
233
						$where[ $table . '.form_id' ] = $args['ids'];
234
					}
235
				break;
236
				case 'styles':
237
					// Loop through all exported forms and get their selected style IDs
238
					$frm_style = new FrmStyle();
239
					$default_style = $frm_style->get_default_style();
240
					$form_ids = $args['ids'];
241
					$style_ids = array();
242
					foreach ( $form_ids as $form_id ) {
243
						$form_data = FrmForm::getOne( $form_id );
244
						// For forms that have not been updated while running 2.0, check if custom_style is set
245
						if ( isset( $form_data->options['custom_style'] ) ) {
246
							if ( 1 === $form_data->options['custom_style'] ) {
247
								$style_ids[] = $default_style->ID;
248
							} else {
249
								$style_ids[] = $form_data->options['custom_style'];
250
							}
251
						}
252
						unset( $form_id, $form_data );
253
					}
254
					$select = $table . '.ID';
255
					$where['post_type'] = 'frm_styles';
256
257
					// Only export selected styles
258
					if ( ! empty( $style_ids ) ) {
259
						$where['ID'] = $style_ids;
260
					}
261
				break;
262
				default:
263
					$select = $table . '.ID';
264
					$join = ' INNER JOIN ' . $wpdb->postmeta . ' pm ON (pm.post_id=' . $table . '.ID)';
265
					$where['pm.meta_key'] = 'frm_form_id';
266
267
					if ( empty( $args['ids'] ) ) {
268
						$where['pm.meta_value >'] = 1;
269
					} else {
270
						$where['pm.meta_value'] = $args['ids'];
271
					}
272
				break;
273
			}
274
275
			$records[ $tb_type ] = FrmDb::get_col( $table . $join, $where, $select );
276
			unset( $tb_type );
277
		}
278
279
		echo '<?xml version="1.0" encoding="' . esc_attr( get_bloginfo( 'charset' ) ) . "\" ?>\n";
280
		include( FrmAppHelper::plugin_path() . '/classes/views/xml/xml.php' );
281
	}
282
283
	private static function prepare_types_array( &$type ) {
284
		$type = (array) $type;
285
		if ( ! in_array( 'forms', $type ) && ( in_array( 'items', $type ) || in_array( 'posts', $type ) ) ) {
286
			// make sure the form is included if there are entries
287
			$type[] = 'forms';
288
		}
289
290
		if ( in_array( 'forms', $type ) ) {
291
			// include actions with forms
292
			$type[] = 'actions';
293
		}
294
	}
295
296
	public static function generate_csv( $atts ) {
297
		$form_ids = $atts['ids'];
298
		if ( empty( $form_ids ) ) {
299
			wp_die( esc_html__( 'Please select a form', 'formidable' ) );
300
		}
301
		self::csv( reset( $form_ids ) );
302
	}
303
304
	/**
305
	 * Export to CSV
306
	 * @since 2.0.19
307
	 */
308
	public static function csv( $form_id = false, $search = '', $fid = '' ) {
309
		FrmAppHelper::permission_check( 'frm_view_entries' );
310
311
		if ( ! $form_id ) {
312
			$form_id = FrmAppHelper::get_param( 'form', '', 'get', 'sanitize_text_field' );
313
			$search = FrmAppHelper::get_param( ( isset( $_REQUEST['s'] ) ? 's' : 'search' ), '', 'get', 'sanitize_text_field' );
314
			$fid = FrmAppHelper::get_param( 'fid', '', 'get', 'sanitize_text_field' );
315
		}
316
317
		set_time_limit( 0 ); //Remove time limit to execute this function
318
		$mem_limit = str_replace( 'M', '', ini_get( 'memory_limit' ) );
319
		if ( (int) $mem_limit < 256 ) {
320
			ini_set( 'memory_limit', '256M' );
321
		}
322
323
		global $wpdb;
324
325
		$form = FrmForm::getOne( $form_id );
326
		$form_id = $form->id;
327
328
		$form_cols = self::get_fields_for_csv_export( $form_id, $form );
329
330
		$item_id = FrmAppHelper::get_param( 'item_id', 0, 'get', 'sanitize_text_field' );
331
		if ( ! empty( $item_id ) ) {
332
			$item_id = explode( ',', $item_id );
333
		}
334
335
		$query = array(
336
			'form_id' => $form_id,
337
		);
338
339
		if ( $item_id ) {
340
			$query['id'] = $item_id;
341
		}
342
343
		/**
344
		 * Allows the query to be changed for fetching the entry ids to include in the export
345
		 *
346
		 * $query is the array of options to be filtered. It includes form_id, and maybe id (array of entry ids),
347
		 * and the search query. This should return an array, but it can be handled as a string as well.
348
		 */
349
		$query = apply_filters( 'frm_csv_where', $query, compact( 'form_id', 'search', 'fid', 'item_id' ) );
350
351
		$entry_ids = FrmDb::get_col( $wpdb->prefix . 'frm_items it', $query );
352
		unset( $query );
353
354
		if ( empty( $entry_ids ) ) {
355
			esc_html_e( 'There are no entries for that form.', 'formidable' );
356
		} else {
357
			FrmCSVExportHelper::generate_csv( compact( 'form', 'entry_ids', 'form_cols' ) );
358
		}
359
360
		wp_die();
361
	}
362
363
	/**
364
	* Get the fields that should be included in the CSV export
365
	*
366
	* @since 2.0.19
367
	*
368
	* @param int $form_id
369
	* @param object $form
370
	* @return array $csv_fields
371
	*/
372
	private static function get_fields_for_csv_export( $form_id, $form ) {
373
		// Phase frm_csv_field_ids out by 2.01.05
374
		$csv_field_ids = apply_filters( 'frm_csv_field_ids', '', $form_id, array(
375
			'form' => $form,
376
		) );
377
378
		if ( $csv_field_ids ) {
379
			 _deprecated_function( 'The frm_csv_field_ids filter', '2.0.19', 'the frm_csv_columns filter' );
380
			$where = array(
381
				'fi.type not' => FrmField::no_save_fields(),
382
				array(
383
					'or'         => 1,
384
					'fi.form_id' => $form->id,
385
					'fr.parent_form_id' => $form->id,
386
				),
387
			);
388
389
			if ( ! is_array( $csv_field_ids ) ) {
390
				$csv_field_ids = explode( ',', $csv_field_ids );
391
			}
392
			if ( ! empty( $csv_field_ids ) ) {
393
				$where['fi.id'] = $csv_field_ids;
394
			}
395
			$csv_fields = FrmField::getAll( $where, 'field_order' );
396
		} else {
397
			$csv_fields = FrmField::get_all_for_form( $form_id, '', 'include', 'include' );
398
			$no_export_fields = FrmField::no_save_fields();
399
			foreach ( $csv_fields as $k => $f ) {
400
				if ( in_array( $f->type, $no_export_fields, true ) ) {
401
					unset( $csv_fields[ $k ] );
402
				}
403
			}
404
		}
405
406
		return $csv_fields;
407
	}
408
409
	public static function allow_mime( $mimes ) {
410
		if ( ! isset( $mimes['csv'] ) ) {
411
			// allow csv files
412
			$mimes['csv'] = 'text/csv';
413
		}
414
415
		if ( ! isset( $mimes['xml'] ) ) {
416
			// allow xml
417
			$mimes['xml'] = 'text/xml';
418
		}
419
420
		return $mimes;
421
	}
422
}
423