Completed
Push — develop ( 7592b8...3eb7c5 )
by Zack
14:44
created

includes/class-ajax.php (2 issues)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
class GravityView_Ajax {
4
5
	function __construct() {
6
7
		//get field options
8
		add_action( 'wp_ajax_gv_field_options', array( $this, 'get_field_options' ) );
9
10
		// get available fields
11
		add_action( 'wp_ajax_gv_available_fields', array( $this, 'get_available_fields_html' ) );
12
13
		// get active areas
14
		add_action( 'wp_ajax_gv_get_active_areas', array( $this, 'get_active_areas' ) );
15
16
		// get preset fields
17
		add_action( 'wp_ajax_gv_get_preset_fields', array( $this, 'get_preset_fields_config' ) );
18
19
		// get preset fields
20
		add_action( 'wp_ajax_gv_set_preset_form', array( $this, 'create_preset_form' ) );
21
22
		add_action( 'wp_ajax_gv_sortable_fields_form', array( $this, 'get_sortable_fields' ) );
23
	}
24
25
	/**
26
	 * Handle exiting the script (for unit testing)
27
	 *
28
	 * @since 1.15
29
	 * @param bool|false $mixed
30
	 *
31
	 * @return bool
32
	 */
33
	private function _exit( $mixed = NULL ) {
34
35
		/**
36
		 * Don't exit if we're running test suite.
37
		 * @since 1.15
38
		 */
39
		if( defined( 'DOING_GRAVITYVIEW_TESTS' ) && DOING_GRAVITYVIEW_TESTS ) {
40
			return $mixed;
41
		}
42
43
		exit( $mixed );
44
	}
45
46
	/** -------- AJAX ---------- */
47
48
	/**
49
	 * Verify the nonce. Exit if not verified.
50
	 * @return void
51
	 */
52
	function check_ajax_nonce() {
53
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'gravityview_ajaxviews' ) ) {
54
			$this->_exit( false );
55
		}
56
	}
57
58
	/**
59
	 * Returns available fields given a form ID or a preset template ID
60
	 * AJAX callback
61
	 *
62
	 * @access public
63
	 * @return void
64
	 */
65
	function get_available_fields_html() {
66
67
		//check nonce
68
		$this->check_ajax_nonce();
69
70
		$context = isset($_POST['context']) ? esc_attr( $_POST['context'] ) : 'directory';
71
72
		// If Form was changed, JS sends form ID, if start fresh, JS sends template_id
73
		if( !empty( $_POST['form_id'] ) ) {
74
			do_action( 'gravityview_render_available_fields', (int) $_POST['form_id'], $context );
75
			$this->_exit();
76
		} elseif( !empty( $_POST['template_id'] ) ) {
77
			$form = GravityView_Ajax::pre_get_form_fields( $_POST['template_id'] );
0 ignored issues
show
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_POST
Loading history...
78
79
			/** @see GravityView_Admin_Views::render_available_fields */
80
			do_action( 'gravityview_render_available_fields', $form, $context );
81
			$this->_exit();
82
		}
83
84
		//if everything fails..
85
		$this->_exit( false );
86
	}
87
88
89
	/**
90
	 * Returns template active areas given a template ID
91
	 * AJAX callback
92
	 *
93
	 * @access public
94
	 * @return void
95
	 */
96
	function get_active_areas() {
97
		$this->check_ajax_nonce();
98
99
		if( empty( $_POST['template_id'] ) ) {
100
			$this->_exit( false );
101
		}
102
103
		ob_start();
104
		do_action( 'gravityview_render_directory_active_areas', $_POST['template_id'], 'directory', '', true );
105
		$response['directory'] = ob_get_clean();
106
107
		ob_start();
108
		do_action( 'gravityview_render_directory_active_areas',  $_POST['template_id'], 'single', '', true );
109
		$response['single'] = ob_get_clean();
110
111
		$response = array_map( 'gravityview_strip_whitespace', $response );
112
113
		$this->_exit( json_encode( $response ) );
114
	}
115
116
	/**
117
	 * Fill in active areas with preset configuration according to the template selected
118
	 * @return void
119
	 */
