Files
easystream-main/docs/CONFLICT_RESOLUTION_GUIDE.md
SamiAhmed7777 f0f346deb9
Some checks failed
EasyStream Test Suite / test (pull_request) Has been cancelled
EasyStream Test Suite / code-quality (pull_request) Has been cancelled
EasyStream Test Suite / integration-test (pull_request) Has been cancelled
Sync current dev state
2025-12-15 17:28:21 -08:00

16 KiB

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
  2. Authentication Class Conflicts
  3. Database Query Conflicts
  4. Frontend JavaScript Conflicts
  5. API Response Format Conflicts
  6. 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:

// 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
/**
 * 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:

/**
 * 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:

// 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:

// 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:

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

After:

$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

// 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

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:

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

After:

// 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

# 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:
$db = $database->db_connect();
$result = $db->Execute("SELECT ...");
  1. VDatabase wrapper (correct):
$db = VDatabase::getInstance();
$result = $db->execute("SELECT ...", $params);
  1. Old procedural style:
$result = mysql_query("SELECT ...");

Solution

Standardize on VDatabase singleton pattern

Search and Replace Pattern

Find:

$database->db_connect()
$db->Execute()
$db->GetRow()

Replace with:

$db = VDatabase::getInstance();
$db->execute()
$db->singleRow()

Example Fix

Before:

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:

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):
jQuery.post(url, data, function(result) { ... });
  1. jQuery $.ajax (legacy):
jQuery.ajax({ url: url, method: 'POST', data: data });
  1. Modern fetch via api-helper (new):
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:

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:

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:

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:

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):
{
  "success": true,
  "data": { ... },
  "error": null
}
  1. Old endpoints (inconsistent):
{
  "status": "ok",
  "result": { ... }
}

OR just raw data:

{ "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
/**
 * 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:

// Returns raw data, no standard format
echo json_encode($result);

After:

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:

// 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:

// 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:

// 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:

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:
git add .
git commit -m "Before conflict resolution"
  1. If issues occur:
git revert HEAD
  1. Test specific fix in isolation:
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