# Press Zone Plugin Decoupling Plan

## Executive Summary

All Press Zone plugins currently have a **hard dependency** on `Community Press Zone` (`\PressZone\Core`). This prevents any plugin from being activated independently. The goal is to make each plugin **fully standalone** while enabling **optional cross-plugin integrations** when multiple plugins are active.

---

## Current Dependency Analysis

### Hard Dependencies (Blocking Activation)

| Plugin | Dependency Check | Behavior |
|--------|-----------------|----------|
| **Game Press Zone** | `class_exists('\PressZone\Core')` | Shows error, blocks init |
| **Wallet Press Zone** | `class_exists('\PressZone\Core')` | Shows error, blocks init |
| **Artist Press Zone** | `class_exists('PressZone\Core')` | Shows error, blocks init |
| **Newsletter Press Zone** | `class_exists('\PressZone\Core')` | Shows error, **deactivates self** |
| **Social Press Zone** | `class_exists('\PressZone\Core')` | Shows error, **deactivates self** |
| **Forum Press Zone** | *None* | ✅ Already independent! |

### Cross-Plugin Feature Dependencies

| Feature | Source Plugin | Target Plugin | Current Implementation |
|---------|--------------|---------------|------------------------|
| XP in Comments | Game | Community | Not implemented |
| Coins for Purchases | Wallet | Game (Redemption Engine) | `class_exists('\PressZone\Wallet\Wallet')` check |
| Comment Points | Community | Game | `do_action('press_zone_social_comment_posted')` |
| Wallet Spent Points | Wallet | Game | `do_action('press_zone_wallet_spent')` |
| Tip Sent Points | Wallet | Game | `do_action('press_zone_tip_sent')` |
| Shared Admin Styles | Community | All | CSS enqueue from Community |
| Unified Admin Menu | Community | All | `Unified_Menu::init()` in Community |

---

## What Community Press Zone Actually Provides

1. **Comments System** (`Comments\Comment_Manager`) - Custom comment templates, voting, pinning UI
2. **Unified Admin Menu** (`Unified_Menu`) - Centralized admin navigation
3. **Dashboard** (`Dashboard`) - Unified statistics
4. **Shared CSS** (`community-press-zone-admin-shared.css`)
5. **Cloud Connection** - Site registration with Press Zone cloud
6. **Access Control** (`Access`) - Content filtering
7. **Canvas Mode** (`Canvas`) - Custom page templates
8. **REST API** (`REST_Controller`) - Core API endpoints
9. **Health Checks** (`Health`) - System monitoring

---

## Decoupling Strategy

### Phase 1: Remove Hard Dependencies (Priority: HIGH)

**Goal:** Each plugin should initialize and function without any other Press Zone plugin.

#### 1.1 Game Press Zone

**File:** `game-press-zone/game-press-zone.php`

**Current Code (lines 46-51, 69-77):**
```php
function press_zone_game_init(): void {
    if (!class_exists('\\PressZone\\Core')) {
        add_action('admin_notices', __NAMESPACE__ . '\\press_zone_game_dependency_notice');
        return;
    }
    // ... rest of init
}
```

**New Code:**
```php
function press_zone_game_init(): void {
    // No hard dependency check - initialize independently
    
    // Load the autoloader.
    require_once PressZone_GAME_PLUGIN_DIR . 'includes/class-autoloader.php';

    // Initialize autoloader.
    $autoloader = new Autoloader();
    $autoloader->register();

    // Bootstrap the plugin.
    $plugin = Plugin::get_instance();
    $plugin->init();
}
```

**Remove:** The `press_zone_game_dependency_notice()` function entirely.

**Update Activation Hook:** Remove the `class_exists` check from `press_zone_game_activate()`.

---

#### 1.2 Wallet Press Zone

**File:** `wallet-press-zone/wallet-press-zone.php`

**Current Code (lines 79-89):**
```php
function check_dependencies(): bool {
    if (!class_exists('\\PressZone\\Core')) {
        // error notice
        return false;
    }
    return true;
}
```

