Files
easystream-main/docs/LEGACY_CODE_CLEANUP_PLAN.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

751 lines
18 KiB
Markdown

# 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
1. [Critical Removals](#critical-removals)
2. [Authentication System Cleanup](#authentication-system-cleanup)
3. [Database Query Optimization](#database-query-optimization)
4. [Frontend JavaScript Modernization](#frontend-javascript-modernization)
5. [File Structure Reorganization](#file-structure-reorganization)
6. [Performance Optimizations](#performance-optimizations)
7. [Migration Checklist](#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:**
1. Search codebase for `VLogin` references
2. Replace with `VAuth::getInstance()`
3. Update all login forms to use VAuth
4. Remove class.login.php entirely
**Command to find VLogin usage:**
```bash
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:**
1. Extract all `<script>` tags from PHP files
2. Move to dedicated .js files
3. Use data attributes for configuration
4. 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
1. **Old VLogin** (deprecated)
2. **VSession** (redundant)
3. **VAuth** (modern, keep this)
### Cleanup Steps
#### Step 1: Find All VLogin Usage
```bash
# 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:**
```php
$login = new VLogin();
$login->doLogin($username, $password);
if ($login->isLoggedIn()) {
// ...
}
```
**After:**
```php
$auth = VAuth::getInstance();
$result = $auth->login($identifier, $password);
if ($auth->isAuthenticated()) {
// ...
}
```
#### Step 3: Remove Old Files
```bash
# 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:**
```php
// 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:**
```php
// 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:**
```php
foreach ($videos as $video) {
$commentCount = $db->singleFieldValue("SELECT COUNT(*) FROM db_comments WHERE file_key = ?", [$video['file_key']]);
}
```
**Good:**
```php
// 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:**
```php
// 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:**
```php
// 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:
```sql
-- 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`:
```javascript
// 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:**
```javascript
jQuery(document).ready(function() {
jQuery('.button').click(function() {
jQuery(this).addClass('active');
});
});
```
**After:**
```javascript
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.button').forEach(btn => {
btn.addEventListener('click', () => {
btn.classList.add('active');
});
});
});
```
Or using event delegation (more efficient):
```javascript
document.addEventListener('click', (e) => {
if (e.target.classList.contains('button')) {
e.target.classList.add('active');
}
});
```
### Files to Modernize
Priority order:
1. **High Priority (User-facing)**
- `browse.init.js` - Video browsing
- `login.init.js` - Authentication
- `jquery.init.js` - Global utilities
2. **Medium Priority**
- `files.init.js` - File management
- `channels.init.js` - Channel features
- `subdashboard.js` - Dashboard
3. **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
1. **Flat file structure** - Hard to navigate
2. **Mixed concerns** - Frontend/backend not separated
3. **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
```bash
# 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:**
```javascript
// 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):**
```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:**
```javascript
// 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:**
```php
// 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:**
```json
// 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:
```javascript
// 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:**
```html
<!-- 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:
```html
<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:
```bash
# 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
1. **Backup everything** before making changes
2. **Start with authentication** cleanup (lowest risk)
3. **Test thoroughly** after each phase
4. **Monitor performance** metrics
5. **Document changes** as you go
---
**Created:** January 2025
**Status:** Planning Phase