feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
This commit is contained in:
579
docs/DEVELOPMENT.md
Normal file
579
docs/DEVELOPMENT.md
Normal file
@@ -0,0 +1,579 @@
|
||||
# Development Guide
|
||||
|
||||
This guide covers development workflows, coding standards, and best practices for EasyStream development.
|
||||
|
||||
## Development Environment Setup
|
||||
|
||||
### Local Development with Docker
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone <repository-url>
|
||||
cd easystream
|
||||
|
||||
# Copy environment configuration
|
||||
cp .env.example .env
|
||||
|
||||
# Start development environment
|
||||
docker-compose up -d --build
|
||||
|
||||
# Access the application
|
||||
open http://localhost:8083
|
||||
```
|
||||
|
||||
### Native PHP Development
|
||||
```bash
|
||||
# Install PHP 8.2+ with required extensions
|
||||
# - pdo_mysql
|
||||
# - gd
|
||||
# - curl
|
||||
# - mbstring
|
||||
# - xml
|
||||
# - zip
|
||||
|
||||
# Install Composer dependencies (if any)
|
||||
composer install
|
||||
|
||||
# Configure database connection
|
||||
cp f_core/config.database.php.example f_core/config.database.php
|
||||
# Edit database settings
|
||||
|
||||
# Set up web server (Apache/Nginx)
|
||||
# Point document root to project directory
|
||||
```
|
||||
|
||||
## Project Structure Deep Dive
|
||||
|
||||
### Core Framework (`f_core/`)
|
||||
```
|
||||
f_core/
|
||||
├── config.*.php # Configuration files
|
||||
├── f_classes/ # Core business logic classes
|
||||
├── f_functions/ # Utility functions
|
||||
└── f_workers/ # Background workers
|
||||
```
|
||||
|
||||
### Modules (`f_modules/`)
|
||||
```
|
||||
f_modules/
|
||||
├── m_frontend/ # User-facing modules
|
||||
├── m_backend/ # Admin modules
|
||||
└── api/ # API endpoints
|
||||
```
|
||||
|
||||
### Templates (`f_templates/`)
|
||||
```
|
||||
f_templates/
|
||||
├── tpl_frontend/ # User interface templates
|
||||
├── tpl_backend/ # Admin interface templates
|
||||
└── frontend/ # Static frontend assets
|
||||
```
|
||||
|
||||
### Jobs (`f_jobs/`)
|
||||
```
|
||||
f_jobs/
|
||||
├── BaseJob.php # Base job class
|
||||
├── VideoProcessingJob.php
|
||||
├── NotificationJob.php
|
||||
└── CleanupJob.php
|
||||
```
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### PHP Standards
|
||||
Follow PSR-12 coding standards with EasyStream-specific conventions:
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
* @author Your Name
|
||||
* @version 1.0
|
||||
*/
|
||||
class VExampleClass
|
||||
{
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
* @param string $param Parameter description
|
||||
* @return bool Return value description
|
||||
*/
|
||||
public function exampleMethod(string $param): bool
|
||||
{
|
||||
// Implementation
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
- Classes: PascalCase with 'V' prefix for core classes (`VDatabase`, `VSecurity`)
|
||||
- Methods: camelCase (`getUserById`, `validateInput`)
|
||||
- Variables: camelCase (`$userId`, `$videoData`)
|
||||
- Constants: UPPER_SNAKE_CASE (`MAX_FILE_SIZE`, `DEFAULT_TIMEOUT`)
|
||||
- Files: lowercase with underscores (`class.database.php`, `functions.security.php`)
|
||||
|
||||
### Database Conventions
|
||||
- Tables: lowercase with underscores (`user_sessions`, `video_metadata`)
|
||||
- Columns: lowercase with underscores (`user_id`, `created_at`)
|
||||
- Primary keys: `id` (auto-increment)
|
||||
- Foreign keys: `{table}_id` (`user_id`, `video_id`)
|
||||
- Timestamps: `created_at`, `updated_at`
|
||||
|
||||
## Development Workflows
|
||||
|
||||
### Feature Development
|
||||
1. **Create Feature Branch**
|
||||
```bash
|
||||
git checkout -b feature/new-feature-name
|
||||
```
|
||||
|
||||
2. **Create Spec (Optional)**
|
||||
```bash
|
||||
# For complex features, create a spec
|
||||
mkdir -p .kiro/specs/feature-name
|
||||
# Create requirements.md, design.md, tasks.md
|
||||
```
|
||||
|
||||
3. **Implement Feature**
|
||||
- Follow the task list if using specs
|
||||
- Write tests alongside implementation
|
||||
- Update documentation
|
||||
|
||||
4. **Test Implementation**
|
||||
```bash
|
||||
# Run all tests
|
||||
./run-tests.sh
|
||||
|
||||
# Run specific test suite
|
||||
phpunit tests/Unit/NewFeatureTest.php
|
||||
```
|
||||
|
||||
5. **Create Pull Request**
|
||||
- Ensure all tests pass
|
||||
- Update CHANGELOG.md
|
||||
- Request code review
|
||||
|
||||
### Bug Fix Workflow
|
||||
1. **Reproduce Issue**
|
||||
- Create test case that demonstrates the bug
|
||||
- Document expected vs actual behavior
|
||||
|
||||
2. **Fix Implementation**
|
||||
- Make minimal changes to fix the issue
|
||||
- Ensure fix doesn't break existing functionality
|
||||
|
||||
3. **Verify Fix**
|
||||
- Run test suite
|
||||
- Manual testing of affected areas
|
||||
- Performance impact assessment
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
### Unit Testing
|
||||
```php
|
||||
<?php
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class VSecurityTest extends TestCase
|
||||
{
|
||||
public function testValidateInput()
|
||||
{
|
||||
$result = VSecurity::validateInput('test@example.com', 'email');
|
||||
$this->assertEquals('test@example.com', $result);
|
||||
}
|
||||
|
||||
public function testValidateInputInvalid()
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
VSecurity::validateInput('invalid-email', 'email');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Integration Testing
|
||||
```php
|
||||
<?php
|
||||
class AuthIntegrationTest extends TestCase
|
||||
{
|
||||
public function testUserLoginFlow()
|
||||
{
|
||||
// Test complete login process
|
||||
$user = $this->createTestUser();
|
||||
$result = VAuth::authenticate($user['username'], 'password');
|
||||
$this->assertTrue($result);
|
||||
$this->assertTrue(VAuth::isLoggedIn());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Data Management
|
||||
```php
|
||||
<?php
|
||||
// tests/fixtures/test_data.sql
|
||||
INSERT INTO users (username, email, password_hash) VALUES
|
||||
('testuser', 'test@example.com', '$2y$10$...');
|
||||
|
||||
// In test classes
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->loadFixtures('test_data.sql');
|
||||
}
|
||||
```
|
||||
|
||||
## Database Development
|
||||
|
||||
### Migration Pattern
|
||||
```php
|
||||
<?php
|
||||
// __install/updatedb_feature.sql
|
||||
-- Add new table
|
||||
CREATE TABLE IF NOT EXISTS feature_data (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
data TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
-- Add index
|
||||
CREATE INDEX idx_feature_user ON feature_data(user_id);
|
||||
```
|
||||
|
||||
### Query Development
|
||||
```php
|
||||
<?php
|
||||
// Always use prepared statements
|
||||
class VFeatureRepository
|
||||
{
|
||||
public function getFeatureData(int $userId): array
|
||||
{
|
||||
global $class_database;
|
||||
|
||||
$sql = "SELECT * FROM feature_data WHERE user_id = ? ORDER BY created_at DESC";
|
||||
return $class_database->execute($sql, [$userId])->getRows();
|
||||
}
|
||||
|
||||
public function createFeatureData(int $userId, string $data): bool
|
||||
{
|
||||
global $class_database;
|
||||
|
||||
$sql = "INSERT INTO feature_data (user_id, data) VALUES (?, ?)";
|
||||
return $class_database->execute($sql, [$userId, $data])->rowCount() > 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Frontend Development
|
||||
|
||||
### Template Development
|
||||
```smarty
|
||||
{* f_templates/tpl_frontend/feature.tpl *}
|
||||
<div class="feature-container">
|
||||
<h2>{$feature_title|escape}</h2>
|
||||
|
||||
{if $user_logged_in}
|
||||
<form method="post" action="{$form_action}">
|
||||
{csrf_field('feature_form')}
|
||||
<input type="text" name="feature_input" value="{$feature_value|escape}">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
{else}
|
||||
<p>Please <a href="/login">login</a> to use this feature.</p>
|
||||
{/if}
|
||||
</div>
|
||||
```
|
||||
|
||||
### JavaScript Development
|
||||
```javascript
|
||||
// f_templates/frontend/js/feature.js
|
||||
class FeatureManager {
|
||||
constructor() {
|
||||
this.initializeEventListeners();
|
||||
}
|
||||
|
||||
initializeEventListeners() {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
this.setupFeatureForm();
|
||||
});
|
||||
}
|
||||
|
||||
setupFeatureForm() {
|
||||
const form = document.getElementById('feature-form');
|
||||
if (form) {
|
||||
form.addEventListener('submit', this.handleFormSubmit.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
async handleFormSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/feature', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
this.handleResponse(result);
|
||||
} catch (error) {
|
||||
console.error('Feature submission failed:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
new FeatureManager();
|
||||
```
|
||||
|
||||
## API Development
|
||||
|
||||
### RESTful API Structure
|
||||
```php
|
||||
<?php
|
||||
// api/feature.php
|
||||
require_once '../f_core/config.core.php';
|
||||
|
||||
class FeatureAPI
|
||||
{
|
||||
public function handleRequest()
|
||||
{
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
return $this->getFeature();
|
||||
case 'POST':
|
||||
return $this->createFeature();
|
||||
case 'PUT':
|
||||
return $this->updateFeature();
|
||||
case 'DELETE':
|
||||
return $this->deleteFeature();
|
||||
default:
|
||||
http_response_code(405);
|
||||
return ['error' => 'Method not allowed'];
|
||||
}
|
||||
}
|
||||
|
||||
private function getFeature()
|
||||
{
|
||||
$id = get_param('id', 'int');
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
return ['error' => 'Feature ID required'];
|
||||
}
|
||||
|
||||
// Implementation
|
||||
return ['feature' => $featureData];
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the request
|
||||
$api = new FeatureAPI();
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($api->handleRequest());
|
||||
```
|
||||
|
||||
## Background Jobs
|
||||
|
||||
### Job Implementation
|
||||
```php
|
||||
<?php
|
||||
// f_jobs/FeatureProcessingJob.php
|
||||
class FeatureProcessingJob extends BaseJob
|
||||
{
|
||||
protected string $jobType = 'feature_processing';
|
||||
|
||||
public function execute(array $data): bool
|
||||
{
|
||||
try {
|
||||
$featureId = $data['feature_id'] ?? null;
|
||||
|
||||
if (!$featureId) {
|
||||
throw new InvalidArgumentException('Feature ID required');
|
||||
}
|
||||
|
||||
$this->processFeature($featureId);
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$this->logError('Feature processing failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'data' => $data
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function processFeature(int $featureId): void
|
||||
{
|
||||
// Implementation
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Job Queue Management
|
||||
```php
|
||||
<?php
|
||||
// Queue a job
|
||||
$queueManager = new VQueueManager();
|
||||
$queueManager->addJob('feature_processing', [
|
||||
'feature_id' => $featureId,
|
||||
'priority' => 'high'
|
||||
]);
|
||||
|
||||
// Process jobs (in worker)
|
||||
$worker = new QueueWorker();
|
||||
$worker->processJobs();
|
||||
```
|
||||
|
||||
## Security Development
|
||||
|
||||
### Input Validation
|
||||
```php
|
||||
<?php
|
||||
// Always validate input
|
||||
$username = post_param('username', 'alphanum');
|
||||
$email = post_param('email', 'email');
|
||||
$age = post_param('age', 'int');
|
||||
|
||||
// Custom validation
|
||||
$customValue = VSecurity::validateInput($input, [
|
||||
'type' => 'custom',
|
||||
'pattern' => '/^[A-Z]{2,5}$/',
|
||||
'required' => true
|
||||
]);
|
||||
```
|
||||
|
||||
### CSRF Protection
|
||||
```php
|
||||
<?php
|
||||
// In forms
|
||||
echo csrf_field('form_action');
|
||||
|
||||
// Validation
|
||||
if (!validate_csrf('form_action')) {
|
||||
throw new SecurityException('CSRF validation failed');
|
||||
}
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
```php
|
||||
<?php
|
||||
// Check rate limit
|
||||
if (!check_rate_limit('api_' . $userId, 100, 3600)) {
|
||||
http_response_code(429);
|
||||
exit('Rate limit exceeded');
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Database Optimization
|
||||
- Use appropriate indexes
|
||||
- Optimize query structure
|
||||
- Implement query caching
|
||||
- Use connection pooling
|
||||
|
||||
### Caching Strategy
|
||||
```php
|
||||
<?php
|
||||
// Application-level caching
|
||||
$cacheKey = "user_data_{$userId}";
|
||||
$userData = $cache->get($cacheKey);
|
||||
|
||||
if (!$userData) {
|
||||
$userData = $this->loadUserData($userId);
|
||||
$cache->set($cacheKey, $userData, 3600); // 1 hour
|
||||
}
|
||||
```
|
||||
|
||||
### Template Optimization
|
||||
- Enable Smarty template caching
|
||||
- Minimize template complexity
|
||||
- Use template inheritance
|
||||
- Optimize asset loading
|
||||
|
||||
## Debugging and Troubleshooting
|
||||
|
||||
### Debug Mode
|
||||
```php
|
||||
<?php
|
||||
// Enable debug mode in development
|
||||
$cfg['debug_mode'] = true;
|
||||
|
||||
// Debug logging
|
||||
VLogger::debug('Debug information', [
|
||||
'variable' => $value,
|
||||
'context' => $context
|
||||
]);
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
```php
|
||||
<?php
|
||||
try {
|
||||
// Risky operation
|
||||
$result = $this->performOperation();
|
||||
} catch (Exception $e) {
|
||||
VLogger::error('Operation failed', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
// Handle gracefully
|
||||
return $this->handleError($e);
|
||||
}
|
||||
```
|
||||
|
||||
### Log Analysis
|
||||
```bash
|
||||
# View recent errors
|
||||
tail -f f_data/logs/error_$(date +%Y-%m-%d).log
|
||||
|
||||
# Search for specific issues
|
||||
grep "CRITICAL" f_data/logs/*.log
|
||||
|
||||
# Monitor performance
|
||||
grep "SLOW_QUERY" f_data/logs/*.log
|
||||
```
|
||||
|
||||
## Deployment Preparation
|
||||
|
||||
### Pre-deployment Checklist
|
||||
- [ ] All tests passing
|
||||
- [ ] Security review completed
|
||||
- [ ] Performance testing done
|
||||
- [ ] Database migrations ready
|
||||
- [ ] Configuration updated
|
||||
- [ ] Documentation updated
|
||||
|
||||
### Production Considerations
|
||||
- Disable debug mode
|
||||
- Configure proper logging levels
|
||||
- Set up monitoring and alerts
|
||||
- Implement backup procedures
|
||||
- Configure SSL/TLS properly
|
||||
|
||||
## Code Review Guidelines
|
||||
|
||||
### Review Checklist
|
||||
- [ ] Code follows project standards
|
||||
- [ ] Security best practices implemented
|
||||
- [ ] Tests cover new functionality
|
||||
- [ ] Documentation updated
|
||||
- [ ] Performance impact considered
|
||||
- [ ] Error handling implemented
|
||||
- [ ] Logging added where appropriate
|
||||
|
||||
### Common Issues to Check
|
||||
- SQL injection vulnerabilities
|
||||
- XSS vulnerabilities
|
||||
- Missing input validation
|
||||
- Improper error handling
|
||||
- Performance bottlenecks
|
||||
- Missing tests
|
||||
- Inadequate logging
|
||||
Reference in New Issue
Block a user