Major refactor

- update the structure to have monolithic setup
- updated deployments
- added live-reloading for devops
This commit is contained in:
Théophile Gervreau-Mercier
2026-02-05 20:07:05 +01:00
parent f23fbb481b
commit d2b3c6ca67
75 changed files with 3359 additions and 3987 deletions

181
docs/DATABASE_CONFIG.md Normal file
View File

@@ -0,0 +1,181 @@
# Database Configuration
This document explains the centralized database configuration for the Post-ERG thesis management system.
## Overview
Database paths are centralized in `shared/config.php` to provide a single source of truth for:
- Test database location (development)
- Production database location (deployment)
- Environment detection logic
## Database Locations
```
database/
├── test.db # Development/testing database
└── posterg.db # Production database
```
## Configuration File
The `shared/config.php` file defines:
```php
// Test database (development)
DB_TEST_PATH = '/path/to/database/test.db'
// Production database (server)
DB_PROD_PATH = '/path/to/database/posterg.db'
```
## How It Works
### Automatic Detection
By default, the system automatically determines which database to use:
1. **If `database/test.db` exists** → Use test database (development mode)
2. **Otherwise** → Use production database (production mode)
This means:
- Developers get test database automatically when it exists
- Production server uses production database (no test.db present)
### Manual Override
You can force a specific database using the `DB_ENV` environment variable:
```bash
# Force test database
export DB_ENV=test
php apps/public/index.php
# Force production database
export DB_ENV=prod
php apps/public/index.php
```
### Custom Path Override
You can also pass a custom database path directly:
```php
// Use specific database file
$db = new Database('/custom/path/to/database.db');
// Or with singleton
$db = Database::getInstance('/custom/path/to/database.db');
```
## Deployment Workflow
### Development
When working locally:
```bash
# Create test database with fixtures
just create-fixtures
# Start development server (uses test.db automatically)
just serve-public
just serve-admin
```
### Production
When deploying to server:
```bash
# Deploy applications and shared code (excludes test.db automatically)
just deploy
# The deploy command explicitly excludes:
# - test.db (test database)
# - *.db (all database files)
# - tests/ (test suites)
# - cache/ (temporary files)
# - *.md (documentation)
# Result: Only posterg.db exists on server
# Application automatically uses production database
```
### Deploying Test Database (Explicitly)
If you need to deploy the test database to the server (for testing):
```bash
# This is a separate, explicit command
just test-deploy
# ⚠️ Warning: This will overwrite the remote test.db file
```
### Deploying Database Structure Only
To deploy schema and fixtures without databases:
```bash
# Deploy schema.sql and fixtures/ only (excludes all .db files)
just deploy-database
```
### Testing on Production
To test with production data locally:
```bash
# Download production database (optional)
scp posterg:/var/www/html/database/posterg.db database/
# Remove test database to force production mode
rm database/test.db
# Or set environment variable
export DB_ENV=prod
php apps/public/index.php
```
## Benefits of Centralized Configuration
1. **Single source of truth** - All database paths defined in one place
2. **Environment-aware** - Automatically detects development vs production
3. **Override capability** - Can force specific database when needed
4. **Maintainable** - Easy to update paths or add new environments
5. **Safe deployment** - Test database never deployed to production
## Integration with Database Class
The `Database` class automatically uses this configuration:
```php
require_once 'shared/Database.php';
// Automatically uses correct database based on environment
$db = new Database();
```
The path resolution order is:
1. Custom path (if provided)
2. `DB_ENV` environment variable
3. Auto-detection (test.db exists → test mode, otherwise → production)
## Helper Functions
`shared/config.php` provides helper functions:
```php
// Get current database path
$path = getDatabasePath();
// Check if running in test mode
if (isTestMode()) {
echo "Using test database";
}
```
## Notes
- **Deployment safety**: The `deploy`, `deploy-public`, and `deploy-admin` recipes explicitly exclude `test.db` and all `*.db` files
- **Explicit test deploy**: Use `just test-deploy` to explicitly deploy test.db when needed
- **Git ignored**: Test database is in `.gitignore` and never committed
- **Backups**: Production database should be backed up regularly
- **Schema**: Both databases use the same schema (`database/schema.sql`)
- **Verification**: Run `rsync --dry-run` to preview what will be deployed before deploying

507
docs/DEVELOPMENT_GUIDE.md Normal file
View File

