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