Files
michaelschiemer/src/Framework/Audit/InMemoryAuditLogger.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- 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.
2025-10-25 19:18:37 +02:00

127 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Audit;
use App\Framework\Audit\ValueObjects\AuditEntry;
use App\Framework\Audit\ValueObjects\AuditId;
use App\Framework\Audit\ValueObjects\AuditQuery;
use DateTimeImmutable;
/**
* In-memory audit logger for testing
*/
final class InMemoryAuditLogger implements AuditLogger
{
/**
* @var array<string, AuditEntry>
*/
private array $entries = [];
public function log(AuditEntry $entry): void
{
$this->entries[$entry->id->toString()] = $entry;
}
public function find(AuditId $id): ?AuditEntry
{
return $this->entries[$id->toString()] ?? null;
}
/**
* @return array<AuditEntry>
*/
public function query(AuditQuery $query): array
{
$results = array_values($this->entries);
// Apply filters
if ($query->action !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->action === $query->action
);
}
if ($query->entityType !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->entityType === $query->entityType
);
}
if ($query->entityId !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->entityId === $query->entityId
);
}
if ($query->userId !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->userId === $query->userId
);
}
if ($query->success !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->success === $query->success
);
}
if ($query->startDate !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->timestamp >= $query->startDate
);
}
if ($query->endDate !== null) {
$results = array_filter(
$results,
fn(AuditEntry $entry) => $entry->timestamp <= $query->endDate
);
}
// Sort by timestamp descending (newest first)
usort($results, fn(AuditEntry $a, AuditEntry $b) =>
$b->timestamp <=> $a->timestamp
);
// Apply pagination
return array_slice($results, $query->offset, $query->limit);
}
public function count(AuditQuery $query): int
{
// Reuse query logic but count instead
$queryWithoutPagination = $query->withLimit(PHP_INT_MAX)->withOffset(0);
return count($this->query($queryWithoutPagination));
}
public function purgeOlderThan(DateTimeImmutable $date): int
{
$count = 0;
foreach ($this->entries as $id => $entry) {
if ($entry->timestamp < $date) {
unset($this->entries[$id]);
$count++;
}
}
return $count;
}
/**
* Clear all entries (for testing)
*/
public function clear(): void
{
$this->entries = [];
}
}