Files
WooNooW/MENU_FIX_SUMMARY.md

9.6 KiB

Settings Submenu Fix - Complete Summary

🐛 Problem Identified

Issue: Settings submenu only appeared in standalone mode, not in wp-admin or fullscreen mode.

Root Cause: The navigation tree has TWO sources:

  1. Backend (PHP): NavigationRegistry::get_base_tree() - Used in wp-admin and all modes
  2. Frontend (TypeScript): tree.ts fallback - Only used if backend fails

The backend was providing empty children for settings:

// NavigationRegistry.php line 159
'children' => [], // Settings children will be added by SettingsProvider

But SettingsProvider never actually populated the navigation tree!


Solution Implemented

1. Fixed Backend Navigation Registry

File: includes/Compat/NavigationRegistry.php

Changes:

  • Added get_settings_children() method
  • Populated settings submenu in get_base_tree()
  • Made backend the single source of truth

Code:

[
    'key'      => 'settings',
    'label'    => __('Settings', 'woonoow'),
    'path'     => '/settings',
    'icon'     => 'settings',
    'children' => self::get_settings_children(), // ✅ Now populated!
],

Settings Children:

private static function get_settings_children(): array {
    $admin = admin_url('admin.php');
    
    return [
        // WooNooW Settings
        ['label' => __('WooNooW', 'woonoow'), 'mode' => 'spa', 'path' => '/settings'],
        
        // WooCommerce Settings (Most Used First)
        ['label' => __('General', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/general'],
        ['label' => __('Payments', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/payments'],
        ['label' => __('Shipping', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/shipping'],
        ['label' => __('Products', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/products'],
        ['label' => __('Tax', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/tax'],
        ['label' => __('Accounts & Privacy', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/accounts'],
        ['label' => __('Emails', 'woonoow'), 'mode' => 'spa', 'path' => '/settings/emails'],
        
        // Less Common (Bridge to WP Admin for now)
        ['label' => __('Advanced', 'woonoow'), 'mode' => 'bridge', 'href' => $admin . '?page=wc-settings&tab=advanced'],
        ['label' => __('Integration', 'woonoow'), 'mode' => 'bridge', 'href' => $admin . '?page=wc-settings&tab=integration'],
        ['label' => __('Status', 'woonoow'), 'mode' => 'bridge', 'href' => $admin . '?page=wc-status'],
        ['label' => __('Extensions', 'woonoow'), 'mode' => 'bridge', 'href' => $admin . '?page=wc-addons'],
    ];
}

2. Frontend Already Correct

File: admin-spa/src/nav/tree.ts

The frontend fallback tree was already correct (we fixed it earlier), but it wasn't being used because the backend tree takes precedence.

Data Flow:

function getNavTreeFromBackend(): MainNode[] {
  const backendTree = (window as any).WNW_NAV_TREE;
  
  if (Array.isArray(backendTree) && backendTree.length > 0) {
    return backendTree; // ✅ Backend tree used (from PHP)
  }
  
  // Fallback to static tree (for development/safety)
  return getStaticFallbackTree();
}

🎯 Single Source of Truth Established

Backend (PHP) - PRIMARY SOURCE

File: includes/Compat/NavigationRegistry.php

  • Builds navigation tree on init hook
  • Stores in wnw_nav_tree option
  • Localizes to window.WNW_NAV_TREE
  • Used by all modes (wp-admin, fullscreen, standalone)

Frontend (TypeScript) - FALLBACK ONLY

File: admin-spa/src/nav/tree.ts

  • Reads from window.WNW_NAV_TREE (backend)
  • Falls back to static tree if backend unavailable
  • Static tree matches backend structure

Flow Diagram

┌─────────────────────────────────────────┐
│ NavigationRegistry::build_nav_tree()   │
│ (PHP - runs on init hook)              │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│ Store in option: wnw_nav_tree           │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│ Localize to: window.WNW_NAV_TREE        │
│ (via Assets.php)                        │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│ Frontend reads: window.WNW_NAV_TREE     │
│ (tree.ts)                               │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│ useActiveSection() hook                 │
│ Returns: { main, children }             │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│ SubmenuBar component                    │
│ Renders: main.children                  │
└─────────────────────────────────────────┘

🧪 How to Test

1. Clear Navigation Cache

The navigation tree is cached in WordPress options. To rebuild:

  • Deactivate and reactivate WooNooW plugin, OR
  • Visit any admin page (tree rebuilds on init hook)

2. Test in wp-admin Mode

  1. Go to /wp-admin/admin.php?page=woonoow
  2. Click "Settings" in sidebar
  3. Should see submenu: WooNooW, General, Payments, Shipping, Products, Tax, Accounts & Privacy, Emails, Advanced, Integration, Status, Extensions

3. Test in Fullscreen Mode

  1. Click fullscreen toggle
  2. Click "Settings" in sidebar
  3. Should see same submenu

4. Test in Standalone Mode

  1. Go to /admin
  2. Click "Settings" in sidebar
  3. Should see same submenu

5. Verify Backend Data

Open browser console and check:

console.log(window.WNW_NAV_TREE);
// Should show array with settings.children populated

📊 Before vs After

Before

wp-admin mode:
Settings
└── (no submenu)

fullscreen mode:
Settings
└── (no submenu)

standalone mode:
Settings
├── WooNooW
├── General
├── Payments
└── ... (all items)

After

ALL MODES:
Settings
├── WooNooW
├── General
├── Payments
├── Shipping
├── Products
├── Tax
├── Accounts & Privacy
├── Emails
├── Advanced (bridge)
├── Integration (bridge)
├── Status (bridge)
└── Extensions (bridge)

🔧 Files Modified

Backend

  • includes/Compat/NavigationRegistry.php
    • Added get_settings_children() method
    • Updated get_base_tree() to use it

Frontend

  • admin-spa/src/nav/tree.ts (already correct from previous fix)
  • admin-spa/src/types/window.d.ts (TypeScript types)

Documentation

  • SETTINGS_TREE_PLAN.md (new - comprehensive implementation plan)
  • MENU_FIX_SUMMARY.md (this document)

🎯 Key Learnings

1. Dynamic Navigation System

WooNooW uses a dynamic navigation system where:

  • Backend (PHP) builds the tree
  • Frontend (TypeScript) consumes it
  • Addons can extend via filters

2. Cache Awareness

Navigation tree is cached in wnw_nav_tree option:

  • Rebuilt on init hook
  • Flushed on plugin activate/deactivate
  • Can be manually flushed: delete_option('wnw_nav_tree')

3. Extensibility

Addons can modify navigation via filters:

// Add new main section
add_filter('woonoow/nav_tree', function($tree) {
    $tree[] = [
        'key' => 'subscriptions',
        'label' => 'Subscriptions',
        'path' => '/subscriptions',
        'icon' => 'repeat',
        'children' => [...]
    ];
    return $tree;
});

// Add to existing section
add_filter('woonoow/nav_tree/settings/children', function($children) {
    $children[] = [
        'label' => 'My Custom Setting',
        'mode' => 'spa',
        'path' => '/settings/custom'
    ];
    return $children;
});

Verification Checklist

  • Backend provides settings children
  • Frontend reads from backend
  • Fallback tree matches backend
  • TypeScript types updated
  • No console errors
  • Settings submenu shows in all modes
  • Bridge links work
  • Documentation updated
  • Code committed

🚀 Next Steps

  1. Test the fix:

    • Reload wp-admin page
    • Check settings submenu appears
    • Test in all three modes
  2. Implement settings pages:

    • Start with Phase 1 (General, Payments, Shipping)
    • Follow SETTINGS_TREE_PLAN.md
  3. Monitor for issues:

    • Check browser console
    • Test with different user roles
    • Verify 3rd party plugin compatibility

Fix Date: November 5, 2025
Status: Complete
Tested: Pending user verification
Next: Implement General Settings page