134 lines
3.3 KiB
PHP
134 lines
3.3 KiB
PHP
<?php
|
||
|
||
/*
|
||
* Copyright (c) 2025, Антон Аксенов
|
||
* This file is part of m3u.su project
|
||
* MIT License: https://git.axenov.dev/IPTV/web/src/branch/master/LICENSE
|
||
*/
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Core;
|
||
|
||
use App\Exceptions\FileReadException;
|
||
use App\Exceptions\IniParsingException;
|
||
use App\Exceptions\PlaylistNotFoundException;
|
||
use ArrayAccess;
|
||
use Override;
|
||
use Throwable;
|
||
|
||
/**
|
||
* Класс для работы со списком плейлистов
|
||
*
|
||
* @phpstan-type TIniFile array{}|TPlaylistDefinition[]
|
||
* @phpstan-type TPlaylistDefinition array{name?: string, desc?: string, url: string, src?: string}
|
||
* @template TKey as non-falsy-string
|
||
* @template TValue as TPlaylistDefinition
|
||
* @implements ArrayAccess<TKey, TValue>
|
||
*/
|
||
class IniFile implements ArrayAccess
|
||
{
|
||
/**
|
||
* @var array{}|array<TKey, TValue> Коллекция подгруженных плейлистов
|
||
*/
|
||
protected array $playlists;
|
||
|
||
/**
|
||
* @var positive-int Дата последнего обновления списка
|
||
*/
|
||
protected int $updatedAt;
|
||
|
||
/**
|
||
* Загружает ini-файл и инициализирует плейлисты
|
||
*
|
||
* @param string $filepath
|
||
* @throws FileReadException
|
||
* @throws IniParsingException
|
||
*/
|
||
public function __construct(
|
||
protected string $filepath,
|
||
) {
|
||
try {
|
||
$content = file_get_contents($this->filepath);
|
||
} catch (Throwable) {
|
||
$content = false;
|
||
}
|
||
|
||
$content === false && throw new FileReadException($this->filepath);
|
||
|
||
$parsed = parse_ini_string($content, true);
|
||
$parsed === false && throw new IniParsingException($this->filepath);
|
||
$this->playlists = $parsed;
|
||
|
||
/** @var positive-int $timestamp */
|
||
$timestamp = is_readable($this->filepath) ? filemtime($this->filepath) : time();
|
||
$this->updatedAt = $timestamp;
|
||
}
|
||
|
||
/**
|
||
* Возвращает определение плейлиста по его коду
|
||
*
|
||
* @param TKey $code
|
||
* @return TValue
|
||
* @throws PlaylistNotFoundException
|
||
*/
|
||
public function playlist(string $code): array
|
||
{
|
||
return $this->playlists[$code] ?? throw new PlaylistNotFoundException($code);
|
||
}
|
||
|
||
/**
|
||
* Возвращает дату обновления ini-файла
|
||
*
|
||
* @return string
|
||
*/
|
||
public function updatedAt(): string
|
||
{
|
||
return date('d.m.Y h:i', $this->updatedAt);
|
||
}
|
||
|
||
/**
|
||
* @inheritDoc
|
||
* @param non-falsy-string $offset
|
||
* @return bool
|
||
*/
|
||
#[Override]
|
||
public function offsetExists(mixed $offset): bool
|
||
{
|
||
return isset($this->playlists[$offset]);
|
||
}
|
||
|
||
/**
|
||
* @inheritDoc
|
||
* @param TKey $offset
|
||
* @return TPlaylistDefinition
|
||
* @throws PlaylistNotFoundException
|
||
*/
|
||
#[Override]
|
||
public function offsetGet(mixed $offset): array
|
||
{
|
||
return $this->playlist($offset);
|
||
}
|
||
|
||
/**
|
||
* @inheritDoc
|
||
* @param TKey $offset
|
||
* @param TValue $value
|
||
* @return void
|
||
*/
|
||
#[Override]
|
||
public function offsetSet(mixed $offset, mixed $value): void
|
||
{
|
||
}
|
||
|
||
/**
|
||
* @inheritDoc
|
||
* @param non-falsy-string $offset
|
||
* @return void
|
||
*/
|
||
#[Override]
|
||
public function offsetUnset(mixed $offset): void
|
||
{
|
||
}
|
||
}
|