PluginProbe ʕ •ᴥ•ʔ
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More / 1.5.4.1
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More v1.5.4.1
1.10.1.1 1.10.1 1.10.0.5 trunk 1.1.4 1.1.4.2 1.1.5 1.1.5.1 1.1.6 1.1.6.1 1.1.7 1.1.7.1 1.1.7.2 1.1.8 1.1.8.1 1.1.8.2 1.1.8.3 1.1.8.4 1.10.0.1 1.10.0.2 1.10.0.3 1.10.0.4 1.2.0 1.2.0.1 1.2.1 1.2.2 1.2.2.1 1.2.2.2 1.2.3 1.2.3.1 1.2.3.2 1.2.4 1.2.4.1 1.2.5 1.2.5.1 1.2.6 1.2.7 1.2.8 1.2.8.1 1.2.9 1.3.0 1.3.1 1.3.1.1 1.3.1.2 1.3.2 1.3.3 1.3.5 1.3.6 1.3.6.1 1.3.6.2 1.3.7.2 1.3.7.3 1.3.7.4 1.3.8 1.3.9.1 1.4.0.1 1.4.1.1 1.4.2 1.4.2.1 1.4.2.2 1.4.3 1.4.4 1.4.4.1 1.4.5 1.4.5.1 1.4.5.2 1.4.5.3 1.4.6 1.4.7.1 1.4.7.2 1.4.8.1 1.4.9 1.5.0.1 1.5.0.3 1.5.0.4 1.5.1 1.5.1.1 1.5.1.3 1.5.2.1 1.5.2.2 1.5.2.3 1.5.3 1.5.3.1 1.5.4.1 1.5.4.2 1.5.5 1.5.5.1 1.5.6 1.5.6.2 1.5.7 1.5.8.2 1.5.9.1 1.5.9.4 1.5.9.5 1.6.0.1 1.6.0.2 1.6.1 1.6.2.2 1.6.2.3 1.6.3.1 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.7 1.6.7.1 1.6.7.2 1.6.7.3 1.6.8 1.6.8.1 1.6.9 1.7.0 1.7.1.1 1.7.1.2 1.7.2 1.7.2.1 1.7.3 1.7.4 1.7.4.1 1.7.4.2 1.7.5.1 1.7.5.2 1.7.5.3 1.7.5.5 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.7.9.1 1.8.0.1 1.8.0.2 1.8.1.1 1.8.1.2 1.8.1.3 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.3.1 1.8.4 1.8.4.1 1.8.5.2 1.8.5.3 1.8.5.4 1.8.6.2 1.8.6.3 1.8.6.4 1.8.7.2 1.8.8.2 1.8.8.3 1.8.9.1 1.8.9.2 1.8.9.4 1.8.9.5 1.8.9.6 1.9.0.1 1.9.0.2 1.9.0.3 1.9.0.4 1.9.1.1 1.9.1.2 1.9.1.3 1.9.1.4 1.9.1.5 1.9.1.6 1.9.2.1 1.9.2.2 1.9.2.3 1.9.3.1 1.9.3.2 1.9.4.1 1.9.4.2 1.9.5 1.9.5.1 1.9.5.2 1.9.6 1.9.6.1 1.9.6.2 1.9.7.1 1.9.7.2 1.9.7.3 1.9.8.1 1.9.8.2 1.9.8.4 1.9.8.7 1.9.9.2 1.9.9.3 1.9.9.4
wpforms-lite / includes / class-conditional-logic-core.php
wpforms-lite / includes Last commit date
admin 6 years ago analytics 7 years ago emails 7 years ago fields 6 years ago providers 7 years ago templates 7 years ago class-conditional-logic-core.php 7 years ago class-fields.php 7 years ago class-form.php 6 years ago class-frontend.php 6 years ago class-install.php 7 years ago class-license.php 6 years ago class-logging.php 7 years ago class-process.php 6 years ago class-providers.php 8 years ago class-smart-tags.php 6 years ago class-templates.php 8 years ago class-updater.php 6 years ago class-upgrader-skin.php 6 years ago class-widget.php 7 years ago functions.php 6 years ago integrations.php 7 years ago
class-conditional-logic-core.php
745 lines
1 <?php
2
3 /**
4 * Conditional logic core.
5 *
6 * Contains functionality for using conditional logic in the form builder as
7 * well as a global processing method that can be leveraged by all types of
8 * conditional logic.
9 *
10 * This was contained in an addon until version 1.3.8 when it was rolled into
11 * core.
12 *
13 * @package WPForms
14 * @author WPForms
15 * @since 1.3.8
16 * @license GPL-2.0+
17 * @copyright Copyright (c) 2017, WPForms LLC
18 */
19 class WPForms_Conditional_Logic_Core {
20
21 /**
22 * One is the loneliest number that you'll ever do.
23 *
24 * @since 1.1.0
25 * @var WPForms_Conditional_Logic_Core
26 */
27 private static $instance;
28
29 /**
30 * Main Instance.
31 *
32 * @since 1.1.0
33 * @return WPForms_Conditional_Logic_Core
34 */
35 public static function instance() {
36
37 if ( ! isset( self::$instance ) && ! ( self::$instance instanceof WPForms_Conditional_Logic_Core ) ) {
38 self::$instance = new WPForms_Conditional_Logic_Core;
39 add_action( 'wpforms_loaded', array( self::$instance, 'init' ), 10 );
40 }
41
42 return self::$instance;
43 }
44
45 /**
46 * Initialize.
47 *
48 * @since 1.0.0
49 */
50 public function init() {
51
52 // Form builder.
53 add_action( 'wpforms_builder_enqueues', array( $this, 'builder_assets' ) );
54 add_action( 'wpforms_builder_print_footer_scripts', array( $this, 'builder_footer_scripts' ) );
55 }
56
57 /**
58 * Enqueue assets for the builder.
59 *
60 * @since 1.0.0
61 */
62 public function builder_assets() {
63
64 // CSS.
65 wp_enqueue_style(
66 'wpforms-builder-conditionals',
67 WPFORMS_PLUGIN_URL . 'assets/css/admin-builder-conditional-logic-core.css',
68 array(),
69 WPFORMS_VERSION
70 );
71
72 // JavaScript.
73 wp_enqueue_script(
74 'wpforms-builder-conditionals',
75 WPFORMS_PLUGIN_URL . 'assets/js/admin-builder-conditional-logic-core.js',
76 array( 'jquery', 'wpforms-utils', 'wpforms-builder' ),
77 WPFORMS_VERSION,
78 false
79 );
80 }
81
82 /**
83 * Outputs footer scripts inside the form builder.
84 *
85 * @since 1.3.8
86 */
87 public function builder_footer_scripts() {
88
89 ?>
90 <script type="text/html" id="tmpl-wpforms-conditional-block">
91 <# var containerID = data.fieldName.replace(/]/g, '').replace(/\[/g, '-'); #>
92 <div class="wpforms-conditional-groups" id="wpforms-conditional-groups-{{ containerID }}">
93 <h4>
94 <select name="{{ data.fieldName }}[conditional_type]">
95 <# _.each(data.actions, function(key, val) { #>
96 <option value="{{ val }}">{{ key }}</option>
97 <# }) #>
98 </select>
99 {{ data.actionDesc }}
100 </h4>
101 <div class="wpforms-conditional-group" data-reference="{{ data.fieldID }}">
102 <table><tbody>
103 <tr class="wpforms-conditional-row" data-field-id="{{ data.fieldID }}" data-input-name="{{ data.fieldName }}">
104 <td class="field">
105 <select name="{{ data.fieldName }}[conditionals][0][0][field]" class="wpforms-conditional-field" data-groupid="0" data-ruleid="0">
106 <option value="">{{ wpforms_builder.select_field }}</option>
107 </select>
108 </td>
109 <td class="operator">
110 <select name="{{ data.fieldName }}[conditionals][0][0][operator]" class="wpforms-conditional-operator">
111 <option value="==">{{ wpforms_builder.operator_is }}</option>
112 <option value="!=">{{ wpforms_builder.operator_is_not }}</option>
113 <option value="e">{{ wpforms_builder.operator_empty }}</option>
114 <option value="!e">{{ wpforms_builder.operator_not_empty }}</option>
115 <option value="c">{{ wpforms_builder.operator_contains }}</option>
116 <option value="!c">{{ wpforms_builder.operator_not_contains }}</option>
117 <option value="^">{{ wpforms_builder.operator_starts }}</option>
118 <option value="~">{{ wpforms_builder.operator_ends }}</option>
119 <option value=">">{{ wpforms_builder.operator_greater_than }}</option>
120 <option value="<">{{ wpforms_builder.operator_less_than }}</option>
121 </select>
122 </td>
123 <td class="value">
124 <select name="{{ data.fieldName }}[conditionals][0][0][value]" class="wpforms-conditional-value">
125 <option value="">{{ wpforms_builder.select_choice }}</option>
126 </select>
127 </td>
128 <td class="actions">
129 <button class="wpforms-conditional-rule-add" title="{{ wpforms_builder.rule_create }}">{{ wpforms_builder.and }}</button><button class="wpforms-conditional-rule-delete" title="{{ wpforms_builder.rule_delete }}"><i class="fa fa-times-circle" aria-hidden="true"></i></button>
130 </td>
131 </tr>
132 </tbody></table>
133 <h5>{{ wpforms_builder.or }}</h5>
134 </div>
135 <button class="wpforms-conditional-groups-add">{{ wpforms_builder.rule_create_group }}</button>
136 </div>
137 </script>
138 <?php
139 }
140
141 /**
142 * Builds the conditional logic settings to display in the form builder.
143 *
144 * @since 1.3.8
145 *
146 * @param array $args Data needed for a block to be generated properly.
147 * @param bool $echo Whether to return or print. Default: print.
148 *
149 * @return string
150 */
151 public function builder_block( $args = array(), $echo = true ) {
152
153 if ( ! empty( $args['form'] ) ) {
154 $form_fields = wpforms_get_form_fields( $args['form'], wpforms_get_conditional_logic_form_fields_supported() );
155 } else {
156 $form_fields = array();
157 }
158
159 // Define data.
160 $type = ! empty( $args['type'] ) ? $args['type'] : 'field';
161 $panel = ! empty( $args['panel'] ) ? $args['panel'] : false; // notifications/connections.
162 $parent = ! empty( $args['parent'] ) ? $args['parent'] : false; // settings.
163 $subsection = ! empty( $args['subsection'] ) ? $args['subsection'] : false;
164 $field = ! empty( $args['field'] ) ? $args['field'] : false;
165 $reference = ! empty( $args['reference'] ) ? $args['reference'] : '';
166 $data_attrs = '';
167
168 ob_start();
169
170 // Block open markup.
171 printf(
172 '<div class="wpforms-conditional-block wpforms-conditional-block-%s" data-type="%s">',
173 esc_attr( $type ),
174 esc_attr( $type )
175 );
176
177 switch ( $type ) {
178 case 'field':
179 /*
180 * This settings block is for a field.
181 */
182
183 // Define more data for this field.
184 $fields_instance = $args['instance'];
185 $field_id = absint( $field['id'] );
186 $field_name = "fields[{$field_id}]";
187 $groups_id = "wpforms-conditional-groups-fields-{$field_id}";
188 $action_selected = ! empty( $field['conditional_type'] ) ? $field['conditional_type'] : '';
189 $conditionals = ! empty( $field['conditionals'] ) ? $field['conditionals'] : array( array( array() ) );
190 $data_attrs = 'data-field-id="' . $field_id . '" ';
191 $reference = $field_id;
192 $enabled = isset( $field['conditional_logic'] ) ? $field['conditional_logic'] : false;
193 $action_desc = ! empty( $args['action_desc'] ) ? $args['action_desc'] : esc_html__( 'this field if', 'wpforms-lite' );
194
195 if ( empty( $args['actions'] ) ) {
196 $actions = array(
197 'show' => esc_attr__( 'Show', 'wpforms-lite' ),
198 'hide' => esc_attr__( 'Hide', 'wpforms-lite' ),
199 );
200 } else {
201 $actions = array_map( 'esc_attr', $args['actions'] );
202 }
203
204 // Output Conditional Logic toggle checkbox field option.
205 $fld = $fields_instance->field_element(
206 'checkbox',
207 $field,
208 array(
209 'slug' => 'conditional_logic',
210 'value' => $enabled,
211 'desc' => esc_html__( 'Enable conditional logic', 'wpforms-lite' ),
212 'tooltip' => '<a href="https://wpforms.com/docs/how-to-use-conditional-logic-with-wpforms/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'How to use Conditional Logic', 'wpforms-lite' ) . '</a>',
213 'data' => array(
214 'name' => $field_name,
215 'actions' => $actions,
216 'action-desc' => esc_attr( $action_desc ),
217 ),
218 ),
219 false
220 );
221 $fields_instance->field_element(
222 'row',
223 $field,
224 array(
225 'slug' => 'conditional_logic',
226 'content' => $fld,
227 'class' => 'wpforms-conditionals-enable-toggle',
228 )
229 );
230
231 // Prevent conditional logic from being applied to itself.
232 if ( ! empty( $form_fields[ $field['id'] ] ) ) {
233 unset( $form_fields[ $field['id'] ] );
234 }
235 break;
236
237 case 'panel':
238 /*
239 * This settings block is for something else - connections / notifications etc.
240 */
241
242 $form_data = $args['form'];
243
244 $action_desc = ! empty( $args['action_desc'] ) ? $args['action_desc'] : esc_html__( 'this connection if', 'wpforms-lite' );
245
246 if ( empty( $args['actions'] ) ) {
247 $actions = array(
248 'go' => esc_attr__( 'Process', 'wpforms-lite' ),
249 'stop' => esc_attr__( 'Don\'t process', 'wpforms-lite' ),
250 );
251 } else {
252 $actions = array_map( 'esc_attr', $args['actions'] );
253 }
254
255 // Below we do a bunch of voodoo to determine where this block
256 // is located in the form builder - eg is it in a top level
257 // setting or in a subsection, etc.
258 if ( ! empty( $parent ) ) {
259 if ( ! empty( $subsection ) ) {
260 $field_name = sprintf( '%s[%s][%s]', $parent, $panel, $subsection );
261 $groups_id = sprintf( 'wpforms-conditional-groups-%s-%s-%s', $parent, $panel, $subsection );
262 $enabled = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditional_logic'] ) ? true : false;
263 $action_selected = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditional_type'] ) ? $form_data[ $parent ][ $panel ][ $subsection ]['conditional_type'] : '';
264 $conditionals = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditionals'] ) ? $form_data[ $parent ][ $panel ][ $subsection ]['conditionals'] : array( array( array() ) );
265 } else {
266 $field_name = sprintf( '%s[%s]', $parent, $panel );
267 $groups_id = sprintf( 'wpforms-conditional-groups-%s-%s', $parent, $panel );
268 $enabled = ! empty( $form_data[ $parent ][ $panel ]['conditional_logic'] ) ? true : false;
269 $action_selected = ! empty( $form_data[ $parent ][ $panel ]['conditional_type'] ) ? $form_data[ $parent ][ $panel ]['conditional_type'] : '';
270 $conditionals = ! empty( $form_data[ $parent ][ $panel ]['conditionals'] ) ? $form_data[ $parent ][ $panel ]['conditionals'] : array( array( array() ) );
271 }
272 } else {
273 $field_name = sprintf( '%s', $panel );
274 $groups_id = sprintf( 'wpforms-conditional-groups-%s', $panel );
275 $enabled = ! empty( $form_data[ $panel ]['conditional_logic'] ) ? true : false;
276 $action_selected = ! empty( $form_data[ $panel ]['conditional_type'] ) ? $form_data[ $panel ]['conditional_type'] : '';
277 $conditionals = ! empty( $form_data[ $panel ]['conditionals'] ) ? $form_data[ $panel ]['conditionals'] : array( array( array() ) );
278 }
279
280 // Output Conditional Logic toggle checkbox panel setting.
281 wpforms_panel_field(
282 'checkbox',
283 $panel,
284 'conditional_logic',
285 $args['form'],
286 esc_html__( 'Enable conditional logic', 'wpforms-lite' ),
287 array(
288 'tooltip' => '<a href="https://wpforms.com/docs/how-to-use-conditional-logic-with-wpforms/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'How to use Conditional Logic', 'wpforms-lite' ) . '</a>',
289 'parent' => $parent,
290 'subsection' => $subsection,
291 'input_id' => 'wpforms-panel-field-' . implode( '-', array_filter( array( $parent, $panel, $subsection, 'conditional_logic', 'checkbox' ) ) ),
292 'input_class' => 'wpforms-panel-field-conditional_logic-checkbox',
293 'class' => 'wpforms-conditionals-enable-toggle',
294 'data' => array(
295 'name' => $field_name,
296 'actions' => $actions,
297 'action-desc' => esc_attr( $action_desc ),
298 ),
299 )
300 );
301 break;
302
303 default:
304 $enabled = false;
305 $field_name = '';
306 $reference = '';
307 $action_selected = '';
308 $action_desc = '';
309 $groups_id = '';
310 $actions = array();
311 $conditionals = array();
312 }
313
314 // Only display the block details if conditional logic is enabled.
315 if ( $enabled ) :
316
317 $data_attrs .= 'data-input-name="' . esc_attr( $field_name ) . '"';
318 $style = $enabled ? '' : 'display:none;';
319
320 // Groups wrap open markup.
321 printf(
322 '<div class="wpforms-conditional-groups" id="%s" style="%s">',
323 sanitize_html_class( $groups_id ),
324 esc_attr( $style )
325 );
326
327 // This is the "[Show] this field if" type text and setting.
328 echo '<h4>';
329 echo '<select name="' . esc_attr( $field_name ) . '[conditional_type]">';
330 foreach ( $actions as $key => $label ) {
331 printf(
332 '<option value="%s" %s>%s</option>',
333 esc_attr( trim( $key ) ),
334 selected( $key, $action_selected, false ),
335 esc_html( $label )
336 );
337 }
338 echo '</select>';
339 echo esc_html( $action_desc ); // Eg "this field if".
340 echo '</h4>';
341
342 // Go through each conditional logic group.
343 foreach ( $conditionals as $group_id => $group ) :
344
345 // Individual group open markup.
346 echo '<div class="wpforms-conditional-group" data-reference="' . $reference . '">';
347
348 echo '<table><tbody>';
349
350 foreach ( $group as $rule_id => $rule ) :
351
352 $selected_current = false;
353
354 // Individual rule table row.
355 echo '<tr class="wpforms-conditional-row" ' . $data_attrs . '>';
356
357 // Rule field - allows the user to select
358 // which field the conditional logic rule is
359 // anchored to.
360 echo '<td class="field">';
361
362 printf(
363 '<select name="%s[conditionals][%d][%d][field]" class="wpforms-conditional-field" data-groupid="%d" data-ruleid="%d">',
364 esc_attr( $field_name ),
365 (int) $group_id,
366 (int) $rule_id,
367 (int) $group_id,
368 (int) $rule_id
369 );
370
371 echo '<option value="">' . esc_html__( '--- Select Field ---', 'wpforms-lite' ) . '</option>';
372
373 if ( ! empty( $form_fields ) ) {
374
375 foreach ( $form_fields as $form_field ) {
376
377 // Exclude fields that are
378 // leveraging dynamic choices.
379 if ( ! empty( $form_field['dynamic_choices'] ) ) {
380 continue;
381 }
382
383 if ( isset( $rule['field'] ) ) {
384 $selected = $rule['field'];
385 $selected_current = $rule['field'];
386 } else {
387 $selected = false;
388 }
389
390 $selected = selected( $selected, $form_field['id'], false );
391 printf( '<option value="%s" %s>%s</option>', absint( $form_field['id'] ), $selected, esc_html( $form_field['label'] ) );
392 }
393 }
394
395 echo '</select>';
396
397 echo '</td>';
398
399 // Rule operator - allows the user to
400 // determine the comparison operator used
401 // for processing.
402 echo '<td class="operator">';
403
404 printf(
405 '<select name="%s[conditionals][%s][%s][operator]" class="wpforms-conditional-operator">',
406 $field_name,
407 $group_id,
408 $rule_id
409 );
410
411 $operator = ! empty( $rule['operator'] ) ? $rule['operator'] : false;
412 printf( '<option value="==" %s>%s</option>', selected( $operator, '==', false ), esc_html__( 'is', 'wpforms-lite' ) );
413 printf( '<option value="!=" %s>%s</option>', selected( $operator, '!=', false ), esc_html__( 'is not', 'wpforms-lite' ) );
414 printf( '<option value="e" %s>%s</option>', selected( $operator, 'e', false ), esc_html__( 'empty', 'wpforms-lite' ) );
415 printf( '<option value="!e" %s>%s</option>', selected( $operator, '!e', false ), esc_html__( 'not empty', 'wpforms-lite' ) );
416
417 // Only text based fields support
418 // these additional operators.
419 $disabled = '';
420 if ( ! empty( $form_fields[ $rule['field'] ]['type'] ) ) {
421 $disabled = in_array( $form_fields[ $rule['field'] ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'net_promoter_score' ), true ) ? '' : ' disabled';
422 }
423
424 printf( '<option value="c" %s%s>%s</option>', selected( $operator, 'c', false ), $disabled, esc_html__( 'contains', 'wpforms-lite' ) );
425 printf( '<option value="!c" %s%s>%s</option>', selected( $operator, '!c', false ), $disabled, esc_html__( 'does not contain', 'wpforms-lite' ) );
426 printf( '<option value="^" %s%s>%s</option>', selected( $operator, '^', false ), $disabled, esc_html__( 'starts with', 'wpforms-lite' ) );
427 printf( '<option value="~" %s%s>%s</option>', selected( $operator, '~', false ), $disabled, esc_html__( 'ends with', 'wpforms-lite' ) );
428 printf( '<option value=">" %s%s>%s</option>', selected( $operator, '>', false ), $disabled, esc_html__( 'greater than', 'wpforms-lite' ) );
429 printf( '<option value="<" %s%s>%s</option>', selected( $operator, '<', false ), $disabled, esc_html__( 'less than', 'wpforms-lite' ) );
430
431 echo '</select>';
432
433 echo '</td>';
434
435 // Rule value - allows the user to
436 // determine the value we are using for
437 // comparison.
438 echo '<td class="value">';
439
440 if ( isset( $rule['field'] ) ) {
441
442 // For empty/not empty fields the field value input is not needed so we disable it.
443 if ( ! empty( $rule['operator'] ) && in_array( $rule['operator'], array( 'e', '!e' ), true ) ) {
444 $disabled = 'disabled';
445 $rule['value'] = '';
446 } else {
447 $disabled = '';
448 }
449
450 if ( isset( $form_fields[ $rule['field'] ]['type'] ) && in_array( $form_fields[ $rule['field'] ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'net_promoter_score' ), true ) ) {
451
452 $type = in_array( $form_fields[ $rule['field'] ]['type'], array( 'rating', 'net_promoter_score' ), true ) ? 'number' : 'text';
453
454 printf(
455 '<input type="%s" name="%s[conditionals][%s][%s][value]" value="%s" class="wpforms-conditional-value" %s>',
456 $type,
457 $field_name,
458 $group_id,
459 $rule_id,
460 esc_attr( $rule['value'] ),
461 $disabled
462 );
463
464 } else {
465
466 printf(
467 '<select name="%s[conditionals][%s][%s][value]" class="wpforms-conditional-value" %d>',
468 $field_name,
469 $group_id,
470 $rule_id,
471 $disabled
472 );
473
474 echo '<option value="">' . esc_html__( '--- Select Choice ---', 'wpforms-lite' ) . '</option>';
475
476 if ( ! empty( $form_fields[ $rule['field'] ]['choices'] ) ) {
477
478 foreach ( $form_fields[ $rule['field'] ]['choices'] as $option_id => $option ) {
479 $value = isset( $rule['value'] ) ? $rule['value'] : '';
480 $selected = selected( $option_id, $value, false );
481 printf( '<option value="%s" %s>%s</option>', $option_id, $selected, esc_html( $option['label'] ) );
482 }
483 }
484
485 echo '</select>';
486 }
487 } else {
488 echo '<select></select>';
489 } // End if().
490 echo '</td>';
491
492 // Rule actions.
493 echo '<td class="actions">';
494 echo '<button class="wpforms-conditional-rule-add" title="' . esc_attr__( 'Create new rule', 'wpforms-lite' ) . '">' . esc_html_x( 'AND', 'Conditional Logic: new rule logic.', 'wpforms-lite' ) . '</button>';
495 echo '<button class="wpforms-conditional-rule-delete" title="' . esc_attr__( 'Delete rule', 'wpforms-lite' ) . '"><i class="fa fa-times-circle" aria-hidden="true"></i></button>';
496 echo '</td>';
497
498 echo '</tr>'; // Close individual rule table row.
499
500 endforeach; // End foreach() for individual rules.
501
502 echo '</tbody></table>';
503
504 echo '<h5>' . esc_html_x( 'or', 'Conditional Logic: new rule logic.', 'wpforms-lite' ) . '</h5>';
505
506 echo '</div>'; // Close individual group markup.
507
508 endforeach; // End foreach() for conditional logic groups.
509
510 echo '<button class="wpforms-conditional-groups-add">' . esc_html__( 'Add rule group', 'wpforms-lite' ) . '</button>';
511
512 echo '</div>'; // Close Groups wrap markup.
513
514 endif; // End $enabled.
515
516 echo '</div>'; // Close block markup.
517
518 $output = ob_get_clean();
519
520 if ( $echo ) {
521 echo $output; //phpcs:ignore
522 } else {
523 return $output;
524 }
525 }
526
527 /**
528 * Alias method for backwards compatibility.
529 *
530 * @since 1.1.0
531 * @deprecated 1.3.8 Use wpforms_conditional_logic()->builder_block() instead.
532 *
533 * @param array $args Data needed for a block to be generated properly.
534 * @param bool $echo Whether to return or print. Default: print.
535 *
536 * @return string
537 */
538 public function conditionals_block( $args = array(), $echo = true ) {
539
540 if ( $echo ) {
541 echo $this->builder_block( $args, $echo ); //phpcs:ignore
542 } else {
543 return $this->builder_block( $args, $echo );
544 }
545 }
546
547 /**
548 * Process conditional rules.
549 *
550 * Checks if a form passes the conditional logic rules that are provided.
551 *
552 * @since 1.3.8
553 *
554 * @param array $fields List of fields with data and settings.
555 * @param array $form_data Form data and settings.
556 * @param array $conditionals List of conditionals.
557 *
558 * @return bool
559 */
560 public function process( $fields, $form_data, $conditionals ) {
561
562 if ( empty( $conditionals ) ) {
563 return true;
564 }
565
566 $pass = false;
567
568 foreach ( $conditionals as $group_id => $group ) {
569
570 $pass_group = true;
571
572 if ( ! empty( $group ) ) {
573
574 foreach ( $group as $rule_id => $rule ) {
575
576 if ( ! isset( $rule['field'] ) || '' == $rule['field'] || ! isset( $rule['operator'] ) ) {
577 continue;
578 }
579
580 if ( ! isset( $rule['value'] ) && ! in_array( $rule['operator'], array( 'e', '!e' ), true ) ) {
581 continue;
582 }
583
584 $rule_field = $rule['field'];
585 $rule_operator = $rule['operator'];
586 $rule_value = isset( $rule['value'] ) ? $rule['value'] : '';
587
588 if ( in_array( $fields[ $rule_field ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'net_promoter_score' ), true ) ) {
589
590 // Text based fields.
591 $left = trim( strtolower( $fields[ $rule_field ]['value'] ) );
592 $right = trim( strtolower( $rule_value ) );
593
594 switch ( $rule_operator ) {
595 case '==':
596 $pass_rule = ( $left == $right );
597 break;
598 case '!=':
599 $pass_rule = ( $left != $right );
600 break;
601 case 'c':
602 $pass_rule = ( strpos( $left, $right ) !== false );
603 break;
604 case '!c':
605 $pass_rule = ( strpos( $left, $right ) === false );
606 break;
607 case '^':
608 $pass_rule = ( strrpos( $left, $right, -strlen( $left ) ) !== false );
609 break;
610 case '~':
611 $pass_rule = ( ( $temp = strlen( $left ) - strlen( $right ) ) >= 0 && strpos( $left, $right, $temp ) !== false );
612 break;
613 case 'e':
614 $pass_rule = ( '' == $left );
615 break;
616 case '!e':
617 $pass_rule = ( '' != $left );
618 break;
619 case '>':
620 $left = preg_replace( '/[^0-9.]/', '', $left );
621 $pass_rule = ( '' !== $left ) && ( floatval( $left ) > floatval( $right ) );
622 break;
623 case '<':
624 $left = preg_replace( '/[^0-9.]/', '', $left );
625 $pass_rule = ( '' !== $left ) && ( floatval( $left ) < floatval( $right ) );
626 break;
627 default:
628 $pass_rule = apply_filters( 'wpforms_process_conditional_logic', false, $rule_operator, $left, $right );
629 break;
630 }
631 } else {
632
633 // Selector based fields.
634 $provided_id = false;
635
636 if (
637 in_array( $fields[ $rule_field ]['type'], array( 'payment-multiple', 'payment-checkbox', 'payment-select' ), true ) &&
638 isset( $fields[ $rule_field ]['value_raw'] ) &&
639 '' != $fields[ $rule_field ]['value_raw']
640 ) {
641
642 // Payment Multiple/Checkbox fields store the option key,
643 // so we can reference that easily.
644 $provided_id = $fields[ $rule_field ]['value_raw'];
645
646 } elseif ( isset( $fields[ $rule_field ]['value'] ) && '' != $fields[ $rule_field ]['value'] ) {
647
648 // Other select type fields we don't store the
649 // option key so we have to do the logic to locate
650 // it ourselves.
651 $provided_id = array();
652
653 if ( 'checkbox' === $fields[ $rule_field ]['type'] ) {
654 $values = explode( "\n", $fields[ $rule_field ]['value'] );
655 } else {
656 $values = (array) $fields[ $rule_field ]['value'];
657 }
658
659 foreach ( $form_data['fields'][ $rule_field ]['choices'] as $key => $choice ) {
660
661 $choice = array_map( 'sanitize_text_field', $choice );
662
663 foreach ( $values as $value ) {
664 $value = wpforms_decode_string( $value );
665
666 if ( in_array( $value, $choice, true ) ) {
667 $provided_id[] = $key;
668 }
669 }
670 }
671 }
672
673 $left = (array) $provided_id;
674 $right = strtolower( trim( (int) $rule_value ) );
675
676 switch ( $rule_operator ) {
677 case '==':
678 case 'c': // BC, no longer available.
679 case '^': // BC, no longer available.
680 case '~': // BC, no longer available.
681 $pass_rule = in_array( $right, $left );
682 break;
683 case '!=':
684 case '!c': // BC, no longer available.
685 $pass_rule = ! in_array( $right, $left );
686 break;
687 case 'e':
688 $pass_rule = ( false === $left[0] );
689 break;
690 case '!e':
691 $pass_rule = ( false !== $left[0] );
692 break;
693 default:
694 $pass_rule = apply_filters( 'wpforms_process_conditional_logic', false, $rule_operator, $left, $right );
695 break;
696 }
697 } // End if().
698
699 if ( ! $pass_rule ) {
700 $pass_group = false;
701 break;
702 }
703 } // End foreach().
704 } // End if().
705
706 if ( $pass_group ) {
707 $pass = true;
708 }
709 } // End foreach().
710
711 return $pass;
712 }
713
714 /**
715 * Alias function for backwards compatibility.
716 *
717 * @since 1.0.0
718 *
719 * @param array $fields List of fields with data and settings.
720 * @param array $form_data Form data and settings.
721 * @param array $conditionals List of conditionals.
722 *
723 * @return bool
724 */
725 public function conditionals_process( $fields, $form_data, $conditionals ) {
726 return $this->process( $fields, $form_data, $conditionals );
727 }
728 }
729
730 /**
731 * The function which returns the one WPForms_Conditional_Logic_Core instance.
732 *
733 * Use this function like you would a global variable, except without needing
734 * to declare the global.
735 *
736 * @since 1.1.0
737 *
738 * @return WPForms_Conditional_Logic_Core
739 */
740 function wpforms_conditional_logic() {
741 return WPForms_Conditional_Logic_Core::instance();
742 }
743
744 wpforms_conditional_logic();
745