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'] ); |
|
|
|
|
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
|
|
|
function import_form( $xml_or_json_path = '' ) { |
|
|
|
|
208
|
|
|
|
209
|
|
|
do_action( 'gravityview_log_debug', '[import_form] Import Preset Form. (File)', $xml_or_json_path ); |
210
|
|
|
|
211
|
|
|
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
|
|
|
$forms = ''; |
218
|
|
|
$count = GFExport::import_file( $xml_or_json_path, $forms ); |
219
|
|
|
|
220
|
|
|
do_action( 'gravityview_log_debug', '[import_form] Importing form (Result)', $count ); |
221
|
|
|
do_action( 'gravityview_log_debug', '[import_form] Importing form (Form) ', $forms ); |
222
|
|
|
|
223
|
|
|
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
|
|
|
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
|
|
|
static function pre_get_form_fields( $template_id = '') { |
|
|
|
|
304
|
|
|
|
305
|
|
|
if( empty( $template_id ) ) { |
306
|
|
|
do_action( 'gravityview_log_error', __METHOD__ . ' - Template ID not set.' ); |
307
|
|
|
return false; |
308
|
|
|
} else { |
309
|
|
|
$form_file = apply_filters( 'gravityview_template_formxml', '', $template_id ); |
310
|
|
|
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
|
|
|
if( class_exists( 'GFCommon' ) ) { |
318
|
|
|
$xml_parser = GFCommon::get_base_path() . '/xml.php'; |
319
|
|
|
} else { |
320
|
|
|
$xml_parser = trailingslashit( WP_PLUGIN_DIR ) . 'gravityforms/xml.php'; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
if( file_exists( $xml_parser ) ) { |
324
|
|
|
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
|
|
|
$xmlstr = file_get_contents( $form_file ); |
|
|
|
|
332
|
|
|
|
333
|
|
|
$options = array( |
334
|
|
|
"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
|
|
|
$xml = new RGXML($options); |
|
|
|
|
348
|
|
|
$forms = $xml->unserialize($xmlstr); |
|
|
|
|
349
|
|
|
|
350
|
|
|
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
|
|
|
if( !empty( $forms[0] ) && is_array( $forms[0] ) ) { |
|
|
|
|
356
|
|
|
$form = $forms[0]; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
if( empty( $form ) ) { |
360
|
|
|
do_action( 'gravityview_log_error', '[pre_get_available_fields] $form not set.', $forms ); |
361
|
|
|
return false; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
do_action( 'gravityview_log_debug', '[pre_get_available_fields] Importing Form Fields for preset ['. $template_id .']. (Form)', $form ); |
365
|
|
|
|
366
|
|
|
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
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.