GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-common.php
Go to the documentation of this file.
1 <?php
2 /**
3  * Set of common functions to separate main plugin from Gravity Forms API and other cross-plugin methods
4  *
5  * @package GravityView
6  * @license GPL2+
7  * @author GravityView <[email protected]>
8  * @link http://gravityview.co
9  * @copyright Copyright 2014, Katz Web Services, Inc.
10  *
11  * @since 1.5.2
12  */
13 
14 /** If this file is called directly, abort. */
15 if ( ! defined( 'ABSPATH' ) ) {
16  die;
17 }
18 
19 class GVCommon {
20 
21  /**
22  * Returns the form object for a given Form ID.
23  *
24  * @param mixed $form_id
25  * @return array|false Array: Form object returned from Gravity Forms; False: no form ID specified or Gravity Forms isn't active.
26  */
27  public static function get_form( $form_id ) {
28  if ( empty( $form_id ) ) {
29  return false;
30  }
31 
32  // Only get_form_meta is cached. ::facepalm::
33  if ( class_exists( 'GFFormsModel' ) ) {
34  return GFFormsModel::get_form_meta( $form_id );
35  }
36 
37  if ( class_exists( 'GFAPI' ) ) {
38  return GFAPI::get_form( $form_id );
39  }
40 
41  return false;
42  }
43 
44  /**
45  * Returns form object for existing form or a form template.
46  *
47  * @since 2.16
48  *
49  * @param int|string $form_id Gravity Forms form ID. Default: 0.
50  *
51  * @return array|false
52  */
53  public static function get_form_or_form_template( $form_id = 0 ) {
54  // Determine if form is a preset and convert it to an array with fields
55  if ( is_string( $form_id ) && preg_match( '/^preset_/', $form_id ) ) {
57  } else {
58  $form = self::get_form( $form_id );
59  }
60 
61  return $form;
62  }
63 
64  /**
65  * Alias of GravityView_Roles_Capabilities::has_cap()
66  *
67  * @since 1.15
68  *
69  * @see GravityView_Roles_Capabilities::has_cap()
70  *
71  * @param string|array $caps Single capability or array of capabilities
72  * @param int $object_id (optional) Parameter can be used to check for capabilities against a specific object, such as a post or user
73  * @param int|null $user_id (optional) Check the capabilities for a user who is not necessarily the currently logged-in user
74  *
75  * @return bool True: user has at least one passed capability; False: user does not have any defined capabilities
76  */
77  public static function has_cap( $caps = '', $object_id = null, $user_id = null ) {
78  return GravityView_Roles_Capabilities::has_cap( $caps, $object_id, $user_id );
79  }
80 
81  /**
82  * Return a Gravity Forms field array, whether using GF 1.9 or not
83  *
84  * @since 1.7
85  *
86  * @param array|GF_Fields $field Gravity Forms field or array
87  * @return array Array version of $field
88  */
89  public static function get_field_array( $field ) {
90 
91  if ( class_exists( 'GF_Fields' ) ) {
92 
93  $field_object = GF_Fields::create( $field );
94 
95  // Convert the field object in 1.9 to an array for backward compatibility
96  $field_array = get_object_vars( $field_object );
97 
98  } else {
99  $field_array = $field;
100  }
101 
102  return $field_array;
103  }
104 
105  /**
106  * Get all existing Views
107  *
108  * @since 1.5.4 Added $args array
109  *
110  * @param array $args Pass custom array of args, formatted as if for `get_posts()`
111  *
112  * @return WP_Post[] Array of Views as `WP_Post`. Empty array if none found.
113  */
114  public static function get_all_views( $args = array() ) {
115 
116  $default_params = array(
117  'post_type' => 'gravityview',
118  'posts_per_page' => -1,
119  'post_status' => 'publish',
120  );
121 
122  $params = wp_parse_args( $args, $default_params );
123 
124  /**
125  * @filter `gravityview/get_all_views/params` Modify the parameters sent to get all views.
126  * @param array $params Array of parameters to pass to `get_posts()`
127  */
128  $views_params = apply_filters( 'gravityview/get_all_views/params', $params );
129 
130  $views = get_posts( $views_params );
131 
132  return $views;
133  }
134 
135 
136  /**
137  * Get the form array for an entry based only on the entry ID
138  *
139  * @param int|string $entry_slug Entry slug
140  * @return array|false Array: Form object returned from Gravity Forms; False: form doesn't exist, or $entry didn't exist or $entry didn't specify form ID
141  */
142  public static function get_form_from_entry_id( $entry_slug ) {
143 
144  $entry = self::get_entry( $entry_slug, true, false );
145 
146  $form = false;
147 
148  if ( $entry ) {
149  $form = GFAPI::get_form( $entry['form_id'] );
150  }
151 
152  return $form;
153  }
154 
155  /**
156  * Check whether a form has product fields
157  *
158  * @since 1.16
159  * @since 1.20 Refactored the field types to get_product_field_types() method
160  *
161  * @param array $form Gravity Forms form array
162  *
163  * @return bool|GF_Field[]
164  */
165  public static function has_product_field( $form = array() ) {
166 
167  $product_fields = self::get_product_field_types();
168 
169  $fields = GFAPI::get_fields_by_type( $form, $product_fields );
170 
171  return empty( $fields ) ? false : $fields;
172  }
173 
174  /**
175  * Return array of product field types
176  *
177  * Modify the value using the `gform_product_field_types` filter
178  *
179  * @since 1.20
180  *
181  * @return array
182  */
183  public static function get_product_field_types() {
184 
185  $product_fields = apply_filters( 'gform_product_field_types', array( 'option', 'quantity', 'product', 'total', 'shipping', 'calculation', 'price', 'hiddenproduct', 'singleproduct', 'singleshipping' ) );
186 
187  return $product_fields;
188  }
189 
190  /**
191  * Check if an entry has transaction data
192  *
193  * Checks the following keys to see if they are set: 'payment_status', 'payment_date', 'transaction_id', 'payment_amount', 'payment_method'
194  *
195  * @since 1.20
196  *
197  * @param array $entry Gravity Forms entry array
198  *
199  * @return bool True: Entry has metadata suggesting it has communicated with a payment gateway; False: it does not have that data.
200  */
201  public static function entry_has_transaction_data( $entry = array() ) {
202 
203  if ( ! is_array( $entry ) ) {
204  return false;
205  }
206 
207  $has_transaction_data = false;
208 
209  $payment_meta = array( 'payment_status', 'payment_date', 'transaction_id', 'payment_amount', 'payment_method' );
210 
211  foreach ( $payment_meta as $meta ) {
212 
213  $has_transaction_data = \GV\Utils::get( $entry, $meta, false );
214 
215  if ( is_numeric( $has_transaction_data ) && ( ! floatval( $has_transaction_data ) > 0 ) ) {
216  $has_transaction_data = false;
217  continue;
218  }
219 
220  if ( ! empty( $has_transaction_data ) ) {
221  break;
222  }
223  }
224 
225  return (bool) $has_transaction_data;
226  }
227 
228  /**
229  * Get the entry ID from the entry slug, which may or may not be the entry ID
230  *
231  * @since 1.5.2
232  * @param string $slug The entry slug, as returned by GravityView_API::get_entry_slug()
233  * @return int|null The entry ID, if exists; `NULL` if not
234  */
235  public static function get_entry_id_from_slug( $slug ) {
236  global $wpdb;
237 
238  $search_criteria = array(
239  'field_filters' => array(
240  array(
241  'key' => 'gravityview_unique_id', // Search the meta values
242  'value' => $slug,
243  'operator' => 'is',
244  'type' => 'meta',
245  ),
246  ),
247  );
248 
249  // Limit to one for speed
250  $paging = array(
251  'page_size' => 1,
252  );
253 
254  /**
255  * @filter `gravityview/common/get_entry_id_from_slug/form_id` The form ID used to get the custom entry ID. Change this to avoid collisions with data from other forms with the same values and the same field ID.
256  * @since 1.17.2
257  * @param int $form_id ID of the form to search. Default: `0` (searches all forms)
258  */
259  $form_id = apply_filters( 'gravityview/common/get_entry_id_from_slug/form_id', 0 );
260 
261  $results = GFAPI::get_entries( intval( $form_id ), $search_criteria, null, $paging );
262 
263  $result = ( ! empty( $results ) && ! empty( $results[0]['id'] ) ) ? $results[0]['id'] : null;
264 
265  return $result;
266  }
267 
268  /**
269  * Get all forms to use as options in View settings.
270  *
271  * @since 2.17
272  *
273  * @uses GFAPI::get_form()
274  * @used-by \GV\View_Settings::defaults()
275  *
276  * @param bool $active True if active forms are returned. False to get inactive forms. Defaults to true.
277  * @param bool $trash True if trashed forms are returned. False to exclude trash. Defaults to false.
278  * @param string $sort_column The column to sort the results on.
279  * @param string $sort_dir The sort direction, ASC or DESC.
280  *
281  * @return array
282  */
283  public static function get_forms_as_options( $active = true, $trash = false, $sort_column = 'id', $sort_dir = 'ASC' ) {
284 
285  $forms = GFAPI::get_forms( $active, $trash, $sort_column, $sort_dir );
286 
287  if ( empty( $forms ) ) {
288  return array();
289  }
290 
291  $options = array(
292  '' => esc_html__( 'Select a Form', 'gk-gravityview' ),
293  );
294 
295  foreach ( $forms as $form ) {
296  $options[ (int) $form['id'] ] = esc_html( $form['title'] );
297  }
298 
299  return $options;
300  }
301 
302  /**
303  * Alias of GFAPI::get_forms()
304  *
305  * @see GFAPI::get_forms()
306  *
307  * @since 1.19 Allow "any" $active status option
308  * @since 2.7.2 Allow sorting forms using wp_list_sort()
309  *
310  * @param bool|string $active Status of forms. Use `any` to get array of forms with any status. Default: `true`
311  * @param bool $trash Include forms in trash? Default: `false`
312  * @param string|array $order_by Optional. Either the field name to order by or an array of multiple orderby fields as $orderby => $order.
313  * @param string $order Optional. Either 'ASC' or 'DESC'. Only used if $orderby is a string.
314  *
315  * @return array Empty array if GFAPI class isn't available or no forms. Otherwise, the array of Forms
316  */
317  public static function get_forms( $active = true, $trash = false, $order_by = 'id', $order = 'ASC' ) {
318  $forms = array();
319  if ( ! class_exists( 'GFAPI' ) ) {
320  return array();
321  }
322 
323  if ( 'any' === $active ) {
324  $active_forms = GFAPI::get_forms( true, $trash );
325  $inactive_forms = GFAPI::get_forms( false, $trash );
326  $forms = array_merge( array_filter( $active_forms ), array_filter( $inactive_forms ) );
327  } else {
328  $forms = GFAPI::get_forms( $active, $trash );
329  }
330 
331  $forms = wp_list_sort( $forms, $order_by, $order, true );
332 
333  return $forms;
334  }
335 
336  /**
337  * Return array of fields' id and label, for a given Form ID
338  *
339  * @param string|array $form_id (default: '') or $form object
340  * @param bool $add_default_properties
341  * @param bool $include_parent_field
342  * @return array
343  */
344  public static function get_form_fields( $form = '', $add_default_properties = false, $include_parent_field = true ) {
345 
346  if ( ! is_array( $form ) ) {
347  $form = self::get_form( $form );
348  }
349 
350  $fields = array();
351  $has_product_fields = false;
352  $has_post_fields = false;
353 
354  if ( $form ) {
355  foreach ( $form['fields'] as $field ) {
356  if ( $include_parent_field || empty( $field['inputs'] ) ) {
357  $fields[ "{$field['id']}" ] = array(
358  'label' => \GV\Utils::get( $field, 'label' ),
359  'parent' => null,
360  'type' => \GV\Utils::get( $field, 'type' ),
361  'adminLabel' => \GV\Utils::get( $field, 'adminLabel' ),
362  'adminOnly' => \GV\Utils::get( $field, 'adminOnly' ),
363  );
364  }
365 
366  if ( $add_default_properties && ! empty( $field['inputs'] ) ) {
367  foreach ( $field['inputs'] as $input ) {
368 
369  if ( ! empty( $input['isHidden'] ) ) {
370  continue;
371  }
372 
373  /**
374  * @hack
375  * In case of email/email confirmation, the input for email has the same id as the parent field
376  */
377  if ( 'email' === $field['type'] && false === strpos( $input['id'], '.' ) ) {
378  continue;
379  }
380  $fields[ "{$input['id']}" ] = array(
381  'label' => \GV\Utils::get( $input, 'label' ),
382  'customLabel' => \GV\Utils::get( $input, 'customLabel' ),
383  'parent' => $field,
384  'type' => \GV\Utils::get( $field, 'type' ),
385  'adminLabel' => \GV\Utils::get( $field, 'adminLabel' ),
386  'adminOnly' => \GV\Utils::get( $field, 'adminOnly' ),
387  );
388  }
389  }
390 
391  if ( GFCommon::is_product_field( $field['type'] ) ) {
392  $has_product_fields = true;
393  }
394 
395  if ( GFCommon::is_post_field( $field ) ) {
396  $has_post_fields = true;
397  }
398  }
399  }
400 
401  /**
402  * @since 1.7
403  */
404  if ( $has_post_fields ) {
405  $fields['post_id'] = array(
406  'label' => __( 'Post ID', 'gk-gravityview' ),
407  'type' => 'post_id',
408  );
409  }
410 
411  if ( $has_product_fields ) {
412 
413  $payment_fields = GravityView_Fields::get_all( 'pricing' );
414 
415  foreach ( $payment_fields as $payment_field ) {
416 
417  // Either the field exists ($fields['shipping']) or the form explicitly contains a `shipping` field with numeric key
418  if ( isset( $fields[ "{$payment_field->name}" ] ) || GFCommon::get_fields_by_type( $form, $payment_field->name ) ) {
419  continue;
420  }
421 
422  $fields[ "{$payment_field->name}" ] = array(
423  'label' => $payment_field->label,
424  'desc' => $payment_field->description,
425  'type' => $payment_field->name,
426  );
427  }
428  }
429 
430  /**
431  * @filter `gravityview/common/get_form_fields` Modify the form fields shown in the Add Field field picker.
432  * @since 1.17
433  * @param array $fields Associative array of fields, with keys as field type, values an array with the following keys: (string) `label` (required), (string) `type` (required), `desc`, (string) `customLabel`, (GF_Field) `parent`, (string) `adminLabel`, (bool)`adminOnly`
434  * @param array $form GF Form array
435  * @param bool $include_parent_field Whether to include the parent field when getting a field with inputs
436  */
437  $fields = apply_filters( 'gravityview/common/get_form_fields', $fields, $form, $include_parent_field );
438 
439  return $fields;
440 
441  }
442 
443  /**
444  * get extra fields from entry meta
445  *
446  * @param string $form_id (default: '')
447  * @return array
448  */
449  public static function get_entry_meta( $form_id, $only_default_column = true ) {
450 
451  $extra_fields = GFFormsModel::get_entry_meta( $form_id );
452 
453  $fields = array();
454 
455  foreach ( $extra_fields as $key => $field ) {
456  if ( ! empty( $only_default_column ) && ! empty( $field['is_default_column'] ) ) {
457  $fields[ $key ] = array(
458  'label' => $field['label'],
459  'type' => 'entry_meta',
460  );
461  }
462  }
463 
464  return $fields;
465  }
466 
467 
468  /**
469  * Wrapper for the Gravity Forms GFFormsModel::search_lead_ids() method
470  *
471  * @see GFEntryList::leads_page()
472  * @param int $form_id ID of the Gravity Forms form
473  * @since 1.1.6
474  * @return array|void Array of entry IDs. Void if Gravity Forms isn't active.
475  */
476  public static function get_entry_ids( $form_id, $search_criteria = array() ) {
477 
478  if ( ! class_exists( 'GFFormsModel' ) ) {
479  return;
480  }
481 
482  return GFFormsModel::search_lead_ids( $form_id, $search_criteria );
483  }
484 
485  /**
486  * Calculates the Search Criteria used on the self::get_entries / self::get_entry methods
487  *
488  * @since 1.7.4
489  *
490  * @param array $passed_criteria array Input Criteria (search_criteria, sorting, paging)
491  * @param array $form_ids array Gravity Forms form IDs
492  * @return array
493  */
494  public static function calculate_get_entries_criteria( $passed_criteria = array(), $form_ids = array() ) {
495 
496  $search_criteria_defaults = array(
497  'search_criteria' => null,
498  'sorting' => null,
499  'paging' => null,
500  'cache' => ( isset( $passed_criteria['cache'] ) ? (bool) $passed_criteria['cache'] : true ),
501  'context_view_id' => null,
502  );
503 
504  $criteria = wp_parse_args( $passed_criteria, $search_criteria_defaults );
505 
506  if ( ! empty( $criteria['search_criteria']['field_filters'] ) && is_array( $criteria['search_criteria']['field_filters'] ) ) {
507  foreach ( $criteria['search_criteria']['field_filters'] as &$filter ) {
508 
509  if ( ! is_array( $filter ) ) {
510  continue;
511  }
512 
513  // By default, we want searches to be wildcard for each field.
514  $filter['operator'] = empty( $filter['operator'] ) ? 'contains' : $filter['operator'];
515 
516  /**
517  * @filter `gravityview_search_operator` Modify the search operator for the field (contains, is, isnot, etc)
518  * @param string $operator Existing search operator
519  * @param array $filter array with `key`, `value`, `operator`, `type` keys
520  */
521  $filter['operator'] = apply_filters( 'gravityview_search_operator', $filter['operator'], $filter );
522  }
523 
524  // don't send just the [mode] without any field filter.
525  if ( count( $criteria['search_criteria']['field_filters'] ) === 1 && array_key_exists( 'mode', $criteria['search_criteria']['field_filters'] ) ) {
526  unset( $criteria['search_criteria']['field_filters']['mode'] );
527  }
528  }
529 
530  /**
531  * Prepare date formats to be in Gravity Forms DB format;
532  * $passed_criteria may include date formats incompatible with Gravity Forms.
533  */
534  foreach ( array( 'start_date', 'end_date' ) as $key ) {
535 
536  if ( ! empty( $criteria['search_criteria'][ $key ] ) ) {
537 
538  // Use date_create instead of new DateTime so it returns false if invalid date format.
539  $date = date_create( $criteria['search_criteria'][ $key ] );
540 
541  if ( $date ) {
542  // Gravity Forms wants dates in the `Y-m-d H:i:s` format.
543  $criteria['search_criteria'][ $key ] = $date->format( 'Y-m-d H:i:s' );
544  } else {
545  gravityview()->log->error(
546  '{key} Date format not valid:',
547  array(
548  'key' => $key,
549  $criteria['search_criteria'][ $key ],
550  )
551  );
552 
553  // If it's an invalid date, unset it. Gravity Forms freaks out otherwise.
554  unset( $criteria['search_criteria'][ $key ] );
555  }
556  }
557  }
558 
559  if ( empty( $criteria['context_view_id'] ) ) {
560  // Calculate the context view id and send it to the advanced filter
561  if ( GravityView_frontend::getInstance()->getSingleEntry() ) {
562  $criteria['context_view_id'] = GravityView_frontend::getInstance()->get_context_view_id();
563  } elseif ( class_exists( 'GravityView_View_Data' ) && GravityView_View_Data::getInstance() && GravityView_View_Data::getInstance()->has_multiple_views() ) {
564  $criteria['context_view_id'] = GravityView_frontend::getInstance()->get_context_view_id();
565  } elseif ( 'delete' === GFForms::get( 'action' ) ) {
566  $criteria['context_view_id'] = isset( $_GET['view_id'] ) ? intval( $_GET['view_id'] ) : null;
567  }
568  }
569 
570  /**
571  * @filter `gravityview_search_criteria` Apply final criteria filter (Used by the Advanced Filter extension)
572  * @param array $criteria Search criteria used by GravityView
573  * @param array $form_ids Forms to search
574  * @param int $view_id ID of the view being used to search
575  */
576  $criteria = apply_filters( 'gravityview_search_criteria', $criteria, $form_ids, $criteria['context_view_id'] );
577 
578  return (array) $criteria;
579  }
580 
581 
582  /**
583  * Retrieve entries given search, sort, paging criteria
584  *
585  * @see GFAPI::get_entries()
586  * @see GFFormsModel::get_field_filters_where()
587  * @param int|array $form_ids The ID of the form or an array IDs of the Forms. Zero for all forms.
588  * @param mixed $passed_criteria (default: null)
589  * @param mixed &$total Optional. An output parameter containing the total number of entries. Pass a non-null value to generate the total count. (default: null)
590  *
591  * @deprecated See \GV\View::get_entries.
592  *
593  * @return mixed False: Error fetching entries. Array: Multi-dimensional array of Gravity Forms entry arrays
594  */
595  public static function get_entries( $form_ids = null, $passed_criteria = null, &$total = null ) {
596 
597  gravityview()->log->notice( '\GVCommon::get_entries is deprecated. Use \GV\View::get_entries instead.' );
598 
599  // Filter the criteria before query (includes Adv Filter)
600  $criteria = self::calculate_get_entries_criteria( $passed_criteria, $form_ids );
601 
602  gravityview()->log->debug( '[gravityview_get_entries] Final Parameters', array( 'data' => $criteria ) );
603 
604  // Return value
605  $return = null;
606 
607  /** Reduce # of database calls */
608  add_filter( 'gform_is_encrypted_field', '__return_false' );
609 
610  if ( ! empty( $criteria['cache'] ) ) {
611 
612  $Cache = new GravityView_Cache( $form_ids, $criteria );
613 
614  if ( $entries = $Cache->get() ) {
615 
616  // Still update the total count when using cached results
617  if ( ! is_null( $total ) ) {
618  $total = GFAPI::count_entries( $form_ids, $criteria['search_criteria'] );
619  }
620 
621  $return = $entries;
622  }
623  }
624 
625  if ( is_null( $return ) && class_exists( 'GFAPI' ) && ( is_numeric( $form_ids ) || is_array( $form_ids ) ) ) {
626 
627  /**
628  * @filter `gravityview_pre_get_entries` Define entries to be used before GFAPI::get_entries() is called
629  * @since 1.14
630  * @param null $return If you want to override GFAPI::get_entries() and define entries yourself, tap in here.
631  * @param array $criteria The final search criteria used to generate the request to `GFAPI::get_entries()`
632  * @param array $passed_criteria The original search criteria passed to `GVCommon::get_entries()`
633  * @param int|null $total Optional. An output parameter containing the total number of entries. Pass a non-null value to generate
634  * @since 2.1 The $total parameter can now be overriden by reference.
635  * @deprecated
636  */
637  $entries = apply_filters_ref_array( 'gravityview_before_get_entries', array( null, $criteria, $passed_criteria, &$total ) );
638 
639  // No entries returned from gravityview_before_get_entries
640  if ( is_null( $entries ) ) {
641 
642  $entries = GFAPI::get_entries( $form_ids, $criteria['search_criteria'], $criteria['sorting'], $criteria['paging'], $total );
643 
644  if ( is_wp_error( $entries ) ) {
645  gravityview()->log->error(
646  '{error}',
647  array(
648  'error' => $entries->get_error_message(),
649  'data' => $entries,
650  )
651  );
652 
653  /** Remove filter added above */
654  remove_filter( 'gform_is_encrypted_field', '__return_false' );
655  return false;
656  }
657  }
658 
659  if ( ! empty( $criteria['cache'] ) && isset( $Cache ) ) {
660 
661  // Cache results
662  $Cache->set( $entries, 'entries' );
663 
664  }
665 
666  $return = $entries;
667  }
668 
669  /** Remove filter added above */
670  remove_filter( 'gform_is_encrypted_field', '__return_false' );
671 
672  /**
673  * @filter `gravityview_entries` Modify the array of entries returned to GravityView after it has been fetched from the cache or from `GFAPI::get_entries()`.
674  * @param array|null $entries Array of entries as returned by the cache or by `GFAPI::get_entries()`
675  * @param array $criteria The final search criteria used to generate the request to `GFAPI::get_entries()`
676  * @param array $passed_criteria The original search criteria passed to `GVCommon::get_entries()`
677  * @param int|null $total Optional. An output parameter containing the total number of entries. Pass a non-null value to generate
678  * @since 2.1 The $total parameter can now be overriden by reference.
679  * @deprecated
680  */
681  $return = apply_filters_ref_array( 'gravityview_entries', array( $return, $criteria, $passed_criteria, &$total ) );
682 
683  return $return;
684  }
685 
686 
687  /**
688  * Get the entry ID from a string that may be the Entry ID or the Entry Slug
689  *
690  * @since 1.18
691  *
692  * @param string $entry_id_or_slug The ID or slug of an entry.
693  * @param bool $force_allow_ids Whether to force allowing getting the ID of an entry, even if custom slugs are enabled
694  *
695  * @return false|int|null Returns the ID of the entry found, if custom slugs is enabled. Returns original value if custom slugs is disabled. Returns false if not allowed to convert slug to ID. Returns NULL if entry not found for the passed slug.
696  */
697  public static function get_entry_id( $entry_id_or_slug = '', $force_allow_ids = false ) {
698 
699  $entry_id = false;
700 
701  /**
702  * @filter `gravityview_custom_entry_slug` Whether to enable and use custom entry slugs.
703  * @param boolean True: Allow for slugs based on entry values. False: always use entry IDs (default)
704  */
705  $custom_slug = apply_filters( 'gravityview_custom_entry_slug', false );
706 
707  /**
708  * @filter `gravityview_custom_entry_slug_allow_id` When using a custom slug, allow access to the entry using the original slug (the Entry ID).
709  * - If disabled (default), only allow access to an entry using the custom slug value. (example: `/entry/custom-slug/` NOT `/entry/123/`)
710  * - If enabled, you could access using the custom slug OR the entry id (example: `/entry/custom-slug/` OR `/entry/123/`)
711  * @param boolean $custom_slug_id_access True: allow accessing the slug by ID; False: only use the slug passed to the method.
712  */
713  $custom_slug_id_access = $force_allow_ids || apply_filters( 'gravityview_custom_entry_slug_allow_id', false );
714 
715  /**
716  * If we're using custom entry slugs, we do a meta value search
717  * instead of doing a straight-up ID search.
718  */
719  if ( $custom_slug ) {
720  // Search for IDs matching $entry_id_or_slug
721  $entry_id = self::get_entry_id_from_slug( $entry_id_or_slug );
722  }
723 
724  // The custom slug search found something; return early.
725  if ( $entry_id ) {
726  return $entry_id;
727  }
728 
729  // If custom slug is off, search using the entry ID
730  // If allow ID access is on, also use entry ID as a backup
731  if ( false === $custom_slug || true === $custom_slug_id_access ) {
732  $entry_id = $entry_id_or_slug;
733  }
734 
735  return $entry_id;
736  }
737 
738  /**
739  * Return a single entry object
740  *
741  * Since 1.4, supports custom entry slugs. The way that GravityView fetches an entry based on the custom slug is by searching `gravityview_unique_id` meta. The `$entry_slug` is fetched by getting the current query var set by `is_single_entry()`
742  *
743  * @param string|int $entry_slug Either entry ID or entry slug string
744  * @param boolean $force_allow_ids Force the get_entry() method to allow passed entry IDs, even if the `gravityview_custom_entry_slug_allow_id` filter returns false.
745  * @param boolean $check_entry_display Check whether the entry is visible for the current View configuration. Default: true. {@since 1.14}
746  * @param \GV\View|null $view The View if $check_entry_display is set to true. In legacy context mocks, can be null. {@since develop}
747  * @return array|boolean
748  */
749  public static function get_entry( $entry_slug, $force_allow_ids = false, $check_entry_display = true, $view = null ) {
750 
751  if ( ! class_exists( 'GFAPI' ) || empty( $entry_slug ) ) {
752  return false;
753  }
754 
755  $entry_id = self::get_entry_id( $entry_slug, $force_allow_ids );
756 
757  if ( empty( $entry_id ) ) {
758  return false;
759  }
760 
761  // fetch the entry
762  $entry = GFAPI::get_entry( $entry_id );
763 
764  /**
765  * @filter `gravityview/common/get_entry/check_entry_display` Override whether to check entry display rules against filters
766  * @since 1.16.2
767  * @since 2.6 Added $view parameter
768  * @param bool $check_entry_display Check whether the entry is visible for the current View configuration. Default: true.
769  * @param array $entry Gravity Forms entry array
770  * @param \GV\View|null $view The View
771  */
772  $check_entry_display = apply_filters( 'gravityview/common/get_entry/check_entry_display', $check_entry_display, $entry, $view );
773 
774  // Is the entry allowed
775  if ( $check_entry_display ) {
776 
777  $gvid = \GV\Utils::_GET( 'gvid' );
778 
779  if ( $gvid ) {
780  $view = \GV\View::by_id( $gvid );
781  }
782 
783  $entry = self::check_entry_display( $entry, $view );
784  }
785 
786  if ( is_wp_error( $entry ) ) {
787  gravityview()->log->error( '{error}', array( 'error' => $entry->get_error_message() ) );
788  return false;
789  }
790 
791  return $entry;
792  }
793 
794  /**
795  * Wrapper for the GFFormsModel::matches_operation() method that adds additional comparisons, including:
796  * 'equals', 'greater_than_or_is', 'greater_than_or_equals', 'less_than_or_is', 'less_than_or_equals',
797  * 'not_contains', 'in', and 'not_in'
798  *
799  * @since 1.13 You can define context, which displays/hides based on what's being displayed (single, multiple, edit)
800  * @since 1.22.1 Added 'in' and 'not_in' for JSON-encoded array values, serialized non-strings
801  *
802  * @see https://docs.gravityview.co/article/252-gvlogic-shortcode
803  * @uses GFFormsModel::matches_operation
804  * @since 1.7.5
805  *
806  * @param mixed $val1 Left side of comparison
807  * @param mixed $val2 Right side of comparison
808  * @param string $operation Type of comparison
809  *
810  * @return bool True: matches, false: not matches
811  */
812  public static function matches_operation( $val1, $val2, $operation ) {
813 
814  // Only process strings
815  $val1 = ! is_string( $val1 ) ? wp_json_encode( $val1 ) : $val1;
816  $val2 = ! is_string( $val2 ) ? wp_json_encode( $val2 ) : $val2;
817 
818  $value = false;
819 
820  if ( 'context' === $val1 ) {
821 
822  $matching_contexts = array( $val2 );
823 
824  // We allow for non-standard contexts.
825  switch ( $val2 ) {
826  // Check for either single or edit
827  case 'singular':
828  $matching_contexts = array( 'single', 'edit' );
829  break;
830  // Use multiple as alias for directory for consistency
831  case 'multiple':
832  $matching_contexts = array( 'directory' );
833  break;
834  }
835 
836  $val1 = in_array( gravityview_get_context(), $matching_contexts ) ? $val2 : false;
837  }
838 
839  // Attempt to parse dates.
842 
843  // If both are timestamps, cast to string so we can use the > and < comparisons below.
844  if ( $timestamp_1 && $timestamp_2 ) {
845  $val1 = (string) $timestamp_1;
846  $val2 = (string) $timestamp_2;
847  }
848 
849  switch ( $operation ) {
850  case 'equals':
851  $value = self::matches_operation( $val1, $val2, 'is' );
852  break;
853  case 'greater_than_or_is':
854  case 'greater_than_or_equals':
855  $is = self::matches_operation( $val1, $val2, 'is' );
856  $gt = self::matches_operation( $val1, $val2, 'greater_than' );
857  $value = ( $is || $gt );
858  break;
859  case 'less_than_or_is':
860  case 'less_than_or_equals':
861  $is = self::matches_operation( $val1, $val2, 'is' );
862  $gt = self::matches_operation( $val1, $val2, 'less_than' );
863  $value = ( $is || $gt );
864  break;
865  case 'not_contains':
866  $contains = self::matches_operation( $val1, $val2, 'contains' );
867  $value = ! $contains;
868  break;
869  /**
870  * @since 1.22.1 Handle JSON-encoded comparisons
871  */
872  case 'in':
873  case 'not_in':
874  $json_val_1 = json_decode( $val1, true );
875  $json_val_2 = json_decode( $val2, true );
876 
877  if ( ! empty( $json_val_1 ) || ! empty( $json_val_2 ) ) {
878 
879  $json_in = false;
880  $json_val_1 = $json_val_1 ? (array) $json_val_1 : array( $val1 );
881  $json_val_2 = $json_val_2 ? (array) $json_val_2 : array( $val2 );
882 
883  // For JSON, we want to compare as "in" or "not in" rather than "contains"
884  foreach ( $json_val_1 as $item_1 ) {
885  foreach ( $json_val_2 as $item_2 ) {
886  $json_in = self::matches_operation( $item_1, $item_2, 'is' );
887 
888  if ( $json_in ) {
889  break 2;
890  }
891  }
892  }
893 
894  $value = ( $operation === 'in' ) ? $json_in : ! $json_in;
895  }
896  break;
897 
898  case 'less_than':
899  case '<':
900  if ( is_string( $val1 ) && is_string( $val2 ) ) {
901  $value = $val1 < $val2;
902  } else {
903  $value = GFFormsModel::matches_operation( $val1, $val2, $operation );
904  }
905  break;
906  case 'greater_than':
907  case '>':
908  if ( is_string( $val1 ) && is_string( $val2 ) ) {
909  $value = $val1 > $val2;
910  } else {
911  $value = GFFormsModel::matches_operation( $val1, $val2, $operation );
912  }
913  break;
914  default:
915  $value = GFFormsModel::matches_operation( $val1, $val2, $operation );
916  }
917 
918  return $value;
919  }
920 
921  /**
922  *
923  * Checks if a certain entry is valid according to the View search filters (specially the Adv Filters)
924  *
925  * @uses GVCommon::calculate_get_entries_criteria();
926  * @see GFFormsModel::is_value_match()
927  *
928  * @since 1.7.4
929  * @since 2.1 Added $view parameter
930  *
931  * @param array $entry Gravity Forms Entry object
932  * @param \GV\View|\GV\View_Collection $view The View or a View Collection
933  *
934  * @return WP_Error|array Returns WP_Error if entry is not valid according to the view search filters (Adv Filter). Returns original $entry value if passes.
935  */
936  public static function check_entry_display( $entry, $view = null ) {
937 
938  if ( ! $entry || is_wp_error( $entry ) ) {
939  return new WP_Error( 'entry_not_found', 'Entry was not found.', $entry );
940  }
941 
942  if ( empty( $entry['form_id'] ) ) {
943  return new WP_Error( 'form_id_not_set', '[apply_filters_to_entry] Entry is empty!', $entry );
944  }
945 
946  if ( is_null( $view ) ) {
947  gravityview()->log->warning( '$view was not supplied to check_entry_display, results will be non-typical.' );
948  return new WP_Error( 'view_not_supplied', 'View is not supplied!', $entry );
949  }
950 
951  if ( ! gravityview()->plugin->supports( \GV\Plugin::FEATURE_GFQUERY ) ) {
952  return new WP_Error( 'no_gf_query', 'GF_Query is missing.', $entry );
953  }
954 
955  $_gvid = \GV\Utils::_GET( 'gvid' );
956 
957  if ( $_gvid && $view->ID !== (int) $_gvid ) {
958  return new WP_Error( 'view_id_not_match_gvid', 'View does not match passed $_GET["gvid"].', $view->ID );
959  }
960 
961  $view_form_id = $view->form->ID;
962 
963  if ( $view->joins ) {
964  if ( in_array( (int) $entry['form_id'], array_keys( $view::get_joined_forms( $view->ID ) ), true ) ) {
965  $view_form_id = $entry['form_id'];
966  }
967  }
968 
969  if ( (int) $view_form_id !== (int) $entry['form_id'] ) {
970  return new WP_Error( 'view_id_not_match', 'View form source does not match entry form source ID.', $entry );
971  }
972 
973  /**
974  * Check whether the entry is in the entries subset by running a modified query.
975  */
976  add_action(
977  'gravityview/view/query',
978  $entry_subset_callback = function( &$query, $view, $request ) use ( $entry, $view_form_id ) {
979  $_tmp_query = new \GF_Query(
980  $view_form_id,
981  array(
982  'field_filters' => array(
983  'mode' => 'all',
984  array(
985  'key' => 'id',
986  'operation' => 'is',
987  'value' => $entry['id'],
988  ),
989  ),
990  )
991  );
992 
993  $_tmp_query_parts = $_tmp_query->_introspect();
994 
995  /** @type \GF_Query $query */
996  $query_parts = $query->_introspect();
997 
998  $query->where( \GF_Query_Condition::_and( $_tmp_query_parts['where'], $query_parts['where'] ) );
999 
1000  },
1001  10,
1002  3
1003  );
1004 
1005  // Prevent page offset from being applied to the single entry query; it's used to return to the referring page number
1006  add_filter(
1007  'gravityview_search_criteria',
1008  $remove_pagenum = function( $criteria ) {
1009 
1010  $criteria['paging'] = array(
1011  'offset' => 0,
1012  'page_size' => 25,
1013  );
1014 
1015  return $criteria;
1016  }
1017  );
1018 
1019  $entries = $view->get_entries()->all();
1020 
1021  // Remove the modifying filter
1022  remove_filter( 'gravityview_search_criteria', $remove_pagenum );
1023 
1024  if ( ! $entries ) {
1025  remove_action( 'gravityview/view/query', $entry_subset_callback );
1026  return new \WP_Error( 'failed_criteria', 'Entry failed search_criteria and field_filters' );
1027  }
1028 
1029  // This entry is on a View with joins
1030  if ( $entries[0]->is_multi() ) {
1031 
1032  $multi_entry_ids = array();
1033 
1034  foreach ( $entries[0]->entries as $multi_entry ) {
1035  $multi_entry_ids[] = (int) $multi_entry->ID;
1036  }
1037 
1038  if ( ! in_array( (int) $entry['id'], $multi_entry_ids, true ) ) {
1039  remove_action( 'gravityview/view/query', $entry_subset_callback );
1040  return new \WP_Error( 'failed_criteria', 'Entry failed search_criteria and field_filters' );
1041  }
1042  } elseif ( (int) $entries[0]->ID !== (int) $entry['id'] ) {
1043  remove_action( 'gravityview/view/query', $entry_subset_callback );
1044  return new \WP_Error( 'failed_criteria', 'Entry failed search_criteria and field_filters' );
1045  }
1046 
1047  remove_action( 'gravityview/view/query', $entry_subset_callback );
1048  return $entry;
1049  }
1050 
1051 
1052  /**
1053  * Allow formatting date and time based on GravityView standards
1054  *
1055  * @since 1.16
1056  *
1057  * @see GVCommon_Test::test_format_date for examples
1058  *
1059  * @param string $date_string The date as stored by Gravity Forms (`Y-m-d h:i:s` GMT)
1060  * @param string|array $args Array or string of settings for output parsed by `wp_parse_args()`; Can use `raw=1` or `array('raw' => true)` \n
1061  * - `raw` Un-formatted date string in original `Y-m-d h:i:s` format
1062  * - `timestamp` Integer timestamp returned by GFCommon::get_local_timestamp()
1063  * - `diff` "%s ago" format, unless other `format` is defined
1064  * - `human` Set $is_human parameter to true for `GFCommon::format_date()`. Shows `diff` within 24 hours or date after. Format based on blog setting, unless `format` is defined.
1065  * - `time` Include time in the `GFCommon::format_date()` output
1066  * - `format` Define your own date format, or `diff` format
1067  *
1068  * @return int|null|string Formatted date based on the original date
1069  */
1070  public static function format_date( $date_string = '', $args = array() ) {
1071 
1072  $default_atts = array(
1073  'raw' => false,
1074  'timestamp' => false,
1075  'diff' => false,
1076  'human' => false,
1077  'format' => '',
1078  'time' => false,
1079  );
1080 
1081  $atts = wp_parse_args( $args, $default_atts );
1082 
1083  /**
1084  * Gravity Forms code to adjust date to locally-configured Time Zone
1085  *
1086  * @see GFCommon::format_date() for original code
1087  */
1088  $date_gmt_time = mysql2date( 'G', $date_string );
1089  $date_local_timestamp = GFCommon::get_local_timestamp( $date_gmt_time );
1090 
1091  $format = \GV\Utils::get( $atts, 'format' );
1092  $is_human = ! empty( $atts['human'] );
1093  $is_diff = ! empty( $atts['diff'] );
1094  $is_raw = ! empty( $atts['raw'] );
1095  $is_timestamp = ! empty( $atts['timestamp'] );
1096  $include_time = ! empty( $atts['time'] );
1097 
1098  // If we're using time diff, we want to have a different default format
1099  if ( empty( $format ) ) {
1100  /* translators: %s: relative time from now, used for generic date comparisons. "1 day ago", or "20 seconds ago" */
1101  $format = $is_diff ? esc_html__( '%s ago', 'gk-gravityview' ) : get_option( 'date_format' );
1102  }
1103 
1104  // If raw was specified, don't modify the stored value
1105  if ( $is_raw ) {
1106  $formatted_date = $date_string;
1107  } elseif ( $is_timestamp ) {
1108  $formatted_date = $date_local_timestamp;
1109  } elseif ( $is_diff ) {
1110  $formatted_date = sprintf( $format, human_time_diff( $date_gmt_time ) );
1111  } else {
1112  $formatted_date = GFCommon::format_date( $date_string, $is_human, $format, $include_time );
1113  }
1114 
1115  unset( $format, $is_diff, $is_human, $is_timestamp, $is_raw, $date_gmt_time, $date_local_timestamp, $default_atts );
1116 
1117  return $formatted_date;
1118  }
1119 
1120  /**
1121  * Retrieve the label of a given field id (for a specific form)
1122  *
1123  * @since 1.17 Added $field_value parameter
1124  *
1125  * @param array $form Gravity Forms form array
1126  * @param string $field_id ID of the field. If an input, full input ID (like `1.3`)
1127  * @param string|array $field_value Raw value of the field.
1128  * @return string
1129  */
1130  public static function get_field_label( $form = array(), $field_id = '', $field_value = '' ) {
1131 
1132  if ( empty( $form ) || empty( $field_id ) ) {
1133  return '';
1134  }
1135 
1136  $field = self::get_field( $form, $field_id );
1137 
1138  $label = \GV\Utils::get( $field, 'label' );
1139 
1140  if ( floor( $field_id ) !== floatval( $field_id ) ) {
1141  $label = GFFormsModel::get_choice_text( $field, $field_value, $field_id );
1142  }
1143 
1144  return $label;
1145  }
1146 
1147 
1148  /**
1149  * Returns the field details array of a specific form given the field id
1150  *
1151  * Alias of GFFormsModel::get_field
1152  *
1153  * @since 1.19 Allow passing form ID as well as form array
1154  *
1155  * @uses GFFormsModel::get_field
1156  * @see GFFormsModel::get_field
1157  * @param array|int $form Form array or ID
1158  * @param string|int $field_id
1159  * @return GF_Field|null Gravity Forms field object, or NULL: Gravity Forms GFFormsModel does not exist or field at $field_id doesn't exist.
1160  */
1161  public static function get_field( $form, $field_id ) {
1162  $field = GFAPI::get_field( $form, $field_id );
1163 
1164  // Maintain previous behavior by returning null instead of false.
1165  return $field ? $field : null;
1166  }
1167 
1168 
1169  /**
1170  * Check whether the post is GravityView
1171  *
1172  * - Check post type. Is it `gravityview`?
1173  * - Check shortcode
1174  *
1175  * @param WP_Post $post WordPress post object
1176  * @return boolean True: yep, GravityView; No: not!
1177  */
1178  public static function has_gravityview_shortcode( $post = null ) {
1179  if ( ! is_a( $post, 'WP_Post' ) ) {
1180  return false;
1181  }
1182 
1183  if ( 'gravityview' === get_post_type( $post ) ) {
1184  return true;
1185  }
1186 
1187  return self::has_shortcode_r( $post->post_content, 'gravityview' ) ? true : false;
1188 
1189  }
1190 
1191 
1192  /**
1193  * Placeholder until the recursive has_shortcode() patch is merged
1194  *
1195  * @see https://core.trac.wordpress.org/ticket/26343#comment:10
1196  * @param string $content Content to check whether there's a shortcode
1197  * @param string $tag Current shortcode tag
1198  */
1199  public static function has_shortcode_r( $content, $tag = 'gravityview' ) {
1200  if ( false === strpos( $content, '[' ) ) {
1201  return false;
1202  }
1203 
1204  if ( shortcode_exists( $tag ) ) {
1205 
1206  $shortcodes = array();
1207 
1208  preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER );
1209  if ( empty( $matches ) ) {
1210  return false;
1211  }
1212 
1213  foreach ( $matches as $shortcode ) {
1214  if ( $tag === $shortcode[2] ) {
1215 
1216  // Changed this to $shortcode instead of true so we get the parsed atts.
1217  $shortcodes[] = $shortcode;
1218 
1219  } elseif ( isset( $shortcode[5] ) && $results = self::has_shortcode_r( $shortcode[5], $tag ) ) {
1220  foreach ( $results as $result ) {
1221  $shortcodes[] = $result;
1222  }
1223  }
1224  }
1225 
1226  return $shortcodes;
1227  }
1228  return false;
1229  }
1230 
1231 
1232 
1233  /**
1234  * Get the views for a particular form
1235  *
1236  * @since 1.15.2 Add $args array and limit posts_per_page to 500
1237  *
1238  * @uses get_posts()
1239  *
1240  * @param int $form_id Gravity Forms form ID
1241  * @param array $args Pass args sent to get_posts()
1242  *
1243  * @return array Array with view details, as returned by get_posts()
1244  */
1245  public static function get_connected_views( $form_id, $args = array() ) {
1246 
1247  global $wpdb;
1248 
1249  $defaults = array(
1250  'post_type' => 'gravityview',
1251  'posts_per_page' => 100,
1252  'meta_key' => '_gravityview_form_id',
1253  'meta_value' => (int) $form_id,
1254  );
1255  $args = wp_parse_args( $args, $defaults );
1256  $views = get_posts( $args );
1257 
1258  $views_with_joins = $wpdb->get_results( "SELECT `post_id`, `meta_value` FROM $wpdb->postmeta WHERE `meta_key` = '_gravityview_form_joins'" );
1259 
1260  $joined_forms = array();
1261  foreach ( $views_with_joins as $view ) {
1262 
1263  $data = unserialize( $view->meta_value );
1264 
1265  if ( ! $data || ! is_array( $data ) ) {
1266  continue;
1267  }
1268 
1269  foreach ( $data as $datum ) {
1270  if ( ! empty( $datum[2] ) && (int) $datum[2] === (int) $form_id ) {
1271  $joined_forms[] = $view->post_id;
1272  }
1273  }
1274  }
1275 
1276  if ( $joined_forms ) {
1277  $joined_args = array(
1278  'post_type' => 'gravityview',
1279  'posts_per_page' => $args['posts_per_page'],
1280  'post__in' => $joined_forms,
1281  );
1282  $views = array_merge( $views, get_posts( $joined_args ) );
1283  }
1284 
1285  return $views;
1286  }
1287 
1288  /**
1289  * Get the Gravity Forms form ID connected to a View
1290  *
1291  * @param int $view_id The ID of the View to get the connected form of
1292  *
1293  * @return false|string ID of the connected Form, if exists. Empty string if not. False if not the View ID isn't valid.
1294  */
1295  public static function get_meta_form_id( $view_id ) {
1296  return get_post_meta( $view_id, '_gravityview_form_id', true );
1297  }
1298 
1299  /**
1300  * Get the template ID (`list`, `table`, `datatables`, `map`) for a View
1301  *
1302  * @see GravityView_Template::template_id
1303  *
1304  * @param int $view_id The ID of the View to get the layout of
1305  *
1306  * @return string GravityView_Template::template_id value. Empty string if not.
1307  */
1308  public static function get_meta_template_id( $view_id ) {
1309  return get_post_meta( $view_id, '_gravityview_directory_template', true );
1310  }
1311 
1312 
1313  /**
1314  * Get all the settings for a View
1315  *
1316  * @uses \GV\View_Settings::defaults() Parses the settings with the plugin defaults as backups.
1317  * @param int $post_id View ID
1318  * @return array Associative array of settings with plugin defaults used if not set by the View
1319  */
1320  public static function get_template_settings( $post_id ) {
1321 
1322  $settings = get_post_meta( $post_id, '_gravityview_template_settings', true );
1323 
1324  if ( class_exists( '\GV\View_Settings' ) ) {
1325 
1326  return wp_parse_args( (array) $settings, \GV\View_Settings::defaults() );
1327 
1328  }
1329 
1330  // Backup, in case GravityView_View_Data isn't loaded yet.
1331  return $settings;
1332  }
1333 
1334  /**
1335  * Get the setting for a View
1336  *
1337  * If the setting isn't set by the View, it returns the plugin default.
1338  *
1339  * @param int $post_id View ID
1340  * @param string $key Key for the setting
1341  * @return mixed|null Setting value, or NULL if not set.
1342  */
1343  public static function get_template_setting( $post_id, $key ) {
1344 
1345  $settings = self::get_template_settings( $post_id );
1346 
1347  if ( isset( $settings[ $key ] ) ) {
1348  return $settings[ $key ];
1349  }
1350 
1351  return null;
1352  }
1353 
1354  /**
1355  * Get the field configuration for the View
1356  *
1357  * array(
1358  *
1359  * [other zones]
1360  *
1361  * 'directory_list-title' => array(
1362  *
1363  * [other fields]
1364  *
1365  * '5372653f25d44' => array(
1366  * 'id' => string '9' (length=1)
1367  * 'label' => string 'Screenshots' (length=11)
1368  * 'show_label' => string '1' (length=1)
1369  * 'custom_label' => string '' (length=0)
1370  * 'custom_class' => string 'gv-gallery' (length=10)
1371  * 'only_loggedin' => string '0' (length=1)
1372  * 'only_loggedin_cap' => string 'read' (length=4)
1373  * )
1374  *
1375  * [other fields]
1376  * )
1377  *
1378  * [other zones]
1379  * )
1380  *
1381  * @since 1.17.4 Added $apply_filter parameter.
1382  * @since 2.17 Added $form_id parameter.
1383  *
1384  * @param int $post_id View ID.
1385  * @param bool $apply_filter Whether to apply the `gravityview/configuration/fields` filter [Default: true]
1386  * @return array Multi-array of fields with first level being the field zones. See code comment.
1387  */
1388  public static function get_directory_fields( $post_id, $apply_filter = true, $form_id = 0 ) {
1389  $fields = get_post_meta( $post_id, '_gravityview_directory_fields', true );
1390 
1391  if ( $apply_filter ) {
1392  /**
1393  * @filter `gravityview/configuration/fields` Filter the View fields' configuration array
1394  * @since 1.6.5
1395  * @since 2.16.3 Added the $form_id parameter.
1396  *
1397  * @param $fields array Multi-array of fields with first level being the field zones
1398  * @param $post_id int Post ID
1399  * @param int $form_id The main form ID for the View.
1400  */
1401  $fields = apply_filters( 'gravityview/configuration/fields', $fields, $post_id, $form_id );
1402 
1403  /**
1404  * @filter `gravityview/view/configuration/fields` Filter the View fields' configuration array.
1405  * @since 2.0
1406  * @since 2.16.3 Added the $form_id parameter.
1407  *
1408  * @param array $fields Multi-array of fields with first level being the field zones.
1409  * @param \GV\View $view The View the fields are being pulled for.
1410  * @param int $form_id The main form ID for the View.
1411  */
1412  $fields = apply_filters( 'gravityview/view/configuration/fields', $fields, \GV\View::by_id( $post_id ), $form_id );
1413  }
1414 
1415  return $fields;
1416  }
1417 
1418  /**
1419  * Get the widget configuration for a View
1420  *
1421  * @param int $view_id View ID
1422  * @param bool $json_decode Whether to JSON-decode the widget values. Default: `false`
1423  *
1424  * @return array Multi-array of widgets, with the slug of each widget "zone" being the key ("header_top"), and each widget having their own "id"
1425  */
1426  public static function get_directory_widgets( $view_id, $json_decode = false ) {
1427 
1428  $view_widgets = get_post_meta( $view_id, '_gravityview_directory_widgets', true );
1429 
1430  $defaults = array(
1431  'header_top' => array(),
1432  'header_left' => array(),
1433  'header_right' => array(),
1434  'footer_left' => array(),
1435  'footer_right' => array(),
1436  );
1437 
1438  $directory_widgets = wp_parse_args( $view_widgets, $defaults );
1439 
1440  if ( $json_decode ) {
1441  $directory_widgets = gv_map_deep( $directory_widgets, 'gv_maybe_json_decode' );
1442  }
1443 
1444  return $directory_widgets;
1445  }
1446 
1447 
1448  /**
1449  * Render dropdown (select) with the list of sortable fields from a form ID
1450  *
1451  * @param int $formid Form ID
1452  * @return string html
1453  */
1454  public static function get_sortable_fields( $formid, $current = '' ) {
1455  $output = '<option value="" ' . selected( '', $current, false ) . '>' . esc_html__( 'Default (Entry ID)', 'gk-gravityview' ) . '</option>';
1456 
1457  if ( empty( $formid ) ) {
1458  return $output;
1459  }
1460 
1461  $fields = self::get_sortable_fields_array( $formid );
1462 
1463  if ( ! empty( $fields ) ) {
1464 
1465  $blocklist_field_types = array( 'list', 'textarea' );
1466 
1467  $blocklist_field_types = apply_filters_deprecated( 'gravityview_blacklist_field_types', array( $blocklist_field_types, null ), '2.14', 'gravityview_blocklist_field_types' );
1468 
1469  $blocklist_field_types = apply_filters( 'gravityview_blocklist_field_types', $blocklist_field_types, null );
1470 
1471  foreach ( $fields as $id => $field ) {
1472  if ( in_array( $field['type'], $blocklist_field_types ) ) {
1473  continue;
1474  }
1475 
1476  $output .= '<option value="' . $id . '" ' . selected( $id, $current, false ) . '>' . esc_attr( $field['label'] ) . '</option>';
1477  }
1478  }
1479 
1480  return $output;
1481  }
1482 
1483  /**
1484  *
1485  * @param int $formid Gravity Forms form ID
1486  * @param array $blocklist Field types to exclude
1487  *
1488  * @since 1.8
1489  *
1490  * @todo Get all fields, check if sortable dynamically
1491  *
1492  * @return array
1493  */
1494  public static function get_sortable_fields_array( $formid, $blocklist = array( 'list', 'textarea' ) ) {
1495 
1496  // Get fields with sub-inputs and no parent
1497  $fields = self::get_form_fields( $formid, true, false );
1498 
1499  $date_created = array(
1500  'date_created' => array(
1501  'type' => 'date_created',
1502  'label' => __( 'Date Created', 'gk-gravityview' ),
1503  ),
1504  'date_updated' => array(
1505  'type' => 'date_updated',
1506  'label' => __( 'Date Updated', 'gk-gravityview' ),
1507  ),
1508  );
1509 
1510  $fields = $date_created + $fields;
1511 
1512  $blocklist_field_types = $blocklist;
1513 
1514  $blocklist_field_types = apply_filters_deprecated( 'gravityview_blacklist_field_types', array( $blocklist_field_types, null ), '2.14', 'gravityview_blocklist_field_types' );
1515 
1516  $blocklist_field_types = apply_filters( 'gravityview_blocklist_field_types', $blocklist_field_types, null );
1517 
1518  // TODO: Convert to using array_filter
1519  foreach ( $fields as $id => $field ) {
1520 
1521  if ( in_array( $field['type'], $blocklist_field_types ) ) {
1522  unset( $fields[ $id ] );
1523  }
1524 
1525  /**
1526  * Merge date and time subfields.
1527  */
1528  if ( in_array( $field['type'], array( 'date', 'time' ) ) && ! empty( $field['parent'] ) ) {
1529  $fields[ intval( $id ) ] = array(
1530  'label' => \GV\Utils::get( $field, 'parent/label' ),
1531  'parent' => null,
1532  'type' => \GV\Utils::get( $field, 'parent/type' ),
1533  'adminLabel' => \GV\Utils::get( $field, 'parent/adminLabel' ),
1534  'adminOnly' => \GV\Utils::get( $field, 'parent/adminOnly' ),
1535  );
1536 
1537  unset( $fields[ $id ] );
1538  }
1539  }
1540 
1541  /**
1542  * @filter `gravityview/common/sortable_fields` Filter the sortable fields
1543  * @since 1.12
1544  * @param array $fields Sub-set of GF form fields that are sortable
1545  * @param int $formid The Gravity Forms form ID that the fields are from
1546  */
1547  $fields = apply_filters( 'gravityview/common/sortable_fields', $fields, $formid );
1548 
1549  return $fields;
1550  }
1551 
1552  /**
1553  * Returns the GF Form field type for a certain field(id) of a form
1554  *
1555  * @param object $form Gravity Forms form
1556  * @param mixed $field_id Field ID or Field array
1557  * @return string field type
1558  */
1559  public static function get_field_type( $form = null, $field_id = '' ) {
1560 
1561  if ( ! empty( $field_id ) && ! is_array( $field_id ) ) {
1562  $field = self::get_field( $form, $field_id );
1563  } else {
1564  $field = $field_id;
1565  }
1566 
1567  return class_exists( 'RGFormsModel' ) ? RGFormsModel::get_input_type( $field ) : '';
1568 
1569  }
1570 
1571 
1572  /**
1573  * Checks if the field type is a 'numeric' field type (e.g. to be used when sorting)
1574  *
1575  * @param int|array $form form ID or form array
1576  * @param int|array $field field key or field array
1577  * @return boolean
1578  */
1579  public static function is_field_numeric( $form = null, $field = '' ) {
1580 
1581  if ( ! is_array( $form ) && ! is_array( $field ) ) {
1582  $form = self::get_form( $form );
1583  }
1584 
1585  // If entry meta, it's a string. Otherwise, numeric
1586  if ( ! is_numeric( $field ) && is_string( $field ) ) {
1587  $type = $field;
1588  } else {
1589  $type = self::get_field_type( $form, $field );
1590  }
1591 
1592  /**
1593  * @filter `gravityview/common/numeric_types` What types of fields are numeric?
1594  * @since 1.5.2
1595  * @param array $numeric_types Fields that are numeric. Default: `[ number, time ]`
1596  */
1597  $numeric_types = apply_filters( 'gravityview/common/numeric_types', array( 'number', 'time' ) );
1598 
1599  // Defer to GravityView_Field setting, if the field type is registered and `is_numeric` is true
1600  if ( $gv_field = GravityView_Fields::get( $type ) ) {
1601  if ( true === $gv_field->is_numeric ) {
1602  $numeric_types[] = $gv_field->is_numeric;
1603  }
1604  }
1605 
1606  $return = in_array( $type, $numeric_types );
1607 
1608  return $return;
1609  }
1610 
1611  /**
1612  * Encrypt content using Javascript so that it's hidden when JS is disabled.
1613  *
1614  * This is mostly used to hide email addresses from scraper bots.
1615  *
1616  * @param string $content Content to encrypt
1617  * @param string $message Message shown if Javascript is disabled
1618  *
1619  * @see https://github.com/katzwebservices/standalone-phpenkoder StandalonePHPEnkoder on Github
1620  *
1621  * @since 1.7
1622  *
1623  * @return string Content, encrypted
1624  */
1625  public static function js_encrypt( $content, $message = '' ) {
1626 
1627  $output = $content;
1628 
1629  if ( ! class_exists( 'StandalonePHPEnkoder' ) ) {
1630  include_once GRAVITYVIEW_DIR . 'includes/lib/StandalonePHPEnkoder.php';
1631  }
1632 
1633  if ( class_exists( 'StandalonePHPEnkoder' ) ) {
1634 
1635  $enkoder = new StandalonePHPEnkoder();
1636 
1637  $message = empty( $message ) ? __( 'Email hidden; Javascript is required.', 'gk-gravityview' ) : $message;
1638 
1639  /**
1640  * @filter `gravityview/phpenkoder/msg` Modify the message shown when Javascript is disabled and an encrypted email field is displayed
1641  * @since 1.7
1642  * @param string $message Existing message
1643  * @param string $content Content to encrypt
1644  */
1645  $enkoder->enkode_msg = apply_filters( 'gravityview/phpenkoder/msg', $message, $content );
1646 
1647  $output = $enkoder->enkode( $content );
1648  }
1649 
1650  return $output;
1651  }
1652 
1653  /**
1654  *
1655  * Do the same than parse_str without max_input_vars limitation:
1656  * Parses $string as if it were the query string passed via a URL and sets variables in the current scope.
1657  *
1658  * @param $string string string to parse (not altered like in the original parse_str(), use the second parameter!)
1659  * @param $result array If the second parameter is present, variables are stored in this variable as array elements
1660  * @return bool true or false if $string is an empty string
1661  * @since 1.5.3
1662  *
1663  * @see https://gist.github.com/rubo77/6821632
1664  **/
1665  public static function gv_parse_str( $string, &$result ) {
1666  if ( empty( $string ) ) {
1667  return false;
1668  }
1669 
1670  $result = array();
1671 
1672  // find the pairs "name=value"
1673  $pairs = explode( '&', $string );
1674 
1675  foreach ( $pairs as $pair ) {
1676  // use the original parse_str() on each element
1677  parse_str( $pair, $params );
1678 
1679  $k = key( $params );
1680  if ( ! isset( $result[ $k ] ) ) {
1681  $result += $params;
1682  } elseif ( array_key_exists( $k, $params ) && is_array( $params[ $k ] ) ) {
1683  $result[ $k ] = self::array_merge_recursive_distinct( $result[ $k ], $params[ $k ] );
1684  }
1685  }
1686  return true;
1687  }
1688 
1689 
1690  /**
1691  * Generate an HTML anchor tag with a list of supported attributes
1692  *
1693  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a Supported attributes defined here
1694  * @uses esc_url_raw() to sanitize $href
1695  * @uses esc_attr() to sanitize $atts
1696  *
1697  * @since 1.6
1698  *
1699  * @param string $href URL of the link. Sanitized using `esc_url_raw()`
1700  * @param string $anchor_text The text or HTML inside the anchor. This is not sanitized in the function.
1701  * @param array|string $atts Attributes to be added to the anchor tag. Parsed by `wp_parse_args()`, sanitized using `esc_attr()`
1702  *
1703  * @return string HTML output of anchor link. If empty $href, returns NULL
1704  */
1705  public static function get_link_html( $href = '', $anchor_text = '', $atts = array() ) {
1706 
1707  // Supported attributes for anchor tags. HREF left out intentionally.
1708  $allowed_atts = array(
1709  'href' => null, // Will override the $href argument if set
1710  'title' => null,
1711  'rel' => null,
1712  'id' => null,
1713  'class' => null,
1714  'target' => null,
1715  'style' => null,
1716 
1717  // Used by GravityView
1718  'data-viewid' => null,
1719 
1720  // Not standard
1721  'hreflang' => null,
1722  'type' => null,
1723  'tabindex' => null,
1724 
1725  // Deprecated HTML4 but still used
1726  'name' => null,
1727  'onclick' => null,
1728  'onchange' => null,
1729  'onkeyup' => null,
1730 
1731  // HTML5 only
1732  'download' => null,
1733  'media' => null,
1734  'ping' => null,
1735  );
1736 
1737  /**
1738  * @filter `gravityview/get_link/allowed_atts` Modify the attributes that are allowed to be used in generating links
1739  * @since 1.6
1740  * @param array $allowed_atts Array of attributes allowed
1741  */
1742  $allowed_atts = apply_filters( 'gravityview/get_link/allowed_atts', $allowed_atts );
1743 
1744  // Make sure the attributes are formatted as array
1745  $passed_atts = wp_parse_args( $atts );
1746 
1747  // Make sure the allowed attributes are only the ones in the $allowed_atts list
1748  $final_atts = shortcode_atts( $allowed_atts, $passed_atts );
1749 
1750  // Remove attributes with empty values
1751  $final_atts = array_filter( $final_atts );
1752 
1753  // If the href wasn't passed as an attribute, use the value passed to the function
1754  if ( empty( $final_atts['href'] ) && ! empty( $href ) ) {
1755  $final_atts['href'] = $href;
1756  }
1757 
1758  if ( isset( $final_atts['href'] ) ) {
1759  $final_atts['href'] = esc_url_raw( $final_atts['href'] );
1760  }
1761 
1762  /**
1763  * Fix potential security issue with target=_blank
1764  *
1765  * @see https://dev.to/ben/the-targetblank-vulnerability-by-example
1766  */
1767  if ( '_blank' === \GV\Utils::get( $final_atts, 'target' ) ) {
1768  $final_atts['rel'] = trim( \GV\Utils::get( $final_atts, 'rel', '' ) . ' noopener noreferrer' );
1769  }
1770 
1771  // Sort the attributes alphabetically, to help testing
1772  ksort( $final_atts );
1773 
1774  // For each attribute, generate the code
1775  $output = '';
1776  foreach ( $final_atts as $attr => $value ) {
1777  $output .= sprintf( ' %s="%s"', $attr, esc_attr( $value ) );
1778  }
1779 
1780  if ( '' !== $output ) {
1781  $output = '<a' . $output . '>' . $anchor_text . '</a>';
1782  }
1783 
1784  return $output;
1785  }
1786 
1787  /**
1788  * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
1789  * keys to arrays rather than overwriting the value in the first array with the duplicate
1790  * value in the second array, as array_merge does.
1791  *
1792  * @see http://php.net/manual/en/function.array-merge-recursive.php
1793  *
1794  * @since 1.5.3
1795  * @param array $array1
1796  * @param array $array2
1797  * @return array
1798  * @author Daniel <[email protected]>
1799  * @author Gabriel Sobrinho <[email protected]>
1800  */
1801  public static function array_merge_recursive_distinct( array &$array1, array &$array2 ) {
1802  $merged = $array1;
1803  foreach ( $array2 as $key => $value ) {
1804  if ( is_array( $value ) && isset( $merged[ $key ] ) && is_array( $merged[ $key ] ) ) {
1805  $merged[ $key ] = self::array_merge_recursive_distinct( $merged[ $key ], $value );
1806  } elseif ( is_numeric( $key ) && isset( $merged[ $key ] ) ) {
1807  $merged[] = $value;
1808  } else {
1809  $merged[ $key ] = $value;
1810  }
1811  }
1812 
1813  return $merged;
1814  }
1815 
1816  /**
1817  * Get WordPress users with reasonable limits set
1818  *
1819  * @param string $context Where are we using this information (e.g. change_entry_creator, search_widget ..)
1820  * @param array $args Arguments to modify the user query. See get_users() {@since 1.14}
1821  * @return array Array of WP_User objects.
1822  */
1823  public static function get_users( $context = 'change_entry_creator', $args = array() ) {
1824 
1825  $default_args = array(
1826  'number' => 2000,
1827  'orderby' => 'display_name',
1828  'order' => 'ASC',
1829  'fields' => array( 'ID', 'display_name', 'user_login', 'user_nicename' ),
1830  );
1831 
1832  // Merge in the passed arg
1833  $get_users_settings = wp_parse_args( $args, $default_args );
1834 
1835  /**
1836  * @filter `gravityview/get_users/{$context}` There are issues with too many users using [get_users()](http://codex.wordpress.org/Function_Reference/get_users) where it breaks the select. We try to keep it at a reasonable number. \n
1837  * `$context` is where are we using this information (e.g. change_entry_creator, search_widget ..)
1838  * @param array $settings Settings array, with `number` key defining the # of users to display
1839  */
1840  $get_users_settings = apply_filters( 'gravityview/get_users/' . $context, apply_filters( 'gravityview_change_entry_creator_user_parameters', $get_users_settings ) );
1841 
1842  return get_users( $get_users_settings );
1843  }
1844 
1845 
1846  /**
1847  * Display updated/error notice
1848  *
1849  * @since 1.19.2 Added $cap and $object_id parameters
1850  *
1851  * @param string $notice text/HTML of notice
1852  * @param string $class CSS class for notice (`updated` or `error`)
1853  * @param string $cap [Optional] Define a capability required to show a notice. If not set, displays to all caps.
1854  *
1855  * @return string
1856  */
1857  public static function generate_notice( $notice, $class = '', $cap = '', $object_id = null ) {
1858 
1859  // If $cap is defined, only show notice if user has capability
1860  if ( $cap && ! self::has_cap( $cap, $object_id ) ) {
1861  return '';
1862  }
1863 
1864  return '<div class="gv-notice ' . gravityview_sanitize_html_class( $class ) . '">' . $notice . '</div>';
1865  }
1866 
1867  /**
1868  * Inspired on \GFCommon::encode_shortcodes, reverse the encoding by replacing the ascii characters by the shortcode brackets
1869  *
1870  * @since 1.16.5
1871  * @param string $string Input string to decode
1872  * @return string $string Output string
1873  */
1874  public static function decode_shortcodes( $string ) {
1875  $replace = array( '[', ']', '"' );
1876  $find = array( '&#91;', '&#93;', '&quot;' );
1877  $string = str_replace( $find, $replace, $string );
1878 
1879  return $string;
1880  }
1881 
1882 
1883  /**
1884  * Send email using GFCommon::send_email()
1885  *
1886  * @since 1.17
1887  *
1888  * @see GFCommon::send_email This just makes the method public
1889  *
1890  * @param string $from Sender address (required)
1891  * @param string $to Recipient address (required)
1892  * @param string $bcc BCC recipients (required)
1893  * @param string $reply_to Reply-to address (required)
1894  * @param string $subject Subject line (required)
1895  * @param string $message Message body (required)
1896  * @param string $from_name Displayed name of the sender
1897  * @param string $message_format If "html", sent text as `text/html`. Otherwise, `text/plain`. Default: "html".
1898  * @param string|array $attachments Optional. Files to attach. {@see wp_mail()} for usage. Default: "".
1899  * @param array|false $entry Gravity Forms entry array, related to the email. Default: false.
1900  * @param array|false $notification Gravity Forms notification that triggered the email. {@see GFCommon::send_notification}. Default:false.
1901  */
1902  public static function send_email( $from, $to, $bcc, $reply_to, $subject, $message, $from_name = '', $message_format = 'html', $attachments = '', $entry = false, $notification = false ) {
1903 
1904  $SendEmail = new ReflectionMethod( 'GFCommon', 'send_email' );
1905 
1906  // It was private; let's make it public
1907  $SendEmail->setAccessible( true );
1908 
1909  // Required: $from, $to, $bcc, $replyTo, $subject, $message
1910  // Optional: $from_name, $message_format, $attachments, $lead, $notification
1911  $SendEmail->invoke( new GFCommon(), $from, $to, $bcc, $reply_to, $subject, $message, $from_name, $message_format, $attachments, $entry, $notification );
1912  }
1913 
1914 
1915 }//end class
1916 
1917 
1918 /**
1919  * Generate an HTML anchor tag with a list of supported attributes
1920  *
1921  * @see GVCommon::get_link_html()
1922  *
1923  * @since 1.6
1924  *
1925  * @param string $href URL of the link.
1926  * @param string $anchor_text The text or HTML inside the anchor. This is not sanitized in the function.
1927  * @param array|string $atts Attributes to be added to the anchor tag
1928  *
1929  * @return string HTML output of anchor link. If empty $href, returns NULL
1930  */
1931 function gravityview_get_link( $href = '', $anchor_text = '', $atts = array() ) {
1932  return GVCommon::get_link_html( $href, $anchor_text, $atts );
1933 }
const GRAVITYVIEW_DIR
"GRAVITYVIEW_DIR" "./" The absolute path to the plugin directory, with trailing slash ...
Definition: gravityview.php:49
static get_entry_meta( $form_id, $only_default_column=true)
get extra fields from entry meta
static has_product_field( $form=array())
Check whether a form has product fields.
static has_shortcode_r( $content, $tag='gravityview')
Placeholder until the recursive has_shortcode() patch is merged.
static js_encrypt( $content, $message='')
Encrypt content using Javascript so that it&#39;s hidden when JS is disabled.
static get_directory_fields( $post_id, $apply_filter=true, $form_id=0)
Get the field configuration for the View.
static _GET( $name, $default=null)
Grab a value from the _GET superglobal or default.
gravityview_maybe_convert_date_string_to_timestamp( $value='')
Convert a string to a timestamp if it&#39;s a valid date or a relative date prefixed with "relative:"...
$forms
Definition: data-source.php:19
static get_entry_id_from_slug( $slug)
Get the entry ID from the entry slug, which may or may not be the entry ID.
static array_merge_recursive_distinct(array &$array1, array &$array2)
array_merge_recursive does indeed merge arrays, but it converts values with duplicate keys to arrays ...
static get_directory_widgets( $view_id, $json_decode=false)
Get the widget configuration for a View.
static get_connected_views( $form_id, $args=array())
Get the views for a particular form.
static get_form_fields( $form='', $add_default_properties=false, $include_parent_field=true)
Return array of fields&#39; id and label, for a given Form ID.
static entry_has_transaction_data( $entry=array())
Check if an entry has transaction data.
static calculate_get_entries_criteria( $passed_criteria=array(), $form_ids=array())
Calculates the Search Criteria used on the self::get_entries / self::get_entry methods.
new GravityView_Cache
static get_form_from_entry_id( $entry_slug)
Get the form array for an entry based only on the entry ID.
static getInstance( $passed_post=NULL)
Definition: class-data.php:122
static get_template_setting( $post_id, $key)
Get the setting for a View.
if(gv_empty( $field['value'], false, false)) $format
static get_forms( $active=true, $trash=false, $order_by='id', $order='ASC')
Alias of GFAPI::get_forms()
static get( $field_name)
Alias for get_instance()
static get_meta_form_id( $view_id)
Get the Gravity Forms form ID connected to a View.
static get_forms_as_options( $active=true, $trash=false, $sort_column='id', $sort_dir='ASC')
Get all forms to use as options in View settings.
static has_cap( $caps_to_check='', $object_id=null, $user_id=null)
Check whether the current user has a capability.
static decode_shortcodes( $string)
Inspired on ::encode_shortcodes, reverse the encoding by replacing the ascii characters by the shortc...
$class
static generate_notice( $notice, $class='', $cap='', $object_id=null)
Display updated/error notice.
$entries
gravityview_get_link( $href='', $anchor_text='', $atts=array())
Generate an HTML anchor tag with a list of supported attributes.
static get_sortable_fields( $formid, $current='')
Render dropdown (select) with the list of sortable fields from a form ID.
static gv_parse_str( $string, &$result)
Do the same than parse_str without max_input_vars limitation: Parses $string as if it were the query ...
global $post
Definition: delete-entry.php:7
if(gravityview() ->plugin->is_GF_25()) $form
static matches_operation( $val1, $val2, $operation)
Wrapper for the GFFormsModel::matches_operation() method that adds additional comparisons, including: &#39;equals&#39;, &#39;greater_than_or_is&#39;, &#39;greater_than_or_equals&#39;, &#39;less_than_or_is&#39;, &#39;less_than_or_equals&#39;, &#39;not_contains&#39;, &#39;in&#39;, and &#39;not_in&#39;.
$criteria['paging']
Modify the search parameters before the entries are fetched.
static get_template_settings( $post_id)
Get all the settings for a View.
if(empty( $field_settings['content'])) $content
Definition: custom.php:37
static get_entry_id( $entry_id_or_slug='', $force_allow_ids=false)
Get the entry ID from a string that may be the Entry ID or the Entry Slug.
static get_entry_ids( $form_id, $search_criteria=array())
Wrapper for the Gravity Forms GFFormsModel::search_lead_ids() method.
gv_map_deep( $value, $callback)
Maps a function to all non-iterable elements of an array or an object.
static get_field_type( $form=null, $field_id='')
Returns the GF Form field type for a certain field(id) of a form.
static get_field_array( $field)
Return a Gravity Forms field array, whether using GF 1.9 or not.
static check_entry_display( $entry, $view=null)
Checks if a certain entry is valid according to the View search filters (specially the Adv Filters) ...
static get_product_field_types()
Return array of product field types.
static get_field( $form, $field_id)
Returns the field details array of a specific form given the field id.
$gv_field
Definition: time.php:11
static pre_get_form_fields( $template_id='')
Get the form fields for a preset (no form created yet)
Definition: class-ajax.php:319
static send_email( $from, $to, $bcc, $reply_to, $subject, $message, $from_name='', $message_format='html', $attachments='', $entry=false, $notification=false)
Send email using GFCommon::send_email()
static is_field_numeric( $form=null, $field='')
Checks if the field type is a &#39;numeric&#39; field type (e.g.
static get_form_or_form_template( $form_id=0)
Returns form object for existing form or a form template.
static by_id( $post_id)
Construct a instance from a post ID.
static get_users( $context='change_entry_creator', $args=array())
Get WordPress users with reasonable limits set.
static get_sortable_fields_array( $formid, $blocklist=array( 'list', 'textarea'))
static format_date( $date_string='', $args=array())
Allow formatting date and time based on GravityView standards.
static get_entries( $form_ids=null, $passed_criteria=null, &$total=null)
Retrieve entries given search, sort, paging criteria.
static has_gravityview_shortcode( $post=null)
Check whether the post is GravityView.
if(empty( $created_by)) $form_id
static get( $array, $key, $default=null)
Grab a value from an array or an object or default.
gravityview()
The main GravityView wrapper function.
static get_field_label( $form=array(), $field_id='', $field_value='')
Retrieve the label of a given field id (for a specific form)
static get_all( $groups='')
Get all fields.
gravityview_get_context()
Returns the current GravityView context, or empty string if not GravityView.
Definition: class-api.php:1330
$entry_slug
Definition: notes.php:30
static get_entry( $entry_slug, $force_allow_ids=false, $check_entry_display=true, $view=null)
Return a single entry object.
static has_cap( $caps='', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
static get_meta_template_id( $view_id)
Get the template ID (list, table, datatables, map) for a View.
$entry
Definition: notes.php:27
if(false !==strpos( $value, '00:00')) $field_id
string $field_id ID of the field being displayed
Definition: time.php:22
static get_all_views( $args=array())
Get all existing Views.
static get_link_html( $href='', $anchor_text='', $atts=array())
Generate an HTML anchor tag with a list of supported attributes.
static get_form( $form_id)
Returns the form object for a given Form ID.
$field_value
Definition: checkbox.php:24
static getInstance()
Get the one true instantiated self.