**New Code:**
```php
function check_dependencies(): bool {
    // No hard dependencies - always return true
    return true;
}
```

Or simply remove the function and all calls to it.

---

#### 1.3 Artist Press Zone

**File:** `artist-press-zone/artist-press-zone.php`

**Current Code (lines 122-135):**
```php
add_action('plugins_loaded', function () {
    if (!class_exists('CPZ\Core') && !class_exists('PressZone\Core')) {
        // error notice
        return;
    }
    // ...
});
```

**New Code:**
```php
add_action('plugins_loaded', function () {
    // Check PHP version only
    if (version_compare(PHP_VERSION, '8.0', '<')) {
        // error notice
        return;
    }

    // Initialize plugin core
    if (!class_exists('\APZ\Core')) {
        require_once APZ_PLUGIN_DIR . 'includes/class-apz-core.php';
    }
    \APZ\Core::getInstance()->init();
}, 20);
```

---

#### 1.4 Newsletter Press Zone

**File:** `newsletter-press-zone/newsletter-press-zone.php`

**Current Code (lines 49-63):**
```php
function press_zone_newsletter_check_dependencies(): void {
    if ( ! class_exists( '\\PressZone\\Core' ) ) {
        // error notice
        // DEACTIVATES SELF!
        deactivate_plugins( plugin_basename( __FILE__ ) );
    }
}
```

**New Code:**
```php
function press_zone_newsletter_check_dependencies(): void {
    // No hard dependencies - plugin works standalone
    // Optional: Show info notice about enhanced features with Community Press Zone
}
```

**Update `press_zone_newsletter_init()`:** Remove the `class_exists` guard.

---

#### 1.5 Social Press Zone

**File:** `social-press-zone/social-press-zone.php`

**Current Code (lines 57-73):**
```php
add_action('plugins_loaded', function (): void {
    if (!class_exists('\\PressZone\\Core')) {
        // error notice
        // DEACTIVATES SELF!
        add_action('admin_init', function (): void {
            deactivate_plugins(PressZone_SOCIAL_BASENAME);
        });
        return;
    }
    // ...
});
```

**New Code:**
```php
add_action('plugins_loaded', function (): void {
    // Initialize the plugin independently
    Social\Plugin::get_instance();
}, 20);
```

---

### Phase 2: Create Optional Integration Layer (Priority: MEDIUM)

**Goal:** Features that require multiple plugins should gracefully degrade or enhance based on what's available.

#### 2.1 Create Helper Trait for Cross-Plugin Checks

**File:** Create in each plugin: `includes/trait-plugin-integration.php`

```php
<?php
namespace PressZone\Game;

trait Plugin_Integration
{
    /**
     * Check if Community Press Zone is active.
     */
    protected function is_community_active(): bool
    {
        return class_exists('\PressZone\Core');
    }

    /**
     * Check if Wallet Press Zone is active.
     */
    protected function is_wallet_active(): bool
    {
        return class_exists('\PressZone\Wallet\Wallet');
    }

    /**
     * Check if Game Press Zone is active.
     */
    protected function is_game_active(): bool
    {
        return class_exists('\PressZone\Game\Plugin');
    }

    /**
     * Check if Forum Press Zone is active.
     */
    protected function is_forum_active(): bool
    {
        return class_exists('\FPZ\Plugin');
    }
}
```

---

#### 2.2 Update Game Press Zone Redemption Engine

**File:** `game-press-zone/includes/class-redemption-engine.php`

**Current Code (line 144-149):**
```php
if (!class_exists('\\PressZone\\Wallet\\Wallet')) {
    return [
        'success' => false,
        'message' => __('Wallet system is not active.', 'game-press-zone'),
    ];
}
```

**Keep this as-is** - this is correct optional integration behavior! The feature (coin purchases) gracefully fails when Wallet is not present.

---

#### 2.3 Update Game Press Zone Hooks

**File:** `game-press-zone/includes/class-plugin.php`

The current hook registrations are **already correct**:
```php
add_action('press_zone_social_comment_posted', [$this->point_engine, 'handle_comment_posted'], 10, 2);
add_action('press_zone_wallet_spent', [$this->point_engine, 'handle_cash_spent'], 10, 2);
```

