GravityView  2.5
The best, easiest way to display Gravity Forms entries on your website.
class-gravityview-field-sequence.php
Go to the documentation of this file.
1 <?php
2 /**
3  * @file class-gravityview-field-sequence.php
4  * @package GravityView
5  * @subpackage includes\fields
6  */
7 
8 /**
9  * Add a sequence field.
10  * @since 2.3.3
11  */
13 
14  var $name = 'sequence';
15 
16  var $contexts = array( 'single', 'multiple' );
17 
18  /**
19  * @var bool
20  */
21  var $is_sortable = false;
22 
23  /**
24  * @var bool
25  */
26  var $is_searchable = false;
27 
28  /**
29  * @var bool
30  */
31  var $is_numeric = true;
32 
33  var $_custom_merge_tag = 'sequence';
34 
35  var $group = 'gravityview';
36 
37  public function __construct() {
38 
39  $this->label = esc_html__( 'Number Sequence', 'gravityview' );
40 
41  add_filter( 'gravityview/metaboxes/tooltips', array( $this, 'field_tooltips') );
42 
43  parent::__construct();
44  }
45 
46  /**
47  * Add tooltips
48  * @param array $tooltips Existing tooltips
49  * @return array Modified tooltips
50  */
51  public function field_tooltips( $tooltips ) {
52 
53  $return = $tooltips;
54 
55  $return['reverse_sequence'] = array(
56  'title' => __('Reverse the order of the result numbers', 'gravityview'),
57  'value' => __('Output the number sequence in descending order. If enabled, numbers will count down from high to low.', 'gravityview'),
58  );
59 
60  return $return;
61  }
62 
63  public function field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id ) {
64 
65  unset ( $field_options['search_filter'] );
66 
67  $new_fields = array(
68  'start' => array(
69  'type' => 'number',
70  'label' => __( 'First Number in the Sequence', 'gravityview' ),
71  'desc' => __('For each entry, the displayed number will increase by one. When displaying ten entries, the first entry will display "1", and the last entry will show "10".', 'gravityview'),
72  'value' => '1',
73  'merge_tags' => false,
74  ),
75  'reverse' => array(
76  'type' => 'checkbox',
77  'label' => __( 'Reverse the order of the number sequence (high to low)', 'gravityview' ),
78  'tooltip' => 'reverse_sequence',
79  'value' => '',
80  ),
81  );
82 
83  return $new_fields + $field_options;
84  }
85 
86  /**
87  * Replace {sequence} Merge Tags inside Custom Content fields
88  *
89  * TODO:
90  * - Find a better way to infer current View data (without using legacy code)
91  *
92  * @param array $matches
93  * @param string $text
94  * @param array $form
95  * @param array $entry
96  * @param bool $url_encode
97  * @param bool $esc_html
98  *
99  * @return string
100  */
101  public function replace_merge_tag( $matches = array(), $text = '', $form = array(), $entry = array(), $url_encode = false, $esc_html = false ) {
102  /**
103  * An internal cache for sequence tag reuse within one field.
104  * Avoids calling get_sequence over and over again, off-by-many increments, etc.
105  */
106  static $merge_tag_sequences = array();
107 
108  $view_data = gravityview_get_current_view_data(); // TODO: Don't use legacy code...
109 
110  // If we're not in a View or embed, don't replace the merge tag
111  if ( empty( $view_data ) ) {
112  gravityview()->log->error( '{sequence} Merge Tag used outside of a GravityView View.', array( 'data' => $matches ) );
113  return $text;
114  }
115 
116  $legacy_field = \GravityView_View::getInstance()->getCurrentField(); // TODO: Don't use legacy code...
117 
118  // If we're outside field context (like a GV widget), don't replace the merge tag
119  if ( ! $legacy_field ) {
120  gravityview()->log->error( '{sequence} Merge Tag was used without outside of the GravityView entry loop.', array( 'data' => $matches ) );
121  return $text;
122  }
123 
124  $return = $text;
125 
126  $context = new \GV\Template_Context();
127  $context->view = \GV\View::by_id( $view_data['view_id'] );
128  $context->entry = \GV\GF_Entry::from_entry( $entry );
129 
130  $gv_field = \GV\Internal_Field::by_id( 'sequence' );
131  $merge_tag_context = \GV\Utils::get( $legacy_field, 'UID' );
132  $merge_tag_context = $entry['id'] . "/{$merge_tag_context}";
133 
134  foreach ( $matches as $match ) {
135 
136  $full_tag = $match[0];
137  $property = $match[1];
138 
139  $gv_field->reverse = false;
140  $gv_field->start = 1;
141 
142  $modifiers = explode( ',', trim( $property ) );
143 
144  foreach ( $modifiers as $modifier ) {
145 
146  $modifier = trim( $modifier );
147 
148  if ( 'reverse' === $modifier ) {
149  $gv_field->reverse = true;
150  }
151 
152  $maybe_start = explode( ':', $modifier );
153 
154  // If there is a field with the ID of the start number, the merge tag won't work.
155  // In that case, you can use "=" instead: `{sequence start=10}`
156  if( 1 === sizeof( $maybe_start ) ) {
157  $maybe_start = explode( '=', $modifier );
158  }
159 
160  if ( 'start' === rgar( $maybe_start, 0 ) && is_numeric( rgar( $maybe_start, 1 ) ) ) {
161  $gv_field->start = (int) rgar( $maybe_start, 1 );
162  }
163  }
164 
165  /**
166  * We make sure that distinct sequence modifiers have their own
167  * output counters.
168  */
169  $merge_tag_context_modifiers = $merge_tag_context . '/' . var_export( $gv_field->reverse, true ) . '/' . $gv_field->start;
170 
171  if ( ! isset( $merge_tag_sequences[ $merge_tag_context_modifiers ] ) ) {
172  $gv_field->UID = $legacy_field['UID'] . '/' . var_export( $gv_field->reverse, true ) . '/' . $gv_field->start;
173  $context->field = $gv_field;
174  $sequence = $merge_tag_sequences[ $merge_tag_context_modifiers ] = $this->get_sequence( $context );
175  } else {
176  $sequence = $merge_tag_sequences[ $merge_tag_context_modifiers ];
177  }
178 
179  $return = str_replace( $full_tag, $sequence, $return );
180  }
181 
182  return $return;
183  }
184 
185  /**
186  * Calculate the current sequence number for the context.
187  *
188  * @param \GV\Template_Context $context The context.
189  *
190  * @return int The sequence number for the field/entry within the view results.
191  */
192  public function get_sequence( $context ) {
193  static $startlines = array();
194 
195  $context_key = md5( json_encode(
196  array(
197  $context->view->ID,
198  \GV\Utils::get( $context, 'field/UID' ),
199  )
200  ) );
201 
202  /**
203  * Figure out the starting number.
204  */
205  if ( $context->request && $entry = $context->request->is_entry() ) {
206 
207  $sql_query = array();
208 
209  add_filter( 'gform_gf_query_sql', $callback = function( $sql ) use ( &$sql_query ) {
210  $sql_query = $sql;
211  return $sql;
212  } );
213 
214  $total = $context->view->get_entries()->total();
215  remove_filter( 'gform_gf_query_sql', $callback );
216 
217  unset( $sql_query['paginate'] );
218 
219  global $wpdb;
220 
221  foreach ( $wpdb->get_results( implode( ' ', $sql_query ), ARRAY_A ) as $n => $result ) {
222  if ( in_array( $entry->ID, $result ) ) {
223  return $context->field->reverse ? ( $total - $n ) : ( $n + 1 );
224  }
225  }
226 
227  return 0;
228  } elseif ( ! isset( $startlines[ $context_key ] ) ) {
229  $pagenum = max( 0, \GV\Utils::_GET( 'pagenum', 1 ) - 1 );
230  $pagesize = $context->view->settings->get( 'page_size', 25 );
231 
232  if ( $context->field->reverse ) {
233  $startlines[ $context_key ] = $context->view->get_entries()->total() - ( $pagenum * $pagesize );
234  $startlines[ $context_key ] += $context->field->start - 1;
235  } else {
236  $startlines[ $context_key ] = ( $pagenum * $pagesize ) + $context->field->start;
237  }
238  }
239 
240  return $context->field->reverse ? $startlines[ $context_key ]-- : $startlines[ $context_key ]++;
241  }
242 }
243 
Modify field settings by extending this class.
static getInstance( $passed_post=NULL)
replace_merge_tag( $matches=array(), $text='', $form=array(), $entry=array(), $url_encode=false, $esc_html=false)
Replace {sequence} Merge Tags inside Custom Content fields.
gravityview_get_current_view_data( $view_id=0)
Get data for a specific view.
Definition: class-api.php:1020
gravityview()
Definition: _stubs.php:26
static from_entry( $entry)
Construct a instance from a Gravity Forms entry array.
get( $key, $default=null)
Retrieve a setting.
$gv_field
Definition: time.php:11
static by_id( $post_id)
Construct a instance from a post ID.
$field_id
Definition: time.php:17
field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id)
static by_id( $field_id)
Get a from an internal Gravity Forms field ID.
if(empty( $created_by)) $form_id
static get( $array, $key, $default=null)
Grab a value from an array or an object or default.
$entry
Definition: notes.php:27
get_sequence( $context)
Calculate the current sequence number for the context.