204 lines
6.1 KiB
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';
|
|
}
|
|
}
|