Пакет · sdk-s5w

Сущности

Объекты, в которые SDK превращает ответы сервера. Все они неизменяемы (readonly) и описывают состояние на момент ответа; чтобы увидеть новое состояние, используйте то, что вернул метод изменения, или перечитайте объект.

Пространство имён Flytachi\Winter\SDK\S5w\Entity

Общее

Даты — DateTimeImmutable с часовым поясом сервера.

Перечисления — объекты PHP-перечислений (Retention::WEEK), а не числа. См. Опции и перечисления.

JSON. Каждая сущность реализует JsonSerializable и метод toArray(), поэтому её можно сразу отдать в ответ: ResponseEntity::ok($file). В JSON даты — строки ISO 8601 (2026-11-07T14:54:51+00:00), перечисления — имена ("WEEK"), вложенные объекты — массивы.

php
json_encode($folder);
// {"name":"avatars","public":true,"retention":"NONE",
//  "cache":{"maxAge":null,"visibility":null},
//  "createdAt":"2026-11-07T14:54:51+00:00","updatedAt":"2026-11-07T14:54:51+00:00"}

Проверка ответа. Если в ответе сервера нет нужного поля или у него не тот тип, SDK бросает ResponseException с путём к полю — например, S5W v1/check: bytes.quota must be int, got string.

File

Файл в бакете.

Поле Тип Описание
id string 16 символов A-Za-z0-9_-; по нему файл адресуется везде. На сервере — slug. Не меняется при переименовании и переносе
name string имя; уникально в папке
folder ?string имя папки; null — корень бакета
content FileContent размер, тип, расширение, хеш
public bool доступен ли по publicUrl без ключа; следует за папкой
deduplicated bool такие байты в бакете уже были — место на диске не потрачено
processed ?Processing отчёт об обработке картинки; только в ответе на загрузку, при чтении — null
expiresAt ?DateTimeImmutable когда файл удалит срок хранения папки; null — не удалится сам
privateUrl string адрес /p/{id} — отдаёт файл с любым ключом в заголовке Authorization
publicUrl ?string адрес /o/{bucketId}/{id} — без ключа; null, пока файл не публичный
createdAt DateTimeImmutable когда загружен
updatedAt DateTimeImmutable когда изменён (имя, папка)

Адреса строятся от PUBLIC_BASE_URL сервера — см. настройку S5W.

File::ID_PATTERN, File::isValidId()

Формат id: /^[A-Za-z0-9_-]{16}$/. Метод проверяет только форму, а не существование файла — удобно, чтобы отсеять мусор из адреса страницы до запроса.

php
public const string ID_PATTERN = '/^[A-Za-z0-9_-]{16}$/';
public static function isValidId(string $id): bool
php
File::isValidId('FXOkqegbdrNRWQgc');   // true
File::isValidId('../etc/passwd');      // false

FileContent

Байты файла. Два файла с одинаковым содержимым ссылаются на одни и те же байты.

Поле Тип Описание
size int размер в байтах
mime string MIME-тип, определённый сервером по содержимому
extension string расширение, соответствующее типу; может быть пустым
hash string SHA-256 содержимого, 64 символа в нижнем регистре

Processing

Что сервер сделал с картинкой при загрузке.

Поле Тип Описание
applied bool была ли обработка
reason ?string почему не было: no options, nothing to do, animated, output is larger than source; null, если была
operations list<string> что сделано, например ["resize:400x267", "encode:webp@80"]
source ?ImageInfo исходная картинка; null, если обработки не было
result ?ImageInfo результат; null, если обработки не было

Методы

saved(): int — сколько байт сэкономлено: source->size - result->size. Отрицательное, если результат тяжелее; 0, если обработки не было.

ImageInfo

Поле Тип Описание
width int ширина, пикселей
height int высота, пикселей
size int размер, байт
mime string MIME-тип

Folder

Папка. Один уровень, без вложенности; имя уникально в бакете.

