# Phase 1: Detailed Implementation Plan

## Week 1: Database Foundation

### Task 1.1: Database Schema Implementation

**Required Skills:** `database-operations`
**File:** includes/Core/Database.php
**Class:** MultilingualPressZone\Core\Database

#### Sub-task 1.1.1: Class Structure & Properties

**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace `MultilingualPressZone\Core`
- [ ] Add file header with `declare(strict_types=1)`
- [ ] Add ABSPATH security check
- [ ] Add private property `$wpdb` with type hint `\wpdb`
- [ ] Add private property `$table_prefix` (string)
- [ ] Add private property `$charset_collate` (string)
- [ ] Add constant `DB_VERSION` = '1.0.0'
- [ ] Add constant `DB_VERSION_OPTION` = 'mpz_db_version'
- [ ] Add public property `$languages_table` (string)
- [ ] Add public property `$translations_table` (string)
- [ ] Add public property `$string_translations_table` (string)
- [ ] Add constructor accepting `\wpdb $wpdb`
- [ ] Constructor: Set `$this->wpdb = $wpdb`
- [ ] Constructor: Set `$this->table_prefix = $wpdb->prefix`
- [ ] Constructor: Set table names with prefix
- [ ] Constructor: Set charset/collate from `$wpdb->get_charset_collate()`
- [ ] Add private property `$last_error` (string|null)
- [ ] Add getter method `get_last_error(): ?string`

#### Sub-task 1.1.2: Table Creation - Languages Table

**Required Skills:** `database-operations`, `wpml-integration`
- [ ] Method: `create_languages_table(): bool`
- [ ] Add method docblock with @return bool
- [ ] Get table name with prefix: `{$this->table_prefix}mpz_languages`
- [ ] Build SQL: CREATE TABLE IF NOT EXISTS
- [ ] Add column: `id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY`
- [ ] Add column: `code VARCHAR(10) NOT NULL COMMENT 'Language code (en, es, fr)'`
- [ ] Add column: `locale VARCHAR(20) NOT NULL COMMENT 'Full locale (en_US, es_ES)'`
- [ ] Add column: `name VARCHAR(100) NOT NULL COMMENT 'English name'`
- [ ] Add column: `native_name VARCHAR(100) NOT NULL COMMENT 'Native name'`
- [ ] Add column: `flag_code VARCHAR(10) DEFAULT NULL COMMENT 'Flag emoji code'`
- [ ] Add column: `is_default TINYINT(1) DEFAULT 0 COMMENT '1 if default language'`
- [ ] Add column: `is_active TINYINT(1) DEFAULT 1 COMMENT '1 if active'`
- [ ] Add column: `sort_order INT(11) DEFAULT 0 COMMENT 'Display order'`
- [ ] Add column: `url_structure ENUM('subdirectory', 'subdomain', 'parameter') DEFAULT 'subdirectory'`
- [ ] Add column: `text_direction ENUM('ltr', 'rtl') DEFAULT 'ltr'`
- [ ] Add column: `created_at DATETIME NOT NULL`
- [ ] Add column: `updated_at DATETIME NOT NULL`
- [ ] Add index: `UNIQUE KEY idx_code (code)`
- [ ] Add index: `KEY idx_active (is_active)`
- [ ] Add index: `KEY idx_default (is_default)`
- [ ] Set ENGINE=InnoDB
- [ ] Append `$this->charset_collate`
- [ ] Require `wp-admin/includes/upgrade.php`
- [ ] Execute with `dbDelta($sql)`
- [ ] Check for errors with `$this->wpdb->last_error`
- [ ] Store error in `$this->last_error`
- [ ] Return false on error, true on success
- [ ] Wrap in try-catch block
- [ ] Log errors to error_log with context

#### Sub-task 1.1.3: Table Creation - Translations Table

**Required Skills:** `database-operations`, `wpml-integration`
- [ ] Method: `create_translations_table(): bool`
- [ ] Add method docblock
- [ ] Get table name: `{$this->table_prefix}mpz_translations`
- [ ] Build SQL: CREATE TABLE IF NOT EXISTS
- [ ] Add column: `id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY`
- [ ] Add column: `translation_group_id BIGINT(20) UNSIGNED NOT NULL COMMENT 'Groups related translations'`
- [ ] Add column: `element_type VARCHAR(50) NOT NULL COMMENT 'post, page, product, term'`
- [ ] Add column: `element_id BIGINT(20) UNSIGNED NOT NULL COMMENT 'Post ID, Term ID, etc'`
- [ ] Add column: `language_code VARCHAR(10) NOT NULL COMMENT 'Language of this element'`
- [ ] Add column: `source_element_id BIGINT(20) UNSIGNED DEFAULT NULL COMMENT 'Original element ID'`
- [ ] Add column: `translation_status ENUM('original', 'translated', 'needs_update', 'draft') DEFAULT 'original'`
- [ ] Add column: `content_hash VARCHAR(64) DEFAULT NULL COMMENT 'SHA256 for change detection'`
- [ ] Add column: `created_at DATETIME NOT NULL`
- [ ] Add column: `updated_at DATETIME NOT NULL`
- [ ] Add index: `UNIQUE KEY idx_element (element_type, element_id, language_code)`
- [ ] Add index: `KEY idx_group (translation_group_id)`
- [ ] Add index: `KEY idx_language (language_code)`
- [ ] Add index: `KEY idx_source (source_element_id)`
- [ ] Add index: `KEY idx_covering (element_type, language_code, element_id, translation_group_id)`
- [ ] Set ENGINE=InnoDB
- [ ] Append charset/collate
- [ ] Execute with dbDelta
- [ ] Error handling
- [ ] Return boolean
- [ ] Try-catch wrapper

#### Sub-task 1.1.4: Table Creation - String Translations Table

**Required Skills:** `database-operations`, `wpml-integration`
- [ ] Method: `create_string_translations_table(): bool`
- [ ] Add method docblock
- [ ] Get table name: `{$this->table_prefix}mpz_string_translations`
- [ ] Build SQL: CREATE TABLE IF NOT EXISTS
- [ ] Add column: `id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY`
- [ ] Add column: `string_key VARCHAR(255) NOT NULL COMMENT 'Unique identifier'`
- [ ] Add column: `context VARCHAR(100) DEFAULT 'default' COMMENT 'Domain/context'`
- [ ] Add column: `original_string TEXT NOT NULL COMMENT 'Original text'`
- [ ] Add column: `language_code VARCHAR(10) NOT NULL COMMENT 'Target language'`
- [ ] Add column: `translated_string TEXT DEFAULT NULL COMMENT 'Translation'`
- [ ] Add column: `translation_status ENUM('pending', 'translated', 'needs_review') DEFAULT 'pending'`
- [ ] Add column: `created_at DATETIME NOT NULL`
- [ ] Add column: `updated_at DATETIME NOT NULL`
- [ ] Add index: `UNIQUE KEY idx_string_lang (string_key(191), language_code, context)`
- [ ] Add index: `KEY idx_context (context)`
- [ ] Add index: `KEY idx_language (language_code)`
- [ ] Set ENGINE=InnoDB
- [ ] Append charset/collate
- [ ] Execute with dbDelta
- [ ] Error handling
- [ ] Return boolean
- [ ] Try-catch wrapper

#### Sub-task 1.1.5: Master Installation Method
- [ ] Method: `install(): bool`
- [ ] Add method docblock
- [ ] Check if tables already exist with `$wpdb->get_var("SHOW TABLES LIKE '{$table_name}'")`
- [ ] Call `create_languages_table()`
- [ ] Check return value, log if failed
- [ ] Call `create_translations_table()`
- [ ] Check return value, log if failed
- [ ] Call `create_string_translations_table()`
- [ ] Check return value, log if failed
- [ ] Update DB version option: `update_option(self::DB_VERSION_OPTION, self::DB_VERSION)`
- [ ] Return true if all successful
- [ ] Return false if any failed
- [ ] Add database transaction wrapper if supported
- [ ] Log installation timestamp