120
	function get_preset_fields_config() {
121
122
		$this->check_ajax_nonce();
123
124
		if( empty( $_POST['template_id'] ) ) {
125
			$this->_exit( false );
126
		}
127
128
		// get the fields xml config file for this specific preset
129
		$preset_fields_path = apply_filters( 'gravityview_template_fieldsxml', array(), $_POST['template_id'] );
130
		// import fields
131
		if( !empty( $preset_fields_path ) ) {
132
			$presets = $this->import_fields( $preset_fields_path );
133
		} else {
134
			$presets = array( 'widgets' => array(), 'fields' => array() );
135
		}
136
137
		$template_id = esc_attr( $_POST['template_id'] );
138
139
		// template areas
140
		$template_areas_directory = apply_filters( 'gravityview_template_active_areas', array(), $template_id, 'directory' );
141
        $template_areas_single = apply_filters( 'gravityview_template_active_areas', array(), $template_id, 'single' );
142
143
		// widget areas
144
		$default_widget_areas = GravityView_Plugin::get_default_widget_areas();
145
146
		ob_start();
147
		do_action('gravityview_render_active_areas', $template_id, 'widget', 'header', $default_widget_areas, $presets['widgets'] );
148
		$response['header'] = ob_get_clean();
149
150
		ob_start();
151
		do_action('gravityview_render_active_areas', $template_id, 'widget', 'footer', $default_widget_areas, $presets['widgets'] );
152
		$response['footer'] = ob_get_clean();
153
154
		ob_start();
155
		do_action('gravityview_render_active_areas', $template_id, 'field', 'directory', $template_areas_directory, $presets['fields'] );
156
		$response['directory'] = ob_get_clean();
157
158
		ob_start();
159
		do_action('gravityview_render_active_areas', $template_id, 'field', 'single', $template_areas_single, $presets['fields'] );
160
		$response['single'] = ob_get_clean();
161
162
		$response = array_map( 'gravityview_strip_whitespace', $response );
163
164
		do_action( 'gravityview_log_debug', '[get_preset_fields_config] AJAX Response', $response );
165
166
		$this->_exit( json_encode( $response ) );
167
	}
168
169
	/**
170
	 * Create the preset form requested before the View save
171
	 *
172
	 * @return void
173
	 */
174
	function create_preset_form() {
175
176
		$this->check_ajax_nonce();
177
178
		if( empty( $_POST['template_id'] ) ) {
179
			do_action( 'gravityview_log_error', '[create_preset_form] Cannot create preset form; the template_id is empty.' );
180
			$this->_exit( false );
181
		}
182
183
		// get the xml for this specific template_id
184
		$preset_form_xml_path = apply_filters( 'gravityview_template_formxml', '', $_POST['template_id'] );
185
186
		// import form
187
		$form = $this->import_form( $preset_form_xml_path );
188
189
		// get the form ID
190
		if( false === $form ) {
191
			// send error to user
192
			do_action( 'gravityview_log_error', '[create_preset_form] Error importing form for template id: ' . (int) $_POST['template_id'] );
193
194
			$this->_exit( false );
195
		}
196
197
		$this->_exit( '<option value="'.esc_attr( $form['id'] ).'" selected="selected">'.esc_html( $form['title'] ).'</option>' );
198
199
	}
200
201
	/**
202
	 * Import Gravity Form XML or JSON
203
	 *
204
	 * @param  string $xml_or_json_path Path to form XML or JSON file
205
	 * @return int|bool       Imported form ID or false
206
	 */
207 1
	function import_form( $xml_or_json_path = '' ) {
208
209 1
		do_action( 'gravityview_log_debug', '[import_form] Import Preset Form. (File)', $xml_or_json_path );
210
211 1
		if( empty( $xml_or_json_path ) || !class_exists('GFExport') || !file_exists( $xml_or_json_path ) ) {
212
			do_action( 'gravityview_log_error', '[import_form] Class GFExport or file not found. file: ', $xml_or_json_path );
213
			return false;
214
		}
215
216
		// import form
217 1
		$forms = '';
218 1
		$count = GFExport::import_file( $xml_or_json_path, $forms );
219
220 1
		do_action( 'gravityview_log_debug', '[import_form] Importing form (Result)', $count );
221 1
		do_action( 'gravityview_log_debug', '[import_form] Importing form (Form) ', $forms );
222
223 1
		if( $count != 1 || empty( $forms[0]['id'] ) ) {
224
			do_action( 'gravityview_log_error', '[import_form] Form Import Failed!' );
225
			return false;
226
		}
227
228
		// import success - return form id
229 1
		return $forms[0];
230
	}