@@ -0,0 +1,507 @@
# Post-ERG Development Guide
Complete guide for developing the Post-ERG thesis management system.
## 🚀 Quick Start
### 1. Setup (One Time)
```bash
# Clone php-live-reload and setup directories
just setup
```
### 2. Start Development Server
```bash
just serve
```
This starts **one unified server** at:
- **Public site:** http://localhost:8000
- **Admin panel:** http://localhost:8000/admin/
**Live reload enabled** - your browser auto-refreshes when you save files!
### 3. Edit & Watch
Edit any PHP file and watch your browser automatically refresh! 🎉
---
## 📁 Project Structure
```
posterg-website/
├── index.php # Public homepage
├── memoire.php # Thesis detail page
├── search.php # Search page
├── *.php # Other public pages
├── admin/ # Admin panel
│ ├── index.php # Admin dashboard
│ ├── list.php # Thesis list
│ ├── edit.php # Edit thesis
│ └── formulaire.php # Add thesis
├── lib/ # Shared libraries
│ ├── Database.php # Database class
│ ├── RateLimit.php # Rate limiting
│ └── config.php # Configuration
├── inc/ # Page templates
│ ├── header.php # Site header
│ └── footer.php # Site footer
├── assets/ # Static files
│ ├── posterg.css # Main CSS
│ └── fonts/ # Custom fonts
├── database/ # Database
│ ├── schema.sql # Schema definition
│ ├── test.db # Test database
│ └── fixtures/ # Sample data
├── tests/ # Test suite
│ ├── Unit/ # Unit tests
│ ├── Integration/ # Integration tests
│ └── Security/ # Security tests
└── vendor/ # Third-party (gitignored)
└── php-live-reload/
```
---
## 🛠️ Development Workflow
### Starting Development
```bash
# Start the development server
just serve
# In your browser:
# - Public site: http://localhost:8000
# - Admin panel: http://localhost:8000/admin/
```
### Making Changes
1. **Edit PHP files** - Auto-refreshes browser
2. **Edit CSS** - Auto-refreshes browser
3. **Test changes** - See them instantly!
### Running Tests
```bash
# Run all tests
just test
# Run specific test suites
just test-unit # Unit tests
just test-integration # Integration tests
just test-security # Security tests
```
### Database Operations
```bash
# View database stats
just stats
# Open SQLite shell
just query
# Show specific thesis
just show 42
# Reset database
just reset-db
# Create with sample data
just fixtures
```
---
## 📝 Common Tasks
### Create a New Page
1. Create `newpage.php` in root
2. Add `require_once __DIR__ . '/lib/Database.php';`
3. Include header: `include 'inc/header.php';`
4. Add your content
5. Include footer: `include 'inc/footer.php';`
Example:
```php
<?php
require_once __DIR__ . '/lib/Database.php';
include 'inc/header.php';
?>
<section class="section">
<div class="container">
<h1 class="title">My New Page</h1>
<p>Content here...</p>
</div>
</section>
<?php include 'inc/footer.php'; ?>
```
### Add a Database Function
1. Edit `lib/Database.php`
2. Add your method to the `Database` class
3. Write a test in `tests/Unit/DatabaseTest.php`
4. Run tests: `just test-unit`
### Update CSS
1. Edit `assets/posterg.css`
2. Browser auto-refreshes!
3. (Optional) Increment version in `inc/header.php`: `posterg.css?v=3`
### Add a Test
1. Choose location:
- `tests/Unit/` - For testing classes/functions
- `tests/Integration/` - For testing workflows
- `tests/Security/` - For testing security
2. Create test file (e.g., `tests/Unit/MyTest.php`)
3. Follow the template in `tests/README.md`
4. Add to `tests/run-tests.php`
5. Run: `just test`
---
## 🧪 Testing
### Test Database
Development uses `database/test.db` (gitignored).
**Create test database:**
```bash
just init-db
```
**Populate with sample data:**
```bash
just fixtures
```
**Deploy test database to server:**
```bash
just deploy-test-db
```
**Reset everything:**
```bash
just reset-db
```
### Writing Tests
See `tests/README.md` for complete testing guide.
**Quick example:**
```php
<?php
require_once __DIR__ . '/../../lib/Database.php';
echo "My Test\n";
echo "=======\n\n";
try {
$db = Database::getInstance();
echo "✓ PASS: Test passed\n";
return true;
} catch (Exception $e) {
echo "❌ FAIL: " . $e->getMessage() . "\n";
return false;
}
```
---
## 🚀 Deployment
### Deploy Everything
```bash
just deploy
```
This deploys:
- Public site (root PHP files)
- Admin panel (`admin/`)
- Shared libraries (`lib/`)
**Note:** `vendor/` is automatically excluded from deployment.
### Deploy Selectively
```bash
# Deploy only the code
just deploy
# Deploy test database
just deploy-test-db
# Deploy nginx config
just deploy-nginx
# Deploy admin tools
just deploy-admin-tools
```
---
## 🔧 Justfile Commands
### Development
| Command | Description |
|---------|-------------|
| `just setup` | Setup development environment (one-time) |
| `just serve` | Start development server with live reload |
| `just stop` | Stop development server |
| `just logs` | View development logs |
### Testing
| Command | Description |
|---------|-------------|
| `just test` | Run all tests |
| `just test-unit` | Run unit tests |
| `just test-integration` | Run integration tests |
| `just test-security` | Run security tests |
| `just syntax` | Check PHP syntax |
### Database
| Command | Description |
|---------|-------------|
| `just init-db` | Create test database |
| `just reset-db` | Reset test database |
| `just query` | Open SQLite shell |
| `just show <id>` | Show thesis by ID |
| `just backup` | Backup database |
| `just fixtures` | Create sample data |
| `just deploy-test-db` | Deploy test database to server |
### Statistics
| Command | Description |
|---------|-------------|
| `just stats` | Show database statistics |
| `just recent` | Show recent theses |
### Deployment
| Command | Description |
|---------|-------------|
| `just deploy` | Deploy complete site |
| `just deploy-nginx` | Deploy nginx configuration |
| `just deploy-admin-tools` | Deploy admin user management |
### Server
| Command | Description |
|---------|-------------|
| `just server-logs` | View server logs |
| `just server-status` | Check server status |
### Utilities
| Command | Description |
|---------|-------------|
| `just clean` | Clean up dev files |
| `just setup-dirs` | Create data directories |
---
## 💡 Tips & Tricks
### Live Reload
The `just serve` command uses php-live-reload to automatically refresh your browser when you save files.
**What triggers refresh:**
- Saving any `.php` file
- Saving any file in the project
**How it works:**
- WebSocket connection monitors file changes
- Browser receives reload signal
- Page refreshes automatically
**No browser extension needed!**
### Multiple Browser Windows
Open multiple browser windows/tabs - they all get live reload!
```
http://localhost:8000/ # Public site
http://localhost:8000/admin/ # Admin panel
http://localhost:8000/memoire.php?id=13 # Specific thesis
```
All will auto-refresh when you save files! ✨
### Using a Real Test Database
The test database (`database/test.db`) is gitignored. To share test data:
```bash
# Create fixtures
just fixtures
# Commit the fixtures generator
git add database/fixtures/
git commit -m "Update test fixtures"
```
Others can recreate with: `just fixtures`
### Debugging
**Check error logs:**
```bash
just logs
```
**Or directly:**
```bash
tail -f error.log
```
**PHP errors in browser:**
Edit your PHP file temporarily:
```php
ini_set('display_errors', 1);
error_reporting(E_ALL);
```
**Database issues:**
```bash
# Check database exists
ls -lh database/test.db
# Open database shell
just query
# Check tables
sqlite> .tables
# Show schema
sqlite> .schema theses
```
---
## 🔍 Troubleshooting
### Server won't start
**Port already in use:**
```bash
just stop
# Or manually:
pkill -f "php -S 127.0.0.1:8000"
```
**php-live-reload missing:**
```bash
just setup
```
### Live reload not working
**Check vendor directory:**
```bash
ls -la vendor/php-live-reload/
```
**Reinstall:**
```bash
rm -rf vendor/php-live-reload
just setup
```
### Database errors
**Database not found:**
```bash
just init-db
```
**Permissions error:**
```bash
chmod 644 database/test.db
```
**Schema errors:**
```bash
just reset-db
```
### Tests failing
**Run individual test:**
```bash
php tests/Unit/DatabaseTest.php
```
**Check database:**
```bash
just stats
```
**Reset database:**
```bash
just reset-db
just fixtures
just test
```
---
## 📚 Further Reading
- [Test Documentation](../tests/README.md)
- [Database Specification](../database/DATABASE_SPECIFICATION.md)
- [Migration Guide](../MIGRATION_GUIDE.md)
- [Deployment Guide](../nginx/DEPLOYMENT_COMPLETE.md)
---
## ✨ Quick Reference
**Start developing:**
```bash
just setup # One time
just serve # Start server
```
**Test your changes:**
```bash
just test # Run tests
just stats # Check database
```
**Deploy to production:**
```bash
just deploy
```
That's it! Happy coding! 🚀

