'; } /** * Collect all WooCommerce-related admin menus (including add-ons) and expose to SPA via window.WNW_WC_MENUS. */ public static function localize_wc_menus() : void { // Ensure we're in admin and script handle exists later; safe to call regardless global $menu, $submenu; if ( ! is_array( $menu ) ) return; $items = []; $seen = []; $is_wc_slug = static function(string $slug) : bool { $s = strtolower($slug); return ( strpos($s, 'woocommerce') !== false || strpos($s, 'wc-admin') !== false || strpos($s, 'wc-') === 0 || strpos($s, 'edit.php?post_type=product') !== false || strpos($s, 'edit.php?post_type=shop_order') !== false || strpos($s, 'edit.php?post_type=shop_coupon') !== false ); }; foreach ( $menu as $m ) { // $m: [0] title, [1] cap, [2] slug, [3] page_title, [4] class, [5] id, [6] icon, [7] position if ( ! isset( $m[2] ) || ! is_string( $m[2] ) ) continue; $slug = (string) $m[2]; if ( ! $is_wc_slug( $slug ) ) continue; $title = wp_strip_all_tags( (string) ($m[0] ?? $m[3] ?? 'Woo') ); $key = md5( $slug . '|' . $title ); if ( isset($seen[$key]) ) continue; $seen[$key] = true; $children = []; if ( isset($submenu[$slug]) && is_array($submenu[$slug]) ) { foreach ( $submenu[$slug] as $sm ) { // $sm: [0] title, [1] cap, [2] slug $childTitle = wp_strip_all_tags( (string) ($sm[0] ?? '') ); $childSlug = (string) ($sm[2] ?? '' ); if ( $childSlug === '' ) continue; $children[] = [ 'key' => md5( $childSlug . '|' . $childTitle ), 'title' => $childTitle, 'href' => admin_url( $childSlug ), 'slug' => $childSlug, ]; } } $items[] = [ 'key' => $key, 'title' => $title, 'href' => admin_url( $slug ), 'slug' => $slug, 'children' => $children, ]; } // Attach to both possible script handles (dev/prod) foreach ( [ 'wnw-admin-dev-config', 'wnw-admin' ] as $handle ) { if ( wp_script_is( $handle, 'enqueued' ) || wp_script_is( $handle, 'registered' ) ) { wp_localize_script( $handle, 'WNW_WC_MENUS', [ 'items' => $items ] ); wp_add_inline_script( $handle, 'window.WNW_WC_MENUS = window.WNW_WC_MENUS || WNW_WC_MENUS;', 'after' ); } } // Absolute last resort: inject a tiny inline if no handle was matched (e.g., race condition) if ( ! isset( $GLOBALS['wp_scripts']->registered['wnw-admin'] ) && ! isset( $GLOBALS['wp_scripts']->registered['wnw-admin-dev-config'] ) ) { printf( '', wp_json_encode( [ 'items' => $items ] ) ); } } /** * Add link to standalone admin in WordPress admin bar */ public static function add_admin_bar_link( $wp_admin_bar ) { // Only show for users with WooCommerce permissions if ( ! current_user_can( 'manage_woocommerce' ) ) { return; } $wp_admin_bar->add_node( [ 'id' => 'woonoow-standalone', 'title' => 'WooNooW', 'href' => home_url( '/admin' ), 'meta' => [ 'title' => __( 'WooNooW Standalone Admin', 'woonoow' ), ], ] ); } }