231
232
233
	/**
234
	 * Returns field options - called by ajax when dropping fields into active areas
235
	 * AJAX callback
236
	 *
237
	 * @access public
238
	 * @return void
239
	 */
240
	function get_field_options() {
241
		$this->check_ajax_nonce();
242
243
		if( empty( $_POST['template'] ) || empty( $_POST['area'] ) || empty( $_POST['field_id'] ) || empty( $_POST['field_type'] ) ) {
244
			do_action( 'gravityview_log_error', '[get_field_options] Required fields were not set in the $_POST request. ' );
245
			$this->_exit( false );
246
		}
247
248
		// Fix apostrophes added by JSON response
249
		$_post = array_map( 'stripslashes_deep', $_POST );
250
251
		// Sanitize
252
		$_post = array_map( 'esc_attr', $_post );
253
254
		// The GF type of field: `product`, `name`, `creditcard`, `id`, `text`
255
		$input_type = isset($_post['input_type']) ? esc_attr( $_post['input_type'] ) : NULL;
256
		$context = isset($_post['context']) ? esc_attr( $_post['context'] ) : NULL;
257
258
		$response = GravityView_Render_Settings::render_field_options( $_post['field_type'], $_post['template'], $_post['field_id'], $_post['field_label'], $_post['area'], $input_type, '', '', $context  );
259
260
		$response = gravityview_strip_whitespace( $response );
261
262
		$this->_exit( $response );
263
	}
264
265
	/**
266
	 * Given a View id, calculates the assigned form, and returns the form fields (only the sortable ones )
267
	 * AJAX callback
268
	 *
269
	 *
270
	 * @access public
271
	 * @return void
272
	 */
273
	function get_sortable_fields() {
274
		$this->check_ajax_nonce();
275
276
		$form = '';
277
278
		// if form id is set, use it, else, get form from preset
279
		if( !empty( $_POST['form_id'] ) ) {
280
281
			$form = (int) $_POST['form_id'];
282
283
		}
284
		// get form from preset
285
		elseif( !empty( $_POST['template_id'] ) ) {
286
287
			$form = GravityView_Ajax::pre_get_form_fields( $_POST['template_id'] );
288
289
		}
290
291
		$response = gravityview_get_sortable_fields( $form );
292
293
		$response = gravityview_strip_whitespace( $response );
294
295
		$this->_exit( $response );
296
	}
297
298
	/**
299
	 * Get the the form fields for a preset (no form created yet)
300
	 * @param  string $template_id Preset template
301
	 *
302
	 */
