PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
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.4, at app/Hooks/Handlers/MenuHandler.php

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