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
- Session Variable Conflicts
- Authentication Class Conflicts
- Database Query Conflicts
- Frontend JavaScript Conflicts
- API Response Format Conflicts
- 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.phpf_modules/m_frontend/templatebuilder.phpf_modules/m_frontend/templatebuilder_ajax.phpf_modules/m_frontend/m_player/embed.phpf_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:
VLogin- Old, deprecated, still referenced inaccount.phpVSession- Redundant with VAuthVAuth- 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:
- Old direct ADOdb calls:
$db = $database->db_connect();
$result = $db->Execute("SELECT ...");
- VDatabase wrapper (correct):
$db = VDatabase::getInstance();
$result = $db->execute("SELECT ...", $params);
- 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:
- jQuery $.post (legacy):
jQuery.post(url, data, function(result) { ... });
- jQuery $.ajax (legacy):
jQuery.ajax({ url: url, method: 'POST', data: data });
- 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:
- New API endpoints (standardized):
{
"success": true,
"data": { ... },
"error": null
}
- 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:
- Create the file with helper functions (code provided above)
- Include in
f_core/config.core.php - 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.phpapi/user.phpapi/comments.phpapi/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:
- Backup before changes:
git add .
git commit -m "Before conflict resolution"
- If issues occur:
git revert HEAD
- Test specific fix in isolation:
git checkout -b test-session-fix
# Apply only session fix
# Test thoroughly
# If good, merge to main
Priority Order
- ✅ Session Helper Functions - Do this FIRST (CRITICAL)
- ✅ Update API Endpoints - Fix session access (HIGH)
- ✅ Fix account.php VLogin - Currently broken (CRITICAL)
- ⏸️ Standardize Database Queries - Performance (MEDIUM)
- ⏸️ Migrate jQuery AJAX - Performance (MEDIUM)
- ⏸️ 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
- Create
f_core/f_functions/functions.session.php - Update
f_core/config.core.phpto include it - Update all API endpoints to use
getCurrentUserId() - Fix
f_modules/m_frontend/m_acct/account.php - Test authentication thoroughly
- Proceed to medium priority fixes
Document Created: January 2025 Status: Ready for Implementation