303 2
	static function pre_get_form_fields( $template_id = '') {
304
305 2
		if( empty( $template_id ) ) {
306
			do_action( 'gravityview_log_error', __METHOD__ . ' - Template ID not set.' );
307
			return false;
308
		} else {
309 2
			$form_file = apply_filters( 'gravityview_template_formxml', '', $template_id );
310 2
			if( !file_exists( $form_file )  ) {
311
				do_action( 'gravityview_log_error', __METHOD__ . ' - Importing Form Fields for preset ['. $template_id .']. File not found. file: ' . $form_file );
312
				return false;
313
			}
314
		}
315
316
		// Load xml parser (from GravityForms)
317 2
		if( class_exists( 'GFCommon' ) ) {
318 2
			$xml_parser = GFCommon::get_base_path() . '/xml.php';
319
		} else {
320
			$xml_parser = trailingslashit( WP_PLUGIN_DIR ) . 'gravityforms/xml.php';
321
		}
322
323 2
		if( file_exists( $xml_parser ) ) {
324 2
			require_once( $xml_parser );
325
		} else {
326
			do_action( 'gravityview_log_debug', __METHOD__ . ' - Gravity Forms XML Parser not found.', $xml_parser );
327
			return false;
328
		}
329
330
		// load file
331 2
		$xmlstr = file_get_contents( $form_file );
332
333
        $options = array(
334 2
            "page" => array("unserialize_as_array" => true),
335
            "form"=> array("unserialize_as_array" => true),
336
            "field"=> array("unserialize_as_array" => true),
337
            "rule"=> array("unserialize_as_array" => true),
338
            "choice"=> array("unserialize_as_array" => true),
339
            "input"=> array("unserialize_as_array" => true),
340
            "routing_item"=> array("unserialize_as_array" => true),
341
            "creditCard"=> array("unserialize_as_array" => true),
342
            "routin"=> array("unserialize_as_array" => true),
343
            "confirmation" => array("unserialize_as_array" => true),
344
            "notification" => array("unserialize_as_array" => true)
345
        );
346
347 2
		$xml = new RGXML($options);
348 2
        $forms = $xml->unserialize($xmlstr);
349
350 2
        if( !$forms ) {
351
        	do_action( 'gravityview_log_error', '[pre_get_available_fields] Importing Form Fields for preset ['. $template_id .']. Error importing file. (File)', $form_file );
352
        	return false;
353
        }
354
355 2
        if( !empty( $forms[0] ) && is_array( $forms[0] ) ) {
356 2
        	$form = $forms[0];
357
        }
358
359 2
        if( empty( $form ) ) {
360
        	do_action( 'gravityview_log_error', '[pre_get_available_fields] $form not set.', $forms );
361
        	return false;
362
        }
363
364 2
        do_action( 'gravityview_log_debug', '[pre_get_available_fields] Importing Form Fields for preset ['. $template_id .']. (Form)', $form );
365
366 2
        return $form;
367
368
	}
369
370
371
	/**
372
	 * Import fields configuration from an exported WordPress View preset
373
	 * @param  string $file path to file
374
	 * @return array       Fields config array (unserialized)
375
	 */
376
	function import_fields( $file ) {
377
378
		if( empty( $file ) || !file_exists(  $file ) ) {
379
			do_action( 'gravityview_log_error', '[import_fields] Importing Preset Fields. File not found. (File)', $file );
380
			return false;
381
		}
382
383
		if( !class_exists('WXR_Parser') ) {
384
			include_once GRAVITYVIEW_DIR . 'includes/lib/xml-parsers/parsers.php';
385
		}
386
387
		$parser = new WXR_Parser();
388
		$presets = $parser->parse( $file );
389
390
		if(is_wp_error( $presets )) {
391
			do_action( 'gravityview_log_error', '[import_fields] Importing Preset Fields failed. Threw WP_Error.', $presets );
392
			return false;
393
		}
394
395
		if( empty( $presets['posts'][0]['postmeta'] ) && !is_array( $presets['posts'][0]['postmeta'] ) ) {
396
			do_action( 'gravityview_log_error', '[import_fields] Importing Preset Fields failed. Meta not found in file.', $file );
397
			return false;
398
		}
399
400
		do_action( 'gravityview_log_debug', '[import_fields] postmeta', $presets['posts'][0]['postmeta'] );
401
402
		$fields = $widgets = array();
403
		foreach( $presets['posts'][0]['postmeta'] as $meta ) {
404
			switch ($meta['key']) {
405
				case '_gravityview_directory_fields':
406
					$fields = maybe_unserialize( $meta['value'] );
407
					break;
408
				case '_gravityview_directory_widgets':
409
					$widgets = maybe_unserialize( $meta['value'] );
410
					break;
411
			}
412
		}
413
414
		do_action( 'gravityview_log_debug', '[import_fields] Imported Preset (Fields)', $fields );
415
		do_action( 'gravityview_log_debug', '[import_fields] Imported Preset (Widgets)', $widgets );
416
417
		return array(
418
			'fields' => $fields,
419
			'widgets' => $widgets
420
		);
421
	}
422
}
423
424
new GravityView_Ajax;
425