DateBasedInvoiceStorage.php
Pfad: src/Infrastructure/Rechnung/DateBasedInvoiceStorage.php
Ext: php
Größe: 2915 Bytes
Geändert: 2026-07-16T14:11:10+02:00
Frühere Version vom 2026-07-16T14:11:10+02:00 · zur aktuellen Fassung
<?php
declare(strict_types=1);
namespace Demo\Infrastructure\Rechnung;
use Demo\Domain\Rechnung\InvoiceFileStoragePort;
/**
* Erzeugt lokale Pfade YYYY/MM/YYYY-MM-DD_<firma>_<hash>.pdf und speichert die PDF.
*/
final class DateBasedInvoiceStorage implements InvoiceFileStoragePort
{
/**
* @param string $basePath Stammpfad (z. B. /var/www/.../rechnungen/originale).
*/
public function __construct(
private string $basePath
) {
}
/**
* @inheritDoc
*/
public function buildTargetPath(?string $invoiceDateHint, string $vendorName, string $sourceId): string
{
$date = $this->normalizeDate($invoiceDateHint);
$dir = $this->basePath . '/' . $date->format('Y') . '/' . $date->format('m');
if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) {
throw new \RuntimeException('Ablageverzeichnis fuer PDF kann nicht erzeugt werden');
}
$safeVendor = $this->sanitize($vendorName);
$shortId = substr(hash('sha1', $sourceId), 0, 8);
$filename = $date->format('Y-m-d') . '_' . $safeVendor . '_' . $shortId . '.pdf';
return $dir . '/' . $filename;
}
/**
* @inheritDoc
*/
public function persistDownloadedPdf(string $pdfBinary, string $targetPath): void
{
if (is_file($targetPath)) {
return;
}
if (file_put_contents($targetPath, $pdfBinary, LOCK_EX) === false) {
throw new \RuntimeException('Konnte PDF lokal nicht speichern: ' . $targetPath);
}
}
/**
* @inheritDoc
*/
public function sha256(string $path): string
{
$hash = hash_file('sha256', $path);
return $hash === false ? '' : $hash;
}
/**
* @param string $input Eingabe.
* @return string Bereinigter Dateiname.
*/
private function sanitize(string $input): string
{
$reduced = strtolower(trim($input));
if ($reduced === '') {
return 'unbekannt';
}
$reduced = preg_replace('/\s+/', '_', $reduced);
$reduced = preg_replace('/[^a-z0-9_-]/i', '', $reduced);
return trim((string) $reduced, '_') ?: 'unbekannt';
}
/**
* @param string|null $invoiceDateHint Datumstext.
* @return \DateTimeImmutable Normalisiertes Datum.
*/
private function normalizeDate(?string $invoiceDateHint): \DateTimeImmutable
{
$formats = ['Y-m-d', 'd.m.Y', 'd/m/Y', 'Y/m/d'];
if ($invoiceDateHint !== null) {
$invoiceDateHint = trim($invoiceDateHint);
foreach ($formats as $format) {
$date = \DateTimeImmutable::createFromFormat($format, $invoiceDateHint);
if ($date instanceof \DateTimeImmutable) {
return $date;
}
}
}
return new \DateTimeImmutable('today');
}
}