These hooks only fire if the source plugin (Community/Wallet) triggers them. **No changes needed.**

---

#### 2.4 Add XP Display to Community Comments (Optional Enhancement)

**File:** `community-press-zone/includes/Comments/Comment_Walker.php`

**Add optional XP display:**
```php
// In start_el() method, after author name:
if (class_exists('\PressZone\Game\Plugin')) {
    $game = \PressZone\Game\Plugin::get_instance();
    $profile = $game->get_profile_repository()->get_profile($comment->user_id);
    if ($profile && $profile->current_level > 1) {
        $output .= '<span class="community-press-zone-comment__level">Lvl ' . esc_html($profile->current_level) . '</span>';
    }
}
```

---

### Phase 3: Shared Resources (Priority: LOW)

**Goal:** Handle shared CSS/JS gracefully.

#### 3.1 Each Plugin Should Bundle Its Own Admin Styles

Instead of relying on Community Press Zone's shared CSS, each plugin should:

1. Have its own admin CSS file
2. Optionally load shared styles IF Community is active

**Example pattern:**
```php
public function enqueue_admin_assets(): void
{
    // Always load own styles
    wp_enqueue_style(
        'game-press-zone-admin',
        PressZone_GAME_PLUGIN_URL . 'assets/css/admin.css',
        [],
        PressZone_GAME_VERSION
    );

    // Optionally load shared styles if available
    if (defined('PressZone_CORE_URL')) {
        wp_enqueue_style(
            'community-press-zone-admin-shared',
            PressZone_CORE_URL . 'assets/css/community-press-zone-admin-shared.css',
            ['game-press-zone-admin'],
            PressZone_CORE_VERSION
        );
    }
}
```

---

### Phase 4: Unified Admin Menu (Priority: LOW)

**Current:** `Unified_Menu::init()` in Community Press Zone creates a central menu.

**Solution:** Each plugin registers its own menu. If Community is active, it can aggregate them.

**Pattern:**
```php
// In each plugin
add_action('admin_menu', function() {
    // If Unified Menu is available, register with it
    if (class_exists('\PressZone\Unified_Menu')) {
        \PressZone\Unified_Menu::register_tab('game', [
            'title' => 'Game',
            'callback' => [$this, 'render_page'],
        ]);
    } else {
        // Create standalone menu
        add_menu_page(
            'Game Press Zone',
            'Game',
            'manage_options',
            'game-press-zone',
            [$this, 'render_page'],
            'dashicons-awards',
            55
        );
    }
});
```

---

## Implementation Order

1. **Phase 1.1-1.5:** Remove all hard dependency checks (1-2 hours)
2. **Phase 2.1:** Create integration trait (30 mins)
3. **Phase 2.4:** Add optional XP in comments (30 mins)
4. **Phase 3.1:** Duplicate shared CSS to each plugin (1 hour)
5. **Phase 4:** Unified menu fallback (1 hour)

---

## Testing Checklist

After implementation, verify each scenario:

- [ ] Game Press Zone activates alone
- [ ] Wallet Press Zone activates alone
- [ ] Artist Press Zone activates alone
- [ ] Newsletter Press Zone activates alone
- [ ] Social Press Zone activates alone
- [ ] Forum Press Zone activates alone (already works)
- [ ] All plugins activate together without errors
- [ ] Game points work without Wallet (XP only)
- [ ] Game points work WITH Wallet (Coins enabled)
- [ ] Comments show XP when Game is active
- [ ] Comments work without Game (no XP display)
- [ ] Admin menus appear correctly in all combinations

---

## Summary

The current architecture uses `\PressZone\Core` as a **hard dependency marker**, but in reality:
- Plugins don't USE any code from Community Press Zone directly
- They only listen to hooks that may or may not fire
- The only real shared resource is CSS

**The fix is simple:** Remove the `class_exists('\PressZone\Core')` checks and let each plugin work independently. Cross-plugin features are already designed correctly with optional checks.
