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

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