297
docs/LIVE_RELOAD_SETUP.md Normal file
View File

@@ -0,0 +1,297 @@
# Live Reload Setup
Guide to setting up and using live reload for Post-ERG development.
## 🎯 What is Live Reload?
Live reload automatically refreshes your browser when you save files during development. No need to manually hit refresh!
## ✨ How It Works
1. **JavaScript** in the page polls the server for file changes
2. **PHP backend** checks file modification times
3. **Browser** automatically refreshes when changes detected
**No browser extension needed!**
---
## 🚀 Setup (One Time)
```bash
just setup
```
This clones `php-live-reload` into `vendor/php-live-reload/` (which is gitignored).
---
## 🏃 Using Live Reload
### Start Server
```bash
just serve
```
Output:
```
🚀 Starting Post-ERG development server
========================================
📍 Public site: http://localhost:8000
📍 Admin panel: http://localhost:8000/admin/
✨ Live reload enabled - browser auto-refreshes on file save!
Press Ctrl+C to stop
```
### Edit Files
1. Open http://localhost:8000 in your browser
2. Edit any PHP, CSS, or JS file
3. Save the file
4. **Browser automatically refreshes!**
### What Triggers Reload
- Saving `.php` files
- Saving `.css` files
- Saving `.js` files
- Any file change in the project
---
## 🔧 How It's Integrated
### In `inc/header.php`
Live reload script is conditionally included only during development:
```php
<?php if (getenv('PHP_ENV') === 'development' || php_sapi_name() === 'cli-server'): ?>
<!-- Live reload for development -->
<script src="/vendor/php-live-reload/php-live-reload/live-reload.js"></script>
<?php endif; ?>
```
**Result:**
- ✅ Included when using `php -S` (development server)
- ❌ NOT included in production (nginx/apache)
- ❌ NOT deployed to server (vendor/ is gitignored)
### Detection Logic
```php
php_sapi_name() === 'cli-server' // True when using PHP dev server
```
This means live reload is automatically enabled/disabled based on environment!
---
## 📁 File Structure
```
vendor/php-live-reload/
├── php-live-reload/
│ ├── live-reload.js # JavaScript client
│ ├── live-reload.php # PHP backend (checks files)
│ └── config.php # Configuration
└── README.md
```
---
## 🧪 Testing Live Reload
### Test It Works
1. Start server: `just serve`
2. Open http://localhost:8000
3. Open browser console (F12)
4. Edit `index.php` and save
5. Watch browser auto-refresh!
You'll see in console:
```javascript
GET /vendor/php-live-reload/php-live-reload/live-reload.php
change detected
```
---
## ⚙️ Configuration
### Polling Interval
Default: Checks every ~1-2 seconds
To change, edit `vendor/php-live-reload/php-live-reload/config.php`:
```php
define('MIN_DELAY', 1000); // Minimum milliseconds between checks
```
### File Watching
By default, watches all files in project directory.
To exclude paths, edit config:
```php
$exclude = [
'vendor',
'.git',
'node_modules',
'cache'
];
```
---
## 🐛 Troubleshooting
### Live Reload Not Working
**1. Check vendor directory exists:**
```bash
ls -la vendor/php-live-reload/
```
If missing:
```bash
just setup
```
**2. Check script is included in page:**
```bash
curl -s http://localhost:8000/ | grep live-reload
```
Should show:
```html
<script src="/vendor/php-live-reload/php-live-reload/live-reload.js"></script>
```
**3. Check endpoint is accessible:**
```bash
curl http://localhost:8000/vendor/php-live-reload/php-live-reload/live-reload.php
```
Should return JSON:
```json
{"time": 10, "changed": false}
```
**4. Check browser console for errors**
Open browser console (F12) and look for:
- WebSocket errors
- Network errors to `/vendor/php-live-reload/`
### Script Not Loading
**Make sure you're using dev server:**
```bash
just serve
```
NOT production (nginx/apache).
**Check PHP detection:**
```bash
php -r "echo php_sapi_name();"
```
When using `just serve`, should output: `cli-server`
### Changes Not Detected
**Check polling is working:**
Open browser console, you should see repeated requests to:
```
/vendor/php-live-reload/php-live-reload/live-reload.php
```
If not, check JavaScript loaded:
```bash
curl -I http://localhost:8000/vendor/php-live-reload/php-live-reload/live-reload.js
```
Should return `200 OK`.
---
## 🚫 Production Behavior
### Automatically Disabled
Live reload is **automatically disabled** in production because:
1. **`php_sapi_name()` check**: Only true with PHP dev server
2. **vendor/ gitignored**: Not deployed to server
3. **nginx serves files**: Different SAPI, condition false
### Verification
On production server:
```bash
curl https://posterg.erg.be/ | grep live-reload
```
Should return nothing (script not included).
---
## 💡 Tips
### Multiple Browser Windows
Open multiple tabs/windows - they all get live reload!
```
http://localhost:8000/ # Homepage
http://localhost:8000/admin/ # Admin panel
http://localhost:8000/memoire.php?id=13 # Thesis page
```
All will auto-refresh on file changes.
### Faster Development
With live reload:
1. ✅ Edit code
2. ✅ Save
3. ✅ Browser refreshes
4. ✅ See changes instantly!
No more:
1. ❌ Edit code
2. ❌ Save
3. ❌ Switch to browser
4. ❌ Hit F5
5. ❌ Switch back to editor
**Saves you seconds on every change!**
---
## 📚 More Information
- GitHub: https://github.com/ryantate13/php-live-reload
- Alternative: https://github.com/guard/guard-livereload
---
## ✅ Quick Reference
| Command | Description |
|---------|-------------|
| `just setup` | Install live reload (one time) |
| `just serve` | Start server with live reload |
| `just stop` | Stop server |
**To use:** `just serve` and edit files - browser auto-refreshes! ✨

