mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
Phase 1: Consolidate shared infrastructure - Create shared/ directory for common code - Consolidate Database.php from front-backend and formulaire into unified shared/Database.php - Smart path detection for test.db vs posterg.db - Secure search with wildcard escaping and input validation - Support both singleton and direct instantiation patterns - Full CRUD methods for admin functionality - Move RateLimit.php to shared/ (30 requests/min) - Update all require paths across apps to use shared/ Phase 2: Reorganize directory structure - Rename front-backend/ → apps/public/ - Rename formulaire/ → apps/admin/ - Rename db/ → database/ - Update all file paths for new structure - Create root .gitignore excluding databases, cache, logs Implement secure search feature - Add apps/public/search.php with full-text search across theses - Search filters: query, year, orientation, AP program, keywords - Security features: - SQL injection prevention (prepared statements) - Wildcard injection prevention (escape % and _) - Input validation (max 200 chars, year range 1900-2100) - Rate limiting (30 req/min per IP) - Pagination limited to 100 results/page - XSS protection (htmlspecialchars on output) Add comprehensive test suite - Create apps/public/tests/ with proper structure - tests/Integration/SearchTest.php - 12 search scenarios - tests/Security/SecurityTest.php - vulnerability testing - tests/Unit/RateLimitTest.php - rate limit behavior - Create database/fixtures/CreateTestDatabase.php - Add apps/public/run-tests.php test runner - All tests passing (4/4 suites) Update deployment configuration - Rename justfile 'sync' recipe to 'deploy' - Create deploy group with separate deploy-public and deploy-admin - Add test-deploy recipe for test database - Exclude *.db, tests/, cache/, *.md from production deploy - Deploy shared/ to both public and admin locations Stats: +4482 insertions, -654 deletions across 72 files
122 lines
4.1 KiB
PHP
122 lines
4.1 KiB
PHP
<?php
|
|
/**
|
|
* Test script for search functionality
|
|
* Run this to verify that search methods work correctly
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../../../shared/Database.php';
|
|
|
|
echo "=== Testing Search Feature ===\n\n";
|
|
|
|
try {
|
|
$db = Database::getInstance();
|
|
|
|
// Test 1: Get all published theses
|
|
echo "Test 1: Getting all published theses\n";
|
|
$allTheses = $db->searchTheses([], 100, 0);
|
|
echo "Found " . count($allTheses) . " published theses\n";
|
|
foreach ($allTheses as $thesis) {
|
|
echo " - [{$thesis['year']}] {$thesis['title']} by {$thesis['authors']}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 2: Full-text search
|
|
echo "Test 2: Full-text search for 'urbain'\n";
|
|
$results = $db->searchTheses(['query' => 'urbain']);
|
|
echo "Found " . count($results) . " results\n";
|
|
foreach ($results as $thesis) {
|
|
echo " - {$thesis['title']}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 3: Search by year
|
|
echo "Test 3: Search by year (2024)\n";
|
|
$results = $db->searchTheses(['year' => 2024]);
|
|
echo "Found " . count($results) . " results\n";
|
|
foreach ($results as $thesis) {
|
|
echo " - [{$thesis['year']}] {$thesis['title']}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 4: Search by orientation
|
|
echo "Test 4: Search by orientation (Installation-Performance)\n";
|
|
$results = $db->searchTheses(['orientation' => 'Installation-Performance']);
|
|
echo "Found " . count($results) . " results\n";
|
|
foreach ($results as $thesis) {
|
|
echo " - {$thesis['title']} ({$thesis['orientation']})\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 5: Search by AP program
|
|
echo "Test 5: Search by AP program (Narration Spéculative)\n";
|
|
$results = $db->searchTheses(['ap_program' => 'Narration Spéculative']);
|
|
echo "Found " . count($results) . " results\n";
|
|
foreach ($results as $thesis) {
|
|
echo " - {$thesis['title']} ({$thesis['ap_program']})\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 6: Search by keyword
|
|
echo "Test 6: Search by keyword (performance)\n";
|
|
$results = $db->searchTheses(['keyword' => 'performance']);
|
|
echo "Found " . count($results) . " results\n";
|
|
foreach ($results as $thesis) {
|
|
echo " - {$thesis['title']}\n";
|
|
echo " Keywords: {$thesis['keywords']}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 7: Combined search
|
|
echo "Test 7: Combined search (query='performance' + year=2024)\n";
|
|
$results = $db->searchTheses(['query' => 'performance', 'year' => 2024]);
|
|
echo "Found " . count($results) . " results\n";
|
|
foreach ($results as $thesis) {
|
|
echo " - [{$thesis['year']}] {$thesis['title']}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// Test 8: Get available years
|
|
echo "Test 8: Getting available years\n";
|
|
$years = $db->getAvailableYears();
|
|
echo "Available years: " . implode(', ', $years) . "\n\n";
|
|
|
|
// Test 9: Get orientations
|
|
echo "Test 9: Getting orientations\n";
|
|
$orientations = $db->getOrientations();
|
|
echo "Total orientations: " . count($orientations) . "\n";
|
|
echo "Sample: " . $orientations[0]['name'] . ", " . $orientations[1]['name'] . ", ...\n\n";
|
|
|
|
// Test 10: Get keywords
|
|
echo "Test 10: Getting used keywords\n";
|
|
$keywords = $db->getUsedKeywords();
|
|
echo "Total keywords in use: " . count($keywords) . "\n";
|
|
$keywordNames = array_map(function($k) { return $k['keyword']; }, $keywords);
|
|
echo "Keywords: " . implode(', ', array_slice($keywordNames, 0, 10)) . "...\n\n";
|
|
|
|
// Test 11: Count results
|
|
echo "Test 11: Count search results\n";
|
|
$count = $db->countSearchResults(['year' => 2024]);
|
|
echo "Count for year 2024: $count\n\n";
|
|
|
|
// Test 12: Pagination
|
|
echo "Test 12: Testing pagination\n";
|
|
$page1 = $db->searchTheses([], 2, 0); // First 2 results
|
|
$page2 = $db->searchTheses([], 2, 2); // Next 2 results
|
|
echo "Page 1 (first 2):\n";
|
|
foreach ($page1 as $thesis) {
|
|
echo " - {$thesis['title']}\n";
|
|
}
|
|
echo "Page 2 (next 2):\n";
|
|
foreach ($page2 as $thesis) {
|
|
echo " - {$thesis['title']}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
echo "✅ All tests completed successfully!\n";
|
|
|
|
} catch (Exception $e) {
|
|
echo "❌ Error: " . $e->getMessage() . "\n";
|
|
echo "Stack trace:\n" . $e->getTraceAsString() . "\n";
|
|
exit(1);
|
|
}
|