#### Sub-task 1.1.6: Database Version Management

**Required Skills:** `database-operations`
- [ ] Method: `get_installed_version(): ?string`
- [ ] Return `get_option(self::DB_VERSION_OPTION, null)`
- [ ] Method: `needs_upgrade(): bool`
- [ ] Get installed version
- [ ] Compare with `self::DB_VERSION` using version_compare
- [ ] Return true if upgrade needed
- [ ] Method: `update_version(): bool`
- [ ] Update option with current version
- [ ] Return success status
- [ ] Add filter hook: `mpz_db_version` for version override

#### Sub-task 1.1.7: Table Existence Checks

**Required Skills:** `database-operations`
- [ ] Method: `table_exists(string $table_name): bool`
- [ ] Prepare SQL: `SHOW TABLES LIKE %s`
- [ ] Execute with `$wpdb->prepare()`
- [ ] Return boolean based on result
- [ ] Method: `all_tables_exist(): bool`
- [ ] Check languages table exists
- [ ] Check translations table exists
- [ ] Check string_translations table exists
- [ ] Return true only if all exist
- [ ] Cache result in object property

#### Sub-task 1.1.8: Table Drop Methods (for uninstall)

**Required Skills:** `database-operations`
- [ ] Method: `drop_all_tables(): bool`
- [ ] Check capability: `current_user_can('manage_options')`
- [ ] Add confirmation parameter: `bool $confirm = false`
- [ ] Return false if not confirmed
- [ ] Build SQL: `DROP TABLE IF EXISTS {$table_name}`
- [ ] Execute for languages table
- [ ] Execute for translations table
- [ ] Execute for string_translations table
- [ ] Delete version option
- [ ] Return success status
- [ ] Add action hook: `mpz_before_drop_tables`
- [ ] Add action hook: `mpz_after_drop_tables`

#### Sub-task 1.1.9: Database Repair Methods

**Required Skills:** `database-operations`
- [ ] Method: `repair_tables(): array`
- [ ] Return array of repair results
- [ ] For each table: `REPAIR TABLE {$table_name}`
- [ ] Execute and capture result
- [ ] Method: `optimize_tables(): array`
- [ ] For each table: `OPTIMIZE TABLE {$table_name}`
- [ ] Execute and capture result
- [ ] Return array with success/failure per table

#### Sub-task 1.1.10: Index Verification
- [ ] Method: `verify_indexes(): array`
- [ ] Query: `SHOW INDEX FROM {$table_name}`
- [ ] Check all expected indexes exist
- [ ] Return array of missing indexes
- [ ] Method: `recreate_indexes(): bool`
- [ ] Drop existing indexes if needed
- [ ] Recreate all indexes from schema
- [ ] Return success status

### Task 1.2: Migration System

**Required Skills:** `database-operations`
**File:** includes/Core/Migrations.php
**Class:** MultilingualPressZone\Core\Migrations

#### Sub-task 1.2.1: Migration Class Structure

**Required Skills:** `database-operations`, `wordpress-php-integration`
- [ ] Define class with namespace
- [ ] Add file header with declare(strict_types=1)
- [ ] Add ABSPATH check
- [ ] Add private property `$wpdb`
- [ ] Add private property `$database` (Database instance)
- [ ] Add private property `$migrations_option` = 'mpz_applied_migrations'
- [ ] Add constructor with Database dependency injection
- [ ] Store Database instance
- [ ] Store wpdb instance

#### Sub-task 1.2.2: Migration Tracking

**Required Skills:** `database-operations`
- [ ] Method: `get_applied_migrations(): array`
- [ ] Retrieve option as array
- [ ] Return empty array if none
- [ ] Method: `mark_migration_applied(string $migration_id): bool`
- [ ] Get current applied migrations
- [ ] Add new migration ID with timestamp
- [ ] Update option
- [ ] Return success status
- [ ] Method: `is_migration_applied(string $migration_id): bool`
- [ ] Check if ID exists in applied migrations
- [ ] Return boolean

#### Sub-task 1.2.3: Migration Execution Framework

**Required Skills:** `database-operations`
- [ ] Method: `run_pending_migrations(): array`
- [ ] Get list of all migration files from includes/Migrations/
- [ ] Get list of applied migrations
- [ ] Filter to pending migrations
- [ ] Sort by version number
- [ ] Execute each migration
- [ ] Track success/failure
- [ ] Return results array
- [ ] Method: `execute_migration(string $migration_file): bool`
- [ ] Require migration file
- [ ] Instantiate migration class
- [ ] Call `up()` method
- [ ] Wrap in try-catch
- [ ] Mark as applied if successful
- [ ] Return success status

#### Sub-task 1.2.4: Rollback Support
- [ ] Method: `rollback_migration(string $migration_id): bool`
- [ ] Find migration file by ID
- [ ] Require migration file
- [ ] Instantiate migration class
- [ ] Call `down()` method
- [ ] Remove from applied migrations
- [ ] Return success status
- [ ] Wrap in try-catch

#### Sub-task 1.2.5: Migration Base Class

**Required Skills:** `database-operations`, `wordpress-php-integration`
**File:** includes/Core/AbstractMigration.php
- [ ] Define abstract class
- [ ] Add namespace
- [ ] Add protected property `$wpdb`
- [ ] Add protected property `$database`
- [ ] Add abstract method `up(): bool`
- [ ] Add abstract method `down(): bool`
- [ ] Add method `get_id(): string` (returns class name)
- [ ] Add method `get_description(): string` (returns empty, can be overridden)
- [ ] Add constructor with dependencies

#### Sub-task 1.2.6: Initial Migration - Seed Default Language

**Required Skills:** `database-operations`, `wpml-integration`
**File:** includes/Migrations/Migration_001_SeedDefaultLanguage.php
- [ ] Extend AbstractMigration
- [ ] Method: `up(): bool`
- [ ] Check if any languages exist
- [ ] If none, insert English as default
- [ ] Insert data: code='en', locale='en_US', name='English', native_name='English'
- [ ] Set is_default=1, is_active=1
- [ ] Set created_at and updated_at to current time
- [ ] Use prepared statement
- [ ] Return success status
- [ ] Method: `down(): bool`
- [ ] Delete English default language
- [ ] Return success status
- [ ] Method: `get_description(): string`
- [ ] Return "Seeds English as default language"

### Task 1.3: Plugin Activation/Deactivation
**File:** multilingual-press-zone.php (main plugin file)

#### Sub-task 1.3.1: Main Plugin File Structure
- [ ] Add plugin header comment block
- [ ] Plugin Name: Multilingual Press Zone
- [ ] Plugin URI: (to be determined)
- [ ] Description: Enterprise-grade WPML alternative, 10-100x faster
- [ ] Version: 1.0.0
- [ ] Requires at least: 6.0
- [ ] Requires PHP: 8.3
- [ ] Author: (to be determined)
- [ ] Text Domain: multilingual-press-zone
- [ ] Domain Path: /languages
- [ ] License: GPL v2 or later
- [ ] Add `declare(strict_types=1)`
- [ ] Add ABSPATH security check
- [ ] Define constant `MPZ_VERSION` = '1.0.0'
- [ ] Define constant `MPZ_PLUGIN_FILE` = __FILE__
- [ ] Define constant `MPZ_PLUGIN_DIR` = plugin_dir_path(__FILE__)
- [ ] Define constant `MPZ_PLUGIN_URL` = plugin_dir_url(__FILE__)
- [ ] Define constant `MPZ_PLUGIN_BASENAME` = plugin_basename(__FILE__)