Поле Тип Описание
name string имя
public bool файлы внутри доступны без ключа
retention Retention срок хранения файлов
cache CachePolicy политика кэша папки
createdAt DateTimeImmutable когда создана
updatedAt DateTimeImmutable когда изменена

Folder::ROOT

Корень бакета там, где ожидается папка.

php
public const string ROOT = '/';

Значение / не может быть именем настоящей папки, поэтому путаницы нет. Где действует:

Метод Что значит Folder::ROOT
files()->list(), files()->all() только файлы без папки
files()->move(), files()->update() перенести в корень (файл станет публичным)
files()->upload(), uploads()->send() и другие загрузки загрузить в корень — то же, что null

CachePolicy

Переопределение кэша на уровне папки. Каждое поле со значением null наследуется от бакета.

Поле Тип Описание
maxAge ?int max-age, секунд
visibility ?CacheVisibility кто может кэшировать

Методы

isInherited(): bool — true, если оба поля null: папка ничего не переопределяет.

Page

Одна страница списка. Повторяет формат сервера { meta, data }.

Поле Тип Описание
items list<T> элементы этой страницы (File или Folder)
current int номер страницы, с 1
size int размер страницы, который применил сервер
total int сколько элементов всего под фильтром, на всех страницах
pages int сколько всего страниц
previous ?int номер предыдущей страницы или null
next ?int номер следующей страницы или null

Методы

hasNext(): bool — есть ли следующая страница.

isEmpty(): bool — пуста ли эта страница.

count($page) — сколько элементов на этой странице (Countable). Не путать с total.

foreach ($page as $item) — обход элементов этой страницы (IteratorAggregate).

map(callable $fn): Page — новая страница, где каждый элемент прошёл через $fn; мета сохраняется. Удобно, чтобы превратить сущности в свои DTO.

toArray() / jsonSerialize() — { meta: { current, size, total, pages, previous, next }, data: [...] }.

php
$page = $s5w->files()->list(limit: 10);

count($page);       // 10 — на этой странице
$page->total;       // 134 — всего
$page->hasNext();   // true

$names = $page->map(fn(File $f) => $f->name);
json_encode($names);   // {"meta":{…},"data":["a.txt","b.txt",…]}

previous за последней страницей

Если запросить страницу дальше последней, сервер вернёт пустой список, но previous будет равен current - 1 — например, 998 при pages = 1. Для навигации надёжнее опираться на pages.

UploadSession

Состояние загрузки частями. Каждый вызов uploads() возвращает новую сессию с текущим смещением сервера.

Поле Тип Описание
id string UUID сессии; пустая строка, если сработала дедупликация
name string имя, заявленное при старте
size int заявленный размер, байт
offset int сколько байт уже на сервере — отсюда начинается следующая часть
chunkSize int каким размером сервер просит слать части; 0 при дедупликации
expiresAt ?DateTimeImmutable когда сессию удалят без новых частей; null при дедупликации
file ?File готовый файл, если содержимое уже было в бакете

Методы

isDeduplicated(): bool — содержимое было в бакете, файл готов, передавать нечего.

isComplete(): bool — все байты на сервере (offset >= size), можно собирать.

remaining(): int — сколько байт осталось отправить.

KeyInfo

Ответ check(): что стоит за ключом.

Поле Тип Описание
bucket BucketRef бакет ключа
access TokenAccess уровень доступа
expiresAt ?DateTimeImmutable когда ключ истечёт; null — бессрочный
storage Storage место в бакете

Методы

expiresBefore(DateTimeInterface $at = now): bool — истечёт ли ключ к моменту $at.

php
if ($s5w->check()->expiresBefore(new DateTimeImmutable('+7 days'))) {
  $logger->warning('Ключ S5W истекает в течение недели');
}

BucketRef

Поле Тип Описание
id string UUID бакета; это {bucketId} в публичных адресах /o/{bucketId}/{id}
name string имя бакета

Storage

Место в бакете, в байтах.

Поле Тип Описание
quota int квота
used int занято
free int свободно

Методы

fits(int $bytes): bool — поместится ли ещё $bytes байт.

usage(): float — доля занятого, от 0.0 до 1.0.