| @@ -14,9 +14,9 @@ | ||
| 14 | 14 | $errors = new \WP_Error(); |
| 15 | 15 | |
| 16 | 16 | $sanitized_user_login = sanitize_user($user_login); |
| 17 | 17 | |
| 18 | - $user_email = apply_filters('user_registration_email', $user_email); | |
| 18 | + $user_email = apply_filters('user_registration_email', $user_email); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 19 | 19 | |
| 20 | 20 | // Check the username. |
| 21 | 21 | if ('' === $sanitized_user_login) { |
| 22 | 22 | $errors->add('empty_username', __('<strong>Error</strong>: Please enter a username.', 'fluent-community')); |
| @@ -26,9 +26,9 @@ | ||
| 26 | 26 | } elseif (username_exists($sanitized_user_login)) { |
| 27 | 27 | $errors->add('username_exists', __('<strong>Error</strong>: This username is already registered. Please choose another one.', 'fluent-community')); |
| 28 | 28 | } else { |
| 29 | 29 | /** This filter is documented in wp-includes/user.php */ |
| 30 | - $illegal_user_logins = (array)apply_filters('illegal_user_logins', array()); | |
| 30 | + $illegal_user_logins = (array)apply_filters('illegal_user_logins', array()); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 31 | 31 | if (in_array(strtolower($sanitized_user_login), array_map('strtolower', $illegal_user_logins), true)) { |
| 32 | 32 | $errors->add('invalid_username', __('<strong>Error</strong>: Sorry, that username is not allowed.', 'fluent-community')); |
| 33 | 33 | } |
| 34 | 34 | } |
| @@ -45,12 +45,20 @@ | ||
| 45 | 45 | __('<strong>Error:</strong> This email address is already registered. Please login or try resetting your password.', 'fluent-community') |
| 46 | 46 | ); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | - do_action('register_post', $sanitized_user_login, $user_email, $errors); | |
| 49 | + /** | |
| 50 | + * MemberPress rejects every `register_post` while its "Disable WordPress registration form" | |
| 51 | + * option is on (default on). That option targets wp-login.php, not the community portal, which has its own registration gate. | |
| 52 | + */ | |
| 53 | + $hadMeprBlocker = remove_action('register_post', 'MeprUsersCtrl::maybe_disable_wp_registration_form', 10); | |
| 50 | 54 | |
| 51 | - $errors = apply_filters('registration_errors', $errors, $sanitized_user_login, $user_email); | |
| 55 | + do_action('register_post', $sanitized_user_login, $user_email, $errors); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 52 | 56 | |
| 57 | + if ($hadMeprBlocker) { | |
| 58 | + add_action('register_post', 'MeprUsersCtrl::maybe_disable_wp_registration_form', 10, 3); | |
| 59 | + } | |
| 60 | + | |
| 53 | 61 | if ($errors->has_errors()) { |
| 54 | 62 | return $errors; |
| 55 | 63 | } |
| 56 | 64 | |
| @@ -104,15 +112,15 @@ | ||
| 104 | 112 | return $errors; |
| 105 | 113 | } |
| 106 | 114 | |
| 107 | 115 | if (!empty($_COOKIE['wp_lang'])) { |
| 108 | - $wp_lang = sanitize_text_field($_COOKIE['wp_lang']); | |
| 116 | + $wp_lang = sanitize_text_field(wp_unslash($_COOKIE['wp_lang'])); | |
| 109 | 117 | if (in_array($wp_lang, get_available_languages(), true)) { |
| 110 | 118 | update_user_meta($user_id, 'locale', $wp_lang); // Set user locale if defined on registration. |
| 111 | 119 | } |
| 112 | 120 | } |
| 113 | 121 | |
| 114 | - do_action('register_new_user', $user_id); | |
| 122 | + do_action('register_new_user', $user_id); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 115 | 123 | |
| 116 | 124 | return $user_id; |
| 117 | 125 | } |
| 118 | 126 | |
| @@ -124,9 +132,9 @@ | ||
| 124 | 132 | |
| 125 | 133 | $user = get_user_by('ID', $user->ID); |
| 126 | 134 | |
| 127 | 135 | if ($user) { |
| 128 | - do_action('wp_login', $user->user_login, $user); | |
| 136 | + do_action('wp_login', $user->user_login, $user); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 129 | 137 | } |
| 130 | 138 | |
| 131 | 139 | return $user; |
| 132 | 140 | } |
| @@ -139,11 +147,24 @@ | ||
| 139 | 147 | |
| 140 | 148 | return false; |
| 141 | 149 | } |
| 142 | 150 | |
| 151 | + public static function getTermsText() | |
| 152 | + { | |
| 153 | + $policyUrl = apply_filters('fluent_community/terms_policy_url', get_privacy_policy_url()); | |
| 154 | + | |
| 155 | + $termsText = __('I agree to the terms and conditions', 'fluent-community'); | |
| 156 | + if ($policyUrl) { | |
| 157 | + /* translators: %1$s is replaced by the text "terms and conditions", %2$s is replaced by the text "to the terms and conditions" */ | |
| 158 | + $termsText = sprintf(__('I agree to the %1$s terms and conditions %2$s', 'fluent-community'), '<a rel="noopener" href="' . esc_url($policyUrl) . '" target="_blank">', '</a>'); | |
| 159 | + } | |
| 160 | + | |
| 161 | + return $termsText; | |
| 162 | + } | |
| 163 | + | |
| 143 | 164 | public static function getFormFields($invitation = null) |
| 144 | 165 | { |
| 145 | - $fields = apply_filters('fluent_communuty/auth/signup_fields', [ | |
| 166 | + $fields = apply_filters('fluent_community/auth/signup_fields', [ | |
| 146 | 167 | 'full_name' => [ |
| 147 | 168 | 'label' => __('Full name', 'fluent-community'), |
| 148 | 169 | 'placeholder' => __('Your first & last name', 'fluent-community'), |
| 149 | 170 | 'type' => 'text', |
| @@ -156,15 +177,15 @@ | ||
| 156 | 177 | 'placeholder' => __('Your email address', 'fluent-community'), |
| 157 | 178 | 'label' => __('Email Address', 'fluent-community'), |
| 158 | 179 | 'required' => true, |
| 159 | 180 | 'value' => $invitation ? $invitation->message : '', |
| 160 | - 'readonly' => !!$invitation, | |
| 181 | + 'readonly' => $invitation && $invitation->message, | |
| 161 | 182 | 'sanitize_callback' => 'sanitize_email' |
| 162 | 183 | ], |
| 163 | 184 | 'username' => [ |
| 164 | 185 | 'type' => 'text', |
| 165 | 186 | 'placeholder' => __('No space or special characters', 'fluent-community'), |
| 166 | - 'label' => __('Space username', 'fluent-community'), | |
| 187 | + 'label' => __('Username', 'fluent-community'), | |
| 167 | 188 | 'required' => true, |
| 168 | 189 | 'sanitize_callback' => 'sanitize_user' |
| 169 | 190 | ], |
| 170 | 191 | 'password' => [ |
| @@ -182,9 +203,9 @@ | ||
| 182 | 203 | 'sanitize_callback' => 'sanitize_text_field' |
| 183 | 204 | ], |
| 184 | 205 | 'terms' => [ |
| 185 | 206 | 'type' => 'inline_checkbox', |
| 186 | - 'inline_label' => __('I agree to the terms and conditions', 'fluent-community'), | |
| 207 | + 'inline_label' => self::getTermsText(), | |
| 187 | 208 | 'required' => true |
| 188 | 209 | ] |
| 189 | 210 | ], $invitation); |
| 190 | 211 | |
| @@ -194,21 +215,67 @@ | ||
| 194 | 215 | |
| 195 | 216 | return $fields; |
| 196 | 217 | } |
| 197 | 218 | |
| 219 | + public static function getLostPasswordUrl($redirectUrl = '') | |
| 220 | + { | |
| 221 | + if (self::isFluentAuthAvailable()) { | |
| 222 | + $url = add_query_arg([ | |
| 223 | + 'form' => 'reset_password' | |
| 224 | + ], Helper::getAuthUrl()); | |
| 225 | + } else { | |
| 226 | + $url = wp_lostpassword_url($redirectUrl);; | |
| 227 | + } | |
| 228 | + | |
| 229 | + return apply_filters('fluent_community/auth/lost_password_url', $url); | |
| 230 | + } | |
| 231 | + | |
| 232 | + public static function getLoginFormFields() | |
| 233 | + { | |
| 234 | + return apply_filters('fluent_community/auth/login_fields', [ | |
| 235 | + 'username' => [ | |
| 236 | + 'type' => 'text', | |
| 237 | + 'placeholder' => __('Your account email address', 'fluent-community'), | |
| 238 | + 'label' => __('Email Address', 'fluent-community'), | |
| 239 | + 'required' => true, | |
| 240 | + 'sanitize_callback' => 'sanitize_user' | |
| 241 | + ], | |
| 242 | + 'password' => [ | |
| 243 | + 'type' => 'password', | |
| 244 | + 'placeholder' => __('Your account password', 'fluent-community'), | |
| 245 | + 'label' => __('Password', 'fluent-community'), | |
| 246 | + 'required' => true, | |
| 247 | + 'sanitize_callback' => 'sanitize_text_field' | |
| 248 | + ] | |
| 249 | + ]); | |
| 250 | + } | |
| 251 | + | |
| 198 | 252 | public static function isPasswordConfRequired() |
| 199 | 253 | { |
| 200 | - return apply_filters('fluent_community/autg/password_confirmation', true); | |
| 254 | + $isRequired = apply_filters_deprecated('fluent_community/autg/password_confirmation', [true], '2.7.8', 'fluent_community/auth/password_confirmation'); | |
| 255 | + | |
| 256 | + return apply_filters('fluent_community/auth/password_confirmation', $isRequired); | |
| 201 | 257 | } |
| 202 | 258 | |
| 203 | 259 | public static function isRegistrationEnabled() |
| 204 | 260 | { |
| 205 | - return apply_filters('fluent_community/auth/registration_enabled', !!get_option('users_can_register')); | |
| 261 | + | |
| 262 | + $enabled = !!get_option('users_can_register'); | |
| 263 | + | |
| 264 | + if (!$enabled) { | |
| 265 | + $generalSettinsg = Helper::generalSettings(); | |
| 266 | + $enabled = $generalSettinsg['explicit_registration'] !== 'no'; | |
| 267 | + } | |
| 268 | + | |
| 269 | + return apply_filters('fluent_community/auth/registration_enabled', $enabled); | |
| 206 | 270 | } |
| 207 | 271 | |
| 208 | 272 | public static function isTwoFactorEnabled() |
| 209 | 273 | { |
| 210 | - return apply_filters('fluent_community/auth/two_factor_enabled', true); | |
| 274 | + // fluent_auth/verify_signup_email is kept for backward compatibility with FluentAuth-targeted snippets | |
| 275 | + $enabled = apply_filters('fluent_auth/verify_signup_email', true); | |
| 276 | + | |
| 277 | + return apply_filters('fluent_community/auth/two_factor_enabled', $enabled); | |
| 211 | 278 | } |
| 212 | 279 | |
| 213 | 280 | public static function get2FaRegistrationCodeForm($formData) |
| 214 | 281 | { |
| @@ -213,34 +280,33 @@ | ||
| 213 | 280 | public static function get2FaRegistrationCodeForm($formData) |
| 214 | 281 | { |
| 215 | 282 | $generalSettings = Helper::generalSettings(); |
| 216 | 283 | try { |
| 217 | - $verifcationCode = str_pad(random_int(100123, 900987), 6, 0, STR_PAD_LEFT); | |
| 284 | + $verifcationCode = str_pad((string) random_int(100123, 900987), 6, '0', STR_PAD_LEFT); | |
| 218 | 285 | } catch (\Exception $e) { |
| 219 | - $verifcationCode = str_pad(mt_rand(100123, 900987), 6, 0, STR_PAD_LEFT); | |
| 286 | + $verifcationCode = str_pad((string) wp_rand(100123, 900987), 6, '0', STR_PAD_LEFT); | |
| 220 | 287 | } |
| 221 | 288 | |
| 222 | - // Hash the code | |
| 289 | + // Keep the code hash server-side, keyed by an opaque challenge id. The client only ever | |
| 290 | + // receives the id, never the password verifier, so the code cannot be recovered offline. | |
| 223 | 291 | $codeHash = wp_hash_password($verifcationCode); |
| 224 | - | |
| 225 | - // Create a token with the email and code hash | |
| 226 | - $data = [ | |
| 292 | + $signedToken = 'fcs_' . wp_generate_password(40, false); | |
| 293 | + set_transient('fcom_signup_2fa_' . $signedToken, [ | |
| 227 | 294 | 'email' => $formData['email'], |
| 228 | 295 | 'code_hash' => $codeHash, |
| 229 | - 'expires' => time() + 600 // 10 minutes expiry | |
| 230 | - ]; | |
| 231 | - $token = base64_encode(json_encode($data)); | |
| 296 | + 'expires' => time() + 600, // 10 minutes expiry | |
| 297 | + 'attempts' => 0, | |
| 298 | + ], 600); | |
| 232 | 299 | |
| 233 | - // Sign the token | |
| 234 | - $signature = hash_hmac('sha256', $token, SECURE_AUTH_KEY); | |
| 235 | - $signedToken = $token . '.' . $signature; | |
| 236 | - | |
| 300 | + /* translators: %s is replaced by the title of the site */ | |
| 237 | 301 | $mailSubject = apply_filters("fluent_community/auth/signup_verification_mail_subject", sprintf(__('Your registration verification code for %s', 'fluent-community'), Arr::get($generalSettings, 'site_title'))); |
| 238 | 302 | |
| 239 | 303 | $pStart = '<p style="font-family: Arial, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">'; |
| 240 | 304 | |
| 305 | + /* translators: %s is replaced by the name of the user */ | |
| 241 | 306 | $message = $pStart . sprintf(__('Hello %s,', 'fluent-community'), Arr::get($formData, 'first_name')) . '</p>' . |
| 242 | 307 | $pStart . __('Thank you for registering with us! To complete the setup of your account, please enter the verification code below on the registration page.', 'fluent-community') . '</p>' . |
| 308 | + /* translators: %s is replaced by the verification code */ | |
| 243 | 309 | $pStart . '<b>' . sprintf(__('Verification Code: %s', 'fluent-community'), $verifcationCode) . '</b></p>' . |
| 244 | 310 | '<br />' . |
| 245 | 311 | $pStart . __('This code is valid for 10 minutes and is meant to ensure the security of your account. If you did not initiate this request, please ignore this email.', 'fluent-community') . '</p>'; |
| 246 | 312 | |
| @@ -255,9 +321,10 @@ | ||
| 255 | 321 | 'bodyContent' => $message, |
| 256 | 322 | 'pre_header' => __('Activate your account', 'fluent-community'), |
| 257 | 323 | 'footerLines' => [ |
| 258 | 324 | __('If you did not initiate this request, please ignore this email.', 'fluent-community'), |
| 259 | - sprintf(__('This email has been sent from %1$s. Site: %2$s', 'fluent-community'), Arr::get($generalSettings, 'site_title'), site_url()) | |
| 325 | + /* translators: %1$s is replaced by the title of the site, %2$s is replaced by the home URL */ | |
| 326 | + sprintf(__('This email has been sent from %1$s. Site: %2$s', 'fluent-community'), Arr::get($generalSettings, 'site_title'), home_url()) | |
| 260 | 327 | ] |
| 261 | 328 | ]); |
| 262 | 329 | |
| 263 | 330 | $mailer = new Mailer($formData['email'], $mailSubject, $message); |
| @@ -272,23 +339,35 @@ | ||
| 272 | 339 | ob_start(); |
| 273 | 340 | ?> |
| 274 | 341 | <div class="fls_signup_verification"> |
| 275 | 342 | <input type="hidden" name="__two_fa_signed_token" value="<?php echo esc_attr($signedToken); ?>"/> |
| 276 | - <p><?php echo esc_html(sprintf(__('A verification code has been sent to %s. Please provide the code below: ', 'fluent-community'), $formData['email'])) ?></p> | |
| 277 | - <div class="fcom_form-group fcom_field_vefication"> | |
| 343 | + <?php /* translators: %s is replaced by the email address */ ?> | |
| 344 | + <p><?php echo esc_html(\sprintf(__('A verification code has been sent to %s. Please provide the code below: ', 'fluent-community'), $formData['email'])) ?></p> | |
| 345 | + <div class="fcom_form-group fcom_field_verification"> | |
| 278 | 346 | <div class="fcom_form_label"> |
| 279 | - <label for="fcom_field_vefication"><?php _e('Verification Code', 'fluent-community'); ?></label> | |
| 347 | + <label for="fcom_field_verification"><?php esc_html_e('Verification Code', 'fluent-community'); ?></label> | |
| 280 | 348 | </div> |
| 281 | 349 | <div class="fs_input_wrap"> |
| 282 | - <input type="text" id="fcom_field_vefication" | |
| 283 | - placeholder="<?php _e('2FA Code', 'fluent-community'); ?>" name="_email_verification_code" | |
| 350 | + <input type="text" id="fcom_field_verification" | |
| 351 | + placeholder="<?php esc_html_e('2FA Code', 'fluent-community'); ?>" name="_email_verification_code" | |
| 284 | 352 | required/> |
| 285 | 353 | </div> |
| 286 | 354 | </div> |
| 287 | 355 | <div class="fcom_form-group"> |
| 288 | 356 | <div class="fcom_form_input"> |
| 289 | - <button type="submit" class="fcom_btn fcom_btn_primary"> | |
| 290 | - <?php _e('Complete Signup', 'fluent-community'); ?> | |
| 357 | + <button type="submit" class="fcom_btn has_svg_loader fcom_btn_primary"> | |
| 358 | + <svg version="1.1" class="fls_loading_svg" x="0px" y="0px" width="40px" height="20px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> | |
| 359 | + <path fill="currentColor" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z"> | |
| 360 | + <animateTransform attributeType="xml" | |
| 361 | + attributeName="transform" | |
| 362 | + type="rotate" | |
| 363 | + from="0 25 25" | |
| 364 | + to="360 25 25" | |
| 365 | + dur="0.6s" | |
| 366 | + repeatCount="indefinite"/> | |
| 367 | + </path> | |
| 368 | + </svg> | |
| 369 | + <span> <?php esc_html_e('Complete Signup', 'fluent-community'); ?></span> | |
| 291 | 370 | </button> |
| 292 | 371 | </div> |
| 293 | 372 | </div> |
| 294 | 373 | </div> |
| @@ -298,28 +377,43 @@ | ||
| 298 | 377 | } |
| 299 | 378 | |
| 300 | 379 | public static function validateVerificationCode($code, $verificationToken, $formData) |
| 301 | 380 | { |
| 302 | - list($data, $signature) = explode('.', $verificationToken, 2); | |
| 303 | - $expectedSignature = hash_hmac('sha256', $data, SECURE_AUTH_KEY); | |
| 381 | + if (!is_string($verificationToken) || $verificationToken === '') { | |
| 382 | + return new \WP_Error('invalid_token', __('Invalid verification token. Please try again', 'fluent-community')); | |
| 383 | + } | |
| 304 | 384 | |
| 305 | - if (!hash_equals($expectedSignature, $signature)) { | |
| 385 | + $transientKey = 'fcom_signup_2fa_' . $verificationToken; | |
| 386 | + $data = get_transient($transientKey); | |
| 387 | + | |
| 388 | + if (!is_array($data) || empty($data['expires']) || empty($data['email']) || empty($data['code_hash'])) { | |
| 306 | 389 | return new \WP_Error('invalid_token', __('Invalid verification token. Please try again', 'fluent-community')); |
| 307 | 390 | } |
| 308 | 391 | |
| 309 | - $data = json_decode(base64_decode($data), true); | |
| 310 | - if ($data['expires'] < time()) { | |
| 392 | + if ((int)$data['expires'] < time()) { | |
| 393 | + delete_transient($transientKey); | |
| 311 | 394 | return new \WP_Error('expired_token', __('Verification token has expired. Please try again.', 'fluent-community')); |
| 312 | 395 | } |
| 313 | 396 | |
| 314 | - if ($data['email'] !== $formData['email']) { | |
| 397 | + if (!isset($formData['email']) || $data['email'] !== $formData['email']) { | |
| 315 | 398 | return new \WP_Error('invalid_email', __('Invalid email address. Please try again', 'fluent-community')); |
| 316 | 399 | } |
| 317 | 400 | |
| 401 | + // Cap online guesses per challenge: after too many wrong codes the challenge is burned. | |
| 402 | + if ((int) Arr::get($data, 'attempts', 0) >= 10) { | |
| 403 | + delete_transient($transientKey); | |
| 404 | + return new \WP_Error('too_many_attempts', __('Too many invalid attempts. Please try again', 'fluent-community')); | |
| 405 | + } | |
| 406 | + | |
| 318 | 407 | if (!wp_check_password($code, $data['code_hash'])) { |
| 408 | + $data['attempts'] = (int) Arr::get($data, 'attempts', 0) + 1; | |
| 409 | + set_transient($transientKey, $data, max(1, (int) $data['expires'] - time())); | |
| 319 | 410 | return new \WP_Error('invalid_code', __('Invalid verification code. Please try again', 'fluent-community')); |
| 320 | 411 | } |
| 321 | 412 | |
| 413 | + // Single-use: consume the challenge on success. | |
| 414 | + delete_transient($transientKey); | |
| 415 | + | |
| 322 | 416 | return true; |
| 323 | 417 | } |
| 324 | 418 | |
| 325 | 419 | public static function isAuthRateLimit() |
| @@ -341,6 +435,105 @@ | ||
| 341 | 435 | |
| 342 | 436 | $rateLimit = $rateLimit + 1; |
| 343 | 437 | set_transient($transientKey, $rateLimit, 300); // per 5 minutes |
| 344 | 438 | return true; |
| 439 | + } | |
| 440 | + | |
| 441 | + | |
| 442 | + public static function nativeLoginForm($args = array(), $hiddenFields = []) | |
| 443 | + { | |
| 444 | + $defaults = array( | |
| 445 | + 'echo' => true, | |
| 446 | + 'redirect' => (is_ssl() ? 'https://' : 'http://') | |
| 447 | + . (isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '') | |
| 448 | + . (isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : ''), | |
| 449 | + 'form_id' => 'loginform', | |
| 450 | + 'label_username' => __('Email Address', 'fluent-community'), | |
| 451 | + 'label_password' => __('Password', 'fluent-community'), | |
| 452 | + 'label_remember' => __('Remember Me', 'fluent-community'), | |
| 453 | + 'label_log_in' => __('Log In', 'fluent-community'), | |
| 454 | + 'id_username' => 'user_login', | |
| 455 | + 'id_password' => 'user_pass', | |
| 456 | + 'id_remember' => 'rememberme', | |
| 457 | + 'id_submit' => 'wp-submit', | |
| 458 | + 'remember' => true, | |
| 459 | + 'value_username' => '', | |
| 460 | + 'username_placeholder' => __('Your account email address', 'fluent-community'), | |
| 461 | + 'password_placeholder' => __('Your account password', 'fluent-community'), | |
| 462 | + 'value_remember' => false, | |
| 463 | + ); | |
| 464 | + | |
| 465 | + $args = wp_parse_args($args, apply_filters('login_form_defaults', $defaults)); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 466 | + | |
| 467 | + $login_form_top = apply_filters('login_form_top', '', $args); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 468 | + | |
| 469 | + $login_form_middle = apply_filters('login_form_middle', '', $args); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 470 | + | |
| 471 | + $login_form_bottom = apply_filters('login_form_bottom', '', $args); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound | |
| 472 | + | |
| 473 | + $actionUrl = esc_url(site_url('wp-login.php', 'login_post')); | |
| 474 | + | |
| 475 | + if (isset($args['action_url'])) { | |
| 476 | + $actionUrl = esc_url($args['action_url']); | |
| 477 | + } | |
| 478 | + | |
| 479 | + foreach ($hiddenFields as $key => $value) { | |
| 480 | + $login_form_top .= \sprintf( | |
| 481 | + '<input type="hidden" name="%1$s" value="%2$s" />', | |
| 482 | + esc_attr($key), | |
| 483 | + esc_attr($value) | |
| 484 | + ); | |
| 485 | + } | |
| 486 | + | |
| 487 | + $form = \sprintf( | |
| 488 | + '<form name="%1$s" id="%1$s" action="%2$s" method="post">', | |
| 489 | + esc_attr($args['form_id']), | |
| 490 | + $actionUrl | |
| 491 | + ) . | |
| 492 | + $login_form_top . | |
| 493 | + \sprintf( | |
| 494 | + '<p class="login-username fcom_form-group"> | |
| 495 | + <label for="%1$s">%2$s</label> | |
| 496 | + <input type="text" name="log" id="%1$s" autocomplete="username" class="input" value="%3$s" placeholder="%4$s" size="20" /> | |
| 497 | + </p>', | |
| 498 | + esc_attr($args['id_username']), | |
| 499 | + esc_html($args['label_username']), | |
| 500 | + esc_attr($args['value_username']), | |
| 501 | + esc_attr($args['username_placeholder']), | |
| 502 | + ) . | |
| 503 | + \sprintf( | |
| 504 | + '<p class="login-password fcom_form-group"> | |
| 505 | + <label for="%1$s">%2$s</label> | |
| 506 | + <input type="password" name="pwd" id="%1$s" autocomplete="current-password" placeholder="%3$s" class="input" value="" size="20" /> | |
| 507 | + </p>', | |
| 508 | + esc_attr($args['id_password']), | |
| 509 | + esc_html($args['label_password']), | |
| 510 | + esc_attr($args['password_placeholder']) | |
| 511 | + ) . | |
| 512 | + $login_form_middle . | |
| 513 | + ($args['remember'] ? | |
| 514 | + \sprintf( | |
| 515 | + '<p class="login-remember fcom_form-group"><label><input name="rememberme" type="checkbox" id="%1$s" value="forever"%2$s /> %3$s</label></p>', | |
| 516 | + esc_attr($args['id_remember']), | |
| 517 | + ($args['value_remember'] ? ' checked="checked"' : ''), | |
| 518 | + esc_html($args['label_remember']) | |
| 519 | + ) : '' | |
| 520 | + ) . | |
| 521 | + \sprintf( | |
| 522 | + '<p class="login-submit"> | |
| 523 | + <input type="submit" name="wp-submit" id="%1$s" class="button button-primary" value="%2$s" /> | |
| 524 | + <input type="hidden" name="redirect_to" value="%3$s" /> | |
| 525 | + </p>', | |
| 526 | + esc_attr($args['id_submit']), | |
| 527 | + esc_attr($args['label_log_in']), | |
| 528 | + esc_url($args['redirect']) | |
| 529 | + ) . | |
| 530 | + $login_form_bottom . | |
| 531 | + '</form>'; | |
| 532 | + | |
| 533 | + if ($args['echo']) { | |
| 534 | + echo $form; // @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 535 | + } else { | |
| 536 | + return $form; | |
| 537 | + } | |
| 345 | 538 | } |
| 346 | 539 | } |