476
docs/MIGRATION_GUIDE.md Normal file
View File

@@ -0,0 +1,476 @@
# Repository Restructure Migration Guide
This guide explains how to migrate the Post-ERG repository to a standard idiomatic PHP structure.
## 📋 Overview
### Current Structure
```
posterg-website/
├── apps/
│ ├── public/ # Public website
│ └── admin/ # Admin panel
├── shared/ # Shared PHP libraries
└── database/ # Database files
```
### New Structure (Standard PHP)
```
posterg-website/
├── index.php # Public root
├── *.php # Public PHP files
├── admin/ # Admin panel
├── lib/ # Shared libraries (renamed from shared/)
├── inc/ # Templates (header/footer)
├── assets/ # Static files
├── database/ # Database files
└── vendor/ # Third-party code (gitignored)
```
---
## 🎯 Benefits
**Standard PHP structure** - Follows community conventions
**Flatter hierarchy** - Easier navigation
**Simpler paths** - Less `../../` in code
**Cleaner deployment** - Single rsync command
**Live reload** - Auto-refresh during development
---
## 🚀 Migration Steps
### Step 1: Review the Plan
Read the restructure plan:
```bash
cat docs/RESTRUCTURE_PLAN.md
```
### Step 2: Commit Current State
**Important:** Commit all your current work first!
```bash
git add -A
git commit -m "Pre-migration checkpoint"
```
### Step 3: Run Migration Script
```bash
./migrate-structure.sh
```
This will:
- Move `apps/public/*` to root
- Move `apps/admin/` to `admin/`
- Rename `shared/` to `lib/`
- Update all `require` paths automatically
- Remove `apps/` directory
- Update `.gitignore`
### Step 4: Test Locally
```bash
# Setup development environment
just setup-dev
# Test public site (with live reload!)
just serve-public
# Test admin panel
just serve-admin
```
Visit:
- http://localhost:8000 - Public site
- http://localhost:3000 - Admin panel
### Step 5: Verify Changes
```bash
# Check syntax
just check-public
# Run database tests
just stats-public
# View structure
tree -L 2 -I 'node_modules|.git|vendor'
```
### Step 6: Update Justfile
```bash
# Backup old justfile
mv justfile justfile.old
# Use new justfile
mv justfile.new justfile
```
### Step 7: Commit Migration
```bash
git add -A
git commit -m "Restructure to idiomatic PHP layout
- Moved apps/public to root
- Moved apps/admin to admin/
- Renamed shared/ to lib/
- Added php-live-reload for local dev
- Updated all require paths
- Simplified deployment"
```
### Step 8: Deploy to Production
```bash
# Deploy everything
just deploy
# Or deploy separately
just deploy-public
just deploy-admin
```
---
## 📝 What Changed
### File Movements
| Old Path | New Path |
|----------|----------|
| `apps/public/index.php` | `index.php` |
| `apps/public/memoire.php` | `memoire.php` |
| `apps/public/assets/` | `assets/` |
| `apps/public/inc/` | `inc/` |
| `apps/admin/` | `admin/` |
| `shared/Database.php` | `lib/Database.php` |
| `shared/config.php` | `lib/config.php` |
| `shared/cache/` | `lib/cache/` |
### Path Updates
All PHP files automatically updated:
**Root files:**
```php
// Before
require_once __DIR__ . '/shared/Database.php';
// After
require_once __DIR__ . '/lib/Database.php';
```
**Admin files:**
```php
// Before
require_once __DIR__ . '/../../shared/Database.php';
// After
require_once __DIR__ . '/../lib/Database.php';
```
**Config file:**
```php
// Before
define('DB_ROOT', __DIR__ . '/..');
// After (stays the same)
define('DB_ROOT', __DIR__ . '/..');
```
### Justfile Changes
**Before:**
```bash
just serve-public # Basic PHP server
```
**After:**
```bash
just setup-dev # One-time: Install php-live-reload
just serve-public # PHP server with live reload!
```
**Before:**
```bash
# Deploy in multiple steps
rsync apps/public/ posterg:/var/www/html/
rsync apps/admin/ posterg:/var/www/html/formulaire/
rsync shared/ posterg:/var/www/html/shared/
```
**After:**
```bash
# Deploy in one command
just deploy
```
---
## 🔄 PHP Live Reload
### What It Does
Automatically refreshes your browser when you save PHP files!
### Setup (One Time)
```bash
just setup-dev
```
This clones https://github.com/ryantate13/php-live-reload to `vendor/php-live-reload/` (gitignored).
### Usage
```bash
# Start with live reload
just serve-public # or serve-admin
# Edit PHP files
# Browser auto-refreshes on save! 🎉
```
### How It Works
- Monitors PHP files for changes
- Sends reload signal via WebSocket
- Browser reloads automatically
- No browser extension needed
- Only for local development
- Never deployed to production
---
## 🧪 Testing
### Before Deploying
1. **Syntax check:**
```bash
just check-public
```
2. **Test database:**
```bash
just stats-public
```
3. **Test public site:**
```bash
just serve-public
# Visit http://localhost:8000
```
4. **Test admin:**
```bash
just serve-admin
# Visit http://localhost:3000
```
5. **Check file permissions:**
```bash
ls -la | head -n 20
ls -la admin/ | head -n 20
ls -la lib/
```
### After Deploying
1. **Test public site:**
```bash
curl -I https://posterg.erg.be/
```
2. **Test CSS loading:**
```bash
curl -I https://posterg.erg.be/assets/posterg.css
```
3. **Test admin:**
```bash
curl -I https://posterg.erg.be/admin/
```
---
## 🔙 Rollback (If Needed)
If something goes wrong:
```bash
# Revert the migration
git reset --hard HEAD~1
# Or restore from backup
git checkout HEAD~1 -- .
```
---
## 📚 New Directory Structure
```
posterg-website/
├── index.php # Public site root
├── memoire.php # Thesis detail page
├── search.php # Search page
├── apropos.php # About page
├── contact.php # Contact page
├── licences.php # Licenses page
├── test_db.php # Database test script
├── assets/ # Static files
│ ├── posterg.css # Main CSS
│ ├── normalize.css # CSS reset
│ ├── fonts/ # Custom fonts
│ └── icons.svg # Icon set
├── inc/ # Page templates
│ ├── header.php # Site header
│ └── footer.php # Site footer
├── lib/ # Shared libraries (was shared/)
│ ├── Database.php # Database class
│ ├── RateLimit.php # Rate limiting
│ ├── config.php # Configuration
│ └── cache/ # Cache files
├── admin/ # Admin panel (was apps/admin/)
│ ├── index.php # Admin dashboard
│ ├── list.php # Thesis list
│ ├── edit.php # Edit thesis
│ ├── formulaire.php # Add thesis
│ ├── import.php # Import tool
│ └── data/ # Upload directories
├── database/ # Database files & schema
│ ├── schema.sql # Database schema
│ ├── test.db # Test database
│ ├── fixtures/ # Test data generators
│ └── *.md # Documentation
├── vendor/ # Third-party code (gitignored)
│ └── php-live-reload/ # Live reload tool
├── nginx/ # Server configuration
├── docs/ # Documentation
├── tests/ # Tests (future)
├── justfile # Task runner
├── .gitignore # Git ignore rules
└── README.md # Project readme
```
---
## ❓ FAQ
### Q: Will the migration break the deployed site?
**A:** No. The migration only affects your local repository. Deploy only after testing locally.
### Q: Do I need to update the database?
**A:** No. The database structure doesn't change. Only file paths change.
### Q: What about nginx configuration?
**A:** Nginx config doesn't need to change. It still serves from `/var/www/html/`.
### Q: Will git history be preserved?
**A:** Yes. Git tracks file movements. Use `git log --follow filename.php` to see history.
### Q: Can I undo the migration?
**A:** Yes. Use `git reset --hard HEAD~1` before committing.
### Q: Does php-live-reload work on all platforms?
**A:** Yes. Works on Linux, macOS, and Windows (with PHP installed).
### Q: Will php-live-reload be deployed?
**A:** No. It's in `vendor/` which is gitignored and excluded from deployment.
---
## 🆘 Troubleshooting
### Migration script fails
**Check you're in the repo root:**
```bash
pwd
ls -la apps shared
```
**Make script executable:**
```bash
chmod +x migrate-structure.sh
```
### PHP can't find lib/ files
**Check paths were updated:**
```bash
grep -r "require.*lib/" . --include="*.php" | head -n 5
```
**Manually fix a file:**
```bash
# Edit the file and change:
require_once __DIR__ . '/shared/Database.php';
# To:
require_once __DIR__ . '/lib/Database.php';
```
### Live reload doesn't work
**Check vendor directory:**
```bash
ls -la vendor/php-live-reload/
```
**Re-run setup:**
```bash
just setup-dev
```
### Site works locally but not on server
**Check file permissions on server:**
```bash
ssh posterg "ls -la /var/www/html/ | head -n 20"
```
**Re-run deployment:**
```bash
just deploy
```
---
## 📞 Need Help?
1. **Check the plan:** `cat docs/RESTRUCTURE_PLAN.md`
2. **Review justfile:** `cat justfile`
3. **Check git status:** `git status`
4. **Test locally first:** `just serve-public`
---
**Ready to migrate?**
```bash
./migrate-structure.sh
```
Good luck! 🚀