#### Sub-task 1.3.2: Autoloader Setup
- [ ] Require Composer autoload if exists: `require_once MPZ_PLUGIN_DIR . 'vendor/autoload.php'`
- [ ] Add fallback PSR-4 autoloader function
- [ ] Register autoloader with `spl_autoload_register()`
- [ ] Map namespace `MultilingualPressZone` to `includes/` directory
- [ ] Convert namespace to file path
- [ ] Check file exists before requiring

#### Sub-task 1.3.3: Activation Hook Function

**Required Skills:** `wordpress-php-integration`
- [ ] Function: `mpz_activate()`
- [ ] Add to register_activation_hook
- [ ] Check PHP version >= 8.3
- [ ] If version check fails, deactivate and wp_die with message
- [ ] Check WordPress version >= 6.0
- [ ] If version check fails, deactivate and wp_die with message
- [ ] Check MySQL version >= 8.0
- [ ] If version check fails, deactivate and wp_die with message
- [ ] Instantiate Database class
- [ ] Call `install()` method
- [ ] Check return value
- [ ] If failed, deactivate and show error
- [ ] Instantiate Migrations class
- [ ] Run pending migrations
- [ ] Set option 'mpz_activation_time' with current timestamp
- [ ] Set option 'mpz_activation_version' with current version
- [ ] Flush rewrite rules
- [ ] Do action: `mpz_activated`

#### Sub-task 1.3.4: Deactivation Hook Function

**Required Skills:** `wordpress-php-integration`
- [ ] Function: `mpz_deactivate()`
- [ ] Add to register_deactivation_hook
- [ ] Flush rewrite rules
- [ ] Clear all caches (call CacheManager clear method)
- [ ] Set option 'mpz_deactivation_time' with timestamp
- [ ] Do action: `mpz_deactivated`
- [ ] Do NOT drop tables (preserve data)

#### Sub-task 1.3.5: Uninstall Hook

**Required Skills:** `wordpress-php-integration`
**File:** uninstall.php
- [ ] Check if 'WP_UNINSTALL_PLUGIN' is defined
- [ ] If not, exit immediately
- [ ] Require autoloader
- [ ] Instantiate Database class
- [ ] Check for option 'mpz_delete_data_on_uninstall'
- [ ] If true, call `drop_all_tables(true)` with confirmation
- [ ] Delete all plugin options with prefix 'mpz_'
- [ ] Query all options: `SELECT option_name FROM wp_options WHERE option_name LIKE 'mpz_%'`
- [ ] Delete each option
- [ ] Clear all caches
- [ ] Do action: `mpz_uninstalled`

### Task 1.4: Plugin Initialization
**File:** includes/Core/Plugin.php
**Class:** MultilingualPressZone\Core\Plugin

#### Sub-task 1.4.1: Singleton Pattern Setup
- [ ] Define class with namespace
- [ ] Add file header
- [ ] Add ABSPATH check
- [ ] Add private static property `$instance` (self|null)
- [ ] Add private constructor (prevents direct instantiation)
- [ ] Add private __clone method (prevents cloning)
- [ ] Add private __wakeup method (prevents unserialization)
- [ ] Method: `public static function get_instance(): self`
- [ ] Check if `self::$instance` is null
- [ ] If null, create new instance
- [ ] Return instance

#### Sub-task 1.4.2: Core Properties
- [ ] Add private property `$database` (Database instance)
- [ ] Add private property `$language_manager` (LanguageManager instance)
- [ ] Add private property `$content_manager` (ContentManager instance)
- [ ] Add private property `$query_optimizer` (QueryOptimizer instance)
- [ ] Add private property `$cache_manager` (CacheManager instance)
- [ ] Add private property `$url_manager` (URLManager instance)
- [ ] Add private property `$initialized` (bool) = false
- [ ] Add getter methods for each manager

#### Sub-task 1.4.3: Initialization Method
- [ ] Method: `public function init(): void`
- [ ] Check if already initialized
- [ ] If yes, return early
- [ ] Load text domain for translations
- [ ] Instantiate Database with global $wpdb
- [ ] Instantiate CacheManager
- [ ] Instantiate LanguageManager with dependencies
- [ ] Instantiate ContentManager with dependencies
- [ ] Instantiate QueryOptimizer with dependencies
- [ ] Instantiate URLManager with dependencies
- [ ] Initialize admin components if is_admin()
- [ ] Initialize frontend components if !is_admin()
- [ ] Register hooks
- [ ] Set `$initialized` = true
- [ ] Do action: `mpz_initialized`

#### Sub-task 1.4.4: Admin Initialization

**Required Skills:** `admin-panel-fullstack`
- [ ] Method: `private function init_admin(): void`
- [ ] Check `is_admin()` returns true
- [ ] Instantiate Admin\Dashboard
- [ ] Instantiate Admin\LanguageSettings
- [ ] Instantiate Admin\TranslationInterface
- [ ] Register admin menu hooks
- [ ] Enqueue admin scripts
- [ ] Enqueue admin styles
- [ ] Do action: `mpz_admin_initialized`

#### Sub-task 1.4.5: Frontend Initialization
- [ ] Method: `private function init_frontend(): void`
- [ ] Check `!is_admin()` returns true
- [ ] Instantiate Frontend\LanguageSwitcher
- [ ] Register widgets
- [ ] Register shortcodes
- [ ] Enqueue frontend scripts
- [ ] Enqueue frontend styles
- [ ] Do action: `mpz_frontend_initialized`

#### Sub-task 1.4.6: Hook Registration

**Required Skills:** `wordpress-php-integration`
- [ ] Method: `private function register_hooks(): void`
- [ ] Add action: `init` => method `load_plugin_textdomain`, priority 0
- [ ] Add action: `wp_loaded` => method `check_version_update`, priority 10
- [ ] Add action: `admin_init` => method `init_admin`, priority 10
- [ ] Add action: `wp` => method `init_frontend`, priority 10
- [ ] Add filter: `plugin_action_links_{$plugin_basename}` => method `add_action_links`
- [ ] Add filter: `plugin_row_meta` => method `add_row_meta_links`

#### Sub-task 1.4.7: Text Domain Loading
- [ ] Method: `public function load_plugin_textdomain(): void`
- [ ] Call `load_plugin_textdomain()`
- [ ] First parameter: 'multilingual-press-zone'
- [ ] Second parameter: false
- [ ] Third parameter: dirname(MPZ_PLUGIN_BASENAME) . '/languages'
- [ ] Check return value
- [ ] Log if loading failed

#### Sub-task 1.4.8: Version Update Check
- [ ] Method: `public function check_version_update(): void`
- [ ] Get installed version from option
- [ ] Compare with current MPZ_VERSION
- [ ] If different, trigger update process
- [ ] Call Migrations::run_pending_migrations()
- [ ] Update version option
- [ ] Do action: `mpz_version_updated` with old and new version

#### Sub-task 1.4.9: Plugin Links
- [ ] Method: `add_action_links(array $links): array`
- [ ] Add 'Settings' link to admin settings page
- [ ] URL: admin_url('admin.php?page=multilingual-press-zone')
- [ ] Prepend to $links array
- [ ] Return modified array
- [ ] Method: `add_row_meta_links(array $links, string $file): array`
- [ ] Check if $file matches plugin basename
- [ ] Add 'Documentation' link
- [ ] Add 'Support' link
- [ ] Add 'Rate Plugin' link
- [ ] Append to $links array
- [ ] Return modified array

