PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.14
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.14
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.14, at classes/models/FrmEntryMeta.php

531 lines 15.7 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 /**
112 * @param int|string $entry_id
113 * @param array $values Either indexed by field ID or field key.
114 * @return void
115 */
116 public static function update_entry_metas( $entry_id, $values ) {
117 global $wpdb;
118
119 $previous_field_ids = FrmDb::get_col(
120 'frm_item_metas',
121 array(
122 'item_id' => $entry_id,
123 'field_id !' => 0,
124 ),
125 'field_id'
126 );
127
128 $values_indexed_by_field_id = array();
129 foreach ( $values as $field_id_or_key => $meta_value ) {
130 $field_id = $field_id_or_key;
131 $field = null;
132
133 if ( $field_id_or_key ) {
134 $field = FrmField::getOne( $field_id_or_key );
135
136 if ( is_object( $field ) ) {
137 $field_id = $field->id;
138 }
139 }
140
141 $values_indexed_by_field_id[ $field_id ] = $meta_value;
142
143 self::get_value_to_save( compact( 'field', 'field_id', 'entry_id' ), $meta_value );
144
145 if ( $previous_field_ids && in_array( $field_id, $previous_field_ids ) ) {
146
147 if ( ( is_array( $meta_value ) && empty( $meta_value ) ) || ( ! is_array( $meta_value ) && trim( $meta_value ) == '' ) ) {
148 // Remove blank fields.
149 unset( $values_indexed_by_field_id[ $field_id ] );
150 } else {
151 // if value exists, then update it
152 self::update_entry_meta( $entry_id, $field_id, '', $meta_value );
153 }
154 } else {
155 // if value does not exist, then create it
156 self::add_entry_meta( $entry_id, $field_id, '', $meta_value );
157 }
158 }//end foreach
159
160 if ( empty( $previous_field_ids ) ) {
161 return;
162 }
163
164 $field_ids_to_remove = array_diff( $previous_field_ids, array_keys( $values_indexed_by_field_id ) );
165
166 if ( ! $field_ids_to_remove ) {
167 return;
168 }
169
170 // prepare the query
171 $where = array(
172 'item_id' => $entry_id,
173 'field_id' => $field_ids_to_remove,
174 );
175 FrmDb::get_where_clause_and_values( $where );
176
177 // Delete any leftovers
178 $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->prefix . 'frm_item_metas ' . $where['where'], $where['values'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
179 self::clear_cache();
180 }
181
182 public static function duplicate_entry_metas( $old_id, $new_id ) {
183 $metas = self::get_entry_meta_info( $old_id );
184
185 /**
186 * Allows changing entry duplicate values before save.
187 *
188 * @since 5.4.4
189 *
190 * @param array $metas The list of entry meta values.
191 */
192 $metas = apply_filters( 'frm_before_duplicate_entry_values', $metas );
193 foreach ( $metas as $meta ) {
194 self::add_entry_meta( $new_id, $meta->field_id, '', $meta->meta_value );
195 unset( $meta );
196 }
197 self::clear_cache();
198 }
199
200 public static function delete_entry_meta( $entry_id, $field_id ) {
201 global $wpdb;
202 self::clear_cache();
203
204 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}frm_item_metas WHERE field_id=%d AND item_id=%d", $field_id, $entry_id ) );
205 }
206
207 /**
208 * Clear entry meta caching
209 * Called when a meta is added or changed
210 *
211 * @since 2.0.5
212 */
213 public static function clear_cache() {
214 FrmDb::cache_delete_group( 'frm_entry_meta' );
215 FrmDb::cache_delete_group( 'frm_item_meta' );
216 }
217
218 /**
219 * @since 2.0.9
220 *
221 * @param stdClass $entry
222 * @param int|string $field_id
223 * @return mixed
224 */
225 public static function get_meta_value( $entry, $field_id ) {
226 if ( isset( $entry->metas ) ) {
227 return isset( $entry->metas[ $field_id ] ) ? $entry->metas[ $field_id ] : false;
228 }
229 return self::get_entry_meta_by_field( $entry->id, $field_id );
230 }
231
232 public static function get_entry_meta_by_field( $entry_id, $field_id ) {
233 global $wpdb;
234
235 if ( is_object( $entry_id ) ) {
236 $entry = $entry_id;
237 $entry_id = $entry->id;
238 $cached = $entry;
239 } else {
240 $entry_id = (int) $entry_id;
241 $cached = FrmDb::check_cache( $entry_id, 'frm_entry' );
242 }
243
244 if ( $cached && isset( $cached->metas ) && isset( $cached->metas[ $field_id ] ) ) {
245 $result = $cached->metas[ $field_id ];
246
247 return wp_unslash( $result );
248 }
249
250 $get_table = $wpdb->prefix . 'frm_item_metas';
251 $query = array( 'item_id' => $entry_id );
252 if ( is_numeric( $field_id ) ) {
253 $query['field_id'] = $field_id;
254 } else {
255 $get_table .= ' it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id';
256 $query['fi.field_key'] = $field_id;
257 }
258
259 $result = FrmDb::get_var( $get_table, $query, 'meta_value' );
260
261 $field_type = FrmField::get_type( $field_id );
262 FrmFieldsHelper::prepare_field_value( $result, $field_type );
263
264 $result = wp_unslash( $result );
265
266 return $result;
267 }
268
269 public static function get_entry_metas_for_field( $field_id, $order = '', $limit = '', $args = array() ) {
270 $defaults = array(
271 'value' => false,
272 'unique' => false,
273 'stripslashes' => true,
274 'is_draft' => false,
275 );
276 $args = wp_parse_args( $args, $defaults );
277
278 $query = array();
279 self::meta_field_query( $field_id, $order, $limit, $args, $query );
280 $query = implode( ' ', $query );
281
282 $cache_key = 'entry_metas_for_field_' . $field_id . $order . $limit . FrmAppHelper::maybe_json_encode( $args );
283 $values = FrmDb::check_cache( $cache_key, 'frm_entry', $query, 'get_col' );
284
285 if ( ! $args['stripslashes'] ) {
286 return $values;
287 }
288
289 foreach ( $values as $k => $v ) {
290 FrmAppHelper::unserialize_or_decode( $v );
291 $values[ $k ] = $v;
292 unset( $k, $v );
293 }
294
295 return wp_unslash( $values );
296 }
297
298 /**
299 * @param int|string $field_id
300 * @param string $order
301 * @param string $limit
302 * @param array $args
303 * @param array $query
304 */
305 private static function meta_field_query( $field_id, $order, $limit, $args, array &$query ) {
306 global $wpdb;
307 $query[] = 'SELECT';
308 $query[] = $args['unique'] ? 'DISTINCT(em.meta_value)' : 'em.meta_value';
309 $query[] = 'FROM ' . $wpdb->prefix . 'frm_item_metas em ';
310
311 if ( ! $args['is_draft'] ) {
312 $query[] = 'INNER JOIN ' . $wpdb->prefix . 'frm_items e ON (e.id=em.item_id)';
313 }
314
315 if ( is_numeric( $field_id ) ) {
316 $query[] = $wpdb->prepare( 'WHERE em.field_id=%d', $field_id );
317 } else {
318 $query[] = $wpdb->prepare( 'LEFT JOIN ' . $wpdb->prefix . 'frm_fields fi ON (em.field_id = fi.id) WHERE fi.field_key=%s', $field_id );
319 }
320
321 if ( ! $args['is_draft'] ) {
322 $query[] = 'AND e.is_draft=0';
323 }
324
325 if ( $args['value'] ) {
326 $query[] = $wpdb->prepare( ' AND meta_value=%s', $args['value'] );
327 }
328 $query[] = $order . $limit;
329 }
330
331 public static function get_entry_meta_info( $entry_id ) {
332 return FrmDb::get_results( 'frm_item_metas', array( 'item_id' => $entry_id ) );
333 }
334
335 /**
336 * @param array $where
337 * @param string $order_by
338 * @param string $limit
339 * @param bool $stripslashes
340 * @return array
341 */
342 public static function getAll( $where = array(), $order_by = '', $limit = '', $stripslashes = false ) {
343 global $wpdb;
344 $query = 'SELECT it.*, fi.type as field_type, fi.field_key as field_key,
345 fi.required as required, fi.form_id as field_form_id, fi.name as field_name, fi.options as fi_options
346 FROM ' . $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id' .
347 FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
348
349 $cache_key = 'all_' . FrmAppHelper::maybe_json_encode( $where ) . $order_by . $limit;
350 $results = FrmDb::check_cache( $cache_key, 'frm_entry', $query, ( $limit == ' LIMIT 1' ? 'get_row' : 'get_results' ) );
351
352 if ( ! $results || ! $stripslashes ) {
353 return $results;
354 }
355
356 foreach ( $results as $k => $result ) {
357 FrmAppHelper::unserialize_or_decode( $result->meta_value );
358 $results[ $k ]->meta_value = wp_unslash( $result->meta_value );
359 unset( $k, $result );
360 }
361
362 return $results;
363 }
364
365 public static function getEntryIds( $where = array(), $order_by = '', $limit = '', $unique = true, $args = array() ) {
366 $defaults = array(
367 'is_draft' => false,
368 'user_id' => '',
369 'group_by' => '',
370 );
371 $args = wp_parse_args( $args, $defaults );
372
373 $query = array();
374 self::get_ids_query( $where, $order_by, $limit, $unique, $args, $query );
375 $query = implode( ' ', $query );
376
377 $cache_key = 'ids_' . FrmAppHelper::maybe_json_encode( $where ) . $order_by . 'l' . $limit . 'u' . $unique . FrmAppHelper::maybe_json_encode( $args );
378 $type = 'get_' . ( ' LIMIT 1' === $limit ? 'var' : 'col' );
379 return FrmDb::check_cache( $cache_key, 'frm_entry', $query, $type );
380 }
381
382 /**
383 * Given a query including a form id and its child form ids, output an array of matching entry ids
384 * If a child entry id is matched, its parent will be returned in its place
385 *
386 * @param array $query
387 * @param array $args
388 * @return array
389 */
390 public static function get_top_level_entry_ids( $query, $args ) {
391 $args['return_parent_id_if_0_return_id'] = true;
392 return self::getEntryIds( $query, '', '', true, $args );
393 }
394
395 /**
396 * @param array|string $where
397 * @param string $order_by
398 * @param string $limit
399 */
400 private static function get_ids_query( $where, $order_by, $limit, $unique, $args, array &$query ) {
401 global $wpdb;
402 $query[] = 'SELECT';
403 $defaults = array(
404 'return_parent_id' => false,
405 'return_parent_id_if_0_return_id' => false,
406 );
407 $args = array_merge( $defaults, $args );
408
409 if ( $unique ) {
410 $query[] = 'DISTINCT';
411 }
412
413 if ( $args['return_parent_id_if_0_return_id'] ) {
414 $query[] = 'IF ( e.parent_item_id = 0, it.item_id, e.parent_item_id )';
415 } elseif ( $args['return_parent_id'] ) {
416 $query[] = 'e.parent_item_id';
417 } else {
418 $query[] = 'it.item_id';
419 }
420
421 $query[] = 'FROM ' . $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id';
422
423 $query[] = 'INNER JOIN ' . $wpdb->prefix . 'frm_items e ON (e.id=it.item_id)';
424 if ( is_array( $where ) ) {
425 if ( ! $args['is_draft'] ) {
426 $where['e.is_draft'] = 0;
427 } elseif ( is_numeric( $args['is_draft'] ) ) {
428 if ( class_exists( 'FrmAbandonmentHooksController', false ) ) {
429 $where['e.is_draft'] = absint( $args['is_draft'] );
430 } else {
431 $where['e.is_draft'] = 1;
432 }
433 } elseif ( 'both' === $args['is_draft'] && class_exists( 'FrmAbandonmentHooksController', false ) ) {
434 $where['e.is_draft'] = array( 0, 1 );
435 } elseif ( false !== strpos( $args['is_draft'], ',' ) ) {
436 $is_draft = array_reduce(
437 explode( ',', $args['is_draft'] ),
438 function ( $total, $current ) {
439 if ( is_numeric( $current ) ) {
440 $total[] = absint( $current );
441 }
442 return $total;
443 },
444 array()
445 );
446 if ( $is_draft ) {
447 $where['e.is_draft'] = $is_draft;
448 }
449 }//end if
450
451 if ( ! empty( $args['user_id'] ) ) {
452 $where['e.user_id'] = $args['user_id'];
453 }
454 $query[] = FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
455
456 if ( $args['group_by'] ) {
457 $query[] = ' GROUP BY ' . sanitize_text_field( $args['group_by'] );
458 }
459
460 return;
461 }//end if
462
463 $draft_where = '';
464 $user_where = '';
465 if ( ! $args['is_draft'] ) {
466 $draft_where = $wpdb->prepare( ' AND e.is_draft=%d', 0 );
467 } elseif ( $args['is_draft'] == 1 ) {
468 $draft_where = $wpdb->prepare( ' AND e.is_draft=%d', 1 );
469 }
470
471 if ( ! empty( $args['user_id'] ) ) {
472 $user_where = $wpdb->prepare( ' AND e.user_id=%d', $args['user_id'] );
473 }
474
475 if ( strpos( $where, ' GROUP BY ' ) ) {
476 // don't inject WHERE filtering after GROUP BY
477 $parts = explode( ' GROUP BY ', $where );
478 $where = $parts[0];
479 $where .= $draft_where . $user_where;
480 $where .= ' GROUP BY ' . $parts[1];
481 } else {
482 $where .= $draft_where . $user_where;
483 }
484
485 // The query has already been prepared
486 $query[] = FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
487 }
488
489 public static function search_entry_metas( $search, $field_id, $operator ) {
490 $cache_key = 'search_' . FrmAppHelper::maybe_json_encode( $search ) . $field_id . $operator;
491 $results = wp_cache_get( $cache_key, 'frm_entry' );
492 if ( false !== $results ) {
493 return $results;
494 }
495
496 global $wpdb;
497 if ( is_array( $search ) ) {
498 $where = '';
499 foreach ( $search as $field => $value ) {
500 if ( $value <= 0 || ! in_array( $field, array( 'year', 'month', 'day' ) ) ) {
501 continue;
502 }
503
504 switch ( $field ) {
505 case 'year':
506 $value = '%' . $value;
507 break;
508 case 'month':
509 $value .= '%';
510 break;
511 case 'day':
512 $value = '%' . $value . '%';
513 }
514 $where .= $wpdb->prepare( ' meta_value ' . $operator . ' %s and', $value ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
515 }
516 $where .= $wpdb->prepare( ' field_id=%d', $field_id );
517 $query = 'SELECT DISTINCT item_id FROM ' . $wpdb->prefix . 'frm_item_metas' . FrmDb::prepend_and_or_where( ' WHERE ', $where );
518 } else {
519 if ( $operator === 'LIKE' ) {
520 $search = '%' . $search . '%';
521 }
522 $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
523 }//end if
524
525 $results = $wpdb->get_col( $query, 0 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
526 FrmDb::set_cache( $cache_key, $results, 'frm_entry' );
527
528 return $results;
529 }
530 }
531