Obvody/app/Model/ObvodFacade.php

133 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Model;
use Nette;
use Nette\Database\Explorer;
use Nette\Database\Row;
use Nette\Security\User;
use Nette\Utils\DateTime;
/**
* Třída pro načítání informací o obvodech z DB.
*/
final class ObvodFacade
{
/** Sloupce bez GEO, aby seznam obvodů nenačítal hranice. */
private const SLOUPCE = 'ID, NAZEV, CISLO, SKUPINA, AKTIVNI';
public function __construct(
private Explorer $database,
private User $user,
) {
}
/**
* Základní informace o obvodu.
* @param int $id
* @return Nette\Database\Table\ActiveRow|null
*/
public function getObvod(int $id): Row|null
{
$sql = 'SELECT ' . self::SLOUPCE . '
FROM OBVOD
WHERE OBVOD.ID = ?';
return $this->database->fetch($sql, $id);
}
public const SKUPINA_COOKIE = 'obvodSkupina';
/**
* Základní informace o obvodech.
* @return array<int, Row>
*/
public function getObvody(?string $skupina = null): array
{
if ($skupina === null || $skupina === '') {
return $this->database->fetchAll('SELECT ' . self::SLOUPCE . ' FROM OBVOD ORDER BY CISLO');
}
return $this->database->fetchAll(
'SELECT ' . self::SLOUPCE . ' FROM OBVOD WHERE SKUPINA = ? ORDER BY CISLO',
$skupina,
);
}
/**
* @return list<string>
*/
public function getSkupiny(): array
{
$radky = $this->database->fetchAll(
"SELECT DISTINCT SKUPINA
FROM OBVOD
WHERE SKUPINA IS NOT NULL AND LTRIM(RTRIM(SKUPINA)) <> ''
ORDER BY SKUPINA",
);
return array_map(static fn(Row $radek): string => (string) $radek->SKUPINA, $radky);
}
/**
* Předchozí a další existující obvod podle čísla.
* Čísla nemusí jít po sobě.
*
* @return array{predchozi: int|null, dalsi: int|null}
*/
public function getSousede(int $id): array
{
$prazdne = ['predchozi' => null, 'dalsi' => null];
$radky = $this->database->fetchAll('SELECT ID FROM OBVOD ORDER BY CISLO, ID');
$ids = array_map(static fn(Row $radek): int => (int) $radek->ID, $radky);
$index = array_search($id, $ids, true);
if ($index === false) {
return $prazdne;
}
return [
'predchozi' => $index > 0 ? $ids[$index - 1] : null,
'dalsi' => $index < count($ids) - 1 ? $ids[$index + 1] : null,
];
}
public function vyberSkupinu(?string $pozadovana, ?string $ulozena): string
{
$skupiny = $this->getSkupiny();
if ($pozadovana !== null && in_array($pozadovana, $skupiny, true)) {
return $pozadovana;
}
if ($ulozena !== null && in_array($ulozena, $skupiny, true)) {
return $ulozena;
}
return $skupiny[0] ?? '';
}
/**
* Hranice obvodů jako GeoJSON FeatureCollection.
* GEO v databázi je GeoJSON geometrie (Polygon nebo MultiPolygon).
*/
public function getGeoJson(): string
{
$radky = $this->database->fetchAll(
"SELECT CISLO, GEO
FROM OBVOD
WHERE GEO IS NOT NULL AND LTRIM(RTRIM(GEO)) <> ''
ORDER BY CISLO",
);
$features = [];
foreach ($radky as $radek) {
$features[] = '{"type":"Feature","properties":{"number":'
. (int) $radek->CISLO
. '},"geometry":'
. $radek->GEO
. '}';
}
return '{"type":"FeatureCollection","features":[' . implode(',', $features) . ']}';
}
}