#### Sub-task 1.4.10: Bootstrap in Main Plugin File
**File:** multilingual-press-zone.php
- [ ] After autoloader, add: `add_action('plugins_loaded', 'mpz_init', 10)`
- [ ] Function: `mpz_init()`
- [ ] Get Plugin instance: `$plugin = Plugin::get_instance()`
- [ ] Call `$plugin->init()`
- [ ] Wrap in try-catch
- [ ] Log errors if initialization fails

### Task 1.5: Composer and Dependencies
**File:** composer.json

#### Sub-task 1.5.1: Composer Configuration

**Required Skills:** `settings-management`
- [ ] Create composer.json in plugin root
- [ ] Set name: "presszone/multilingual-press-zone"
- [ ] Set description: "Enterprise-grade WPML alternative"
- [ ] Set type: "wordpress-plugin"
- [ ] Set license: "GPL-2.0-or-later"
- [ ] Set minimum-stability: "stable"
- [ ] Set require: PHP ^8.3
- [ ] Set require-dev: phpunit/phpunit ^10.0
- [ ] Set require-dev: wp-coding-standards/wpcs ^3.0
- [ ] Set require-dev: phpstan/phpstan ^1.10
- [ ] Configure autoload PSR-4: "MultilingualPressZone\\": "includes/"
- [ ] Configure autoload-dev PSR-4 for tests
- [ ] Add scripts for phpcs, phpstan, phpunit

#### Sub-task 1.5.2: Run Composer Install
- [ ] Execute: `composer install --no-dev` for production
- [ ] Execute: `composer install` for development
- [ ] Verify vendor directory created
- [ ] Verify autoload files generated

### Task 1.6: License Management
**Required Skills:** `settings-management`, `api-integration`
**File:** includes/Core/LicenseManager.php
**Class:** MultilingualPressZone\Core\LicenseManager

#### Sub-task 1.6.1: License Class Structure
**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace `MultilingualPressZone\Core`
- [ ] Add properties: `$api_url`, `$license_key`, `$status`
- [ ] Constructor: Load license key from options
- [ ] Method: `activate(string $key): bool` - Call Backend API
- [ ] Method: `deactivate(): bool`
- [ ] Method: `check_status(): string`

#### Sub-task 1.6.2: Admin UI Integration
**Required Skills:** `admin-panel-fullstack`
- [ ] Register setting: `presszone_multilingual_license_key`
- [ ] Add License Field to Settings Page
- [ ] Add "Activate" button with AJAX handler
- [ ] Display license status (Active/Expired)
- [ ] Handle API response from Backend (`/v1/licenses/activate`)

---

## Week 2: Core Managers

### Task 2.1: Cache Manager Implementation
**File:** includes/Core/CacheManager.php
**Class:** MultilingualPressZone\Core\CacheManager

#### Sub-task 2.1.1: Class Structure & Cache Layers

**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace
- [ ] Add file header
- [ ] Add ABSPATH check
- [ ] Define constant `CACHE_GROUP` = 'mpz'
- [ ] Define constant `MEMORY_CACHE_SIZE` = 1000
- [ ] Define constant `DEFAULT_TTL` = 3600 (1 hour)
- [ ] Add private property `$memory_cache` (array)
- [ ] Add private property `$memory_cache_hits` (int)
- [ ] Add private property `$memory_cache_misses` (int)
- [ ] Add private property `$object_cache_hits` (int)
- [ ] Add private property `$object_cache_misses` (int)
- [ ] Add private property `$use_object_cache` (bool)
- [ ] Add private property `$use_transients` (bool)
- [ ] Constructor: Initialize memory cache as empty array
- [ ] Constructor: Check if object cache available with `wp_using_ext_object_cache()`
- [ ] Constructor: Set flags accordingly

#### Sub-task 2.1.2: Cache Key Generation
- [ ] Method: `generate_key(string $prefix, ...$parts): string`
- [ ] Concatenate prefix with all parts
- [ ] Use separator: ':'
- [ ] Example: "languages:all:active"
- [ ] Hash long keys with md5 if > 172 chars (Redis limit)
- [ ] Return sanitized cache key
- [ ] Method: `sanitize_key(string $key): string`
- [ ] Remove special characters
- [ ] Convert to lowercase
- [ ] Limit length to 172 characters

#### Sub-task 2.1.3: Memory Cache (Layer 1)
- [ ] Method: `get_from_memory(string $key): mixed`
- [ ] Check if key exists in `$this->memory_cache`
- [ ] If exists, increment hits counter
- [ ] Return value
- [ ] If not exists, increment misses counter
- [ ] Return null
- [ ] Method: `set_in_memory(string $key, mixed $value): void`
- [ ] Check if memory cache size exceeds limit
- [ ] If yes, remove oldest entries (FIFO)
- [ ] Store key => value in array
- [ ] Store timestamp for age tracking
- [ ] Method: `delete_from_memory(string $key): void`
- [ ] Unset key from array

#### Sub-task 2.1.4: Object Cache (Layer 2 - Redis/Memcached)
- [ ] Method: `get_from_object_cache(string $key): mixed`
- [ ] Check if object cache is available
- [ ] Call `wp_cache_get($key, self::CACHE_GROUP)`
- [ ] If found, increment hits counter
- [ ] Return value
- [ ] If not found, increment misses counter
- [ ] Return false
- [ ] Method: `set_in_object_cache(string $key, mixed $value, int $ttl = self::DEFAULT_TTL): bool`
- [ ] Check if object cache available
- [ ] Call `wp_cache_set($key, $value, self::CACHE_GROUP, $ttl)`
- [ ] Return success status
- [ ] Method: `delete_from_object_cache(string $key): bool`
- [ ] Call `wp_cache_delete($key, self::CACHE_GROUP)`
- [ ] Return success status

#### Sub-task 2.1.5: Transient Cache (Layer 3 - Database)

**Required Skills:** `database-operations`
- [ ] Method: `get_from_transient(string $key): mixed`
- [ ] Build transient key: "mpz_{$key}"
- [ ] Call `get_transient($transient_key)`
- [ ] Return value or false
- [ ] Method: `set_in_transient(string $key, mixed $value, int $ttl = self::DEFAULT_TTL): bool`
- [ ] Build transient key: "mpz_{$key}"
- [ ] Call `set_transient($transient_key, $value, $ttl)`
- [ ] Return success status
- [ ] Method: `delete_transient(string $key): bool`
- [ ] Build transient key: "mpz_{$key}"
- [ ] Call `delete_transient($transient_key)`
- [ ] Return success status

#### Sub-task 2.1.6: Unified Get Method (Cascading)
- [ ] Method: `get(string $key, callable $callback = null, int $ttl = self::DEFAULT_TTL): mixed`
- [ ] Try Layer 1: Check memory cache
- [ ] If found, return value immediately
- [ ] Try Layer 2: Check object cache
- [ ] If found, populate memory cache
- [ ] Return value
- [ ] Try Layer 3: Check transient cache
- [ ] If found, populate object cache and memory cache
- [ ] Return value
- [ ] If all miss and callback provided:
- [ ] Execute callback to generate value
- [ ] Store in all cache layers
- [ ] Return generated value
- [ ] If no callback, return null

#### Sub-task 2.1.7: Unified Set Method
- [ ] Method: `set(string $key, mixed $value, int $ttl = self::DEFAULT_TTL): bool`
- [ ] Set in memory cache
- [ ] Set in object cache if available
- [ ] Set in transient cache
- [ ] Return true if at least one succeeded
- [ ] Log any failures

#### Sub-task 2.1.8: Unified Delete Method
- [ ] Method: `delete(string $key): bool`
- [ ] Delete from memory cache
- [ ] Delete from object cache
- [ ] Delete from transient cache
- [ ] Return true if all succeeded
- [ ] Log any failures

