- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
230 lines
8.4 KiB
PHP
230 lines
8.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Core\Events\AfterControllerExecution;
|
|
use App\Framework\Core\Events\AfterHandleRequest;
|
|
use App\Framework\Core\Events\AfterMiddlewareExecution;
|
|
use App\Framework\Core\Events\AfterRouteMatching;
|
|
use App\Framework\Core\Events\BeforeControllerExecution;
|
|
use App\Framework\Core\Events\BeforeHandleRequest;
|
|
use App\Framework\Core\Events\BeforeMiddlewareExecution;
|
|
use App\Framework\Core\Events\BeforeRouteMatching;
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
use App\Framework\Core\ValueObjects\MethodName;
|
|
use App\Framework\Core\ValueObjects\Timestamp;
|
|
use App\Framework\Http\Request;
|
|
use App\Framework\Http\Response;
|
|
|
|
echo "=== Testing Request Lifecycle Hooks ===\n\n";
|
|
|
|
echo "1. Testing Enhanced Lifecycle Events with Value Objects:\n";
|
|
|
|
try {
|
|
// Mock request and response for testing
|
|
$mockRequest = new class () {
|
|
public $path;
|
|
|
|
public $method;
|
|
|
|
public $server;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->path = new class () {
|
|
public function toString(): string
|
|
{
|
|
return '/test';
|
|
}
|
|
};
|
|
$this->method = new class () {
|
|
public $value = 'GET';
|
|
};
|
|
$this->server = new class () {
|
|
public function getUserAgent()
|
|
{
|
|
return new class () {
|
|
public function toString(): string
|
|
{
|
|
return 'Test Agent';
|
|
}
|
|
};
|
|
}
|
|
|
|
public function getClientIp()
|
|
{
|
|
return new class () {
|
|
public function __toString(): string
|
|
{
|
|
return '127.0.0.1';
|
|
}
|
|
};
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
$mockResponse = new class () {
|
|
public $statusCode = 200;
|
|
|
|
public $body = 'Test Response';
|
|
|
|
public $headers = ['Content-Type' => 'text/html'];
|
|
};
|
|
|
|
echo " ✅ Testing BeforeHandleRequest Event:\n";
|
|
$beforeEvent = new BeforeHandleRequest(
|
|
request: $mockRequest,
|
|
context: [
|
|
'route' => '/test',
|
|
'method' => 'GET',
|
|
'user_agent' => 'Test Agent',
|
|
'client_ip' => '127.0.0.1',
|
|
]
|
|
);
|
|
echo " • Timestamp: {$beforeEvent->timestamp->format('H:i:s.u')}\n";
|
|
echo " • Context keys: " . implode(', ', array_keys($beforeEvent->context)) . "\n\n";
|
|
|
|
echo " ✅ Testing AfterHandleRequest Event:\n";
|
|
$afterEvent = new AfterHandleRequest(
|
|
request: $mockRequest,
|
|
response: $mockResponse,
|
|
processingTime: Duration::fromMilliseconds(45.7),
|
|
context: [
|
|
'status_code' => 200,
|
|
'content_length' => 13,
|
|
'memory_peak' => 1024000,
|
|
]
|
|
);
|
|
echo " • Processing time: {$afterEvent->processingTime->toHumanReadable()}\n";
|
|
echo " • Timestamp: {$afterEvent->timestamp->format('H:i:s.u')}\n\n";
|
|
|
|
echo " ✅ Testing BeforeRouteMatching Event:\n";
|
|
$routeBeforeEvent = new BeforeRouteMatching(
|
|
request: $mockRequest,
|
|
context: ['pattern_count' => 25]
|
|
);
|
|
echo " • Timestamp: {$routeBeforeEvent->timestamp->format('H:i:s.u')}\n";
|
|
|
|
echo " ✅ Testing AfterRouteMatching Event:\n";
|
|
$routeAfterEvent = new AfterRouteMatching(
|
|
request: $mockRequest,
|
|
routeName: 'api.users.show',
|
|
routeParameters: ['id' => '123'],
|
|
matchingTime: Duration::fromMicroseconds(150),
|
|
context: ['matched_patterns' => 3]
|
|
);
|
|
echo " • Route name: {$routeAfterEvent->routeName}\n";
|
|
echo " • Matching time: {$routeAfterEvent->matchingTime->toHumanReadable()}\n";
|
|
echo " • Parameters: " . json_encode($routeAfterEvent->routeParameters) . "\n\n";
|
|
|
|
echo " ✅ Testing BeforeControllerExecution Event:\n";
|
|
$controllerBeforeEvent = new BeforeControllerExecution(
|
|
request: $mockRequest,
|
|
controllerClass: ClassName::create('App\\Application\\Api\\UserController'),
|
|
methodName: MethodName::create('show'),
|
|
parameters: ['id' => '123'],
|
|
context: ['auth_user' => 'user_456']
|
|
);
|
|
echo " • Controller: {$controllerBeforeEvent->controllerClass->getShortName()}\n";
|
|
echo " • Method: {$controllerBeforeEvent->methodName->toString()}\n";
|
|
echo " • Parameters: " . json_encode($controllerBeforeEvent->parameters) . "\n\n";
|
|
|
|
echo " ✅ Testing AfterControllerExecution Event:\n";
|
|
$controllerAfterEvent = new AfterControllerExecution(
|
|
request: $mockRequest,
|
|
response: $mockResponse,
|
|
controllerClass: ClassName::create('App\\Application\\Api\\UserController'),
|
|
methodName: MethodName::create('show'),
|
|
executionTime: Duration::fromMilliseconds(23.4),
|
|
context: ['db_queries' => 2, 'cache_hits' => 1]
|
|
);
|
|
echo " • Execution time: {$controllerAfterEvent->executionTime->toHumanReadable()}\n";
|
|
echo " • DB queries: {$controllerAfterEvent->context['db_queries']}\n\n";
|
|
|
|
echo " ✅ Testing BeforeMiddlewareExecution Event:\n";
|
|
$middlewareBeforeEvent = new BeforeMiddlewareExecution(
|
|
request: $mockRequest,
|
|
middlewareClass: ClassName::create('App\\Framework\\Http\\Middlewares\\AuthMiddleware'),
|
|
priority: 100,
|
|
context: ['middleware_chain_position' => 2]
|
|
);
|
|
echo " • Middleware: {$middlewareBeforeEvent->middlewareClass->getShortName()}\n";
|
|
echo " • Priority: {$middlewareBeforeEvent->priority}\n\n";
|
|
|
|
echo " ✅ Testing AfterMiddlewareExecution Event:\n";
|
|
$middlewareAfterEvent = new AfterMiddlewareExecution(
|
|
request: $mockRequest,
|
|
response: $mockResponse,
|
|
middlewareClass: ClassName::create('App\\Framework\\Http\\Middlewares\\AuthMiddleware'),
|
|
executionTime: Duration::fromMicroseconds(850),
|
|
context: ['auth_checks' => 1, 'headers_added' => 2]
|
|
);
|
|
echo " • Execution time: {$middlewareAfterEvent->executionTime->toHumanReadable()}\n";
|
|
echo " • Headers added: {$middlewareAfterEvent->context['headers_added']}\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "2. Testing Timestamp and Duration Value Objects:\n";
|
|
|
|
try {
|
|
$start = Timestamp::now();
|
|
usleep(1000); // 1ms delay
|
|
$end = Timestamp::now();
|
|
|
|
$duration = $start->diff($end);
|
|
|
|
echo " ✅ Timestamp calculations:\n";
|
|
echo " • Start: {$start->format('H:i:s.u')}\n";
|
|
echo " • End: {$end->format('H:i:s.u')}\n";
|
|
echo " • Duration: {$duration->toHumanReadable()}\n";
|
|
echo " • Duration (microseconds): {$duration->toMicroseconds()}\n\n";
|
|
|
|
echo " ✅ Duration factory methods:\n";
|
|
$durations = [
|
|
'Microseconds' => Duration::fromMicroseconds(500),
|
|
'Milliseconds' => Duration::fromMilliseconds(45.7),
|
|
'Seconds' => Duration::fromSeconds(2.5),
|
|
'Minutes' => Duration::fromMinutes(1.5),
|
|
];
|
|
|
|
foreach ($durations as $type => $duration) {
|
|
echo " • {$type}: {$duration->toHumanReadable()}\n";
|
|
}
|
|
echo "\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "3. Testing ClassName and MethodName Value Objects:\n";
|
|
|
|
try {
|
|
$className = ClassName::create('App\\Framework\\Http\\Middlewares\\AuthenticationMiddleware');
|
|
$methodName = MethodName::create('handle');
|
|
|
|
echo " ✅ ClassName operations:\n";
|
|
echo " • Full name: {$className->getFullyQualified()}\n";
|
|
echo " • Short name: {$className->getShortName()}\n";
|
|
echo " • Namespace: {$className->getNamespace()}\n\n";
|
|
|
|
echo " ✅ MethodName operations:\n";
|
|
echo " • Method name: {$methodName->toString()}\n";
|
|
echo " • Is magic method: " . ($methodName->isMagicMethod() ? 'Yes' : 'No') . "\n\n";
|
|
|
|
$magicMethod = MethodName::construct();
|
|
echo " ✅ Magic method example:\n";
|
|
echo " • Method: {$magicMethod->toString()}\n";
|
|
echo " • Is magic: " . ($magicMethod->isMagicMethod() ? 'Yes' : 'No') . "\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "=== Request Lifecycle Hooks Test Completed ===\n";
|