PluginProbe
WP-Members Membership Plugin / trunk
WP-Members Membership Plugin vtrunk
trunk 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.4.2 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.4.9.1 3.4.9.2 3.4.9.3 3.4.9.4 3.4.9.5 3.4.9.6 3.4.9.7 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 All 34 releases
wp-members / includes / class-wp-members-forms.php

class-wp-members-forms.php in WP-Members Membership Plugin trunk, at includes/class-wp-members-forms.php

2,281 lines 86.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The WP_Members Forms Class.
4 *
5 * @package WP-Members
6 * @subpackage WP_Members Forms Object Class
7 * @since 3.1.0
8 */
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit();
13 }
14
15 class WP_Members_Forms {
16
17 public $reg_form_showing = false;
18
19 /**
20 * Plugin initialization function.
21 *
22 * @since 3.1.0
23 */
24 function __construct() {
25
26 }
27
28 /**
29 * Sets the registration fields.
30 *
31 * @since 3.0.0
32 * @since 3.1.5 Added $form argument.
33 * @since 3.3.0 Added $tag argument.
34 *
35 * @global stdClass $wpmem
36 * @param string $tag
37 * @param string $form The form being generated.
38 */
39 function load_fields( $tag = "all", $form = 'default' ) {
40
41 global $wpmem;
42
43 // @todo Temp fix for admin notification bug.
44 $tag = ( 'admin_notify' == $tag ) ? 'register' : $tag;
45 $tag = ( 'register_wp' == $tag ) ? 'register' : $tag;
46
47 // Get stored fields settings.
48 $fields = get_option( 'wpmembers_fields' );
49
50 // Validate fields settings.
51 if ( ! isset( $fields ) || empty( $fields ) ) {
52 // Update settings.
53 $fields = array( array( 10, esc_html__( 'Email', 'wp-members' ), 'user_email', 'email', 'y', 'y', 'y', 'profile'=>true ) );
54 }
55
56 // Check woo reg fields.
57 if ( 'woo' == $tag && 1 == $wpmem->woo->add_my_account_fields ) {
58 $woo_reg_fields = get_option( 'wpmembers_wcacct_fields' );
59 $woo_reg_fields = ( $woo_reg_fields ) ? $woo_reg_fields : array();
60 }
61
62 // Establish $assembled_fields as an array explicitly.
63 $assembled_fields = array();
64
65 // Add new field array keys
66 foreach ( $fields as $key => $val ) {
67
68 // Start by checking if we need this field or not.
69 if (
70 ( 'register' == $tag && 'y' == $val[4] )
71 || ( 'profile' == $tag && ( ! isset( $val['profile'] ) || 1 == $val['profile'] ) ) // @todo Currently checking ! isset because some fields don't have $val['profile']. Should probably handle on update to set $val['profile'] for all fields.
72 || ( 'all' == $tag )
73 || ( 'woo' == $tag && 1 == $wpmem->woo->add_my_account_fields && in_array( $val[2], $woo_reg_fields ) )
74 ) {
75
76 if ( 'woo' == $tag && in_array( $val[2], $woo_reg_fields ) ) {
77 $val[4] = 'y';
78 }
79
80 // Key fields with meta key.
81 $meta_key = $val[2];
82
83 // What is the field type.
84 $field_type = $val[3];
85
86 // Old format, new key.
87 foreach ( $val as $subkey => $subval ) {
88 $assembled_fields[ $meta_key ][ $subkey ] = $subval;
89 }
90
91 // Setup field properties.
92 $assembled_fields[ $meta_key ]['label'] = $val[1];
93 $assembled_fields[ $meta_key ]['type'] = $field_type;
94 $assembled_fields[ $meta_key ]['register'] = ( 'y' == $val[4] ) ? true : false;
95 $assembled_fields[ $meta_key ]['required'] = ( 'y' == $val[5] ) ? true : false;
96 $assembled_fields[ $meta_key ]['profile'] = ( isset( $val['profile'] ) ) ? $val['profile'] : ( ( 'y' == $val[4] ) ? true : false );
97 $assembled_fields[ $meta_key ]['native'] = ( 'y' == $val[6] ) ? true : false;
98
99 // These field types have additional properties.
100 switch ( $field_type ) {
101
102 case 'checkbox':
103 $assembled_fields[ $meta_key ]['checked_value'] = $val[7];
104 $assembled_fields[ $meta_key ]['checked_default'] = ( 'y' == $val[8] ) ? true : false;
105 $assembled_fields[ $meta_key ]['checkbox_label'] = ( isset( $val['checkbox_label'] ) ) ? $val['checkbox_label'] : 0;
106 break;
107
108 case 'select':
109 case 'multiselect':
110 case 'multicheckbox':
111 case 'radio':
112 case 'membership':
113 if ( 'membership' == $field_type ) {
114 /**
115 * Filter the membership field dropdown default.
116 *
117 * @since 3.5.0
118 *
119 * @param string $default
120 */
121 $membership_default = apply_filters( 'wpmem_membership_field_default', wpmem_get_text( 'membership_field' ) );
122 $val[7] = array( $membership_default . '|' );
123 foreach( wpmem_get_memberships() as $membership_key => $membership_value ) {
124 $val[7][] = $membership_value['title'] . '|' . $membership_key;
125 }
126 }
127 // Correct a malformed value (if last value is empty due to a trailing comma).
128 if ( '' == end( $val[7] ) ) {
129 array_pop( $val[7] );
130 $assembled_fields[ $meta_key ][7] = $val[7];
131 }
132 $assembled_fields[ $meta_key ]['values'] = $val[7];
133 $assembled_fields[ $meta_key ]['delimiter'] = ( isset( $val[8] ) ) ? $val[8] : '|';
134 $assembled_fields[ $meta_key ]['options'] = array();
135 foreach ( $val[7] as $value ) {
136 $pieces = explode( '|', trim( $value ) );
137 // @todo The following originally eliminated an empty option value. However, this
138 // is needed for WooCommerce. Check to see if this causes issues elsewhere.
139 //if ( isset( $pieces[1] ) && $pieces[1] != '' ) {
140 $assembled_fields[ $meta_key ]['options'][ $pieces[1] ] = $pieces[0];
141 //}
142 }
143 break;
144
145 case 'file':
146 case 'image':
147 $assembled_fields[ $meta_key ]['file_types'] = $val[7];
148 break;
149
150 case 'hidden':
151 $assembled_fields[ $meta_key ]['value'] = $val[7];
152 break;
153
154 default:
155 $assembled_fields[ $meta_key ]['value'] = ( isset( $val['value'] ) ) ? $val['value'] : ''; // @since 3.5.0 adds default value.
156 break;
157 }
158 }
159 }
160
161 // @todo Set for checking backwards compatibility, but eventually get $wpmem->fields out altogether.
162 $wpmem->fields = $assembled_fields;
163
164 return $assembled_fields;
165 }
166
167 /**
168 * Filter custom fields for localization.
169 *
170 * @since 3.3.9
171 *
172 * @param array $fields
173 */
174 function localize_fields( $fields ) {
175 // @todo Find wpmem_custom_translation_strings()
176 if ( function_exists( 'wpmem_custom_translation_strings' ) ) {
177 $string_map = wpmem_custom_translation_strings( get_locale() );
178 foreach ( $string_map as $meta_key => $value ) {
179 if ( is_array( $value ) ) {
180 if ( isset( $fields[ $meta_key ]['placeholder'] ) && isset( $value['placeholder'] ) ) {
181 $fields[ $meta_key ]['placeholder'] = $string_map[ $meta_key ]['placeholder'];
182 }
183 if ( isset( $fields[ $meta_key ]['title'] ) && isset( $value['title'] ) ) {
184 $fields[ $meta_key ]['title'] = $string_map[ $meta_key ]['title'];
185 }
186 if ( isset( $fields[ $meta_key ]['label'] ) && isset( $value['label'] ) ) {
187 $fields[ $meta_key ]['label'] = $string_map[ $meta_key ]['label'];
188 }
189 } else {
190 $fields[ $meta_key ]['label'] = $string_map[ $meta_key ];
191 }
192 }
193 }
194 return $fields;
195 }
196
197 /**
198 * Get excluded meta fields.
199 *
200 * @since 3.0.0
201 * @since 3.3.3 Update $tag to match wpmem_fields() tags.
202 *
203 * @param string $tag A tag so we know where the function is being used.
204 * @return array The excluded fields.
205 */
206 function excluded_fields( $tag ) {
207
208 // Default excluded fields.
209 $excluded_fields = array( 'password', 'confirm_password', 'confirm_email', 'password_confirm', 'email_confirm' );
210
211 if ( 'update' == $tag || 'admin-profile' == $tag || 'user-profile' == $tag || 'wp-register' == $tag ) {
212 $excluded_fields[] = 'username';
213 }
214
215 if ( 'admin-profile' == $tag || 'user-profile' == $tag ) {
216 array_push( $excluded_fields, 'first_name', 'last_name', 'nickname', 'display_name', 'user_email', 'description', 'user_url' );
217
218 // If WooCommerce is used, remove these meta - WC already adds them in their own section.
219 if ( class_exists( 'woocommerce' ) ) {
220 array_push( $excluded_fields,
221 'billing_first_name',
222 'billing_last_name',
223 'billing_company',
224 'billing_address_1',
225 'billing_address_2',
226 'billing_city',
227 'billing_postcode',
228 'billing_country',
229 'billing_state',
230 'billing_email',
231 'billing_phone',
232 'shipping_first_name',
233 'shipping_last_name',
234 'shipping_company',
235 'shipping_address_1',
236 'shipping_address_2',
237 'shipping_city',
238 'shipping_postcode',
239 'shipping_country',
240 'shipping_state'
241 );
242 }
243 }
244
245 /**
246 * Filter excluded meta fields.
247 *
248 * @since 2.9.3
249 * @since 3.0.0 Moved to new method in WP_Members Class.
250 * @since 3.3.3 Update $tag to match wpmem_fields() tags.
251 *
252 * @param array An array of the field meta names to exclude.
253 * @param string $tag A tag so we know where the function is being used.
254 */
255 $excluded_fields = apply_filters( 'wpmem_exclude_fields', $excluded_fields, $tag );
256
257 // Return excluded fields.
258 return $excluded_fields;
259 }
260
261 /**
262 * Creates form fields
263 *
264 * Creates various form fields and returns them as a string.
265 *
266 * @since 3.1.0
267 * @since 3.1.1 Added $delimiter.
268 * @since 3.1.2 Changed $valtochk to $compare.
269 * @since 3.1.6 Added $placeholder.
270 * @since 3.1.7 Added number type & $min, $max, $title and $pattern attributes.
271 * @since 3.2.0 Added $id argument.
272 * @since 3.2.4 Added radio group and multiple checkbox individual item labels.
273 *
274 * @global object $wpmem The WP_Members object class.
275 * @param array $args {
276 * @type string $id
277 * @type string $name
278 * @type string $type
279 * @type string $value
280 * @type string $compare
281 * @type string $class
282 * @type boolean $required
283 * @type string $delimiter
284 * @type string $placeholder
285 * @type string $pattern
286 * @type string $title
287 * @type string $min
288 * @type string $max
289 * @type string $rows Number of rows for a textarea (default:5).
290 * @type string $cols Number of columns for a textarea (default:20).
291 * }
292 * @return string $str The field returned as a string.
293 */
294 function create_form_field( $args ) {
295
296 // Set defaults for most possible $args.
297 $id = ( isset( $args['id'] ) ) ? esc_attr( $args['id'] ) : esc_attr( $args['name'] );
298 $name = esc_attr( $args['name'] );
299 $type = esc_attr( $args['type'] );
300 $value = ( isset( $args['value'] ) ) ? $args['value'] : '';
301 $compare = ( isset( $args['compare'] ) ) ? $args['compare'] : '';
302 $class = ( isset( $args['class'] ) ) ? $args['class'] : 'textbox';
303 $required = ( isset( $args['required'] ) ) ? $args['required'] : false;
304 $delimiter = ( isset( $args['delimiter'] ) ) ? $args['delimiter'] : '|';
305 $placeholder = ( isset( $args['placeholder'] ) ) ? $args['placeholder'] : false;
306 $pattern = ( isset( $args['pattern'] ) ) ? $args['pattern'] : false;
307 $title = ( isset( $args['title'] ) ) ? $args['title'] : false;
308 $file_types = ( isset( $args['file_types'] ) ) ? $args['file_types'] : false;
309 $timestamp = ( isset( $args['timestamp_display'] ) ) ? $args['timestamp_display'] : 'Y-m-d';
310
311 // Handle field creation by type.
312 switch ( $type ) {
313
314 /*
315 * Field types text|url|email|number|date are all handled essentially the
316 * same. The primary differences are CSS class (with a default fallback
317 * of 'textbox'), how values are escaped, and the application of min|max
318 * values for number fields.
319 */
320 case "text":
321 case "url":
322 case "email":
323 case "number":
324 case "date":
325 case "timestamp":
326 $class = ( 'textbox' == $class ) ? "textbox" : wpmem_sanitize_class( $class );
327 switch ( $type ) {
328 case 'url':
329 $value = esc_url( $value );
330 break;
331 case 'timestamp':
332 $value = ( '' != $value ) ? date( $timestamp, intval( $value ) ) : '';
333 break;
334 default:
335 $value = wp_unslash( esc_attr( $value ) );
336 break;
337 }
338 $required = ( $required ) ? ' required' : '';
339 $placeholder = ( $placeholder ) ? ' placeholder="' . esc_attr( __( $placeholder, 'wp-members' ) ) . '"' : '';
340 $title = ( $title ) ? ' title="' . esc_attr( __( $title, 'wp-members' ) ) . '"' : '';
341 $pattern = ( $pattern && 'number' != $type ) ? ' pattern="' . esc_attr( $pattern ) . '"' : '';
342 $min = ( isset( $args['min'] ) && $args['min'] != '' ) ? ' min="' . esc_attr( $args['min'] ) . '"' : '';
343 $max = ( isset( $args['max'] ) && $args['max'] != '' ) ? ' max="' . esc_attr( $args['max'] ). '"' : '';
344 $str = "<input name=\"$name\" type=\"$type\" id=\"$id\" value=\"$value\" class=\"$class\"$placeholder$title$pattern$min$max" . ( ( $required ) ? " required " : "" ) . " />";
345 break;
346
347 case "password":
348 $class = wpmem_sanitize_class( $class );
349 $placeholder = ( $placeholder ) ? ' placeholder="' . esc_attr( __( $placeholder, 'wp-members' ) ) . '"' : '';
350 $pattern = ( $pattern ) ? ' pattern="' . esc_attr( $pattern ) . '"' : '';
351 $title = ( $title ) ? ' title="' . esc_attr( __( $title, 'wp-members' ) ) . '"' : '';
352 $str = "<input name=\"$name\" type=\"$type\" id=\"$id\" class=\"$class\"$placeholder$title$pattern" . ( ( $required ) ? " required " : "" ) . " />";
353 break;
354
355 case "image":
356 case "file":
357 if ( $file_types ) {
358 $file_types = explode( '|', $file_types );
359 foreach( $file_types as $file_type ) {
360 $array[] = "." . $file_type;
361 }
362 $accept = ' accept="' . implode( ",", $array ) . '"';
363 } else {
364 $accept = '';
365 }
366 $class = ( 'textbox' == $class ) ? "file" : wpmem_sanitize_class( $class );
367 $str = "<input name=\"$name\" type=\"file\" id=\"$id\" value=\"" . esc_attr( $value ) . "\" class=\"$class\"$accept" . ( ( $required ) ? " required " : "" ) . ( ( 'image' == $type ) ? ' onchange="loadFile(event, this.id)"' : '' ) . ' />';
368 break;
369
370 case "checkbox":
371 $class = ( 'textbox' == $class ) ? "checkbox" : wpmem_sanitize_class( $class );
372 $str = "<input name=\"$name\" type=\"$type\" id=\"$id\" value=\"" . esc_attr( $value ) . "\"" . checked( $value, $compare, false ) . ( ( $required ) ? " required " : "" ) . " />";
373 break;
374
375 case "textarea":
376 $value = esc_textarea( stripslashes( $value ) ); // stripslashes( esc_textarea( $value ) );
377 $class = ( 'textbox' == $class ) ? "textarea" : wpmem_sanitize_class( $class );
378 $placeholder = ( $placeholder ) ? ' placeholder="' . esc_attr( __( $placeholder, 'wp-members' ) ) . '"' : '';
379 $rows = ( isset( $args['rows'] ) && $args['rows'] ) ? esc_attr( $args['rows'] ) : '5';
380 $cols = ( isset( $args['cols'] ) && $args['cols'] ) ? esc_attr( $args['cols'] ) : '20';
381 $str = "<textarea cols=\"$cols\" rows=\"$rows\" name=\"$name\" id=\"$id\" class=\"$class\"$placeholder" . ( ( $required ) ? " required " : "" ) . ">$value</textarea>";
382 break;
383
384 case "hidden":
385 $str = "<input name=\"$name\" type=\"$type\" value=\"" . esc_attr( $value ) . "\" />";
386 break;
387
388 case "option":
389 $str = "<option value=\"" . esc_attr( $value ) . "\" " . selected( $value, $compare, false ) . " >" . __( $name, 'wp-members' ) . "</option>";
390 break;
391
392 case "select":
393 case "multiselect":
394 case "membership":
395 $class = ( 'textbox' == $class && 'multiselect' != $type ) ? "dropdown" : $class;
396 $class = ( 'textbox' == $class && 'multiselect' == $type ) ? "multiselect" : $class;
397 $pname = ( 'multiselect' == $type ) ? $name . "[]" : $name;
398 $str = "<select name=\"$pname\" id=\"$id\" class=\"$class\"" . ( ( 'multiselect' == $type ) ? " multiple " : "" ) . ( ( $required ) ? " required " : "" ) . ">\n";
399 if ( 'membership' == $type ) {
400 $value = array( wpmem_get_text( 'membership_field' ) . '|' );
401 foreach( wpmem_get_memberships() as $membership_key => $membership_value ) {
402 $value[] = $membership_value['title'] . '|' . $membership_key;
403 }
404 }
405 foreach ( $value as $option ) {
406 $pieces = array_map( 'trim', explode( '|', $option ) );
407 if ( 'multiselect' == $type ) {
408 $chk = '';
409 $values = ( empty( $compare ) ) ? array() : ( is_array( $compare ) ? $compare : explode( $delimiter, $compare ) );
410 } else {
411 $chk = $compare;
412 $values = array();
413 }
414 if ( isset( $pieces[1] ) && '' != $pieces[1] ) {
415 $chk = ( ( isset( $pieces[2] ) && '' == $compare ) || in_array( $pieces[1], $values ) ) ? $pieces[1] : $chk;
416 } else {
417 $chk = 'not selected';
418 }
419 $pieces[1] = ( isset( $pieces[1] ) ) ? $pieces[1] : ''; // If someone skipped a pipe, treat it as empty.
420 $str = $str . "<option value=\"$pieces[1]\"" . selected( $pieces[1], $chk, false ) . ">" . esc_attr( __( $pieces[0], 'wp-members' ) ) . "</option>\n";
421 }
422 $str = $str . "</select>";
423 break;
424
425 case "multicheckbox":
426 $class = ( 'textbox' == $class ) ? "checkbox" : $class;
427 $str = '';
428 $num = 1;
429 foreach ( $value as $option ) {
430 $pieces = explode( '|', $option );
431 $values = ( empty( $compare ) ) ? array() : ( is_array( $compare ) ? $compare : explode( $delimiter, $compare ) );
432 $chk = ( isset( $pieces[2] ) && '' == $compare ) ? $pieces[1] : '';
433 if ( isset( $pieces[1] ) && '' != $pieces[1] ) {
434 $id_value = esc_attr( $id . '[' . $pieces[1] . ']' );
435 $label = wpmem_form_label( array( 'meta_key'=>$id_value, 'label'=>esc_html( __( $pieces[0], 'wp-members' ) ), 'type'=>'multicheckbox', 'id'=>$id_value ) );
436 $str = $str . wpmem_form_field( array(
437 'id' => $id_value,
438 'name' => $name . '[]',
439 'type' => 'checkbox',
440 'value' => $pieces[1],
441 'compare' => ( in_array( $pieces[1], $values ) ) ? $pieces[1] : $chk,
442 ) ) . "&nbsp;" . $label . "<br />\n";
443 } else {
444 $str = $str . '<span class="div_multicheckbox_separator">' . esc_html( __( $pieces[0], 'wp-members' ) ) . "</span><br />\n";
445 }
446 }
447 break;
448
449 case "radio":
450 $class = ( 'textbox' == $class ) ? "radio" : wpmem_sanitize_class( $class );
451 $str = '';
452 $num = 1;
453 foreach ( $value as $option ) {
454 $pieces = explode( '|', $option );
455 $id_num = $id . '_' . $num;
456 if ( isset( $pieces[1] ) && '' != $pieces[1] ) {
457 $label = wpmem_form_label( array( 'meta_key'=>esc_attr( $id_num ), 'label'=>esc_html( __( $pieces[0], 'wp-members' ) ), 'type'=>'radio', 'id'=>esc_attr( "label_" . $id_num ) ) );
458 $str = $str . "<input type=\"radio\" name=\"$name\" id=\"" . esc_attr( $id_num ) . "\" value=\"" . esc_attr( $pieces[1] ) . '"' . checked( $pieces[1], $compare, false ) . ( ( $required ) ? " required " : " " ) . "> $label<br />\n";
459 $num++;
460 } else {
461 $str = $str . '<span class="div_radio_separator">' . esc_html( __( $pieces[0], 'wp-members' ) ) . "</span><br />\n";
462 }
463 }
464 break;
465
466 }
467
468 return $str;
469 } // End create_form_field()
470
471 /**
472 * Create form label.
473 *
474 * @since 3.1.7
475 * @since 3.2.4 Added $id
476 *
477 * @param array $args {
478 * @type string $meta_key
479 * @type string $label
480 * @type string $type
481 * @type string $id (optional)
482 * @type string $class (optional)
483 * @type string $required (optional)
484 * @type string $req_mark (optional)
485 * }
486 * @return string $label
487 */
488 function create_form_label( $args ) {
489
490 $defaults = array(
491 'meta_key' => $args['meta_key'],
492 'label' => $args['label'],
493 'type' => $args['type'],
494 'class' => ( isset( $args['class'] ) ) ? $args['class'] : false,
495 'id' => ( isset( $args['id'] ) ) ? $args['id'] : false,
496 'required' => ( isset( $args['required'] ) ) ? $args['required'] : false,
497 'req_mark ' => ( isset( $args['req_mark'] ) ) ? $args['req_mark'] : false,
498 'label_href' => ( isset( $args['label_href'] ) ) ? $args['label_href'] : false,
499 );
500
501 /**
502 * Filter the form label args before assembly.
503 *
504 * @since 3.5.3
505 *
506 * @param array $args
507 */
508 $args = apply_filters( 'wpmem_create_form_label_args', $defaults );
509
510 $req_mark = ( ! isset( $args['req_mark'] ) || ! $args['req_mark'] ) ? wpmem_get_text( 'register_req_mark' ) : $args['req_mark'];
511
512 if ( isset( $args['label_href'] ) && '' != $args['label_href'] ) {
513 $label_text_escd = $this->apply_label_link( $args['meta_key'], $args );
514 } else {
515 $label_text_escd = esc_html( __( $args['label'], 'wp-members' ) );
516 }
517
518 if ( ! $args['class'] ) {
519 $class = ( $args['type'] == 'password' || $args['type'] == 'email' || $args['type'] == 'url' ) ? 'text' : $args['type'];
520 } else {
521 $class = $args['class'];
522 }
523
524 $id_escd = ( $args['id'] ) ? ' id="' . esc_attr( $args['id'] ) . '"' : '';
525
526 $label = '<label for="' . esc_attr( $args['meta_key'] ) . '"' . $id_escd . ' class="' . wpmem_sanitize_class( $class ) . '">' . $label_text_escd;
527 $label = ( $args['required'] ) ? $label . $req_mark : $label; // $req_mark text is escaped in wpmem_get_text() and then wrapped with html tag.
528 $label = $label . '</label>';
529
530 return $label;
531 }
532
533 /**
534 * Login Form Builder.
535 *
536 * Builds the form used for login, change password, and reset password.
537 *
538 * @since 2.5.1
539 * @since 3.1.7 Moved to forms object class as login_form().
540 * @since 3.1.7 Added WP action login_form.
541 * @since 3.2.6 Added nonce to the short form.
542 *
543 * @param string $page
544 * @param array $arr {
545 * The elements needed to generate the form (login|reset password|forgotten password).
546 *
547 * @type string $heading Form heading text.
548 * @type string $action The form action (login|pwdchange|pwdreset|getusername).
549 * @type string $button_text Form submit button text.
550 * @type array $inputs {
551 * The form input values.
552 *
553 * @type array {
554 *
555 * @type string $name The field label.
556 * @type string $type Input type.
557 * @type string $tag Input tag name.
558 * @type string $class Input tag class.
559 * @type string $div Div wrapper class.
560 * }
561 * }
562 * @type string $redirect_to Optional. URL to redirect to.
563 * }
564 * @return string $form The HTML for the form as a string.
565 */
566 function login_form( $mixed, $arr = array() ) {
567
568 global $wpmem;
569
570 // Handle legacy use.
571 if ( is_array( $mixed ) ) {
572 $page = ( isset( $mixed['page'] ) ) ? $mixed['page'] : 'login';
573 $arr = $mixed;
574 } else {
575 $page = $mixed;
576 }
577
578 $action = ( ! isset( $arr['action'] ) ) ? 'login' : $arr['action'];
579
580 // Set up redirect_to
581 $redirect_to = wpmem_get_redirect_to( $arr );
582
583 // Set up default wrappers.
584 // NOTE: DO NOT EDIT! There is a filter hook for this -> wpmem_login_form_args.
585 $defaults = array(
586
587 // wrappers
588 'heading_before' => '<legend>',
589 'heading_after' => '</legend>',
590 'fieldset_before' => '<fieldset>',
591 'fieldset_after' => '</fieldset>',
592 'main_div_before' => '<div id="wpmem_login">',
593 'main_div_after' => '</div>',
594 'row_before' => '',
595 'row_after' => '',
596 'buttons_before' => '<div class="button_div">',
597 'buttons_after' => '</div>',
598 'link_before' => '<div class="link-text">',
599 'link_after' => '</div>',
600 'link_span_before' => '<span class="link-text-%s">',
601 'link_span_after' => '</span>',
602
603 // classes & ids
604 'form_id' => 'wpmem_' . $action . '_form',
605 'form_class' => 'form',
606 'button_id' => '',
607 'button_class' => 'buttons',
608
609 // other
610 'strip_breaks' => true,
611 'wrap_inputs' => true,
612 'remember_check' => true,
613 'n' => "\n",
614 't' => "\t",
615 'redirect_to' => $redirect_to,
616 'login_form_action' => true,
617 'novalidate' => false,
618 );
619
620 /**
621 * Filter the default form arguments.
622 *
623 * This filter accepts an array of various elements to replace the form defaults. This
624 * includes default tags, labels, text, and small items including various booleans.
625 *
626 * @since 2.9.0
627 * @since 3.3.0 Passes $defaults as an argument.
628 *
629 * @param array $args {
630 * An array of arguments to merge with defaults.
631 *
632 * @type string $heading_before Default: '<legend>'
633 * @type string $heading_after Default: '</legend>'
634 * @type string $fieldset_before Default: '<fieldset>'
635 * @type string $fieldset_after Default: '</fieldset>'
636 * @type string $main_div_before Default: '<div id="wpmem_login">'
637 * @type string $main_div_after Default: '</div>'
638 * @type string $row_before Default: ''
639 * @type string $row_after Default: ''
640 * @type string $buttons_before Default: '<div class="button_div">'
641 * @type string $buttons_after Default: '</div>'
642 * @type string $link_before Default: '<div class="link-text">'
643 * @type string $link_after Default: '</div>'
644 * @type string $link_span_before Default: '<span class="link-text-%s">'
645 * @type string $link_span_after Default: '</span>'
646 * @type string $form_id Default: 'wpmem_' . $action . '_form' (for example, wpmem_login_form or wpmem_pwdreset_form)
647 * @type string $form_class Default: 'form'
648 * @type string $button_id Default: ''
649 * @type string $button_class Default: buttons'
650 * @type boolean $strip_breaks Default: true (if true, strips all line breaks from the generated HTML)
651 * @type boolean $wrap_inputs Default: true (if true, includes main_div_before/after wrappers around input tags)
652 * @type boolean $remember_check Default: true
653 * @type string $n Default: "\n" (the new line character if breaks are not stripped (see $strip_breaks))
654 * @type string $t Default: "\t" (the line indent character if breaks are not stripped (see $strip_breaks))
655 * @type string $redirect_to Default: (the $redirect_to argument passed to the function)
656 * @type boolean $login_form_action Default: true (if true, adds the WP login_form action)
657 * }
658 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
659 */
660 $args = apply_filters( 'wpmem_login_form_args', $defaults, $action );
661
662 // Merge $args with defaults.
663 $args = wp_parse_args( $args, $defaults );
664
665 // Build the input rows.
666 foreach ( $arr['inputs'] as $input ) {
667 $label = '<label for="' . esc_attr( $input['tag'] ) . '">' . $input['name'] . '</label>';
668 $field = wpmem_form_field( array(
669 'name' => $input['tag'],
670 'type' => $input['type'],
671 'class' => $input['class'],
672 'required' => true,
673 ) );
674 $field_before = ( $args['wrap_inputs'] ) ? '<div class="' . wpmem_sanitize_class( $input['div'] ) . '">' : '';
675 $field_after = ( $args['wrap_inputs'] ) ? '</div>' : '';
676 $rows[] = array(
677 'row_before' => $args['row_before'],
678 'label' => $label,
679 'field_before' => $field_before,
680 'field' => $field,
681 'field_after' => $field_after,
682 'row_after' => $args['row_after'],
683 );
684 }
685
686 /**
687 * Filter the array of form rows.
688 *
689 * This filter receives an array of the main rows in the form, each array element being
690 * an array of that particular row's pieces. This allows making changes to individual
691 * parts of a row without needing to parse through a string of HTML.
692 *
693 * @since 2.9.0
694 * @since 3.2.6 Added $arr parameter so all settings are passed.
695 *
696 * @param array $rows An array containing the form rows.
697 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
698 * @param array $arr An array containing all of the form settings.
699 */
700 $rows = apply_filters( 'wpmem_login_form_rows', $rows, $action, $arr );
701
702 // Put the rows from the array into $form.
703 $form = '';
704 foreach ( $rows as $row_item ) {
705 $row = ( $row_item['row_before'] != '' ) ? $row_item['row_before'] . $args['n'] . $row_item['label'] . $args['n'] : $row_item['label'] . $args['n'];
706 $row .= ( $row_item['field_before'] != '' ) ? $row_item['field_before'] . $args['n'] . $args['t'] . $row_item['field'] . $args['n'] . $row_item['field_after'] . $args['n'] : $row_item['field'] . $args['n'];
707 $row .= ( $row_item['row_after'] != '' ) ? $row_item['row_after'] . $args['n'] : '';
708 $form.= $row;
709 }
710
711 // Handle outside elements added to the login form (currently ONLY for login).
712 if ( 'login' == $action && $args['login_form_action'] ) {
713 ob_start();
714 /** This action is documented in wp-login.php */
715 do_action( 'login_form' );
716 $add_to_form = ob_get_contents();
717 ob_end_clean();
718 $form.= $add_to_form;
719 }
720
721 // Build hidden fields, filter, and add to the form.
722 if ( 'set_password_from_key' == wpmem_get( 'a', false, 'request' ) && 'login' != $action ) {
723 $hidden['action'] = wpmem_form_field( array( 'name' => 'a', 'type' => 'hidden', 'value' => 'set_password_from_key' ) );
724 $hidden['key'] = wpmem_form_field( array( 'name' => 'key', 'type' => 'hidden', 'value' => sanitize_text_field( wpmem_get( 'key', null, 'request' ) ) ) );
725 $hidden['login'] = wpmem_form_field( array( 'name' => 'login', 'type' => 'hidden', 'value' => sanitize_user( wpmem_get( 'login', null, 'request' ) ) ) );
726 } else {
727 $hidden['action'] = wpmem_form_field( array( 'name' => 'a', 'type' => 'hidden', 'value' => $action ) );
728 $hidden['redirect_to'] = wpmem_form_field( array( 'name' => 'redirect_to', 'type' => 'hidden', 'value' => esc_url( $args['redirect_to'] ) ) );
729 }
730
731 if ( $action != 'login' ) {
732 $hidden['formsubmit'] = wpmem_form_field( array( 'name' => 'formsubmit', 'type' => 'hidden', 'value' => '1' ) );
733 }
734
735 /**
736 * Filter hidden fields array.
737 *
738 * @since 3.4.0
739 *
740 * @param array $hidden
741 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
742 */
743 $hidden = apply_filters( 'wpmem_login_hidden_field_rows', $hidden, $action );
744
745 $hidden_field_string = '';
746 foreach ( $hidden as $field ) {
747 $hidden_field_string .= $field . $args['n'];
748 }
749
750 /**
751 * Filter the hidden field HTML.
752 *
753 * @since 2.9.0
754 *
755 * @param string $hidden The generated HTML of hidden fields.
756 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
757 */
758 $form = $form . apply_filters( 'wpmem_login_hidden_fields', $hidden_field_string, $action );
759
760 // Build the buttons, filter, and add to the form.
761 if ( $action == 'login' ) {
762 $buttons[] = ( $args['remember_check'] ) ? $args['t'] . wpmem_form_field( array( 'name' => 'rememberme', 'type' => 'checkbox', 'value' => 'forever' ) ) . '&nbsp;' . '<label for="rememberme">' . wpmem_get_text( 'remember_me' ) . '</label>&nbsp;&nbsp;' . $args['n'] : '';
763 $buttons[] = $args['t'] . '<input type="submit" name="Submit" value="' . esc_attr( $arr['button_text'] ) . '" class="' . wpmem_sanitize_class( $args['button_class'] ) . '" />' . $args['n'];
764 } else {
765 $buttons[] = '<input type="submit" name="Submit" value="' . esc_attr( $arr['button_text'] ) . '" class="' . wpmem_sanitize_class( $args['button_class'] ) . '" />' . $args['n'];
766 }
767
768 /**
769 * Filter the button parts.
770 *
771 * @since 3.4.5
772 *
773 * @param array $rows
774 * @param string $action
775 */
776 $buttons = apply_filters( 'wpmem_login_form_button_rows', $buttons, $action );
777
778 // HTML assembly for buttons.
779 $button_html = '';
780 foreach ( $buttons as $button_row ) {
781 $button_html .= $button_row;
782 }
783
784 /**
785 * Filter the HTML for form buttons.
786 *
787 * The string includes the buttons, as well as the before/after wrapper elements.
788 *
789 * @since 2.9.0
790 *
791 * @param string $buttons The generated HTML of the form buttons.
792 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
793 */
794 $form = $form . apply_filters( 'wpmem_login_form_buttons', $args['buttons_before'] . $args['n'] . $button_html . $args['buttons_after'] . $args['n'], $action );
795
796 $links_array = array(
797 'forgot' => array(
798 'tag' => 'forgot',
799 'link' => wpmem_pwd_reset_url(),
800 'page' => 'profile',
801 'action' => 'login',
802 ),
803 'register' => array(
804 'tag' => 'reg',
805 'link' => wpmem_register_url(),
806 'page' => 'register',
807 'action' => 'login',
808 ),
809 'username' => array(
810 'tag' => 'username',
811 'link' => wpmem_forgot_username_url(),
812 'page' => 'profile',
813 'action' => 'pwdreset',
814 ),
815 );
816
817 if ( wpmem_is_enabled( 'act_link' ) ) {
818 $links_array['reconfirm'] = array(
819 'tag' => 'reconfirm',
820 'link' => wpmem_reconfirm_url(),
821 'page' => 'profile',
822 'action' => 'pwdreset',
823 );
824 }
825
826 foreach ( $links_array as $key => $value ) {
827 $tag = $value['tag'];
828 if ( ( $wpmem->user_pages[ $value['page'] ] || 'profile' == $page ) && $value['action'] == $action ) {
829 /**
830 * Filters register, forgot password, forgot username, and resend confirmation links.
831 *
832 * @since 2.8.0
833 * @since 3.1.7 Combined all to a single process.
834 * @since 3.2.5 Added $tag parameter.
835 *
836 * @param string The raw link.
837 * @param string $tag forgot|reg|pwdreset|username.
838 */
839 $link = apply_filters( "wpmem_{$tag}_link", $value['link'], $tag );
840 $str = wpmem_get_text( "{$key}_link_before" ) . '<a href="' . esc_url( $link ) . '">' . wpmem_get_text( "{$key}_link" ) . '</a>';
841 $link_str = $args['link_before'];
842 $link_str.= ( '' != $args['link_span_before'] ) ? sprintf( $args['link_span_before'], $key ) : '';
843 /**
844 * Filters the register, forgot password, forgot username, and resend confirmation links HTML.
845 *
846 * @since 2.9.0
847 * @since 3.0.9 Added $link parameter.
848 * @since 3.1.7 Combined all to a single process.
849 * @since 3.2.5 Added $tag parameter.
850 *
851 * @param string $str The link HTML.
852 * @param string $link The link.
853 * @param string $tag forgot|reg|pwdreset.
854 */
855 $link_str.= apply_filters( "wpmem_{$tag}_link_str", $str, $link, $tag );
856 $link_str.= ( '' != $args['link_span_after'] ) ? $args['link_span_after'] : '';
857 $link_str.= $args['link_after'] . $args['n'];
858 /*
859 * If this is the register link, and the current post type is set to
860 * display the register form, and the current page is not the login
861 * page, then do not add the register link, otherwise add the link.
862 */
863 if ( 'register' == $key ) {
864 if ( ! isset( $wpmem->user_pages['register'] ) || '' == $wpmem->user_pages['register'] ) {
865 $form = $form;
866 } else {
867 if ( isset( $wpmem->user_pages['login'] ) && '' != $wpmem->user_pages['login'] ) {
868 $form = ( 1 == $wpmem->show_reg[ get_post_type( get_the_ID() ) ] && wpmem_current_url( true, false ) != wpmem_login_url() ) ? $form : $form . $link_str;
869 } else {
870 global $post;
871 if ( has_shortcode( $post->post_content, 'wpmem_profile' ) ) {
872 $form = $form;
873 } else {
874 $form = ( 1 == $wpmem->show_reg[ get_post_type( get_the_ID() ) ] && ! has_shortcode( $post->post_content, 'wpmem_form' ) ) ? $form : $form . $link_str;
875 }
876 }
877 }
878 } else {
879 $form = $form . $link_str;
880 }
881 }
882 }
883
884 $novalidate = ( $args['novalidate'] ) ? 'novalidate' : '';
885
886 // Apply the heading.
887 $form = $args['heading_before'] . $arr['heading'] . $args['heading_after'] . $args['n'] . $form;
888
889 // Apply fieldset wrapper.
890 $form = $args['fieldset_before'] . $args['n'] . $form . $args['fieldset_after'] . $args['n'];
891
892 // Apply nonce.
893 $form = wp_nonce_field( 'wpmem_shortform_nonce', '_wpmem_' . $action . '_nonce', true, false ) . $args['n'] . $form;
894
895 // Apply form wrapper.
896 $form = '<form action="' . esc_url( get_permalink() ) . '" method="POST" id="' . wpmem_sanitize_class( $args['form_id'] ) . '" class="' . wpmem_sanitize_class( $args['form_class'] ) . '"' . $novalidate . '>' . $args['n'] . $form . '</form>';
897
898 // Apply anchor.
899 $form = '<a id="' . esc_attr( $action ) . '"></a>' . $args['n'] . $form;
900
901 // Apply main wrapper.
902 $form = $args['main_div_before'] . $args['n'] . $form . $args['n'] . $args['main_div_after'];
903
904 // Remove line breaks.
905 $form = ( $args['strip_breaks'] ) ? str_replace( array( "\n", "\r", "\t" ), array( '','','' ), $form ) : $form;
906
907 /**
908 * Filter the generated HTML of the entire form.
909 *
910 * @since 2.7.4
911 * @since 2.9.1 Added $action argument
912 *
913 * @param string $form The HTML of the final generated form.
914 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
915 */
916 $form = apply_filters( 'wpmem_login_form', $form, $action );
917
918 /**
919 * Filter before the form.
920 *
921 * This rarely used filter allows you to stick any string onto the front of
922 * the generated form.
923 *
924 * @since 2.7.4
925 *
926 * @param string $str The HTML to add before the form. Default null.
927 * @param string $action The action being performed by the form. login|pwdreset|pwdchange|getusername.
928 */
929 $form = apply_filters( 'wpmem_login_form_before', '', $action ) . $form;
930
931 return $form;
932 } // End login_form.
933
934 /**
935 * Registration Form Builder.
936 *
937 * Outputs the form for new user registration and existing user edits.
938 *
939 * @since 2.5.1
940 * @since 3.1.7 Moved to forms object class as register_form().
941 * @since 3.2.5 use_nonce now obsolete (nonce is added automatically).
942 * @since 3.3.0 $heading argument obsolete.
943 * @since 3.3.3 Image field type now shows the preview image when "choose file" is clicked.
944 * @since 3.4.6 Added $user object as a filterable arg.
945 *
946 * @global object $wpmem The WP_Members object.
947 * @param mixed $mixed (optional) String toggles between new registration ('new') and user profile edit ('edit'), or array containing settings arguments.
948 * @return string $form The HTML for the entire form as a string.
949 */
950 function register_form( $mixed = 'new', $redirect_to = null ) {
951
952 /*
953 * Removes the action to load form elements for the WP registration
954 * form. Otherwise, when the register_form action is fired in this
955 * form, we'd get a duplication of all custom fields.
956 */
957 remove_action( 'register_form', 'wpmem_wp_register_form' );
958
959 // Handle legacy use.
960 if ( is_array( $mixed ) ) {
961 $id = ( isset( $mixed['id'] ) ) ? $mixed['id'] : '';
962 $tag = ( isset( $mixed['tag'] ) ) ? $mixed['tag'] : 'new';
963 $heading = ( isset( $mixed['heading'] ) ) ? $mixed['heading'] : '';
964 $redirect_to = ( isset( $mixed['redirect_to'] ) ) ? $mixed['redirect_to'] : '';
965 $fields = ( isset( $mixed['fields'] ) ) ? $mixed['fields'] : false;
966 } else {
967 $id = 'default';
968 $tag = $mixed;
969 }
970
971 global $wpmem;
972
973 // If editing, the user object of the user being edit.
974 $user = ( 'edit' == $tag ) ? get_user_by( 'ID', get_current_user_id() ) : false;
975
976 /**
977 * Set up default wrappers.
978 *
979 * DO NOT EDIT THESE! If you need to customize, use the filter hook
980 * documented below to set up a proper, external filter function.
981 *
982 * @see wpmem_register_form_args
983 * @link https://rocketgeek.com/plugins/wp-members/docs/filter-hooks/wpmem_register_form_args/
984 */
985 $defaults = array(
986
987 // Wrappers.
988 'heading_before' => '<legend>',
989 'heading_after' => '</legend>',
990 'fieldset_before' => '<fieldset>',
991 'fieldset_after' => '</fieldset>',
992 'main_div_before' => '<div id="wpmem_reg">',
993 'main_div_after' => '</div>',
994 'row_before' => '',
995 'row_after' => '',
996 'buttons_before' => '<div class="button_div">',
997 'buttons_after' => '</div>',
998
999 // Classes & ids.
1000 'form_id' => ( 'new' == $tag ) ? 'wpmem_register_form' : 'wpmem_profile_form',
1001 'form_class' => 'form',
1002 'button_id' => '',
1003 'button_class' => 'buttons',
1004
1005 // Required field tags and text.
1006 'req_mark' => wpmem_get_text( 'register_req_mark' ),
1007 'req_label' => wpmem_get_text( 'register_required' ),
1008 'req_label_before' => '<div class="req-text">',
1009 'req_label_after' => '</div>',
1010
1011 // Buttons.
1012 'show_clear_form' => false,
1013 'clear_form' => wpmem_get_text( 'register_clear' ),
1014 'submit_register' => wpmem_get_text( 'register_submit' ),
1015 'submit_update' => wpmem_get_text( 'profile_submit' ),
1016
1017 // Other.
1018 'post_to' => get_permalink(),
1019 'strip_breaks' => true,
1020 'wrap_inputs' => true,
1021 'n' => "\n",
1022 't' => "\t",
1023 'register_form_action' => true,
1024 'user' => $user,
1025 'novalidate' => false,
1026 );
1027
1028 /**
1029 * Filter the default form arguments.
1030 *
1031 * This filter accepts an array of various elements to replace the form defaults. This
1032 * includes default tags, labels, text, and small items including various booleans.
1033 *
1034 * @since 2.9.0
1035 * @since 3.2.5 Added $id
1036 * @since 3.3.0 Passes $defaults as an argument.
1037 * @since 3.4.6 Added $user as an argument.
1038 *
1039 * @param array An array of arguments to merge with defaults. Default null.
1040 * @param string $tag Toggle new registration or profile update. new|edit.
1041 * @param string $id An id for the form (optional).
1042 */
1043 $args = apply_filters( 'wpmem_register_form_args', $defaults, $tag, $id );
1044
1045 // Merge $args with defaults.
1046 $args = wp_parse_args( $args, $defaults );
1047
1048 // User ID based on filtered value.
1049 $user = $args['user'];
1050
1051 // Get fields.
1052 $wpmem_fields = wpmem_fields( $tag );
1053
1054 // Fields to skip for user profile update.
1055 if ( 'edit' == $tag ) {
1056 $pass_arr = array( 'username', 'password', 'confirm_password', 'password_confirm' );
1057 // Skips tos on user edit page, unless they haven't got a value for tos.
1058 $user_tos_val = ( is_object( $user ) ) ? get_user_meta( $user->ID, 'tos', true ) : false;
1059 if ( isset( $wpmem_fields['tos'] ) && ( $wpmem_fields['tos']['checked_value'] == $user_tos_val ) ) {
1060 $pass_arr[] = 'tos';
1061 }
1062 foreach ( $pass_arr as $pass ) {
1063 unset( $wpmem_fields[ $pass ] );
1064 }
1065 }
1066
1067 /**
1068 * Filter the array of form fields.
1069 *
1070 * The form fields are stored in the WP options table as wpmembers_fields. This
1071 * filter can filter that array after the option is retreived before the fields
1072 * are parsed. This allows you to change the fields that may be used in the form
1073 * on the fly.
1074 *
1075 * @since 2.9.0
1076 * @deprecated 3.1.7 Use wpmem_fields instead.
1077 *
1078 * @param array The array of form fields.
1079 * @param string $tag Toggle new registration or profile update. new|edit.
1080 */
1081 $wpmem_fields = apply_filters_deprecated( 'wpmem_register_fields_arr', array( $wpmem_fields, $tag ), '3.1.7', 'wpmem_fields' );
1082
1083 $hidden_rows = array();
1084 $form_has_file = false;
1085
1086 // Loop through the remaining fields.
1087 foreach ( $wpmem_fields as $meta_key => $field ) {
1088
1089 // Start with a clean row.
1090 $val = ''; $label = ''; $input = ''; $field_before = ''; $field_after = '';
1091
1092 // If the field is set to display and we aren't skipping, construct the row.
1093 // Handle hidden fields
1094 if ( 'hidden' == $field['type'] ) {
1095 $do_row = false;
1096 $hidden_rows[ $meta_key ] = wpmem_form_field( array(
1097 'name' => $meta_key,
1098 'type' => $field['type'],
1099 'value' => $field['value'],
1100 'compare' => $valtochk,
1101 'required' => $field['required'],
1102 ) );
1103 }
1104
1105 // Label for all but TOS and hidden fields.
1106 if ( 'tos' != $meta_key && 'hidden' != $field['type'] ) {
1107
1108 $class = ( $field['type'] == 'password' || $field['type'] == 'email' || $field['type'] == 'url' ) ? 'text' : $field['type'];
1109
1110 $label = wpmem_form_label( array(
1111 'meta_key' => $meta_key, //( 'username' == $meta_key ) ? 'user_login' : $meta_key,
1112 'label' => __( $field['label'], 'wp-members' ),
1113 'type' => $field['type'],
1114 'class' => $class,
1115 'required' => $field['required'],
1116 'req_mark' => $args['req_mark'],
1117 'label_href' => ( isset( $field['label_href'] ) ) ? $field['label_href'] : false,
1118 ) );
1119
1120 }
1121
1122 // Gets the field value for edit profile.
1123 if ( ( 'edit' == $tag ) && ( '' == wpmem_get_form_state() ) ) {
1124 switch ( $meta_key ) {
1125 case( 'description' ):
1126 case( 'textarea' == $field['type'] ):
1127 $val = ( is_object( $user ) ) ? get_user_meta( $user->ID, $meta_key, 'true' ) : ''; // esc_textarea() is run when field is created.
1128 break;
1129
1130 case 'user_email':
1131 case 'confirm_email':
1132 $val = ( is_object( $user ) ) ? sanitize_email( $user->user_email ) : '';
1133 break;
1134
1135 case 'user_url':
1136 $val = ( is_object( $user ) ) ? $user->user_url : ''; // esc_url() is run when the field is created.
1137 break;
1138
1139 case 'display_name':
1140 $val = ( is_object( $user ) ) ? sanitize_text_field( $user->display_name ) : '';
1141 break;
1142
1143 default:
1144 $val = ( is_object( $user ) ) ? sanitize_text_field( get_user_meta( $user->ID, $meta_key, 'true' ) ) : '';
1145 break;
1146 }
1147
1148 } else {
1149 if ( 'file' == $field['type'] ) {
1150 $val = ( isset( $_FILES[ $meta_key ]['name'] ) ) ? sanitize_file_name( $_FILES[ $meta_key ]['name'] ) : '' ;
1151 } else {
1152 $val = wpmem_get_sanitized( $meta_key, '', 'post', $field['type'] ); // ( isset( $_POST[ $meta_key ] ) ) ? wpmem_sanitize_field( $_POST[ $meta_key ], $field['type'] ) : '';
1153 }
1154
1155 if ( isset( $field['value'] ) && '' != $field['value'] ) {
1156 $val = $field['value'];
1157 }
1158 }
1159
1160 // Does the tos field.
1161 if ( 'tos' == $meta_key ) {
1162
1163 // $val = sanitize_text_field( wpmem_get( $meta_key, '' ) );
1164
1165 // Should be checked by default? and only if form hasn't been submitted.
1166 $val = ( ! $_POST && $field['checked_default'] ) ? $field['checked_value'] : $val;
1167 $input = wpmem_form_field( array(
1168 'name' => $meta_key,
1169 'type' => $field['type'],
1170 'value' => $field['checked_value'],
1171 'compare' => $val,
1172 'required' => $field['required'],
1173 ) );
1174
1175 $input .= ' ' . $this->get_tos_link( $field, $tag );
1176
1177 $input = ( $field['required'] ) ? $input . $args['req_mark'] : $input;
1178
1179 // In previous versions, the div class would end up being the same as the row before.
1180 $field_before = ( $args['wrap_inputs'] ) ? '<div class="div_text">' : '';
1181 $field_after = ( $args['wrap_inputs'] ) ? '</div>' : '';
1182
1183 } elseif ( 'hidden' != $field['type'] ) {
1184
1185 // For checkboxes.
1186 if ( 'checkbox' == $field['type'] ) {
1187 $valtochk = $val;
1188 $val = $field['checked_value'];
1189 // if it should it be checked by default (& only if form not submitted), then override above...
1190 if ( $field['checked_default'] && ( ! $_POST && $tag != 'edit' ) ) {
1191 $val = $valtochk = $field['checked_value'];
1192 }
1193 }
1194
1195 // For dropdown select.
1196 if ( 'select' == $field['type'] || 'radio' == $field['type'] || 'multiselect' == $field['type'] || 'multicheckbox' == $field['type'] || 'membership' == $field['type'] ) {
1197 $valtochk = $val;
1198 $val = $field['values'];
1199 }
1200
1201 if ( ! isset( $valtochk ) ) {
1202 $valtochk = '';
1203 }
1204
1205 if ( ( 'file' == $field['type'] || 'image' == $field['type'] ) ) {
1206
1207 $form_has_file = true;
1208
1209 // Handle files differently for multisite vs. single install.
1210 // @see: https://core.trac.wordpress.org/ticket/32145
1211 if ( is_multisite() ) {
1212 $attachment = get_post( $val );
1213 $attachment_url = $attachment->guid;
1214 } else {
1215 $attachment_url = wp_get_attachment_url( $val );
1216 }
1217
1218 $empty_file = '<span class="description">' . __( 'None' ) . '</span>';
1219 if ( 'edit' == $tag ) {
1220 if ( 'file' == $field['type'] ) {
1221 $input = ( $attachment_url ) ? '<a href="' . esc_url( $attachment_url ) . '" id="' . $meta_key . '_file">' . get_the_title( $val ) . '</a>' : $empty_file;
1222 } else {
1223 $input = ( $attachment_url ) ? '<img src="' . esc_url( $attachment_url ) . '" id="' . $meta_key . '_img" />' : $empty_file;
1224 }
1225 $input.= '<br />' . wpmem_get_text( 'profile_upload' ) . '<br />';
1226 } else {
1227 if ( 'image' == $field['type'] ) {
1228 $input = '<img src="" id="' . $meta_key . '_img" />';
1229 }
1230 }
1231 $input.= wpmem_form_field( array(
1232 'name' => $meta_key,
1233 'type' => $field['type'],
1234 'value' => $val,
1235 'compare' => $valtochk,
1236 'file_types' => $field['file_types'],
1237 ) );
1238
1239 } else {
1240
1241 // For all other input types.
1242 $formfield_args = array(
1243 'name' => $meta_key, // ( 'username' == $meta_key ) ? 'user_login' : $meta_key,
1244 'type' => $field['type'],
1245 'value' => $val,
1246 'compare' => $valtochk,
1247 //'class' => ( $class ) ? $class : 'textbox',
1248 'required' => $field['required'],
1249 'placeholder' => ( isset( $field['placeholder'] ) ) ? $field['placeholder'] : '',
1250 'pattern' => ( isset( $field['pattern'] ) ) ? $field['pattern'] : false,
1251 'title' => ( isset( $field['title'] ) ) ? $field['title'] : false,
1252 'min' => ( isset( $field['min'] ) ) ? $field['min'] : false,
1253 'max' => ( isset( $field['max'] ) ) ? $field['max'] : false,
1254 'rows' => ( isset( $field['rows'] ) ) ? $field['rows'] : false,
1255 'cols' => ( isset( $field['cols'] ) ) ? $field['cols'] : false,
1256 'file_types' => ( isset( $field['file_types'] ) ) ? $field['file_types'] : false,
1257 );
1258 if ( 'multicheckbox' == $field['type'] || 'multiselect' == $field['type'] ) {
1259 $formfield_args['delimiter'] = $field['delimiter'];
1260 }
1261 // Add timestamp support.
1262 if ( 'timestamp' == $field['type'] ) {
1263 $formfield_args['timestamp_display'] = $field['timestamp_display'];
1264 }
1265 $input = wpmem_form_field( $formfield_args );
1266
1267 // If checkbox label option is enabled.
1268 // @todo "checkbox_label" should be set already, check why it isn't.
1269 if ( 'checkbox' == $field['type'] && isset( $field['checkbox_label'] ) && 1 == $field['checkbox_label'] ) {
1270 $input = $input . ' <label for="' . $meta_key . '">' . $label . '</label>';
1271 $label = ''; // @todo Overdoing it throws a "Automatic conversion of false to array is deprecated" error: $fields[ $meta_key ]['label'] = $field['label'] = $label = '';
1272 }
1273 }
1274
1275 // Determine input wrappers.
1276 $field_before = ( $args['wrap_inputs'] ) ? '<div class="div_' . $class . '">' : '';
1277 $field_after = ( $args['wrap_inputs'] ) ? '</div>' : '';
1278 }
1279
1280
1281 // If the row is set to display, add the row to the form array.
1282 if ( 'hidden' != $field['type'] ) {
1283
1284 $values = '';
1285 if ( 'multicheckbox' == $field['type'] || 'select' == $field['type'] || 'multiselect' == $field['type'] || 'radio' == $field['type'] ) {
1286 $values = $val;
1287 $val = $valtochk;
1288 }
1289
1290 $rows[ $meta_key ] = array(
1291 'meta' => $meta_key,
1292 'type' => $field['type'],
1293 'value' => $val,
1294 'values' => $values,
1295 'label_text' => __( $field['label'], 'wp-members' ),
1296 'row_before' => $args['row_before'],
1297 'label' => $label,
1298 'field_before' => $field_before,
1299 'field' => $input,
1300 'field_after' => $field_after,
1301 'row_after' => $args['row_after'],
1302 );
1303 }
1304 }
1305
1306 // If captcha is Really Simple CAPTCHA.
1307 if ( 2 == $wpmem->captcha && 'edit' != $tag ) {
1308 // Build the captcha.
1309 $row = WP_Members_Captcha::rs_captcha( 'array' );
1310 $rows['captcha'] = array(
1311 'meta' => '',
1312 'type' => 'text',
1313 'value' => '',
1314 'values' => '',
1315 'label_text' => $row['label_text'],
1316 'row_before' => $args['row_before'],
1317 'label' => $row['label'],
1318 'field_before' => ( $args['wrap_inputs'] ) ? '<div class="div_text">' : '',
1319 'field' => $row['img'] . $row['hidden'] . $row['field'],
1320 'field_after' => ( $args['wrap_inputs'] ) ? '</div>' : '',
1321 'row_after' => $args['row_after'],
1322 );
1323 }
1324
1325 /**
1326 * Filter the array of form rows.
1327 *
1328 * This filter receives an array of the main rows in the form, each array element being
1329 * an array of that particular row's pieces. This allows making changes to individual
1330 * parts of a row without needing to parse through a string of HTML.
1331 *
1332 * @since 2.9.0
1333 * @since 3.0.9 Added $rows['label_text'].
1334 * @since 3.1.0 Added $rows['key'].
1335 * @since 3.1.6 Deprecated $rows['order'].
1336 *
1337 * @param array $rows {
1338 * An array containing the form rows.
1339 *
1340 * @type string order Field display order. (deprecated as of 3.1.6)
1341 * @type string meta Field meta tag (not used for display).
1342 * @type string type Input field type (not used for display).
1343 * @type string value Input field value (not used for display).
1344 * @type string values Possible field values (dropdown, multiple select/check, radio).
1345 * @type string label_text Raw text for the label (not used for display).
1346 * @type string row_before Opening wrapper tag around the row.
1347 * @type string label Label tag.
1348 * @type string field_before Opening wrapper tag before the input tag.
1349 * @type string field The field input tag.
1350 * @type string field_after Closing wrapper tag around the input tag.
1351 * @type string row_after Closing wrapper tag around the row.
1352 * }
1353 * @param string $tag Toggle new registration or profile update. new|edit.
1354 */
1355 $rows = apply_filters( 'wpmem_register_form_rows', $rows, $tag );
1356
1357 // Put the rows from the array into $form.
1358 $form = ''; $enctype = '';
1359 foreach ( $rows as $meta_key => $row_item ) {
1360 // Make sure all keys are set just in case someone didn't return a proper array through the filter.
1361 foreach ( $this->get_reg_row_keys() as $check_key ) {
1362 if ( ! isset( $rows[ $meta_key ][ $check_key ] ) ) {
1363 $rows[ $meta_key ][ $check_key ] = '';
1364 $row_item[ $check_key ] = '';
1365 }
1366 }
1367 // Check form to see if we need multipart enctype.
1368 $enctype = ( $row_item['type'] == 'file' || $row_item['type'] == 'image' ) ? "multipart/form-data" : $enctype;
1369 // Assemble row pieces.
1370 $row = ( $row_item['row_before'] != '' ) ? $row_item['row_before'] . $args['n'] . $row_item['label'] . $args['n'] : $row_item['label'] . $args['n'];
1371 $row .= ( $row_item['field_before'] != '' ) ? $row_item['field_before'] . $args['n'] . $args['t'] . $row_item['field'] . $args['n'] . $row_item['field_after'] . $args['n'] : $row_item['field'] . $args['n'];
1372 $row .= ( $row_item['row_after'] != '' ) ? $row_item['row_after'] . $args['n'] : '';
1373 $form.= $row;
1374 }
1375
1376 // Handle outside elements added to the register form with register_form.
1377 if ( 'new' == $tag && $args['register_form_action'] ) {
1378 ob_start();
1379 /** This action is documented in wp-login.php */
1380 do_action( 'register_form' );
1381 $add_to_form = ob_get_contents();
1382 ob_end_clean();
1383 $form.= $add_to_form;
1384 }
1385
1386 // Do recaptcha if enabled.
1387 if ( ( 1 == $wpmem->captcha || 3 == $wpmem->captcha || 4 == $wpmem->captcha ) && $tag != 'edit' ) { // don't show on edit page!
1388
1389 $row = WP_Members_Captcha::recaptcha();
1390
1391 if ( 4 != $wpmem->captcha ) {
1392 $row = '<div class="clear"></div><div class="captcha">' . $row . '</div>';
1393 }
1394
1395 // Add the captcha row to the form.
1396 /**
1397 * Filter the HTML for the CAPTCHA row.
1398 *
1399 * @since 2.9.0
1400 *
1401 * @param string The HTML for the entire row (includes HTML tags plus reCAPTCHA).
1402 * @param string $tag Toggle new registration or profile update. new|edit.
1403 */
1404 $form.= apply_filters( 'wpmem_register_captcha_row', $args['row_before'] . $row . $args['row_after'], $tag );
1405 }
1406
1407 if ( 5 == $wpmem->captcha && 'edit' != $tag ) {
1408 $row = WP_Members_Captcha::hcaptcha();
1409 /** This filter is documented in /includes/class-wp-members-forms.php */
1410 $form.= apply_filters( 'wpmem_register_captcha_row', $args['row_before'] . $row . $args['row_after'], $tag );
1411 }
1412
1413 // Create hidden fields.
1414 $var = ( $tag == 'edit' ) ? 'update' : 'register';
1415 $redirect_to = ( isset( $_REQUEST['redirect_to'] ) ) ? $_REQUEST['redirect_to'] : ( ( $redirect_to ) ? $redirect_to : get_permalink() );
1416 $hidden_rows['_wpmem_a'] = '<input name="a" type="hidden" value="' . esc_attr( $var ) . '" />';
1417 $hidden_rows['_wpmem_reg_page'] = '<input name="wpmem_reg_page" type="hidden" value="' . esc_url( get_permalink() ) . '" />';
1418 if ( $redirect_to != get_permalink() ) {
1419 $hidden_rows['_wpmem_redirect_to'] = '<input name="redirect_to" type="hidden" value="' . esc_url( $redirect_to ) . '" />';
1420 }
1421
1422 /**
1423 * Filter the hidden form rows.
1424 *
1425 * @since 3.2.0
1426 *
1427 * @param array $hidden_rows
1428 * @param string $tag
1429 */
1430 $hidden_rows = apply_filters( 'wpmem_register_hidden_rows', $hidden_rows, $tag );
1431
1432 // Assemble hidden fields HTML.
1433 $hidden = '';
1434 foreach ( $hidden_rows as $hidden_row ) {
1435 $hidden .= $hidden_row . $args['n'];
1436 }
1437
1438 /**
1439 * Filter the hidden field HTML.
1440 *
1441 * @since 2.9.0
1442 *
1443 * @param string $hidden The generated HTML of hidden fields.
1444 * @param string $tag Toggle new registration or profile update. new|edit.
1445 */
1446 $hidden = apply_filters( 'wpmem_register_hidden_fields', $hidden, $tag );
1447
1448 // Add the hidden fields to the form.
1449 $form.= $hidden;
1450
1451 // Create buttons and wrapper.
1452 $button_text = ( $tag == 'edit' ) ? $args['submit_update'] : $args['submit_register'];
1453 $button_html = array(
1454 'reset' => ( $args['show_clear_form'] ) ? '<input name="reset" type="reset" value="' . esc_attr( $args['clear_form'] ) . '" class="' . wpmem_sanitize_class( $args['button_class'] ) . '" /> ' : '',
1455 'submit' => '<input name="submit" type="submit" value="' . esc_attr( $button_text ) . '" class="' . wpmem_sanitize_class( $args['button_class'] ) . '" />',
1456 );
1457 $buttons = $button_html['reset'] . $args['n'] . $button_html['submit'] . $args['n'];
1458
1459 /**
1460 * Filter the HTML for form buttons.
1461 *
1462 * The string passed through the filter includes the buttons, as well as the HTML wrapper elements.
1463 *
1464 * @since 2.9.0
1465 * @since 3.2.6 Added $button_html parameter
1466 *
1467 * @param string $buttons The generated HTML of the form buttons.
1468 * @param string $tag Toggle new registration or profile update. new|edit.
1469 * @param array $button_html The individual button html.
1470 */
1471 $buttons = apply_filters( 'wpmem_register_form_buttons', $buttons, $tag, $button_html );
1472
1473 // Add the buttons to the form.
1474 $form.= $args['buttons_before'] . $args['n'] . $buttons . $args['buttons_after'] . $args['n'];
1475
1476 // Add the required field notation to the bottom of the form.
1477 $form.= $args['req_label_before'] . $args['req_label'] . $args['req_label_after'];
1478
1479 // Apply the heading.
1480 if ( 'edit' == $tag ) {
1481 /**
1482 * Filter the default heading in User Profile edit mode.
1483 *
1484 * @since 2.7.5
1485 * @since 3.3.0 Moved into main registration function (from profile shortcode).
1486 *
1487 * @param string The default edit mode heading.
1488 */
1489 $heading = ( isset( $heading ) && '' != $heading ) ? $heading : apply_filters( 'wpmem_user_edit_heading', wpmem_get_text( 'profile_heading' ) );
1490 } else {
1491 /**
1492 * Filter the registration form heading.
1493 *
1494 * @since 2.8.2
1495 *
1496 * @param string $str
1497 * @param string $tag Toggle new registration or profile update. new|edit.
1498 */
1499 $heading = ( isset( $heading ) && '' != $heading ) ? $heading : apply_filters( 'wpmem_register_heading', wpmem_get_text( 'register_heading' ), $tag );
1500 }
1501 $form = $args['heading_before'] . $heading . $args['heading_after'] . $args['n'] . $form;
1502
1503 // Apply fieldset wrapper.
1504 $form = $args['fieldset_before'] . $args['n'] . $form . $args['n'] . $args['fieldset_after'];
1505
1506 // Apply attribution if enabled.
1507 $form = $form . $this->attribution();
1508
1509 // Apply nonce. Nonce uses $tag value of the form processor, NOT the form builder.
1510 $nonce = ( $tag == 'edit' ) ? 'update' : 'register';
1511 $form = wp_nonce_field( 'wpmem_longform_nonce', '_wpmem_' . $nonce . '_nonce', true, false ) . $args['n'] . $form;
1512
1513 // Apply form wrapper.
1514 $novalidate = ( $args['novalidate'] ) ? 'novalidate' : '';
1515 $enctype = ( $enctype == 'multipart/form-data' ) ? ' enctype="multipart/form-data"' : '';
1516 $form = '<form name="form" method="post"' . $enctype . ' action="' . esc_attr( $args['post_to'] ) . '" id="' . wpmem_sanitize_class( $args['form_id'] ) . '" class="' . wpmem_sanitize_class( $args['form_class'] ) . '"' . $novalidate . '>' . $args['n'] . $form . $args['n'] . '</form>';
1517
1518 // Apply anchor.
1519 $form = '<a id="register"></a>' . $args['n'] . $form;
1520
1521 // Apply main div wrapper.
1522 $form = $args['main_div_before'] . $args['n'] . $form . $args['n'] . $args['main_div_after'] . $args['n'];
1523
1524 // Remove line breaks if enabled for easier filtering later.
1525 $form = ( $args['strip_breaks'] ) ? $this->strip_breaks( $form, $rows ) : $form; //str_replace( array( "\n", "\r", "\t" ), array( '','','' ), $form ) : $form;
1526
1527 // If there is an image input type, include the following script.
1528 $form = ( $form_has_file ) ? $form . '
1529 <script>
1530 var loadFile = function(event, clicked_id) {
1531 var reader = new FileReader();
1532 var the_id = clicked_id + "_img";
1533 reader.onload = function() {
1534 var output = document.getElementById(the_id);
1535 output.src = reader.result;
1536 };
1537 reader.readAsDataURL(event.target.files[0]);
1538 };
1539 </script>' : $form;
1540
1541 /**
1542 * Filter the generated HTML of the entire form.
1543 *
1544 * @since 2.7.4
1545 *
1546 * @param string $form The HTML of the final generated form.
1547 * @param string $tag Toggle new registration or profile update. new|edit.
1548 * @param array $rows {
1549 * An array containing the form rows.
1550 *
1551 * @type string order Field display order.
1552 * @type string meta Field meta tag (not used for display).
1553 * @type string type Input field type (not used for display).
1554 * @type string value Input field value (not used for display).
1555 * @type string values The possible values for the field (dropdown, multiple select/checkbox, radio group).
1556 * @type string label_text Raw text for the label (not used for display).
1557 * @type string row_before Opening wrapper tag around the row.
1558 * @type string label Label tag.
1559 * @type string field_before Opening wrapper tag before the input tag.
1560 * @type string field The field input tag.
1561 * @type string field_after Closing wrapper tag around the input tag.
1562 * @type string row_after Closing wrapper tag around the row.
1563 * }
1564 * @param string $hidden The HTML string of hidden fields
1565 */
1566 $form = apply_filters( 'wpmem_register_form', $form, $tag, $rows, $hidden );
1567
1568 /**
1569 * Filter before the form.
1570 *
1571 * This rarely used filter allows you to stick any string onto the front of
1572 * the generated form.
1573 *
1574 * @since 2.7.4
1575 *
1576 * @param string $str The HTML to add before the form. Default null.
1577 * @param string $tag Toggle new registration or profile update. new|edit.
1578 */
1579 $form = apply_filters( 'wpmem_register_form_before', '', $tag ) . $form;
1580
1581 $wpmem->forms->set_reg_form_showing( true );
1582
1583 // Return the generated form.
1584 return $form;
1585 } // End register_form().
1586
1587 /**
1588 * Strip line breaks from form.
1589 *
1590 * Function removes line breaks and tabs. Checks for textarea fields
1591 * before stripping line breaks.
1592 *
1593 * @since 3.1.8
1594 *
1595 * @param string $form
1596 * @param array $rows
1597 * @return string $form
1598 */
1599 private function strip_breaks( $form, $rows ) {
1600 foreach( $rows as $key => $row ) {
1601 if ( 'textarea' == $row['type'] ) {
1602 $textareas[ $key ] = $row['field'];
1603 }
1604 }
1605 $form = str_replace( array( "\n", "\r", "\t" ), array( '','','' ), $form );
1606 if ( ! empty ( $textareas ) ) {
1607 foreach ( $textareas as $textarea ) {
1608 $stripped = str_replace( array( "\n", "\r", "\t" ), array( '','','' ), $textarea );
1609 $form = str_replace( $stripped, $textarea, $form );
1610 }
1611 }
1612 return $form;
1613 }
1614
1615 /**
1616 * Appends WP-Members registration fields to wp-login.php registration form.
1617 *
1618 * @since 2.8.7
1619 * @since 3.1.1 Updated to support new (3.1.0) field types.
1620 * @since 3.1.6 Updated to support new fields array. Added WC classes.
1621 * @since 3.1.8 Added $process parameter.
1622 * @since 3.3.0 Ported from wpmem_do_wp_register_form() in wp-registration.php.
1623 *
1624 * @global stdClass $wpmem
1625 * @param string $process
1626 */
1627 function wp_register_form( $process = 'wp' ) {
1628
1629 global $wpmem;
1630 $wpmem_fields = wpmem_fields( $process );
1631
1632 // Check if this is WooCommerce account page.
1633 $is_woo = false;
1634 if ( 'woo' == $process ) {
1635 $is_woo = true;
1636 } else {
1637 if ( function_exists( 'is_account_page' ) ) {
1638 $is_woo = ( is_account_page() ) ? true : $is_woo;
1639 }
1640 }
1641
1642 if ( isset( $wpmem_fields ) && is_array( $wpmem_fields ) ) {
1643
1644 unset( $wpmem_fields['username'] );
1645
1646 if ( $is_woo ) {
1647 // Woo has its own setting for password fields.
1648 unset( $wpmem_fields['password'] );
1649 unset( $wpmem_fields['confirm_password'] );
1650 }
1651
1652 foreach ( $wpmem_fields as $meta_key => $field ) {
1653
1654 $req = ( $field['required'] ) ? ( ( $is_woo ) ? ' <span class="required">*</span>' : ' <span class="req">' . wpmem_get_text( 'wp_form_required' ) . '</span>' ) : '';
1655
1656 // File fields not yet supported for this form.
1657 if ( $field['register'] && $meta_key != 'user_email' && $field['type'] != 'file' && $field['type'] != 'image' ) {
1658
1659 if ( 'checkbox' == $field['type'] ) {
1660
1661 if ( 'tos' == $meta_key ) {
1662 $tos_link_text = $this->get_tos_link( $field, 'woo' );
1663 }
1664
1665 if ( isset( $field['label_href'] ) ) {
1666 $label = $wpmem->forms->apply_label_link( $meta_key, $field );
1667 } else {
1668 $label = ( 'tos' == $meta_key ) ? $tos_link_text : esc_html__( $field['label'], 'wp-members' );
1669 }
1670
1671 $val = esc_attr( wpmem_get( $meta_key, '' ) ); // ( isset( $_POST[ $meta_key ] ) ) ? esc_attr( $_POST[ $meta_key ] ) : '';
1672 $val = ( ! $_POST && $field['checked_default'] ) ? $field['checked_value'] : $val;
1673
1674 $row_before = '<p class="wpmem-checkbox">';
1675 $label = '<label for="' . $meta_key . '">' . $label . $req . '</label>';
1676 $input = wpmem_form_field( $meta_key, $field['type'], $field['checked_value'], $val );
1677 $row_after = '</p>';
1678
1679 } elseif ( 'hidden' == $field['type'] ) {
1680
1681 // Handle hidden fields
1682 $row_before = '';
1683 $label = '';
1684 $input = wpmem_form_field( array(
1685 'name' => $meta_key,
1686 'type' => $field['type'],
1687 'value' => $field['value'],
1688 'compare' => $valtochk,
1689 'required' => $field['required'],
1690 ) );
1691 $row_after = '';
1692
1693 } else {
1694
1695 $row_before = ( $is_woo ) ? '<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">' : '<p>';
1696 $label = '<label for="' . $meta_key . '">' . __( $field['label'], 'wp-members' ) . $req . '</label>';
1697 $label .= ( 'multicheckbox' == $field['type'] || 'radio' == $field['type'] ) ? '<br />' : '';
1698
1699 // determine the field type and generate accordingly...
1700
1701 switch ( $field['type'] ) {
1702
1703 case( 'textarea' ):
1704 $input = '<textarea name="' . $meta_key . '" id="' . $meta_key . '" class="textarea">';
1705 $input.= esc_textarea( wpmem_get( $meta_key, '' ) ); // ( isset( $_POST[ $meta_key ] ) ) ? esc_textarea( $_POST[ $meta_key ] ) : '';
1706 $input.= '</textarea>';
1707 break;
1708
1709 case( 'select' ):
1710 case( 'multiselect' ):
1711 case( 'multicheckbox' ):
1712 case( 'radio' ):
1713 case( 'membership' ):
1714 $row_before = ( $is_woo && ( 'select' == $field['type'] || 'multiselect' == $field['type'] || 'membership' == $field['type'] ) ) ? $row_before : '<p class="' . $field['type'] . '">';
1715 $valtochk = sanitize_text_field( wpmem_get( $meta_key, '' ) ); // ( isset( $_POST[ $meta_key ] ) ) ? sanitize_text_field( $_POST[ $meta_key ] ) : '';
1716 $formfield_args = array(
1717 'name' => $meta_key,
1718 'type' => $field['type'],
1719 'value' => $field['values'],
1720 'compare' => $valtochk,
1721 'required' => $field['required'],
1722 'class' => ( $is_woo && ( 'select' == $field['type'] || 'multiselect' == $field['type'] || 'membership' == $field['type'] ) ) ? 'woocommerce-Input woocommerce-Input--text input-text' : $field['type'],
1723 );
1724 if ( 'multicheckbox' == $field['type'] || 'multiselect' == $field['type'] ) {
1725 $formfield_args['delimiter'] = $field['delimiter'];
1726 }
1727 $input = wpmem_form_field( $formfield_args );
1728 break;
1729
1730 case( 'file' ):
1731 case( 'image' ):
1732 // Field type not supported for this yet.
1733 break;
1734
1735 default:
1736 $class = ( $is_woo ) ? 'woocommerce-Input woocommerce-Input--text input-text' : 'input';
1737 //$input = '<input type="' . $field['type'] . '" name="' . $meta_key . '" id="' . $meta_key . '" class="' . $class . '" value="';
1738 $formfield_args = array(
1739 'name' => $meta_key,
1740 'type' => $field['type'],
1741 'value' => wpmem_sanitize_field( wpmem_get( $meta_key, '' ), $field['type'] ),
1742 'compare' => ( isset( $field['compare'] ) ) ? $field['compare'] : '',
1743 'required' => $field['required'],
1744 'class' => $class,
1745 'placeholder' => ( isset( $field['placeholder'] ) ) ? $field['placeholder'] : '',
1746 'pattern' => ( isset( $field['pattern'] ) ) ? $field['pattern'] : false,
1747 'title' => ( isset( $field['title'] ) ) ? $field['title'] : false,
1748 'min' => ( isset( $field['min'] ) ) ? $field['min'] : false,
1749 'max' => ( isset( $field['max'] ) ) ? $field['max'] : false,
1750 'rows' => ( isset( $field['rows'] ) ) ? $field['rows'] : false,
1751 'cols' => ( isset( $field['cols'] ) ) ? $field['cols'] : false,
1752 );
1753
1754 // Add timestamp support.
1755 if ( 'timestamp' == $field['type'] ) {
1756 $formfield_args['timestamp_display'] = $field['timestamp_display'];
1757 }
1758
1759 $input = wpmem_form_field( $formfield_args );
1760 //$input.= ( isset( $_POST[ $meta_key ] ) ) ? esc_attr( $_POST[ $meta_key ] ) : '';
1761 //$input.= '" size="25" />';
1762 break;
1763 }
1764
1765 $row_after = '</p>';
1766
1767 }
1768
1769 // if the row is set to display, add the row to the form array
1770 $rows[ $meta_key ] = array(
1771 'type' => $field['type'],
1772 'row_before' => $row_before,
1773 'label' => $label,
1774 'field' => $input,
1775 'row_after' => $row_after,
1776 );
1777 }
1778 }
1779
1780 // Do recaptcha if enabled.
1781 if ( ! $is_woo && isset( $wpmem->captcha ) && $wpmem->captcha != 0 ) {
1782
1783 $row_before = '<p>';
1784 $row_after = '</p>';
1785 $label = '';
1786 $captcha = '';
1787
1788 if ( in_array( $wpmem->captcha, array( 1, 3, 4 ) ) ) {
1789 $captcha = WP_Members_Captcha::recaptcha();
1790 } elseif ( 5 == $wpmem->captcha ) {
1791 $captcha = WP_Members_Captcha::hcaptcha();
1792 } elseif ( 2 == $wpmem->captcha ) {
1793 $row = WP_Members_Captcha::rs_captcha( 'array' );
1794 $label = $row['label']; //$row['label_text'];
1795 $captcha = $row['img'] . $row['hidden'] . $row['field'];
1796 }
1797 if ( 4 == $wpmem->captcha ) {
1798 $row_before = '';
1799 $row_after = '';
1800 }
1801
1802 $rows['captcha'] = array(
1803 'type' => '',
1804 'row_before' => $row_before,
1805 'row_after' => $row_after,
1806 'label' => $label,
1807 'field' => $captcha,
1808 );
1809 }
1810
1811 if ( isset( $rows ) && is_array( $rows ) ) {
1812
1813 /**
1814 * Filter the native registration form rows.
1815 *
1816 * @since 2.9.3.
1817 *
1818 * @param array $rows The custom rows added to the form.
1819 */
1820 $rows = apply_filters( 'wpmem_native_form_rows', $rows );
1821
1822 foreach ( $rows as $row_item ) {
1823 if ( $row_item['type'] == 'checkbox' ) {
1824 echo $row_item['row_before'] . $row_item['field'] . $row_item['label'] . $row_item['row_after'];
1825 } else {
1826 echo $row_item['row_before'] . $row_item['label'] . $row_item['field'] . $row_item['row_after'];
1827 }
1828 }
1829 }
1830 }
1831 }
1832
1833
1834 /**
1835 * Appends WP-Members registration fields to Users > Add New User screen.
1836 *
1837 * @since 2.9.0
1838 * @since 3.1.1 Updated to support new (3.1.0) field types and user activation.
1839 * @since 3.1.6 Updated to support new fields array.
1840 * @since 3.3.0 Ported from wpmem_do_wp_newuser_form() in wp-registration.php.
1841 *
1842 * @global stdClass $wpmem
1843 */
1844 function wp_newuser_form() {
1845
1846 global $wpmem;
1847 echo '<table class="form-table"><tbody>';
1848
1849 $wpmem_fields = wpmem_fields(); // @todo For now in 3.5+, load all fields. Perhaps at some point we go to wpmem_fields( 'add_new' );
1850 $exclude = wpmem_get_excluded_meta( 'wp-register' );
1851
1852 foreach ( $wpmem_fields as $meta_key => $field ) {
1853
1854 if ( ! $field['native'] && ! in_array( $meta_key, $exclude ) ) {
1855
1856 $label = wpmem_get_field_label( $meta_key );
1857
1858 $req = ( $field['required'] ) ? ' <span class="description">' . wpmem_get_text( 'wp_form_required' ) . '</span>' : '';
1859
1860 $class = ( 'radio' == $field['type']
1861 || 'checkbox' == $field['type']
1862 || 'date' == $field['type'] ) ? '' : ' class="form-field" ';
1863 echo '<tr' . $class . '>
1864 <th scope="row">
1865 <label for="' . esc_attr( $meta_key ) . '">' . $label . $req . '</label>
1866 </th>
1867 <td>';
1868
1869 // determine the field type and generate accordingly.
1870
1871 // All fields use the following:
1872 $args['name'] = $meta_key;
1873 $args['type'] = $field['type'];
1874 $args['required'] = $field['required'];
1875
1876 $args['placeholder'] = ( isset( $field['placeholder'] ) ) ? $field['placeholder'] : '';
1877 $args['pattern'] = ( isset( $field['pattern'] ) ) ? $field['pattern'] : '';
1878 $args['title'] = ( isset( $field['title'] ) ) ? $field['title'] : '';
1879
1880 $posted_meta = wpmem_get( $meta_key, '' );
1881
1882 switch ( $field['type'] ) {
1883
1884 case( 'select' ):
1885 $val = sanitize_text_field( $posted_meta ); // ( isset( $_POST[ $meta_key ] ) ) ? sanitize_text_field( $_POST[ $meta_key ] ) : '';
1886 $args['value'] = $field['values'];
1887 $args['compare'] = $val;
1888 echo wpmem_form_field( $args );
1889 break;
1890
1891 case( 'textarea' ):
1892 $args['value'] = esc_textarea( $posted_meta ); // ( isset( $_POST[ $meta_key ] ) ) ? esc_textarea( $_POST[ $meta_key ] ) : '';
1893 echo wpmem_form_field( $args );
1894 break;
1895
1896 case( 'checkbox' ):
1897 $val = sanitize_text_field( $posted_meta ); // ( isset( $_POST[ $meta_key ] ) ) ? sanitize_text_field( $_POST[ $meta_key ] ) : '';
1898 $val = ( ! $_POST && $field['checked_default'] ) ? $field['checked_value'] : $val;
1899 $args['value'] = $field['checked_value'];
1900 $args['compare'] = $val;
1901 echo wpmem_form_field( $args );
1902 break;
1903
1904 case( 'multiselect' ):
1905 case( 'multicheckbox' ):
1906 case( 'radio' ):
1907 case( 'membership' );
1908 $args['value'] = $field['values'];
1909 $args['compare'] = sanitize_text_field( $posted_meta ); // ( isset( $_POST[ $meta_key ] ) ) ? sanitize_text_field( $_POST[ $meta_key ] ) : '';
1910 if ( 'multicheckbox' == $field['type'] || 'multiselect' == $field['type'] ) {
1911 $args['delimiter'] = $field['delimiter'];
1912 }
1913 echo wpmem_form_field( $args );
1914 break;
1915
1916 case( 'file' ):
1917 case( 'image' ):
1918 echo 'Not currently supported for this form';
1919 break;
1920
1921 default:
1922 $args['value'] = esc_attr( $posted_meta ); // ( isset( $_POST[ $meta_key ] ) ) ? esc_attr( $_POST[ $meta_key ] ) : '';
1923 echo wpmem_form_field( $args );
1924 break;
1925 }
1926
1927 echo '</td>
1928 </tr>';
1929
1930 }
1931 }
1932
1933 // If moderated registration is enabled, add checkbox to set user as active.
1934 if ( 1 == $wpmem->mod_reg ) {
1935 echo '<tr>
1936 <th scope="row">
1937 <label for="activate_user">' . wpmem_get_text( 'wp_form_activate' ) . '</label>
1938 </th>
1939 <td>' . wpmem_form_field( array( 'name' => 'activate_user', 'type' => 'checkbox', 'value' => 1, 'compare' => '' ) ) . '</td>
1940 </tr>';
1941 }
1942
1943 echo '</tbody></table>';
1944
1945 }
1946
1947 /**
1948 * Create an attribution link in the form.
1949 *
1950 * @since 2.6.0
1951 * @since 3.1.1 Updated to use new object setting.
1952 * @since 3.3.0 Ported from wpmem_inc_attribution() in forms.php.
1953 *
1954 * @global object $wpmem
1955 * @return string $str
1956 */
1957 function attribution() {
1958
1959 global $wpmem;
1960 $str = '
1961 <div align="center">
1962 <small>Powered by <a href="https://rocketgeek.com" target="_blank">WP-Members</a></small>
1963 </div>';
1964
1965 return ( 1 == $wpmem->attrib ) ? $str : '';
1966 }
1967
1968 /**
1969 * Settings for building Short Form (login).
1970 *
1971 * Replaces individual legacy functions and filters for
1972 * the short forms, combined into a single method.
1973 *
1974 * @since 3.3.0
1975 * @since 3.4.0 Change inputs.
1976 *
1977 * @global stdClass $post
1978 * @global stdClass $wpmem
1979 *
1980 * @param string $form login|changepassword|resetpassword|forgotusername
1981 * @param array $args
1982 * @return string $form
1983 */
1984 function do_shortform( $form, $args = array() ) {
1985
1986 $input_arrays = array(
1987 'login' => array(
1988 array(
1989 'name' => wpmem_get_text( 'login_username' ),
1990 'type' => 'text',
1991 'tag' => 'log',
1992 'class' => 'username',
1993 'div' => 'div_text',
1994 ),
1995 array(
1996 'name' => wpmem_get_text( 'login_password' ),
1997 'type' => 'password',
1998 'tag' => 'pwd',
1999 'class' => 'password',
2000 'div' => 'div_text',
2001 ),
2002 ),
2003 'changepassword' => array(
2004 array(
2005 'name' => wpmem_get_text( 'pwdchg_password1' ),
2006 'type' => 'password',
2007 'tag' => 'pass1',
2008 'class' => 'password',
2009 'div' => 'div_text',
2010 ),
2011 array(
2012 'name' => wpmem_get_text( 'pwdchg_password2' ),
2013 'type' => 'password',
2014 'tag' => 'pass2',
2015 'class' => 'password',
2016 'div' => 'div_text',
2017 ),
2018 ),
2019 'resetpassword' => array(
2020 array(
2021 'name' => wpmem_get_text( 'login_username' ),
2022 'type' => 'text',
2023 'tag' => 'user',
2024 'class' => 'username',
2025 'div' => 'div_text',
2026 ),
2027 ),
2028 'forgotusername' => array(
2029 array(
2030 'name' => wpmem_get_text( 'username_email' ),
2031 'type' => 'text',
2032 'tag' => 'user_email',
2033 'class' => 'username',
2034 'div' => 'div_text',
2035 ),
2036 ),
2037 'reconfirm' => array(
2038 array(
2039 'name' => wpmem_get_text( 'login_username' ),
2040 'type' => 'text',
2041 'tag' => 'user',
2042 'class' => 'username',
2043 'div' => 'div_text',
2044 ),
2045 )
2046 );
2047
2048 /**
2049 * Filter the array of change password form fields.
2050 *
2051 * @since 2.9.0
2052 * @deprecated 3.3.0 Use wpmem_{$form}_form_defaults instead.
2053 *
2054 * @param array $default_inputs An array matching the elements used by default.
2055 */
2056 $default_inputs = apply_filters_deprecated( 'wpmem_inc_' . $form . '_inputs', array( $input_arrays[ $form ] ), '3.3.0', 'wpmem_' . $form . '_form_defaults' );
2057
2058 $form_arrays = array(
2059 'login' => array(
2060 'heading' => wpmem_get_text( 'login_heading' ),
2061 'action' => 'login',
2062 'button_text' => wpmem_get_text( 'login_button' ),
2063 'inputs' => $default_inputs,
2064 'redirect_to' => ( isset( $args['redirect_to'] ) ) ? $args['redirect_to'] : get_permalink(),
2065 ),
2066 'changepassword' => array(
2067 'heading' => wpmem_get_text( 'pwdchg_heading' ),
2068 'action' => 'pwdchange',
2069 'button_text' => wpmem_get_text( 'pwdchg_button' ),
2070 'inputs' => $default_inputs,
2071 ),
2072 'resetpassword' => array(
2073 'heading' => wpmem_get_text( 'pwdreset_heading' ),
2074 'action' => 'pwdreset',
2075 'button_text' => wpmem_get_text( 'pwdreset_button' ),
2076 'inputs' => $default_inputs,
2077 ),
2078 'forgotusername' => array(
2079 'heading' => wpmem_get_text( 'username_heading' ),
2080 'action' => 'getusername',
2081 'button_text' => wpmem_get_text( 'username_button' ),
2082 'inputs' => $default_inputs,
2083 ),
2084 'reconfirm' => array(
2085 'heading' => wpmem_get_text( 'reconfirm_heading' ),
2086 'action' => 'reconfirm',
2087 'button_text' => wpmem_get_text( 'reconfirm_button' ),
2088 'inputs' => $default_inputs,
2089 ),
2090 );
2091
2092 /**
2093 * Filter the arguments to override form defaults.
2094 *
2095 * @since 2.9.0
2096 * @deprecated 3.3.0 Use wpmem_{$form}_form_defaults instead.
2097 *
2098 * @param array $args An array of arguments to use. Default null. (login|changepassword|resetpassword|forgotusername)
2099 */
2100 $args = apply_filters_deprecated( 'wpmem_inc_' . $form . '_args', array(''), '3.3.0', 'wpmem_' . $form . '_form_defaults' );
2101 $arr = wp_parse_args( $args, $form_arrays[ $form ] );
2102
2103 /**
2104 * Filter the arguments to override change password form defaults.
2105 *
2106 * @since 3.3.0
2107 * @since 3.4.6 Added $form of the filter being used.
2108 *
2109 * @param array $args An array of arguments to use.
2110 * @param string $form Tag of the form being used (login|changepassword|resetpassword|forgotusername)
2111 */
2112 $arr = apply_filters( 'wpmem_' . $form . '_form_defaults', $arr, $form );
2113
2114 return $this->login_form( '', $arr );
2115 }
2116
2117 /**
2118 * Applies the post restricted message above the short form.
2119 *
2120 * @since 3.3.0
2121 *
2122 * @global stdClass $wpmem
2123 *
2124 * @return string $str The generated message.
2125 */
2126 public function add_restricted_msg() {
2127
2128 $str = '';
2129
2130 if ( "success" != wpmem_get_form_state() ) {
2131
2132 $dialogs = get_option( 'wpmembers_dialogs' );
2133
2134 // The message shown above blocked content.
2135 $msg = wpmem_get_text( 'restricted_msg' );
2136 /**
2137 * Filter the message args.
2138 *
2139 * @since 3.5.0
2140 *
2141 * @todo Eliminate <p> tag from before/after. Use CSS to adjust the div size instead.
2142 * @todo Rework localization of custom strings into dialogs class.
2143 *
2144 * @param array $args {
2145 * The various parts of the restricted dialog.
2146 *
2147 * @type string $msg The actual message.
2148 * @type string $before The opening HTML tags.
2149 * @type string $after The closing HTML tags (no need to change this if you're not changing the opening tag type).
2150 * }
2151 */
2152 $args = apply_filters( 'wpmem_restricted_msg_args', array(
2153 'msg' => ( $dialogs['restricted_msg'] == $msg ) ? $msg : __( stripslashes( $dialogs['restricted_msg'] ), 'wp-members' ),
2154 'before' => '<div id="wpmem_restricted_msg"><p>',
2155 'after' => '</p></div>',
2156 ));
2157 $full_html = $args['before'] . $args['msg'] . $args['after'];
2158
2159 /**
2160 * Filter the post restricted message.
2161 *
2162 * @since 2.7.3
2163 * @since 3.2.0 Added raw message string and HTML as separate params.
2164 *
2165 * @param string $full_html The post restricted message with HTML.
2166 * @param string $message The raw message string.
2167 * @param string $before The 'before' HTML wrapper.
2168 * @param string $after The 'after' HTML wrapper.
2169 */
2170 $str = apply_filters( 'wpmem_restricted_msg', $full_html, $args['msg'], $args['before'], $args['after'] );
2171 }
2172
2173 return $str;
2174 }
2175
2176 /**
2177 * Alias for handing the default WP login form.
2178 *
2179 * @since 3.3.2
2180 */
2181 function wp_login_form( $args ) {
2182 return wp_login_form( $args );
2183 }
2184
2185 /**
2186 * Generate TOS field with link.
2187 *
2188 * @since 3.3.5
2189 *
2190 * @param array $field
2191 * @param string $tag
2192 * @return string
2193 */
2194 function get_tos_link( $field, $tag = 'new' ) {
2195 $tos_content = stripslashes( get_option( 'wpmembers_tos' ) );
2196 if ( has_shortcode( $tos_content, 'wpmem_tos' ) || has_shortcode( $tos_content, 'wp-members' ) ) {
2197 $tos_link_url = do_shortcode( $tos_content );
2198 } else {
2199 $tos_link_url = add_query_arg( 'tos', 'display', wpmem_current_url( true, false ) );
2200 }
2201 $tos_link_tag = '<a href="' . esc_url( $tos_link_url ) . '" target="_blank">';
2202
2203 /**
2204 * Filter the TOS link.
2205 *
2206 * @since 3.2.6
2207 *
2208 * @param string $tos_link_tag
2209 * @param string $tos_link_url
2210 */
2211 $tos_link_tag = apply_filters( 'wpmem_tos_link_tag', $tos_link_tag, $tos_link_url );
2212
2213 /**
2214 * Filter the TOS link text.
2215 *
2216 * @since 2.7.5
2217 *
2218 * @param string The link text.
2219 * @param string $tag Toggle new registration or profile update. new|edit.
2220 */
2221 $tos_link_text = apply_filters( 'wpmem_tos_link_txt', wpmem_get_text( 'register_tos' ), $tag );
2222
2223 // If filtered value is not the default label, use that, otherwise use label.
2224 // @note: if default changes, this check must change.
2225 if ( __( 'Please indicate that you agree to the %s Terms of Service %s', 'wp-members' ) == $tos_link_text ) {
2226 if ( __( 'TOS', 'wp-members' ) != $field['label'] && __( 'Terms of Service', 'wp-members' ) != $field['label'] ) {
2227 $tos_link_text = $field['label'];
2228 }
2229 }
2230
2231 // If tos string does not contain link identifiers (%s), wrap the whole string.
2232 if ( ! strpos( $tos_link_text, '%s' ) ) {
2233 $tos_link_text = '%s' . $tos_link_text . '%s';
2234 }
2235
2236 return sprintf( $tos_link_text, $tos_link_tag, '</a>' );
2237 }
2238
2239 function get_reg_row_keys() {
2240 return array( 'meta', 'type', 'value', 'values', 'label_text', 'row_before', 'label', 'field_before', 'field', 'field_after', 'row_after' );
2241 }
2242
2243 function is_reg_form_showing() {
2244 return $this->reg_form_showing;
2245 }
2246
2247 function set_reg_form_showing( $value ) {
2248 $this->reg_form_showing = $value;
2249 }
2250
2251 /**
2252 * Applies the label link if there is a label_href val in the args.
2253 * @since 3.5.4
2254 */
2255 function apply_label_link( $meta_key, $args ) {
2256 // Adjust placeholders.
2257 $label_text = str_replace( '%', '%s', esc_html( __( $args['label'], 'wp-members' ) ) );
2258
2259 /**
2260 * Filters the anchor tag.
2261 *
2262 * @since 3.5.3
2263 *
2264 * @param array $atts An array of attributes for the <a> tag.
2265 * @param string $meta_key Meta key of the field.
2266 */
2267 $tag_atts = apply_filters( 'wpmem_form_label_link', array (
2268 'href' => $args['label_href'],
2269 'target' => '_blank',
2270 ), $meta_key );
2271
2272 $anchor_tag = "<a ";
2273 foreach ( $tag_atts as $attribute => $value ) {
2274 $anchor_tag .= ( '' != $value ) ? esc_attr( $attribute ) . '="' . esc_attr( $value ) . '" ' : esc_attr( $attribute ) . ' ';
2275 }
2276 $anchor_tag .= ">";
2277
2278 return sprintf( $label_text, $anchor_tag, '</a>' );
2279 }
2280
2281 } // End of WP_Members_Forms class.