GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-gravityview-field.php
Go to the documentation of this file.
1 <?php
2 /**
3  * @file class-gravityview-field.php
4  * @package GravityView
5  * @subpackage includes\fields
6  */
7 
8 /**
9  * Modify field settings by extending this class.
10  */
11 abstract class GravityView_Field {
12 
13  /**
14  * The name of the GravityView field type
15  * Example: `created_by`, `text`, `fileupload`, `address`, `entry_link`
16  * @var string
17  */
18  public $name;
19 
20  /**
21  * @internal Not yet implemented
22  * @since 1.15.2
23  * @type string The description of the field in the field picker
24  */
25  public $description;
26 
27  /**
28  * @since 1.15.2
29  * @type string The label of the field in the field picker
30  */
31  public $label;
32 
33  /**
34  * @var string The default search label used by the search widget, if not set
35  */
37 
38  /**
39  * `standard`, `advanced`, `post`, `pricing`, `meta`, `gravityview`, or `add-ons`
40  *
41  * @since 1.15.2
42  * @type string The group belongs to this field in the field picker
43  */
44  public $group;
45 
46  /**
47  * @internal Not yet implemented
48  * @type boolean Can the field be searched?
49  * @since 1.15.2
50  */
51  public $is_searchable = true;
52 
53  /**
54  * @internal Not yet implemented
55  * @type array $search_operators The type of search operators available for this field
56  * @since 1.15.2
57  */
59 
60  /**
61  * @type boolean Can the field be sorted in search?
62  * @since 1.15.2
63  */
64  public $is_sortable = true;
65 
66  /**
67  * @type boolean Is field content number-based?
68  * @since 1.15.2
69  */
70  public $is_numeric;
71 
72  /**
73  * @var null|string The key used to search and sort entry meta in Gravity Forms. Used if the field stores data as custom entry meta.
74  * @see https://www.gravityhelp.com/documentation/article/gform_entry_meta/
75  * @since 1.19
76  */
77  public $entry_meta_key = null;
78 
79  /**
80  * @var string|array Optional. The callback function after entry meta is updated, only used if $entry_meta_key is set.
81  * @see https://www.gravityhelp.com/documentation/article/gform_entry_meta/
82  * @since 1.19
83  */
85 
86  /**
87  * @var bool Whether to show meta when set to true automatically adds the column to the entry list, without having to edit and add the column for display
88  * @since 1.19
89  */
91 
92  /**
93  * @internal Not yet implemented
94  * @todo implement supports_context() method
95  * The contexts in which a field is available. Some fields aren't editable, for example.
96  * - `singular` is an alias for both `single` and `edit`
97  * - `multiple` is an alias for `directory` (backward compatibility)
98  * @type array
99  * @since 1.15.2
100  */
101  public $contexts = array( 'single', 'multiple', 'edit', 'export' );
102 
103  /**
104  * @var string An icon that represents the field type in the field picker.
105  *
106  * Supports these icon formats:
107  * - Gravity Forms icon class: The string starts with "gform-icon". Note: the site must be running GF 2.5+. No need to also pass "gform-icon".
108  * - Dashicons: The string starts with "dashicons". No need to also pass "dashicons".
109  * - Inline SVG: Starts with "data:"
110  * - If not matching those formats, the value will be used as a CSS class in a `<i>` element.
111  *
112  * @since 2.8.1
113  * @see GravityView_Admin_View_Item::getOutput
114  */
115  public $icon = 'dashicons-admin-generic';
116 
117  /**
118  * @since 1.15.2
119  * @since 1.16.2.2 Changed access to public (previously, protected)
120  * @type string The name of a corresponding Gravity Forms GF_Field class, if exists
121  */
123 
124  /**
125  * @var string The field ID being requested
126  * @since 1.14
127  */
128  protected $_field_id = '';
129 
130  /**
131  * @var string Field options to be rendered
132  * @since 1.14
133  */
134  protected $_field_options = array();
135 
136  /**
137  * @var bool|string Name of merge tag (without curly brackets), if the field has custom GravityView merge tags to add. Otherwise, false.
138  * @since 1.16
139  */
140  protected $_custom_merge_tag = false;
141 
142  /**
143  * GravityView_Field constructor.
144  */
145  public function __construct() {
146 
147  /**
148  * Modify the field options based on the name of the field type
149  * @see GravityView_Render_Settings::get_default_field_options
150  */
151  add_filter( sprintf( 'gravityview_template_%s_options', $this->name ), array( &$this, 'field_options' ), 10, 6 );
152 
153  add_filter( 'gravityview/sortable/field_blocklist', array( $this, '_filter_sortable_fields' ), 1 );
154 
155  if( $this->entry_meta_key ) {
156  add_filter( 'gform_entry_meta', array( $this, 'add_entry_meta' ) );
157  add_filter( 'gravityview/common/sortable_fields', array( $this, 'add_sortable_field' ), 10, 2 );
158  }
159 
160  if( $this->_custom_merge_tag ) {
161  add_filter( 'gform_custom_merge_tags', array( $this, '_filter_gform_custom_merge_tags' ), 10, 4 );
162  add_filter( 'gform_replace_merge_tags', array( $this, '_filter_gform_replace_merge_tags' ), 10, 7 );
163  }
164 
165  if( 'meta' === $this->group || '' !== $this->default_search_label ) {
166  add_filter( 'gravityview_search_field_label', array( $this, 'set_default_search_label' ), 10, 3 );
167  }
168 
169  /**
170  * Auto-assign label from Gravity Forms label, if exists
171  * @since 1.20
172  */
173  if( empty( $this->label ) && ! empty( $this->_gf_field_class_name ) && class_exists( $this->_gf_field_class_name ) ) {
174  $this->label = ucfirst( GF_Fields::get( $this->name )->get_form_editor_field_title() );
175  }
176 
177  try {
179  } catch ( Exception $exception ) {
180  gravityview()->log->critical( $exception->getMessage() );
181  }
182  }
183 
184  /**
185  * Returns the field as an array to be used in field pickers
186  *
187  * @since 2.10
188  *
189  * @return array[]
190  */
191  public function as_array() {
192  return array(
193  $this->name => array(
194  'label' => $this->label,
195  'desc' => $this->description,
196  'type' => $this->name,
197  'icon' => $this->icon,
198  'group' => $this->group,
199  ),
200  );
201  }
202 
203  /**
204  * Returns the icon for a field
205  *
206  * @since 2.17
207  *
208  * @return string The dashicon or gform-icon class name for a field.
209  */
210  public function get_icon() {
211 
212  // GF only has icons in 2.5+
213  if ( ! gravityview()->plugin->is_GF_25() ) {
214  return $this->icon;
215  }
216 
217  // If the field doesn't have an associated GF field class, return the default icon.
218  if ( empty( $this->_gf_field_class_name ) || ! class_exists( $this->_gf_field_class_name ) ) {
219  return $this->icon;
220  }
221 
222  /** @var GF_Field $gf_field */
223  $gf_field = GF_Fields::get( $this->name );
224 
225  // If the field exists and is a GF_Field, return the icon.
226  if( $gf_field && $gf_field instanceof GF_Field ) {
227  return $gf_field->get_form_editor_field_icon();
228  }
229 
230  return $this->icon;
231  }
232 
233  /**
234  * Add the field to the Filter & Sort available fields
235  *
236  * @since 1.19
237  *
238  * @param array $fields Sub-set of GF form fields that are sortable
239  *
240  * @return array Modified $fields array to include approval status in the sorting dropdown
241  */
242  public function add_sortable_field( $fields ) {
243 
244  $added_field = array(
245  'label' => $this->label,
246  'type' => $this->name
247  );
248 
249  $fields["{$this->entry_meta_key}"] = $added_field;
250 
251  return $fields;
252  }
253 
254  /**
255  * Allow setting a default search label for search fields based on the field type
256  *
257  * Useful for entry meta "fields" that don't have Gravity Forms labels, like `created_by`
258  *
259  * @since 1.17.3
260  *
261  * @param string $label Existing label text, sanitized.
262  * @param array $gf_field Gravity Forms field array, as returned by `GFFormsModel::get_field()`
263  * @param array $field Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys
264  *
265  * @return string
266  */
267  function set_default_search_label( $label = '', $gf_field = null, $field = array() ) {
268 
269  if( $this->name === $field['field'] && '' === $label ) {
270  $label = esc_html( $this->default_search_label );
271  }
272 
273  return $label;
274  }
275 
276  /**
277  * Match the merge tag in replacement text for the field. DO NOT OVERRIDE.
278  *
279  * @see replace_merge_tag Override replace_merge_tag() to handle any matches
280  *
281  * @since 1.16
282  *
283  * @param string $text Text to replace
284  * @param array $form Gravity Forms form array
285  * @param array $entry Entry array
286  * @param bool $url_encode Whether to URL-encode output
287  *
288  * @return string Original text if {_custom_merge_tag} isn't found. Otherwise, replaced text.
289  */
290  public function _filter_gform_replace_merge_tags( $text, $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
291 
292  // Is there is field merge tag? Strip whitespace off the ned, too.
293  preg_match_all( '/{' . preg_quote( $this->_custom_merge_tag ) . ':?(.*?)(?:\s)?}/ism', $text, $matches, PREG_SET_ORDER );
294 
295  // If there are no matches, return original text
296  if ( empty( $matches ) ) {
297  return $text;
298  }
299 
300  return $this->replace_merge_tag( $matches, $text, $form, $entry, $url_encode, $esc_html );
301  }
302 
303  /**
304  * Run GravityView filters when using GFCommon::replace_variables()
305  *
306  * Instead of adding multiple hooks, add all hooks into this one method to improve speed
307  *
308  * @since 1.8.4
309  *
310  * @see GFCommon::replace_variables()
311  *
312  * @param array $matches Array of Merge Tag matches found in text by preg_match_all
313  * @param string $text Text to replace
314  * @param array|bool $form Gravity Forms form array. When called inside {@see GFCommon::replace_variables()} (now deprecated), `false`
315  * @param array|bool $entry Entry array. When called inside {@see GFCommon::replace_variables()} (now deprecated), `false`
316  * @param bool $url_encode Whether to URL-encode output
317  * @param bool $esc_html Whether to apply `esc_html()` to output
318  *
319  * @return mixed
320  */
321  public function replace_merge_tag( $matches = array(), $text = '', $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
322 
323  foreach( $matches as $match ) {
324 
325  $full_tag = $match[0];
326 
327  // Strip the Merge Tags
328  $tag = str_replace( array( '{', '}'), '', $full_tag );
329 
330  // Replace the value from the entry, if exists
331  if( isset( $entry[ $tag ] ) ) {
332 
333  $value = $entry[ $tag ];
334 
335  if( is_callable( array( $this, 'get_content') ) ) {
336  $value = $this->get_content( $value );
337  }
338 
339  $text = str_replace( $full_tag, $value, $text );
340  }
341  }
342 
343  unset( $value, $tag, $full_tag );
344 
345  return $text;
346  }
347 
348  /**
349  * Add custom merge tags to merge tag options. DO NOT OVERRIDE.
350  *
351  * @internal Not to be overridden by fields
352  *
353  * @since 1.8.4
354  *
355  * @param array $custom_merge_tags
356  * @param int $form_id GF Form ID
357  * @param GF_Field[] $fields Array of fields in the form
358  * @param string $element_id The ID of the input that Merge Tags are being used on
359  *
360  * @return array Modified merge tags
361  */
362  public function _filter_gform_custom_merge_tags( $custom_merge_tags = array(), $form_id = 0, $fields = array(), $element_id = '' ) {
363 
365 
366  $field_merge_tags = $this->custom_merge_tags( $form, $fields );
367 
368  return array_merge( $custom_merge_tags, $field_merge_tags );
369  }
370 
371  /**
372  * Add custom Merge Tags to Merge Tag options, if custom Merge Tags exist
373  *
374  * Should be overridden if there's more than one Merge Tag to add or if the Merge Tag isn't {_custom_merge_tag}
375  *
376  * @since 1.16
377  *
378  * @param array $form GF Form array
379  * @param GF_Field[] $fields Array of fields in the form
380  *
381  * @return array Merge tag array with `label` and `tag` keys based on class `label` and `_custom_merge_tag` variables
382  */
383  protected function custom_merge_tags( $form = array(), $fields = array() ) {
384 
385  // Use variables to make it unnecessary for other fields to override
386  $merge_tags = array(
387  array(
388  'label' => $this->label,
389  'tag' => '{' . $this->_custom_merge_tag . '}',
390  ),
391  );
392 
393  return $merge_tags;
394  }
395 
396  /**
397  * Use field settings to modify whether a field is sortable
398  *
399  * @see GravityView_frontend::is_field_sortable
400  * @since 1.15.3
401  *
402  * @param array $not_sortable Existing field types that aren't sortable
403  *
404  * @return array
405  */
406  public function _filter_sortable_fields( $not_sortable ) {
407 
408  if( ! $this->is_sortable ) {
409  $not_sortable[] = $this->name;
410  }
411 
412  return $not_sortable;
413  }
414 
415  /**
416  * Add the custom entry meta key to make it searchable and sortable
417  *
418  * @see https://www.gravityhelp.com/documentation/article/gform_entry_meta/
419  *
420  * @param array $entry_meta Array of custom entry meta keys with associative arrays
421  *
422  * @return mixed
423  */
424  function add_entry_meta( $entry_meta ) {
425 
426  if( ! isset( $entry_meta["{$this->entry_meta_key}"] ) ) {
427 
428  $added_meta = array(
429  'label' => $this->label,
430  'is_numeric' => $this->is_numeric,
431  'is_default_column' => $this->entry_meta_is_default_column,
432  );
433 
434  if ( $this->entry_meta_update_callback && is_callable( $this->entry_meta_update_callback ) ) {
435  $added_meta['update_entry_meta_callback'] = $this->entry_meta_update_callback;
436  }
437 
438  $entry_meta["{$this->entry_meta_key}"] = $added_meta;
439 
440  } else {
441  gravityview()->log->error( 'Entry meta already set: {meta_key}', array( 'meta_key' => $this->entry_meta_key, 'data' => $entry_meta["{$this->entry_meta_key}"] ) );
442  }
443 
444  return $entry_meta;
445  }
446 
447  private function field_support_options() {
448  $options = array(
449  'link_to_post' => array(
450  'type' => 'checkbox',
451  'label' => __( 'Link to the post', 'gk-gravityview' ),
452  'desc' => __( 'Link to the post created by the entry.', 'gk-gravityview' ),
453  'value' => false,
454  'priority' => 1200,
455  'group' => 'display',
456  ),
457  'link_to_term' => array(
458  'type' => 'checkbox',
459  'label' => __( 'Link to the category or tag', 'gk-gravityview' ),
460  'desc' => __( 'Link to the current category or tag. "Link to single entry" must be unchecked.', 'gk-gravityview' ),
461  'value' => false,
462  'priority' => 1210,
463  'group' => 'display',
464  ),
465  'dynamic_data' => array(
466  'type' => 'checkbox',
467  'label' => __( 'Use the live post data', 'gk-gravityview' ),
468  'desc' => __( 'Instead of using the entry data, instead use the current post data.', 'gk-gravityview' ),
469  'value' => true,
470  'priority' => 1100,
471  'group' => 'display',
472  ),
473  'date_display' => array(
474  'type' => 'text',
475  'label' => __( 'Override Date Format', 'gk-gravityview' ),
476  'desc' => sprintf( __( 'Define how the date is displayed (using %sthe PHP date format%s)', 'gk-gravityview'), '<a href="https://wordpress.org/support/article/formatting-date-and-time/" rel="external">', '</a>' ),
477  /**
478  * @filter `gravityview_date_format` Override the date format with a [PHP date format](https://codex.wordpress.org/Formatting_Date_and_Time)
479  * @param null|string $date_format Date Format (default: null)
480  */
481  'value' => apply_filters( 'gravityview_date_format', null ),
482  'class' => 'code widefat',
483  'priority' => 1500,
484  'group' => 'display',
485  ),
486  'new_window' => array(
487  'type' => 'checkbox',
488  'label' => __( 'Open link in a new tab or window?', 'gk-gravityview' ),
489  'value' => false,
490  'group' => 'display',
491  'priority' => 1300,
492  ),
493  );
494 
495  /**
496  * @filter `gravityview_field_support_options` Modify the settings that a field supports
497  * @param array $options Options multidimensional array with each key being the input name, with each array setting having `type`, `label`, `desc` and `value` (default values) keys
498  */
499  return apply_filters( 'gravityview_field_support_options', $options );
500  }
501 
502  /**
503  * @param string $key
504  * @param array $field_options
505  *
506  * @return array
507  */
508  function add_field_support( $key, &$field_options ) {
509 
510  $options = $this->field_support_options();
511 
512  if( isset( $options[ $key ] ) ) {
513  $field_options[ $key ] = $options[ $key ];
514  }
515 
516  return $field_options;
517  }
518 
519  /**
520  * Tap in here to modify field options.
521  *
522  * Here's an example:
523  *
524  * <pre>
525  * $field_options['name_display'] = array(
526  * 'type' => 'select',
527  * 'label' => __( 'User Format', 'gravityview' ),
528  * 'desc' => __( 'How should the User information be displayed?', 'gravityview'),
529  * 'choices' => array(
530  * array(
531  * 'value' => 'display_name',
532  * 'label' => __('Display Name (Example: "Ellen Ripley")', 'gravityview'),
533  * ),
534  * array(
535  * 'value' => 'user_login',
536  * 'label' => __('Username (Example: "nostromo")', 'gravityview')
537  * ),
538  * 'value' => 'display_name'
539  * );
540  * </pre>
541  *
542  * @param array $field_options [description]
543  * @param string $template_id [description]
544  * @param string $field_id [description]
545  * @param string $context [description]
546  * @param string $input_type [description]
547  * @return array [description]
548  */
549  public function field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id ) {
550 
551  $this->_field_options = $field_options;
552  $this->_field_id = $field_id;
553 
554  return $field_options;
555  }
556 
557  /**
558  * Check whether the `enableChoiceValue` flag is set for a GF field
559  *
560  * Gets the current form ID, gets the field at that ID, then checks for the enableChoiceValue value.
561  *
562  * @access protected
563  *
564  * @uses GFAPI::get_form
565  *
566  * @since 1.17
567  *
568  * @return bool True: Enable Choice Value is active for field; False: not active, or form invalid, or form not found.
569  */
570  protected function is_choice_value_enabled() {
571 
572  // If "Add Field" button is processing, get the Form ID
573  $connected_form = \GV\Utils::_POST( 'form_id' );
574 
575  // Otherwise, get the Form ID from the Post page
576  if( empty( $connected_form ) ) {
577  $connected_form = gravityview_get_form_id( get_the_ID() );
578  }
579 
580  if( empty( $connected_form ) ) {
581  gravityview()->log->error( 'Form not found for form ID "{form_id}"', array( 'form_id' => $connected_form ) );
582  return false;
583  }
584 
585  $form = GFAPI::get_form( $connected_form );
586 
587  if ( ! $form ) {
588  gravityview()->log->error( 'Form not found for field ID of "{field_id}", when checking for a form with ID of "{form_id}"', array( 'field_id' => $this->_field_id, 'form_id' => $connected_form ) );
589  return false;
590  }
591 
592  $field = gravityview_get_field( $form, $this->_field_id );
593 
594  return ! empty( $field->enableChoiceValue );
595  }
596 
597 }
Modify field settings by extending this class.
__construct()
GravityView_Field constructor.
$is_numeric
boolean Is field content number-based?
add_entry_meta( $entry_meta)
Add the custom entry meta key to make it searchable and sortable.
_filter_gform_custom_merge_tags( $custom_merge_tags=array(), $form_id=0, $fields=array(), $element_id='')
Add custom merge tags to merge tag options.
replace_merge_tag( $matches=array(), $text='', $form=array(), $entry=array(), $url_encode=false, $esc_html=false)
Run GravityView filters when using GFCommon::replace_variables()
add_field_support( $key, &$field_options)
if(gravityview() ->plugin->is_GF_25()) $form
$group
standard, advanced, post, pricing, meta, gravityview, or add-ons
gravityview_get_field( $form, $field_id)
Returns the field details array of a specific form given the field id.
scale description p description
$is_sortable
boolean Can the field be sorted in search?
add_sortable_field( $fields)
Add the field to the Filter & Sort available fields.
custom_merge_tags( $form=array(), $fields=array())
Add custom Merge Tags to Merge Tag options, if custom Merge Tags exist.
gravityview_get_form_id( $view_id)
Get the connected form ID from a View ID.
is_choice_value_enabled()
Check whether the enableChoiceValue flag is set for a GF field.
if(empty( $created_by)) $form_id
field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id)
Tap in here to modify field options.
gravityview()
The main GravityView wrapper function.
_filter_sortable_fields( $not_sortable)
Use field settings to modify whether a field is sortable.
set_default_search_label( $label='', $gf_field=null, $field=array())
Allow setting a default search label for search fields based on the field type.
$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
_filter_gform_replace_merge_tags( $text, $form=array(), $entry=array(), $url_encode=false, $esc_html=false)
Match the merge tag in replacement text for the field.
static get_form( $form_id)
Returns the form object for a given Form ID.
static _POST( $name, $default=null)
Grab a value from the _POST superglobal or default.
as_array()
Returns the field as an array to be used in field pickers.