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

801 lines
16 KiB
Markdown

# 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