# EasyStream Conflict Resolution Guide

## Overview

This document identifies and provides solutions for conflicts between legacy code and new modern code in EasyStream.

**Last Updated:** January 2025

---

## Table of Contents

1. [Session Variable Conflicts](#session-variable-conflicts)
2. [Authentication Class Conflicts](#authentication-class-conflicts)
3. [Database Query Conflicts](#database-query-conflicts)
4. [Frontend JavaScript Conflicts](#frontend-javascript-conflicts)
5. [API Response Format Conflicts](#api-response-format-conflicts)
6. [Migration Action Plan](#migration-action-plan)

---

## 1. Session Variable Conflicts

### Problem

Multiple session variable names are used inconsistently:
- `$_SESSION['USER_ID']` (uppercase)
- `$_SESSION['usr_id']` (lowercase)
- `$_SESSION['user_id']` (lowercase with underscore)

This causes bugs where authentication checks fail randomly.

### Current Impact

**Files affected:** 26+ files

**Example conflicts:**
```php
// api/videos.php - Checks both!
if (!$userId && isset($_SESSION['USER_ID'])) {
    $userId = $_SESSION['USER_ID'];
} elseif (!$userId && isset($_SESSION['usr_id'])) {
    $userId = $_SESSION['usr_id'];
}

// f_modules/m_frontend/m_acct/account.php - Uses different one
$membership_check = ($_SESSION["USER_ID"] > 0) ? VLogin::checkSubscription() : null;
```

### Solution

**Standardize on ONE session variable: `$_SESSION['USER_ID']`**

#### Step 1: Create Session Helper Function

**File:** `f_core/f_functions/functions.session.php`

```php
<?php
/**
 * Session Helper Functions
 * Provides standardized session access
 */

/**
 * Get current user ID from session
 * Handles legacy session variable names
 *
 * @return int User ID or 0 if not logged in
 */
function getCurrentUserId() {
    // Check modern standard
    if (isset($_SESSION['USER_ID']) && $_SESSION['USER_ID'] > 0) {
        return (int) $_SESSION['USER_ID'];
    }

    // Check legacy variants (for migration period)
    if (isset($_SESSION['usr_id']) && $_SESSION['usr_id'] > 0) {
        // Migrate to new standard
        $_SESSION['USER_ID'] = (int) $_SESSION['usr_id'];
        unset($_SESSION['usr_id']);
        return (int) $_SESSION['USER_ID'];
    }

    if (isset($_SESSION['user_id']) && $_SESSION['user_id'] > 0) {
        // Migrate to new standard
        $_SESSION['USER_ID'] = (int) $_SESSION['user_id'];
        unset($_SESSION['user_id']);
        return (int) $_SESSION['USER_ID'];
    }

    return 0;
}

/**
 * Set current user ID in session
 *
 * @param int $userId User ID to set
 */
function setCurrentUserId($userId) {
    $_SESSION['USER_ID'] = (int) $userId;

    // Clean up legacy session variables
    unset($_SESSION['usr_id']);
    unset($_SESSION['user_id']);
}

/**
 * Check if user is logged in
 *
 * @return bool
 */
function isUserLoggedIn() {
    return getCurrentUserId() > 0;
}

/**
 * Clear user session
 */
function clearUserSession() {
    unset($_SESSION['USER_ID']);
    unset($_SESSION['usr_id']);
    unset($_SESSION['user_id']);
}
```

#### Step 2: Update VAuth to Use Standard

**File:** `f_core/f_classes/class.auth.php`

Add to VAuth class:

```php
/**
 * Get current user ID
 * @return int
 */
public static function getCurrentUserId() {
    return getCurrentUserId(); // Use helper function
}

/**
 * Set user ID after login
 * @param int $userId
 */
private function setUserId($userId) {
    setCurrentUserId($userId);
}
```

#### Step 3: Update All API Endpoints

Replace this pattern:
```php
// OLD - checking multiple variables
if (!$userId && isset($_SESSION['USER_ID'])) {
    $userId = $_SESSION['USER_ID'];
} elseif (!$userId && isset($_SESSION['usr_id'])) {
    $userId = $_SESSION['usr_id'];
}
```

With:
```php
// NEW - use helper function
if (!$userId) {
    $userId = getCurrentUserId();
}
```

#### Step 4: Update All Module Files

**Files to update:**
- `f_modules/m_frontend/m_acct/account.php`
- `f_modules/m_frontend/templatebuilder.php`
- `f_modules/m_frontend/templatebuilder_ajax.php`
- `f_modules/m_frontend/m_player/embed.php`
- `f_modules/m_frontend/m_notif/notifications_bell.php`

**Before:**
```php
$user_id = isset($_SESSION['USER_ID']) ? (int)$_SESSION['USER_ID'] : 0;
```

**After:**
```php
$user_id = getCurrentUserId();
```

---

## 2. Authentication Class Conflicts

### Problem

**Multiple authentication classes exist:**
1. `VLogin` - Old, deprecated, still referenced in `account.php`
2. `VSession` - Redundant with VAuth
3. `VAuth` - Modern, should be the only one used

### Current Impact

**File:** `f_modules/m_frontend/m_acct/account.php`

```php
// Line 37 - Uses OLD VLogin class!
$membership_check = ($_SESSION["USER_ID"] > 0) ? VLogin::checkSubscription() : null;
```

This will FAIL if VLogin class is removed.

### Solution

#### Step 1: Check if VLogin Class Exists

```bash
find . -name "class.login.php" -type f
```

**Result:** No `class.login.php` found - VLogin doesn't exist!

This means `account.php` line 37 will throw a fatal error.

#### Step 2: Fix account.php

**File:** `f_modules/m_frontend/m_acct/account.php`

**Before:**
```php
$membership_check = ($cfg["paid_memberships"] == 1 and $_SESSION["USER_ID"] > 0)
    ? VLogin::checkSubscription()
    : null;
```

**After:**
```php
// Use VAuth or VMembership class instead
require_once $cfg['classes_dir'] . '/class.membership.php';

$membership_check = ($cfg["paid_memberships"] == 1 && getCurrentUserId() > 0)
    ? VMembership::checkSubscription(getCurrentUserId())
    : null;
```

#### Step 3: Search and Replace All VLogin References

```bash
# Find all VLogin references
grep -r "VLogin" --include="*.php" f_modules/

# Replace with VAuth
# For each file found, update to use VAuth::getInstance()
```

---

## 3. Database Query Conflicts

### Problem

**Multiple patterns for database queries:**

1. **Old direct ADOdb calls:**
```php
$db = $database->db_connect();
$result = $db->Execute("SELECT ...");
```

2. **VDatabase wrapper (correct):**
```php
$db = VDatabase::getInstance();
$result = $db->execute("SELECT ...", $params);
```

3. **Old procedural style:**
```php
$result = mysql_query("SELECT ...");
```

### Solution

**Standardize on VDatabase singleton pattern**

#### Search and Replace Pattern

**Find:**
```php
$database->db_connect()
$db->Execute()
$db->GetRow()
```

**Replace with:**
```php
$db = VDatabase::getInstance();
$db->execute()
$db->singleRow()
```

#### Example Fix

**Before:**
```php
function getUser($userId) {
    global $database;
    $db = $database->db_connect();
    $sql = "SELECT * FROM db_users WHERE usr_id = " . $userId; // SQL injection!
    $result = $db->Execute($sql);
    return $result->FetchRow();
}
```

**After:**
```php
function getUser($userId) {
    $db = VDatabase::getInstance();
    $sql = "SELECT * FROM db_users WHERE usr_id = ?";
    $result = $db->execute($sql, [$userId]);
    return $result && $result->RecordCount() > 0 ? $result->fields : null;
}
```

---

## 4. Frontend JavaScript Conflicts

### Problem

**Three different AJAX patterns:**

1. **jQuery $.post (legacy):**
```javascript
jQuery.post(url, data, function(result) { ... });
```

2. **jQuery $.ajax (legacy):**
```javascript
jQuery.ajax({ url: url, method: 'POST', data: data });
```

3. **Modern fetch via api-helper (new):**
```javascript
await api.post(url, data);
```

### Current Impact

- **Page weight:** jQuery adds 87KB
- **Maintenance:** Three patterns to maintain
- **Consistency:** Different error handling for each

### Solution

**Migrate all to api-helper.js**

#### Migration Example 1: Browse Videos

**File:** `f_scripts/fe/js/browse.init.js`

**Before:**
```javascript
jQuery(".more-button").click(function () {
    var page = parseInt(jQuery(this).attr("rel-page"));
    var url = _rel + "?p=0&m=" + idnr + "&sort=" + type + "&page=" + page;

    jQuery("#list ul").mask("");

    jQuery.get(url, function(result) {
        jQuery("#list ul").append(result).unmask();
        jQuery(".more-button").attr("rel-page", page + 1);
    });
});
```

**After:**
```javascript
document.addEventListener('click', async (e) => {
    const moreBtn = e.target.closest('.more-button');
    if (!moreBtn) return;

    const page = parseInt(moreBtn.dataset.page);

    try {
        showLoading(moreBtn);

        const result = await api.getVideos({
            page: page,
            sort: currentSort,
            category: currentCategory
        });

        if (result.success) {
            appendVideos(result.data.videos);
            moreBtn.dataset.page = page + 1;

            // Hide button if no more pages
            if (page >= result.data.pagination.pages) {
                moreBtn.style.display = 'none';
            }
        }
    } catch (error) {
        api.handleError(error);
    } finally {
        hideLoading(moreBtn);
    }
});

function appendVideos(videos) {
    const list = document.getElementById('video-list');
    videos.forEach(video => {
        const item = createVideoElement(video);
        list.appendChild(item);
    });
}
```

#### Migration Example 2: Watch Later

**File:** `f_scripts/fe/js/browse.init.js`

**Before:**
```javascript
jQuery(".watch_later_wrap").click(function () {
    var file_key = jQuery(this).attr("rel-key");
    var _this = jQuery(this);

    jQuery.post(url, {"fileid[0]": file_key}, function(result) {
        _this.find(".icon-clock")
            .removeClass("icon-clock")
            .addClass("icon-check");
    });
});
```

**After:**
```javascript
document.addEventListener('click', async (e) => {
    const watchBtn = e.target.closest('.watch-later-btn');
    if (!watchBtn) return;

    const fileKey = watchBtn.dataset.fileKey;

    try {
        const result = await api.toggleWatchLater(fileKey);

        if (result.success) {
            const icon = watchBtn.querySelector('.icon');

            if (result.data.action === 'added') {
                icon.classList.remove('icon-clock');
                icon.classList.add('icon-check');
                watchBtn.title = 'In Watch List';
            } else {
                icon.classList.remove('icon-check');
                icon.classList.add('icon-clock');
                watchBtn.title = 'Watch Later';
            }
        }
    } catch (error) {
        api.handleError(error);
    }
});
```

---

## 5. API Response Format Conflicts

### Problem

**Inconsistent response formats:**

1. **New API endpoints (standardized):**
```json
{
  "success": true,
  "data": { ... },
  "error": null
}
```

2. **Old endpoints (inconsistent):**
```json
{
  "status": "ok",
  "result": { ... }
}
```

OR just raw data:
```json
{ "usr_id": 1, "usr_name": "john" }
```

### Solution

**Update all old endpoints to use standard format**

#### Standard Response Helper

**File:** `f_core/f_functions/functions.api.php`

```php
<?php
/**
 * API Response Functions
 * Provides standardized API responses
 */

/**
 * Send success response
 *
 * @param mixed $data Data to return
 * @param int $statusCode HTTP status code
 */
function sendApiSuccess($data = null, $statusCode = 200) {
    http_response_code($statusCode);
    header('Content-Type: application/json');

    echo json_encode([
        'success' => true,
        'data' => $data,
        'error' => null
    ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

    exit;
}

/**
 * Send error response
 *
 * @param string $message Error message
 * @param int $statusCode HTTP status code
 * @param array $details Additional error details
 */
function sendApiError($message, $statusCode = 400, $details = null) {
    http_response_code($statusCode);
    header('Content-Type: application/json');

    $response = [
        'success' => false,
        'data' => null,
        'error' => $message
    ];

    if ($details) {
        $response['details'] = $details;
    }

    echo json_encode($response, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

    exit;
}

/**
 * Validate API request method
 *
 * @param string|array $allowedMethods Allowed HTTP method(s)
 * @throws Exception if method not allowed
 */
function validateApiMethod($allowedMethods) {
    $allowedMethods = (array) $allowedMethods;
    $currentMethod = $_SERVER['REQUEST_METHOD'];

    if (!in_array($currentMethod, $allowedMethods)) {
        sendApiError(
            'Method not allowed. Allowed: ' . implode(', ', $allowedMethods),
            405
        );
    }
}
```

#### Update Old API Endpoints

**Example:** `api/privacy.php`

**Before:**
```php
// Returns raw data, no standard format
echo json_encode($result);
```

**After:**
```php
require_once __DIR__ . '/../f_core/f_functions/functions.api.php';

try {
    // ... existing code ...

    sendApiSuccess([
        'privacy_settings' => $result
    ]);

} catch (Exception $e) {
    sendApiError($e->getMessage(), 500);
}
```

---

## 6. Migration Action Plan

### Critical Fixes (Do First - High Impact)

#### Fix 1: Create Session Helper Functions

**File to create:** `f_core/f_functions/functions.session.php`

**Priority:** CRITICAL - Affects authentication everywhere

**Time:** 30 minutes

**Steps:**
1. Create the file with helper functions (code provided above)
2. Include in `f_core/config.core.php`
3. Test that `getCurrentUserId()` works

**Test:**
```php
// Add to any page temporarily
echo "User ID: " . getCurrentUserId();
```

#### Fix 2: Update API Endpoints to Use Helper

**Files to update:**
- `api/videos.php`
- `api/user.php`
- `api/comments.php`
- `api/subscriptions.php`

**Priority:** HIGH - Prevents session bugs

**Time:** 1 hour

**Pattern to replace:**
```php
// Find this:
if (!$userId && isset($_SESSION['USER_ID'])) {
    $userId = $_SESSION['USER_ID'];
} elseif (!$userId && isset($_SESSION['usr_id'])) {
    $userId = $_SESSION['usr_id'];
}

// Replace with:
if (!$userId) {
    $userId = getCurrentUserId();
}
```

#### Fix 3: Fix VLogin Reference in account.php

**File:** `f_modules/m_frontend/m_acct/account.php`

**Priority:** CRITICAL - Currently broken!

**Time:** 15 minutes

**Line 37 fix:**
```php
// Before:
$membership_check = ($_SESSION["USER_ID"] > 0) ? VLogin::checkSubscription() : null;

// After:
$membership_check = ($cfg["paid_memberships"] == 1 && getCurrentUserId() > 0)
    ? VMembership::checkSubscription(getCurrentUserId())
    : null;
```

### Medium Priority Fixes

#### Fix 4: Standardize Database Queries

**Pattern:** Search for `$database->db_connect()` and replace with `VDatabase::getInstance()`

**Priority:** MEDIUM - Performance improvement

**Time:** 2-3 hours

**Command:**
```bash
grep -r "db_connect" --include="*.php" f_modules/
```

#### Fix 5: Migrate jQuery AJAX in browse.init.js

**File:** `f_scripts/fe/js/browse.init.js`

**Priority:** MEDIUM - Performance improvement

**Time:** 3-4 hours

**See examples in section 4 above**

### Low Priority (Can wait)

#### Fix 6: Create API Response Helper

**File to create:** `f_core/f_functions/functions.api.php`

**Priority:** LOW - Nice to have

**Time:** 1 hour

#### Fix 7: Update Old API Endpoints

**Files:** `api/privacy.php`, `api/telegram.php`, etc.

**Priority:** LOW - These endpoints still work

**Time:** 2-3 hours

---

## Testing Checklist

After each fix, test:

```
Authentication:
☐ Login works
☐ Session persists after page reload
☐ Logout clears session
☐ Protected pages redirect to login

API Endpoints:
☐ Videos list loads
☐ Comments load and post
☐ Subscribe/unsubscribe works
☐ User profile loads

Frontend:
☐ Browse videos page works
☐ Load more pagination works
☐ Watch later toggle works
☐ No JavaScript console errors
```

---

## Rollback Plan

If something breaks:

1. **Backup before changes:**
```bash
git add .
git commit -m "Before conflict resolution"
```

2. **If issues occur:**
```bash
git revert HEAD
```

3. **Test specific fix in isolation:**
```bash
git checkout -b test-session-fix
# Apply only session fix
# Test thoroughly
# If good, merge to main
```

---

## Priority Order

1. ✅ **Session Helper Functions** - Do this FIRST (CRITICAL)
2. ✅ **Update API Endpoints** - Fix session access (HIGH)
3. ✅ **Fix account.php VLogin** - Currently broken (CRITICAL)
4. ⏸️ **Standardize Database Queries** - Performance (MEDIUM)
5. ⏸️ **Migrate jQuery AJAX** - Performance (MEDIUM)
6. ⏸️ **API Response Helpers** - Nice to have (LOW)

---

## Estimated Timeline

- **Critical fixes (1-3):** 2-3 hours
- **Medium fixes (4-5):** 1 week
- **Low priority (6-7):** 1-2 weeks

**Total: 2-3 weeks for complete resolution**

---

## Next Steps

1. Create `f_core/f_functions/functions.session.php`
2. Update `f_core/config.core.php` to include it
3. Update all API endpoints to use `getCurrentUserId()`
4. Fix `f_modules/m_frontend/m_acct/account.php`
5. Test authentication thoroughly
6. Proceed to medium priority fixes

---

**Document Created:** January 2025
**Status:** Ready for Implementation
