PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.6.0
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.6.0
2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 All 96 releases
sureforms / inc / admin-ajax.php

admin-ajax.php in SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz 2.6.0, at inc/admin-ajax.php

454 lines 12.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Sureforms Admin Ajax Class.
4 *
5 * Class file for public functions.
6 *
7 * @package sureforms
8 */
9
10 namespace SRFM\Inc;
11
12 use BSF_UTM_Analytics;
13 use SRFM\Inc\Traits\Get_Instance;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 if ( ! function_exists( 'get_plugins' ) ) {
20 require_once ABSPATH . 'wp-admin/includes/plugin.php';
21 }
22
23 /**
24 * Public Class
25 *
26 * @since 0.0.1
27 */
28 class Admin_Ajax {
29 use Get_Instance;
30
31 /**
32 * Constructor
33 *
34 * @since 0.0.1
35 */
36 public function __construct() {
37 add_action( 'wp_ajax_sureforms_recommended_plugin_activate', [ $this, 'required_plugin_activate' ] );
38 add_action( 'wp_ajax_sureforms_recommended_plugin_install', 'wp_ajax_install_plugin' );
39 add_action( 'wp_ajax_sureforms_integration', [ $this, 'generate_data_for_suretriggers_integration' ] );
40 add_action( 'wp_ajax_srfm_download_export', [ $this, 'download_export_file' ] );
41
42 add_filter( SRFM_SLUG . '_admin_filter', [ $this, 'localize_script_integration' ] );
43 }
44
45 /**
46 * Required Plugin Activate
47 *
48 * @return void
49 * @since 0.0.1
50 */
51 public function required_plugin_activate() {
52
53 $response_data = [ 'message' => $this->get_error_msg( 'permission' ) ];
54
55 if ( ! Helper::current_user_can() ) {
56 wp_send_json_error( $response_data );
57 }
58
59 if ( empty( $_POST ) ) {
60 $response_data = [ 'message' => $this->get_error_msg( 'invalid' ) ];
61 wp_send_json_error( $response_data );
62 }
63
64 /**
65 * Nonce verification.
66 */
67 if ( ! check_ajax_referer( 'sf_plugin_manager_nonce', 'security', false ) ) {
68 $response_data = [ 'message' => $this->get_error_msg( 'nonce' ) ];
69 wp_send_json_error( $response_data );
70 }
71
72 if ( ! isset( $_POST['init'] ) || ! sanitize_text_field( wp_unslash( $_POST['init'] ) ) ) {
73 wp_send_json_error(
74 [
75 'success' => false,
76 'message' => __( 'No plugin specified', 'sureforms' ),
77 ]
78 );
79 }
80
81 $plugin_init = isset( $_POST['init'] ) ? sanitize_text_field( wp_unslash( $_POST['init'] ) ) : '';
82
83 $plugin_slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : '';
84
85 $activate = activate_plugin( $plugin_init, '', false, true );
86
87 if ( is_wp_error( $activate ) ) {
88 wp_send_json_error(
89 [
90 'success' => false,
91 'message' => $activate->get_error_message(),
92 ]
93 );
94 }
95
96 if ( class_exists( 'BSF_UTM_Analytics' ) && is_callable( 'BSF_UTM_Analytics::update_referer' ) ) {
97 $plugin_slug = pathinfo( $plugin_slug, PATHINFO_FILENAME );
98 BSF_UTM_Analytics::update_referer( 'sureforms', $plugin_slug );
99 }
100
101 wp_send_json_success(
102 [
103 'success' => true,
104 'message' => __( 'Plugin Successfully Activated', 'sureforms' ),
105 ]
106 );
107 }
108
109 /**
110 * Get ajax error message.
111 *
112 * @param string $type Message type.
113 * @return string
114 * @since 0.0.2
115 */
116 public function get_error_msg( $type ) {
117
118 if ( ! isset( $this->errors[ $type ] ) ) {
119 $type = 'default';
120 }
121 if ( ! isset( $this->errors ) ) {
122 return '';
123 }
124 return $this->errors[ $type ];
125 }
126
127 /**
128 * Localize the variables required for integration plugins.
129 *
130 * @param array<mixed> $values localized values.
131 * @return array<mixed>
132 * @since 0.0.1
133 */
134 public function localize_script_integration( $values ) {
135 $is_screen_sureforms_menu = Helper::validate_request_context( 'sureforms_menu', 'page' );
136 return array_merge(
137 $values,
138 [
139 'ajax_url' => admin_url( 'admin-ajax.php' ),
140 'sfPluginManagerNonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
141 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
142 'isRTL' => is_rtl(),
143 'current_screen_id' => $is_screen_sureforms_menu ? 'sureforms_menu' : '',
144 'form_id' => get_post() ? get_post()->ID : '',
145 'suretriggers_nonce' => wp_create_nonce( 'suretriggers_nonce' ),
146 ]
147 );
148 }
149
150 /**
151 * Generates data required for suretriggers integration
152 *
153 * @since 0.0.8
154 * @return void
155 */
156 public function generate_data_for_suretriggers_integration() {
157 if ( ! Helper::current_user_can() ) {
158 wp_send_json_error( [ 'message' => __( 'You do not have permission to access this page.', 'sureforms' ) ] );
159 }
160
161 if ( ! check_ajax_referer( 'suretriggers_nonce', 'security', false ) ) {
162 wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ] );
163 }
164
165 if ( empty( $_POST['formId'] ) ) {
166 wp_send_json_error( [ 'message' => __( 'Form ID is required.', 'sureforms' ) ] );
167 }
168
169 if ( ! Helper::is_suretriggers_ready() ) {
170 wp_send_json_error(
171 [
172 'code' => 'invalid_secret_key',
173 'message' => __( 'OttoKit is not configured properly.', 'sureforms' ),
174 ]
175 );
176 }
177
178 $form_id = Helper::get_integer_value( sanitize_text_field( wp_unslash( $_POST['formId'] ) ) );
179 $form = get_post( $form_id );
180
181 if ( is_null( $form ) || SRFM_FORMS_POST_TYPE !== $form->post_type ) {
182 wp_send_json_error( [ 'message' => __( 'Invalid form ID.', 'sureforms' ) ] );
183 }
184
185 // Translators: %s: Form ID.
186 $form_name = ! empty( $form->post_title ) ? $form->post_title : sprintf( __( 'SureForms id: %s', 'sureforms' ), $form_id );
187 $api_url = apply_filters( 'suretriggers_get_iframe_url', SRFM_SURETRIGGERS_INTEGRATION_BASE_URL );
188
189 // This is the format of data required by SureTriggers for adding iframe in target id.
190 $body = [
191 'client_id' => 'SureForms',
192 'st_embed_url' => $api_url,
193 'embedded_identifier' => $form_id,
194 'target' => 'suretriggers-iframe-wrapper', // div where we want SureTriggers to add iframe should have this target id.
195 'event' => [
196 'label' => __( 'Form Submitted', 'sureforms' ),
197 'value' => 'sureforms_form_submitted',
198 'description' => __( 'Runs when a form is submitted', 'sureforms' ),
199 ],
200 'summary' => $form_name,
201 'selected_options' => [
202 'form_id' => [
203 'value' => $form_id,
204 'label' => $form_name,
205 ],
206 ],
207 'integration' => 'SureForms',
208 'sample_response' => [
209 'form_id' => $form_id,
210 'to_emails' => [
211 'dev-email@wpengine.local',
212 ],
213 'form_name' => $form_name,
214 'data' => $this->get_form_fields( $form_id ),
215 ],
216 ];
217
218 // Adding entry_id in body sample response if do_not_store_entries is not enabled.
219 $compliance = get_post_meta( $form_id, '_srfm_compliance', true );
220 $do_not_store_entries = is_array( $compliance ) && isset( $compliance[0]['do_not_store_entries'] )
221 ? $compliance[0]['do_not_store_entries']
222 : null;
223
224 if ( ! $do_not_store_entries ) {
225 $body['sample_response']['entry_id'] = 12;
226 }
227
228 wp_send_json_success(
229 [
230 'message' => 'success',
231 'data' => apply_filters( 'srfm_suretriggers_integration_data_filter', $body, $form_id ),
232 ]
233 );
234 }
235
236 /**
237 * This function populates data for particular form.
238 *
239 * @param int $form_id Form ID.
240 * @since 0.0.8
241 * @return array<mixed>
242 */
243 public function get_form_fields( $form_id ) {
244 if ( empty( $form_id ) || ! is_int( $form_id ) ) {
245 return [];
246 }
247
248 if ( SRFM_FORMS_POST_TYPE !== get_post_type( $form_id ) ) {
249 return [];
250 }
251
252 $post = get_post( $form_id );
253
254 if ( is_null( $post ) ) {
255 return [];
256 }
257
258 $blocks = parse_blocks( $post->post_content );
259
260 $blocks = array_filter(
261 $blocks,
262 static function( $block ) {
263 if ( 'srfm/html' === $block['blockName'] ) {
264 return false;
265 }
266 return true;
267 }
268 );
269
270 $blocks = array_values( $blocks );
271
272 if ( empty( $blocks ) ) {
273 return [];
274 }
275
276 $data = [];
277
278 foreach ( $blocks as $block ) {
279 if ( ! empty( $block['blockName'] ) && 0 === strpos( $block['blockName'], 'srfm/' ) ) {
280
281 /**
282 * Determine whether to skip this field from the sample data.
283 *
284 * @param bool $should_skip Default value indicating if field should be skipped.
285 * @param array $block_details Array containing block attributes, including 'block_name'.
286 *
287 * @since 2.0.0
288 *
289 * @hook srfm_should_skip_field_from_sample_data
290 */
291 $should_skip_this_field = apply_filters(
292 'srfm_should_skip_field_from_sample_data',
293 false,
294 [
295 'block_name' => $block['blockName'],
296 ]
297 );
298
299 if ( $should_skip_this_field ) {
300 continue;
301 }
302
303 if ( ! empty( $block['attrs']['slug'] ) ) {
304 $data[ $block['attrs']['slug'] ] = $this->get_sample_data( $block['blockName'] );
305 }
306 }
307 }
308
309 if ( empty( $data ) ) {
310 return [];
311 }
312
313 return $data;
314 }
315
316 /**
317 * Returns sample data for a block.
318 *
319 * @param string $block_name Block name.
320 * @since 0.0.8
321 * @return mixed
322 */
323 public function get_sample_data( $block_name ) {
324 if ( empty( $block_name ) ) {
325 return __( 'Sample data', 'sureforms' );
326 }
327
328 $dummy_data = [
329 'srfm/input' => __( 'Sample input data', 'sureforms' ),
330 'srfm/email' => 'noreply@sureforms.com',
331 'srfm/textarea' => __( 'Sample textarea data', 'sureforms' ),
332 'srfm/number' => 123,
333 'srfm/checkbox' => 'checkbox value',
334 'srfm/gdpr' => 'GDPR value',
335 'srfm/phone' => '1234567890',
336 'srfm/address' => __( 'Address data', 'sureforms' ),
337 'srfm/address-compact' => __( 'Address data', 'sureforms' ),
338 'srfm/dropdown' => __( 'Selected dropdown option', 'sureforms' ),
339 'srfm/multi-choice' => __( 'Selected Multichoice option', 'sureforms' ),
340 'srfm/radio' => __( 'Selected radio option', 'sureforms' ),
341 'srfm/submit' => __( 'Submit', 'sureforms' ),
342 'srfm/url' => 'https://example.com',
343 'srfm/date-time-picker' => '2022-01-01 12:00:00',
344 'srfm/hidden' => __( 'Hidden Value', 'sureforms' ),
345 'srfm/slider' => 50,
346 'srfm/password' => 'DummyPassword123',
347 'srfm/rating' => 4,
348 'srfm/upload' => 'https://example.com/uploads/file.pdf',
349 ];
350
351 /**
352 * Filter the sample data for specific block types.
353 *
354 * Allows plugins and themes to add custom sample data for their block types
355 * or modify existing sample data. This is particularly useful for dynamic
356 * block types that require complex sample data structures.
357 *
358 * @since 0.0.8
359 *
360 * @param array $dummy_data {
361 * Array of sample data keyed by block name.
362 *
363 * @type string|array $block_name Sample data for the block.
364 * }
365 * @param array $filter_args {
366 * Additional filter arguments.
367 *
368 * @type string $block_name The name of the block being processed.
369 * }
370 */
371 $dummy_data = Helper::apply_filters_as_array( 'srfm_sample_data_filter', $dummy_data, [ 'block_name' => $block_name ] );
372
373 if ( ! empty( $dummy_data[ $block_name ] ) ) {
374 return $dummy_data[ $block_name ];
375 }
376 return __( 'Sample data', 'sureforms' );
377 }
378
379 /**
380 * Download exported file.
381 *
382 * @since 2.0.0
383 * @return void
384 */
385 public function download_export_file() {
386 // Check user permissions.
387 if ( ! Helper::current_user_can() ) {
388 wp_die( esc_html__( 'You do not have permission to access this file.', 'sureforms' ) );
389 }
390
391 // Verify nonce for security.
392 if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'srfm_download_export' ) ) {
393 wp_die( esc_html__( 'Security check failed.', 'sureforms' ) );
394 }
395
396 // Get and sanitize the file parameter.
397 $file = isset( $_GET['file'] ) ? sanitize_file_name( wp_unslash( $_GET['file'] ) ) : '';
398
399 if ( empty( $file ) ) {
400 wp_die( esc_html__( 'Invalid file request.', 'sureforms' ) );
401 }
402
403 // Build the full file path.
404 $temp_dir = wp_normalize_path( trailingslashit( get_temp_dir() ) );
405 $filepath = $temp_dir . $file;
406
407 // Security check: ensure the file is in the temp directory.
408 if ( strpos( wp_normalize_path( $filepath ), $temp_dir ) !== 0 ) {
409 wp_die( esc_html__( 'Invalid file path.', 'sureforms' ) );
410 }
411
412 // Check if file exists.
413 if ( ! file_exists( $filepath ) ) {
414 wp_die( esc_html__( 'File not found.', 'sureforms' ) );
415 }
416
417 // Get file info.
418 $file_size = filesize( $filepath );
419 $file_info = pathinfo( $filepath );
420
421 // Determine content type and filename based on file extension.
422 $content_type = 'application/octet-stream';
423 $filename = $file_info['basename'];
424 if ( isset( $file_info['extension'] ) ) {
425 if ( 'csv' === $file_info['extension'] ) {
426 $content_type = 'text/csv';
427 } elseif ( 'zip' === $file_info['extension'] ) {
428 $content_type = 'application/zip';
429 $filename = 'SureForms Entries.zip';
430 }
431 }
432
433 // Set headers for download.
434 header( 'Content-Type: ' . $content_type );
435 header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
436 header( 'Content-Length: ' . $file_size );
437 header( 'Cache-Control: private, max-age=0, must-revalidate' );
438 header( 'Pragma: public' );
439
440 // Clear output buffers.
441 if ( ob_get_level() ) {
442 ob_end_clean();
443 }
444
445 // Output the file.
446 readfile( $filepath ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_readfile -- Need direct file output for download.
447
448 // Clean up the temporary file.
449 unlink( $filepath );
450
451 exit;
452 }
453 }
454