View File

@@ -0,0 +1,534 @@
# Repository Structure Analysis
## Current Structure
```
posterg-website/ (monorepo root)
├── front-backend/ Public-facing site
│ ├── index.php Browse theses
│ ├── search.php Search feature
│ ├── memoire.php View individual thesis
│ ├── Database.php DB connection (reads ../formulaire/test.db)
│ ├── RateLimit.php Rate limiting
│ ├── tests/ Tests (Unit/Integration/Security)
│ ├── assets/ CSS, images
│ └── inc/ Header/footer templates
├── formulaire/ Submission system (admin)
│ ├── index.php List submissions
│ ├── formulaire.php Submission form
│ ├── edit.php Edit submissions
│ ├── Database.php DB connection (different implementation!)
│ ├── assets/ CSS, images
│ └── data/ Upload storage
├── db/ Shared database schemas
│ ├── schema.sql Database structure
│ ├── posterg.db Production database
│ └── README.md Documentation
├── justfile Deployment recipes
└── README.md
```
## Deployment Model
```bash
# front-backend → /var/www/html/ (root domain)
rsync ./front-backend/ server:/var/www/html/
# formulaire → /var/www/html/formulaire/ (subdomain or /formulaire path)
rsync ./formulaire/ server:/var/www/html/formulaire/
```
**URL Structure:**
- Public site: `https://posterg.example.com/`
- Admin/submission: `https://posterg.example.com/formulaire/`
## Issues with Current Structure
### ❌ Problems
1. **Inconsistent Database Access**
- `front-backend/Database.php` points to `../formulaire/test.db`
- `formulaire/Database.php` points to `../db/posterg.db` (production)
- Different implementations, different paths
2. **Code Duplication**
- Two separate `Database.php` files with different logic
- No shared code between front-backend and formulaire
3. **Confusing Dependencies**
- front-backend depends on formulaire for database location
- Circular/unclear relationship
4. **Test Database Location**
- Currently in `formulaire/test.db`
- Should be in `db/` with schema
---
## Option Analysis
### Option A: Keep Monorepo, Improve Organization ⭐ RECOMMENDED
```
posterg-website/
├── apps/ Application code
│ ├── public/ Public-facing site (was front-backend)
│ │ ├── index.php
│ │ ├── search.php
│ │ ├── memoire.php
│ │ ├── assets/
│ │ ├── inc/
│ │ └── tests/
│ │
│ └── admin/ Submission system (was formulaire)
│ ├── index.php
│ ├── formulaire.php
│ ├── edit.php
│ ├── assets/
│ └── data/
├── shared/ Shared code
│ ├── Database.php Single DB class used by both apps
│ └── RateLimit.php Shared utilities
├── database/ Database files (was db/)
│ ├── schema.sql
│ ├── posterg.db Production database
│ ├── test.db Test database
│ └── README.md
├── justfile Deployment
├── composer.json Dependencies
└── README.md
```
**Pros:**
- ✅ Clear separation: public vs admin
- ✅ Shared code in one place (DRY)
- ✅ Single source of truth for database
- ✅ Professional naming (apps/, shared/, database/)
- ✅ Easy to add more apps later
**Cons:**
- ⚠️ Requires refactoring paths in all files
- ⚠️ Need to update deployment scripts
**Migration Effort:** Medium (2-3 hours)
---
### Option B: Promote front-backend to Root
```
posterg-website/ (IS the public site)
├── index.php Public site files at root
├── search.php
├── memoire.php
├── Database.php
├── RateLimit.php
├── assets/
├── inc/
├── tests/
├── formulaire/ Keep admin as subfolder
│ ├── index.php
│ ├── formulaire.php
│ └── ...
└── db/ Shared database
├── schema.sql
└── posterg.db
```
**Pros:**
- ✅ Simpler paths for main application
- ✅ Less nesting
- ✅ Minimal refactoring needed
**Cons:**
- ❌ Root directory becomes cluttered
- ❌ Mixed responsibilities (public site + monorepo management)
- ❌ Still have duplicate Database.php files
- ❌ Harder to add new applications
- ❌ Tests mixed with application code at root
**Migration Effort:** Low (30 mins)
---
### Option C: Flatten Everything
```
posterg-website/
├── public/ Public site (was front-backend)
├── admin/ Submission (was formulaire)
├── database/ Schemas (was db)
├── shared/ Shared code
├── tests/ All tests
├── composer.json
└── justfile
```
**Pros:**
- ✅ Very clean root directory
- ✅ Professional structure
- ✅ Clear naming
**Cons:**
- ❌ Deployment scripts need updates
- ❌ All tests in one place (less clear ownership)
**Migration Effort:** Medium (2 hours)
---
### Option D: Keep Current Structure, Fix Issues
```
posterg-website/
├── front-backend/ Keep as-is
│ └── (no Database.php here)
├── formulaire/ Keep as-is
│ └── (no Database.php here)
├── shared/ NEW: Shared code
│ ├── Database.php Single database class
│ └── RateLimit.php
└── db/ Keep as-is
├── schema.sql
├── posterg.db
└── test.db
```
**Pros:**
- ✅ Minimal changes
- ✅ Keeps familiar structure
- ✅ Fixes code duplication
**Cons:**
- ⚠️ Still nested (front-backend, formulaire)
- ⚠️ Names not professional (what does "front-backend" mean?)
**Migration Effort:** Low (1 hour)
---
## Detailed Recommendation: Option A
### Why Option A is Best
1. **Scalability** - Easy to add new apps:
- `apps/api/` for REST API
- `apps/import/` for batch imports
- Each app is independent
2. **Professional** - Industry standard structure:
- Clear naming (`public`, `admin`, `shared`)
- Other developers understand immediately
- Matches Laravel, Symfony conventions
3. **Maintainability**:
- Single Database.php used by all apps
- Shared utilities (RateLimit) in one place
- Tests stay with their applications
4. **Deployment Clarity**:
```just
deploy-public:
rsync apps/public/ server:/var/www/html/
deploy-admin:
rsync apps/admin/ server:/var/www/html/formulaire/
deploy-shared:
rsync shared/ server:/var/www/html/shared/
```
### Proposed Structure Details
```
posterg-website/
├── apps/ Applications
│ ├── public/ Public-facing site
│ │ ├── index.php Homepage (browse theses)
│ │ ├── search.php Search interface
│ │ ├── memoire.php Individual thesis view
│ │ ├── apropos.php, contact.php, licences.php
│ │ ├── assets/ Public CSS, images
│ │ ├── inc/ Templates (header, footer)
│ │ └── tests/ Public site tests
│ │ ├── Unit/
│ │ ├── Integration/
│ │ ├── Security/
│ │ └── Fixtures/
│ │
│ └── admin/ Admin/submission system
│ ├── index.php Dashboard (list theses)
│ ├── formulaire.php Submission form
│ ├── edit.php Edit submission
│ ├── import.php Bulk import
│ ├── list.php List view
│ ├── assets/ Admin CSS
│ ├── data/ File uploads
│ └── tests/ Admin tests (optional)
├── shared/ Shared code (library)
│ ├── Database.php Single database class
│ ├── RateLimit.php Rate limiting
│ └── (future shared utilities)
├── database/ Database files & schemas
│ ├── schema.sql Database structure
│ ├── migrations/ Migration scripts (future)
│ ├── fixtures/ Test data
│ │ └── CreateTestDatabase.php
│ ├── posterg.db Production database (gitignored)
│ └── test.db Test database (gitignored)
├── config/ Configuration (optional)
│ ├── database.php DB connection settings
│ └── paths.php Path constants
├── .gitignore Git exclusions
├── justfile Deployment recipes
├── composer.json Dependencies
├── run-tests.php Test runner
└── README.md Documentation
```
### Migration Steps for Option A
1. **Create new structure** (no breaking changes yet):
```bash
mkdir -p apps/{public,admin}
mkdir -p shared
mkdir -p database/fixtures
```
2. **Move applications**:
```bash
mv front-backend/* apps/public/
mv formulaire/* apps/admin/
rmdir front-backend formulaire
```
3. **Create shared Database.php**:
- Merge best parts of both Database.php files
- Make database path configurable
- Use production db by default
4. **Move shared utilities**:
```bash
mv apps/public/RateLimit.php shared/
```
5. **Reorganize database**:
```bash
mv db database
mv apps/public/tests/Fixtures/CreateTestDatabase.php database/fixtures/
```
6. **Update all `require_once` paths**:
```php
// In apps/public/index.php
require_once __DIR__ . '/../../shared/Database.php';
require_once __DIR__ . '/../../shared/RateLimit.php';
// In apps/admin/index.php
require_once __DIR__ . '/../../shared/Database.php';
```
7. **Update Database.php to use config**:
```php
class Database {
private function __construct() {
// Determine database path
$dbPath = $this->getDatabasePath();
$this->pdo = new PDO('sqlite:' . $dbPath);
// ...
}
private function getDatabasePath() {
// Check environment
if (file_exists(__DIR__ . '/../database/test.db')) {
return __DIR__ . '/../database/test.db';
}
return __DIR__ . '/../database/posterg.db';
}
}
```
8. **Update justfile**:
```just
[group('deploy')]
deploy-public:
rsync -vur --progress \
--exclude 'tests/' \
--exclude '*.md' \
apps/public/ posterg:/var/www/html/
rsync -vur shared/ posterg:/var/www/html/shared/
[group('deploy')]
deploy-admin:
rsync -vur --progress \
--exclude 'tests/' \
apps/admin/ posterg:/var/www/html/formulaire/
[group('deploy')]
deploy: deploy-public deploy-admin
```
9. **Update .gitignore**:
```
/database/*.db
/apps/*/cache/
/shared/cache/
*.log
```
10. **Test everything**:
```bash
php run-tests.php
```
---
## Alternative: Quick Fix (Option D)
If you don't want major refactoring right now:
### Minimal Changes to Current Structure
1. **Create shared/ directory**:
```bash
mkdir shared
```
2. **Create unified Database.php in shared/**:
```php
// shared/Database.php - works for both apps
class Database {
private function __construct() {
// Smart path detection
if (file_exists(__DIR__ . '/../db/test.db')) {
$dbPath = __DIR__ . '/../db/test.db';
} else {
$dbPath = __DIR__ . '/../db/posterg.db';
}
$this->pdo = new PDO('sqlite:' . $dbPath);
// ... rest of implementation
}
}
```
3. **Move RateLimit.php to shared/**:
```bash
mv front-backend/RateLimit.php shared/
```
4. **Update both apps to use shared/**:
```php
// In front-backend/index.php
require_once __DIR__ . '/../shared/Database.php';
// In formulaire/index.php
require_once __DIR__ . '/../shared/Database.php';
```
5. **Delete duplicate Database.php files**:
```bash
rm front-backend/Database.php
rm formulaire/Database.php
```
**Result:**
```
posterg-website/
├── front-backend/ (uses shared/)
├── formulaire/ (uses shared/)
├── shared/ NEW: shared code
│ ├── Database.php
│ └── RateLimit.php
└── db/ (existing)
```
---
## Comparison Matrix
| Criteria | Option A (Restructure) | Option B (Root) | Option C (Flatten) | Option D (Quick Fix) | Current |
|----------|----------------------|-----------------|-------------------|---------------------|---------|
| **Professional** | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| **Scalable** | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| **Clear Separation** | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| **Ease of Migration** | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | N/A |
| **Code Reuse** | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ |
| **Maintainability** | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
---
## Final Recommendation
### Short Term: Option D (Quick Fix)
- Takes 1 hour
- Fixes code duplication immediately
- Minimal risk
- Keeps familiar structure
### Long Term: Option A (Full Restructure)
- Plan for when you have 2-3 hours
- Professional, scalable structure
- Industry standard conventions
- Future-proof
### Do NOT: Option B (Promote to Root)
- Creates more problems than it solves
- Clutters root directory
- Doesn't fix core issues
---
## Questions to Consider
1. **How often do you modify both apps?**
- Often → Option A (shared code helps)
- Rarely → Option D is fine
2. **Will you add more applications?**
- Yes (API, mobile backend, etc.) → Option A
- No → Option D
3. **Team size?**
- Solo → Option D ok
- Team → Option A for clarity
4. **Timeline?**
- Urgent → Option D
- Can wait → Option A
---
## My Recommendation
**Start with Option D (Quick Fix), migrate to Option A later.**
**Immediate (30 mins):**
1. Create `shared/` directory
2. Move Database.php and RateLimit.php to shared/
3. Update both apps to use shared/
4. Test and deploy
**When you have time (Option A):**
- Better names (`apps/public/`, `apps/admin/`)
- Professional structure
- Industry conventions
Would you like me to help implement either approach?

135
docs/RESTRUCTURE_PLAN.md Normal file
View File

@@ -0,0 +1,135 @@
# Repository Restructure Plan
## Current Structure
```
posterg-website/
├── apps/
│ ├── public/ # Public website
│ └── admin/ # Admin panel
├── shared/ # Shared PHP libraries
├── database/ # Database files
├── nginx/ # Server config
└── docs/ # Documentation
```
## Proposed Structure (Idiomatic PHP)
```
posterg-website/
├── index.php # Public website root
├── memoire.php
├── search.php
├── apropos.php
├── contact.php
├── licences.php
├── assets/ # Static files (CSS, JS, images)
│ ├── posterg.css
│ ├── normalize.css
│ └── fonts/
├── inc/ # Page templates/partials
│ ├── header.php
│ └── footer.php
├── lib/ # Shared libraries (renamed from shared/)
│ ├── Database.php
│ ├── RateLimit.php
│ ├── config.php
│ └── cache/
├── admin/ # Admin panel (from apps/admin/)
│ ├── index.php
│ ├── list.php
│ ├── edit.php
│ └── ...
├── database/ # Database files & schema
│ ├── schema.sql
│ ├── test.db
│ └── ...
├── vendor/ # Third-party dependencies (gitignored)
│ └── php-live-reload/ # Local dev only
├── nginx/ # Server configuration
├── docs/ # Documentation
├── tests/ # Tests (future)
└── .gitignore # Updated
```
## Benefits
**Standard PHP structure** - Follows common conventions
**Flatter hierarchy** - Easier to navigate
**Clear separation** - lib/ for code, inc/ for templates, assets/ for static files
**Simpler paths** - Less `../../` in require statements
**Vendor folder** - Standard for third-party code
## Migration Steps
### 1. Move public to root
```bash
mv apps/public/* .
```
### 2. Move admin
```bash
mv apps/admin admin/
rm -rf apps/
```
### 3. Rename shared to lib
```bash
mv shared lib/
```
### 4. Update all require paths
- `require_once __DIR__ . '/shared/Database.php'``require_once __DIR__ . '/lib/Database.php'`
- `require_once __DIR__ . '/../shared/Database.php'``require_once __DIR__ . '/../lib/Database.php'`
### 5. Setup vendor for local dev
```bash
mkdir -p vendor/
echo "vendor/" >> .gitignore
```
## Path Changes Summary
| Old Path | New Path |
|----------|----------|
| `apps/public/index.php` | `index.php` |
| `apps/public/inc/header.php` | `inc/header.php` |
| `apps/public/assets/posterg.css` | `assets/posterg.css` |
| `apps/admin/index.php` | `admin/index.php` |
| `shared/Database.php` | `lib/Database.php` |
| `shared/config.php` | `lib/config.php` |
| `shared/cache/` | `lib/cache/` |
## Deployment Changes
### Before
```
rsync apps/public/ posterg:/var/www/html/
rsync apps/admin/ posterg:/var/www/html/formulaire/
rsync shared/ posterg:/var/www/html/shared/
```
### After
```
rsync --exclude 'vendor' --exclude 'tests' . posterg:/var/www/html/
```
Much simpler!
## PHP Live Reload Setup
### For Local Development Only
1. Clone to `vendor/php-live-reload/` (gitignored)
2. Include in local dev server
3. Auto-refresh browser on file changes
4. Never deployed to production
### Usage
```bash
# Setup (one time)
just setup-dev
# Start dev server with live reload
just serve-public # or serve-admin
```

299
docs/TEST_CENTRALIZATION.md Normal file
View File

@@ -0,0 +1,299 @@
# Test Centralization Summary
All tests have been centralized into the `tests/` directory following standard testing conventions.
## 📁 New Test Structure
```
tests/
├── run-tests.php # Main test runner
├── README.md # Test documentation
├── Unit/ # Unit tests
│ ├── DatabaseTest.php # Database connection & queries
│ └── RateLimitTest.php # Rate limiting functionality
├── Integration/ # Integration tests
│ └── SearchTest.php # Search functionality
└── Security/ # Security tests
└── SecurityTest.php # SQL injection & XSS protection
```
## ✅ What Was Done
### 1. Created Test Directory Structure
- `tests/Unit/` - Tests for individual components
- `tests/Integration/` - Tests for feature workflows
- `tests/Security/` - Tests for security vulnerabilities
### 2. Moved & Created Tests
**Before:**
- `test_db.php` (root) - Basic database test
- `run-tests.php` (root) - Old test runner
**After:**
- `tests/Unit/DatabaseTest.php` - Comprehensive database testing
- `tests/Unit/RateLimitTest.php` - Rate limit testing
- `tests/Integration/SearchTest.php` - Search functionality testing
- `tests/Security/SecurityTest.php` - Security testing
- `tests/run-tests.php` - New unified test runner
- `tests/README.md` - Complete test documentation
### 3. Updated Justfile
**New Commands:**
```bash
just test # Run all tests
just test-unit # Run unit tests only
just test-integration # Run integration tests only
just test-security # Run security tests only
just syntax # Check PHP syntax
```
**Removed:**
- Old scattered test commands
- Duplicate test logic
### 4. Removed Old Files
- ✅ Deleted `test_db.php` from root
- ✅ Deleted `run-tests.php` from root
---
## 🚀 Running Tests
### Run All Tests (Recommended)
```bash
just test
```
Output:
```
╔════════════════════════════════════════════╗
║ Post-ERG Test Suite ║
╚════════════════════════════════════════════╝
┌─────────────────────────────────────────┐
│ Database (Unit) │
└─────────────────────────────────────────┘
✓ PASS: Database connection successful
✓ PASS: Found 16 published theses
...
✅ TEST PASSED
...
╔════════════════════════════════════════════╗
║ Test Summary ║
╠════════════════════════════════════════════╣
║ Total: 4 ║
║ Passed: 4 ✅ ║
║ Failed: 0 ║
╚════════════════════════════════════════════╝
✅ All tests passed!
```
### Run Specific Test Suites
```bash
# Unit tests only
just test-unit
# Integration tests only
just test-integration
# Security tests only
just test-security
# Syntax check only
just syntax
```
### Run Individual Tests
```bash
# Database test
php tests/Unit/DatabaseTest.php
# Search test
php tests/Integration/SearchTest.php
# Security test
php tests/Security/SecurityTest.php
# Rate limit test
php tests/Unit/RateLimitTest.php
```
---
## ✅ Test Coverage
### Unit Tests (2)
**DatabaseTest.php** - 4 assertions
- ✅ Database connection
- ✅ Count published theses
- ✅ Get published theses
- ✅ Get single thesis by ID
**RateLimitTest.php** - 5 assertions
- ✅ RateLimit initialization
- ✅ check() method returns boolean
- ✅ sendHeaders() executes
- ✅ getResetTime() returns valid value
- ✅ cleanup() executes
### Integration Tests (1)
**SearchTest.php** - 3 assertions
- ✅ Empty search query handling
- ✅ Search for specific terms
- ✅ Special characters in search
### Security Tests (1)
**SecurityTest.php** - 3 test groups
- ✅ SQL injection protection (4 injection attempts blocked)
- ✅ Invalid ID rejection (4 invalid IDs rejected)
- ✅ XSS protection verification
**Total: 4 test files, 15 assertions**
---
## 📝 Test Results
All tests passing:
```
✅ Database (Unit) - PASSED
✅ Rate Limit (Unit) - PASSED
✅ Search (Integration) - PASSED
✅ Security - PASSED
Total: 4
Passed: 4 ✅
Failed: 0
```
---
## 🎯 Benefits
### Before Centralization
- ❌ Tests scattered in root directory
- ❌ No clear organization
- ❌ Hard to run specific test types
- ❌ No test documentation
- ❌ Inconsistent test format
### After Centralization
- ✅ All tests in `tests/` directory
- ✅ Clear organization (Unit/Integration/Security)
- ✅ Easy to run any combination
- ✅ Comprehensive test documentation
- ✅ Consistent test format and output
- ✅ Single test runner
- ✅ Beautiful formatted output
---
## 📚 Writing New Tests
### 1. Choose Test Type
- **Unit Test** → `tests/Unit/` - Tests single functions/classes
- **Integration Test** → `tests/Integration/` - Tests feature workflows
- **Security Test** → `tests/Security/` - Tests security measures
### 2. Use Template
```php
<?php
/**
* Test Name
* Description
*/
require_once __DIR__ . '/../../lib/YourClass.php';
echo "Test Name\n";
echo "=========\n\n";
try {
echo "Test 1: Description\n";
// ... test code ...
echo "✓ PASS: Test passed\n\n";
echo "✅ All tests passed!\n";
return true;
} catch (Exception $e) {
echo "❌ FAIL: " . $e->getMessage() . "\n";
return false;
}
```
### 3. Add to Test Runner
Edit `tests/run-tests.php` and add your test to the `$testFiles` array:
```php
['name' => 'Your Test Name', 'path' => __DIR__ . '/Unit/YourTest.php'],
```
### 4. Run It
```bash
just test
```
---
## 🔄 CI/CD Integration (Future)
Tests are ready for CI/CD integration:
```yaml
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- name: Run tests
run: php tests/run-tests.php
```
---
## 📖 Related Documentation
- [Test README](../tests/README.md) - Complete test documentation
- [Database Specification](../database/DATABASE_SPECIFICATION.md)
- [Security Documentation](SECURITY.md)
---
## ✨ Quick Reference
| Command | Description |
|---------|-------------|
| `just test` | Run all tests |
| `just test-unit` | Unit tests only |
| `just test-integration` | Integration tests only |
| `just test-security` | Security tests only |
| `just syntax` | Check PHP syntax |
| `php tests/run-tests.php` | Run test runner directly |
---
**All tests centralized and passing!**