PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.12
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.12
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / FrmEntryMeta.php

FrmEntryMeta.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.12, at classes/models/FrmEntryMeta.php

517 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmEntryMeta {
7
8 /**
9 * @param int $entry_id
10 * @param int $field_id
11 * @param string $meta_key usually set to '' as this parameter is no longer used.
12 * @param mixed $meta_value
13 * @return int
14 */
15 public static function add_entry_meta( $entry_id, $field_id, $meta_key, $meta_value ) {
16 global $wpdb;
17
18 if ( FrmAppHelper::is_empty_value( $meta_value ) ) {
19 // don't save blank fields
20 return 0;
21 }
22
23 $new_values = array(
24 'meta_value' => is_array( $meta_value ) ? serialize( array_filter( $meta_value, 'FrmAppHelper::is_not_empty_value' ) ) : trim( $meta_value ),
25 'item_id' => $entry_id,
26 'field_id' => $field_id,
27 'created_at' => current_time( 'mysql', 1 ),
28 );
29
30 self::set_value_before_save( $new_values );
31 $new_values = apply_filters( 'frm_add_entry_meta', $new_values );
32
33 $query_results = $wpdb->insert( $wpdb->prefix . 'frm_item_metas', $new_values );
34
35 if ( $query_results ) {
36 self::clear_cache();
37 wp_cache_delete( $entry_id, 'frm_entry' );
38 $id = $wpdb->insert_id;
39 } else {
40 $id = 0;
41 }
42
43 return $id;
44 }
45
46 /**
47 * @param int $entry_id
48 * @param int $field_id
49 * @param string $meta_key Deprecated.
50 * @param array|string $meta_value
51 *
52 * @return bool|false|int
53 */
54 public static function update_entry_meta( $entry_id, $field_id, $meta_key, $meta_value ) {
55 if ( ! $field_id ) {
56 return false;
57 }
58
59 global $wpdb;
60
61 $values = array(
62 'item_id' => $entry_id,
63 'field_id' => $field_id,
64 );
65 $where_values = $values;
66 $values['meta_value'] = $meta_value;
67 self::set_value_before_save( $values );
68 $values = apply_filters( 'frm_update_entry_meta', $values );
69
70 if ( is_array( $values['meta_value'] ) ) {
71 $values['meta_value'] = array_filter( $values['meta_value'], 'FrmAppHelper::is_not_empty_value' );
72 }
73 $meta_value = maybe_serialize( $values['meta_value'] );
74
75 wp_cache_delete( $entry_id, 'frm_entry' );
76 self::clear_cache();
77
78 return $wpdb->update( $wpdb->prefix . 'frm_item_metas', array( 'meta_value' => $meta_value ), $where_values );
79 }
80
81 /**
82 * @since 3.0
83 */
84 private static function set_value_before_save( &$values ) {
85 $field = FrmField::getOne( $values['field_id'] );
86 if ( $field ) {
87 $field_obj = FrmFieldFactory::get_field_object( $field );
88
89 $values['meta_value'] = $field_obj->set_value_before_save( $values['meta_value'] );
90 }
91 }
92
93 /**
94 * @since 3.0
95 */
96 private static function get_value_to_save( $atts, &$value ) {
97 if ( is_object( $atts['field'] ) ) {
98 $field_obj = FrmFieldFactory::get_field_object( $atts['field'] );
99 $value = $field_obj->get_value_to_save(
100 $value,
101 array(
102 'entry_id' => $atts['entry_id'],
103 'field_id' => $atts['field_id'],
104 )
105 );
106 }
107
108 $value = apply_filters( 'frm_prepare_data_before_db', $value, $atts['field_id'], $atts['entry_id'], array( 'field' => $atts['field'] ) );
109 }
110
111 public static function update_entry_metas( $entry_id, $values ) {
112 global $wpdb;
113
114 $prev_values = FrmDb::get_col(
115 $wpdb->prefix . 'frm_item_metas',
116 array(
117 'item_id' => $entry_id,
118 'field_id !' => 0,
119 ),
120 'field_id'
121 );
122
123 foreach ( $values as $field_id => $meta_value ) {
124 $field = false;
125 if ( ! empty( $field_id ) ) {
126 $field = FrmField::getOne( $field_id );
127 }
128
129 self::get_value_to_save( compact( 'field', 'field_id', 'entry_id' ), $meta_value );
130
131 if ( $prev_values && in_array( $field_id, $prev_values ) ) {
132
133 if ( ( is_array( $meta_value ) && empty( $meta_value ) ) || ( ! is_array( $meta_value ) && trim( $meta_value ) == '' ) ) {
134 // remove blank fields
135 unset( $values[ $field_id ] );
136 } else {
137 // if value exists, then update it
138 self::update_entry_meta( $entry_id, $field_id, '', $meta_value );
139 }
140 } else {
141 // if value does not exist, then create it
142 self::add_entry_meta( $entry_id, $field_id, '', $meta_value );
143 }
144 }//end foreach
145
146 if ( empty( $prev_values ) ) {
147 return;
148 }
149
150 $prev_values = array_diff( $prev_values, array_keys( $values ) );
151
152 if ( empty( $prev_values ) ) {
153 return;
154 }
155
156 // prepare the query
157 $where = array(
158 'item_id' => $entry_id,
159 'field_id' => $prev_values,
160 );
161 FrmDb::get_where_clause_and_values( $where );
162
163 // Delete any leftovers
164 $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
165 self::clear_cache();
166 }
167
168 public static function duplicate_entry_metas( $old_id, $new_id ) {
169 $metas = self::get_entry_meta_info( $old_id );
170
171 /**
172 * Allows changing entry duplicate values before save.
173 *
174 * @since 5.4.4
175 *
176 * @param array $metas The list of entry meta values.
177 */
178 $metas = apply_filters( 'frm_before_duplicate_entry_values', $metas );
179 foreach ( $metas as $meta ) {
180 self::add_entry_meta( $new_id, $meta->field_id, '', $meta->meta_value );
181 unset( $meta );
182 }
183 self::clear_cache();
184 }
185
186 public static function delete_entry_meta( $entry_id, $field_id ) {
187 global $wpdb;
188 self::clear_cache();
189
190 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}frm_item_metas WHERE field_id=%d AND item_id=%d", $field_id, $entry_id ) );
191 }
192
193 /**
194 * Clear entry meta caching
195 * Called when a meta is added or changed
196 *
197 * @since 2.0.5
198 */
199 public static function clear_cache() {
200 FrmDb::cache_delete_group( 'frm_entry_meta' );
201 FrmDb::cache_delete_group( 'frm_item_meta' );
202 }
203
204 /**
205 * @since 2.0.9
206 *
207 * @param stdClass $entry
208 * @param int|string $field_id
209 * @return mixed
210 */
211 public static function get_meta_value( $entry, $field_id ) {
212 if ( isset( $entry->metas ) ) {
213 return isset( $entry->metas[ $field_id ] ) ? $entry->metas[ $field_id ] : false;
214 }
215 return self::get_entry_meta_by_field( $entry->id, $field_id );
216 }
217
218 public static function get_entry_meta_by_field( $entry_id, $field_id ) {
219 global $wpdb;
220
221 if ( is_object( $entry_id ) ) {
222 $entry = $entry_id;
223 $entry_id = $entry->id;
224 $cached = $entry;
225 } else {
226 $entry_id = (int) $entry_id;
227 $cached = FrmDb::check_cache( $entry_id, 'frm_entry' );
228 }
229
230 if ( $cached && isset( $cached->metas ) && isset( $cached->metas[ $field_id ] ) ) {
231 $result = $cached->metas[ $field_id ];
232
233 return wp_unslash( $result );
234 }
235
236 $get_table = $wpdb->prefix . 'frm_item_metas';
237 $query = array( 'item_id' => $entry_id );
238 if ( is_numeric( $field_id ) ) {
239 $query['field_id'] = $field_id;
240 } else {
241 $get_table .= ' it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id';
242 $query['fi.field_key'] = $field_id;
243 }
244
245 $result = FrmDb::get_var( $get_table, $query, 'meta_value' );
246
247 $field_type = FrmField::get_type( $field_id );
248 FrmFieldsHelper::prepare_field_value( $result, $field_type );
249
250 $result = wp_unslash( $result );
251
252 return $result;
253 }
254
255 public static function get_entry_metas_for_field( $field_id, $order = '', $limit = '', $args = array() ) {
256 $defaults = array(
257 'value' => false,
258 'unique' => false,
259 'stripslashes' => true,
260 'is_draft' => false,
261 );
262 $args = wp_parse_args( $args, $defaults );
263
264 $query = array();
265 self::meta_field_query( $field_id, $order, $limit, $args, $query );
266 $query = implode( ' ', $query );
267
268 $cache_key = 'entry_metas_for_field_' . $field_id . $order . $limit . FrmAppHelper::maybe_json_encode( $args );
269 $values = FrmDb::check_cache( $cache_key, 'frm_entry', $query, 'get_col' );
270
271 if ( ! $args['stripslashes'] ) {
272 return $values;
273 }
274
275 foreach ( $values as $k => $v ) {
276 FrmAppHelper::unserialize_or_decode( $v );
277 $values[ $k ] = $v;
278 unset( $k, $v );
279 }
280
281 return wp_unslash( $values );
282 }
283
284 /**
285 * @param int|string $field_id
286 * @param string $order
287 * @param string $limit
288 * @param array $args
289 * @param array $query
290 */
291 private static function meta_field_query( $field_id, $order, $limit, $args, array &$query ) {
292 global $wpdb;
293 $query[] = 'SELECT';
294 $query[] = $args['unique'] ? 'DISTINCT(em.meta_value)' : 'em.meta_value';
295 $query[] = 'FROM ' . $wpdb->prefix . 'frm_item_metas em ';
296
297 if ( ! $args['is_draft'] ) {
298 $query[] = 'INNER JOIN ' . $wpdb->prefix . 'frm_items e ON (e.id=em.item_id)';
299 }
300
301 if ( is_numeric( $field_id ) ) {
302 $query[] = $wpdb->prepare( 'WHERE em.field_id=%d', $field_id );
303 } else {
304 $query[] = $wpdb->prepare( 'LEFT JOIN ' . $wpdb->prefix . 'frm_fields fi ON (em.field_id = fi.id) WHERE fi.field_key=%s', $field_id );
305 }
306
307 if ( ! $args['is_draft'] ) {
308 $query[] = 'AND e.is_draft=0';
309 }
310
311 if ( $args['value'] ) {
312 $query[] = $wpdb->prepare( ' AND meta_value=%s', $args['value'] );
313 }
314 $query[] = $order . $limit;
315 }
316
317 public static function get_entry_meta_info( $entry_id ) {
318 return FrmDb::get_results( 'frm_item_metas', array( 'item_id' => $entry_id ) );
319 }
320
321 /**
322 * @param array $where
323 * @param string $order_by
324 * @param string $limit
325 * @param bool $stripslashes
326 * @return array
327 */
328 public static function getAll( $where = array(), $order_by = '', $limit = '', $stripslashes = false ) {
329 global $wpdb;
330 $query = 'SELECT it.*, fi.type as field_type, fi.field_key as field_key,
331 fi.required as required, fi.form_id as field_form_id, fi.name as field_name, fi.options as fi_options
332 FROM ' . $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id' .
333 FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
334
335 $cache_key = 'all_' . FrmAppHelper::maybe_json_encode( $where ) . $order_by . $limit;
336 $results = FrmDb::check_cache( $cache_key, 'frm_entry', $query, ( $limit == ' LIMIT 1' ? 'get_row' : 'get_results' ) );
337
338 if ( ! $results || ! $stripslashes ) {
339 return $results;
340 }
341
342 foreach ( $results as $k => $result ) {
343 FrmAppHelper::unserialize_or_decode( $result->meta_value );
344 $results[ $k ]->meta_value = wp_unslash( $result->meta_value );
345 unset( $k, $result );
346 }
347
348 return $results;
349 }
350
351 public static function getEntryIds( $where = array(), $order_by = '', $limit = '', $unique = true, $args = array() ) {
352 $defaults = array(
353 'is_draft' => false,
354 'user_id' => '',
355 'group_by' => '',
356 );
357 $args = wp_parse_args( $args, $defaults );
358
359 $query = array();
360 self::get_ids_query( $where, $order_by, $limit, $unique, $args, $query );
361 $query = implode( ' ', $query );
362
363 $cache_key = 'ids_' . FrmAppHelper::maybe_json_encode( $where ) . $order_by . 'l' . $limit . 'u' . $unique . FrmAppHelper::maybe_json_encode( $args );
364 $type = 'get_' . ( ' LIMIT 1' === $limit ? 'var' : 'col' );
365 return FrmDb::check_cache( $cache_key, 'frm_entry', $query, $type );
366 }
367
368 /**
369 * Given a query including a form id and its child form ids, output an array of matching entry ids
370 * If a child entry id is matched, its parent will be returned in its place
371 *
372 * @param array $query
373 * @param array $args
374 * @return array
375 */
376 public static function get_top_level_entry_ids( $query, $args ) {
377 $args['return_parent_id_if_0_return_id'] = true;
378 return self::getEntryIds( $query, '', '', true, $args );
379 }
380
381 /**
382 * @param array|string $where
383 * @param string $order_by
384 * @param string $limit
385 */
386 private static function get_ids_query( $where, $order_by, $limit, $unique, $args, array &$query ) {
387 global $wpdb;
388 $query[] = 'SELECT';
389 $defaults = array(
390 'return_parent_id' => false,
391 'return_parent_id_if_0_return_id' => false,
392 );
393 $args = array_merge( $defaults, $args );
394
395 if ( $unique ) {
396 $query[] = 'DISTINCT';
397 }
398
399 if ( $args['return_parent_id_if_0_return_id'] ) {
400 $query[] = 'IF ( e.parent_item_id = 0, it.item_id, e.parent_item_id )';
401 } elseif ( $args['return_parent_id'] ) {
402 $query[] = 'e.parent_item_id';
403 } else {
404 $query[] = 'it.item_id';
405 }
406
407 $query[] = 'FROM ' . $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id';
408
409 $query[] = 'INNER JOIN ' . $wpdb->prefix . 'frm_items e ON (e.id=it.item_id)';
410 if ( is_array( $where ) ) {
411 if ( ! $args['is_draft'] ) {
412 $where['e.is_draft'] = 0;
413 } elseif ( is_numeric( $args['is_draft'] ) ) {
414 if ( class_exists( 'FrmAbandonmentHooksController', false ) ) {
415 $where['e.is_draft'] = absint( $args['is_draft'] );
416 } else {
417 $where['e.is_draft'] = 1;
418 }
419 } elseif ( 'both' === $args['is_draft'] && class_exists( 'FrmAbandonmentHooksController', false ) ) {
420 $where['e.is_draft'] = array( 0, 1 );
421 } elseif ( false !== strpos( $args['is_draft'], ',' ) ) {
422 $is_draft = array_reduce(
423 explode( ',', $args['is_draft'] ),
424 function ( $total, $current ) {
425 if ( is_numeric( $current ) ) {
426 $total[] = absint( $current );
427 }
428 return $total;
429 },
430 array()
431 );
432 if ( $is_draft ) {
433 $where['e.is_draft'] = $is_draft;
434 }
435 }//end if
436
437 if ( ! empty( $args['user_id'] ) ) {
438 $where['e.user_id'] = $args['user_id'];
439 }
440 $query[] = FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
441
442 if ( $args['group_by'] ) {
443 $query[] = ' GROUP BY ' . sanitize_text_field( $args['group_by'] );
444 }
445
446 return;
447 }//end if
448
449 $draft_where = '';
450 $user_where = '';
451 if ( ! $args['is_draft'] ) {
452 $draft_where = $wpdb->prepare( ' AND e.is_draft=%d', 0 );
453 } elseif ( $args['is_draft'] == 1 ) {
454 $draft_where = $wpdb->prepare( ' AND e.is_draft=%d', 1 );
455 }
456
457 if ( ! empty( $args['user_id'] ) ) {
458 $user_where = $wpdb->prepare( ' AND e.user_id=%d', $args['user_id'] );
459 }
460
461 if ( strpos( $where, ' GROUP BY ' ) ) {
462 // don't inject WHERE filtering after GROUP BY
463 $parts = explode( ' GROUP BY ', $where );
464 $where = $parts[0];
465 $where .= $draft_where . $user_where;
466 $where .= ' GROUP BY ' . $parts[1];
467 } else {
468 $where .= $draft_where . $user_where;
469 }
470
471 // The query has already been prepared
472 $query[] = FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
473 }
474
475 public static function search_entry_metas( $search, $field_id, $operator ) {
476 $cache_key = 'search_' . FrmAppHelper::maybe_json_encode( $search ) . $field_id . $operator;
477 $results = wp_cache_get( $cache_key, 'frm_entry' );
478 if ( false !== $results ) {
479 return $results;
480 }
481
482 global $wpdb;
483 if ( is_array( $search ) ) {
484 $where = '';
485 foreach ( $search as $field => $value ) {
486 if ( $value <= 0 || ! in_array( $field, array( 'year', 'month', 'day' ) ) ) {
487 continue;
488 }
489
490 switch ( $field ) {
491 case 'year':
492 $value = '%' . $value;
493 break;
494 case 'month':
495 $value .= '%';
496 break;
497 case 'day':
498 $value = '%' . $value . '%';
499 }
500 $where .= $wpdb->prepare( ' meta_value ' . $operator . ' %s and', $value ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
501 }
502 $where .= $wpdb->prepare( ' field_id=%d', $field_id );
503 $query = 'SELECT DISTINCT item_id FROM ' . $wpdb->prefix . 'frm_item_metas' . FrmDb::prepend_and_or_where( ' WHERE ', $where );
504 } else {
505 if ( $operator === 'LIKE' ) {
506 $search = '%' . $search . '%';
507 }
508 $query = $wpdb->prepare( "SELECT DISTINCT item_id FROM {$wpdb->prefix}frm_item_metas WHERE meta_value {$operator} %s and field_id = %d", $search, $field_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
509 }//end if
510
511 $results = $wpdb->get_col( $query, 0 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
512 FrmDb::set_cache( $cache_key, $results, 'frm_entry' );
513
514 return $results;
515 }
516 }
517