Files
WooNooW/MODULE_SYSTEM_IMPLEMENTATION.md
Dwindi Ramadhana 07020bc0dd feat: Implement centralized module management system
- Add ModuleRegistry for managing built-in modules (newsletter, wishlist, affiliate, subscription, licensing)
- Add ModulesController REST API for module enable/disable
- Create Modules settings page with category grouping and toggle controls
- Integrate module checks across admin-spa and customer-spa
- Add useModules hook for both SPAs to check module status
- Hide newsletter from footer builder when module disabled
- Hide wishlist features when module disabled (product cards, account menu, wishlist page)
- Protect wishlist API endpoints with module checks
- Auto-update navigation tree when modules toggled
- Clean up obsolete documentation files
- Add comprehensive documentation:
  - MODULE_SYSTEM_IMPLEMENTATION.md
  - MODULE_INTEGRATION_SUMMARY.md
  - ADDON_MODULE_INTEGRATION.md (proposal)
  - ADDON_MODULE_DESIGN_DECISIONS.md (design doc)
  - FEATURE_ROADMAP.md
  - SHIPPING_INTEGRATION.md

Module system provides:
- Centralized enable/disable for all features
- Automatic navigation updates
- Frontend/backend integration
- Foundation for addon-module unification
2025-12-26 19:19:49 +07:00

9.5 KiB

Module Management System - Implementation Guide

Status: Complete
Date: December 26, 2025


Overview

Centralized module management system that allows enabling/disabling features to improve performance and reduce clutter.


Architecture

Backend Components

1. ModuleRegistry (includes/Core/ModuleRegistry.php)

Central registry for all modules with enable/disable functionality.

Methods:

  • get_all_modules() - Get all registered modules
  • get_enabled_modules() - Get list of enabled module IDs
  • is_enabled($module_id) - Check if a module is enabled
  • enable($module_id) - Enable a module
  • disable($module_id) - Disable a module

Storage: woonoow_enabled_modules option (array of enabled module IDs)

2. ModulesController (includes/Api/ModulesController.php)

REST API endpoints for module management.

Endpoints:

  • GET /woonoow/v1/modules - Get all modules with status (admin only)
  • POST /woonoow/v1/modules/toggle - Toggle module on/off (admin only)
  • GET /woonoow/v1/modules/enabled - Get enabled modules (public, cached)

3. Navigation Integration

Added "Modules" to Settings menu in NavigationRegistry.php.


Frontend Components

1. Settings Page (admin-spa/src/routes/Settings/Modules.tsx)

React component for managing modules.

Features:

  • Grouped by category (Marketing, Customers, Products)
  • Toggle switches for each module
  • Module descriptions and feature lists
  • Real-time enable/disable with API integration

2. useModules Hook

Custom React hook for checking module status.

Files:

  • admin-spa/src/hooks/useModules.ts
  • customer-spa/src/hooks/useModules.ts

Usage:

import { useModules } from '@/hooks/useModules';

function MyComponent() {
  const { isEnabled, enabledModules, isLoading } = useModules();
  
  if (!isEnabled('wishlist')) {
    return null; // Hide feature if module disabled
  }
  
  return <WishlistButton />;
}

Registered Modules

1. Newsletter & Campaigns

  • ID: newsletter
  • Category: Marketing
  • Default: Enabled
  • Features: Subscriber management, email campaigns, scheduling

2. Customer Wishlist

  • ID: wishlist
  • Category: Customers
  • Default: Enabled
  • Features: Save products, wishlist page, sharing

3. Affiliate Program

  • ID: affiliate
  • Category: Marketing
  • Default: Disabled
  • Features: Referral tracking, commissions, dashboard, payouts

4. Product Subscriptions

  • ID: subscription
  • Category: Products
  • Default: Disabled
  • Features: Recurring billing, subscription management, renewals, trials

5. Software Licensing

  • ID: licensing
  • Category: Products
  • Default: Disabled
  • Features: License keys, activation management, validation API, expiry

Integration Examples

Example 1: Hide Wishlist Heart Icon (Frontend)

File: customer-spa/src/pages/Product/index.tsx

import { useModules } from '@/hooks/useModules';

export default function ProductPage() {
  const { isEnabled } = useModules();
  
  return (
    <div>
      {/* Only show wishlist button if module enabled */}
      {isEnabled('wishlist') && (
        <button onClick={addToWishlist}>
          <Heart />
        </button>
      )}
    </div>
  );
}

Example 2: Hide Newsletter Menu (Backend)

File: includes/Compat/NavigationRegistry.php

use WooNooW\Core\ModuleRegistry;

private static function get_base_tree(): array {
    $tree = [
        // ... other sections
        [
            'key' => 'marketing',
            'label' => __('Marketing', 'woonoow'),
            'path' => '/marketing',
            'icon' => 'mail',
            'children' => [],
        ],
    ];
    
    // Only add newsletter if module enabled
    if (ModuleRegistry::is_enabled('newsletter')) {
        $tree[4]['children'][] = [
            'label' => __('Newsletter', 'woonoow'),
            'mode' => 'spa',
            'path' => '/marketing/newsletter'
        ];
    }
    
    return $tree;
}

Example 3: Conditional Settings Display (Admin)