#### Sub-task 2.1.9: Bulk Operations
- [ ] Method: `get_multiple(array $keys): array`
- [ ] Accept array of cache keys
- [ ] Return associative array: key => value
- [ ] Use cascading lookup for each key
- [ ] Optimize with single object cache call if possible
- [ ] Method: `set_multiple(array $items, int $ttl = self::DEFAULT_TTL): bool`
- [ ] Accept array: key => value
- [ ] Set each in all cache layers
- [ ] Return true if all succeeded
- [ ] Method: `delete_multiple(array $keys): bool`
- [ ] Delete each key from all layers
- [ ] Return true if all succeeded

#### Sub-task 2.1.10: Pattern-Based Deletion
- [ ] Method: `delete_by_pattern(string $pattern): int`
- [ ] Clear matching keys from memory cache
- [ ] If object cache supports it, use flush by pattern
- [ ] Query database for matching transient keys
- [ ] Use SQL: `SELECT option_name FROM wp_options WHERE option_name LIKE '_transient_mpz_{$pattern}%'`
- [ ] Delete each matching transient
- [ ] Return count of deleted items
- [ ] Method: `delete_by_prefix(string $prefix): int`
- [ ] Call `delete_by_pattern()` with prefix wildcard

#### Sub-task 2.1.11: Cache Invalidation
- [ ] Method: `invalidate_language_cache(string $language_code = null): void`
- [ ] If language_code provided, delete specific language caches
- [ ] Delete: "language:{$code}"
- [ ] Delete: "language_by_locale:{$locale}"
- [ ] If null, delete all language caches
- [ ] Delete by prefix: "language"
- [ ] Delete by prefix: "languages"
- [ ] Method: `invalidate_translation_cache(int $element_id, string $element_type): void`
- [ ] Delete: "translation:{$element_type}:{$element_id}"
- [ ] Delete: "translation_group:{$element_type}:{$element_id}"
- [ ] Delete by prefix: "translations:{$element_type}"
- [ ] Method: `invalidate_all(): void`
- [ ] Clear memory cache completely
- [ ] Flush object cache group: `wp_cache_flush_group(self::CACHE_GROUP)`
- [ ] Delete all transients with prefix "mpz_"
- [ ] Reset statistics counters

#### Sub-task 2.1.12: Cache Warming
- [ ] Method: `warm_cache(): void`
- [ ] Load all active languages
- [ ] Cache each language individually
- [ ] Load language code => ID map
- [ ] Cache the map
- [ ] Pre-cache common queries
- [ ] Log warming completion time
- [ ] Method: `warm_language_cache(): void`
- [ ] Query all active languages from database
- [ ] Store each in cache
- [ ] Method: `warm_translation_cache(int $element_id, string $element_type): void`
- [ ] Load all translations for element
- [ ] Cache translation group
- [ ] Cache each individual translation

#### Sub-task 2.1.13: Statistics & Monitoring
- [ ] Method: `get_stats(): array`
- [ ] Return array with hit/miss counts
- [ ] Calculate hit ratio
- [ ] Include memory cache size
- [ ] Include object cache status
- [ ] Method: `reset_stats(): void`
- [ ] Reset all counters to zero
- [ ] Method: `get_memory_usage(): int`
- [ ] Calculate size of memory cache array
- [ ] Return bytes
- [ ] Method: `get_cache_info(): array`
- [ ] Return comprehensive cache status
- [ ] Include backend types available
- [ ] Include cache sizes
- [ ] Include hit ratios

#### Sub-task 2.1.14: Debug & Logging
- [ ] Method: `enable_debug_mode(): void`
- [ ] Set private property `$debug_mode` = true
- [ ] Method: `log_cache_operation(string $operation, string $key, bool $success): void`
- [ ] Only log if debug mode enabled
- [ ] Write to debug.log with timestamp
- [ ] Include operation type, key, success status
- [ ] Method: `get_debug_log(): array`
- [ ] Return array of recent operations
- [ ] Store last 100 operations in memory

### Task 2.2: Language Manager Implementation

**Required Skills:** `wpml-integration`
**File:** includes/Core/LanguageManager.php
**Class:** MultilingualPressZone\Core\LanguageManager

#### Sub-task 2.2.1: Class Structure & Dependencies

**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace
- [ ] Add file header
- [ ] Add ABSPATH check
- [ ] Add private property `$wpdb` (\wpdb)
- [ ] Add private property `$cache_manager` (CacheManager)
- [ ] Add private property `$table_name` (string)
- [ ] Add private property `$default_language` (object|null)
- [ ] Add private property `$active_languages` (array|null)
- [ ] Constructor: Accept $wpdb and CacheManager
- [ ] Constructor: Set table name from $wpdb->prefix
- [ ] Constructor: Initialize default language as null

#### Sub-task 2.2.2: Language Entity Class

**Required Skills:** `wordpress-php-integration`, `wpml-integration`
**File:** includes/Entities/Language.php
- [ ] Define class with namespace
- [ ] Add public property `$id` (int)
- [ ] Add public property `$code` (string)
- [ ] Add public property `$locale` (string)
- [ ] Add public property `$name` (string)
- [ ] Add public property `$native_name` (string)
- [ ] Add public property `$flag_code` (string|null)
- [ ] Add public property `$is_default` (bool)
- [ ] Add public property `$is_active` (bool)
- [ ] Add public property `$sort_order` (int)
- [ ] Add public property `$url_structure` (string)
- [ ] Add public property `$text_direction` (string)
- [ ] Add public property `$created_at` (string)
- [ ] Add public property `$updated_at` (string)
- [ ] Method: `to_array(): array`
- [ ] Convert all properties to array
- [ ] Return array
- [ ] Method: `static from_db_row(object $row): self`
- [ ] Create new instance from database row
- [ ] Map all database columns to properties
- [ ] Cast types appropriately
- [ ] Return instance

#### Sub-task 2.2.3: Get Language by Code

**Required Skills:** `wpml-integration`
- [ ] Method: `get_language_by_code(string $code): ?Language`
- [ ] Add parameter validation: code not empty
- [ ] Sanitize code: lowercase, alphanumeric only
- [ ] Generate cache key: "language:{$code}"
- [ ] Try to get from cache
- [ ] If cached, return Language entity
- [ ] If not cached, query database
- [ ] SQL: `SELECT * FROM {$table_name} WHERE code = %s LIMIT 1`
- [ ] Prepare statement with $wpdb->prepare()
- [ ] Execute with $wpdb->get_row()
- [ ] If found, convert to Language entity
- [ ] Store in cache
- [ ] Return Language entity
- [ ] If not found, return null
- [ ] Add filter hook: `mpz_get_language_by_code` with language object

#### Sub-task 2.2.4: Get Language by ID

**Required Skills:** `wpml-integration`
- [ ] Method: `get_language_by_id(int $id): ?Language`
- [ ] Add parameter validation: id > 0
- [ ] Generate cache key: "language_by_id:{$id}"
- [ ] Try to get from cache
- [ ] If cached, return Language entity
- [ ] If not cached, query database
- [ ] SQL: `SELECT * FROM {$table_name} WHERE id = %d LIMIT 1`
- [ ] Prepare and execute
- [ ] Convert to Language entity
- [ ] Store in cache
- [ ] Return Language or null
- [ ] Add filter hook: `mpz_get_language_by_id`

#### Sub-task 2.2.5: Get Language by Locale

**Required Skills:** `wpml-integration`
- [ ] Method: `get_language_by_locale(string $locale): ?Language`
- [ ] Add parameter validation: locale not empty
- [ ] Sanitize locale
- [ ] Generate cache key: "language_by_locale:{$locale}"
- [ ] Try cache first
- [ ] Query database if not cached
- [ ] SQL: `SELECT * FROM {$table_name} WHERE locale = %s LIMIT 1`
- [ ] Convert to Language entity
- [ ] Cache result
- [ ] Return Language or null

