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

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

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