File: admin-spa/src/routes/Settings/Customers.tsx

import { useModules } from '@/hooks/useModules';

export default function CustomersSettings() {
  const { isEnabled } = useModules();
  
  return (
    <div>
      {/* Only show wishlist settings if module enabled */}
      {isEnabled('wishlist') && (
        <SettingsCard title="Wishlist Settings">
          <WishlistOptions />
        </SettingsCard>
      )}
    </div>
  );
}

Example 4: Backend Feature Check (PHP)

File: includes/Api/SomeController.php

use WooNooW\Core\ModuleRegistry;

public function some_endpoint($request) {
    // Check if module enabled before processing
    if (!ModuleRegistry::is_enabled('wishlist')) {
        return new WP_Error(
            'module_disabled',
            __('Wishlist module is disabled', 'woonoow'),
            ['status' => 403]
        );
    }
    
    // Process wishlist request
    // ...
}

Performance Considerations

Caching

  • Frontend: Module status cached for 5 minutes via React Query
  • Backend: Module list stored in wp_options (no transients needed)

Optimization

  • Public endpoint (/modules/enabled) returns only enabled module IDs
  • No authentication required for checking module status
  • Minimal payload (~100 bytes)

Adding New Modules

1. Register Module (Backend)

Edit includes/Core/ModuleRegistry.php:

'my_module' => [
    'id' => 'my_module',
    'label' => __('My Module', 'woonoow'),
    'description' => __('Description of my module', 'woonoow'),
    'category' => 'marketing', // or 'customers', 'products'
    'icon' => 'icon-name', // lucide icon name
    'default_enabled' => false,
    'features' => [
        __('Feature 1', 'woonoow'),
        __('Feature 2', 'woonoow'),
    ],
],

2. Integrate Module Checks

Frontend:

const { isEnabled } = useModules();
if (!isEnabled('my_module')) return null;

Backend:

if (!ModuleRegistry::is_enabled('my_module')) {
    return;
}

3. Update Navigation (Optional)

If module adds menu items, conditionally add them in NavigationRegistry.php.


Testing Checklist

Backend Tests

  • Module registry returns all modules
  • Enable/disable module updates option
  • is_enabled() returns correct status
  • API endpoints require admin permission
  • Public endpoint works without auth

Frontend Tests

  • Modules page displays all modules
  • Toggle switches work
  • Changes persist after page reload
  • useModules hook returns correct status
  • Features hide when module disabled

Integration Tests

  • Wishlist heart icon hidden when module off
  • Newsletter menu hidden when module off
  • Settings sections hidden when module off
  • API endpoints return 403 when module off

Migration Notes

First Time Setup

On first load, modules use default_enabled values:

  • Newsletter: Enabled
  • Wishlist: Enabled
  • Affiliate: Disabled
  • Subscription: Disabled
  • Licensing: Disabled

Existing Installations

No migration needed. System automatically initializes with defaults on first access.


Hooks & Filters

Actions

  • woonoow/module/enabled - Fired when module is enabled
    • Param: $module_id (string)
  • woonoow/module/disabled - Fired when module is disabled
    • Param: $module_id (string)

Filters

  • woonoow/modules/registry - Modify module registry
    • Param: $modules (array)
    • Return: Modified modules array

Example:

add_filter('woonoow/modules/registry', function($modules) {
    $modules['custom_module'] = [
        'id' => 'custom_module',
        'label' => 'Custom Module',
        // ... other properties
    ];
    return $modules;
});

Troubleshooting

Module Toggle Not Working

  1. Check admin permissions (manage_options)
  2. Clear browser cache
  3. Check browser console for API errors
  4. Verify REST API is accessible

Module Status Not Updating

  1. Clear React Query cache (refresh page)
  2. Check woonoow_enabled_modules option in database
  3. Verify API endpoint returns correct data

Features Still Showing When Disabled

  1. Ensure useModules() hook is used
  2. Check component conditional rendering
  3. Verify module ID matches registry
  4. Clear navigation cache if menu items persist

Future Enhancements

Phase 2

  • Module dependencies (e.g., Affiliate requires Newsletter)
  • Module settings page (configure module-specific options)
  • Bulk enable/disable
  • Import/export module configuration

Phase 3

  • Module marketplace (install third-party modules)
  • Module updates and versioning
  • Module analytics (usage tracking)
  • Module recommendations based on store type

Files Created/Modified

New Files

  • includes/Core/ModuleRegistry.php
  • includes/Api/ModulesController.php
  • admin-spa/src/routes/Settings/Modules.tsx
  • admin-spa/src/hooks/useModules.ts
  • customer-spa/src/hooks/useModules.ts
  • MODULE_SYSTEM_IMPLEMENTATION.md (this file)

Modified Files

  • includes/Api/Routes.php - Registered ModulesController
  • includes/Compat/NavigationRegistry.php - Added Modules to Settings menu
  • admin-spa/src/App.tsx - Added Modules route

Summary

Backend: ModuleRegistry + API endpoints complete
Frontend: Settings page + useModules hook complete
Integration: Navigation menu + example integrations documented
Testing: Ready for testing

Next Steps: Test module enable/disable functionality and integrate checks into existing features (wishlist, newsletter, etc.)