GravityView  1.19.4
The best, easiest way to display Gravity Forms entries on your website.
class-gvlogic-shortcode.php
Go to the documentation of this file.
1 <?php
2 
3 /**
4  * Shortcode to handle showing/hiding content in merge tags. Works great with GravityView Custom Content fields
5  */
7 
8  private static $SUPPORTED_SCALAR_OPERATORS = array( 'is', 'isnot', 'contains', 'starts_with', 'ends_with' );
9 
10  private static $SUPPORTED_NUMERIC_OPERATORS = array( 'greater_than', 'less_than' );
11 
12  private static $SUPPORTED_ARRAY_OPERATORS = array( 'in', 'not_in', 'isnot', 'contains' );
13 
14  private static $SUPPORTED_CUSTOM_OPERATORS = array( 'equals', 'greater_than_or_is', 'greater_than_or_equals', 'less_than_or_is', 'less_than_or_equals', 'not_contains' );
15 
16  /**
17  * Attributes passed to the shortcode
18  * @var array
19  */
21 
22  /**
23  * Content inside the shortcode, displayed if matched
24  * @var string
25  */
27 
28  /**
29  * Parsed attributes
30  * @var array
31  */
32  var $atts = array();
33 
34  /**
35  * Parsed content, shown if matched
36  * @var string
37  */
38  var $content = '';
39 
40  /**
41  * Content shown if not matched
42  * This is set by having `[else]` inside the $content block
43  * @var string
44  */
45  var $else_content = '';
46 
47  /**
48  * The current shortcode name being processed
49  * @var string
50  */
51  var $shortcode = 'gvlogic';
52 
53  /**
54  * The left side of the comparison
55  * @var string
56  */
57  var $if = '';
58 
59  /**
60  * The right side of the comparison
61  * @var string
62  */
63  var $comparison = '';
64 
65  /**
66  * The comparison operator
67  * @var string
68  */
69  var $operation = 'is';
70 
71  /**
72  * Does the comparison pass?
73  * @var bool
74  */
75  var $is_match = false;
76 
77  /**
78  * @var GVLogic_Shortcode
79  */
80  private static $instance;
81 
82  /**
83  * Instantiate!
84  * @return GVLogic_Shortcode
85  */
86  public static function get_instance() {
87 
88  if( empty( self::$instance ) ) {
89  self::$instance = new self;
90  }
91 
92  return self::$instance;
93  }
94 
95  /**
96  * Add the WordPress hooks
97  * @return void
98  */
99  private function __construct() {
100  $this->add_hooks();
101  }
102 
103  /**
104  * Register the shortcode
105  * @return void
106  */
107  function add_hooks() {
108  add_shortcode( 'gvlogic', array( $this, 'shortcode' ) );
109  }
110 
111  /**
112  * Get array of supported operators
113  * @param bool $with_values
114  *
115  * @return array
116  */
117  function get_operators( $with_values = false ) {
118 
119  $operators = array_merge( self::$SUPPORTED_ARRAY_OPERATORS, self::$SUPPORTED_NUMERIC_OPERATORS, self::$SUPPORTED_SCALAR_OPERATORS, self::$SUPPORTED_CUSTOM_OPERATORS );
120 
121  if( $with_values ) {
122  $operators_with_values = array();
123  foreach( $operators as $key ) {
124  $operators_with_values[ $key ] = '';
125  }
126  return $operators_with_values;
127  } else {
128  return $operators;
129  }
130  }
131 
132  /**
133  * Set the operation for the shortcode.
134  * @param string $operation
135  *
136  * @return bool True: it's an allowed operation type and was added. False: invalid operation type
137  */
138  function set_operation( $operation = '' ) {
139 
140  if( empty( $operation ) ) {
141  return false;
142  }
143 
144  $operators = $this->get_operators( false );
145 
146  if( !in_array( $operation, $operators ) ) {
147  do_action( 'gravityview_log_debug', __METHOD__ .' Attempted to add invalid operation type.', $operation );
148  return false;
149  }
150 
151  $this->operation = $operation;
152  return true;
153  }
154 
155  /**
156  * Set the operation and comparison for the shortcode
157  *
158  * Loop through each attribute passed to the shortcode and see if it's a valid operator. If so, set it.
159  * Example: [gvlogic if="{example}" greater_than="5"]
160  * `greater_than` will be set as the operator
161  * `5` will be set as the comparison value
162  *
163  * @return bool True: we've got an operation and comparison value; False: no, we don't
164  */
165  private function setup_operation_and_comparison() {
166 
167  foreach( $this->atts as $key => $value ) {
168 
169  $valid = $this->set_operation( $key );
170 
171  if( $valid ) {
172  $this->comparison = $value;
173  return true;
174  }
175  }
176 
177  return false;
178  }
179 
180  /**
181  * @param array $atts User defined attributes in shortcode tag.
182  * @param null $content
183  * @param string $shortcode_tag
184  *
185  * @return string|null
186  */
187  public function shortcode( $atts = array(), $content = NULL, $shortcode_tag = '' ) {
188 
189  // Don't process except on frontend
191  return null;
192  }
193 
194  if( empty( $atts ) ) {
195  do_action( 'gravityview_log_error', __METHOD__.' $atts are empty.', $atts );
196  return null;
197  }
198 
199  $this->passed_atts = $atts;
200  $this->passed_content = $content;
201  $this->shortcode = $shortcode_tag;
202 
203  $this->parse_atts();
204 
205  // We need an "if"
206  if( false === $this->if ) {
207  do_action( 'gravityview_log_error', __METHOD__.' $atts->if is empty.', $this->passed_atts );
208  return null;
209  }
210 
211  $setup = $this->setup_operation_and_comparison();
212 
213  // We need an operation and comparison value
214  if( ! $setup ) {
215  do_action( 'gravityview_log_error', __METHOD__.' No valid operators were passed.', $this->atts );
216  return null;
217  }
218 
219  // Set the content and else_content
221 
222  // Check if it's a match
223  $this->set_is_match();
224 
225  // Return the value!
226  $output = $this->get_output();
227 
228  return $output;
229  }
230 
231  /**
232  * Does the if and the comparison match?
233  * @uses GVCommon::matches_operation
234  *
235  * @return boolean True: yep; false: nope
236  */
237  private function set_is_match() {
238  $this->is_match = GVCommon::matches_operation( $this->if, $this->comparison, $this->operation );
239  }
240 
241  /**
242  * Get the output for the shortcode, based on whether there's a matched value
243  *
244  * @return string HTML/Text output of the shortcode
245  */
246  private function get_output() {
247 
248  if( $this->is_match ) {
250  } else {
252  }
253 
254  // Get recursive!
255  $output = do_shortcode( $output );
256 
257  /**
258  * @filter `gravityview/gvlogic/output` Modify the [gvlogic] output
259  * @param string $output HTML/text output
260  * @param GVLogic_Shortcode $this This class
261  */
262  $output = apply_filters('gravityview/gvlogic/output', $output, $this );
263 
264  do_action( 'gravityview_log_debug', __METHOD__ .' Output: ', $output );
265 
266  return $output;
267  }
268 
269  /**
270  * Check for `[else]` tag inside the shortcode content. If exists, set the else_content variable.
271  * If not, use the `else` attribute passed by the shortcode, if exists.
272  *
273  * @todo allow for chains of [else if="{another field:123}" is="example"] - requires registering [else] shortcode...
274  * @return void
275  */
276  private function set_content_and_else_content() {
277 
278  $content = explode( '[else]', $this->passed_content );
279 
280  $this->content = $content[0];
281 
282  $else_attr = isset( $this->atts['else'] ) ? $this->atts['else'] : NULL;
283 
284  $this->else_content = isset( $content[1] ) ? $content[1] : $else_attr;
285  }
286 
287  /**
288  * Process the attributes passed to the shortcode. Make sure they're valid
289  * @return void
290  */
291  private function parse_atts() {
292 
293  $supported = array(
294  'if' => false,
295  'else' => false,
296  );
297 
298  $supported_args = $supported + $this->get_operators( true );
299 
300  // Whittle down the attributes to only valid pairs
301  $this->atts = shortcode_atts( $supported_args, $this->passed_atts, $this->shortcode );
302 
303  // Only keep the passed attributes after making sure that they're valid pairs
304  $this->atts = function_exists( 'array_intersect_key' ) ? array_intersect_key( $this->passed_atts, $this->atts ) : $this->atts;
305 
306  // Strip whitespace if it's not default false
307  $this->if = ( isset( $this->atts['if'] ) && is_string( $this->atts['if'] ) ) ? trim( $this->atts['if'] ) : false;
308 
309  // Make sure the "if" isn't processed in self::setup_operation_and_comparison()
310  unset( $this->atts['if'] );
311  }
312 }
313 
parse_atts()
Process the attributes passed to the shortcode.
add_hooks()
Register the shortcode.
__construct()
Add the WordPress hooks.
static get_instance()
Instantiate!
set_content_and_else_content()
Check for [else] tag inside the shortcode content.
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;, and &#39;not_contains&#39;.
static is_admin()
Check if is_admin(), and make sure not DOING_AJAX.
set_is_match()
Does the if and the comparison match? GVCommon::matches_operation.
shortcode($atts=array(), $content=NULL, $shortcode_tag= '')
setup_operation_and_comparison()
Set the operation and comparison for the shortcode.
Shortcode to handle showing/hiding content in merge tags.
get_operators($with_values=false)
Get array of supported operators.
get_output()
Get the output for the shortcode, based on whether there&#39;s a matched value.
set_operation($operation= '')
Set the operation for the shortcode.