#### Sub-task 2.2.6: Get All Languages

**Required Skills:** `wpml-integration`
- [ ] Method: `get_all_languages(bool $active_only = false): array`
- [ ] Generate cache key based on $active_only
- [ ] If active_only: "languages:active"
- [ ] If all: "languages:all"
- [ ] Try to get from cache
- [ ] If cached, return array of Language entities
- [ ] If not cached, build SQL query
- [ ] Base: `SELECT * FROM {$table_name}`
- [ ] If active_only: add `WHERE is_active = 1`
- [ ] Add: `ORDER BY sort_order ASC, name ASC`
- [ ] Execute query with $wpdb->get_results()
- [ ] Convert each row to Language entity
- [ ] Store in cache
- [ ] Return array
- [ ] Add filter hook: `mpz_get_all_languages` with array

#### Sub-task 2.2.7: Get Default Language

**Required Skills:** `wpml-integration`
- [ ] Method: `get_default_language(): ?Language`
- [ ] Check if already loaded in `$this->default_language`
- [ ] If yes, return cached value
- [ ] Generate cache key: "language:default"
- [ ] Try to get from cache
- [ ] If not cached, query database
- [ ] SQL: `SELECT * FROM {$table_name} WHERE is_default = 1 LIMIT 1`
- [ ] Execute query
- [ ] Convert to Language entity
- [ ] Store in `$this->default_language`
- [ ] Store in cache
- [ ] Return Language
- [ ] If none found, log error (critical issue)
- [ ] Add filter hook: `mpz_default_language`

#### Sub-task 2.2.8: Create Language

**Required Skills:** `wpml-integration`
- [ ] Method: `create_language(array $data): int|false`
- [ ] Validate required fields: code, locale, name, native_name
- [ ] Check code format: 2-10 chars, alphanumeric + underscore
- [ ] Check locale format: valid locale string
- [ ] Sanitize all input fields
- [ ] code: sanitize_key()
- [ ] locale: sanitize_text_field()
- [ ] name: sanitize_text_field()
- [ ] native_name: sanitize_text_field()
- [ ] flag_code: sanitize_text_field()
- [ ] Check if code already exists
- [ ] If exists, return false and set error
- [ ] Prepare data array for insertion
- [ ] Set created_at: current_time('mysql')
- [ ] Set updated_at: current_time('mysql')
- [ ] Set defaults: is_default=0, is_active=1, sort_order=0
- [ ] Set url_structure default: 'subdirectory'
- [ ] Set text_direction default: 'ltr'
- [ ] Execute insert: `$wpdb->insert($table_name, $data)`
- [ ] Get inserted ID: `$wpdb->insert_id`
- [ ] If insert failed, return false
- [ ] Invalidate language caches
- [ ] Do action: `mpz_language_created` with ID and data
- [ ] Return inserted ID
- [ ] Add transaction wrapper if supported

#### Sub-task 2.2.9: Update Language

**Required Skills:** `wpml-integration`
- [ ] Method: `update_language(int $id, array $data): bool`
- [ ] Validate ID > 0
- [ ] Check if language exists
- [ ] If not exists, return false
- [ ] Get existing language data
- [ ] Sanitize all provided fields
- [ ] Validate code uniqueness if code is being changed
- [ ] Query for duplicate: exclude current ID
- [ ] If duplicate, return false
- [ ] Set updated_at: current_time('mysql')
- [ ] Remove fields that cannot be updated (id, created_at)
- [ ] Prepare WHERE clause: ['id' => $id]
- [ ] Execute update: `$wpdb->update($table_name, $data, $where)`
- [ ] Check affected rows
- [ ] If update failed, return false
- [ ] Invalidate language caches for this ID and code
- [ ] Do action: `mpz_language_updated` with ID, new data, old data
- [ ] Return true

#### Sub-task 2.2.10: Delete Language

**Required Skills:** `wpml-integration`
- [ ] Method: `delete_language(int $id): bool`
- [ ] Validate ID > 0
- [ ] Check if language exists
- [ ] Get language data before deletion
- [ ] Check if it's the default language
- [ ] If default, return false (cannot delete default)
- [ ] Check if language has translations
- [ ] Query translation count from mpz_translations
- [ ] If translations exist, optionally prevent deletion or reassign
- [ ] Add filter: `mpz_allow_language_deletion` to control behavior
- [ ] Execute delete: `$wpdb->delete($table_name, ['id' => $id])`
- [ ] Check affected rows
- [ ] If delete failed, return false
- [ ] Invalidate all language caches
- [ ] Do action: `mpz_language_deleted` with ID and data
- [ ] Return true

#### Sub-task 2.2.11: Set Default Language

**Required Skills:** `wpml-integration`
- [ ] Method: `set_default_language(int $id): bool`
- [ ] Validate ID > 0
- [ ] Check if language exists and is active
- [ ] If not active, return false
- [ ] Start transaction if supported
- [ ] Update all languages: set is_default = 0
- [ ] SQL: `UPDATE {$table_name} SET is_default = 0`
- [ ] Update target language: set is_default = 1
- [ ] SQL: `UPDATE {$table_name} SET is_default = 1 WHERE id = %d`
- [ ] Check if updates succeeded
- [ ] Commit transaction
- [ ] If failed, rollback
- [ ] Clear default language cache
- [ ] Reload `$this->default_language`
- [ ] Do action: `mpz_default_language_changed` with new ID
- [ ] Return success status

#### Sub-task 2.2.12: Toggle Language Active Status

**Required Skills:** `wpml-integration`
- [ ] Method: `toggle_language_active(int $id, bool $is_active): bool`
- [ ] Validate ID > 0
- [ ] Check if language exists
- [ ] Get current language data
- [ ] If it's default language and trying to deactivate, return false
- [ ] Update is_active field
- [ ] Call `update_language()` with new status
- [ ] Invalidate active languages cache
- [ ] Do action: `mpz_language_active_toggled` with ID and status
- [ ] Return success status

#### Sub-task 2.2.13: Reorder Languages

**Required Skills:** `wpml-integration`
- [ ] Method: `reorder_languages(array $language_ids_in_order): bool`
- [ ] Validate array not empty
- [ ] Validate all IDs are integers > 0
- [ ] Start transaction
- [ ] Loop through array with index
- [ ] Update each language's sort_order = index
- [ ] SQL: `UPDATE {$table_name} SET sort_order = %d WHERE id = %d`
- [ ] Check all updates succeeded
- [ ] Commit transaction
- [ ] If any failed, rollback
- [ ] Invalidate language caches
- [ ] Do action: `mpz_languages_reordered`
- [ ] Return success status

#### Sub-task 2.2.14: Validation Methods
- [ ] Method: `validate_language_code(string $code): bool`
- [ ] Check length: 2-10 characters
- [ ] Check format: alphanumeric and underscore only
- [ ] Check against reserved codes (if any)
- [ ] Return boolean
- [ ] Method: `validate_locale(string $locale): bool`
- [ ] Check format: language_COUNTRY (e.g., en_US)
- [ ] Use regex: `/^[a-z]{2,3}_[A-Z]{2}$/`
- [ ] Return boolean
- [ ] Method: `language_code_exists(string $code, int $exclude_id = null): bool`
- [ ] Query for existing code
- [ ] Exclude specific ID if provided
- [ ] Return boolean

#### Sub-task 2.2.15: Language URL Structure

