Kufrik/app/Model/Facade/DatabazeFacade.php

204 lines
6.1 KiB
PHP

<?php
namespace App\Model\Facade;
use Nette\Database\Connection;
use Nette\Http\FileUpload;
use Nette\Utils\FileSystem;
use Nette\Utils\Json;
class DatabazeFacade
{
public function __construct(
private Connection $masterDb,
private string $sdfStorageDir
) {
}
/**
* Seznam databází z master tabulky LOGIN (jeden login = jedna databáze).
*
* @return \stdClass[]
*/
public function getAll(): array
{
$rows = $this->masterDb->fetchAll(
'SELECT ID, EMAIL, POSLEDNI_PRIHLASENI, AKTIVNI, [DATABASE], [SERVER], FIRMA_ID, IS_ADMIN
FROM dbo.LOGIN
ORDER BY [DATABASE], EMAIL'
);
$result = [];
foreach ($rows as $row) {
$result[] = $this->hydrate($row);
}
return $result;
}
public function getById(int $id): ?\stdClass
{
$row = $this->masterDb->fetch(
'SELECT ID, EMAIL, POSLEDNI_PRIHLASENI, AKTIVNI, [DATABASE], [SERVER], FIRMA_ID, IS_ADMIN
FROM dbo.LOGIN
WHERE ID = ?',
$id
);
return $row ? $this->hydrate($row) : null;
}
public function getSdfFilePath(int $loginId): ?string
{
$path = $this->sdfPath($loginId);
return is_file($path) ? $path : null;
}
/**
* @param array<string, mixed> $stats
*/
public function markSdfImported(int $loginId, array $stats): void
{
$meta = $this->readSdfMeta($loginId);
$meta['importedAt'] = (new \DateTimeImmutable())->format('c');
$meta['importStats'] = $stats;
FileSystem::createDir($this->sdfStorageDir);
FileSystem::write($this->sdfMetaPath($loginId), Json::encode($meta, pretty: true));
}
/**
* Položky selectu: ID => „databáze — e-mail“.
*
* @return array<int, string>
*/
public function getSelectItems(): array
{
$items = [];
foreach ($this->getAll() as $login) {
$items[(int) $login->ID] = $login->DATABASE . ' — ' . $login->EMAIL;
}
return $items;
}
/**
* Uloží nahraný .sdf k loginu.
*/
public function saveSdf(int $loginId, FileUpload $file): void
{
$exists = $this->masterDb->fetchField('SELECT ID FROM dbo.LOGIN WHERE ID = ?', $loginId);
if (!$exists) {
throw new \InvalidArgumentException('Vybraná databáze (login) neexistuje.');
}
if (!$file->isOk()) {
throw new \RuntimeException('Soubor se nepodařilo nahrát. Zkontrolujte velikost (limit PHP/upload).');
}
$extension = strtolower(pathinfo($file->getUntrustedName(), PATHINFO_EXTENSION));
if ($extension !== 'sdf') {
throw new \InvalidArgumentException('Soubor musí mít příponu .sdf.');
}
FileSystem::createDir($this->sdfStorageDir);
$file->move($this->sdfPath($loginId));
$this->clearSdfImportMeta($loginId);
$meta = [
'originalName' => $this->safeOriginalName($file->getUntrustedName()),
'uploadedAt' => (new \DateTimeImmutable())->format('c'),
'size' => $file->getSize(),
'loginId' => $loginId,
];
FileSystem::write($this->sdfMetaPath($loginId), Json::encode($meta, pretty: true));
}
/**
* @return array{originalName?: string, uploadedAt?: string, size?: int}|array{}
*/
private function readSdfMeta(int $loginId): array
{
$sdf = $this->sdfPath($loginId);
if (!is_file($sdf)) {
return [];
}
$metaFile = $this->sdfMetaPath($loginId);
$meta = [];
if (is_file($metaFile)) {
try {
$decoded = Json::decode(FileSystem::read($metaFile), forceArrays: true);
$meta = is_array($decoded) ? $decoded : [];
} catch (\Throwable) {
$meta = [];
}
}
$meta['size'] = filesize($sdf) ?: ($meta['size'] ?? null);
$meta['uploadedAt'] ??= date('c', filemtime($sdf) ?: time());
$meta['originalName'] ??= $loginId . '.sdf';
return $meta;
}
private function hydrate(object $row): \stdClass
{
$item = (object) (array) $row;
$meta = $this->readSdfMeta((int) $item->ID);
$item->SDF_SOUBOR = $meta['originalName'] ?? null;
$item->SDF_NAHRANO = isset($meta['uploadedAt']) ? new \DateTimeImmutable($meta['uploadedAt']) : null;
$item->SDF_VELIKOST = $meta['size'] ?? null;
$item->SDF_VELIKOST_TEXT = isset($meta['size']) ? $this->formatBytes((int) $meta['size']) : null;
$item->SDF_IMPORTOVANO = isset($meta['importedAt']) ? new \DateTimeImmutable($meta['importedAt']) : null;
return $item;
}
private function clearSdfImportMeta(int $loginId): void
{
$metaFile = $this->sdfMetaPath($loginId);
if (!is_file($metaFile)) {
return;
}
try {
$decoded = Json::decode(FileSystem::read($metaFile), forceArrays: true);
$meta = is_array($decoded) ? $decoded : [];
} catch (\Throwable) {
return;
}
unset($meta['importedAt'], $meta['importStats']);
FileSystem::write($metaFile, Json::encode($meta, pretty: true));
}
private function sdfPath(int $loginId): string
{
return $this->sdfStorageDir . DIRECTORY_SEPARATOR . $loginId . '.sdf';
}
private function sdfMetaPath(int $loginId): string
{
return $this->sdfStorageDir . DIRECTORY_SEPARATOR . $loginId . '.json';
}
private function formatBytes(int $bytes): string
{
if ($bytes < 1024) {
return $bytes . ' B';
}
if ($bytes < 1024 * 1024) {
return number_format($bytes / 1024, 1, ',', ' ') . ' KB';
}
return number_format($bytes / (1024 * 1024), 1, ',', ' ') . ' MB';
}
private function safeOriginalName(string $name): string
{
$name = str_replace(["\0", "\r", "\n"], '', $name);
$name = basename($name);
return $name !== '' ? mb_substr($name, 0, 255) : 'databaze.sdf';
}
}