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

503 lines 15.0 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 }//end foreach
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|int $field_id
279 * @param string $order
280 * @param string $limit
281 * @param array $args
282 * @param array $query
283 */
284 private static function meta_field_query( $field_id, $order, $limit, $args, array &$query ) {
285 global $wpdb;
286 $query[] = 'SELECT';
287 $query[] = $args['unique'] ? 'DISTINCT(em.meta_value)' : 'em.meta_value';
288 $query[] = 'FROM ' . $wpdb->prefix . 'frm_item_metas em ';
289
290 if ( ! $args['is_draft'] ) {
291 $query[] = 'INNER JOIN ' . $wpdb->prefix . 'frm_items e ON (e.id=em.item_id)';
292 }
293
294 if ( is_numeric( $field_id ) ) {
295 $query[] = $wpdb->prepare( 'WHERE em.field_id=%d', $field_id );
296 } else {
297 $query[] = $wpdb->prepare( 'LEFT JOIN ' . $wpdb->prefix . 'frm_fields fi ON (em.field_id = fi.id) WHERE fi.field_key=%s', $field_id );
298 }
299
300 if ( ! $args['is_draft'] ) {
301 $query[] = 'AND e.is_draft=0';
302 }
303
304 if ( $args['value'] ) {
305 $query[] = $wpdb->prepare( ' AND meta_value=%s', $args['value'] );
306 }
307 $query[] = $order . $limit;
308 }
309
310 public static function get_entry_meta_info( $entry_id ) {
311 return FrmDb::get_results( 'frm_item_metas', array( 'item_id' => $entry_id ) );
312 }
313
314 public static function getAll( $where = array(), $order_by = '', $limit = '', $stripslashes = false ) {
315 global $wpdb;
316 $query = 'SELECT it.*, fi.type as field_type, fi.field_key as field_key,
317 fi.required as required, fi.form_id as field_form_id, fi.name as field_name, fi.options as fi_options
318 FROM ' . $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id' .
319 FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
320
321 $cache_key = 'all_' . FrmAppHelper::maybe_json_encode( $where ) . $order_by . $limit;
322 $results = FrmDb::check_cache( $cache_key, 'frm_entry', $query, ( $limit == ' LIMIT 1' ? 'get_row' : 'get_results' ) );
323
324 if ( ! $results || ! $stripslashes ) {
325 return $results;
326 }
327
328 foreach ( $results as $k => $result ) {
329 FrmAppHelper::unserialize_or_decode( $result->meta_value );
330 $results[ $k ]->meta_value = wp_unslash( $result->meta_value );
331 unset( $k, $result );
332 }
333
334 return $results;
335 }
336
337 public static function getEntryIds( $where = array(), $order_by = '', $limit = '', $unique = true, $args = array() ) {
338 $defaults = array(
339 'is_draft' => false,
340 'user_id' => '',
341 'group_by' => '',
342 );
343 $args = wp_parse_args( $args, $defaults );
344
345 $query = array();
346 self::get_ids_query( $where, $order_by, $limit, $unique, $args, $query );
347 $query = implode( ' ', $query );
348
349 $cache_key = 'ids_' . FrmAppHelper::maybe_json_encode( $where ) . $order_by . 'l' . $limit . 'u' . $unique . FrmAppHelper::maybe_json_encode( $args );
350 $type = 'get_' . ( ' LIMIT 1' === $limit ? 'var' : 'col' );
351 return FrmDb::check_cache( $cache_key, 'frm_entry', $query, $type );
352 }
353
354 /**
355 * Given a query including a form id and its child form ids, output an array of matching entry ids
356 * If a child entry id is matched, its parent will be returned in its place
357 *
358 * @param array $query
359 * @param array $args
360 * @return array
361 */
362 public static function get_top_level_entry_ids( $query, $args ) {
363 $args['return_parent_id_if_0_return_id'] = true;
364 return self::getEntryIds( $query, '', '', true, $args );
365 }
366
367 /**
368 * @param string|array $where
369 * @param string $order_by
370 * @param string $limit
371 */
372 private static function get_ids_query( $where, $order_by, $limit, $unique, $args, array &$query ) {
373 global $wpdb;
374 $query[] = 'SELECT';
375 $defaults = array(
376 'return_parent_id' => false,
377 'return_parent_id_if_0_return_id' => false,
378 );
379 $args = array_merge( $defaults, $args );
380
381 if ( $unique ) {
382 $query[] = 'DISTINCT';
383 }
384
385 if ( $args['return_parent_id_if_0_return_id'] ) {
386 $query[] = 'IF ( e.parent_item_id = 0, it.item_id, e.parent_item_id )';
387 } elseif ( $args['return_parent_id'] ) {
388 $query[] = 'e.parent_item_id';
389 } else {
390 $query[] = 'it.item_id';
391 }
392
393 $query[] = 'FROM ' . $wpdb->prefix . 'frm_item_metas it LEFT OUTER JOIN ' . $wpdb->prefix . 'frm_fields fi ON it.field_id=fi.id';
394
395 $query[] = 'INNER JOIN ' . $wpdb->prefix . 'frm_items e ON (e.id=it.item_id)';
396 if ( is_array( $where ) ) {
397 if ( ! $args['is_draft'] ) {
398 $where['e.is_draft'] = 0;
399 } elseif ( is_numeric( $args['is_draft'] ) ) {
400 if ( class_exists( 'FrmAbandonmentHooksController', false ) ) {
401 $where['e.is_draft'] = absint( $args['is_draft'] );
402 } else {
403 $where['e.is_draft'] = 1;
404 }
405 } elseif ( 'both' === $args['is_draft'] && class_exists( 'FrmAbandonmentHooksController', false ) ) {
406 $where['e.is_draft'] = array( 0, 1 );
407 } elseif ( false !== strpos( $args['is_draft'], ',' ) ) {
408 $is_draft = array_reduce(
409 explode( ',', $args['is_draft'] ),
410 function( $total, $current ) {
411 if ( is_numeric( $current ) ) {
412 $total[] = absint( $current );
413 }
414 return $total;
415 },
416 array()
417 );
418 if ( $is_draft ) {
419 $where['e.is_draft'] = $is_draft;
420 }
421 }//end if
422
423 if ( ! empty( $args['user_id'] ) ) {
424 $where['e.user_id'] = $args['user_id'];
425 }
426 $query[] = FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
427
428 if ( $args['group_by'] ) {
429 $query[] = ' GROUP BY ' . sanitize_text_field( $args['group_by'] );
430 }
431
432 return;
433 }//end if
434
435 $draft_where = '';
436 $user_where = '';
437 if ( ! $args['is_draft'] ) {
438 $draft_where = $wpdb->prepare( ' AND e.is_draft=%d', 0 );
439 } elseif ( $args['is_draft'] == 1 ) {
440 $draft_where = $wpdb->prepare( ' AND e.is_draft=%d', 1 );
441 }
442
443 if ( ! empty( $args['user_id'] ) ) {
444 $user_where = $wpdb->prepare( ' AND e.user_id=%d', $args['user_id'] );
445 }
446
447 if ( strpos( $where, ' GROUP BY ' ) ) {
448 // don't inject WHERE filtering after GROUP BY
449 $parts = explode( ' GROUP BY ', $where );
450 $where = $parts[0];
451 $where .= $draft_where . $user_where;
452 $where .= ' GROUP BY ' . $parts[1];
453 } else {
454 $where .= $draft_where . $user_where;
455 }
456
457 // The query has already been prepared
458 $query[] = FrmDb::prepend_and_or_where( ' WHERE ', $where ) . $order_by . $limit;
459 }
460
461 public static function search_entry_metas( $search, $field_id, $operator ) {
462 $cache_key = 'search_' . FrmAppHelper::maybe_json_encode( $search ) . $field_id . $operator;
463 $results = wp_cache_get( $cache_key, 'frm_entry' );
464 if ( false !== $results ) {
465 return $results;
466 }
467
468 global $wpdb;
469 if ( is_array( $search ) ) {
470 $where = '';
471 foreach ( $search as $field => $value ) {
472 if ( $value <= 0 || ! in_array( $field, array( 'year', 'month', 'day' ) ) ) {
473 continue;
474 }
475
476 switch ( $field ) {
477 case 'year':
478 $value = '%' . $value;
479 break;
480 case 'month':
481 $value .= '%';
482 break;
483 case 'day':
484 $value = '%' . $value . '%';
485 }
486 $where .= $wpdb->prepare( ' meta_value ' . $operator . ' %s and', $value ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
487 }
488 $where .= $wpdb->prepare( ' field_id=%d', $field_id );
489 $query = 'SELECT DISTINCT item_id FROM ' . $wpdb->prefix . 'frm_item_metas' . FrmDb::prepend_and_or_where( ' WHERE ', $where );
490 } else {
491 if ( $operator == 'LIKE' ) {
492 $search = '%' . $search . '%';
493 }
494 $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
495 }//end if
496
497 $results = $wpdb->get_col( $query, 0 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
498 FrmDb::set_cache( $cache_key, $results, 'frm_entry' );
499
500 return $results;
501 }
502 }
503