268 lines
8.8 KiB
PHP
268 lines
8.8 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace mirzaev\vk;
|
||
|
||
use mirzaev\vk\robots\robot;
|
||
use mirzaev\vk\traits\singleton;
|
||
use mirzaev\vk\loggers\jasmo;
|
||
|
||
use exception;
|
||
|
||
/**
|
||
* Ядро
|
||
*
|
||
* @property-read int $robots Количество роботов
|
||
* @property string $timezone Временная зона (журналирование)
|
||
* @property array $path Пути (архитектура проекта)
|
||
*
|
||
* @method protected static function __construct() Инициализация
|
||
* @method public static function init() Запуск инициализации или получение инстанции
|
||
* @method public public function build() Сборщик
|
||
* @method public function set($id, $value) Запись в реестр
|
||
* @method public function get($id = null) Чтение из реестра
|
||
*
|
||
* @package mirzaev\vk
|
||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||
*/
|
||
final class core
|
||
{
|
||
use singleton;
|
||
|
||
/**
|
||
* Счётчик роботов
|
||
*/
|
||
private int $robots = 0;
|
||
|
||
/**
|
||
* Реестр роботов
|
||
*/
|
||
private array $registry = [];
|
||
|
||
/**
|
||
* Временная зона
|
||
*
|
||
* Используется в логировании
|
||
*/
|
||
private readonly string $timezone;
|
||
|
||
/**
|
||
* Путь до корня проекта
|
||
*/
|
||
private readonly string $path_root;
|
||
|
||
/**
|
||
* Путь до папки журналов
|
||
*/
|
||
private readonly string $path_logs;
|
||
|
||
/**
|
||
* Путь до временной папки
|
||
*/
|
||
private readonly string $path_temp;
|
||
|
||
/**
|
||
* Запись в журнал
|
||
*
|
||
* @param string $file Файл для журналирования
|
||
*
|
||
* @return self
|
||
*
|
||
* @todo Добавить установку иного журналиста по спецификации PSR-3
|
||
*/
|
||
public function journal(string $file = null): self
|
||
{
|
||
// Инициализация журналиста (требует переработки)
|
||
jasmo::init()::post($file)::postErrorHandler()::postShutdownHandler();
|
||
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* Записать в реестр
|
||
*
|
||
* @param int $id
|
||
* @param robot $robot
|
||
*
|
||
* @see mirzaev\vk\traits\registry Модификация метода
|
||
*
|
||
* @return void
|
||
*/
|
||
public function write(int $id, robot $robot): void
|
||
{
|
||
try {
|
||
// Инициализация уникального идентификатора сессии
|
||
|
||
$session = count($this->read($id));
|
||
} catch (exception $e) {
|
||
if ($e->getCode() === 404) {
|
||
// Робота или сессии не существует
|
||
|
||
$session = 0;
|
||
}
|
||
} finally {
|
||
// Записать новую сессию
|
||
$this->registry[$id][$session] = $robot;
|
||
|
||
// Прединкрементация счётчика роботов
|
||
++$this->robots;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Прочитать из реестра
|
||
*
|
||
* Если не передать идентификатор, то вернёт все значения
|
||
*
|
||
* @param int|null $id Идентификатор
|
||
* @param int|null $session Сессия
|
||
*
|
||
* @see mirzaev\vk\traits\registry Модификация метода
|
||
*
|
||
* @return mixed Весь реестр, робота или сессию робота
|
||
*/
|
||
public function read(int|null $id = null, int|null $session = null): mixed
|
||
{
|
||
if (isset($id)) {
|
||
// Робот передан
|
||
|
||
if (array_key_exists($id, $this->registry)) {
|
||
// Робот найден
|
||
|
||
if (isset($session)) {
|
||
// Сессия робота передана
|
||
|
||
if (array_key_exists($session, $this->registry[$id])) {
|
||
// Сессия робота найдена
|
||
|
||
return $this->registry[$id][$session];
|
||
}
|
||
|
||
throw new exception("Сессия $session робота с идентификатором $id не найдена", 404);
|
||
}
|
||
|
||
return $this->registry[$id];
|
||
} else {
|
||
|
||
throw new exception("Робот с идентификатором $id не найден", 404);
|
||
}
|
||
}
|
||
|
||
return $this->registry;
|
||
}
|
||
|
||
/**
|
||
* Удалить из реестра
|
||
*
|
||
* @param int|null $id Идентификатор
|
||
* @param int|null $session Сессия
|
||
*
|
||
* @return void
|
||
*
|
||
* @see mirzaev\vk\traits\registry Модификация метода
|
||
*/
|
||
public function delete(int|null $id = null, int|null $session = null): void
|
||
{
|
||
if (isset($id)) {
|
||
// Робот передан
|
||
|
||
if (array_key_exists($id, $this->registry)) {
|
||
// Робот найден
|
||
|
||
if (isset($session)) {
|
||
// Сессия передана
|
||
|
||
if (array_key_exists($session, $this->registry[$id])) {
|
||
// Сессия найдена
|
||
|
||
// Постдекрементация счётчика роботов
|
||
--$this->robots;
|
||
|
||
// Удаление сессии
|
||
unset($this->registry[$id][$session]);
|
||
|
||
return;
|
||
}
|
||
|
||
throw new exception("Сессия $session робота с идентификатором $id не найдена", 404);
|
||
}
|
||
|
||
// Вычитание из счётчика количества сессий робота
|
||
$this->robots = $this->robots - count($this->registry[$id]);
|
||
|
||
// Удаление робота и всех его сессий
|
||
unset($this->registry[$id]);
|
||
|
||
return;
|
||
}
|
||
|
||
throw new exception("Робот с идентификатором $id не найден", 404);
|
||
}
|
||
|
||
// Полная очистка
|
||
$this->registry = [];
|
||
}
|
||
|
||
/**
|
||
* Записать свойство
|
||
*
|
||
* @param string $name Название
|
||
* @param mixed $value Значение
|
||
*
|
||
* @return void
|
||
*/
|
||
public function __set(string $name, mixed $value): void
|
||
{
|
||
match ($name) {
|
||
'timezone' => !isset($this->timezone) ? $this->timezone = $value : throw new exception('Запрещено переопределять часовой пояс', 500),
|
||
'path_root' => !isset($this->path_root) ? $this->path_root = $value : throw new exception('Запрещено переопределять корневой каталог', 500),
|
||
'path_logs' => !isset($this->path_logs) ? $this->path_logs = $value : throw new exception('Запрещено переопределять каталог журналов', 500),
|
||
'path_temp' => !isset($this->path_temp) ? $this->path_temp = $value : throw new exception('Запрещено переопределять каталог временных файлов', 500),
|
||
default => throw new exception("Свойство $name не обнаружено", 404)
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Прочитать свойство
|
||
*
|
||
* Записывает значение по умолчанию, если свойство не инициализировано
|
||
*
|
||
* @param mixed $name Название
|
||
*
|
||
* @return mixed
|
||
*/
|
||
public function __get(string $name): mixed
|
||
{
|
||
return match ($name) {
|
||
'robots' => $this->robots,
|
||
'timezone' => $this->timezone ?? $this->timezone = 'Europe/Moscow',
|
||
'path_root' => $this->path_root ?? $this->path_root = dirname(__DIR__),
|
||
'path_logs' => $this->path_logs ?? $this->path_logs = $this->__get('path_root') . '/logs',
|
||
'path_temp' => $this->path_temp ?? $this->path_temp = $this->__get('path_root') . '/temp',
|
||
default => throw new exception("Свойство \"\$$name\" не обнаружено", 404)
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Вызвать метод
|
||
*
|
||
* Ищет класс описывающий робота,
|
||
* создаёт и возвращает его объект
|
||
*
|
||
* @param string $method Метод
|
||
* @param array $params Параметры
|
||
*
|
||
* @return robot
|
||
*/
|
||
public function __call(string $method, array $params): robot
|
||
{
|
||
if (class_exists($robot = '\\mirzaev\\vk\\robots\\' . $method)) {
|
||
// Если найден класс реализующий запрошенного робота
|
||
return new $robot(...$params);
|
||
} else {
|
||
throw new exception("Робот $method не найден", 404);
|
||
}
|
||
}
|
||
}
|