**Required Skills:** `wpml-integration`
- [ ] Method: `get_language_url_prefix(string $code): string`
- [ ] Get language by code
- [ ] Check url_structure setting
- [ ] If 'subdirectory': return "/{$code}"
- [ ] If 'parameter': return "?lang={$code}"
- [ ] If 'subdomain': return "{$code}."
- [ ] Apply filter: `mpz_language_url_prefix`
- [ ] Return prefix string

#### Sub-task 2.2.16: Bulk Import Languages

**Required Skills:** `wpml-integration`
- [ ] Method: `import_languages(array $languages_data): array`
- [ ] Accept array of language data arrays
- [ ] Validate structure of each entry
- [ ] Track success and failure counts
- [ ] Loop through each language
- [ ] Try to create language
- [ ] Catch validation errors
- [ ] Store error messages
- [ ] Return results array: ['success' => count, 'failed' => count, 'errors' => []]
- [ ] Do action: `mpz_languages_imported` with results

#### Sub-task 2.2.17: Get Language Statistics

**Required Skills:** `wpml-integration`
- [ ] Method: `get_language_stats(int $language_id): array`
- [ ] Query count of translations for language
- [ ] Query count of original content in language
- [ ] Query count of content needing update
- [ ] Query count of draft translations
- [ ] Return associative array with all stats
- [ ] Cache results with short TTL (5 minutes)

### Task 2.3: Content Manager Implementation
**File:** includes/Core/ContentManager.php
**Class:** MultilingualPressZone\Core\ContentManager

#### Sub-task 2.3.1: Class Structure & Dependencies

**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace
- [ ] Add file header
- [ ] Add ABSPATH check
- [ ] Add private property `$wpdb` (\wpdb)
- [ ] Add private property `$cache_manager` (CacheManager)
- [ ] Add private property `$language_manager` (LanguageManager)
- [ ] Add private property `$translations_table` (string)
- [ ] Add private property `$current_language` (string|null)
- [ ] Constructor: Accept dependencies
- [ ] Constructor: Set translations table name
- [ ] Constructor: Initialize current language as null

#### Sub-task 2.3.2: Translation Entity Class

**Required Skills:** `wordpress-php-integration`, `wpml-integration`
**File:** includes/Entities/Translation.php
- [ ] Define class with namespace
- [ ] Add public property `$id` (int)
- [ ] Add public property `$translation_group_id` (int)
- [ ] Add public property `$element_type` (string)
- [ ] Add public property `$element_id` (int)
- [ ] Add public property `$language_code` (string)
- [ ] Add public property `$source_element_id` (int|null)
- [ ] Add public property `$translation_status` (string)
- [ ] Add public property `$content_hash` (string|null)
- [ ] Add public property `$created_at` (string)
- [ ] Add public property `$updated_at` (string)
- [ ] Method: `to_array(): array`
- [ ] Method: `static from_db_row(object $row): self`
- [ ] Map database columns to properties
- [ ] Cast types appropriately

#### Sub-task 2.3.3: Get Current Language

**Required Skills:** `wpml-integration`
- [ ] Method: `get_current_language(): string`
- [ ] If `$this->current_language` is set, return it
- [ ] Check query var: `get_query_var('language')`
- [ ] Check cookie: `$_COOKIE['mpz_language']`
- [ ] Check browser language from HTTP_ACCEPT_LANGUAGE
- [ ] Parse and match against available languages
- [ ] Fallback to default language
- [ ] Store in `$this->current_language`
- [ ] Apply filter: `mpz_current_language`
- [ ] Return language code

#### Sub-task 2.3.4: Set Current Language

**Required Skills:** `wpml-integration`
- [ ] Method: `set_current_language(string $code): bool`
- [ ] Validate language code exists
- [ ] Validate language is active
- [ ] Set `$this->current_language` = $code
- [ ] Set cookie: `setcookie('mpz_language', $code, time() + YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN)`
- [ ] Do action: `mpz_language_switched` with old and new code
- [ ] Return true

#### Sub-task 2.3.5: Get Translation by Element

**Required Skills:** `wpml-integration`
- [ ] Method: `get_translation(int $element_id, string $element_type, string $language_code): ?Translation`
- [ ] Validate parameters: element_id > 0, element_type not empty, language_code not empty
- [ ] Sanitize element_type: alphanumeric and underscore
- [ ] Generate cache key: "translation:{$element_type}:{$element_id}:{$language_code}"
- [ ] Try to get from cache
- [ ] If cached, return Translation entity
- [ ] If not cached, query database
- [ ] SQL: `SELECT * FROM {$table} WHERE element_id = %d AND element_type = %s AND language_code = %s LIMIT 1`
- [ ] Prepare statement
- [ ] Execute query
- [ ] Convert to Translation entity
- [ ] Cache result
- [ ] Return Translation or null

#### Sub-task 2.3.6: Get Translation Group

**Required Skills:** `wpml-integration`
- [ ] Method: `get_translation_group(int $element_id, string $element_type): array`
- [ ] Validate parameters
- [ ] Get translation entry for given element
- [ ] If not found, return empty array
- [ ] Get translation_group_id from entry
- [ ] Generate cache key: "translation_group:{$element_type}:{$element_id}"
- [ ] Try cache first
- [ ] Query all translations with same group ID
- [ ] SQL: `SELECT * FROM {$table} WHERE translation_group_id = %d`
- [ ] Convert to Translation entities
- [ ] Build associative array: language_code => Translation
- [ ] Cache result
- [ ] Return array

#### Sub-task 2.3.7: Create Translation Link

**Required Skills:** `wpml-integration`
- [ ] Method: `create_translation(int $element_id, string $element_type, string $language_code, ?int $source_element_id = null): int|false`
- [ ] Validate all parameters
- [ ] Check if translation already exists
- [ ] If exists, return false or update
- [ ] Determine translation_group_id
- [ ] If source_element_id provided, get source's group ID
- [ ] If no source, generate new group ID
- [ ] Calculate content hash for change detection
- [ ] Get element content based on type
- [ ] Hash with hash('sha256', $content)
- [ ] Determine translation_status
- [ ] If source_element_id is null: 'original'
- [ ] If source provided: 'draft'
- [ ] Prepare data for insertion
- [ ] Set created_at and updated_at
- [ ] Execute insert: `$wpdb->insert($table, $data)`
- [ ] Get insert ID
- [ ] Invalidate translation caches
- [ ] Do action: `mpz_translation_created` with ID and data
- [ ] Return inserted ID

#### Sub-task 2.3.8: Update Translation Link

**Required Skills:** `wpml-integration`
- [ ] Method: `update_translation(int $translation_id, array $data): bool`
- [ ] Validate translation_id > 0
- [ ] Check translation exists
- [ ] Get existing translation data
- [ ] Sanitize provided fields
- [ ] Validate translation_status if provided (must be valid enum value)
- [ ] Set updated_at: current_time('mysql')
- [ ] Remove immutable fields (id, translation_group_id, created_at)
- [ ] Execute update: `$wpdb->update($table, $data, ['id' => $translation_id])`
- [ ] Check affected rows
- [ ] Invalidate translation caches
- [ ] Do action: `mpz_translation_updated`
- [ ] Return success status

#### Sub-task 2.3.9: Delete Translation Link

**Required Skills:** `wpml-integration`
- [ ] Method: `delete_translation(int $element_id, string $element_type, string $language_code): bool`
- [ ] Validate parameters
- [ ] Get translation entry
- [ ] If not exists, return false
- [ ] Check if it's an original (source for others)
- [ ] Query if any translations reference this as source
- [ ] If yes, either prevent deletion or unlink them
- [ ] Execute delete: `$wpdb->delete($table, ['element_id' => $element_id, 'element_type' => $element_type, 'language_code' => $language_code])`
- [ ] Check affected rows
- [ ] Invalidate translation caches
- [ ] Do action: `mpz_translation_deleted`
- [ ] Return success status

