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

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

  1. Critical Removals
  2. Authentication System Cleanup
  3. Database Query Optimization
  4. Frontend JavaScript Modernization
  5. File Structure Reorganization
  6. Performance Optimizations
  7. 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:

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

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

  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

# 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

  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