PluginProbe ʕ •ᴥ•ʔ
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More / 1.9.2.1
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More v1.9.2.1
1.10.1.1 1.10.1 1.10.0.5 trunk 1.1.4 1.1.4.2 1.1.5 1.1.5.1 1.1.6 1.1.6.1 1.1.7 1.1.7.1 1.1.7.2 1.1.8 1.1.8.1 1.1.8.2 1.1.8.3 1.1.8.4 1.10.0.1 1.10.0.2 1.10.0.3 1.10.0.4 1.2.0 1.2.0.1 1.2.1 1.2.2 1.2.2.1 1.2.2.2 1.2.3 1.2.3.1 1.2.3.2 1.2.4 1.2.4.1 1.2.5 1.2.5.1 1.2.6 1.2.7 1.2.8 1.2.8.1 1.2.9 1.3.0 1.3.1 1.3.1.1 1.3.1.2 1.3.2 1.3.3 1.3.5 1.3.6 1.3.6.1 1.3.6.2 1.3.7.2 1.3.7.3 1.3.7.4 1.3.8 1.3.9.1 1.4.0.1 1.4.1.1 1.4.2 1.4.2.1 1.4.2.2 1.4.3 1.4.4 1.4.4.1 1.4.5 1.4.5.1 1.4.5.2 1.4.5.3 1.4.6 1.4.7.1 1.4.7.2 1.4.8.1 1.4.9 1.5.0.1 1.5.0.3 1.5.0.4 1.5.1 1.5.1.1 1.5.1.3 1.5.2.1 1.5.2.2 1.5.2.3 1.5.3 1.5.3.1 1.5.4.1 1.5.4.2 1.5.5 1.5.5.1 1.5.6 1.5.6.2 1.5.7 1.5.8.2 1.5.9.1 1.5.9.4 1.5.9.5 1.6.0.1 1.6.0.2 1.6.1 1.6.2.2 1.6.2.3 1.6.3.1 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.7 1.6.7.1 1.6.7.2 1.6.7.3 1.6.8 1.6.8.1 1.6.9 1.7.0 1.7.1.1 1.7.1.2 1.7.2 1.7.2.1 1.7.3 1.7.4 1.7.4.1 1.7.4.2 1.7.5.1 1.7.5.2 1.7.5.3 1.7.5.5 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.7.9.1 1.8.0.1 1.8.0.2 1.8.1.1 1.8.1.2 1.8.1.3 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.3.1 1.8.4 1.8.4.1 1.8.5.2 1.8.5.3 1.8.5.4 1.8.6.2 1.8.6.3 1.8.6.4 1.8.7.2 1.8.8.2 1.8.8.3 1.8.9.1 1.8.9.2 1.8.9.4 1.8.9.5 1.8.9.6 1.9.0.1 1.9.0.2 1.9.0.3 1.9.0.4 1.9.1.1 1.9.1.2 1.9.1.3 1.9.1.4 1.9.1.5 1.9.1.6 1.9.2.1 1.9.2.2 1.9.2.3 1.9.3.1 1.9.3.2 1.9.4.1 1.9.4.2 1.9.5 1.9.5.1 1.9.5.2 1.9.6 1.9.6.1 1.9.6.2 1.9.7.1 1.9.7.2 1.9.7.3 1.9.8.1 1.9.8.2 1.9.8.4 1.9.8.7 1.9.9.2 1.9.9.3 1.9.9.4
wpforms-lite / includes / admin / ajax-actions.php
wpforms-lite / includes / admin Last commit date
builder 1 year ago admin.php 1 year ago ajax-actions.php 1 year ago class-about.php 1 year ago class-editor.php 1 year ago class-install-skin.php 1 year ago class-menu.php 1 year ago class-notices.php 1 year ago class-review.php 1 year ago class-settings.php 1 year ago class-welcome.php 1 year ago settings-api.php 1 year ago
ajax-actions.php
898 lines
1 <?php
2 /**
3 * Ajax actions used in by admin.
4 *
5 * @since 1.0.0
6 */
7
8 use WPForms\Helpers\DB;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit;
12 }
13
14 /**
15 * Save a form.
16 *
17 * @since 1.0.0
18 */
19 function wpforms_save_form() {
20
21 // Run a security check.
22 if ( ! check_ajax_referer( 'wpforms-builder', 'nonce', false ) ) {
23 wp_send_json_error( esc_html__( 'Your session expired. Please reload the builder.', 'wpforms-lite' ) );
24 }
25
26 // Check for permissions.
27 if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
28 wp_send_json_error( esc_html__( 'You are not allowed to perform this action.', 'wpforms-lite' ) );
29 }
30
31 // Check for form data.
32 if ( empty( $_POST['data'] ) ) {
33 wp_send_json_error( esc_html__( 'Something went wrong while performing this action.', 'wpforms-lite' ) );
34 }
35
36 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
37 $form_post = json_decode( wp_unslash( $_POST['data'] ), false );
38 $data = [
39 'fields' => [],
40 ];
41
42 if ( $form_post ) {
43 foreach ( $form_post as $post_input_data ) {
44 // For input names that are arrays (e.g. `menu-item-db-id[3][4][5]`),
45 // derive the array path keys via regex and set the value in $_POST.
46 preg_match( '#([^\[]*)(\[(.+)\])?#', $post_input_data->name, $matches );
47
48 $array_bits = [ $matches[1] ];
49
50 if ( isset( $matches[3] ) ) {
51 $array_bits = array_merge( $array_bits, explode( '][', $matches[3] ) );
52 }
53
54 $new_post_data = [];
55
56 // Build the new array value from leaf to trunk.
57 for ( $i = count( $array_bits ) - 1; $i >= 0; $i-- ) {
58 if ( $i === count( $array_bits ) - 1 ) {
59 $new_post_data[ $array_bits[ $i ] ] = wp_slash( $post_input_data->value );
60 } else {
61 $new_post_data = [
62 $array_bits[ $i ] => $new_post_data,
63 ];
64 }
65 }
66
67 $data = array_replace_recursive( $data, $new_post_data );
68 }
69 }
70
71 // Get form tags.
72 $form_tags = isset( $data['settings']['form_tags_json'] ) ? json_decode( wp_unslash( $data['settings']['form_tags_json'] ), true ) : [];
73
74 // Clear not needed data.
75 unset( $data['settings']['form_tags_json'] );
76
77 // Store tags labels in the form settings.
78 $data['settings']['form_tags'] = wp_list_pluck( $form_tags, 'label' );
79
80 // Update form data.
81 $form_id = wpforms()->obj( 'form' )->update( $data['id'], $data, [ 'context' => 'save_form' ] );
82
83 /**
84 * Fires after updating form data.
85 *
86 * @since 1.4.0
87 *
88 * @param int $form_id Form ID.
89 * @param array $data Form data.
90 */
91 do_action( 'wpforms_builder_save_form', $form_id, $data );
92
93 if ( ! $form_id ) {
94 wp_send_json_error( esc_html__( 'Something went wrong while saving the form.', 'wpforms-lite' ) );
95 }
96
97 // Update form tags.
98 wp_set_post_terms(
99 $form_id,
100 wpforms()->obj( 'forms_tags_ajax' )->get_processed_tags( $form_tags ),
101 WPForms_Form_Handler::TAGS_TAXONOMY
102 );
103
104 $response_data = [
105 'form_name' => esc_html( $data['settings']['form_title'] ),
106 'form_desc' => $data['settings']['form_desc'],
107 'redirect' => admin_url( 'admin.php?page=wpforms-overview' ),
108 ];
109
110 /**
111 * Allows filtering ajax response data after form was saved.
112 *
113 * @since 1.5.1
114 *
115 * @param array $response_data The data to be sent in the response.
116 * @param int $form_id Form ID.
117 * @param array $data Form data.
118 */
119 $response_data = apply_filters(
120 'wpforms_builder_save_form_response_data',
121 $response_data,
122 $form_id,
123 $data
124 );
125
126 wp_send_json_success( $response_data );
127 }
128
129 add_action( 'wp_ajax_wpforms_save_form', 'wpforms_save_form' );
130
131 /**
132 * Create a new form.
133 *
134 * @since 1.0.0
135 */
136 function wpforms_new_form() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
137
138 check_ajax_referer( 'wpforms-builder', 'nonce' );
139
140 // Prevent second form creating if a user has no license set.
141 // Redirect will lead to the warning page.
142 if ( wpforms()->is_pro() && empty( wpforms_get_license_type() ) && wp_count_posts( 'wpforms' )->publish >= 1 ) {
143 wp_send_json_success( [ 'redirect' => admin_url( 'admin.php?page=wpforms-builder&view=setup' ) ] );
144 }
145
146 if ( empty( $_POST['title'] ) ) {
147 wp_send_json_error(
148 [
149 'error_type' => 'missing_form_title',
150 'message' => esc_html__( 'No Form Name Provided', 'wpforms-lite' ),
151 ]
152 );
153 }
154
155 $form_title = sanitize_text_field( wp_unslash( $_POST['title'] ) );
156 $form_template = empty( $_POST['template'] ) ? 'blank' : sanitize_text_field( wp_unslash( $_POST['template'] ) );
157 $category = empty( $_POST['category'] ) ? 'all' : sanitize_text_field( wp_unslash( $_POST['category'] ) );
158 $subcategory = empty( $_POST['subcategory'] ) ? 'all' : sanitize_text_field( wp_unslash( $_POST['subcategory'] ) );
159
160 if ( ! wpforms()->obj( 'builder_templates' )->is_valid_template( $form_template ) ) {
161 wp_send_json_error(
162 [
163 'error_type' => 'invalid_template',
164 'message' => esc_html__( 'The template you selected is currently not available, but you can try again later. If you continue to have trouble, please reach out to support.', 'wpforms-lite' ),
165 ]
166 );
167 }
168
169 $title_query = new WP_Query(
170 [
171 'post_type' => 'wpforms',
172 'title' => $form_title,
173 'posts_per_page' => 1,
174 'fields' => 'ids',
175 'update_post_meta_cache' => false,
176 'update_post_term_cache' => false,
177 'no_found_rows' => true,
178 ]
179 );
180 $title_exists = $title_query->post_count > 0;
181 $form_id = wpforms()->obj( 'form' )->add(
182 $form_title,
183 [],
184 [
185 'template' => $form_template,
186 'category' => $category,
187 'subcategory' => $subcategory,
188 ]
189 );
190
191 if ( $title_exists ) {
192
193 // Skip creating a revision for this action.
194 remove_action( 'post_updated', 'wp_save_post_revision' );
195
196 wp_update_post(
197 [
198 'ID' => $form_id,
199 'post_title' => $form_title . ' (ID #' . $form_id . ')',
200 ]
201 );
202
203 // Restore the initial revisions state.
204 add_action( 'post_updated', 'wp_save_post_revision' );
205 }
206
207 if ( ! $form_id ) {
208 wp_send_json_error(
209 [
210 'error_type' => 'cant_create_form',
211 'message' => esc_html__( 'Error Creating Form', 'wpforms-lite' ),
212 ]
213 );
214 }
215
216 if ( wpforms_current_user_can( 'edit_form_single', $form_id ) ) {
217 wp_send_json_success(
218 [
219 'id' => $form_id,
220 'redirect' => add_query_arg(
221 [
222 'view' => 'fields',
223 'form_id' => $form_id,
224 'newform' => '1',
225 ],
226 admin_url( 'admin.php?page=wpforms-builder' )
227 ),
228 ]
229 );
230 }
231
232 if ( wpforms_current_user_can( 'view_forms' ) ) {
233 wp_send_json_success( [ 'redirect' => admin_url( 'admin.php?page=wpforms-overview' ) ] );
234 }
235
236 wp_send_json_success( [ 'redirect' => admin_url() ] );
237 }
238
239 add_action( 'wp_ajax_wpforms_new_form', 'wpforms_new_form' );
240
241 /**
242 * Update form template.
243 *
244 * @since 1.0.0
245 */
246 function wpforms_update_form_template() {
247
248 // Run a security check.
249 check_ajax_referer( 'wpforms-builder', 'nonce' );
250
251 // Check for form ID.
252 if ( empty( $_POST['form_id'] ) ) {
253 wp_send_json_error(
254 [
255 'error_type' => 'invalid_form_id',
256 'message' => esc_html__( 'No Form ID Provided', 'wpforms-lite' ),
257 ]
258 );
259 }
260
261 // Set initial variables.
262 $form_id = absint( $_POST['form_id'] );
263 $form_template = empty( $_POST['template'] ) ? 'blank' : sanitize_text_field( wp_unslash( $_POST['template'] ) );
264 $category = empty( $_POST['category'] ) ? 'all' : sanitize_text_field( wp_unslash( $_POST['category'] ) );
265 $subcategory = empty( $_POST['subcategory'] ) ? 'all' : sanitize_text_field( wp_unslash( $_POST['subcategory'] ) );
266
267 // Check for valid template.
268 if ( ! wpforms()->obj( 'builder_templates' )->is_valid_template( $form_template ) ) {
269 wp_send_json_error(
270 [
271 'error_type' => 'invalid_template',
272 'message' => esc_html__( 'The template you selected is currently not available, but you can try again later. If you continue to have trouble, please reach out to support.', 'wpforms-lite' ),
273 ]
274 );
275 }
276
277 // Get current form data.
278 $data = wpforms()->obj( 'form' )->get(
279 $form_id,
280 [
281 'content_only' => true,
282 ]
283 );
284
285 // Get the cached data from the form template JSON.
286 $template_data = wpforms()->obj( 'builder_templates' )->get_template( $form_template );
287
288 // If the template title is set, use it. Otherwise, clear the form title.
289 $template_title = ! empty( $template_data['name'] ) ? $template_data['name'] : '';
290
291 // If the form title is set, use it. Otherwise, use the template title.
292 $form_title = ! empty( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : $template_title;
293
294 // Check if the current form title is equal to the previous template name.
295 // If so, set the form title equal to the new template name.
296 $prev_template_slug = $data['meta']['template'] ?? '';
297 $prev_template = wpforms()->obj( 'builder_templates' )->get_template( $prev_template_slug );
298 $form_title = isset( $prev_template['name'] ) && $prev_template['name'] === $form_title ? $template_title : $form_title;
299
300 // If the these template titles are empty, use the form title.
301 $form_pages_title = $template_title ? $template_title : $form_title;
302 $form_conversational_title = ! empty( $template_data['data']['settings']['conversational_forms_title'] ) ? $template_data['data']['settings']['conversational_forms_title'] : $form_title;
303
304 // If these template slugs are empty, use the form title.
305 $form_conversational_slug = ! empty( $template_data['data']['settings']['conversational_forms_page_slug'] ) ? $template_data['data']['settings']['conversational_forms_page_slug'] : $form_title;
306 $form_pages_slug = ! empty( $template_data['data']['settings']['form_pages_page_slug'] ) ? $template_data['data']['settings']['form_pages_page_slug'] : $form_title;
307
308 // Loop over notifications.
309 $notifications = $template_data['data']['settings']['notifications'] ?? [];
310
311 foreach ( $notifications as $key => $notification ) {
312 // If the subject is empty, set it to an empty string.
313 $notification_subject = ! empty( $notification['subject'] ) ? sanitize_text_field( $notification['subject'] ) : '';
314
315 $data['settings']['notifications'][ $key ]['subject'] = $notification_subject;
316 }
317
318 // Loop over confirmations.
319 $confirmations = $template_data['data']['settings']['confirmations'] ?? [];
320
321 foreach ( $confirmations as $key => $confirmation ) {
322
323 // If the message is empty, set it to an empty string.
324 $confirmation_message = ! empty( $confirmation['message'] ) ? wp_kses_post( $confirmation['message'] ) : '';
325
326 $data['settings']['confirmations'][ $key ]['message'] = $confirmation_message;
327 }
328
329 // Set updated form titles.
330 $data['settings']['form_title'] = sanitize_text_field( $form_title );
331 $data['settings']['form_pages_title'] = sanitize_text_field( $form_pages_title );
332 $data['settings']['conversational_forms_title'] = sanitize_text_field( $form_conversational_title );
333
334 // Set updated form slugs.
335 $data['settings']['form_pages_page_slug'] = sanitize_title( $form_pages_slug );
336 $data['settings']['conversational_forms_page_slug'] = sanitize_title( $form_conversational_slug );
337
338 // Try to update the form.
339 $updated = (bool) wpforms()->obj( 'form' )->update(
340 $form_id,
341 $data,
342 [
343 'template' => $form_template,
344 'category' => $category,
345 'subcategory' => $subcategory,
346 ]
347 );
348
349 // If the form was updated, return the form ID and redirect to the form builder.
350 if ( $updated ) {
351 wp_send_json_success(
352 [
353 'id' => $form_id,
354 'redirect' => add_query_arg(
355 [
356 'view' => 'fields',
357 'form_id' => $form_id,
358 ],
359 admin_url( 'admin.php?page=wpforms-builder' )
360 ),
361 ]
362 );
363 }
364
365 // Otherwise, return an error.
366 wp_send_json_error(
367 [
368 'error_type' => 'cant_update',
369 'message' => esc_html__( 'Error Updating Template', 'wpforms-lite' ),
370 ]
371 );
372 }
373
374 add_action( 'wp_ajax_wpforms_update_form_template', 'wpforms_update_form_template' );
375
376 /**
377 * Form Builder update next field ID.
378 *
379 * @since 1.2.9
380 */
381 function wpforms_builder_increase_next_field_id() {
382
383 // Run a security check.
384 check_ajax_referer( 'wpforms-builder', 'nonce' );
385
386 // Check for permissions.
387 if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
388 wp_send_json_error();
389 }
390
391 // Check for required items.
392 if ( empty( $_POST['form_id'] ) ) {
393 wp_send_json_error();
394 }
395
396 $args = [];
397
398 // In the case of duplicating the Layout field that contains a bunch of fields,
399 // we need to set the next `field_id` to the desired value which is passed via POST argument.
400 if ( ! empty( $_POST['field_id'] ) ) {
401 $args['field_id'] = sanitize_text_field( wp_unslash( $_POST['field_id'] ) );
402 }
403
404 wpforms()->obj( 'form' )->next_field_id( absint( $_POST['form_id'] ), $args );
405
406 wp_send_json_success();
407 }
408
409 add_action( 'wp_ajax_wpforms_builder_increase_next_field_id', 'wpforms_builder_increase_next_field_id' );
410
411 /**
412 * Form Builder Dynamic Choices option toggle.
413 *
414 * This can be triggered with select/radio/checkbox fields.
415 *
416 * @since 1.2.8
417 */
418 function wpforms_builder_dynamic_choices() {
419
420 // Run a security check.
421 check_ajax_referer( 'wpforms-builder', 'nonce' );
422
423 // Check for permissions.
424 if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
425 wp_send_json_error();
426 }
427
428 // Check for valid/required items.
429 if ( ! isset( $_POST['field_id'] ) || empty( $_POST['type'] ) || ! in_array( $_POST['type'], [ 'post_type', 'taxonomy' ], true ) ) {
430 wp_send_json_error();
431 }
432
433 $type = sanitize_key( $_POST['type'] );
434 $id = sanitize_text_field( wp_unslash( $_POST['field_id'] ) );
435
436 // Fetch the option row HTML to be returned to the builder.
437 $field = new WPForms_Field_Select( false );
438 $field_args = [
439 'id' => $id,
440 'dynamic_choices' => $type,
441 ];
442 $option_row = $field->field_option( 'dynamic_choices_source', $field_args, [], false );
443
444 wp_send_json_success(
445 [
446 'markup' => $option_row,
447 ]
448 );
449 }
450
451 add_action( 'wp_ajax_wpforms_builder_dynamic_choices', 'wpforms_builder_dynamic_choices' );
452
453 /**
454 * Form Builder Dynamic Choices Source option toggle.
455 *
456 * This can be triggered with select/radio/checkbox fields.
457 *
458 * @since 1.2.8
459 */
460 function wpforms_builder_dynamic_source() {
461
462 // Run a security check.
463 check_ajax_referer( 'wpforms-builder', 'nonce' );
464
465 // Check for permissions.
466 if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
467 wp_send_json_error();
468 }
469
470 // Check for required items.
471 if ( ! isset( $_POST['field_id'] ) || empty( $_POST['form_id'] ) || empty( $_POST['type'] ) || empty( $_POST['source'] ) ) {
472 wp_send_json_error();
473 }
474
475 $type = sanitize_key( $_POST['type'] );
476 $source = sanitize_key( $_POST['source'] );
477 $id = sanitize_text_field( wp_unslash( $_POST['field_id'] ) );
478 $form_id = absint( $_POST['form_id'] );
479 $items = [];
480 $total = 0;
481 $source_name = '';
482 $type_name = '';
483
484 if ( $type === 'post_type' ) {
485
486 $type_name = esc_html__( 'post type', 'wpforms-lite' );
487 $args = [
488 'post_type' => $source,
489 'posts_per_page' => 20,
490 'orderby' => 'title',
491 'order' => 'ASC',
492 ];
493 $posts = wpforms_get_hierarchical_object(
494 apply_filters(
495 'wpforms_dynamic_choice_post_type_args',
496 $args,
497 [
498 'id' => $id,
499 ],
500 $form_id
501 ),
502 true
503 );
504 $total = wp_count_posts( $source );
505 $total = $total->publish;
506 $pt = get_post_type_object( $source );
507
508 if ( $pt !== null ) {
509 $source_name = $pt->labels->name;
510 }
511
512 foreach ( $posts as $post ) {
513 $items[] = esc_html( wpforms_get_post_title( $post ) );
514 }
515 } elseif ( $type === 'taxonomy' ) {
516
517 $type_name = esc_html__( 'taxonomy', 'wpforms-lite' );
518 $args = [
519 'taxonomy' => $source,
520 'hide_empty' => false,
521 'number' => 20,
522 ];
523 $terms = wpforms_get_hierarchical_object(
524 apply_filters(
525 'wpforms_dynamic_choice_taxonomy_args',
526 $args,
527 [
528 'id' => $id,
529 ],
530 $form_id
531 ),
532 true
533 );
534 $total = wp_count_terms( $source );
535 $tax = get_taxonomy( $source );
536 $source_name = $tax->labels->name;
537
538 foreach ( $terms as $term ) {
539 $items[] = esc_html( wpforms_get_term_name( $term ) );
540 }
541 }
542
543 if ( empty( $items ) ) {
544 $items = [];
545 }
546
547 wp_send_json_success(
548 [
549 'items' => $items,
550 'source' => $source,
551 'source_name' => $source_name,
552 'total' => $total,
553 'type' => $type,
554 'type_name' => $type_name,
555 ]
556 );
557 }
558
559 add_action( 'wp_ajax_wpforms_builder_dynamic_source', 'wpforms_builder_dynamic_source' );
560
561 /**
562 * Perform test connection to verify that the current web host can successfully
563 * make outbound SSL connections.
564 *
565 * @since 1.4.5
566 */
567 function wpforms_verify_ssl() {
568
569 // Run a security check.
570 check_ajax_referer( 'wpforms-admin', 'nonce' );
571
572 // Check for permissions.
573 if ( ! wpforms_current_user_can() ) {
574 wp_send_json_error(
575 [
576 'msg' => esc_html__( 'You do not have permission to perform this operation.', 'wpforms-lite' ),
577 ]
578 );
579 }
580
581 $response = wp_remote_post( 'https://wpforms.com/connection-test.php' );
582
583 if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
584 wp_send_json_success(
585 [
586 'msg' => esc_html__( 'Success! Your server can make SSL connections.', 'wpforms-lite' ),
587 ]
588 );
589 }
590
591 wp_send_json_error(
592 [
593 'msg' => esc_html__( 'There was an error and the connection failed. Please contact your web host with the technical details below.', 'wpforms-lite' ),
594 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
595 'debug' => '<pre>' . print_r( map_deep( $response, 'wp_strip_all_tags' ), true ) . '</pre>',
596 ]
597 );
598 }
599 add_action( 'wp_ajax_wpforms_verify_ssl', 'wpforms_verify_ssl' );
600
601 /**
602 * Recreate custom database tables.
603 *
604 * @since 1.9.0
605 */
606 function wpforms_recreate_tables() {
607
608 // Run a security check.
609 check_ajax_referer( 'wpforms-admin', 'nonce' );
610
611 // Check for permissions.
612 if ( ! wpforms_current_user_can() ) {
613 wp_send_json_error(
614 [
615 'msg' => esc_html__( 'You do not have permission to perform this operation.', 'wpforms-lite' ),
616 ]
617 );
618 }
619
620 DB::create_custom_tables( true );
621
622 if ( DB::custom_tables_exist() ) {
623 wp_send_json_success(
624 [
625 'msg' => esc_html__( 'WPForms custom database tables are recreated.', 'wpforms-lite' ),
626 ]
627 );
628 }
629
630 wp_send_json_error(
631 [
632 'msg' => esc_html__( 'Error recreating WPForms custom database tables.', 'wpforms-lite' ),
633 ]
634 );
635 }
636
637 add_action( 'wp_ajax_wpforms_recreate_tables', 'wpforms_recreate_tables' );
638
639 /**
640 * Deactivate addon.
641 *
642 * @since 1.0.0
643 * @since 1.6.2.3 Updated the permissions checking.
644 */
645 function wpforms_deactivate_addon() {
646
647 // Run a security check.
648 check_ajax_referer( 'wpforms-admin', 'nonce' );
649
650 // Check for permissions.
651 if ( ! current_user_can( 'deactivate_plugins' ) ) {
652 wp_send_json_error( esc_html__( 'Plugin deactivation is disabled for you on this site.', 'wpforms-lite' ) );
653 }
654
655 $type = empty( $_POST['type'] ) ? 'addon' : sanitize_key( $_POST['type'] );
656
657 if ( isset( $_POST['plugin'] ) ) {
658 $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
659
660 deactivate_plugins( $plugin );
661
662 do_action( 'wpforms_plugin_deactivated', $plugin );
663
664 if ( $type === 'plugin' ) {
665 wp_send_json_success( esc_html__( 'Plugin deactivated.', 'wpforms-lite' ) );
666 } else {
667 wp_send_json_success( esc_html__( 'Addon deactivated.', 'wpforms-lite' ) );
668 }
669 }
670
671 wp_send_json_error( esc_html__( 'Could not deactivate the addon. Please deactivate from the Plugins page.', 'wpforms-lite' ) );
672 }
673 add_action( 'wp_ajax_wpforms_deactivate_addon', 'wpforms_deactivate_addon' );
674
675 /**
676 * Activate addon.
677 *
678 * @since 1.0.0
679 * @since 1.6.2.3 Updated the permissions checking.
680 */
681 function wpforms_activate_addon() {
682
683 // Run a security check.
684 check_ajax_referer( 'wpforms-admin', 'nonce' );
685
686 // Check for permissions.
687 if ( ! current_user_can( 'activate_plugins' ) ) {
688 wp_send_json_error( esc_html__( 'Plugin activation is disabled for you on this site.', 'wpforms-lite' ) );
689 }
690
691 $success_messages = [
692 'plugin' => __( 'Plugin activated.', 'wpforms-lite' ),
693 'addon' => __( 'Addon activated.', 'wpforms-lite' ),
694 ];
695 $error_messages = [
696 'plugin' => __( 'Could not activate the plugin. Please activate it on the Plugins page.', 'wpforms-lite' ),
697 'addon' => __( 'Could not activate the addon. Please activate it on the Plugins page.', 'wpforms-lite' ),
698 ];
699
700 $type = ! empty( $_POST['type'] ) ? sanitize_key( $_POST['type'] ) : 'addon';
701 $success_message = $success_messages[ $type ];
702 $error_message = $error_messages[ $type ];
703
704 if ( isset( $_POST['plugin'] ) ) {
705 $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
706 $activate = wpforms_activate_plugin( $plugin );
707
708 /**
709 * Fire after plugin activating via the WPForms installer.
710 *
711 * @since 1.6.3.1
712 *
713 * @param string $plugin Path to the plugin file relative to the plugins' directory.
714 */
715 do_action( 'wpforms_plugin_activated', $plugin );
716
717 if ( $activate === null ) {
718 wp_send_json_success( wp_kses_post( $success_message ) );
719 }
720
721 $error_message = $activate->get_error_message();
722 }
723
724 wp_send_json_error( wp_kses_post( $error_message ) );
725 }
726
727 add_action( 'wp_ajax_wpforms_activate_addon', 'wpforms_activate_addon' );
728
729 /**
730 * Install addon.
731 *
732 * @since 1.0.0
733 * @since 1.6.2.3 Updated the permissions checking.
734 *
735 * @noinspection HtmlUnknownTarget
736 */
737 function wpforms_install_addon() {
738
739 // Run a security check.
740 check_ajax_referer( 'wpforms-admin', 'nonce' );
741
742 $generic_error = esc_html__( 'There was an error while performing your request.', 'wpforms-lite' );
743 $type = ! empty( $_POST['type'] ) ? sanitize_key( $_POST['type'] ) : 'addon';
744
745 // Check if new installations are allowed.
746 if ( ! wpforms_can_install( $type ) ) {
747 wp_send_json_error( $generic_error );
748 }
749
750 $error = $type === 'plugin'
751 ? esc_html__( 'Could not install the plugin. Please download and install it manually.', 'wpforms-lite' )
752 : sprintf(
753 wp_kses( /* translators: %1$s - addon download URL, %2$s - link to manual installation guide, %3$s - link to contact support. */
754 __( 'Could not install the addon. Please <a href="%1$s" target="_blank" rel="noopener noreferrer">download it from wpforms.com</a> and <a href="%2$s" target="_blank" rel="noopener noreferrer">install it manually</a>, or <a href="%3$s" target="_blank" rel="noopener noreferrer">contact support</a> for assistance.', 'wpforms-lite' ),
755 [
756 'a' => [
757 'href' => true,
758 'target' => true,
759 'rel' => true,
760 ],
761 ]
762 ),
763 esc_url( wpforms_utm_link( 'https://wpforms.com/account/licenses/', 'Licenses', 'Addons Error' ) ),
764 esc_url( wpforms_utm_link( 'https://wpforms.com/docs/how-to-manually-install-addons-in-wpforms/', 'Addons Doc', 'Addons Error' ) ),
765 esc_url( wpforms_utm_link( 'https://wpforms.com/contact/', 'Contact', 'Addons Error' ) )
766 );
767
768 $plugin_url = ! empty( $_POST['plugin'] ) ? esc_url_raw( wp_unslash( $_POST['plugin'] ) ) : '';
769
770 if ( empty( $plugin_url ) ) {
771 wp_send_json_error( $error );
772 }
773
774 $args_str = ! empty( $_POST['args'] ) ? sanitize_text_field( wp_unslash( $_POST['args'] ) ) : '';
775 $args = json_decode( $args_str, true ) ?? [];
776
777 // Set the current screen to avoid undefined notices.
778 set_current_screen( 'wpforms_page_wpforms-settings' );
779
780 // Prepare variables.
781 $url = esc_url_raw(
782 add_query_arg(
783 [
784 'page' => 'wpforms-addons',
785 ],
786 admin_url( 'admin.php' )
787 )
788 );
789
790 ob_start();
791 $creds = request_filesystem_credentials( $url, '', false, false );
792
793 // Hide the filesystem credentials form.
794 ob_end_clean();
795
796 // Check for file system permissions.
797 if ( $creds === false ) {
798 wp_send_json_error( $error );
799 }
800
801 if ( ! WP_Filesystem( $creds ) ) {
802 wp_send_json_error( $error );
803 }
804
805 /*
806 * We do not need any extra credentials if we have gotten this far, so let's install the plugin.
807 */
808
809 require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-install-skin.php';
810
811 // Do not allow WordPress to search/download translations, as this will break JS output.
812 remove_action( 'upgrader_process_complete', [ 'Language_Pack_Upgrader', 'async_upgrade' ], 20 );
813
814 // Create the plugin upgrader with our custom skin.
815 $installer = new WPForms\Helpers\PluginSilentUpgrader( new WPForms_Install_Skin() );
816
817 // Error check.
818 if ( ! method_exists( $installer, 'install' ) ) {
819 wp_send_json_error( $error );
820 }
821
822 $installer->install( $plugin_url, $args );
823
824 // Flush the cache and return the newly installed plugin basename.
825 wp_cache_flush();
826
827 $plugin_basename = $installer->plugin_info();
828
829 if ( empty( $plugin_basename ) ) {
830 wp_send_json_error( $error );
831 }
832
833 $result = [
834 'msg' => $generic_error,
835 'is_activated' => false,
836 'basename' => $plugin_basename,
837 ];
838
839 // Check for permissions.
840 if ( ! current_user_can( 'activate_plugins' ) ) {
841 $result['msg'] = $type === 'plugin' ? esc_html__( 'Plugin installed.', 'wpforms-lite' ) : esc_html__( 'Addon installed.', 'wpforms-lite' );
842
843 wp_send_json_success( $result );
844 }
845
846 // Activate the plugin silently.
847 $activated = activate_plugin( $plugin_basename );
848
849 if ( ! is_wp_error( $activated ) ) {
850
851 /**
852 * Fire after plugin activating via the WPForms installer.
853 *
854 * @since 1.7.0
855 *
856 * @param string $plugin_basename Path to the plugin file relative to the plugins' directory.
857 */
858 do_action( 'wpforms_plugin_activated', $plugin_basename );
859
860 $result['is_activated'] = true;
861 $result['msg'] = $type === 'plugin' ? esc_html__( 'Plugin installed & activated.', 'wpforms-lite' ) : esc_html__( 'Addon installed & activated.', 'wpforms-lite' );
862
863 wp_send_json_success( $result );
864 }
865
866 // Fallback error just in case.
867 wp_send_json_error( $result );
868 }
869 add_action( 'wp_ajax_wpforms_install_addon', 'wpforms_install_addon' );
870
871 /**
872 * Search pages for dropdown.
873 *
874 * @since 1.7.9
875 */
876 function wpforms_ajax_search_pages_for_dropdown() {
877
878 // Run a security check.
879 if ( ! check_ajax_referer( 'wpforms-builder', 'nonce', false ) ) {
880 wp_send_json_error( esc_html__( 'Your session expired. Please reload the builder.', 'wpforms-lite' ) );
881 }
882
883 if ( ! array_key_exists( 'search', $_GET ) ) {
884 wp_send_json_error( esc_html__( 'Incorrect usage of this operation.', 'wpforms-lite' ) );
885 }
886
887 $result_pages = wpforms_search_pages_for_dropdown(
888 sanitize_text_field( wp_unslash( $_GET['search'] ) )
889 );
890
891 if ( empty( $result_pages ) ) {
892 wp_send_json_success( [] );
893 }
894
895 wp_send_json_success( $result_pages );
896 }
897 add_action( 'wp_ajax_wpforms_ajax_search_pages_for_dropdown', 'wpforms_ajax_search_pages_for_dropdown' );
898