PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.0
1.7.0 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 All 50 releases
← All changes | app/Hooks/Handlers/ShortCodes/CustomerProfileHandler.php +57 -5 1.6.2 → 1.7.0 View file →
@@ -6,14 +6,20 @@
6 6 use FluentCart\Api\PaymentMethods;
7 7 use FluentCart\Api\Resource\CustomerResource;
8 8 use FluentCart\Api\StoreSettings;
9 9 use FluentCart\App\App;
10 +use FluentCart\App\Services\CustomerIdentity\EmailClaimPortal;
11 +use FluentCart\App\Services\CustomerIdentity\CustomerRecoveryService;
12 +use FluentCart\App\Services\CustomerIdentity\EmailClaimService;
13 +use FluentCart\App\Services\CustomerIdentity\EmailVerificationService;
10 14 use FluentCart\App\Helpers\CurrenciesHelper;
11 15 use FluentCart\App\Helpers\Helper;
12 16 use FluentCart\App\Models\Subscription;
13 17 use FluentCart\App\Modules\Templating\AssetLoader;
18 +use FluentCart\App\Services\ProductReviewService;
14 19 use FluentCart\App\Services\Renderer\CheckoutFieldsSchema;
15 20 use FluentCart\App\Services\TemplateService;
21 +use FluentCart\App\Services\DateTime\DayjsFormatter;
16 22 use FluentCart\App\Services\Translations\TransStrings;
17 23 use FluentCart\App\Vite;
18 24 use FluentCart\Framework\Support\Arr;
19 25 use FluentCart\Framework\Support\Str;
@@ -38,8 +44,18 @@
38 44 public static function register()
39 45 {
40 46 parent::register();
41 47
48 + add_action(CustomerRecoveryService::HOOK, [CustomerRecoveryService::class, 'run']);
49 +
50 + add_action('template_redirect', function () {
51 + $redirect = EmailClaimPortal::handleSubmission();
52 + if ($redirect) {
53 + wp_safe_redirect($redirect);
54 + exit;
55 + }
56 + });
57 +
42 58 // Add wildcard customer profile pages
43 59 // add a custom permalink endpoint
44 60 add_action('init', function () {
45 61 $pageSlug = (new StoreSettings())->getCustomerDashboardPageSlug();
@@ -64,8 +80,13 @@
64 80 $redirectUrl = $this->resolveLoginRedirectUrl(
65 81 (new StoreSettings())->getCustomerProfilePage()
66 82 );
67 83
84 + $claimToken = Arr::get($_GET, EmailClaimService::QUERY_TOKEN, '');
85 + if (is_string($claimToken) && $claimToken !== '') {
86 + $redirectUrl = add_query_arg(EmailClaimService::QUERY_TOKEN, sanitize_text_field(wp_unslash($claimToken)), (new StoreSettings())->getCustomerProfilePage());
87 + }
88 +
68 89 if (defined('FLUENT_AUTH_VERSION') && (new \FluentAuth\App\Hooks\Handlers\CustomAuthHandler())->isEnabled()) {
69 90 ?>
70 91 <div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #CBD5E0; border-radius: 8px;" class="fct_auth_wrap">
71 92 <h4><?php echo esc_html__('Please log in to access your customer portal.', 'fluent-cart'); ?></h4>
@@ -75,14 +96,20 @@
75 96 $attributeUrl = str_replace(['[', ']', '"'], ['%5B', '%5D', '%22'], $redirectUrl);
76 97 echo do_shortcode('[fluent_auth redirect_to="' . $attributeUrl . '"]');
77 98 echo '</div>';
78 99 } else {
100 + // The Login link wears the portal's button pair (see
101 + // customer-profile-global.scss), not the theme's `.button`.
102 + Vite::enqueueStyle(
103 + 'fluent-cart-customer-profile-global',
104 + 'public/customer-profile/style/customer-profile-global.scss'
105 + );
79 106 ?>
80 107 <div class="fct_auth_wrap">
81 108 <div class="fct_auth_message">
82 109 <h2><?php echo esc_html__('Login', 'fluent-cart'); ?></h2>
83 110 <p><?php echo esc_html__('Please log in to access your customer portal.', 'fluent-cart'); ?></p>
84 - <a href="<?php echo esc_url(wp_login_url($redirectUrl ?? '')); ?>" class="button">
111 + <a href="<?php echo esc_url(wp_login_url($redirectUrl ?? '')); ?>" class="button fct-customer-login-btn">
85 112 <?php echo esc_html__('Login', 'fluent-cart'); ?>
86 113 </a>
87 114 </div>
88 115 </div>
@@ -127,8 +154,19 @@
127 154 Vite::enqueueStyle( 'fluent-cart-customer-profile-global',
128 155 'public/customer-profile/style/customer-profile-global.scss',
129 156 );
130 157
158 + // Gate before custom endpoint callbacks or the dashboard load customer data.
159 + $verificationNotice = EmailClaimPortal::render();
160 + if (EmailVerificationService::isRequired(get_current_user_id())) {
161 + echo $verificationNotice; // @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in the view
162 + return;
163 + }
164 +
165 + if (!EmailVerificationService::isEnabled()) {
166 + CustomerResource::getCurrentCustomer(true);
167 + }
168 +
131 169 $customEndpointContent = $this->maybeCustomEndpointContent();
132 170
133 171 if(!$customEndpointContent) {
134 172 (new static())->enqueueStyles();
@@ -135,9 +173,10 @@
135 173 }
136 174
137 175 $colors = self::generateCssColorVariables(Arr::get($this->shortCodeAttributes, 'colors', ''));
138 176 add_action('fluent_cart/customer_menu', array($this, 'renderCustomerMenu'));
139 - add_action('fluent_cart/customer_app', function () use ($customEndpointContent) {
177 + add_action('fluent_cart/customer_app', function () use ($customEndpointContent, $verificationNotice) {
178 + echo $verificationNotice; // @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in the view
140 179 if($customEndpointContent) {
141 180 echo $customEndpointContent; // @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
142 181 } else {
143 182 AssetLoader::loadCustomerDashboardAssets();
@@ -270,8 +309,16 @@
270 309 'icon_svg' => '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
271 310 <path d="M10.75 8.5H14.5L10 13L5.5 8.5H9.25V3.25H10.75V8.5ZM4 15.25H16V10H17.5V16C17.5 16.1989 17.421 16.3897 17.2803 16.5303C17.1397 16.671 16.9489 16.75 16.75 16.75H3.25C3.05109 16.75 2.86032 16.671 2.71967 16.5303C2.57902 16.3897 2.5 16.1989 2.5 16V10H4V15.25Z" fill="currentColor"/>
272 311 </svg>'
273 312 ],
313 + 'reviews' => [
314 + 'label' => __('My Reviews', 'fluent-cart'),
315 + 'css_class' => 'fct_route',
316 + 'link' => $baseUrl . 'reviews',
317 + 'icon_svg' => '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
318 + <path d="M10 1.875L12.4635 6.86713L17.9727 7.66771L13.9863 11.5533L14.9271 17.0398L10 14.4488L5.07295 17.0398L6.01368 11.5533L2.02734 7.66771L7.53647 6.86713L10 1.875ZM10 5.26443L8.53252 8.23787L5.25123 8.71472L7.62536 11.0289L7.06498 14.2963L10 12.7534L12.935 14.2963L12.3746 11.0289L14.7488 8.71472L11.4675 8.23787L10 5.26443Z" fill="currentColor"/>
319 + </svg>'
320 + ],
274 321 'profile' => [
275 322 'label' => __('Profile', 'fluent-cart'),
276 323 'css_class' => 'fct_route',
277 324 'link' => $baseUrl . 'profile',
@@ -286,9 +333,13 @@
286 333 if (!ModuleSettings::isActive('license') || !App::isProActive()) {
287 334 unset($menuItems['licenses']);
288 335 }
289 336
337 + if (ProductReviewService::getReviewSettings()['reviews_enabled'] !== 'yes') {
338 + unset($menuItems['reviews']);
339 + }
290 340
341 +
291 342 if($currentCustomer) {
292 343 $hasSubscriptions = Subscription::query()->where('customer_id', $currentCustomer->id)->exists();
293 344 if(!$hasSubscriptions) {
294 345 unset($menuItems['subscriptions']);
@@ -312,9 +363,9 @@
312 363 $user = wp_get_current_user();
313 364 $profileData = [
314 365 'email' => $user->user_email,
315 366 'full_name' => $user->display_name,
316 - 'photo' => get_avatar_url($user->ID)
367 + 'photo' => Helper::getUserAvatarUrl($user->ID, $user->user_email)
317 368 ];
318 369 }
319 370
320 371 add_filter('fct_allowed_svg_tags', function ($tags) {
@@ -388,9 +439,10 @@
388 439 return html_entity_decode($sign, ENT_QUOTES, 'UTF-8');
389 440 }, CurrenciesHelper::getCurrencySigns()),
390 441 'trans' => TransStrings::getCustomerProfileString(),
391 442 'download_url_base' => site_url('fluent-cart/download-file/?fluent_cart_download=true'),
392 - 'placeholder_image' => Vite::getAssetUrl('images/placeholder.svg'),
443 + 'placeholder_image' => Helper::getProductPlaceholderUrl(),
444 + 'reviews_enabled' => ProductReviewService::getReviewSettings()['reviews_enabled'] === 'yes',
393 445 'stripe_pub_key' => apply_filters('fluent_cart/payment_methods/stripe_pub_key', ''),
394 446 'paypal_client_id' => apply_filters('fluent_cart/payment_methods/paypal_client_id', '', []),
395 447 'assets_path' => Vite::getAssetUrl(),
396 448 'rest' => Helper::getRestInfo(),
@@ -403,9 +455,9 @@
403 455 'first_name' => $currentCustomer ? $currentCustomer->first_name : '',
404 456 'last_name' => $currentCustomer ? $currentCustomer->last_name : '',
405 457 ],
406 458 'logout_url' => wp_logout_url(home_url()),
407 - 'datei18' => TransStrings::dateTimeStrings(),
459 + 'datei18' => DayjsFormatter::localizedStrings(),
408 460 'el_strings' => TransStrings::elStrings(),
409 461 'wp_locale' => get_locale(),
410 462 'is_company_name_enabled' => CheckoutFieldsSchema::isCompanyNameEnabled(),
411 463 'is_company_name_required' => CheckoutFieldsSchema::isCompanyNameRequired(),