PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
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 1.3.19 trunk All 48 releases
fluent-cart / app / Hooks / Handlers / MenuHandler.php

MenuHandler.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.5, at app/Hooks/Handlers/MenuHandler.php

701 lines 29.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Hooks\Handlers;
4
5 use FluentCart\Api\ModuleSettings;
6 use FluentCart\App\App;
7 use FluentCart\App\Services\Renderer\CheckoutFieldsSchema;
8 use FluentCart\App\Vite;
9 use FluentCart\App\Services\URL;
10 use FluentCart\Api\StoreSettings;
11 use FluentCart\Api\PaymentMethods;
12 use FluentCart\App\Helpers\Helper;
13 use FluentCart\App\Helpers\Status;
14 use FluentCart\App\Models\Product;
15 use FluentCart\App\Models\Customer;
16 use FluentCart\Framework\Support\Arr;
17 use FluentCart\App\CPT\FluentProducts;
18 use FluentCart\App\Helpers\AdminHelper;
19 use FluentCart\App\Models\AttributeTerm;
20 use FluentCart\App\Models\AttributeGroup;
21 use FluentCart\App\Models\ShippingMethod;
22 use FluentCart\App\Modules\Tax\TaxModule;
23 use FluentCart\App\Modules\FluentPlayer\FluentPlayerBridge;
24 use FluentCart\App\Modules\AdminFooter\AdminFooter;
25 use FluentCart\App\Helpers\CurrenciesHelper;
26 use FluentCart\App\Services\Filter\TaxFilter;
27 use FluentCart\App\Services\Filter\OrderFilter;
28 use FluentCart\App\Services\Filter\LicenseFilter;
29 use FluentCart\App\Services\Filter\LicenseSiteFilter;
30 use FluentCart\App\Services\Filter\ProductFilter;
31 use FluentCart\App\Services\Filter\CustomerFilter;
32 use FluentCart\App\Services\Filter\CouponFilter;
33 use FluentCart\App\Services\Filter\LogFilter;
34 use FluentCart\App\Services\Filter\OrderBumpFilter;
35 use FluentCart\App\Modules\Shipping\Services\Filter\ShippingClassFilter;
36 use FluentCart\App\Modules\Shipping\Services\Filter\ShippingZoneFilter;
37 use FluentCart\App\Modules\Integrations\AddOnModule;
38 use FluentCart\App\Services\DateTime\DayjsFormatter;
39 use FluentCart\App\Services\Translations\TransStrings;
40 use FluentCart\App\Services\Permission\PermissionManager;
41 use FluentCart\Database\DataBackfills;
42 use FluentCart\App\Modules\PaymentMethods\Core\GatewayManager;
43
44 class MenuHandler
45 {
46 public function register()
47 {
48 add_action('init', [$this, 'init']);
49
50 add_action('admin_init', function () {
51 $page = $_GET['page'] ?? '';
52
53 if ($page == 'fluent-cart') {
54
55 \FluentCart\App\Events\FirstTimePluginActivation::handle();
56 (new AdminFooter())->register();
57 add_action('admin_enqueue_scripts', function () {
58 Vite::enqueueStyle('fluent_cart_admin_app_css',
59 'styles/tailwind/style.css',
60 );
61 Vite::enqueueScript('fluent_cart_admin_global_js',
62 'admin/global.js',
63 );
64 });
65
66 }
67 });
68
69 // Inline dark mode init script for all FluentCart admin pages (prevents flicker)
70 add_action('admin_head', [$this, 'outputFluentCartDarkModeScript']);
71
72 // Enqueue dark mode toggle JS for taxonomy pages
73 add_action('admin_head', [$this, 'enqueueDarkModeToggleForTaxonomy']);
74
75 // Add a post display state for special WC pages.
76 add_filter('display_post_states', array($this, 'addDisplayPostStates'), 10, 2);
77
78 }
79
80
81 public function addDisplayPostStates($states, $post)
82 {
83 if (!$post || $post->post_type != 'page') {
84 return $states;
85 }
86
87
88 $targetKeys = [
89 'checkout_page_id' => __('Checkout Page', 'fluent-cart'),
90 'cart_page_id' => __('Cart Page', 'fluent-cart'),
91 'receipt_page_id' => __('Receipt Page', 'fluent-cart'),
92 'shop_page_id' => __('Shop Page', 'fluent-cart'),
93 'customer_profile_page_id' => __('Customer Profile Page', 'fluent-cart'),
94 ];
95
96 $pagesConfig = (new StoreSettings())->getPagesSettings();
97 $pagesConfig = Arr::only($pagesConfig, array_keys($targetKeys));
98
99 if (!is_array($pagesConfig)) {
100 return $states;
101 }
102 $pagesConfig = array_filter($pagesConfig);
103
104 if (empty($pagesConfig)) {
105 return $states;
106 }
107
108
109 $pagesConfig = array_flip($pagesConfig);
110 $targetKey = Arr::get($pagesConfig, $post->ID);
111
112 if ($targetKey && isset($targetKeys[$targetKey])) {
113
114 $logo = '<svg style="vertical-align: middle; height: 18px; width: 18px;" width="18" height="18" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
115 <rect width="300" height="300" rx="30" fill="white"/>
116 <path d="M136.561 205.944H47.1367L61.1704 173.491C65.2906 163.963 74.6784 157.795 85.0589 157.795H191.584L184.338 174.551C176.098 193.607 157.322 205.944 136.561 205.944Z" fill="#00009F"/>
117 <path d="M210.643 142.439H84.8574L92.1035 125.683C100.344 106.627 119.12 94.2905 139.881 94.2905H248.565L234.531 126.743C230.411 136.271 221.023 142.439 210.643 142.439Z" fill="#00009F"/>
118 </svg>';
119
120 $states['fluent_cart'] = '<span>' . $logo . '<span>' . $targetKeys[$targetKey] . '</span></span>';
121 }
122
123 return $states;
124
125 }
126
127 public function outputFluentCartDarkModeScript()
128 {
129 global $pagenow;
130 $page = $_GET['page'] ?? '';
131 $postType = $_GET['post_type'] ?? '';
132
133 // post.php?post=ID&action=edit omits post_type; resolve it from the post ID.
134 if ($pagenow === 'post.php' && empty($postType)) {
135 $postId = (int) App::request()->get('post', 0);
136 $postType = $postId ? (string) get_post_type($postId) : '';
137 }
138
139 $isFluentCartPage = $page === 'fluent-cart';
140 $isTaxonomyList = $pagenow === 'edit-tags.php' && $postType === FluentProducts::CPT_NAME;
141 $isTermEditPage = $pagenow === 'term.php' && $postType === FluentProducts::CPT_NAME;
142 $isProductEditPage = ($pagenow === 'post.php' || $pagenow === 'edit.php') && $postType === FluentProducts::CPT_NAME;
143
144 if (!$isFluentCartPage && !$isTaxonomyList && !$isTermEditPage && !$isProductEditPage) {
145 return;
146 }
147
148 // Runs synchronously in <head> before any paint — applies the dark class and
149 // data-fct-theme attribute to <html> so logos and the theme icon render correctly
150 // from the very first frame, with no light-to-dark flash.
151 echo '<script>' . $this->getDarkModeInitScript() . '</script>';
152 }
153
154 public function enqueueDarkModeToggleForTaxonomy()
155 {
156 global $pagenow;
157 $postType = $_GET['post_type'] ?? '';
158
159 $isTaxonomyList = $pagenow === 'edit-tags.php' && $postType === FluentProducts::CPT_NAME;
160 $isTermEditPage = $pagenow === 'term.php' && $postType === FluentProducts::CPT_NAME;
161
162 if ($isTaxonomyList || $isTermEditPage) {
163 Vite::enqueueScript(
164 'fluent_cart_dark_mode_toggle',
165 'admin/dark-mode-toggle.js',
166 [],
167 FLUENTCART_VERSION,
168 true
169 );
170 }
171 }
172
173 private function getDarkModeInitScript(): string
174 {
175 return "(function(){" .
176 "var k='fluent_theme_mode',c='fluent_theme_dark'," .
177 "s=localStorage.getItem(k)||localStorage.getItem('fcart_admin_theme')," .
178 "t=s==='dark'?'dark':s==='light'?'light':'system'," .
179 "d=s==='dark'||s==='system:dark'||((!s||s==='system')&&window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches);" .
180 "document.documentElement.setAttribute('data-fct-theme',t);" .
181 "if(d)document.documentElement.classList.add(c);" .
182 "})();";
183 }
184
185 public function init()
186 {
187
188 add_action('admin_menu', array($this, 'addAdminMenu'));
189
190 /*
191 * Disable Gutenberg for Products
192 */
193 add_filter('parent_file', function ($parent_file) {
194 global $submenu_file, $current_screen, $pagenow;
195
196 $postType = $_GET['post_type'] ?? '';
197 if ($postType == FluentProducts::CPT_NAME && $current_screen->post_type == FluentProducts::CPT_NAME) {
198 if ($pagenow == 'post.php') {
199 $submenu_file = 'edit.php?post_type=' . $current_screen->post_type;
200 }
201
202 if ($pagenow == 'edit-tags.php') {
203 $taxonomy = $_GET['taxonomy'] ?? '';
204 $submenu_file = 'edit-tags.php?taxonomy=' . esc_attr($taxonomy) . '&post_type=' . $current_screen->post_type;
205 }
206
207 $parent_file = 'fluent-cart';
208 }
209
210 return $parent_file;
211 });
212
213 add_action('fluent_cart/admin_menu', array($this, 'renderAdminMenu'));
214 // add_action('in_admin_header', array($this, 'maybeRenderAdminMenu'));
215
216 add_action('edit_form_top', array($this, 'pushProductNav'));
217
218 add_action('admin_bar_menu', [$this, 'globalEnqueueAssets'], 10, 1);
219 }
220
221 public function addAdminMenu()
222 {
223 $capability = 'manage_options';
224
225 if (!current_user_can('manage_options') && App::isProActive()) {
226 $capability = PermissionManager::ADMIN_CAP;
227 }
228
229 if (!current_user_can($capability)) {
230 return;
231 }
232
233 global $submenu;
234
235 $adminMenuTitle = apply_filters('fluent_cart/admin_menu_title', 'FluentCart', []);
236
237 add_menu_page(
238 $adminMenuTitle,
239 $adminMenuTitle,
240 $capability,
241 'fluent-cart',
242 [$this, 'renderAdmin'],
243 $this->getMenuIcon(),
244 apply_filters('fluent_cart/admin_menu_position', 3)
245 );
246
247 $submenu['fluent-cart']['dashboard'] = array(
248 __('Dashboard', 'fluent-cart'),
249 $capability,
250 'admin.php?page=fluent-cart#/',
251 '',
252 'fluent_cart_dashboard'
253 );
254
255 if (PermissionManager::hasPermission(['orders/view'])) {
256 $submenu['fluent-cart']['orders'] = array(
257 __('Orders', 'fluent-cart'),
258 $capability,
259 'admin.php?page=fluent-cart#/orders',
260 '',
261 'fluent_cart_orders'
262 );
263 }
264
265 if (PermissionManager::hasPermission(['customers/view', 'customers/manage'])) {
266 $submenu['fluent-cart']['customers'] = array(
267 __('Customers', 'fluent-cart'),
268 $capability,
269 'admin.php?page=fluent-cart#/customers',
270 '',
271 'fluent_cart_customers'
272 );
273 }
274
275 if (PermissionManager::hasPermission(['products/view'])) {
276 $submenu['fluent-cart']['products'] = array(
277 __('Products', 'fluent-cart'),
278 $capability,
279 'admin.php?page=fluent-cart#/products',
280 '',
281 'fluent_cart_products'
282 );
283 }
284
285 if (PermissionManager::hasPermission(['subscriptions/view'])) {
286 $submenu['fluent-cart']['subscriptions'] = array(
287 __('Subscriptions', 'fluent-cart'),
288 $capability,
289 'admin.php?page=fluent-cart#/subscriptions',
290 '',
291 'fluent_cart_subscriptions'
292 );
293 }
294
295 if (PermissionManager::hasPermission(['reports/view'])) {
296 $submenu['fluent-cart']['reports'] = array(
297 __('Reports', 'fluent-cart'),
298 $capability,
299 'admin.php?page=fluent-cart#/reports/overview',
300 '',
301 'fluent_cart_reports'
302 );
303 }
304
305 if (PermissionManager::userCan('is_super_admin')) {
306 $submenu['fluent-cart']['integrations'] = array(
307 __('Integrations', 'fluent-cart'),
308 $capability,
309 'admin.php?page=fluent-cart#/integrations',
310 '',
311 'fluent_cart_integrations'
312 );
313 }
314
315
316 $hasSensitiveAccess = PermissionManager::hasPermission(['store/settings', 'store/sensitive']);
317
318 if ($hasSensitiveAccess) {
319 $submenu['fluent-cart']['settings'] = array(
320 __('Settings', 'fluent-cart'),
321 $capability,
322 'admin.php?page=fluent-cart#/settings/store-settings/',
323 '',
324 'fluent_cart_settings'
325 );
326 }
327
328 if (PermissionManager::hasPermission(['coupons/manage', 'coupons/view'])) {
329 $submenu['fluent-cart']['coupons'] = array(
330 __('Coupons', 'fluent-cart'),
331 $capability,
332 'admin.php?page=fluent-cart#/coupons',
333 '',
334 'fluent_cart_coupons'
335 );
336 }
337
338 if ($hasSensitiveAccess && TaxModule::isTaxEnabled()) {
339 $submenu['fluent-cart']['taxes'] = array(
340 __('Taxes', 'fluent-cart'),
341 $capability,
342 'admin.php?page=fluent-cart#/taxes',
343 '',
344 'fluent_cart_taxes'
345 );
346 }
347
348
349 if (PermissionManager::hasPermission(['products/create', 'products/edit'])) {
350 $taxonomies = get_taxonomies([
351 'object_type' => [FluentProducts::CPT_NAME],
352 'public' => true,
353 ], 'object');
354
355 foreach ($taxonomies as $key => $taxonomy) {
356 $menuUrl = 'edit-tags.php?taxonomy=' . $taxonomy->name . '&post_type=' . FluentProducts::CPT_NAME;
357 $submenu['fluent-cart'][$key] = [
358 $taxonomy->label,
359 $capability,
360 $menuUrl,
361 '',
362 $taxonomy->name
363 ];
364 }
365 }
366
367 if (PermissionManager::userCan('is_super_admin')) {
368 $submenu['fluent-cart']['logs'] = array(
369 __('Logs', 'fluent-cart'),
370 $capability,
371 'admin.php?page=fluent-cart#/logs',
372 '',
373 'fluent_cart_logs'
374 );
375 }
376
377 do_action('fluent_cart/admin_submenu_added', $submenu);
378 }
379
380 public function renderAdmin()
381 {
382 $isCustomDashboardSlugChanged = (new StoreSettings())->getCustomerDashboardPageSlug() != (new StoreSettings())->get('customer_profile_page_slug');
383
384 if ($isCustomDashboardSlugChanged) {
385 $allSettings = (new StoreSettings())->get();
386 (new StoreSettings())->save($allSettings); // we are just resaving to flash the settings cache
387 }
388
389 if (function_exists('wp_enqueue_editor')) {
390 wp_enqueue_editor();
391 wp_tinymce_inline_scripts();
392 wp_enqueue_media();
393 }
394
395 $this->enqueueAssets();
396
397 $config = App::getInstance('config');
398
399 $name = $config->get('app.name');
400
401 $slug = $config->get('app.slug');
402
403 $baseUrl = apply_filters('fluent_connector_base_url', admin_url('admin.php?page=newproject#/'));
404
405 $app = App::getInstance();
406 $assets = $app['url.assets'];
407
408 App::make('view')->render('admin.admin_app', [
409 'name' => $name,
410 'slug' => $slug,
411 'baseUrl' => $baseUrl,
412 'logo' => $assets . 'images/logo.svg',
413 ]);
414 }
415
416 public function maybeRenderAdminMenu()
417 {
418 $postType = $_GET['post_type'] ?? '';
419 if ($postType == FluentProducts::CPT_NAME && is_admin()) {
420 AdminHelper::getAdminMenu(true);
421 AdminHelper::pushGlobalAdminAssets();
422 }
423 }
424
425 public function renderAdminMenu()
426 {
427 if (!apply_filters('fluent_cart/show_admin_top_bar', true)) {
428 return;
429 }
430 AdminHelper::getAdminMenu(true);
431 }
432
433 public function pushProductNav($post)
434 {
435 if (!$post || $post->post_type != FluentProducts::CPT_NAME) {
436 return;
437 }
438
439 AdminHelper::getProductMenu($post->ID, true, 'product_edit');
440 AdminHelper::pushGlobalAdminAssets();
441 }
442
443 public function enqueueAssets()
444 {
445 $app = App::getInstance();
446
447 $slug = $app->config->get('app.slug');
448
449 do_action('fluent_cart/loading_app', $app);
450
451 //This should be done before enqueueing the global script.
452 // wp-i18n backs the admin translator (resources/admin/utils/translator/Translator.js).
453 Vite::enqueueScript($slug . '_admin_app_start', 'admin/bootstrap/app.js', [$slug . '_global_admin_hooks', 'wp-i18n']);
454
455 //Don't register this script using vite.
456 if (!wp_script_is('wp-hooks', 'registered')) {
457 $suffix = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
458 wp_register_script('wp-hooks', includes_url('js/dist/hooks' . $suffix . '.js'), ['wp-polyfill'], FLUENTCART_VERSION, true);
459 }
460 if (!wp_script_is('wp-hooks', 'enqueued')) {
461 wp_enqueue_script('wp-hooks');
462 }
463
464 wp_enqueue_script($slug . '_global_admin_hooks', Vite::getEnqueuePath('admin/admin_hooks.js'), ['wp-hooks'], FLUENTCART_VERSION, true);
465
466 $manager = GatewayManager::getInstance();
467 $payment_routes = $manager->getRoutes();
468 // $payment_routes = apply_filters('fluent_cart/payments/payment_method_settings_routes', []);
469
470 $storage_driver_routes = apply_filters('fluent_cart/storage/storage_driver_settings_routes', [], []);
471
472 $settings = new StoreSettings();
473 $checkoutUrl = add_query_arg(Helper::INSTANT_CHECKOUT_URL_PARAM, '=', $settings->getCheckoutPage());
474 $restVars = Helper::getRestInfo();
475 $hasDataMigrations = current_user_can('manage_options') && DataBackfills::hasPending();
476
477 $filterOptions = [
478 'order_filter_options' => OrderFilter::getTableFilterOptions(),
479 'customer_filter_options' => CustomerFilter::getTableFilterOptions(),
480 'product_filter_options' => ProductFilter::getTableFilterOptions(),
481 'license_filter_options' => LicenseFilter::getTableFilterOptions(),
482 'license_site_filter_options' => LicenseSiteFilter::getTableFilterOptions(),
483 'tax_filter_options' => TaxFilter::getTableFilterOptions(),
484 ];
485 $filterOptions = apply_filters('fluent_cart/admin_filter_options', $filterOptions, []);
486
487 // Structured table config keyed by table name (used by Table.js base class)
488 $tableConfig = [
489 'order_table' => ['filters' => Arr::get($filterOptions, 'order_filter_options', [])],
490 'customers' => ['filters' => Arr::get($filterOptions, 'customer_filter_options', [])],
491 'product_table' => ['filters' => Arr::get($filterOptions, 'product_filter_options', [])],
492 'licenses' => ['filters' => Arr::get($filterOptions, 'license_filter_options', [])],
493 'license_sites' => ['filters' => Arr::get($filterOptions, 'license_site_filter_options', [])],
494 'taxes_table' => ['filters' => Arr::get($filterOptions, 'tax_filter_options', [])],
495 'subscriptions' => ['filters' => Arr::get($filterOptions, 'subscription_filter_options', [])],
496 'shipping_zone_table' => ['filters' => Arr::get($filterOptions, 'shipping_zone_filter_options', [])],
497 // The Order Sources report filters orders, so its advanced-filter UI
498 // reuses the Orders filter vocabulary rather than defining its own.
499 'source_report' => ['filters' => Arr::get($filterOptions, 'order_filter_options', [])],
500 ];
501
502 // Tables that declare sort options on their filter class but carry no
503 // filter-options entry above: the Sort popover still needs them, and
504 // they are what `fluent_cart/{filterName}_table_sorts` feeds.
505 $sortOnlyTables = [
506 'coupon_table' => CouponFilter::class,
507 'log_table' => LogFilter::class,
508 'order_bump_table' => OrderBumpFilter::class,
509 'shipping_class_table' => ShippingClassFilter::class,
510 'shipping_zone_table' => ShippingZoneFilter::class,
511 ];
512
513 foreach ($sortOnlyTables as $tableName => $filterClass) {
514 if (empty($tableConfig[$tableName]['filters']['sorts'])) {
515 $tableConfig[$tableName]['filters']['sorts'] = call_user_func([$filterClass, 'getSortOptions']);
516 }
517 }
518
519 $tableConfig = apply_filters('fluent_cart/admin_table_saved_views', $tableConfig, [
520 'filterOptions' => $filterOptions
521 ]);
522
523 $currentUser = get_user_by('ID', get_current_user_id());
524
525 // Get app config and merge additional properties into it
526 $appConfig = $app->config->get('app');
527 $appConfig['version'] = FLUENTCART_VERSION;
528 $appConfig['permissions'] = PermissionManager::getUserPermissions();
529 $appConfig['isProActive'] = App::isProActive();
530 $appConfig['proVersion'] = defined('FLUENTCART_PRO_PLUGIN_VERSION') ? FLUENTCART_PRO_PLUGIN_VERSION : null;
531 $appConfig['fluentPlayer'] = FluentPlayerBridge::adminAppConfig();
532
533 $appConfig['logos'] = [
534 'dark' => Vite::getAssetUrl('images/logo/logo-full-dark.svg'),
535 'light' => Vite::getAssetUrl('images/logo/logo-full.svg'),
536 ];
537 $appConfig['isModuleTabEnabled'] = $settings->isModuleTabEnabled();
538 $appConfig['upgrade_url'] = Helper::getUpgradeUrl();
539
540 $max_upload_size = wp_max_upload_size(); // Returns size in bytes
541 $adminLocalizeData = apply_filters('fluent_cart/admin_app_data', [
542 'app_config' => $appConfig,
543 'slug' => $app->config->get('app.slug'),
544 'admin_url' => admin_url('admin.php?page=fluent-cart#/'),
545 'wp_admin_url' => rtrim(admin_url(), '/'),
546 'frontend_url' => URL::getFrontEndUrl(''),
547 'nonce' => wp_create_nonce($slug),
548 'rest' => $restVars,
549 'brand_logo' => $this->getMenuIcon(),
550 'asset_url' => Vite::getAssetUrl(),
551 'me' => [
552 'id' => $currentUser->ID,
553 'full_name' => trim($currentUser->display_name),
554 'email' => $currentUser->user_email,
555 'avatar' => get_avatar_url($currentUser->ID)
556 ],
557 'shop' => Helper::shopConfig(),
558 'product_statuses' => Status::getProductStatuses(),
559 'total_products_count' => Product::query()->count(),
560 'payment_statuses' => Status::getEditableTransactionStatuses(true),
561 'payment_routes' => $payment_routes,
562 'storage_driver_routes' => $storage_driver_routes,
563 'editable_payment_statuses' => Status::getEditableTransactionStatuses(true),
564 'order_statuses' => Status::getOrderStatuses(),
565 'editable_order_statuses' => Status::getEditableOrderStatuses(),
566 'editable_customer_statuses' => Status::getEditableCustomerStatuses(),
567 // Backward compat: keep the old typo'd keys for existing frontend code
568 'order_statues' => Status::getOrderStatuses(),
569 'editable_order_statues' => Status::getEditableOrderStatuses(),
570 'editable_customer_statues' => Status::getEditableCustomerStatuses(),
571 'shipping_statuses' => Status::getShippingStatuses(),
572 // Attribute library powering the Advanced Variation feature.
573 'variation_attributes' => AttributeGroup::with(['terms'])->get(),
574 'variation_terms' => AttributeTerm::query()->get()->keyBy('id'),
575 'product_image_base_uri' => Helper::getProductImageBaseUri(),
576 'add_on_modules' => AddOnModule::showAddOns(),
577 'stock_statuses' => Status::getStockStatuses(),
578 'fulfillment_types' => Helper::getFulfilmentTypes(),
579 'variation_types' => Helper::getVariationTypes(),
580 'trans' => TransStrings::getStrings(),
581 'dashboard_url' => admin_url('admin.php?page=fluent-cart#'),
582 'checkout_url' => $checkoutUrl,
583 'dummy_product_info' => apply_filters('fluent_cart/dummy_product_info', []) ?: [],
584 'currency_signs' => CurrenciesHelper::getCurrencySigns(),
585 'filter_options' => $filterOptions,
586 'table_config' => $tableConfig,
587 'receipt_page_url' => $settings->getReceiptPage(),
588 'payment_logos' => PaymentMethods::getIcons(),
589 'is_admin_bar_showing' => is_admin_bar_showing(),
590 'max_upload_size' => size_format($max_upload_size),
591 'available_shipping_method_count' => ShippingMethod::query()->where('is_enabled', '1')->count(),
592 'is_tax_enabled' => TaxModule::isTaxEnabled(),
593 'eu_vat_county_options' => TaxModule::euVatCountyOptions(),
594 'country_tax_titles' => TaxModule::taxTitleLists(),
595 'site_url' => site_url(),
596 'modules_settings' => ModuleSettings::getAllSettings(),
597 'purchase_fluent_cart_link' => 'https://fluentcart.com/',
598 'admin_notices' => apply_filters('fluent_cart/admin_notices', []),
599 // POSTs data-backfills/run until done; endpoint requires manage_options
600 'has_data_migrations' => $hasDataMigrations,
601 'subscription_intervals' => Helper::getAvailableSubscriptionIntervalOptions(),
602
603 'datei18' => DayjsFormatter::localizedStrings(),
604 'el_strings' => TransStrings::elStrings(),
605 'wp_locale' => get_locale(),
606 'is_full_name_required' => CheckoutFieldsSchema::isFullNameRequired(),
607 'business_details' => [
608 'company_name' => [
609 'enabled' => CheckoutFieldsSchema::isCompanyNameEnabled(),
610 'required' => CheckoutFieldsSchema::isCompanyNameRequired(),
611 ],
612 'vat_number' => [
613 'enabled' => CheckoutFieldsSchema::isVatNumberEnabled(),
614 'required' => CheckoutFieldsSchema::isVatNumberRequired(),
615 ],
616 'legal_registration_id' => [
617 'enabled' => CheckoutFieldsSchema::isLegalRegistrationIdEnabled(),
618 'required' => CheckoutFieldsSchema::isLegalRegistrationIdRequired(),
619 ],
620 ],
621 'fct_editor_frame' => '',
622 ]);
623
624 wp_localize_script($slug . '_admin_app_start', 'fluentCartAdminApp', $adminLocalizeData);
625
626 wp_localize_script($slug . '_admin_app_start', 'fluentCartRestVars', [
627 'rest' => $restVars,
628 ]);
629
630 do_action('fluent_cart/admin_js_loaded', $app);
631 }
632
633 public function globalEnqueueAssets($adminBar)
634 {
635 if (function_exists('get_current_screen')) {
636 $screen = get_current_screen();
637 } else {
638 $screen = null;
639 }
640
641 if ($screen && $screen->base !== 'user-edit') {
642 return;
643 }
644
645 $app = App::getInstance();
646
647 $slug = $app->config->get('app.slug');
648 if (is_admin()) {
649 wp_enqueue_script($slug . '_edit_wp_user_admin_global_js', Vite::getEnqueuePath('admin/utils/edit-wp-user-global.js'), ['jquery'], FLUENTCART_VERSION, true);
650 }
651
652
653 $baseUrl = apply_filters('fluent_cart/admin_base_url', admin_url('admin.php?page=fluent-cart#/'), []);
654
655 $editingUserVars = null;
656
657 if (function_exists('get_current_screen')) {
658 $currentScreen = get_current_screen();
659 if ($currentScreen && $currentScreen->id == 'user-edit') {
660 $userId = (int)($_GET['user_id'] ?? 0);
661 $user = get_user_by('ID', $userId);
662
663 if ($userId && $user) {
664 $fluentcartProfile = Customer::query()->where('email', $user->user_email)
665 ->orWhere('user_id', $user->ID)
666 ->first();
667 if ($fluentcartProfile) {
668 $fluentcartProfileUrl = $baseUrl . 'customers/' . $fluentcartProfile->id . '/view';
669 $editingUserVars = [
670 'user_id' => $userId,
671 'fct_profile_id' => $fluentcartProfile->id,
672 'fct_profile_url' => $fluentcartProfileUrl
673 ];
674 }
675 }
676 }
677 }
678 wp_localize_script('fluent-cart_edit_wp_user_admin_global_js', 'fluentcart_edit_user_global_bar_vars', [
679 'customer_base' => $baseUrl . 'customers/',
680 'edit_user_vars' => $editingUserVars
681 ]);
682 }
683
684 protected function getMenuIcon(): string
685 {
686 $svg = '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" fill="none">
687 <g clip-path="url(#clip0_394_8994)">
688 <path d="M90 0C95.5229 0 100 4.47715 100 10V90C100 95.5229 95.5229 100 90 100H10C4.47715 100 0 95.5229 0 90V10C0 4.47715 4.47715 0 10 0H90ZM28.3525 52.5986C24.8927 52.5988 21.7641 54.6544 20.3906 57.8301L15.7119 68.6484H45.5205C52.4408 68.6484 58.6996 64.5355 61.4463 58.1836L63.8613 52.5986H28.3525ZM46.6748 31.333C39.7545 31.333 33.4959 35.4459 30.749 41.7979L28.333 47.3828H70.2617C73.7217 47.3828 76.8513 45.3264 78.2246 42.1504L82.9023 31.333H46.6748Z" fill="#9CA1A8"/>
689 </g>
690 <defs>
691 <clipPath id="clip0_394_8994">
692 <rect width="100" height="100" fill="white"/>
693 </clipPath>
694 </defs>
695 </svg>';
696
697 return 'data:image/svg+xml;base64,' . base64_encode($svg);
698 }
699
700 }
701