#### Sub-task 2.3.10: Link Translations Together

**Required Skills:** `wpml-integration`
- [ ] Method: `link_translations(array $translation_ids): bool`
- [ ] Accept array of translation IDs to link as group
- [ ] Validate all IDs exist
- [ ] Get all translation entries
- [ ] Check element_types match (can only link same type)
- [ ] Generate new translation_group_id
- [ ] Use max existing ID + 1, or timestamp-based
- [ ] Determine which is the original
- [ ] Either user-specified or first in array
- [ ] Start transaction
- [ ] Update all translations with new group_id
- [ ] Set source_element_id appropriately
- [ ] Commit transaction
- [ ] Invalidate all affected caches
- [ ] Do action: `mpz_translations_linked`
- [ ] Return success status

#### Sub-task 2.3.11: Unlink Translation

**Required Skills:** `wpml-integration`
- [ ] Method: `unlink_translation(int $element_id, string $element_type): bool`
- [ ] Get translation entry
- [ ] Generate new unique translation_group_id for this element
- [ ] Update translation with new group_id
- [ ] Set source_element_id to null
- [ ] Set translation_status to 'original'
- [ ] Invalidate caches
- [ ] Do action: `mpz_translation_unlinked`
- [ ] Return success status

#### Sub-task 2.3.12: Get Element Language

**Required Skills:** `wpml-integration`
- [ ] Method: `get_element_language(int $element_id, string $element_type): ?string`
- [ ] Query for translation entry
- [ ] If found, return language_code
- [ ] If not found, return default language code
- [ ] Cache result

#### Sub-task 2.3.13: Get Translated Element ID
- [ ] Method: `get_translated_element_id(int $element_id, string $element_type, string $target_language): ?int`
- [ ] Get translation group for element
- [ ] Check if target language exists in group
- [ ] If yes, return element_id for that language
- [ ] If no, return null
- [ ] Cache result with key including all parameters

#### Sub-task 2.3.14: Get Untranslated Elements
- [ ] Method: `get_untranslated_elements(string $element_type, string $target_language, int $limit = 20, int $offset = 0): array`
- [ ] Query elements of type that don't have translation in target language
- [ ] SQL: Complex query with LEFT JOIN
- [ ] Join wp_posts (or wp_terms) with translations table
- [ ] WHERE translation is NULL for target language
- [ ] Add LIMIT and OFFSET for pagination
- [ ] Return array of element IDs
- [ ] Include count of total untranslated items

#### Sub-task 2.3.15: Content Hash Management
- [ ] Method: `generate_content_hash(int $element_id, string $element_type): string`
- [ ] Get element content based on type
- [ ] For posts: get post_content, post_title, post_excerpt
- [ ] For terms: get name, description
- [ ] Concatenate all content
- [ ] Generate SHA256 hash
- [ ] Return hash string
- [ ] Method: `check_content_modified(int $element_id, string $element_type, string $language_code): bool`
- [ ] Get translation entry
- [ ] Get stored content_hash
- [ ] Generate current content hash
- [ ] Compare hashes
- [ ] If different, return true (modified)
- [ ] If same, return false (not modified)

#### Sub-task 2.3.16: Mark Translation as Needs Update

**Required Skills:** `wpml-integration`
- [ ] Method: `mark_needs_update(int $element_id, string $element_type): int`
- [ ] Get translation group for element
- [ ] Loop through all translations except original
- [ ] Update translation_status to 'needs_update'
- [ ] Update content_hash to current hash
- [ ] Invalidate caches
- [ ] Return count of marked translations
- [ ] Do action: `mpz_translations_marked_needs_update`

#### Sub-task 2.3.17: Bulk Translation Operations

**Required Skills:** `wpml-integration`
- [ ] Method: `bulk_create_translations(array $items): array`
- [ ] Accept array of: ['element_id' => X, 'element_type' => Y, 'language_code' => Z]
- [ ] Loop through each item
- [ ] Try to create translation
- [ ] Track successes and failures
- [ ] Return results array with counts
- [ ] Method: `bulk_delete_translations(array $translation_ids): int`
- [ ] Accept array of translation IDs
- [ ] Use single SQL DELETE with IN clause
- [ ] Return count of deleted rows
- [ ] Invalidate caches

#### Sub-task 2.3.18: Translation Statistics

**Required Skills:** `wpml-integration`
- [ ] Method: `get_translation_stats(string $element_type = null): array`
- [ ] Query counts by status
- [ ] Count 'original' translations
- [ ] Count 'translated' translations
- [ ] Count 'needs_update' translations
- [ ] Count 'draft' translations
- [ ] If element_type specified, filter by type
- [ ] Return associative array with all counts
- [ ] Cache with short TTL

#### Sub-task 2.3.19: WordPress Post Integration
- [ ] Method: `sync_post_translation(int $post_id): void`
- [ ] Get post language (from query or default)
- [ ] Check if translation entry exists
- [ ] If not, create it
- [ ] Calculate content hash
- [ ] Update content hash if changed
- [ ] If original post changed, mark translations as needs_update
- [ ] Hook this method to 'save_post' action

#### Sub-task 2.3.20: WordPress Term Integration
- [ ] Method: `sync_term_translation(int $term_id, string $taxonomy): void`
- [ ] Similar logic to post sync
- [ ] Create/update translation entry for term
- [ ] Handle taxonomy in element_type: "term_{$taxonomy}"
- [ ] Hook to 'saved_term' action

### Task 2.4: Query Optimizer Implementation

**Required Skills:** `database-operations`
**File:** includes/Core/QueryOptimizer.php
**Class:** MultilingualPressZone\Core\QueryOptimizer

#### Sub-task 2.4.1: Class Structure & Dependencies

**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace
- [ ] Add file header
- [ ] Add ABSPATH check
- [ ] Add private property `$wpdb` (\wpdb)
- [ ] Add private property `$cache_manager` (CacheManager)
- [ ] Add private property `$content_manager` (ContentManager)
- [ ] Add private property `$language_manager` (LanguageManager)
- [ ] Add private property `$current_language` (string|null)
- [ ] Add private property `$query_count` (int) for monitoring
- [ ] Constructor: Accept all dependencies
- [ ] Constructor: Initialize query count to 0

#### Sub-task 2.4.2: Hook Registration

**Required Skills:** `wordpress-php-integration`
- [ ] Method: `register_hooks(): void`
- [ ] Add filter: `pre_get_posts`, priority 10
- [ ] Add filter: `the_posts`, priority 10, 2 args
- [ ] Add filter: `get_terms_args`, priority 10, 2 args
- [ ] Add filter: `terms_clauses`, priority 10, 3 args
- [ ] Add action: `wp_loaded` for query analysis

### Task 2.5: Token Estimator Service
**Required Skills:** `api-integration`
**File:** includes/Services/TokenEstimator.php
**Class:** MultilingualPressZone\Services\TokenEstimator

#### Sub-task 2.5.1: Estimation Logic
**Required Skills:** `wordpress-php-integration`
- [ ] Define class with namespace
- [ ] Method: `estimate_post(int $post_id, array $target_langs): int`
- [ ] Get post content (title, content, excerpt)
- [ ] Strip HTML tags
- [ ] Count words/tokens (approx 1 token = 4 chars or 0.75 words)
- [ ] Multiply by number of target languages
- [ ] Return total estimate

#### Sub-task 2.5.2: AJAX Integration
**Required Skills:** `admin-panel-fullstack`
- [ ] Add method `ajax_get_estimate()`
- [ ] Verify nonce
- [ ] Get post_id from request
- [ ] Return JSON with estimate