| 1 |
<?php |
| 2 |
|
| 3 |
declare(strict_types=1); |
| 4 |
|
| 5 |
namespace Yatra\Shortcodes; |
| 6 |
|
| 7 |
use Yatra\Services\SettingsService; |
| 8 |
|
| 9 |
/** |
| 10 |
* Login Shortcode |
| 11 |
* |
| 12 |
* Displays customer login form |
| 13 |
*/ |
| 14 |
class LoginShortcode extends BaseShortcode |
| 15 |
{ |
| 16 |
public function __construct() |
| 17 |
{ |
| 18 |
parent::__construct('yatra_login', [ |
| 19 |
'show_register' => 'yes', |
| 20 |
'show_forgot_password' => 'yes', |
| 21 |
'redirect_url' => '', |
| 22 |
'remember_me' => 'yes', |
| 23 |
'title' => 'Customer Login', |
| 24 |
'subtitle' => 'Login to access your bookings and account' |
| 25 |
]); |
| 26 |
|
| 27 |
// Enqueue assets |
| 28 |
add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']); |
| 29 |
} |
| 30 |
|
| 31 |
/** |
| 32 |
* Enqueue shortcode-specific assets |
| 33 |
*/ |
| 34 |
public function enqueueAssets(): void |
| 35 |
{ |
| 36 |
// Only enqueue assets if shortcode is present on the page |
| 37 |
global $post; |
| 38 |
if (!$post || !has_shortcode($post->post_content, 'yatra_login') && !is_page_template('login-page.php')) { |
| 39 |
return; |
| 40 |
} |
| 41 |
|
| 42 |
// Enqueue CSS |
| 43 |
wp_enqueue_style( |
| 44 |
'yatra-login-shortcode', |
| 45 |
YATRA_PLUGIN_URL . 'assets/css/shortcodes/login-shortcode.css', |
| 46 |
[], |
| 47 |
YATRA_VERSION |
| 48 |
); |
| 49 |
|
| 50 |
// Enqueue JavaScript |
| 51 |
wp_enqueue_script( |
| 52 |
'yatra-login-shortcode', |
| 53 |
YATRA_PLUGIN_URL . 'assets/js/login-shortcode.js', |
| 54 |
['jquery', 'wp-i18n'], |
| 55 |
YATRA_VERSION, |
| 56 |
true |
| 57 |
); |
| 58 |
if (function_exists('wp_set_script_translations')) { |
| 59 |
wp_set_script_translations( |
| 60 |
'yatra-login-shortcode', |
| 61 |
'yatra', |
| 62 |
YATRA_PLUGIN_PATH . 'i18n/languages' |
| 63 |
); |
| 64 |
} |
| 65 |
|
| 66 |
// Localize script for AJAX with security and debugging |
| 67 |
wp_localize_script('yatra-login-shortcode', 'yatra_ajax', [ |
| 68 |
'ajax_url' => admin_url('admin-ajax.php'), |
| 69 |
'nonce' => wp_create_nonce('yatra_login_nonce'), |
| 70 |
'debug' => defined('WP_DEBUG') && WP_DEBUG, |
| 71 |
'strings' => [ |
| 72 |
'login_error' => __('Login failed. Please try again.', 'yatra'), |
| 73 |
'network_error' => __('Network error. Please check your connection.', 'yatra'), |
| 74 |
'validation_error' => __('Please fill in all required fields.', 'yatra') |
| 75 |
] |
| 76 |
]); |
| 77 |
} |
| 78 |
|
| 79 |
/** |
| 80 |
* Render the login shortcode content |
| 81 |
*/ |
| 82 |
protected function renderContent(array $atts): string |
| 83 |
{ |
| 84 |
$atts = shortcode_atts($this->default_attributes, $atts, $this->tag); |
| 85 |
|
| 86 |
// Sanitize and validate attributes |
| 87 |
$atts = $this->sanitizeAttributes($atts); |
| 88 |
|
| 89 |
// Check if user is already logged in |
| 90 |
if (is_user_logged_in()) { |
| 91 |
return $this->renderLoggedInMessage($atts); |
| 92 |
} |
| 93 |
|
| 94 |
// Set secure redirect URL |
| 95 |
$redirect_url = $this->getSecureRedirectUrl($atts['redirect_url']); |
| 96 |
|
| 97 |
// Make variables available to template |
| 98 |
set_query_var('yatra_login_atts', $atts); |
| 99 |
set_query_var('yatra_redirect_url', $redirect_url); |
| 100 |
|
| 101 |
// Load the login template with error handling |
| 102 |
$template_path = YATRA_PLUGIN_PATH . 'templates/shortcodes/login.php'; |
| 103 |
|
| 104 |
if (!file_exists($template_path)) { |
| 105 |
return $this->renderFallbackError(); |
| 106 |
} |
| 107 |
|
| 108 |
ob_start(); |
| 109 |
try { |
| 110 |
include $template_path; |
| 111 |
$content = ob_get_clean(); |
| 112 |
} catch (\Exception $e) { |
| 113 |
ob_end_clean(); |
| 114 |
|
| 115 |
$content = $this->renderFallbackError(); |
| 116 |
} |
| 117 |
|
| 118 |
// Clean up query vars |
| 119 |
set_query_var('yatra_login_atts', null); |
| 120 |
set_query_var('yatra_redirect_url', null); |
| 121 |
|
| 122 |
return $content; |
| 123 |
} |
| 124 |
|
| 125 |
/** |
| 126 |
* Render message for logged in users |
| 127 |
*/ |
| 128 |
private function renderLoggedInMessage(array $atts): string |
| 129 |
{ |
| 130 |
$user = wp_get_current_user(); |
| 131 |
$account_url = home_url('/' . SettingsService::getAccountBase()); |
| 132 |
|
| 133 |
ob_start(); |
| 134 |
?> |
| 135 |
<div class="yatra-login-logged-in"> |
| 136 |
<div class="yatra-logged-in-content"> |
| 137 |
<div class="yatra-logged-in-icon"> |
| 138 |
<?php echo yatra_svg_icon('user', 'yatra-logged-in-icon-svg'); ?> |
| 139 |
</div> |
| 140 |
<h3><?php esc_html_e('Already Logged In', 'yatra'); ?></h3> |
| 141 |
<p> |
| 142 |
<?php |
| 143 |
printf( |
| 144 |
/* translators: %s: logged-in user's display name. */ |
| 145 |
esc_html__('You are logged in as %s.', 'yatra'), |
| 146 |
'<strong>' . esc_html($user->display_name) . '</strong>' |
| 147 |
); |
| 148 |
?> |
| 149 |
</p> |
| 150 |
<div class="yatra-logged-in-actions"> |
| 151 |
<a href="<?php echo esc_url($account_url); ?>" class="yatra-btn yatra-btn-primary"> |
| 152 |
<?php esc_html_e('My Account', 'yatra'); ?> |
| 153 |
</a> |
| 154 |
<a href="<?php echo esc_url(wp_logout_url(get_permalink())); ?>" class="yatra-btn yatra-btn-outline"> |
| 155 |
<?php esc_html_e('Logout', 'yatra'); ?> |
| 156 |
</a> |
| 157 |
</div> |
| 158 |
</div> |
| 159 |
</div> |
| 160 |
<?php |
| 161 |
return ob_get_clean(); |
| 162 |
} |
| 163 |
|
| 164 |
/** |
| 165 |
* Sanitize and validate shortcode attributes |
| 166 |
*/ |
| 167 |
private function sanitizeAttributes(array $atts): array |
| 168 |
{ |
| 169 |
return [ |
| 170 |
'show_register' => in_array($atts['show_register'], ['yes', 'no'], true) ? $atts['show_register'] : 'yes', |
| 171 |
'show_forgot_password' => in_array($atts['show_forgot_password'], ['yes', 'no'], true) ? $atts['show_forgot_password'] : 'yes', |
| 172 |
'redirect_url' => sanitize_url($atts['redirect_url'] ?? ''), |
| 173 |
'remember_me' => in_array($atts['remember_me'], ['yes', 'no'], true) ? $atts['remember_me'] : 'yes', |
| 174 |
'title' => sanitize_text_field($atts['title'] ?? 'Customer Login'), |
| 175 |
'subtitle' => sanitize_text_field($atts['subtitle'] ?? 'Login to access your bookings and account') |
| 176 |
]; |
| 177 |
} |
| 178 |
|
| 179 |
/** |
| 180 |
* Get secure redirect URL |
| 181 |
*/ |
| 182 |
private function getSecureRedirectUrl(string $redirect_url): string |
| 183 |
{ |
| 184 |
if (!empty($redirect_url)) { |
| 185 |
// Validate URL is safe |
| 186 |
if (wp_http_validate_url($redirect_url)) { |
| 187 |
$redirect_host = parse_url($redirect_url, PHP_URL_HOST); |
| 188 |
$site_host = parse_url(home_url(), PHP_URL_HOST); |
| 189 |
|
| 190 |
// Only allow redirects to same host |
| 191 |
if ($redirect_host === $site_host) { |
| 192 |
return $redirect_url; |
| 193 |
} |
| 194 |
} |
| 195 |
} |
| 196 |
|
| 197 |
// Default: always send users to the account area after login. |
| 198 |
// Avoid wp_get_referer() here to prevent redirect loops back to the login form. |
| 199 |
return home_url('/' . SettingsService::getAccountBase()); |
| 200 |
} |
| 201 |
|
| 202 |
/** |
| 203 |
* Render fallback error message |
| 204 |
*/ |
| 205 |
private function renderFallbackError(): string |
| 206 |
{ |
| 207 |
ob_start(); |
| 208 |
?> |
| 209 |
<div class="yatra-login-error"> |
| 210 |
<p><?php esc_html_e('Login form is currently unavailable. Please try again later.', 'yatra'); ?></p> |
| 211 |
</div> |
| 212 |
<?php |
| 213 |
return ob_get_clean(); |
| 214 |
} |
| 215 |
} |
| 216 |
|