18 KiB
Legacy Code Cleanup & Modernization Plan
Overview
This document identifies outdated code, redundant systems, and performance bottlenecks in EasyStream that should be removed or refactored to create a modern, efficient streaming platform.
Table of Contents
- Critical Removals
- Authentication System Cleanup
- Database Query Optimization
- Frontend JavaScript Modernization
- File Structure Reorganization
- Performance Optimizations
- Migration Checklist
Critical Removals
1. Duplicate Authentication Systems
Problem: Multiple authentication systems exist, causing confusion and security risks.
Files to Remove/Consolidate:
REMOVE:
- f_core/f_classes/class.login.php (Old VLogin class)
- f_core/f_classes/class.session.php (Redundant with VAuth)
- Any references to VLogin in other files
KEEP:
- f_core/f_classes/class.auth.php (VAuth - Modern system)
Action Plan:
- Search codebase for
VLoginreferences - Replace with
VAuth::getInstance() - Update all login forms to use VAuth
- Remove class.login.php entirely
Command to find VLogin usage:
grep -r "VLogin" f_core/ f_modules/ *.php
2. Legacy Database Classes
Problem: Multiple database wrapper classes causing overhead.
Files to Audit:
f_core/f_classes/class.database.php - Keep (ADOdb wrapper)
f_core/f_classes/db*.php - Review for redundancy
Action: Ensure all code uses VDatabase::getInstance() and remove any custom DB wrappers.
3. Obsolete jQuery Plugins
Problem: Old jQuery plugins add bloat and security vulnerabilities.
Files to Remove:
f_scripts/be/js/init1.min.js - Contains jquery.form plugin (outdated)
f_scripts/*/jquery.*.min.js - Review each for necessity
Replace With:
- Native FormData API
- Fetch API
- Modern ES6+ code
4. Inline JavaScript in PHP Files
Problem: JavaScript mixed with PHP makes maintenance difficult.
Action:
- Extract all
<script>tags from PHP files - Move to dedicated .js files
- Use data attributes for configuration
- Use modern module pattern
Example Files to Clean:
browse.php - Contains inline JS
profile.php - Contains inline JS
upload.php - Contains inline JS
Authentication System Cleanup
Current State: 3 Auth Methods
- Old VLogin (deprecated)
- VSession (redundant)
- VAuth (modern, keep this)
Cleanup Steps
Step 1: Find All VLogin Usage
# Find files using VLogin
grep -r "VLogin" --include="*.php" .
# Find session_start calls (should be in VAuth only)
grep -r "session_start()" --include="*.php" .
Step 2: Update All References
Before:
$login = new VLogin();
$login->doLogin($username, $password);
if ($login->isLoggedIn()) {
// ...
}
After:
$auth = VAuth::getInstance();
$result = $auth->login($identifier, $password);
if ($auth->isAuthenticated()) {
// ...
}
Step 3: Remove Old Files
# After migrating all code:
rm f_core/f_classes/class.login.php
rm f_core/f_classes/class.session.php
Session Management Consolidation
Keep Only:
- VAuth for all authentication
- VSession for session utilities (if lightweight)
Or: Merge VSession functionality into VAuth
Database Query Optimization
Problem: N+1 Query Issues
Current Issue:
// BAD: N+1 queries
$videos = $db->execute("SELECT * FROM db_videofiles");
while (!$videos->EOF) {
$user = $db->execute("SELECT * FROM db_users WHERE usr_id = ?", [$videos->fields['usr_id']]);
// This runs once per video!
}
Solution:
// GOOD: Single query with JOIN
$sql = "SELECT v.*, u.usr_id, u.usr_user, u.usr_dname, u.usr_avatar
FROM db_videofiles v
LEFT JOIN db_users u ON v.usr_id = u.usr_id
WHERE v.approved = 1";
$videos = $db->execute($sql);
Remove Unnecessary Database Calls
1. Count Queries in Loops
Bad:
foreach ($videos as $video) {
$commentCount = $db->singleFieldValue("SELECT COUNT(*) FROM db_comments WHERE file_key = ?", [$video['file_key']]);
}
Good:
// Get all counts in one query
$sql = "SELECT file_key, COUNT(*) as comment_count
FROM db_comments
WHERE file_key IN (?)
GROUP BY file_key";
2. Redundant Existence Checks
Bad:
// Check if exists
$exists = $db->execute("SELECT COUNT(*) FROM db_users WHERE usr_id = ?", [$userId]);
if ($exists->fields[0] > 0) {
// Then fetch the user
$user = $db->execute("SELECT * FROM db_users WHERE usr_id = ?", [$userId]);
}
Good:
// Just fetch directly, check if result is empty
$user = $db->execute("SELECT * FROM db_users WHERE usr_id = ?", [$userId]);
if ($user && $user->RecordCount() > 0) {
// Use user data
}
Add Database Indexes
Critical indexes to add:
-- Video queries
CREATE INDEX idx_videofiles_approved_privacy ON db_videofiles(approved, privacy);
CREATE INDEX idx_videofiles_usr_id ON db_videofiles(usr_id);
CREATE INDEX idx_videofiles_upload_date ON db_videofiles(upload_date);
CREATE INDEX idx_videofiles_file_views ON db_videofiles(file_views);
-- Comment queries
CREATE INDEX idx_comments_file_key ON db_comments(file_key);
CREATE INDEX idx_comments_parent_id ON db_comments(parent_id);
CREATE INDEX idx_comments_usr_id ON db_comments(usr_id);
-- Subscription queries
CREATE INDEX idx_subscriptions_usr_id ON db_subscriptions(usr_id);
CREATE INDEX idx_subscriptions_channel_id ON db_subscriptions(channel_id);
-- Like queries
CREATE INDEX idx_likes_file_key_type ON db_likes(file_key, like_type);
CREATE INDEX idx_likes_usr_id ON db_likes(usr_id);
-- Session queries
CREATE INDEX idx_sessions_user_id ON db_sessions(user_id);
CREATE INDEX idx_sessions_expires_at ON db_sessions(expires_at);
Frontend JavaScript Modernization
Remove jQuery Dependency
jQuery is heavy (87KB minified) and no longer necessary.
Migration Strategy
Phase 1: Utility Functions
Create f_scripts/fe/js/utils.js:
// Modern replacements for jQuery
const $ = {
// $(selector) -> document.querySelectorAll
select: (selector) => document.querySelectorAll(selector),
selectOne: (selector) => document.querySelector(selector),
// $.ajax -> fetch
ajax: async (url, options = {}) => {
const response = await fetch(url, options);
return response.json();
},
// $.get -> fetch
get: async (url) => {
const response = await fetch(url);
return response.json();
},
// $.post -> fetch
post: async (url, data) => {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
return response.json();
},
// $(element).addClass/removeClass
addClass: (el, className) => el.classList.add(className),
removeClass: (el, className) => el.classList.remove(className),
toggleClass: (el, className) => el.classList.toggle(className),
// $(element).show/hide
show: (el) => el.style.display = '',
hide: (el) => el.style.display = 'none',
// $(element).on
on: (el, event, handler) => el.addEventListener(event, handler),
off: (el, event, handler) => el.removeEventListener(event, handler),
// $.each -> Array.forEach
each: (arr, callback) => Array.from(arr).forEach(callback)
};
Phase 2: Replace jQuery Usage
Before:
jQuery(document).ready(function() {
jQuery('.button').click(function() {
jQuery(this).addClass('active');
});
});
After:
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.button').forEach(btn => {
btn.addEventListener('click', () => {
btn.classList.add('active');
});
});
});
Or using event delegation (more efficient):
document.addEventListener('click', (e) => {
if (e.target.classList.contains('button')) {
e.target.classList.add('active');
}
});
Files to Modernize
Priority order:
-
High Priority (User-facing)
browse.init.js- Video browsinglogin.init.js- Authenticationjquery.init.js- Global utilities
-
Medium Priority
files.init.js- File managementchannels.init.js- Channel featuressubdashboard.js- Dashboard
-
Low Priority
- Backend admin files
- Analytics dashboards
Remove Unused Libraries
Audit and remove:
f_scripts/lib/
├── jquery.old.js - Remove if exists
├── bootstrap.v2.js - If using v4+, remove v2
├── moment.js - Use native Date if possible
├── lodash.js - Use native ES6 methods
└── underscore.js - Redundant with lodash
File Structure Reorganization
Current Issues
- Flat file structure - Hard to navigate
- Mixed concerns - Frontend/backend not separated
- Redundant files - Multiple versions of same functionality
Proposed Structure
api/ # All API endpoints (CLEAN)
├── auth.php
├── videos.php
├── user.php
├── comments.php
├── subscriptions.php
└── cors.config.php
f_core/ # Core backend classes (KEEP CLEAN)
├── config.core.php # Main config
├── config.database.php # DB config
├── f_classes/ # Core classes
│ ├── class.auth.php # KEEP
│ ├── class.database.php # KEEP
│ ├── class.security.php # KEEP
│ ├── class.logger.php # KEEP
│ ├── class.rbac.php # KEEP
│ ├── class.middleware.php # KEEP
│ └── [REMOVE OLD CLASSES]
└── f_functions/ # Utility functions
├── functions.security.php
└── functions.rbac.php
f_scripts/
├── fe/ # Frontend only
│ ├── js/
│ │ ├── api-helper.js # MODERN API client
│ │ ├── utils.js # Native JS utilities
│ │ └── [page-specific].js
│ ├── css/
│ └── img/
└── be/ # Backend admin
└── js/
f_modules/ # Feature modules
├── m_frontend/ # User-facing features
└── m_backend/ # Admin features
docs/ # Documentation
├── API_DOCUMENTATION.md
├── FRONTEND_BACKEND_INTEGRATION_GUIDE.md
└── LEGACY_CODE_CLEANUP_PLAN.md
[root] # Page entry points
├── index.php
├── browse.php
├── profile.php
└── ...
Files to Remove
# Find duplicate/old files
find . -name "*.old.php"
find . -name "*.backup.php"
find . -name "*_old.*"
find . -name "*_backup.*"
# Remove after verification
rm [files]
Performance Optimizations
1. Implement Lazy Loading
Videos/Images:
// Use Intersection Observer instead of scroll events
const lazyLoadObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
lazyLoadObserver.unobserve(img);
}
});
});
document.querySelectorAll('img.lazy').forEach(img => {
lazyLoadObserver.observe(img);
});
2. Implement Caching
Backend (PHP):
// Use Redis/Memcached for session storage (already configured)
// Add query result caching
class VCache {
private static $redis;
public static function get($key) {
if (!self::$redis) {
self::$redis = new Redis();
self::$redis->connect('127.0.0.1', 6379);
}
return self::$redis->get($key);
}
public static function set($key, $value, $ttl = 3600) {
if (!self::$redis) {
self::$redis = new Redis();
self::$redis->connect('127.0.0.1', 6379);
}
return self::$redis->setex($key, $ttl, serialize($value));
}
}
// Usage
$cacheKey = "videos:popular:page:{$page}";
$videos = VCache::get($cacheKey);
if (!$videos) {
$videos = $db->execute($sql, $params);
VCache::set($cacheKey, $videos->GetArray(), 300); // 5 min cache
}
Frontend:
// Cache API responses in memory
class APICache {
constructor(ttl = 60000) { // 1 minute default
this.cache = new Map();
this.ttl = ttl;
}
get(key) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expires) {
this.cache.delete(key);
return null;
}
return item.data;
}
set(key, data) {
this.cache.set(key, {
data,
expires: Date.now() + this.ttl
});
}
clear() {
this.cache.clear();
}
}
// Add to api-helper.js
const apiCache = new APICache();
// In request method:
const cacheKey = `${endpoint}:${JSON.stringify(params)}`;
const cached = apiCache.get(cacheKey);
if (cached && config.cache) {
return cached;
}
// After successful request:
if (config.cache) {
apiCache.set(cacheKey, data);
}
3. Optimize Database Queries
Use Prepared Statement Caching:
// In VDatabase class
private $stmtCache = [];
public function execute($sql, $params = []) {
$cacheKey = md5($sql);
if (!isset($this->stmtCache[$cacheKey])) {
$this->stmtCache[$cacheKey] = $this->connection->Prepare($sql);
}
return $this->connection->Execute($this->stmtCache[$cacheKey], $params);
}
4. Minify and Bundle Assets
Create build process:
// package.json
{
"scripts": {
"build:js": "esbuild f_scripts/fe/js/**/*.js --bundle --minify --outdir=f_scripts/fe/dist/js",
"build:css": "postcss f_scripts/fe/css/**/*.css --dir f_scripts/fe/dist/css --use cssnano",
"build": "npm run build:js && npm run build:css",
"watch": "npm run build -- --watch"
}
}
5. Implement Code Splitting
Split JavaScript into chunks:
// Load features on demand
async function loadVideoPlayer() {
const { VideoPlayer } = await import('./video-player.js');
return new VideoPlayer();
}
// Only load when needed
document.querySelector('.video-container').addEventListener('click', async () => {
const player = await loadVideoPlayer();
player.play();
}, { once: true });
6. Remove Render-Blocking Resources
Move scripts to end of body:
<!-- Before: -->
<head>
<script src="jquery.js"></script>
<script src="app.js"></script>
</head>
<!-- After: -->
<body>
<!-- content -->
<script src="app.js" defer></script>
</body>
Or use async for independent scripts:
<script src="analytics.js" async></script>
Migration Checklist
Phase 1: Remove Duplicate Auth Systems
- Find all VLogin references
- Replace with VAuth
- Test authentication flows
- Remove class.login.php
- Remove class.session.php (if redundant)
- Update documentation
Phase 2: Database Optimization
- Add missing indexes
- Audit for N+1 queries
- Implement query caching
- Use JOINs instead of separate queries
- Enable prepared statement caching
- Monitor slow query log
Phase 3: Frontend Modernization
- Create native JS utility library
- Migrate browse.init.js to modern JS
- Migrate login.init.js to modern JS
- Migrate jquery.init.js to modern JS
- Remove jQuery dependency
- Test all user interactions
- Update build process
Phase 4: File Cleanup
- Remove obsolete files (.old, .backup)
- Reorganize file structure
- Remove unused libraries
- Clean up inline JavaScript
- Move JS to external files
Phase 5: Performance Optimization
- Implement lazy loading for images
- Add Redis caching for queries
- Enable browser caching headers
- Minify and bundle assets
- Implement code splitting
- Add service worker for offline support (optional)
Phase 6: Testing & Validation
- Load test with Apache Bench
- Profile with Chrome DevTools
- Check for memory leaks
- Verify all features work
- Test on slow connections (throttling)
- Mobile device testing
Performance Metrics to Track
Before Cleanup
Measure these metrics before starting:
# Page load time
curl -o /dev/null -s -w 'Total: %{time_total}s\n' http://localhost/
# Time to first byte
curl -o /dev/null -s -w 'TTFB: %{time_starttransfer}s\n' http://localhost/
# Database query count (add logging)
grep "SELECT" /var/log/mysql/query.log | wc -l
After Cleanup - Target Metrics
- Page load time: < 2 seconds
- Time to first byte: < 500ms
- Total JavaScript size: < 200KB
- Database queries per page: < 10
- Memory usage: < 128MB per request
Resource Savings Estimate
Expected Improvements
| Metric | Before | After | Improvement |
|---|---|---|---|
| Page Load Time | 4-6s | 1-2s | 70% faster |
| JavaScript Size | 500KB | 150KB | 70% smaller |
| Database Queries | 30-50 | 5-10 | 80% fewer |
| Memory per Request | 256MB | 64MB | 75% less |
| Server Requests | 40+ | 15-20 | 60% fewer |
Cost Savings
For a platform with 10,000 daily active users:
- Server costs: 50% reduction (fewer resources needed)
- Bandwidth: 60% reduction (smaller assets)
- Database load: 75% reduction (fewer queries, better caching)
Next Steps
- Backup everything before making changes
- Start with authentication cleanup (lowest risk)
- Test thoroughly after each phase
- Monitor performance metrics
- Document changes as you go
Created: January 2025 Status: Planning Phase