GravityView  2.10.1
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  public $icon = 'dashicons-admin-generic';
107 
108  /**
109  * @since 1.15.2
110  * @since 1.16.2.2 Changed access to public (previously, protected)
111  * @type string The name of a corresponding Gravity Forms GF_Field class, if exists
112  */
114 
115  /**
116  * @var string The field ID being requested
117  * @since 1.14
118  */
119  protected $_field_id = '';
120 
121  /**
122  * @var string Field options to be rendered
123  * @since 1.14
124  */
125  protected $_field_options = array();
126 
127  /**
128  * @var bool|string Name of merge tag (without curly brackets), if the field has custom GravityView merge tags to add. Otherwise, false.
129  * @since 1.16
130  */
131  protected $_custom_merge_tag = false;
132 
133  /**
134  * GravityView_Field constructor.
135  */
136  public function __construct() {
137 
138  /**
139  * Modify the field options based on the name of the field type
140  * @see GravityView_Render_Settings::get_default_field_options
141  */
142  add_filter( sprintf( 'gravityview_template_%s_options', $this->name ), array( &$this, 'field_options' ), 10, 6 );
143 
144  add_filter( 'gravityview/sortable/field_blacklist', array( $this, '_filter_sortable_fields' ), 1 );
145 
146  if( $this->entry_meta_key ) {
147  add_filter( 'gform_entry_meta', array( $this, 'add_entry_meta' ) );
148  add_filter( 'gravityview/common/sortable_fields', array( $this, 'add_sortable_field' ), 10, 2 );
149  }
150 
151  if( $this->_custom_merge_tag ) {
152  add_filter( 'gform_custom_merge_tags', array( $this, '_filter_gform_custom_merge_tags' ), 10, 4 );
153  add_filter( 'gform_replace_merge_tags', array( $this, '_filter_gform_replace_merge_tags' ), 10, 7 );
154  }
155 
156  if( 'meta' === $this->group || '' !== $this->default_search_label ) {
157  add_filter( 'gravityview_search_field_label', array( $this, 'set_default_search_label' ), 10, 3 );
158  }
159 
160  /**
161  * Auto-assign label from Gravity Forms label, if exists
162  * @since 1.20
163  */
164  if( empty( $this->label ) && ! empty( $this->_gf_field_class_name ) && class_exists( $this->_gf_field_class_name ) ) {
165  $this->label = ucfirst( GF_Fields::get( $this->name )->get_form_editor_field_title() );
166  }
167 
168  try {
170  } catch ( Exception $exception ) {
171  gravityview()->log->critical( $exception->getMessage() );
172  }
173  }
174 
175  /**
176  * Returns the field as an array to be used in field pickers
177  *
178  * @since 2.10
179  *
180  * @return array[]
181  */
182  public function as_array() {
183  return array(
184  $this->name => array(
185  'label' => $this->label,
186  'desc' => $this->description,
187  'type' => $this->name,
188  'icon' => $this->icon,
189  'group' => $this->group,
190  ),
191  );
192  }
193 
194  /**
195  * Add the field to the Filter & Sort available fields
196  *
197  * @since 1.19
198  *
199  * @param array $fields Sub-set of GF form fields that are sortable
200  *
201  * @return array Modified $fields array to include approval status in the sorting dropdown
202  */
203  public function add_sortable_field( $fields ) {
204 
205  $added_field = array(
206  'label' => $this->label,
207  'type' => $this->name
208  );
209 
210  $fields["{$this->entry_meta_key}"] = $added_field;
211 
212  return $fields;
213  }
214 
215  /**
216  * Allow setting a default search label for search fields based on the field type
217  *
218  * Useful for entry meta "fields" that don't have Gravity Forms labels, like `created_by`
219  *
220  * @since 1.17.3
221  *
222  * @param string $label Existing label text, sanitized.
223  * @param array $gf_field Gravity Forms field array, as returned by `GFFormsModel::get_field()`
224  * @param array $field Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys
225  *
226  * @return string
227  */
228  function set_default_search_label( $label = '', $gf_field = null, $field = array() ) {
229 
230  if( $this->name === $field['field'] && '' === $label ) {
231  $label = esc_html( $this->default_search_label );
232  }
233 
234  return $label;
235  }
236 
237  /**
238  * Match the merge tag in replacement text for the field. DO NOT OVERRIDE.
239  *
240  * @see replace_merge_tag Override replace_merge_tag() to handle any matches
241  *
242  * @since 1.16
243  *
244  * @param string $text Text to replace
245  * @param array $form Gravity Forms form array
246  * @param array $entry Entry array
247  * @param bool $url_encode Whether to URL-encode output
248  *
249  * @return string Original text if {_custom_merge_tag} isn't found. Otherwise, replaced text.
250  */
251  public function _filter_gform_replace_merge_tags( $text, $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
252 
253  // Is there is field merge tag? Strip whitespace off the ned, too.
254  preg_match_all( '/{' . preg_quote( $this->_custom_merge_tag ) . ':?(.*?)(?:\s)?}/ism', $text, $matches, PREG_SET_ORDER );
255 
256  // If there are no matches, return original text
257  if ( empty( $matches ) ) {
258  return $text;
259  }
260 
261  return $this->replace_merge_tag( $matches, $text, $form, $entry, $url_encode, $esc_html );
262  }
263 
264  /**
265  * Run GravityView filters when using GFCommon::replace_variables()
266  *
267  * Instead of adding multiple hooks, add all hooks into this one method to improve speed
268  *
269  * @since 1.8.4
270  *
271  * @see GFCommon::replace_variables()
272  *
273  * @param array $matches Array of Merge Tag matches found in text by preg_match_all
274  * @param string $text Text to replace
275  * @param array|bool $form Gravity Forms form array. When called inside {@see GFCommon::replace_variables()} (now deprecated), `false`
276  * @param array|bool $entry Entry array. When called inside {@see GFCommon::replace_variables()} (now deprecated), `false`
277  * @param bool $url_encode Whether to URL-encode output
278  * @param bool $esc_html Whether to apply `esc_html()` to output
279  *
280  * @return mixed
281  */
282  public function replace_merge_tag( $matches = array(), $text = '', $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
283 
284  foreach( $matches as $match ) {
285 
286  $full_tag = $match[0];
287 
288  // Strip the Merge Tags
289  $tag = str_replace( array( '{', '}'), '', $full_tag );
290 
291  // Replace the value from the entry, if exists
292  if( isset( $entry[ $tag ] ) ) {
293 
294  $value = $entry[ $tag ];
295 
296  if( is_callable( array( $this, 'get_content') ) ) {
297  $value = $this->get_content( $value );
298  }
299 
300  $text = str_replace( $full_tag, $value, $text );
301  }
302  }
303 
304  unset( $value, $tag, $full_tag );
305 
306  return $text;
307  }
308 
309  /**
310  * Add custom merge tags to merge tag options. DO NOT OVERRIDE.
311  *
312  * @internal Not to be overridden by fields
313  *
314  * @since 1.8.4
315  *
316  * @param array $custom_merge_tags
317  * @param int $form_id GF Form ID
318  * @param GF_Field[] $fields Array of fields in the form
319  * @param string $element_id The ID of the input that Merge Tags are being used on
320  *
321  * @return array Modified merge tags
322  */
323  public function _filter_gform_custom_merge_tags( $custom_merge_tags = array(), $form_id, $fields = array(), $element_id = '' ) {
324 
326 
327  $field_merge_tags = $this->custom_merge_tags( $form, $fields );
328 
329  return array_merge( $custom_merge_tags, $field_merge_tags );
330  }
331 
332  /**
333  * Add custom Merge Tags to Merge Tag options, if custom Merge Tags exist
334  *
335  * Should be overridden if there's more than one Merge Tag to add or if the Merge Tag isn't {_custom_merge_tag}
336  *
337  * @since 1.16
338  *
339  * @param array $form GF Form array
340  * @param GF_Field[] $fields Array of fields in the form
341  *
342  * @return array Merge tag array with `label` and `tag` keys based on class `label` and `_custom_merge_tag` variables
343  */
344  protected function custom_merge_tags( $form = array(), $fields = array() ) {
345 
346  // Use variables to make it unnecessary for other fields to override
347  $merge_tags = array(
348  array(
349  'label' => $this->label,
350  'tag' => '{' . $this->_custom_merge_tag . '}',
351  ),
352  );
353 
354  return $merge_tags;
355  }
356 
357  /**
358  * Use field settings to modify whether a field is sortable
359  *
360  * @see GravityView_frontend::is_field_sortable
361  * @since 1.15.3
362  *
363  * @param array $not_sortable Existing field types that aren't sortable
364  *
365  * @return array
366  */
367  public function _filter_sortable_fields( $not_sortable ) {
368 
369  if( ! $this->is_sortable ) {
370  $not_sortable[] = $this->name;
371  }
372 
373  return $not_sortable;
374  }
375 
376  /**
377  * Add the custom entry meta key to make it searchable and sortable
378  *
379  * @see https://www.gravityhelp.com/documentation/article/gform_entry_meta/
380  *
381  * @param array $entry_meta Array of custom entry meta keys with associative arrays
382  *
383  * @return mixed
384  */
385  function add_entry_meta( $entry_meta ) {
386 
387  if( ! isset( $entry_meta["{$this->entry_meta_key}"] ) ) {
388 
389  $added_meta = array(
390  'label' => $this->label,
391  'is_numeric' => $this->is_numeric,
392  'is_default_column' => $this->entry_meta_is_default_column,
393  );
394 
395  if ( $this->entry_meta_update_callback && is_callable( $this->entry_meta_update_callback ) ) {
396  $added_meta['update_entry_meta_callback'] = $this->entry_meta_update_callback;
397  }
398 
399  $entry_meta["{$this->entry_meta_key}"] = $added_meta;
400 
401  } else {
402  gravityview()->log->error( 'Entry meta already set: {meta_key}', array( 'meta_key' => $this->entry_meta_key, 'data' => $entry_meta["{$this->entry_meta_key}"] ) );
403  }
404 
405  return $entry_meta;
406  }
407 
408  private function field_support_options() {
409  $options = array(
410  'link_to_post' => array(
411  'type' => 'checkbox',
412  'label' => __( 'Link to the post', 'gravityview' ),
413  'desc' => __( 'Link to the post created by the entry.', 'gravityview' ),
414  'value' => false,
415  'priority' => 1200,
416  'group' => 'display',
417  ),
418  'link_to_term' => array(
419  'type' => 'checkbox',
420  'label' => __( 'Link to the category or tag', 'gravityview' ),
421  'desc' => __( 'Link to the current category or tag. "Link to single entry" must be unchecked.', 'gravityview' ),
422  'value' => false,
423  'priority' => 1210,
424  'group' => 'display',
425  ),
426  'dynamic_data' => array(
427  'type' => 'checkbox',
428  'label' => __( 'Use the live post data', 'gravityview' ),
429  'desc' => __( 'Instead of using the entry data, instead use the current post data.', 'gravityview' ),
430  'value' => true,
431  'priority' => 1100,
432  'group' => 'display',
433  ),
434  'date_display' => array(
435  'type' => 'text',
436  'label' => __( 'Override Date Format', 'gravityview' ),
437  'desc' => sprintf( __( 'Define how the date is displayed (using %sthe PHP date format%s)', 'gravityview'), '<a href="https://wordpress.org/support/article/formatting-date-and-time/" rel="external">', '</a>' ),
438  /**
439  * @filter `gravityview_date_format` Override the date format with a [PHP date format](https://codex.wordpress.org/Formatting_Date_and_Time)
440  * @param[in,out] null|string $date_format Date Format (default: null)
441  */
442  'value' => apply_filters( 'gravityview_date_format', null ),
443  'class' => 'code widefat',
444  'priority' => 1500,
445  'group' => 'display',
446  ),
447  'new_window' => array(
448  'type' => 'checkbox',
449  'label' => __( 'Open link in a new tab or window?', 'gravityview' ),
450  'value' => false,
451  'group' => 'display',
452  'priority' => 1300,
453  ),
454  );
455 
456  /**
457  * @filter `gravityview_field_support_options` Modify the settings that a field supports
458  * @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
459  */
460  return apply_filters( 'gravityview_field_support_options', $options );
461  }
462 
463  function add_field_support( $key = '', &$field_options ) {
464 
465  $options = $this->field_support_options();
466 
467  if( isset( $options[ $key ] ) ) {
468  $field_options[ $key ] = $options[ $key ];
469  }
470 
471  return $field_options;
472  }
473 
474  /**
475  * Tap in here to modify field options.
476  *
477  * Here's an example:
478  *
479  * <pre>
480  * $field_options['name_display'] = array(
481  * 'type' => 'select',
482  * 'label' => __( 'User Format', 'gravityview' ),
483  * 'desc' => __( 'How should the User information be displayed?', 'gravityview'),
484  * 'choices' => array(
485  * array(
486  * 'value' => 'display_name',
487  * 'label' => __('Display Name (Example: "Ellen Ripley")', 'gravityview'),
488  * ),
489  * array(
490  * 'value' => 'user_login',
491  * 'label' => __('Username (Example: "nostromo")', 'gravityview')
492  * ),
493  * 'value' => 'display_name'
494  * );
495  * </pre>
496  *
497  * @param array $field_options [description]
498  * @param string $template_id [description]
499  * @param string $field_id [description]
500  * @param string $context [description]
501  * @param string $input_type [description]
502  * @return array [description]
503  */
504  public function field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id ) {
505 
506  $this->_field_options = $field_options;
507  $this->_field_id = $field_id;
508 
509  return $field_options;
510  }
511 
512  /**
513  * Check whether the `enableChoiceValue` flag is set for a GF field
514  *
515  * Gets the current form ID, gets the field at that ID, then checks for the enableChoiceValue value.
516  *
517  * @access protected
518  *
519  * @uses GFAPI::get_form
520  *
521  * @since 1.17
522  *
523  * @return bool True: Enable Choice Value is active for field; False: not active, or form invalid, or form not found.
524  */
525  protected function is_choice_value_enabled() {
526 
527  // If "Add Field" button is processing, get the Form ID
528  $connected_form = \GV\Utils::_POST( 'form_id' );
529 
530  // Otherwise, get the Form ID from the Post page
531  if( empty( $connected_form ) ) {
532  $connected_form = gravityview_get_form_id( get_the_ID() );
533  }
534 
535  if( empty( $connected_form ) ) {
536  gravityview()->log->error( 'Form not found for form ID "{form_id}"', array( 'form_id' => $connected_form ) );
537  return false;
538  }
539 
540  $form = GFAPI::get_form( $connected_form );
541 
542  if ( ! $form ) {
543  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 ) );
544  return false;
545  }
546 
547  $field = gravityview_get_field( $form, $this->_field_id );
548 
549  return ! empty( $field->enableChoiceValue );
550  }
551 
552 }
_filter_gform_custom_merge_tags( $custom_merge_tags=array(), $form_id, $fields=array(), $element_id='')
Add custom merge tags to merge tag options.
Modify field settings by extending this class.
__construct()
GravityView_Field constructor.
add_entry_meta( $entry_meta)
Add the custom entry meta key to make it searchable and sortable.
replace_merge_tag( $matches=array(), $text='', $form=array(), $entry=array(), $url_encode=false, $esc_html=false)
Run GravityView filters when using GFCommon::replace_variables()
gravityview()
Definition: _stubs.php:26
get( $key, $default=null)
Retrieve a setting.
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
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.
$field_id
Definition: time.php:17
add_field_support( $key='', &$field_options)
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.
_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
_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.
$field
Definition: gquiz_grade.php:11
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.