docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,261 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Framework\Logging;
use App\Framework\Logging\LogLevel;
use App\Framework\Logging\LogRecord;
use App\Framework\Logging\ValueObjects\LogContext;
use DateTimeImmutable;
use DateTimeZone;
beforeEach(function () {
$this->timestamp = new DateTimeImmutable('2024-01-15 10:30:45', new DateTimeZone('Europe/Berlin'));
$this->context = LogContext::withData(['user' => 'test', 'action' => 'login']);
});
it('can create a log record with required fields', function () {
$record = new LogRecord(
message: 'Test message',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
expect($record->getMessage())->toBe('Test message');
expect($record->getLevel())->toBe(LogLevel::INFO);
expect($record->getTimestamp())->toBe($this->timestamp);
expect($record->getChannel())->toBeNull();
});
it('can create a log record with channel', function () {
$record = new LogRecord(
message: 'Database query executed',
context: $this->context,
level: LogLevel::DEBUG,
timestamp: $this->timestamp,
channel: 'database'
);
expect($record->getChannel())->toBe('database');
});
it('can modify message', function () {
$record = new LogRecord(
message: 'Original message',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$record->setMessage('Modified message');
expect($record->getMessage())->toBe('Modified message');
});
it('can set channel after creation', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$record->setChannel('security');
expect($record->getChannel())->toBe('security');
});
it('can format timestamp', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
expect($record->getFormattedTimestamp())->toBe('2024-01-15 10:30:45');
expect($record->getFormattedTimestamp('Y-m-d'))->toBe('2024-01-15');
expect($record->getFormattedTimestamp('H:i:s'))->toBe('10:30:45');
});
it('can add extra data', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$record->addExtra('request_id', 'req-123');
$record->addExtra('process_id', 5678);
expect($record->hasExtra('request_id'))->toBeTrue();
expect($record->getExtra('request_id'))->toBe('req-123');
expect($record->getExtra('process_id'))->toBe(5678);
expect($record->hasExtra('non_existent'))->toBeFalse();
});
it('can add multiple extras at once', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$extras = [
'server' => 'web-01',
'memory_usage' => 1024000,
'execution_time' => 0.123,
];
$record->addExtras($extras);
expect($record->getExtras())->toBe($extras);
expect($record->getExtra('server'))->toBe('web-01');
expect($record->getExtra('memory_usage'))->toBe(1024000);
expect($record->getExtra('execution_time'))->toBe(0.123);
});
it('returns default value for non-existent extra', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
expect($record->getExtra('missing'))->toBeNull();
expect($record->getExtra('missing', 'default'))->toBe('default');
});
it('maintains fluent interface for setters', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$result = $record
->setMessage('New message')
->setChannel('custom')
->addExtra('key1', 'value1')
->addExtras(['key2' => 'value2']);
expect($result)->toBe($record);
expect($record->getMessage())->toBe('New message');
expect($record->getChannel())->toBe('custom');
expect($record->getExtra('key1'))->toBe('value1');
expect($record->getExtra('key2'))->toBe('value2');
});
it('converts to array correctly', function () {
$record = new LogRecord(
message: 'Test message',
context: $this->context,
level: LogLevel::WARNING,
timestamp: $this->timestamp,
channel: 'test-channel'
);
$record->addExtra('request_id', 'req-456');
$array = $record->toArray();
expect($array)->toHaveKeys([
'message',
'context',
'level',
'level_name',
'timestamp',
'datetime',
'channel',
'extra',
]);
expect($array['message'])->toBe('Test message');
expect($array['context'])->toMatchArray(['user' => 'test', 'action' => 'login']);
expect($array['level'])->toBe(LogLevel::WARNING->value);
expect($array['level_name'])->toBe('WARNING');
expect($array['timestamp'])->toBe('2024-01-15 10:30:45');
expect($array['datetime'])->toBe($this->timestamp);
expect($array['channel'])->toBe('test-channel');
expect($array['extra'])->toBe(['request_id' => 'req-456']);
});
it('handles different log levels correctly', function () {
$levels = [
LogLevel::DEBUG,
LogLevel::INFO,
LogLevel::NOTICE,
LogLevel::WARNING,
LogLevel::ERROR,
LogLevel::CRITICAL,
LogLevel::ALERT,
LogLevel::EMERGENCY,
];
foreach ($levels as $level) {
$record = new LogRecord(
message: "Test {$level->getName()}",
context: $this->context,
level: $level,
timestamp: $this->timestamp
);
expect($record->getLevel())->toBe($level);
expect($record->toArray()['level'])->toBe($level->value);
expect($record->toArray()['level_name'])->toBe($level->getName());
}
});
it('preserves context as LogContext object', function () {
$context = LogContext::withData(['test' => 'data'])
->addTags('important', 'audit');
$record = new LogRecord(
message: 'Test',
context: $context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$contextArray = $record->getContext();
expect($contextArray)->toMatchArray([
'test' => 'data',
'_tags' => ['important', 'audit'],
]);
});
it('can handle empty extras', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
expect($record->getExtras())->toBe([]);
expect($record->hasExtra('any'))->toBeFalse();
});
it('overrides existing extras when adding with same key', function () {
$record = new LogRecord(
message: 'Test',
context: $this->context,
level: LogLevel::INFO,
timestamp: $this->timestamp
);
$record->addExtra('key', 'original');
expect($record->getExtra('key'))->toBe('original');
$record->addExtra('key', 'modified');
expect($record->getExtra('key'))->toBe('modified');
$record->addExtras(['key' => 'final']);
expect($record->getExtra('key'))->toBe('final');
});