PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.9.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.9.1
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
ablocks / includes / blocks / form-builder / query.php

query.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.9.1, at includes/blocks/form-builder/query.php

553 lines 15.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace ABlocks\Blocks\FormBuilder;
3
4 use ABlocks\Blocks\FormBuilder\EmailVerification;
5 use SplTempFileObject;
6 /**
7 * @class Query
8 */
9 class Query {
10 public static function get_entries(
11 $is_in_trash = 'no', // yes | no
12 $search_by_email = null, // search entries by email
13 $form_type = null, // form type, eg: contact
14 $date = null, // all entries of a month, eg: 2024-12 # dec, 2024
15 $from_date = null,
16 $to_date = null,
17 $order_by = 'created_at',
18 $order = 'desc',
19 $status = 'all', // all | read | unread
20 $entry_per_page = 15,
21 $current_page = 1,
22 $do_export_csv = false
23 ) {
24 global $wpdb;
25 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
26
27 $conditions = [];
28 $args = [];
29
30 $conditions[] = 'is_email_verified != %s';
31 $args[] = 'no';
32
33 $conditions[] = 'is_in_trash = %s';
34 $args[] = in_array( $is_in_trash, [ 'yes', 'no' ], true ) ? $is_in_trash : 'no';
35
36 if ( $form_type ) {
37 $conditions[] = 'form_type = %s';
38 $args[] = $form_type;
39 }
40 if ( $search_by_email ) {
41 $conditions[] = 'user_email like %s';
42 $args[] = '%' . $wpdb->esc_like( $search_by_email ) . '%';
43 }
44
45 // format: year-month : 2024-12
46 if ( $date ) {
47 $date = explode( '-', $date );
48 $year = intval( $date[0] );
49 $month = intval( $date[1] );
50 if (
51 count( $date ) === 2 &&
52 $year &&
53 $month
54 ) {
55 $conditions[] = 'YEAR(created_at) = %s';
56 $args[] = $year;
57 $conditions[] = 'MONTH(created_at) = %s';
58 $args[] = $month;
59 }
60 }
61 if ( ! isset( $year ) && $from_date ) {
62 $from_date = gmdate( 'y-m-d h:i:s', strtotime( $from_date ) );
63 $conditions[] = 'created_at >= %s';
64 $args[] = $from_date;
65 }
66 if ( ! isset( $year ) && $to_date ) {
67 $to_date = gmdate( 'y-m-d h:i:s', strtotime( $to_date ) );
68 $conditions[] = 'created_at <= %s';
69 $args[] = $to_date;
70 }
71 if ( in_array( strtolower( $status ), [ 'read', 'unread' ], true ) ) {
72 $conditions[] = 'status = %s';
73 $args[] = $status;
74 }
75
76 $query = "SELECT * FROM {$table_entries} ";
77 $count_query = "select count(*) from {$table_entries} ";
78
79 if ( ! empty( $conditions ) ) {
80 $query .= ' where ' . implode( ' and ', $conditions );
81 $count_query .= ' where ' . implode( ' and ', $conditions );
82 }
83
84 if ( empty( $args ) && empty( $conditions ) ) {
85 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
86 $num_of_entries = $wpdb->get_var( $count_query );
87 } else {
88 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
89 $num_of_entries = $wpdb->get_var( $wpdb->prepare( $count_query, ...$args ) );
90 }
91
92 // order by
93 if ( ! in_array( $order_by, [ 'id', 'user_email', 'created_at' ], true ) ) {
94 $order_by = 'created_at';
95 }
96 // order
97 if (
98 ! in_array( strtoupper( $order ), [ 'ASC', 'DESC' ], true )
99 ) {
100 $order = 'ASC';
101 }
102 $query .= " order by {$order_by} {$order}";
103
104 // export entries in csv format
105 if ( $do_export_csv ) {
106 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
107 $entries_to_export = $wpdb->get_results( $wpdb->prepare( $query, ...$args ), ARRAY_A ) ?? [];
108
109 // make a temporary file object
110 $save_entries_as_csv = new SplTempFileObject();
111
112 // rewind pointer at first line
113 $save_entries_as_csv->rewind();
114
115 // add header to csv
116 $save_entries_as_csv->fputcsv([
117 'email',
118 'form',
119 'page id',
120 'submission date',
121 'ip',
122 'user agent'
123 ]);
124
125 // add row to csv
126 foreach ( $entries_to_export as $entry ) {
127 $save_entries_as_csv->fputcsv([
128 sanitize_text_field( $entry['user_email'] ),
129 sanitize_text_field( strtoupper( $entry['form_type'] ) ),
130 sanitize_text_field( '#' . $entry['post_id'] ),
131 sanitize_text_field( gmdate( 'd m, y h:i:s', strtotime( $entry['created_at'] ) ) ),
132 sanitize_text_field( $entry['ip'] ),
133 sanitize_text_field( $entry['user_agent'] ),
134 ]);
135 }
136 // rewind pointer at top
137 $save_entries_as_csv->rewind();
138
139 // get csv data as string
140 $csv_data = '';
141 foreach ( $save_entries_as_csv as $line ) {
142 $csv_data .= $line;
143 }
144 return [ 'csv_data' => $csv_data ];
145 }//end if
146 // END
147
148 // pagination
149 $current_page = absint( $current_page );
150 $entry_per_page = absint( $entry_per_page );
151 if ( $current_page < 1 || $current_page > $num_of_entries ) {
152 $current_page = 1;
153 }
154 if ( $entry_per_page < 1 ) {
155 $entry_per_page = 15;
156 }
157 $offset = ( $current_page - 1 ) * $entry_per_page;
158
159 $query .= ' limit %d offset %d';
160 $args[] = $entry_per_page;
161 $args[] = $offset;
162
163 $get_available_date_query = "select
164 count(created_at) as total_entries,
165 year(created_at) as year,
166 month(created_at) as month
167 from {$table_entries}
168 group by year, month
169 order by year, month
170 ";
171 $get_available_forms_query = "select
172 form_type
173 from {$table_entries}
174 group by form_type
175 order by form_type asc
176 ";
177 $data = [];
178 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
179 foreach ( $wpdb->get_results( $wpdb->prepare( $query, ...$args ), ARRAY_A ) ?? [] as $item ) {
180 if ( $item['is_in_trash'] === 'yes' ) {
181 $item['status'] = 'trash';
182 }
183 $data[] = $item;
184 }
185
186 return [
187 'total_entries' => $num_of_entries,
188 'current_page' => $current_page,
189 'per_page' => $entry_per_page,
190 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
191 'available_dates' => $wpdb->get_results( $get_available_date_query, ARRAY_A ) ?? [],
192 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
193 'available_forms' => $wpdb->get_results( $get_available_forms_query, ARRAY_A ) ?? [],
194 'data' => $data,
195 ];
196 }
197
198 public static function get_block_attributes( $post_id, $block_id ) {
199 $post_content = get_post_field( 'post_content', $post_id );
200 $blocks = parse_blocks( $post_content );
201 $block_data = self::get_block_attributes_recursive( $block_id, $blocks );
202
203 $fields = [];
204 if ( ( $block_data['innerBlocks'][0]['blockName'] ?? '' ) === 'ablocks/form-multi-step' ) {
205
206 foreach ( $block_data['innerBlocks'][0]['innerBlocks'] ?? [] as $block ) {
207 foreach ( $block['innerBlocks'] as ['attributes' => $attr] ) {
208 $name = $attr['name'] ?? false;
209 $input_type = $attr['inputType'] ?? false;
210 $label = $attr['label'] ?? $attr['placeholder'] ?? false;
211 $radio_arr = $attr['radioArr'] ?? false;
212 // check current input name exists in $all_fields
213 if ( $name ) {
214
215 $fields[ $name ] = [
216 'inputType' => sanitize_text_field( $input_type ), // sanitize value
217 'label' => strtolower( sanitize_text_field( $label ) ), // sanitize value
218 ];
219
220 if ( is_array( $radio_arr ) ) {
221 $fields[ $name ]['radioArr'] = $radio_arr;
222 }
223 }
224 }
225 }
226 } elseif (
227 isset( $block_data['innerBlocks'] )
228 ) {
229 $fields = [];
230 foreach ( $block_data['innerBlocks'] as $input_element_data ) {
231 $name = $input_element_data['attributes']['name'] ?? false;
232 $input_type = $input_element_data['attributes']['inputType'] ?? false;
233 $label = $input_element_data['attributes']['label'] ?? $input_element_data['attributes']['placeholder'] ?? false;
234 $radio_arr = $input_element_data['attributes']['radioArr'] ?? false;
235 // check current input name exists in $all_fields
236 if ( $name ) {
237
238 $fields[ $name ] = [
239 'inputType' => strtolower( sanitize_text_field( $input_type ) ), // sanitize value
240 'label' => sanitize_text_field( $label ), // sanitize value
241 ];
242
243 if ( is_array( $radio_arr ) ) {
244 $fields[ $name ]['radioArr'] = $radio_arr;
245 }
246 }
247 }
248 }//end if
249 return $fields;
250 }
251
252 public static function get_block_attributes_recursive( $block_id, $blocks ) {
253
254 foreach ( $blocks as $block ) {
255
256 if (
257 ( $block['attrs']['block_id'] ?? '' ) === $block_id
258 ) {
259 return [
260 'parentAttributes' => $block['attrs'] ?? [],
261 'innerBlocks' => \ABlocks\Helper::extract_inner_blocks( $block['innerBlocks'] ?? [] ),
262 ];
263 }
264
265 if (
266 array_key_exists( 'innerBlocks', $block ) &&
267 is_array( $block['innerBlocks'] ) &&
268 count( $block['innerBlocks'] ) > 0
269 ) {
270 $data = self::get_block_attributes_recursive(
271 $block_id,
272 $block['innerBlocks']
273 );
274 if (
275 $data
276 ) {
277 return $data;
278 }
279 }
280 }//end foreach
281 return [];
282 }
283
284 public static function get_entry( int $id ) {
285 global $wpdb;
286 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
287 $table_meta = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_meta';
288
289 $query = "SELECT * FROM {$table_entries} WHERE id = %d";
290 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
291 $entry = $wpdb->get_row( $wpdb->prepare( $query, $id ), ARRAY_A );
292 if ( $entry ) {
293 // mark this entry as reas
294 if ( count( self::update_status_of_entries( [ $id ] ) ) > 0 ) {
295 $entry['status'] = 'read';
296 }
297 $meta = $wpdb->get_results(
298 $wpdb->prepare(
299 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
300 "SELECT meta_key, meta_value FROM $table_meta WHERE entry_id = %d ",
301 $id
302 ),
303 ARRAY_A
304 );
305
306 $fields = self::get_block_attributes( $entry['post_id'], $entry['block_id'] );
307 $found = [];
308 foreach ( $meta as $field ) {
309 if ( array_key_exists( $field['meta_key'], $fields ) ) {
310 $found[] = $field['meta_key'];
311
312 if (
313 isset( $fields[ $field['meta_key'] ]['radioArr'] )
314 ) {
315 $field['meta_value'] = explode( ',', $field['meta_value'] );
316 } elseif (
317 ! isset( $fields[ $field['meta_key'] ]['radioArr'] ) &&
318 ( $fields[ $field['meta_key'] ]['inputType'] ?? '' ) === 'checkbox'
319 ) {
320 $field['meta_value'] = strtolower( $field['meta_value'] ) === 'on' ? true : false;
321 }
322
323 $entry['meta'][] = array_merge(
324 $fields[ $field['meta_key'] ],
325 $field
326 );
327
328 } else {
329 $entry['meta'][] = array_merge(
330 $field,
331 [
332 'inputType' => 'text',
333 'label' => ucfirst( preg_replace( '/[_-]/m', ' ', $field['meta_key'] ) ),
334 ]
335 );
336 }//end if
337 }//end foreach
338
339 foreach ( array_diff( array_keys( $fields ), $found ) as $key ) {
340
341 $fields[ $key ]['meta_key'] = $key;
342
343 if (
344 isset( $fields[ $key ]['radioArr'] )
345 ) {
346 $fields[ $key ]['meta_value'] = [];
347 } elseif (
348 ! isset( $fields[ $key ]['radioArr'] ) &&
349 ( $fields[ $key ]['inputType'] ?? '' ) === 'checkbox'
350 ) {
351 $fields[ $key ]['meta_value'] = false;
352 } else {
353 $fields[ $key ]['meta_value'] = null;
354 }
355
356 $entry['meta'][] = $fields[ $key ];
357 }//end foreach
358
359 return $entry;
360 }//end if
361 return [];
362 }
363
364 public static function edit_entry( int $id, array $data ) {
365 global $wpdb;
366 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
367 $table_meta = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_meta';
368
369 // Check if the entry exists
370 $is_entry_exists = (int) $wpdb->get_var(
371 $wpdb->prepare( "SELECT COUNT(*) FROM {$table_entries} WHERE id = %d", $id )// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
372 ) > 0;
373
374 if ( ! $is_entry_exists ) {
375 return false;
376 }
377
378 // Get all meta keys for this entry
379 $get_meta_keys = $wpdb->get_results(
380 $wpdb->prepare(
381 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
382 "SELECT meta_key FROM {$table_meta} WHERE entry_id = %d ",
383 $id
384 ),
385 ARRAY_A
386 );
387
388 if ( empty( $get_meta_keys ) ) {
389 return false;
390 }
391
392 $total_updated = 0;
393
394 foreach ( $get_meta_keys as $key ) {
395 $meta_key = $key['meta_key'];
396
397 // Check if the input data has this meta key
398 if ( array_key_exists( $meta_key, $data ) ) {
399 $is_updated = $wpdb->update(
400 $table_meta,
401 [ 'meta_value' => sanitize_text_field( $data[ $meta_key ] ) ],
402 [
403 'entry_id' => $id,
404 'meta_key' => $meta_key,
405 ],
406 [ '%s' ], // Data format
407 [ '%d', '%s' ] // Where format
408 );
409
410 if ( false !== $is_updated && $is_updated > 0 ) {
411 $total_updated++;
412 }
413 }
414 }//end foreach
415
416 return $total_updated > 0;
417 }
418
419 public static function delete_entries( array $entry_id_array ): array {
420 global $wpdb;
421 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
422 $table_meta = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_meta';
423
424 $total_deleted = [];
425 if ( ! empty( $entry_id_array ) ) {
426 foreach ( $entry_id_array as $entry_id ) {
427
428 if ( $wpdb->delete( $table_entries, [ 'id' => $entry_id ], [ '%d' ] ) ) {
429 $wpdb->delete( $table_meta, [ 'entry_id' => $entry_id ], [ '%d' ] );
430 $total_deleted[] = $entry_id;
431 }
432 }
433 }
434 return $total_deleted;
435 }
436 public static function update_status_of_entries( array $entry_id_array, string $status = 'read' ): array {
437 global $wpdb;
438 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
439
440 $total = [];
441 if ( ! empty( $entry_id_array ) ) {
442 foreach ( $entry_id_array as $entry_id ) {
443
444 if ( $wpdb->update( $table_entries, [ 'status' => $status ], [ 'id' => $entry_id ] ) ) {
445 self::update_trash_status_of_entries( $entry_id, 'no' );
446 $total[] = $entry_id;
447 }
448 }
449 }
450 return $total;
451 }
452
453 public static function update_trash_status_of_entries( int $id, string $send_to_trash = 'yes' ): array {
454 global $wpdb;
455 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
456
457 // Retrieve the current status
458 $status = $wpdb->get_var(
459 $wpdb->prepare( "SELECT status FROM {$table_entries} WHERE id = %d", $id )// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
460 );
461
462 // Initialize response array
463 $total = [];
464
465 if ( $id > 0 ) {
466 // Update the trash status
467 $is_updated = $wpdb->update(
468 $table_entries,
469 [ 'is_in_trash' => sanitize_text_field( $send_to_trash ) ],
470 [ 'id' => $id ],
471 [ '%s' ],
472 [ '%d' ]
473 );
474
475 if ( false !== $is_updated && $is_updated > 0 ) {
476 $total = [
477 'id' => $id,
478 'status' => ( 'yes' === $send_to_trash ) ? 'trash' : $status,
479 ];
480 }
481 }
482
483 return $total;
484 }
485
486 public static function add_new_entry(
487 string $form_type,
488 string $post_id,
489 string $user_email,
490 string $ip,
491 string $user_agent,
492 array $meta_data,
493 string $block_id,
494 bool $is_verification_needed = false
495 ) {
496 global $wpdb;
497 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
498 $table_meta = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_meta';
499 $token = wp_generate_password( 22, false );
500 $wpdb->insert($table_entries,
501 [
502 'form_type' => $form_type,
503 'post_id' => $post_id,
504 'user_email' => $user_email,
505 'ip' => $ip,
506 'user_agent' => $user_agent,
507 'block_id' => $block_id,
508 'email_verification_token' => $token,
509 'expire' => time() + EmailVerification::EXPIRE_IN,
510 'is_email_verified' => $is_verification_needed ? 'no' : '-'
511 ]
512 );
513 $entry_id = $wpdb->insert_id;
514
515 if ( $entry_id ) {
516 foreach ( $meta_data as $input_id => $attr ) {
517 $wpdb->insert($table_meta,
518 [
519 'entry_id' => $entry_id,
520 'meta_key' => $input_id,
521 'meta_value' => $attr['value'],
522 ]
523 );
524 }
525 }
526 return $entry_id;
527 }
528
529 public static function get_token_by_email( string $email ) {
530 global $wpdb;
531 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
532 $entry = $wpdb->get_row(
533 $wpdb->prepare(
534 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
535 "SELECT email_verification_token FROM {$table_entries} WHERE user_email = %s",
536 sanitize_email( $email )
537 ),
538 ARRAY_A
539 );
540
541 return ! empty( $entry['email_verification_token'] ) ? $entry['email_verification_token'] : false;
542 }
543
544 public static function is_email_exists( string $email, string $form_type ) {
545 global $wpdb;
546 $table_entries = $wpdb->prefix . ABLOCKS_PLUGIN_SLUG . '_form_entries';
547
548 $query = "select count(user_email) from {$table_entries} where form_type = %s and user_email = %s";
549 return $wpdb->get_var( $wpdb->prepare( $query, $form_type, $email ) ) > 0;// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
550 }
551
552 }
553