PluginProbe ʕ •ᴥ•ʔ
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More / 1.3.6.1
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More v1.3.6.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-frontend.php
wpforms-lite / includes Last commit date
admin 9 years ago emails 9 years ago fields 9 years ago providers 9 years ago templates 9 years ago class-fields.php 9 years ago class-form.php 9 years ago class-frontend.php 9 years ago class-install.php 9 years ago class-logging.php 9 years ago class-preview.php 9 years ago class-process.php 9 years ago class-providers.php 9 years ago class-smart-tags.php 9 years ago class-templates.php 9 years ago class-widget.php 10 years ago functions.php 9 years ago integrations.php 9 years ago
class-frontend.php
915 lines
1 <?php
2 /**
3 * Form front-end rendering.
4 *
5 * @package WPForms
6 * @author WPForms
7 * @since 1.0.0
8 * @license GPL-2.0+
9 * @copyright Copyright (c) 2016, WPForms LLC
10 */
11 class WPForms_Frontend {
12
13 /**
14 * Contains form data to be referenced later.
15 *
16 * @since 1.0.0
17 * @var array
18 */
19 public $forms;
20
21 /**
22 * Primary class constructor.
23 *
24 * @since 1.0.0
25 */
26 public function __construct() {
27
28 $this->forms = array();
29
30 // Actions
31 add_action( 'wpforms_frontend_output_success', array( $this, 'confirmation' ), 10, 2 );
32 add_action( 'wpforms_frontend_output', array( $this, 'head' ), 5, 5 );
33 add_action( 'wpforms_frontend_output', array( $this, 'page_indicator' ), 10, 5 );
34 add_action( 'wpforms_frontend_output', array( $this, 'fields' ), 10, 5 );
35 add_action( 'wpforms_frontend_output', array( $this, 'honeypot' ), 15, 5 );
36 add_action( 'wpforms_frontend_output', array( $this, 'recaptcha' ), 20, 5 );
37 add_action( 'wpforms_frontend_output', array( $this, 'foot' ), 25, 5 );
38 add_action( 'wp_enqueue_scripts', array( $this, 'assets_header' ) );
39 add_action( 'wp_footer', array( $this, 'assets_footer' ), 15 );
40 add_action( 'wp_footer', array( $this, 'footer_end' ), 99 );
41
42 // Register shortcode
43 add_shortcode( 'wpforms', array( $this, 'shortcode' ) );
44 }
45
46 /**
47 * Primary function to render a form on the frontend.
48 *
49 * @since 1.0.0
50 * @param int $id
51 * @param boolean $title
52 * @param boolean $description
53 */
54 public function output( $id, $title = false, $description = false ) {
55
56 if ( empty( $id ) )
57 return;
58
59 // Grab the form data, if not found then we bail
60 $form = wpforms()->form->get( (int) $id );
61
62 if ( empty( $form ) )
63 return;
64
65 // Basic information
66 $form_data = wpforms_decode( $form->post_content, true );
67 $form_id = absint( $form->ID );
68 $settings = $form_data['settings'];
69 $action = esc_url_raw( remove_query_arg( 'wpforms' ) );
70 $class[] = wpforms_setting( 'disable-css', '1' ) == '1' ? 'wpforms-container-full' : '';
71 $errors = empty( wpforms()->process->errors[$form->ID] ) ? array() : wpforms()->process->errors[$form->ID];
72 $success = false;
73 $title = filter_var( $title, FILTER_VALIDATE_BOOLEAN );
74 $description = filter_var( $description, FILTER_VALIDATE_BOOLEAN );
75
76 // If the form does not contain any fields do not proceed
77 if ( empty( $form_data['fields'] ) ) {
78 echo '<!-- WPForms: no fields, form hidden -->';
79 return;
80 }
81
82 // Before output hook
83 do_action( 'wpforms_frontend_output_before', $form_data, $form );
84
85 // Check for return hash OR error free completed form and confirmation before we continue
86 if ( !empty( $_GET['wpforms_return'] ) ) {
87 $success = wpforms()->process->validate_return_hash( $_GET['wpforms_return'] );
88 if ( $success ) {
89 $form_data = wpforms()->form->get( $success, array( 'content_only' => true ) );
90 }
91 } elseif ( !empty( $_POST['wpforms']['id'] ) && $form->ID == $_POST['wpforms']['id'] && empty( $errors ) ) {
92 $success = true;
93 }
94 if ( $success && !empty( $form_data ) ) {
95
96 do_action( 'wpforms_frontend_output_success', $form_data );
97
98 // Debug
99 wpforms_debug_data( $_POST );
100
101 return;
102 }
103
104 // Allow filter to return early if some condition is not met.
105 if ( ! apply_filters( 'wpforms_frontend_load', true, $form_data, $form ) ) {
106 return;
107 }
108
109 // Prep the form action URL, allow filter
110 if ( !empty( $settings['confirmation_type'] ) && 'message' == $settings['confirmation_type'] && !empty( $settings['confirmation_message_scroll'] ) ) {
111 $action .= '#wpforms-' . $form_id;
112 }
113 $action = apply_filters( 'wpforms_frontend_form_action', $action, $form_data, $form );
114
115 // Allow form container classes to be filtered
116 $class = array_map( 'sanitize_html_class', apply_filters( 'wpforms_frontend_container_class', $class, $form_data ) );
117
118 if ( !empty( $form_data['settings']['form_class'] ) ) {
119 $class = array_merge( $class, array_map('sanitize_html_class', explode( ' ', $form_data['settings']['form_class'] ) ) );
120 }
121
122 // Begin to build the output
123 echo '<div class="wpforms-container ' . implode( ' ', $class ) . '" id="wpforms-' . $form_id . '">';
124
125 echo '<form method="post" enctype="multipart/form-data" id="wpforms-form-' . $form_id . '" action="' . $action . '" class="wpforms-validate wpforms-form" data-formid="' . $form_id . '">';
126
127 do_action( 'wpforms_frontend_output', $form_data, $form, $title, $description, $errors );
128
129 echo '</form>';
130
131 echo '</div>';
132
133 // After output hook
134 do_action( 'wpforms_frontend_output_after', $form_data, $form );
135
136 $this->forms[$form_id] = $form_data;
137
138 // Debug
139 wpforms_debug_data( $form_data );
140 }
141
142 /**
143 * Display form confirmation message.
144 *
145 * @since 1.0.0
146 * @param array $form_data
147 * @param mixed $title
148 * @param mixed $description
149 */
150 function confirmation( $form_data ) {
151
152 if ( !empty( $form_data['settings']['confirmation_type'] ) && 'message' == $form_data['settings']['confirmation_type'] ) {
153
154 // Load confirmatiom specific asssets
155 $this->assets_confirmation();
156
157 $complete = !empty( $_POST['wpforms']['complete'] ) ? $_POST['wpforms']['complete'] : array();
158 $entry_id = !empty( $_POST['wpforms']['entry_id'] ) ? $_POST['wpforms']['entry_id'] : 0;
159 $message = apply_filters( 'wpforms_process_smart_tags', $form_data['settings']['confirmation_message'], $form_data, $complete, $entry_id );
160 $message = apply_filters( 'wpforms_frontend_confirmation_message', $message, $form_data );
161
162 $class = wpforms_setting( 'disable-css', '1' ) == '1' ? 'wpforms-confirmation-container-full' : 'wpforms-confirmation-container';
163
164 echo '<div class="' . $class . '" id="wpforms-confirmation-' . absint( $form_data['id'] ) . '">';
165
166 echo wpautop( $message );
167
168 echo '</div>';
169 }
170 }
171
172 /**
173 * Form head area.
174 *
175 * @since 1.0.0
176 * @param array $form_data
177 * @param object $form
178 * @param mixed $title
179 * @param mixed $description
180 */
181 public function head( $form_data, $form, $title, $description, $errors ) {
182
183 // Output title and/or desc
184 if ( !empty( $title ) || !empty( $description ) ) {
185
186 echo '<div class="wpforms-head-container">';
187
188 if ( !empty( $title ) && !empty( $form->post_title ) ) {
189 echo '<div class="wpforms-title">' . esc_html( $form->post_title ) . '</div>';
190 }
191
192 if ( !empty( $description ) && !empty( $form->post_excerpt ) ) {
193 echo '<div class="wpforms-description">' . $form->post_excerpt . '</div>';
194 }
195
196 echo '</div>';
197 }
198
199 // Output errors if they exist
200 if ( !empty( $errors['header'] ) ) {
201
202 echo '<div class="wpforms-error-container">';
203
204 $allow = array(
205 'a' => array(
206 'href' => array(),
207 'title' => array()
208 ),
209 'br' => array(),
210 'em' => array(),
211 'strong' => array(),
212 'p' => array(),
213 );
214 echo wp_kses( $errors['header'], $allow );
215
216 echo '</div>';
217 }
218 }
219
220 /**
221 * Page Indictor
222 *
223 * This displays if the form contains pagebreaks and is configured to show
224 * a page indicator in the top pagebreak settings.
225 *
226 * @since 1.2.1
227 * @param array $form_data
228 * @param object $form
229 * @param mixed $title
230 * @param mixed $description
231 * @param array $errors
232 */
233 public function page_indicator( $form_data, $form, $title, $description, $errors ) {
234
235 $pagebreak_top = wpforms_get_pagebreak( $form_data, 'top' );
236
237 if ( empty( $pagebreak_top['indicator'] ) || 'none' == apply_filters( 'wpforms_frontend_indicator_theme', $pagebreak_top['indicator'], $form_data ) ) {
238 return;
239 }
240
241 $pagebreak = array(
242 'indicator' => sanitize_html_class( $pagebreak_top['indicator'] ),
243 'color' => wpforms_sanitize_hex_color( $pagebreak_top['indicator_color'] ),
244 'pages' => wpforms_get_pagebreak( $form_data, 'pages' ),
245 );
246 $p = 1;
247
248 printf('<div class="wpforms-page-indicator %s" data-indicator="%s" data-indicator-color="%s">',
249 $pagebreak['indicator'],
250 $pagebreak['indicator'],
251 $pagebreak['color']
252 );
253
254 if ( 'circles' == $pagebreak['indicator'] ) {
255
256 // Circles theme
257 foreach ( $pagebreak['pages'] as $page ) {
258 $class = ( 1 === $p ) ? 'active' : '';
259 $bg = ( 1 === $p ) ? 'style="background-color:' . $pagebreak['color'] . '"' : '';
260 printf( '<div class="wpforms-page-indicator-page %s wpforms-page-indicator-page-%d">', $class, $p );
261 printf( '<span class="wpforms-page-indicator-page-number" %s>%d</span>', $bg, $p );
262 if ( !empty( $page['title'] ) ) {
263 printf( '<span class="wpforms-page-indicator-page-title">%s<span>', esc_html( $page['title'] ) );
264 }
265 echo '</div>';
266 $p++;
267 }
268
269 } elseif ( 'connector' == $pagebreak['indicator'] ) {
270
271 // Connector theme
272 foreach ( $pagebreak['pages'] as $page ) {
273 $class = ( 1=== $p ) ? 'active ' : '';
274 $bg = ( 1=== $p ) ? 'style="background-color:' . $pagebreak['color'] . '"' : '';
275 $border = ( 1=== $p ) ? 'style="border-top-color:' . $pagebreak['color'] . '"' : '';
276 $width = 100/(count($pagebreak['pages'])) . '%';
277 printf( '<div class="wpforms-page-indicator-page %s wpforms-page-indicator-page-%d" style="width:%s;">', $class, $p, $width );
278 printf( '<span class="wpforms-page-indicator-page-number" %s>%d<span class="wpforms-page-indicator-page-triangle" %s></span></span>', $bg, $p, $border );
279 if ( !empty( $page['title'] ) ) {
280 printf( '<span class="wpforms-page-indicator-page-title">%s<span>', esc_html( $page['title'] ) );
281 }
282 echo '</div>';
283 $p++;
284 }
285
286 } elseif ( 'progress' == $pagebreak['indicator'] ) {
287
288 // Progress theme
289 $p1 = !empty( $pagebreak['pages'][0]['title'] ) ? esc_html( $pagebreak['pages'][0]['title'] ) : '';
290 $sep = empty( $p1 ) ? 'style="display:none;"' : '';
291 $width = 100/(count($pagebreak['pages'])) . '%';
292 $prog = 'style="width:' . $width . ';background-color:' . $pagebreak['color'] . ';"';
293 $names = '';
294 $step = __( 'Step', 'wpforms' );
295 $of = __( 'of', 'wpforms' );
296
297 foreach ( $pagebreak['pages'] as $page ) {
298 if ( !empty( $page['title'] ) ) {
299 $names .= sprintf( 'data-page-%d-title="%s" ', $p, esc_attr( $page['title'] ) );
300 }
301 $p++;
302 }
303 printf( '<span class="wpforms-page-indicator-page-title" %s>%s</span>', $names, $p1 );
304 printf( '<span class="wpforms-page-indicator-page-title-sep" %s> - </span>', $sep );
305 printf( '<span class="wpforms-page-indicator-steps">%s <span class="wpforms-page-indicator-steps-current">1</span> %s %d</span>', $step, $of, count( $pagebreak['pages'] ) );
306 printf( '<div class="wpforms-page-indicator-page-progress-wrap"><div class="wpforms-page-indicator-page-progress" %s></div></div>', $prog );
307 }
308
309 do_action( 'wpforms_frontend_indicator', $pagebreak, $form_data );
310
311 echo '</div>';
312 }
313
314 /**
315 * Form field area.
316 *
317 * @since 1.0.0
318 * @param array $form_data
319 * @param object $form
320 * @param mixed $title
321 * @param mixed $description
322 */
323 public function fields( $form_data, $form, $title, $description, $errors ) {
324
325 if ( empty( $form_data['fields'] ) )
326 return;
327
328 $fields = $form_data['fields'];
329 $pagebreak = wpforms_has_pagebreak( $form_data );
330 $page = 0;
331
332 // Form fields area
333 echo '<div class="wpforms-field-container">';
334
335 // Pagebreak, begin first page
336 if ( $pagebreak ) {
337 $pbt = wpforms_get_pagebreak( $form_data, 'top');
338 $pbt_css = !empty( $pbt['css'] ) ? wpforms_sanitize_classes( $pbt['css'] ) : '';
339 echo '<div class="wpforms-page wpforms-page-1 ' . $pbt_css . '">';
340 }
341
342 // Loop through all the fields we have
343 foreach ( $fields as $field ) {
344
345 if ( $field['type'] == 'pagebreak' ) {
346 if ( !empty( $field['position'] ) && 'top' == $field['position'] ) {
347 continue;
348 } else {
349 $page++;
350 $form_data['page_total'] = $pagebreak;
351 $form_data['page_current'] = $page;
352 }
353 }
354
355 $field = apply_filters( 'wpforms_field_data', $field, $form_data );
356
357 if ( ! $fields ) {
358 continue;
359 }
360
361 // Basic generic attributes for easy filtering
362 $field_atts = array(
363 'field_class' => array(
364 'wpforms-field',
365 'wpforms-field-' . sanitize_html_class( $field['type'] ),
366 ),
367 'field_id' => array(
368 'wpforms-' . absint( $form_data['id'] ) . '-field_' . absint( $field['id'] ) . '-container',
369 ),
370 'field_style' => '',
371 'label_class' => array(
372 'wpforms-field-label',
373 ),
374 'label_id' => '',
375 'description_class' => array(
376 'wpforms-field-description'
377 ),
378 'description_id' => array(),
379 'input_id' => array(
380 'wpforms-' . absint( $form_data['id'] ) . '-field_' . absint( $field['id'] ),
381 ),
382 'input_class' => array(),
383 'input_data' => array(),
384 );
385
386 // Check user defined classes
387 if ( !empty( $field['css'] ) ) {
388 $user_classes = explode( ' ', str_replace('.', '', $field['css'] ) );
389 foreach( $user_classes as $user_class ) {
390 $field_atts['field_class'][] = sanitize_html_class( $user_class );
391 }
392 }
393 // Check input columns
394 if ( !empty( $field['input_columns'] ) ) {
395 if ( '2' == $field['input_columns'] ) {
396 $field_atts['field_class'][] = 'wpforms-list-2-columns';
397 } elseif ( '3' == $field['input_columns'] ) {
398 $field_atts['field_class'][] = 'wpforms-list-3-columns';
399 }
400 }
401 // Check size
402 if ( !empty( $field['size'] ) ) {
403 $field_atts['input_class'][] = 'wpforms-field-' . sanitize_html_class( $field['size'] );
404 }
405 // Check if required
406 if ( !empty( $field['required'] ) ) {
407 $field_atts['input_class'][] = 'wpforms-field-required';
408 }
409 // Check if there are errors
410 if ( !empty( wpforms()->process->errors[$form_data['id']][$field['id']] ) ) {
411 $field_atts['input_class'][] = 'wpforms-error';
412 }
413
414 $field_atts = apply_filters( 'wpforms_field_atts', $field_atts, $field, $form_data );
415
416 echo '<div class="' . implode( ' ', $field_atts['field_class'] ) . '" id="' . implode( ' ', $field_atts['field_id'] ) . '" data-field-id="' .absint( $field['id'] ) . '" style="' . esc_html( $field_atts['field_style'] ) . '">';
417
418 // Display label if we have one
419 if ( !empty( $field['label'] ) ) {
420
421 // Check special flat that allows fields to disable labels on front-end
422 if ( empty( $field['label_disable'] ) ) {
423
424 // If user has decided to hide the label, hide it using a special
425 // CSS class in an attempt to keep it readable by screen readers
426 if ( !empty( $field['label_hide'] ) ) {
427 $field_atts['label_class'][] = 'wpforms-label-hide';
428 }
429
430 $label_class = !empty( $field_atts['label_class'] ) ? ' class="' . implode( ' ', $field_atts['label_class'] ) . '"' : '';
431 $label_id = !empty( $field_atts['label_id'] ) ? ' id="' . $field_atts['label_id'] . '"' : '';
432
433 echo '<label for="wpforms-' . absint( $form_data['id'] ) . '-field_' . absint( $field['id'] ) . '"' . $label_class . $label_id . '>';
434
435 echo esc_html( $field['label'] );
436
437 if ( !empty( $field['required'] ) ) {
438 echo apply_filters( 'wpforms_field_required_label', ' <span class="wpforms-required-label">*</span>' );
439 }
440
441 echo '</label>';
442
443 }
444 }
445
446 // Trigger the method to output this field type
447 do_action( "wpforms_display_field_{$field['type']}", $field, $field_atts, $form_data );
448
449 // Display errors if we have one
450 if ( !empty( wpforms()->process->errors[$form_data['id']][$field['id']] ) ) {
451
452 $error = wpforms()->process->errors[$form_data['id']][$field['id']];
453
454 // For some advanced fields with multiple inputs (such
455 // as address or name fields) we handle the displaying
456 // the error within the field class. In these instances
457 // the field error container will be an array. So below
458 // we only show the error message for normal fields.
459 if ( !is_array( $error ) ) {
460 echo '<label id="wpforms-field_' . intval( $field['id'] ) . '-error" class="wpforms-error" for="wpforms-field_' . intval( $field['id'] ) . '">' . esc_html( wpforms()->process->errors[$form_data['id']][$field['id']] ) . '</label>';
461 }
462 }
463
464 // Display description if we have one
465 if ( !empty( $field['description'] ) ) {
466
467 echo '<div class="' . implode( ' ', $field_atts['description_class'] ) . '" id="' . implode( ' ', $field_atts['description_id'] ) . '">';
468
469 echo apply_filters( 'wpforms_process_smart_tags', $field['description'], $form_data );
470
471 echo '</div>';
472 }
473
474 echo '</div>';
475
476 // Pagebreak, end current page and begin the next
477 if ( $field['type'] == 'pagebreak' && $page != $pagebreak ) {
478 $next = $page+1;
479 $last = $next == $pagebreak ? 'last' : '';
480 $css = !empty( $field['css'] ) ? wpforms_sanitize_classes( $field['css'] ) : '';
481 printf ('</div><div class="wpforms-page wpforms-page-%s %s %s" style="display:none;">', $next, $last, $css );
482 }
483 }
484
485 // Pagebreak, end last page
486 if ( $pagebreak ) {
487
488 // If we don't have a bottom pagebreak, the form is pre-v1.2.1
489 // and this is for backwards compatibility.
490 $pbb = wpforms_get_pagebreak( $form_data, 'bottom' );
491 if ( ! $pbb ) {
492 $prev = !empty( $form_data['settings']['pagebreak_prev'] ) ? esc_html( $form_data['settings']['pagebreak_prev'] ) : __('Previous', 'wpforms' );
493 echo '<div class="wpforms-field wpforms-field-pagebreak">';
494 printf(
495 '<button class="wpforms-page-button wpforms-page-prev" data-action="prev" data-page="%d" data-formid="%d">%s</button>',
496 $page+1,
497 $form_data['id'],
498 $prev
499 );
500 echo '</div>';
501 }
502
503 echo '</div>';
504 }
505
506 echo '</div>';
507 }
508
509 /**
510 * Anti-spam honeypot output if configured.
511 *
512 * @since 1.0.0
513 * @param array $form_data
514 * @param object $form
515 * @param mixed $title
516 * @param mixed $description
517 */
518 public function honeypot( $form_data, $form, $title, $description, $errors ) {
519
520 if ( empty( $form_data['settings']['honeypot'] ) || '1' != $form_data['settings']['honeypot'] )
521 return;
522
523 $names = array( 'Name', 'Phone', 'Comment', 'Message', 'Email', 'Website' );
524
525 echo '<div class="wpforms-field wpforms-field-hp" id="wpform-field-hp">';
526
527 echo '<label for="wpforms-field_hp" class="wpforms-field-label">' . esc_html( $names[ array_rand( $names ) ] ) . '</label>';
528
529 echo '<input type="text" name="wpforms[hp]" id="wpforms-field_hp" class="wpforms-field-medium">';
530
531 echo '</div>';
532 }
533
534 /**
535 * reCAPTCHA output if configured.
536 *
537 * @since 1.0.0
538 * @param array $form_data
539 * @param object $form
540 * @param mixed $title
541 * @param mixed $description
542 */
543 public function recaptcha( $form_data, $form, $title, $description, $errors ) {
544
545 // Check that recaptcha is configured in the settings
546 $site_key = wpforms_setting( 'recaptcha-site-key', '' );
547 $secret_key = wpforms_setting( 'recaptcha-secret-key', '' );
548 if ( empty( $site_key ) || empty( $secret_key ) )
549 return;
550
551 // Check that the recaptcha is configured for the specific form
552 if ( !isset( $form_data['settings']['recaptcha'] ) || '1' != $form_data['settings']['recaptcha'] )
553 return;
554
555 $pages = wpforms_has_pagebreak( $form_data );
556 $d = '';
557 $datas = apply_filters( 'wpforms_frontend_recaptcha', array(), $form_data );
558
559
560 if ( $pages ) {
561 echo '<div class="wpforms-recaptcha-container" style="display:none;">';
562 } else {
563 echo '<div class="wpforms-recaptcha-container">';
564 }
565
566 foreach( $datas as $key => $data ) {
567 $d .= 'data-' . $key . '="' . esc_attr( $data ) . '" ';
568 }
569
570 echo '<div class="g-recaptcha" ' . $d . '></div>';
571
572 echo '<input type="text" name="g-recaptcha-hidden" class="wpforms-recaptcha-hidden" style="position:absolute !important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden;padding:0;margin;" required>';
573
574 if ( !empty( wpforms()->process->errors[$form_data['id']]['recaptcha'] ) ) {
575 echo '<label id="wpforms-field_recaptcah-error" class="wpforms-error">' . esc_html( wpforms()->process->errors[$form_data['id']]['recaptcha'] ) . '</label>';
576 }
577
578 echo '</div>';
579 }
580
581 /**
582 * Form footer arera.
583 *
584 * @since 1.0.0
585 * @param array $form_data
586 * @param object $form
587 * @param mixed $title
588 * @param mixed $description
589 */
590 public function foot( $form_data, $form, $title, $description, $errors ) {
591
592 $settings = $form_data['settings'];
593 $submit = apply_filters( 'wpforms_field_submit' , esc_html( $settings['submit_text'] ), $form_data );
594 $submit_process = '';
595 $submit_classes = array();
596 $visible = wpforms_has_pagebreak( $form_data ) ? 'style="display:none;"' : '';
597
598 // Check for submit button alt-text
599 if ( !empty( $settings['submit_text_processing'] ) ) {
600 $submit_process = 'data-alt-text="' . esc_attr( $settings['submit_text_processing'] ) .'"';
601 }
602
603 // Check user defined submit button classes
604 if ( !empty( $settings['submit_class'] ) ) {
605 $user_classes = explode( ' ', str_replace('.', '', $settings['submit_class'] ) );
606 foreach( $user_classes as $user_class ) {
607 $submit_classes[] = sanitize_html_class( $user_class );
608 }
609 }
610
611 // Output errors if they exist
612 if ( !empty( $errors['footer'] ) ) {
613
614 echo '<div class="wpforms-error-container">';
615
616 $allow = array(
617 'a' => array(
618 'href' => array(),
619 'title' => array()
620 ),
621 'br' => array(),
622 'em' => array(),
623 'strong' => array(),
624 'p' => array(),
625 );
626 echo wp_kses( $errors['footer'], $allow );
627
628 echo '</div>';
629 }
630
631 // Submit button area
632 echo '<div class="wpforms-submit-container" ' . $visible . '>';
633
634 echo '<input type="hidden" name="wpforms[id]" value="' . $form->ID . '">';
635
636 echo '<input type="hidden" name="wpforms[author]" value="' . absint( get_the_author_meta( 'ID' ) ) . '">';
637
638 printf(
639 '<button type="submit" name="wpforms[submit]" class="wpforms-submit %s" id="wpforms-submit-%d" value="wpforms-submit" %s>%s</button>',
640 implode( ' ', $submit_classes ),
641 $form->ID,
642 $submit_process,
643 $submit
644 );
645
646 echo '</div>';
647 }
648
649 /**
650 * Determine if we should load assets globally. If false assets will
651 * load conditionally (default).
652 *
653 * @since 1.2.4
654 * @return bool
655 */
656 public function assets_global() {
657
658 return apply_filters( 'wpforms_global_assets', wpforms_setting( 'global-assets', false ) );
659 }
660
661 /**
662 * Load the necessary CSS for single pages/posts earlier if possible.
663 *
664 * If we are viewing a singular page, then we can check the content early
665 * to see if the shortcode was used. If not we fallback and load the assets
666 * later on during the page (widgets, archives, etc).
667 *
668 * @since 1.0.0
669 */
670 public function assets_header() {
671
672 if ( !is_singular() ) {
673 return;
674 }
675
676 global $post;
677
678 if ( has_shortcode( $post->post_content, 'wpforms' ) ) {
679
680 $this->assets_css();
681 }
682 }
683
684 /**
685 * Load the CSS assets for frontend output.
686 *
687 * @since 1.0.0
688 */
689 public function assets_css() {
690
691 do_action( 'wpforms_frontend_css', $this->forms );
692
693 // jquery date/time library CSS
694 if ( $this->assets_global() || true == wpforms_has_field_type( 'date-time', $this->forms, true ) ) :
695 wp_enqueue_style(
696 'wpforms-jquery-timepicker',
697 WPFORMS_PLUGIN_URL . 'assets/css/jquery.timepicker.css',
698 array(),
699 '1.11.5'
700 );
701 wp_enqueue_style(
702 'wpforms-flatpickr',
703 WPFORMS_PLUGIN_URL . 'assets/css/flatpickr.min.css',
704 array(),
705 '2.3.4'
706 );
707 endif;
708
709 // Load CSS per global setting
710 if ( wpforms_setting( 'disable-css', '1' ) == '1' ) {
711 wp_enqueue_style(
712 'wpforms-full',
713 WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css',
714 array(),
715 WPFORMS_VERSION
716 );
717 }
718 if ( wpforms_setting( 'disable-css', '1' ) == '2' ) {
719 wp_enqueue_style(
720 'wpforms-base',
721 WPFORMS_PLUGIN_URL . 'assets/css/wpforms-base.css',
722 array(),
723 WPFORMS_VERSION
724 );
725 }
726 }
727
728 /**
729 * Load the JS assets for frontend output.
730 *
731 * @since 1.0.0
732 */
733 public function assets_js() {
734
735 do_action( 'wpforms_frontend_js', $this->forms );
736
737 // Load jquery validation library - http://jqueryvalidation.org/
738 wp_enqueue_script(
739 'wpforms-validation',
740 WPFORMS_PLUGIN_URL . 'assets/js/jquery.validate.min.js',
741 array( 'jquery' ),
742 '1.15.1',
743 true
744 );
745
746 // Load jquery date/time libraries
747 if ( $this->assets_global() || true == wpforms_has_field_type( 'date-time', $this->forms, true ) ) :
748 wp_enqueue_script(
749 'wpforms-flatpickr',
750 WPFORMS_PLUGIN_URL . 'assets/js/flatpickr.min.js',
751 array( 'jquery' ),
752 '2.0.5',
753 true
754 );
755 wp_enqueue_script(
756 'wpforms-jquery-timepicker',
757 WPFORMS_PLUGIN_URL . 'assets/js/jquery.timepicker.min.js',
758 array( 'jquery' ),
759 '1.11.5',
760 true
761 );
762 endif;
763
764 // Load jquery input mask library - https://github.com/RobinHerbots/jquery.inputmask
765 if ( $this->assets_global() || true == wpforms_has_field_type( array( 'phone', 'address' ), $this->forms, true ) ) :
766 wp_enqueue_script(
767 'wpforms-maskedinput',
768 WPFORMS_PLUGIN_URL . 'assets/js/jquery.inputmask.bundle.min.js',
769 array( 'jquery' ),
770 '3.2.8',
771 true
772 );
773 endif;
774
775 // Load CC payment library - https://github.com/stripe/jquery.payment/
776 if ( $this->assets_global() || true == wpforms_has_field_type( 'credit-card', $this->forms, true ) ) :
777 wp_enqueue_script(
778 'wpforms-payment',
779 WPFORMS_PLUGIN_URL . 'assets/js/jquery.payment.min.js',
780 array( 'jquery' ),
781 WPFORMS_VERSION,
782 true
783 );
784 endif;
785
786 // Load base JS
787 wp_enqueue_script(
788 'wpforms',
789 WPFORMS_PLUGIN_URL . 'assets/js/wpforms.js',
790 array( 'jquery' ),
791 WPFORMS_VERSION,
792 true
793 );
794
795 // If we have payment fields then include currency details
796 $payment_fields = array( 'credit-card', 'payment-single', 'payment-multiple', 'payment-select', 'payment-total' );
797 if ( ( $this->assets_global() || true == wpforms_has_field_type( $payment_fields , $this->forms, true ) ) && function_exists( 'wpforms_get_currencies' ) ) :
798 $currency = wpforms_setting( 'currency', 'USD' );
799 $currencies = wpforms_get_currencies();
800 wp_localize_script(
801 'wpforms',
802 'wpforms_currency',
803 array(
804 'code' => $currency,
805 'thousands' => $currencies[$currency]['thousands_separator'],
806 'decimal' => $currencies[$currency]['decimal_separator'],
807 'symbol' => $currencies[$currency]['symbol'],
808 'symbol_pos' => $currencies[$currency]['symbol_pos']
809 )
810 );
811 endif;
812
813 // Load reCAPTCHA support if form supports it
814 $site_key = wpforms_setting( 'recaptcha-site-key' );
815 $secret_key = wpforms_setting( 'recaptcha-secret-key' );
816 if ( !empty( $site_key ) && !empty( $secret_key ) ) {
817 $reCAPTCHA_api = apply_filters( 'wpforms_frontend_recaptcha_url', 'https://www.google.com/recaptcha/api.js?onload=wpformsRecaptcha&render=explicit' );
818 wp_enqueue_script(
819 'wpforms-recaptcha',
820 $reCAPTCHA_api,
821 array( 'jquery' ),
822 '2.0.0',
823 true
824 );
825 $reCAPTCHA_init = 'var wpformsRecaptcha = function(){
826 jQuery(".g-recaptcha").each(function(index, el) {
827 grecaptcha.render(el, {sitekey : \'' . $site_key . '\',callback:function(){wpforms.recaptchaCallback(el);}});
828 });
829 };';
830 wp_add_inline_script( 'wpforms-recaptcha', $reCAPTCHA_init );
831 }
832 }
833
834 /**
835 * Load the necessary assets for the confirmation message.
836 *
837 * @since 1.1.2
838 */
839 public function assets_confirmation() {
840
841 // Base CSS only
842 if ( wpforms_setting( 'disable-css', '1' ) == '1' ) {
843 wp_enqueue_style(
844 'wpforms-full',
845 WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css',
846 array(),
847 WPFORMS_VERSION
848 );
849 }
850
851 // Special confirmation JS
852 wp_enqueue_script(
853 'wpforms-confirmation',
854 WPFORMS_PLUGIN_URL . 'assets/js/wpforms-confirmation.js',
855 array( 'jquery' ),
856 WPFORMS_VERSION,
857 true
858 );
859
860 do_action( 'wpforms_frontend_confirmation' );
861 }
862
863 /**
864 * Load the assets in footer if needed (archives, widgets, etc).
865 *
866 * @since 1.0.0
867 */
868 public function assets_footer() {
869
870 if ( empty( $this->forms ) && ! $this->assets_global() )
871 return;
872
873 $this->assets_css();
874 $this->assets_js();
875
876 do_action( 'wpforms_wp_footer', $this->forms );
877 }
878
879 /**
880 * Hook at fires at a later priority in wp_footer
881 *
882 * @since 1.0.5
883 */
884 public function footer_end() {
885
886 if ( empty( $this->forms ) && ! $this->assets_global() )
887 return;
888
889 do_action( 'wpforms_wp_footer_end', $this->forms );
890 }
891
892 /**
893 * Shortcode wrapper for the outputting a form.
894 *
895 * @since 1.0.0
896 * @param array $atts
897 * @return array
898 */
899 public function shortcode( $atts ) {
900
901 $atts = shortcode_atts( array(
902 'id' => false,
903 'title' => false,
904 'description' => false,
905 ), $atts, 'output' );
906
907 ob_start();
908
909 $this->output( $atts['id'], $atts['title'], $atts['description'] );
910
911 $output = ob_get_clean();
912
913 return $output;
914 }
915 }