\n\n";
+
+ return $html;
+ }
+}
+
+// Использование
+$response = $filmService->getTopFilms(page: 1);
+$report = new PaginationReport($response);
+
+// Создание текстового отчета
+$textReport = $report->createDetailedReport();
+echo $textReport;
+
+// Создание HTML отчета
+$htmlReport = $report->createHtmlReport('Отчет по пагинации');
+file_put_contents('pagination_report.html', $htmlReport);
+echo "\n✅ HTML отчет сохранен в pagination_report.html\n";
+```
+
+## Анализ пагинации
+
+```php
+function analyzePagination(PaginatedResponse $response): array {
+ $analysis = [
+ 'basicStats' => [
+ 'total' => $response->total,
+ 'totalPages' => $response->totalPages,
+ 'currentPage' => $response->currentPage,
+ 'itemsPerPage' => $response->getCount(),
+ 'averageItemsPerPage' => $response->totalPages > 0 ? round($response->total / $response->totalPages, 1) : 0,
+ 'progress' => $response->totalPages > 0 ? round(($response->currentPage / $response->totalPages) * 100, 1) : 0
+ ],
+ 'navigation' => [
+ 'hasNext' => $response->hasNextPage(),
+ 'hasPrevious' => $response->hasPreviousPage(),
+ 'isFirst' => $response->isFirstPage(),
+ 'isLast' => $response->isLastPage(),
+ 'nextPage' => $response->hasNextPage() ? $response->getNextPage() : null,
+ 'previousPage' => $response->hasPreviousPage() ? $response->getPreviousPage() : null,
+ 'firstPage' => $response->getFirstPage(),
+ 'lastPage' => $response->getLastPage()
+ ],
+ 'pageDistribution' => [
+ 'pagesBeforeCurrent' => $response->currentPage - 1,
+ 'pagesAfterCurrent' => $response->totalPages - $response->currentPage,
+ 'totalPagesInRange' => $response->totalPages,
+ 'currentPagePosition' => $response->totalPages > 0 ? round(($response->currentPage / $response->totalPages) * 100, 1) : 0
+ ]
+ ];
+
+ return $analysis;
+}
+
+// Использование
+$response = $filmService->getTopFilms(page: 1);
+$analysis = analyzePagination($response);
+
+echo "=== Анализ пагинации ===\n";
+
+// Основная статистика
+$basicStats = $analysis['basicStats'];
+echo "Основная статистика:\n";
+echo "- Всего элементов: {$basicStats['total']}\n";
+echo "- Всего страниц: {$basicStats['totalPages']}\n";
+echo "- Текущая страница: {$basicStats['currentPage']}\n";
+echo "- Элементов на странице: {$basicStats['itemsPerPage']}\n";
+echo "- Среднее элементов на странице: {$basicStats['averageItemsPerPage']}\n";
+echo "- Прогресс: {$basicStats['progress']}%\n";
+
+// Навигация
+$navigation = $analysis['navigation'];
+echo "\nНавигация:\n";
+echo "- Есть следующая страница: " . ($navigation['hasNext'] ? 'Да' : 'Нет') . "\n";
+echo "- Есть предыдущая страница: " . ($navigation['hasPrevious'] ? 'Да' : 'Нет') . "\n";
+echo "- Это первая страница: " . ($navigation['isFirst'] ? 'Да' : 'Нет') . "\n";
+echo "- Это последняя страница: " . ($navigation['isLast'] ? 'Да' : 'Нет') . "\n";
+
+if ($navigation['nextPage']) {
+ echo "- Следующая страница: {$navigation['nextPage']}\n";
+}
+if ($navigation['previousPage']) {
+ echo "- Предыдущая страница: {$navigation['previousPage']}\n";
+}
+
+// Распределение страниц
+$pageDistribution = $analysis['pageDistribution'];
+echo "\nРаспределение страниц:\n";
+echo "- Страниц до текущей: {$pageDistribution['pagesBeforeCurrent']}\n";
+echo "- Страниц после текущей: {$pageDistribution['pagesAfterCurrent']}\n";
+echo "- Всего страниц в диапазоне: {$pageDistribution['totalPagesInRange']}\n";
+echo "- Позиция текущей страницы: {$pageDistribution['currentPagePosition']}%\n";
+```
+
+## Связанные классы
+
+- [`DefaultResponse`](default-response.md) - Базовый класс для ответов API
+- [`KpValidationException`](../exceptions/kp-validation-exception.md) - Исключение валидации
+- [`Film`](../models/film.md) - Модель фильма
+- [`FilmService`](../services/film-service.md) - Сервис для работы с фильмами
diff --git a/docs/dev/notkinopoiskphp/responses/review-response.md b/docs/dev/notkinopoiskphp/responses/review-response.md
new file mode 100644
index 0000000..8d805a9
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/responses/review-response.md
@@ -0,0 +1,271 @@
+---
+tags:
+ - PHP
+ - API
+ - Ответы
+title: "ReviewResponse - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по reviewresponse. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Ответы, reviewresponse, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "ReviewResponse"
+og:description: "Документация по reviewresponse. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "ReviewResponse"
+twitter:description: "Документация по reviewresponse. Часть API wrapper для КиноПоиска."
+---
+
+# ReviewResponse
+
+## Описание
+
+`ReviewResponse` - это специализированный класс ответа для работы с отзывами на фильмы от Kinopoisk API. Наследует функциональность `PaginatedResponse` и добавляет специфичные поля для статистики отзывов по типам (положительные, отрицательные, нейтральные).
+
+## Основные возможности
+
+- Наследование функциональности пагинации от `PaginatedResponse`
+- Хранение статистики отзывов по типам
+- Создание объекта из данных API с валидацией
+- Преобразование в массив для сериализации
+- Поддержка всех методов пагинации
+
+## Наследование
+
+```php
+NotKinopoisk\Responses\PaginatedResponse
+└── NotKinopoisk\Responses\ReviewResponse
+```
+
+## Конструктор
+
+```php
+public function __construct(
+ int $total,
+ array $items,
+ int $currentPage,
+ int $totalPages,
+ public int $totalPositiveReviews,
+ public int $totalNegativeReviews,
+ public int $totalNeutralReviews
+)
+```
+
+### Параметры
+
+- `$total` (int) - Общее количество отзывов
+- `$items` (array) - Массив отзывов текущей страницы
+- `$currentPage` (int) - Номер текущей страницы
+- `$totalPages` (int) - Общее количество страниц
+- `$totalPositiveReviews` (int) - Общее количество положительных отзывов
+- `$totalNegativeReviews` (int) - Общее количество отрицательных отзывов
+- `$totalNeutralReviews` (int) - Общее количество нейтральных отзывов
+
+## Свойства
+
+### totalPositiveReviews
+
+```php
+public int $totalPositiveReviews
+```
+
+Общее количество положительных отзывов на фильм.
+
+### totalNegativeReviews
+
+```php
+public int $totalNegativeReviews
+```
+
+Общее количество отрицательных отзывов на фильм.
+
+### totalNeutralReviews
+
+```php
+public int $totalNeutralReviews
+```
+
+Общее количество нейтральных отзывов на фильм.
+
+## Статические методы
+
+### fromArray()
+
+```php
+public static function fromArray(array $data, string $cls): self
+```
+
+Создает экземпляр `ReviewResponse` из массива данных API.
+
+#### Параметры
+
+- `$data` (array) - Массив данных от API, содержащий информацию об отзывах
+- `$cls` (string) - Имя класса для элементов коллекции (обычно `Review::class`)
+
+#### Возвращает
+
+- `ReviewResponse` - Новый экземпляр с данными об отзывах
+
+#### Исключения
+
+- `KpValidationException` - Если данные имеют некорректную структуру
+
+#### Пример использования
+
+```php
+$apiData = [
+ 'total' => 150,
+ 'items' => [...],
+ 'current_page' => 1,
+ 'total_pages' => 5,
+ 'totalPositiveReviews' => 100,
+ 'totalNegativeReviews' => 30,
+ 'totalNeutralReviews' => 20
+];
+
+$reviewResponse = ReviewResponse::fromArray($apiData, Review::class);
+```
+
+## Методы экземпляра
+
+### toArray()
+
+```php
+public function toArray(): array
+```
+
+Преобразует объект в массив.
+
+#### Возвращает
+
+- `array` - Массив с данными об отзывах и статистикой
+
+#### Пример использования
+
+```php
+$response = ReviewResponse::fromArray($apiData, Review::class);
+$array = $response->toArray();
+```
+
+## Наследованные методы
+
+`ReviewResponse` наследует все методы от `PaginatedResponse`:
+
+- `getNextPage()` - Получение номера следующей страницы
+- `hasNextPage()` - Проверка наличия следующей страницы
+- `getPreviousPage()` - Получение номера предыдущей страницы
+- `hasPreviousPage()` - Проверка наличия предыдущей страницы
+- `getFirstPage()` - Получение номера первой страницы
+- `getLastPage()` - Получение номера последней страницы
+- `isFirstPage()` - Проверка, является ли текущая страница первой
+- `isLastPage()` - Проверка, является ли текущая страница последней
+- `getPaginationInfo()` - Получение информации о пагинации
+
+## Типы отзывов
+
+Класс поддерживает следующие типы отзывов:
+
+- **Положительные** - Отзывы с положительной оценкой
+- **Отрицательные** - Отзывы с отрицательной оценкой
+- **Нейтральные** - Отзывы с нейтральной оценкой
+
+## Статистика отзывов
+
+Класс предоставляет доступ к статистике отзывов:
+
+```php
+// Получение статистики
+$positiveCount = $reviewResponse->totalPositiveReviews;
+$negativeCount = $reviewResponse->totalNegativeReviews;
+$neutralCount = $reviewResponse->totalNeutralReviews;
+
+// Вычисление общего количества
+$totalReviews = $positiveCount + $negativeCount + $neutralCount;
+
+// Вычисление процентов
+$positivePercent = ($positiveCount / $totalReviews) * 100;
+$negativePercent = ($negativeCount / $totalReviews) * 100;
+$neutralPercent = ($neutralCount / $totalReviews) * 100;
+```
+
+## Обработка ошибок
+
+Класс включает обработку ошибок:
+
+- Валидация структуры данных API
+- Проверка типизации элементов
+- Обработка некорректных данных отзывов
+- Валидация параметров пагинации
+
+## Пример полного использования
+
+```php
+use NotKinopoisk\Responses\ReviewResponse;
+use NotKinopoisk\Models\Review;
+
+// Получение данных от API
+$apiData = [
+ 'total' => 150,
+ 'items' => [
+ [
+ 'reviewId' => 1,
+ 'reviewType' => 'POSITIVE',
+ 'reviewText' => 'Отличный фильм!'
+ ],
+ [
+ 'reviewId' => 2,
+ 'reviewType' => 'NEGATIVE',
+ 'reviewText' => 'Не понравилось'
+ ]
+ ],
+ 'current_page' => 1,
+ 'total_pages' => 5,
+ 'totalPositiveReviews' => 100,
+ 'totalNegativeReviews' => 30,
+ 'totalNeutralReviews' => 20
+];
+
+// Создание объекта ответа
+$reviewResponse = ReviewResponse::fromArray($apiData, Review::class);
+
+// Анализ статистики отзывов
+$positiveCount = $reviewResponse->totalPositiveReviews;
+$negativeCount = $reviewResponse->totalNegativeReviews;
+$neutralCount = $reviewResponse->totalNeutralReviews;
+
+$totalReviews = $positiveCount + $negativeCount + $neutralCount;
+
+echo "Статистика отзывов:\n";
+echo "- Положительных: {$positiveCount} (" . round(($positiveCount / $totalReviews) * 100, 1) . "%)\n";
+echo "- Отрицательных: {$negativeCount} (" . round(($negativeCount / $totalReviews) * 100, 1) . "%)\n";
+echo "- Нейтральных: {$neutralCount} (" . round(($neutralCount / $totalReviews) * 100, 1) . "%)\n";
+echo "- Всего: {$totalReviews}\n";
+
+// Работа с пагинацией
+echo "\nПагинация:\n";
+echo "- Текущая страница: {$reviewResponse->currentPage}\n";
+echo "- Всего страниц: {$reviewResponse->totalPages}\n";
+echo "- Отзывов на странице: " . count($reviewResponse->items) . "\n";
+
+if ($reviewResponse->hasNextPage()) {
+ echo "- Следующая страница: {$reviewResponse->getNextPage()}\n";
+}
+
+if ($reviewResponse->hasPreviousPage()) {
+ echo "- Предыдущая страница: {$reviewResponse->getPreviousPage()}\n";
+}
+
+// Обработка отзывов
+echo "\nОтзывы на текущей странице:\n";
+foreach ($reviewResponse->items as $review) {
+ echo "- [{$review->reviewType}] {$review->reviewText}\n";
+}
+
+// Преобразование в массив
+$array = $reviewResponse->toArray();
+```
+
+## Связанные классы
+
+- `PaginatedResponse` - Базовый класс для пагинированных ответов
+- `Review` - Модель отзыва на фильм
+- `KpValidationException` - Исключение для ошибок валидации
+- `DefaultResponse` - Базовый класс для всех ответов API
diff --git a/docs/dev/notkinopoiskphp/responses/sequel-prequel-response.md b/docs/dev/notkinopoiskphp/responses/sequel-prequel-response.md
new file mode 100644
index 0000000..c4d38ef
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/responses/sequel-prequel-response.md
@@ -0,0 +1,458 @@
+---
+tags:
+ - PHP
+ - API
+ - Ответы
+title: "SequelPrequelResponse - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по sequelprequelresponse. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Ответы, sequelprequelresponse, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "SequelPrequelResponse"
+og:description: "Документация по sequelprequelresponse. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "SequelPrequelResponse"
+twitter:description: "Документация по sequelprequelresponse. Часть API wrapper для КиноПоиска."
+---
+
+# SequelPrequelResponse
+
+## Описание
+
+`SequelPrequelResponse` - это специализированный класс ответа для работы с сиквелами, приквелами и связанными фильмами от Kinopoisk API. Наследует функциональность `SimpleResponse` и предоставляет расширенные методы для фильтрации и анализа связанных фильмов по типам отношений.
+
+## Основные возможности
+
+- Фильтрация фильмов по типу отношения (сиквелы, приквелы, римейки, похожие)
+- Объединение и сортировка связанных фильмов
+- Статистика по типам отношений
+- Группировка фильмов по типам связей
+- Проверка наличия фильмов определенного типа
+- Получение уникальных типов отношений
+
+## Наследование
+
+```php
+NotKinopoisk\Responses\SimpleResponse
+└── NotKinopoisk\Responses\SequelPrequelResponse
+```
+
+## Конструктор
+
+```php
+public function __construct(public array $items)
+```
+
+### Параметры
+
+- `$items` (array) - Массив связанных фильмов
+
+## Статические методы
+
+### fromArray()
+
+```php
+public static function fromArray(array $data, string $cls): self
+```
+
+Создает экземпляр `SequelPrequelResponse` из массива данных API.
+
+#### Параметры
+
+- `$data` (array) - Массив данных от API
+- `$cls` (string) - Имя класса для элементов коллекции
+
+#### Возвращает
+
+- `SequelPrequelResponse` - Новый экземпляр с данными о связанных фильмах
+
+#### Исключения
+
+- `KpValidationException` - Если данные имеют некорректную структуру
+
+## Методы экземпляра
+
+### getPrequelsAndSequels()
+
+```php
+public function getPrequelsAndSequels(): array
+```
+
+Получает объединённый и отсортированный список приквелов и сиквелов.
+
+#### Возвращает
+
+- `array` - Отсортированный массив приквелов и сиквелов
+
+#### Исключения
+
+- `KpValidationException` - При ошибках во время обработки данных
+
+#### Пример использования
+
+```php
+$combined = $response->getPrequelsAndSequels();
+foreach ($combined as $film) {
+ echo "{$film->getDisplayName()} - {$film->relationType->getDescription()}\n";
+}
+```
+
+### getSequels()
+
+```php
+public function getSequels(): array
+```
+
+Получает все фильмы-сиквелы.
+
+#### Возвращает
+
+- `array` - Массив фильмов-сиквелов
+
+#### Исключения
+
+- `KpValidationException` - При некорректной структуре данных
+
+#### Пример использования
+
+```php
+$sequels = $response->getSequels();
+echo "Найдено сиквелов: " . count($sequels) . "\n";
+foreach ($sequels as $sequel) {
+ echo "- {$sequel->getDisplayName()}\n";
+}
+```
+
+### getPrequels()
+
+```php
+public function getPrequels(): array
+```
+
+Получает все фильмы-приквелы.
+
+#### Возвращает
+
+- `array` - Массив фильмов-приквелов
+
+#### Исключения
+
+- `KpValidationException` - При некорректной структуре данных
+
+#### Пример использования
+
+```php
+$prequels = $response->getPrequels();
+echo "Найдено приквелов: " . count($prequels) . "\n";
+foreach ($prequels as $prequel) {
+ echo "- {$prequel->getDisplayName()}\n";
+}
+```
+
+### hasFilmsOfType()
+
+```php
+public function hasFilmsOfType(RelationType $type): bool
+```
+
+Проверяет наличие фильмов указанного типа.
+
+#### Параметры
+
+- `$type` (RelationType) - Тип отношения для проверки
+
+#### Возвращает
+
+- `bool` - True если фильмы присутствуют, false в противном случае
+
+#### Пример использования
+
+```php
+if ($response->hasFilmsOfType(RelationType::SEQUEL)) {
+ echo "У фильма есть сиквелы\n";
+}
+
+if ($response->hasFilmsOfType(RelationType::PREQUEL)) {
+ echo "У фильма есть приквелы\n";
+}
+```
+
+### getByRelationType()
+
+```php
+public function getByRelationType(RelationType $type): array
+```
+
+Получает все фильмы указанного типа отношения.
+
+#### Параметры
+
+- `$type` (RelationType) - Тип отношения между фильмами
+
+#### Возвращает
+
+- `array` - Массив фильмов указанного типа
+
+#### Исключения
+
+- `KpValidationException` - При некорректных параметрах или данных
+
+#### Пример использования
+
+```php
+// Получение фильмов по типу
+$sequels = $response->getByRelationType(RelationType::SEQUEL);
+$prequels = $response->getByRelationType(RelationType::PREQUEL);
+$remakes = $response->getByRelationType(RelationType::REMAKE);
+$similar = $response->getByRelationType(RelationType::SIMILAR);
+```
+
+### getRemakes()
+
+```php
+public function getRemakes(): array
+```
+
+Получает все римейки.
+
+#### Возвращает
+
+- `array` - Массив римейков
+
+#### Исключения
+
+- `KpValidationException` - При некорректной структуре данных
+
+#### Пример использования
+
+```php
+$remakes = $response->getRemakes();
+echo "Найдено римейков: " . count($remakes) . "\n";
+foreach ($remakes as $remake) {
+ echo "- {$remake->getDisplayName()}\n";
+}
+```
+
+### getSimilar()
+
+```php
+public function getSimilar(): array
+```
+
+Получает все похожие фильмы.
+
+#### Возвращает
+
+- `array` - Массив похожих фильмов
+
+#### Исключения
+
+- `KpValidationException` - При некорректной структуре данных
+
+#### Пример использования
+
+```php
+$similar = $response->getSimilar();
+echo "Найдено похожих фильмов: " . count($similar) . "\n";
+foreach ($similar as $film) {
+ echo "- {$film->getDisplayName()}\n";
+}
+```
+
+### getStatistics()
+
+```php
+public function getStatistics(): array
+```
+
+Получает статистику по всем типам отношений.
+
+#### Возвращает
+
+- `array` - Статистика по типам отношений
+
+#### Пример использования
+
+```php
+$stats = $response->getStatistics();
+echo "Общая статистика:\n";
+echo "- Сиквелов: {$stats['sequels']}\n";
+echo "- Приквелов: {$stats['prequels']}\n";
+echo "- Римейков: {$stats['remakes']}\n";
+echo "- Похожих: {$stats['similar']}\n";
+echo "- Всего: {$stats['total']}\n";
+```
+
+### countByType()
+
+```php
+public function countByType(RelationType $type): int
+```
+
+Возвращает количество фильмов указанного типа.
+
+#### Параметры
+
+- `$type` (RelationType) - Тип отношения для подсчёта
+
+#### Возвращает
+
+- `int` - Количество фильмов указанного типа
+
+#### Пример использования
+
+```php
+$sequelCount = $response->countByType(RelationType::SEQUEL);
+echo "Количество сиквелов: $sequelCount\n";
+
+$prequelCount = $response->countByType(RelationType::PREQUEL);
+echo "Количество приквелов: $prequelCount\n";
+```
+
+### hasRelatedFilms()
+
+```php
+public function hasRelatedFilms(): bool
+```
+
+Проверяет, есть ли связанные фильмы.
+
+#### Возвращает
+
+- `bool` - True если есть хотя бы один связанный фильм
+
+#### Пример использования
+
+```php
+if ($response->hasRelatedFilms()) {
+ echo "У фильма есть связанные фильмы\n";
+} else {
+ echo "У фильма нет связанных фильмов\n";
+}
+```
+
+### getAvailableRelationTypes()
+
+```php
+public function getAvailableRelationTypes(): array
+```
+
+Получает все уникальные типы отношений в текущем наборе данных.
+
+#### Возвращает
+
+- `array` - Массив уникальных типов отношений
+
+#### Пример использования
+
+```php
+$types = $response->getAvailableRelationTypes();
+echo "Доступные типы отношений:\n";
+foreach ($types as $type) {
+ echo "- {$type->getDescription()}\n";
+}
+```
+
+### groupByRelationType()
+
+```php
+public function groupByRelationType(): array
+```
+
+Группирует связанные фильмы по типу отношения.
+
+#### Возвращает
+
+- `array>` - Ассоциативный массив, где ключи - строковые значения типов связей, а значения - массивы объектов RelatedFilm
+
+#### Пример использования
+
+```php
+// Группировка связанных фильмов
+$groups = $response->groupByRelationType();
+
+// Обработка сгруппированных данных
+foreach ($groups as $relationType => $films) {
+ echo "Тип связи: {$relationType}\n";
+ echo "Количество фильмов: " . count($films) . "\n";
+
+ foreach ($films as $film) {
+ echo " - {$film->getDisplayName()}\n";
+ }
+ echo "\n";
+}
+
+// Получение конкретного типа связи
+$sequels = $groups['SEQUEL'] ?? [];
+$similars = $groups['SIMILAR'] ?? [];
+
+// Проверка наличия определённого типа
+if (isset($groups['PREQUEL'])) {
+ echo "Найдены приквелы: " . count($groups['PREQUEL']) . " шт.\n";
+}
+```
+
+## Типы отношений
+
+Класс поддерживает следующие типы отношений:
+
+- **SEQUEL** - Сиквелы (продолжения)
+- **PREQUEL** - Приквелы (предыстории)
+- **REMAKE** - Римейки (новые версии)
+- **SIMILAR** - Похожие фильмы
+- **UNKNOWN** - Неизвестный тип связи
+
+## Обработка ошибок
+
+Класс включает комплексную обработку ошибок:
+
+- Валидация структуры данных API
+- Проверка типизации элементов
+- Обработка некорректных типов отношений
+- Безопасная фильтрация и группировка
+
+## Пример полного использования
+
+```php
+use NotKinopoisk\Responses\SequelPrequelResponse;
+use NotKinopoisk\Models\RelatedFilm;
+use NotKinopoisk\Enums\RelationType;
+
+// Получение данных от API
+$apiData = [
+ ['kinopoiskId' => 1, 'relationType' => 'SEQUEL'],
+ ['kinopoiskId' => 2, 'relationType' => 'PREQUEL'],
+ ['kinopoiskId' => 3, 'relationType' => 'SIMILAR']
+];
+
+// Создание объекта ответа
+$response = SequelPrequelResponse::fromArray($apiData, RelatedFilm::class);
+
+// Анализ связанных фильмов
+$sequels = $response->getSequels();
+$prequels = $response->getPrequels();
+$similar = $response->getSimilar();
+
+$stats = $response->getStatistics();
+$groups = $response->groupByRelationType();
+
+echo "Статистика связанных фильмов:\n";
+foreach ($stats as $type => $count) {
+ echo "- {$type}: {$count}\n";
+}
+
+// Проверка наличия определенных типов
+if ($response->hasFilmsOfType(RelationType::SEQUEL)) {
+ echo "Найдены сиквелы: " . count($sequels) . "\n";
+}
+
+if ($response->hasRelatedFilms()) {
+ echo "Всего связанных фильмов: " . count($response->items) . "\n";
+}
+```
+
+## Связанные классы
+
+- `SimpleResponse` - Базовый класс для простых ответов
+- `RelatedFilm` - Модель связанного фильма
+- `RelationType` - Перечисление типов отношений
+- `KpValidationException` - Исключение для ошибок валидации
diff --git a/docs/dev/notkinopoiskphp/responses/simple-response.md b/docs/dev/notkinopoiskphp/responses/simple-response.md
new file mode 100644
index 0000000..6576757
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/responses/simple-response.md
@@ -0,0 +1,221 @@
+---
+tags:
+ - PHP
+ - API
+ - Ответы
+title: "SimpleResponse - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по simpleresponse. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Ответы, simpleresponse, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "SimpleResponse"
+og:description: "Документация по simpleresponse. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "SimpleResponse"
+twitter:description: "Документация по simpleresponse. Часть API wrapper для КиноПоиска."
+---
+
+# SimpleResponse
+
+## Описание
+
+`SimpleResponse` - это базовый класс для простых ответов API, содержащих только массив элементов без дополнительной метаинформации. Реализует интерфейс `ResponseInterface` и предоставляет базовую функциональность для работы с коллекциями объектов.
+
+## Основные возможности
+
+- Хранение массива элементов в неизменяемом виде
+- Создание объекта из массива данных API с валидацией класса
+- Преобразование элементов в указанный тип через статический метод `fromArray`
+- Преобразование в массив для сериализации
+- Валидация целевого класса для преобразования элементов
+
+## Наследование
+
+```php
+NotKinopoisk\Interfaces\ResponseInterface
+└── NotKinopoisk\Responses\SimpleResponse
+```
+
+## Конструктор
+
+```php
+public function __construct(public array $items)
+```
+
+### Параметры
+
+- `$items` (array) - Массив элементов данных
+
+## Свойства
+
+### items
+
+```php
+public array $items
+```
+
+Массив элементов ответа. Доступен только для чтения.
+
+## Статические методы
+
+### fromArray()
+
+```php
+public static function fromArray(array $data, string $cls): object
+```
+
+Создает экземпляр `SimpleResponse` из массива данных API.
+
+#### Параметры
+
+- `$data` (array) - Массив данных от API
+- `$cls` (string) - Имя класса для преобразования элементов
+
+#### Возвращает
+
+- `object` - Новый экземпляр с преобразованными данными
+
+#### Исключения
+
+- `KpValidationException` - Если указанный класс не существует или не имеет метода `fromArray`
+
+#### Пример использования
+
+```php
+$apiData = [
+ ['id' => 1, 'name' => 'Item 1'],
+ ['id' => 2, 'name' => 'Item 2']
+];
+
+$response = SimpleResponse::fromArray($apiData, MyModel::class);
+```
+
+### checkClass()
+
+```php
+public static function checkClass(string $cls): void
+```
+
+Валидирует целевой класс для преобразования элементов.
+
+#### Параметры
+
+- `$cls` (string) - Полное имя класса
+
+#### Исключения
+
+- `KpValidationException` - Если класс не существует или не имеет статического метода `fromArray`
+
+#### Пример использования
+
+```php
+SimpleResponse::checkClass(MyModel::class);
+```
+
+## Методы экземпляра
+
+### toArray()
+
+```php
+public function toArray(): array
+```
+
+Преобразует объект в массив.
+
+#### Возвращает
+
+- `array` - Массив с преобразованными элементами
+
+#### Пример использования
+
+```php
+$response = SimpleResponse::fromArray($apiData, MyModel::class);
+$array = $response->toArray();
+```
+
+## Требования к целевым классам
+
+Для корректной работы с `SimpleResponse` целевые классы должны:
+
+1. **Существовать** - Класс должен быть доступен в системе
+2. **Иметь статический метод `fromArray`** - Метод должен принимать массив и возвращать объект
+3. **Иметь метод `toArray`** - Для корректного преобразования в массив
+
+### Пример корректного класса
+
+```php
+class MyModel
+{
+ public function __construct(
+ public int $id,
+ public string $name
+ ) {}
+
+ public static function fromArray(array $data): self
+ {
+ return new self(
+ id: $data['id'],
+ name: $data['name']
+ );
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'id' => $this->id,
+ 'name' => $this->name
+ ];
+ }
+}
+```
+
+## Обработка ошибок
+
+Класс включает комплексную обработку ошибок:
+
+- **Проверка существования класса** - Убеждается, что указанный класс существует
+- **Валидация метода `fromArray`** - Проверяет наличие и статичность метода
+- **Обработка ошибок типизации** - Безопасное преобразование данных
+
+## Пример полного использования
+
+```php
+use NotKinopoisk\Responses\SimpleResponse;
+use NotKinopoisk\Models\MyModel;
+
+// Получение данных от API
+$apiData = [
+ ['id' => 1, 'name' => 'Первый элемент'],
+ ['id' => 2, 'name' => 'Второй элемент'],
+ ['id' => 3, 'name' => 'Третий элемент']
+];
+
+// Создание объекта ответа
+$response = SimpleResponse::fromArray($apiData, MyModel::class);
+
+// Доступ к элементам
+$items = $response->items;
+echo "Количество элементов: " . count($items) . "\n";
+
+// Обработка элементов
+foreach ($items as $item) {
+ echo "ID: {$item->id}, Имя: {$item->name}\n";
+}
+
+// Преобразование в массив
+$array = $response->toArray();
+echo "Преобразовано в массив: " . json_encode($array, JSON_UNESCAPED_UNICODE) . "\n";
+```
+
+## Наследование
+
+`SimpleResponse` является базовым классом для более специализированных ответов:
+
+- `MovieStaffResponse` - Для работы со съемочной командой
+- `SequelPrequelResponse` - Для работы с сиквелами и приквелами
+
+## Связанные классы
+
+- `ResponseInterface` - Интерфейс для всех ответов API
+- `KpValidationException` - Исключение для ошибок валидации
+- `DefaultResponse` - Расширенный базовый класс с метаинформацией
+- `PaginatedResponse` - Класс для пагинированных ответов
diff --git a/docs/dev/notkinopoiskphp/services/.nav.yml b/docs/dev/notkinopoiskphp/services/.nav.yml
new file mode 100644
index 0000000..f7437de
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/.nav.yml
@@ -0,0 +1,6 @@
+title: Сервисы (Services)
+nav:
+ - Оглавление: index.md
+ - "*"
+sort:
+ type: alphabetical
diff --git a/docs/dev/notkinopoiskphp/services/abstract-service.md b/docs/dev/notkinopoiskphp/services/abstract-service.md
new file mode 100644
index 0000000..bb190f0
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/abstract-service.md
@@ -0,0 +1,498 @@
+---
+tags:
+ - PHP
+ - API
+ - Сервисы
+title: "AbstractService - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по abstractservice. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Сервисы, abstractservice, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "AbstractService"
+og:description: "Документация по abstractservice. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "AbstractService"
+twitter:description: "Документация по abstractservice. Часть API wrapper для КиноПоиска."
+---
+
+# AbstractService
+
+## Описание
+
+`AbstractService` - это абстрактный базовый класс для сервисов Kinopoisk API. Предоставляет общую функциональность для всех сервисов, работающих с Kinopoisk API, содержащий базовые методы для выполнения запросов и обработки ответов.
+
+## Основные возможности
+
+- Общие методы для работы с API
+- Обработка ошибок и исключений
+- Логирование запросов и ответов
+- Базовая валидация данных
+- Управление версиями API
+
+## Наследование
+
+```php
+NotKinopoisk\Services\AbstractService
+├── NotKinopoisk\Services\FilmService
+├── NotKinopoisk\Services\PersonService
+├── NotKinopoisk\Services\MediaService
+└── NotKinopoisk\Services\UserService
+```
+
+## Конструктор
+
+```php
+public function __construct(Client $client, ApiVersion $apiVersion = ApiVersion::V1)
+```
+
+### Параметры
+
+- `$client` (Client) - Основной клиент для работы с API
+- `$apiVersion` (ApiVersion) - Версия API для использования (по умолчанию 'v1')
+
+## Свойства
+
+### client
+
+```php
+protected Client $client
+```
+
+**Описание:** Основной клиент для работы с API
+
+**Тип:** `Client`
+
+**Доступ:** Защищенный
+
+**Пример:**
+
+```php
+// В наследующем классе
+$response = $this->client->get('/api/v1/endpoint');
+```
+
+### apiVersion
+
+```php
+protected ApiVersion $apiVersion
+```
+
+**Описание:** Версия API для использования
+
+**Тип:** `ApiVersion`
+
+**Доступ:** Защищенный
+
+**Пример:**
+
+```php
+// В наследующем классе
+$version = $this->apiVersion->value; // 'v1', 'v2.1', 'v2.2'
+```
+
+## Защищенные методы
+
+### setApiVersion()
+
+```php
+protected function setApiVersion(ApiVersion $apiVersion): void
+```
+
+Устанавливает версию API для работы сервиса.
+
+#### Параметры
+
+- `$apiVersion` (ApiVersion) - Версия API из перечисления доступных версий
+
+#### Особенности
+
+- Защищенный метод для внутреннего использования в классах-наследниках
+- Версия определяет структуру запросов и доступные эндпоинты
+
+#### Пример использования
+
+```php
+use NotKinopoisk\Services\AbstractService;
+use NotKinopoisk\Enums\ApiVersion;
+
+class MyService extends AbstractService
+{
+ public function useNewApiVersion(): void
+ {
+ // Установка версии API v2.2
+ $this->setApiVersion(ApiVersion::V22);
+
+ // Установка версии API v2.1
+ $this->setApiVersion(ApiVersion::V21);
+ }
+}
+```
+
+### get()
+
+```php
+protected function get(string $uri, array $query = []): array
+```
+
+Выполняет GET запрос к API.
+
+#### Параметры
+
+- `$uri` (string) - URI запроса относительно базового URL API
+- `$query` (array) - Параметры запроса, которые будут добавлены к URI как query string
+
+#### Возвращает
+
+- `array` - Декодированный JSON ответ от API
+
+#### Исключения
+
+- `ApiException` - При ошибках API или сети
+- `InvalidApiKeyException` - При неверном API ключе
+- `RateLimitException` - При превышении лимитов запросов
+- `ResourceNotFoundException` - При отсутствии ресурса
+
+#### Пример использования
+
+```php
+use NotKinopoisk\Services\AbstractService;
+
+class FilmService extends AbstractService
+{
+ public function getFilm(int $id): array
+ {
+ return $this->get("/films/{$id}");
+ }
+
+ public function searchFilms(string $keyword, int $page = 1): array
+ {
+ return $this->get('/films', [
+ 'keyword' => $keyword,
+ 'page' => $page
+ ]);
+ }
+}
+```
+
+### buildUri()
+
+```php
+protected function buildUri(string $endpoint, ?ApiVersion $api_version = null): string
+```
+
+Строит URI для API запроса указанной версии.
+
+#### Параметры
+
+- `$endpoint` (string) - Путь к ресурсу API (без префикса /api/vX.X/)
+- `$api_version` (ApiVersion|null) - Версия API для использования; если null, используется $this->apiVersion
+
+#### Возвращает
+
+- `string` - Полный URI для запроса к указанной версии API
+
+#### Особенности
+
+- Автоматически использует версию API по умолчанию, если версия не указана явно
+- Автоматически удаляет ведущий слеш из endpoint
+
+#### Пример использования
+
+```php
+use NotKinopoisk\Services\AbstractService;
+use NotKinopoisk\Enums\ApiVersion;
+
+class MyService extends AbstractService
+{
+ public function buildEndpoints(): void
+ {
+ // Использование версии по умолчанию
+ $uri = $this->buildUri('films/301');
+ // Результат: '/api/v2.2/films/301' (если $this->apiVersion = ApiVersion::V22)
+
+ // Явное указание версии API
+ $uri = $this->buildUri('films/301', ApiVersion::V21);
+ // Результат: '/api/v2.1/films/301'
+
+ // Автоматическое удаление ведущего слеша
+ $uri = $this->buildUri('/films/301');
+ // Результат: '/api/v2.2/films/301'
+
+ // Работа с вложенными ресурсами
+ $uri = $this->buildUri('films/301/similars');
+ // Результат: '/api/v2.2/films/301/similars'
+ }
+}
+```
+
+## Примеры использования
+
+### Создание базового сервиса
+
+```php
+use NotKinopoisk\Client;
+use NotKinopoisk\Services\AbstractService;
+use NotKinopoisk\Enums\ApiVersion;
+
+// Создание сервиса с версией API по умолчанию
+$client = new Client('your-api-key');
+$service = new FilmService($client);
+
+// Создание сервиса с указанной версией API
+$service = new FilmService($client, ApiVersion::V22);
+```
+
+### Создание собственного сервиса
+
+```php
+use NotKinopoisk\Client;
+use NotKinopoisk\Services\AbstractService;
+use NotKinopoisk\Enums\ApiVersion;
+
+class CustomService extends AbstractService
+{
+ public function getData(): array
+ {
+ $response = $this->client->get('/api/v1/endpoint');
+ return $response->getData();
+ }
+
+ public function getCustomEndpoint(): array
+ {
+ $uri = $this->buildUri('custom/endpoint');
+ return $this->get($uri);
+ }
+
+ public function switchToNewApiVersion(): void
+ {
+ $this->setApiVersion(ApiVersion::V22);
+ }
+}
+```
+
+### Работа с разными версиями API
+
+```php
+use NotKinopoisk\Services\AbstractService;
+use NotKinopoisk\Enums\ApiVersion;
+
+class VersionedService extends AbstractService
+{
+ public function getDataWithVersion(ApiVersion $version): array
+ {
+ $uri = $this->buildUri('data', $version);
+ return $this->get($uri);
+ }
+
+ public function compareApiVersions(): void
+ {
+ // Получение данных с версии v2.1
+ $dataV21 = $this->getDataWithVersion(ApiVersion::V21);
+
+ // Получение данных с версии v2.2
+ $dataV22 = $this->getDataWithVersion(ApiVersion::V22);
+
+ // Сравнение результатов
+ $this->compareResults($dataV21, $dataV22);
+ }
+}
+```
+
+### Обработка ошибок
+
+```php
+use NotKinopoisk\Services\AbstractService;
+use NotKinopoisk\Exception\ApiException;
+use NotKinopoisk\Exception\RateLimitException;
+
+class ErrorHandlingService extends AbstractService
+{
+ public function getDataWithErrorHandling(): array
+ {
+ try {
+ return $this->get('/api/v1/data');
+ } catch (RateLimitException $e) {
+ // Обработка превышения лимитов
+ $this->handleRateLimit($e);
+ throw $e;
+ } catch (ApiException $e) {
+ // Обработка общих ошибок API
+ $this->handleApiError($e);
+ throw $e;
+ }
+ }
+
+ private function handleRateLimit(RateLimitException $e): void
+ {
+ // Логирование и ожидание
+ error_log("Rate limit exceeded: " . $e->getMessage());
+ sleep(60); // Ждем минуту
+ }
+
+ private function handleApiError(ApiException $e): void
+ {
+ // Логирование ошибки
+ error_log("API Error: " . $e->getMessage());
+ }
+}
+```
+
+### Логирование запросов
+
+```php
+use NotKinopoisk\Services\AbstractService;
+
+class LoggingService extends AbstractService
+{
+ public function getWithLogging(string $uri, array $query = []): array
+ {
+ $startTime = microtime(true);
+
+ try {
+ $response = $this->get($uri, $query);
+
+ $duration = microtime(true) - $startTime;
+ $this->logSuccess($uri, $query, $duration);
+
+ return $response;
+ } catch (\Exception $e) {
+ $duration = microtime(true) - $startTime;
+ $this->logError($uri, $query, $duration, $e);
+ throw $e;
+ }
+ }
+
+ private function logSuccess(string $uri, array $query, float $duration): void
+ {
+ error_log(sprintf(
+ "API Success: %s (%.3fs) - Query: %s",
+ $uri,
+ $duration,
+ json_encode($query)
+ ));
+ }
+
+ private function logError(string $uri, array $query, float $duration, \Exception $e): void
+ {
+ error_log(sprintf(
+ "API Error: %s (%.3fs) - Query: %s - Error: %s",
+ $uri,
+ $duration,
+ json_encode($query),
+ $e->getMessage()
+ ));
+ }
+}
+```
+
+### Кэширование запросов
+
+```php
+use NotKinopoisk\Services\AbstractService;
+
+class CachingService extends AbstractService
+{
+ private array $cache = [];
+ private int $cacheTtl = 300; // 5 минут
+
+ public function getWithCache(string $uri, array $query = []): array
+ {
+ $cacheKey = $this->buildCacheKey($uri, $query);
+
+ // Проверяем кэш
+ if (isset($this->cache[$cacheKey]) && $this->isCacheValid($cacheKey)) {
+ return $this->cache[$cacheKey]['data'];
+ }
+
+ // Выполняем запрос
+ $data = $this->get($uri, $query);
+
+ // Сохраняем в кэш
+ $this->cache[$cacheKey] = [
+ 'data' => $data,
+ 'timestamp' => time()
+ ];
+
+ return $data;
+ }
+
+ private function buildCacheKey(string $uri, array $query): string
+ {
+ return md5($uri . json_encode($query));
+ }
+
+ private function isCacheValid(string $cacheKey): bool
+ {
+ $cached = $this->cache[$cacheKey];
+ return (time() - $cached['timestamp']) < $this->cacheTtl;
+ }
+}
+```
+
+### Валидация параметров
+
+```php
+use NotKinopoisk\Services\AbstractService;
+
+class ValidatingService extends AbstractService
+{
+ public function getWithValidation(string $uri, array $query = []): array
+ {
+ $this->validateUri($uri);
+ $this->validateQuery($query);
+
+ return $this->get($uri, $query);
+ }
+
+ private function validateUri(string $uri): void
+ {
+ if (empty($uri)) {
+ throw new \InvalidArgumentException('URI cannot be empty');
+ }
+
+ if (!preg_match('/^[a-zA-Z0-9\/\-_]+$/', $uri)) {
+ throw new \InvalidArgumentException('Invalid URI format');
+ }
+ }
+
+ private function validateQuery(array $query): void
+ {
+ foreach ($query as $key => $value) {
+ if (empty($key)) {
+ throw new \InvalidArgumentException('Query key cannot be empty');
+ }
+
+ if (!is_string($key)) {
+ throw new \InvalidArgumentException('Query key must be string');
+ }
+ }
+ }
+}
+```
+
+## Связанные классы
+
+- `Client` - Основной клиент для работы с API
+- `ApiVersion` - Перечисление версий API
+- `FilmService` - Сервис для работы с фильмами
+- `PersonService` - Сервис для работы с персонами
+- `MediaService` - Сервис для работы с медиа
+- `UserService` - Сервис для работы с пользователями
+
+## Исключения
+
+- `ApiException` - Общие ошибки API
+- `InvalidApiKeyException` - Неверный API ключ
+- `RateLimitException` - Превышение лимитов запросов
+- `ResourceNotFoundException` - Ресурс не найден
+
+## API Endpoints
+
+AbstractService используется как базовый класс для всех сервисов, работающих с Kinopoisk API:
+
+- `/api/v1/*` - API версии 1.0
+- `/api/v2.1/*` - API версии 2.1
+- `/api/v2.2/*` - API версии 2.2
+
+---
+
+**📚 Навигация:** [Главная](../index.md) → [Сервисы](index.md) → AbstractService
diff --git a/docs/dev/notkinopoiskphp/services/film-service.md b/docs/dev/notkinopoiskphp/services/film-service.md
new file mode 100644
index 0000000..6ef5ac7
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/film-service.md
@@ -0,0 +1,434 @@
+---
+tags:
+ - PHP
+ - API
+ - Сервисы
+title: "FilmService - Сервис для работы с фильмами - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по filmservice - сервис для работы с фильмами. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Сервисы, filmservice - сервис для работы с фильмами, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "FilmService - Сервис для работы с фильмами"
+og:description: "Документация по filmservice - сервис для работы с фильмами. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "FilmService - Сервис для работы с фильмами"
+twitter:description: "Документация по filmservice - сервис для работы с фильмами. Часть API wrapper для КиноПоиска."
+---
+
+# FilmService - Сервис для работы с фильмами
+
+Сервис для работы с фильмами в Kinopoisk API.
+
+---
+
+**📚 Навигация:** [Главная](../index.md) → [Сервисы](index.md) → FilmService
+
+**🔗 Связанные классы:**
+
+- [Client](../client.md) - Основной клиент
+- [Film](../models/film.md) - Модель фильма
+- [Staff](../models/staff.md) - Модель съемочной группы
+- [Review](../models/review.md) - Модель отзыва
+- [Fact](../models/fact.md) - Модель факта
+- [Image](../models/image.md) - Модель изображения
+- [Video](../models/video.md) - Модель видео
+- [Award](../models/award.md) - Модель награды
+- [BoxOffice](../models/box-office.md) - Модель кассовых сборов
+- [Episode](../models/episode.md) - Модель эпизода
+- [Season](../models/season.md) - Модель сезона
+- [RelatedFilm](../models/related-film.md) - Модель связанного фильма
+- [FilmSearchResult](../models/film-search-result.md) - Модель результата поиска
+- [KeywordSearchResponse](../responses/keyword-search-response.md) - Ответ поиска
+- [ImageType](../enums/image-type.md) - Типы изображений
+- [ReviewOrder](../enums/review-order.md) - Порядок сортировки отзывов
+- [ReviewType](../enums/review-type.md) - Типы отзывов
+- [FactType](../enums/fact-type.md) - Типы фактов
+- [VideoSite](../enums/video-site.md) - Сайты видео
+- [BoxOfficeType](../enums/box-office-type.md) - Типы кассовых сборов
+- [ContentType](../enums/content-type.md) - Типы контента
+- [FilmOrder](../enums/film-order.md) - Порядок сортировки фильмов
+- [Month](../enums/month.md) - Месяцы
+- [ApiException](../exceptions/api-exception.md) - Базовое исключение API
+- [ResourceNotFoundException](../exceptions/resource-not-found-exception.md) - Ресурс не найден
+- [RateLimitException](../exceptions/rate-limit-exception.md) - Превышение лимита
+
+---
+
+## Описание
+
+Предоставляет полный набор методов для взаимодействия с фильмами через Kinopoisk API. Реализует CRUD операции: Create (поиск), Read (получение данных), Update (не поддерживается), Delete (не поддерживается).
+
+## Основные возможности
+
+- Получение детальной информации о фильмах
+- Поиск фильмов по ключевым словам и фильтрам
+- Получение связанного контента (сезоны, факты, награды, отзывы)
+- Работа с коллекциями фильмов (популярные, топ-250)
+- Получение премьер и фильтров для поиска
+
+## Конструктор
+
+### `__construct(Client $client)`
+
+Инициализирует новый экземпляр сервиса с переданным HTTP-клиентом и устанавливает версию API v2.2 для работы с Kinopoisk Unofficial API.
+
+**Параметры:**
+
+- `$client` (Client) - HTTP-клиент для выполнения запросов к API
+
+**Пример:**
+
+```php
+$client = new Client('your-api-key');
+$service = new FilmService($client);
+```
+
+## Методы
+
+### `getById(int $id): Film`
+
+Получает детальную информацию о фильме по его ID.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма в базе Kinopoisk
+
+**Возвращает:**
+
+- `Film` - Объект с информацией о фильме
+
+**Пример:**
+
+```php
+$film = $filmService->getById(301); // Матрица
+echo $film->getDisplayName();
+```
+
+### `getSeasons(int $id): DefaultResponse`
+
+Получает информацию о сезонах сериала.
+
+**Параметры:**
+
+- `$id` (int) - ID сериала
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с сезонами сериала
+
+### `getFacts(int $id): DefaultResponse`
+
+Получает факты и ошибки о фильме.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с фактами о фильме
+
+### `getDistributions(int $id): DefaultResponse`
+
+Получает информацию о прокате фильма.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с информацией о прокате
+
+### `getBoxOffice(int $id): BudgetResponse`
+
+Получает информацию о кассовых сборах фильма.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `BudgetResponse` - Ответ с информацией о кассовых сборах
+
+### `getAwards(int $id): DefaultResponse`
+
+Получает информацию о наградах фильма.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с информацией о наградах
+
+### `getVideos(int $id): DefaultResponse`
+
+Получает видео контент фильма (трейлеры, клипы).
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с видео контентом
+
+### `getSimilar(int $id): DefaultResponse`
+
+Получает похожие фильмы.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с похожими фильмами
+
+### `getImages(int $id, ImageType $type = ImageType::STILL, int $page = 1): PaginatedResponse`
+
+Получает изображения фильма определенного типа.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+- `$type` (ImageType) - Тип изображений (по умолчанию STILL)
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `PaginatedResponse` - Пагинированный ответ с изображениями
+
+**Пример:**
+
+```php
+// Получение постеров
+$posters = $filmService->getImages(301, ImageType::POSTER);
+
+// Получение кадров из фильма
+$stills = $filmService->getImages(301, ImageType::STILL);
+```
+
+### `getReviews(int $id, int $page = 1, ReviewOrder $order = ReviewOrder::DATE_DESC): ReviewResponse`
+
+Получает отзывы о фильме.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+- `$page` (int) - Номер страницы (по умолчанию 1)
+- `$order` (ReviewOrder) - Порядок сортировки (по умолчанию DATE_DESC)
+
+**Возвращает:**
+
+- `ReviewResponse` - Ответ с отзывами
+
+### `getExternalSources(int $id, int $page = 1): PaginatedResponse`
+
+Получает внешние источники фильма.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `PaginatedResponse` - Пагинированный ответ с внешними источниками
+
+### `getSequelsAndPrequels(int $id): SequelPrequelResponse`
+
+Получает сиквелы и приквелы фильма.
+
+**Параметры:**
+
+- `$id` (int) - ID фильма
+
+**Возвращает:**
+
+- `SequelPrequelResponse` - Ответ с сиквелами и приквелами
+
+### `searchByKeyword(string $keyword, int $page = 1): KeywordSearchResponse`
+
+Поиск фильмов по ключевому слову.
+
+**Параметры:**
+
+- `$keyword` (string) - Ключевое слово для поиска
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `KeywordSearchResponse` - Ответ с результатами поиска
+
+**Пример:**
+
+```php
+$results = $filmService->searchByKeyword('матрица');
+foreach ($results->items as $film) {
+ echo $film->getDisplayName() . "\n";
+}
+```
+
+### `getPremieres(int $year, Month $month): DefaultResponse`
+
+Получает премьеры фильмов в указанном месяце и году.
+
+**Параметры:**
+
+- `$year` (int) - Год
+- `$month` (Month) - Месяц
+
+**Возвращает:**
+
+- `DefaultResponse` - Ответ с премьерами
+
+### `getFilters(): Filters`
+
+Получает доступные фильтры для поиска.
+
+**Возвращает:**
+
+- `Filters` - Объект с доступными фильтрами
+
+### `getPopular(int $page = 1): PaginatedResponse`
+
+Получает популярные фильмы.
+
+**Параметры:**
+
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `PaginatedResponse` - Пагинированный ответ с популярными фильмами
+
+### `getCollections(CollectionType $type = CollectionType::TOP_POPULAR_ALL, int $page = 1): PaginatedResponse`
+
+Получает коллекции фильмов.
+
+**Параметры:**
+
+- `$type` (CollectionType) - Тип коллекции (по умолчанию TOP_POPULAR_ALL)
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `PaginatedResponse` - Пагинированный ответ с коллекцией фильмов
+
+### `getTop250(int $page = 1): PaginatedResponse`
+
+Получает топ-250 фильмов.
+
+**Параметры:**
+
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `PaginatedResponse` - Пагинированный ответ с топ-250 фильмами
+
+### `searchFilmsByFilter(...): PaginatedResponse`
+
+Поиск фильмов с использованием фильтров.
+
+**Параметры:**
+
+- `$country` (array|null) - Массив стран
+- `$genre` (array|null) - Массив жанров
+- `$order` (FilmOrder) - Порядок сортировки (по умолчанию RATING)
+- `$type` (ContentType) - Тип контента (по умолчанию ALL)
+- `$ratingFrom` (float) - Минимальный рейтинг (по умолчанию 0)
+- `$ratingTo` (float) - Максимальный рейтинг (по умолчанию 10)
+- `$yearFrom` (int) - Минимальный год (по умолчанию 1000)
+- `$yearTo` (int) - Максимальный год (по умолчанию 3000)
+- `$imdbId` (string|null) - IMDB ID
+- `$keyword` (string|null) - Ключевое слово
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+**Возвращает:**
+
+- `PaginatedResponse` - Пагинированный ответ с результатами поиска
+
+**Пример:**
+
+```php
+// Поиск боевиков из США с рейтингом выше 7
+$results = $filmService->searchFilmsByFilter(
+ country: ['США'],
+ genre: ['боевик'],
+ order: FilmOrder::RATING,
+ type: ContentType::FILM,
+ ratingFrom: 7.0,
+ yearFrom: 2020
+);
+```
+
+## Примеры использования
+
+### Базовое использование
+
+```php
+films;
+
+// Получение информации о фильме
+$film = $filmService->getById(301);
+echo $film->getDisplayName();
+
+// Поиск фильмов
+$results = $filmService->searchByKeyword('матрица');
+foreach ($results->items as $film) {
+ echo $film->getDisplayName() . "\n";
+}
+```
+
+### Работа с изображениями
+
+```php
+// Получение постеров
+$posters = $filmService->getImages(301, ImageType::POSTER);
+
+// Получение кадров из фильма
+$stills = $filmService->getImages(301, ImageType::STILL);
+
+// Получение фан-артов
+$fanArts = $filmService->getImages(301, ImageType::FAN_ART);
+```
+
+### Работа с коллекциями
+
+```php
+// Получение популярных фильмов
+$popular = $filmService->getPopular();
+
+// Получение топ-250 фильмов
+$top250 = $filmService->getTop250();
+
+// Получение коллекций
+$collections = $filmService->getCollections(CollectionType::TOP_POPULAR_MOVIES);
+```
+
+## Связанные классы
+
+- `\NotKinopoisk\Models\Film` - Модель фильма
+- `\NotKinopoisk\Models\FilmCollection` - Коллекция фильмов
+- `\NotKinopoisk\Responses\PaginatedResponse` - Пагинированный ответ
+- `\NotKinopoisk\Responses\KeywordSearchResponse` - Ответ поиска по ключевым словам
+- `\NotKinopoisk\Enums\ImageType` - Типы изображений
+- `\NotKinopoisk\Enums\CollectionType` - Типы коллекций
+- `\NotKinopoisk\Enums\FilmOrder` - Порядок сортировки фильмов
+
+## Информация о пакете
+
+- **Пакет:** NotKinopoisk\Services
+- **Версия:** 1.0.0
+- **Автор:** Maxim Harder
+- **API версия:** v2.2
diff --git a/docs/dev/notkinopoiskphp/services/index.md b/docs/dev/notkinopoiskphp/services/index.md
new file mode 100644
index 0000000..7431bec
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/index.md
@@ -0,0 +1,236 @@
+---
+tags:
+ - PHP
+ - API
+ - Сервисы
+title: "Сервисы - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по сервисы. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Сервисы, сервисы, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "Сервисы"
+og:description: "Документация по сервисы. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "Сервисы"
+twitter:description: "Документация по сервисы. Часть API wrapper для КиноПоиска."
+---
+
+# Сервисы
+
+Сервисы для работы с различными компонентами Kinopoisk API.
+
+---
+
+**📚 Навигация:** [Главная](./index.md) → Сервисы
+
+---
+
+## 📋 Список сервисов
+
+### 🎬 [FilmService](./film-service.md)
+
+Сервис для работы с фильмами, сериалами и связанным контентом.
+
+**Основные возможности:**
+
+- Получение информации о фильмах
+- Поиск фильмов по ключевым словам
+- Получение топ фильмов
+- Работа со съемочной группой
+- Получение отзывов и фактов
+- Работа с медиа контентом
+
+**Связанные модели:**
+
+- [Film](../models/film.md)
+- [Staff](../models/staff.md)
+- [Review](../models/review.md)
+- [Fact](../models/fact.md)
+- [Image](../models/image.md)
+- [Video](../models/video.md)
+
+### 👥 [PersonService](./person-service.md)
+
+Сервис для работы с персонами (актеры, режиссеры, сценаристы).
+
+**Основные возможности:**
+
+- Получение информации о персонах
+- Поиск персон по имени
+- Получение фильмографии
+- Работа с биографией и фактами
+
+**Связанные модели:**
+
+- [Person](../models/person.md)
+- [PersonFilm](../models/person-film.md)
+- [PersonSpouse](../models/person-spouse.md)
+
+### 🎥 [MediaService](./media-service.md)
+
+Сервис для работы с медиа контентом (изображения, видео).
+
+**Основные возможности:**
+
+- Получение изображений фильмов
+- Работа с видео контентом
+- Фильтрация по типам медиа
+
+**Связанные модели:**
+
+- [Image](../models/image.md)
+- [Video](../models/video.md)
+- [ImageType](../enums/image-type.md)
+- [VideoSite](../enums/video-site.md)
+
+### 👤 [UserService](./user-service.md)
+
+Сервис для работы с пользовательскими данными.
+
+**Основные возможности:**
+
+- Получение информации об API ключе
+- Работа с квотами запросов
+- Получение пользовательских голосов
+
+**Связанные модели:**
+
+- [ApiKeyInfo](../models/api-key-info.md)
+- [ApiKeyQouta](../models/api-key-qouta.md)
+- [UserVote](../models/user-vote.md)
+
+## 🔗 Общие компоненты
+
+Все сервисы используют общие компоненты:
+
+### Исключения
+
+- [ApiException](../exceptions/api-exception.md) - Базовое исключение API
+- [InvalidApiKeyException](../exceptions/invalid-api-key-exception.md) - Неверный API ключ
+- [RateLimitException](../exceptions/rate-limit-exception.md) - Превышение лимита запросов
+- [ResourceNotFoundException](../exceptions/resource-not-found-exception.md) - Ресурс не найден
+- [KpValidationException](../exceptions/kp-validation-exception.md) - Ошибка валидации
+
+### Ответы
+
+- [DefaultResponse](../responses/default-response.md) - Базовый ответ
+- [PaginatedResponse](../responses/paginated-response.md) - Пагинированный ответ
+- [KeywordSearchResponse](../responses/keyword-search-response.md) - Ответ поиска
+
+## 🚀 Быстрый старт
+
+```php
+films->getById(301);
+$searchResults = $client->films->searchByKeyword('матрица');
+
+// Работа с персонами
+$person = $client->persons->getById(123);
+$persons = $client->persons->searchByName('Том Круз');
+
+// Работа с медиа
+$images = $client->media->getImages(301);
+$videos = $client->media->getVideos(301);
+
+// Работа с пользователем
+$apiInfo = $client->user->getApiKeyInfo();
+```
+
+## 📖 Примеры использования
+
+### Получение полной информации о фильме
+
+```php
+$filmId = 301;
+
+// Основная информация
+$film = $client->films->getById($filmId);
+
+// Съемочная группа
+$staff = $client->films->getStaff($filmId);
+
+// Отзывы
+$reviews = $client->films->getReviews($filmId);
+
+// Факты
+$facts = $client->films->getFacts($filmId);
+
+// Изображения
+$posters = $client->media->getImages($filmId, ImageType::POSTER);
+$screenshots = $client->media->getImages($filmId, ImageType::SCREENSHOT);
+
+// Видео
+$videos = $client->media->getVideos($filmId);
+```
+
+### Поиск и анализ
+
+```php
+// Поиск фильмов
+$searchResults = $client->films->searchByKeyword('драма');
+
+// Получение топ фильмов
+$topFilms = $client->films->getTop();
+
+// Поиск персон
+$persons = $client->persons->searchByName('Кристофер Нолан');
+
+// Получение фильмографии
+$films = $client->persons->getFilms(123);
+```
+
+## 🔧 Обработка ошибок
+
+```php
+try {
+ $film = $client->films->getById(999999);
+} catch (ResourceNotFoundException $e) {
+ echo "Фильм не найден: {$e->getMessage()}\n";
+} catch (RateLimitException $e) {
+ echo "Превышен лимит запросов\n";
+ // Ждем и повторяем
+ sleep(1);
+} catch (InvalidApiKeyException $e) {
+ echo "Неверный API ключ\n";
+} catch (ApiException $e) {
+ echo "Ошибка API: {$e->getMessage()}\n";
+}
+```
+
+## 📊 Статистика использования
+
+### FilmService
+
+- **Методы:** 15+
+- **Модели:** 10+
+- **Перечисления:** 8+
+
+### PersonService
+
+- **Методы:** 8+
+- **Модели:** 3+
+- **Перечисления:** 2+
+
+### MediaService
+
+- **Методы:** 6+
+- **Модели:** 2+
+- **Перечисления:** 2+
+
+### UserService
+
+- **Методы:** 4+
+- **Модели:** 3+
+- **Перечисления:** 1+
+
+---
+
+**📚 Навигация:** [Главная](./index.md) → Сервисы
diff --git a/docs/dev/notkinopoiskphp/services/media-service.md b/docs/dev/notkinopoiskphp/services/media-service.md
new file mode 100644
index 0000000..78cafb0
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/media-service.md
@@ -0,0 +1,205 @@
+---
+tags:
+ - PHP
+ - API
+ - Сервисы
+title: "MediaService - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по mediaservice. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Сервисы, mediaservice, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "MediaService"
+og:description: "Документация по mediaservice. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "MediaService"
+twitter:description: "Документация по mediaservice. Часть API wrapper для КиноПоиска."
+---
+
+# MediaService
+
+Сервис для работы с медиа контентом в Kinopoisk API.
+
+## Описание
+
+`MediaService` предоставляет методы для получения медиа материалов, связанных с фильмами: новости, статьи, интервью и другие публикации.
+
+### Основные возможности
+
+- Получение медиа постов о фильмах
+- Наследование функциональности от AbstractService
+- Использование API версии v1 по умолчанию
+- Доступ к HTTP-клиенту для выполнения запросов
+
+## Конструктор
+
+```php
+public function __construct(\NotKinopoisk\Client $client, string $apiVersion = 'v1.4')
+```
+
+### Параметры
+
+- `$client` - Экземпляр клиента для выполнения HTTP запросов
+- `$apiVersion` - Версия API (по умолчанию 'v1.4')
+
+## Методы
+
+### getPosts()
+
+Получает список медиа-постов с поддержкой пагинации.
+
+```php
+public function getPosts(int $page = 1): PaginatedResponse
+```
+
+**API Endpoint:** `/api/v1/media_posts`
+
+#### Параметры
+
+- `$page` (int) - Номер страницы для загрузки (начиная с 1, по умолчанию первая страница)
+
+#### Возвращаемое значение
+
+- `PaginatedResponse` - Пагинированный ответ содержащий коллекцию медиа-постов с метаданными навигации
+
+#### Исключения
+
+- `\NotKinopoisk\Exception\ApiException` - При общих ошибках API или проблемах сети
+- `\NotKinopoisk\Exception\InvalidApiKeyException` - Если API ключ недействителен, заблокирован или отсутствует
+- `\NotKinopoisk\Exception\KpValidationException` - При некорректном номере страницы или других параметрах валидации
+- `\NotKinopoisk\Exception\RateLimitException` - При превышении лимитов запросов (дневных или общих)
+- `\NotKinopoisk\Exception\ResourceNotFoundException` - Если запрашиваемая страница или ресурс не найден
+
+#### Пример использования
+
+```php
+// Получение первой страницы медиа-постов
+$posts = $mediaService->getPosts();
+
+foreach ($posts->items as $post) {
+ echo "Заголовок: {$post->title}\n";
+ echo "Описание: {$post->description}\n";
+ echo "URL: {$post->url}\n";
+ echo "Дата публикации: {$post->publishedAt}\n";
+ echo "Изображение: {$post->imageUrl}\n";
+ echo "---\n";
+}
+
+// Пагинация
+if ($posts->hasNextPage()) {
+ $nextPagePosts = $mediaService->getPosts($posts->getNextPage());
+}
+
+// Получение конкретной страницы
+$secondPagePosts = $mediaService->getPosts(2);
+echo "Страница {$secondPagePosts->currentPage} из {$secondPagePosts->totalPages}";
+```
+
+## Полный пример использования
+
+```php
+media;
+
+// Получение медиа постов
+try {
+ $posts = $mediaService->getPosts(1);
+
+ echo "=== Медиа посты ===\n";
+ echo "Всего постов: {$posts->total}\n";
+ echo "Страница {$posts->currentPage} из {$posts->totalPages}\n\n";
+
+ foreach ($posts->items as $post) {
+ echo "📰 {$post->title}\n";
+ echo "📝 {$post->description}\n";
+ echo "🔗 {$post->url}\n";
+ echo "📅 {$post->publishedAt}\n";
+
+ if ($post->imageUrl) {
+ echo "🖼️ {$post->imageUrl}\n";
+ }
+ echo "---\n";
+ }
+
+ // Навигация по страницам
+ if ($posts->hasNextPage()) {
+ echo "Следующая страница: {$posts->getNextPage()}\n";
+ }
+
+ if ($posts->hasPreviousPage()) {
+ echo "Предыдущая страница: {$posts->getPreviousPage()}\n";
+ }
+
+} catch (\NotKinopoisk\Exception\ApiException $e) {
+ echo "Ошибка API: {$e->getMessage()}\n";
+} catch (\NotKinopoisk\Exception\RateLimitException $e) {
+ echo "Превышен лимит запросов\n";
+} catch (\Exception $e) {
+ echo "Ошибка: {$e->getMessage()}\n";
+}
+```
+
+## Навигация по страницам
+
+```php
+// Функция для получения всех медиа постов
+function getAllMediaPosts(MediaService $mediaService): array {
+ $allPosts = [];
+ $page = 1;
+
+ do {
+ try {
+ $posts = $mediaService->getPosts($page);
+ $allPosts = array_merge($allPosts, $posts->items);
+
+ echo "Загружена страница {$page} из {$posts->totalPages}\n";
+
+ $page++;
+
+ } catch (\Exception $e) {
+ echo "Ошибка при загрузке страницы {$page}: {$e->getMessage()}\n";
+ break;
+ }
+
+ } while ($page <= $posts->totalPages);
+
+ return $allPosts;
+}
+
+// Использование
+$allPosts = getAllMediaPosts($mediaService);
+echo "Всего загружено постов: " . count($allPosts) . "\n";
+```
+
+## Фильтрация и поиск
+
+```php
+// Функция для поиска постов по ключевому слову
+function searchMediaPosts(array $posts, string $keyword): array {
+ $keyword = strtolower($keyword);
+
+ return array_filter($posts, function($post) use ($keyword) {
+ return strpos(strtolower($post->title), $keyword) !== false ||
+ strpos(strtolower($post->description), $keyword) !== false;
+ });
+}
+
+// Использование
+$posts = $mediaService->getPosts(1);
+$filteredPosts = searchMediaPosts($posts->items, 'интервью');
+
+echo "Найдено постов с 'интервью': " . count($filteredPosts) . "\n";
+```
+
+## Связанные классы
+
+- [`MediaPost`](../models/media-post.md) - Модель медиа поста
+- [`PaginatedResponse`](../responses/paginated-response.md) - Пагинированный ответ
diff --git a/docs/dev/notkinopoiskphp/services/person-service.md b/docs/dev/notkinopoiskphp/services/person-service.md
new file mode 100644
index 0000000..b98a09e
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/person-service.md
@@ -0,0 +1,208 @@
+---
+tags:
+ - PHP
+ - API
+ - Сервисы
+title: "PersonService - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по personservice. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Сервисы, personservice, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "PersonService"
+og:description: "Документация по personservice. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "PersonService"
+twitter:description: "Документация по personservice. Часть API wrapper для КиноПоиска."
+---
+
+# PersonService
+
+Сервис для работы с персонами в Kinopoisk API.
+
+## Описание
+
+`PersonService` предоставляет методы для получения информации о персонах (актерах, режиссерах, сценаристах и т.д.) из Kinopoisk API. Поддерживает поиск персон и получение детальной информации о конкретной персоне.
+
+### Основные возможности
+
+- Поиск персон по различным критериям
+- Получение детальной информации о персоне
+- Поддержка пагинации результатов поиска
+- Обработка ошибок API
+
+## Конструктор
+
+```php
+public function __construct(\NotKinopoisk\Client $client, string $apiVersion = 'v1.4')
+```
+
+### Параметры
+
+- `$client` - Экземпляр клиента для выполнения HTTP запросов
+- `$apiVersion` - Версия API (по умолчанию 'v1.4')
+
+## Методы
+
+### searchByName()
+
+Поиск персон по имени.
+
+```php
+public function searchByName(string $name, int $page = 1): PaginatedResponse
+```
+
+**API Endpoint:** `/api/v1/persons`
+
+#### Параметры
+
+- `$name` (string) - Имя или часть имени для поиска
+- `$page` (int) - Номер страницы (по умолчанию 1)
+
+#### Возвращаемое значение
+
+- `PaginatedResponse` - Результат поиска персон
+
+#### Исключения
+
+- `\NotKinopoisk\Exception\ApiException` - При ошибках API
+
+#### Пример использования
+
+```php
+$results = $personService->searchByName('Том Круз');
+echo "Найдено персон: {$results->getCount()}\n";
+
+foreach ($results->items as $person) {
+ echo "- {$person->name} (ID: {$person->personId})\n";
+}
+```
+
+### getById()
+
+Получает детальную информацию о персоне по ID.
+
+```php
+public function getById(int $id): Person
+```
+
+**API Endpoint:** `/api/v1/staff/{id}`
+
+#### Параметры
+
+- `$id` (int) - Уникальный идентификатор персоны в Кинопоиске
+
+#### Возвращаемое значение
+
+- `Person` - Объект персоны с полной информацией
+
+#### Исключения
+
+- `\NotKinopoisk\Exception\ResourceNotFoundException` - Если персона с указанным ID не найдена
+- `\NotKinopoisk\Exception\ApiException` - При других ошибках API
+
+#### Пример использования
+
+```php
+$person = $personService->getById(12345);
+echo "Имя: " . $person->getDisplayName();
+echo "Профессия: " . $person->profession;
+echo "Биография: " . $person->biography;
+```
+
+### getFilmStaff()
+
+Получает персонал фильма (актеры, режиссеры и другие участники).
+
+```php
+public function getFilmStaff(int $filmId): MovieStaffResponse
+```
+
+**API Endpoint:** `/api/v1/staff`
+
+#### Параметры
+
+- `$filmId` (int) - Уникальный идентификатор фильма в Кинопоиске
+
+#### Возвращаемое значение
+
+- `MovieStaffResponse` - Массив объектов персонала фильма
+
+#### Исключения
+
+- `\NotKinopoisk\Exception\ApiException` - При общих ошибках API
+- `\NotKinopoisk\Exception\InvalidApiKeyException` - При неверном или недействительном API ключе
+- `\NotKinopoisk\Exception\KpValidationException` - При ошибках валидации
+- `\NotKinopoisk\Exception\RateLimitException` - При превышении лимита запросов
+- `\NotKinopoisk\Exception\ResourceNotFoundException` - При отсутствии фильма с указанным ID
+
+#### Пример использования
+
+```php
+// Получение персонала фильма "Матрица" (ID: 301)
+$staff = $personService->getFilmStaff(301);
+
+echo "Всего участников: " . count($staff) . "\n";
+
+foreach ($staff as $person) {
+ echo "{$person->getDisplayName()} - {$person->professionText}";
+
+ if ($person->description) {
+ echo " ({$person->description})";
+ }
+ echo "\n";
+}
+
+// Фильтрация по типу профессии
+$actors = array_filter($staff, fn($person) => $person->isActor());
+$directors = array_filter($staff, fn($person) => $person->isDirector());
+
+echo "Актеров: " . count($actors) . "\n";
+echo "Режиссеров: " . count($directors) . "\n";
+```
+
+## Полный пример использования
+
+```php
+persons;
+
+// Поиск персон
+$searchResults = $personService->searchByName('Киану Ривз');
+echo "Найдено персон: {$searchResults->getCount()}\n";
+
+// Получение информации о первой найденной персоне
+if (!empty($searchResults->items)) {
+ $firstPerson = $searchResults->items[0];
+ $person = $personService->getById($firstPerson->personId);
+
+ echo "Детальная информация:\n";
+ echo "Имя: " . $person->getDisplayName() . "\n";
+ echo "Профессия: " . $person->profession . "\n";
+ echo "Биография: " . substr($person->biography, 0, 200) . "...\n";
+}
+
+// Получение персонала фильма
+$staff = $personService->getFilmStaff(301); // Матрица
+echo "Персонал фильма 'Матрица':\n";
+
+foreach ($staff as $member) {
+ echo "- {$member->getDisplayName()} ({$member->professionText})\n";
+}
+```
+
+## Связанные классы
+
+- [`Person`](../models/person.md) - Модель персоны
+- [`PersonByNameResult`](../models/person-by-name-result.md) - Результат поиска по имени
+- [`Staff`](../models/staff.md) - Модель участника съемочной группы
+- [`MovieStaffResponse`](../responses/movie-staff-response.md) - Ответ с персоналом фильма
+- [`PaginatedResponse`](../responses/paginated-response.md) - Пагинированный ответ
diff --git a/docs/dev/notkinopoiskphp/services/user-service.md b/docs/dev/notkinopoiskphp/services/user-service.md
new file mode 100644
index 0000000..7d120c6
--- /dev/null
+++ b/docs/dev/notkinopoiskphp/services/user-service.md
@@ -0,0 +1,206 @@
+---
+tags:
+ - PHP
+ - API
+ - Сервисы
+title: "UserService - KinopoiskUnofficialTech PHP Wrapper"
+description: "Документация по userservice. Часть API wrapper для КиноПоиска."
+keywords: "PHP, API, Сервисы, userservice, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "UserService"
+og:description: "Документация по userservice. Часть API wrapper для КиноПоиска."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "UserService"
+twitter:description: "Документация по userservice. Часть API wrapper для КиноПоиска."
+---
+
+# UserService
+
+Сервис для работы с пользовательскими данными в Kinopoisk API.
+
+## Описание
+
+`UserService` предоставляет методы для получения информации о пользователе и его API ключе, включая статистику использования и лимиты запросов.
+
+### Основные возможности
+
+- Получение информации об API ключе
+- Просмотр статистики использования
+- Проверка лимитов и квот
+- Получение оценок пользователя
+
+## Конструктор
+
+```php
+public function __construct(\NotKinopoisk\Client $client, string $apiVersion = 'v1.4')
+```
+
+### Параметры
+
+- `$client` - Экземпляр клиента для выполнения HTTP запросов
+- `$apiVersion` - Версия API (по умолчанию 'v1.4')
+
+## Методы
+
+### getApiKeyInfo()
+
+Получает информацию об API ключе.
+
+```php
+public function getApiKeyInfo(string $apiKey): ApiKeyInfo
+```
+
+**API Endpoint:** `/api/v1/api_keys/{apiKey}`
+
+#### Параметры
+
+- `$apiKey` (string) - API ключ для проверки
+
+#### Возвращаемое значение
+
+- `ApiKeyInfo` - Информация об API ключе
+
+#### Исключения
+
+- `\NotKinopoisk\Exception\InvalidApiKeyException` - Если API ключ неверный
+- `\NotKinopoisk\Exception\ApiException` - При других ошибках API
+
+#### Пример использования
+
+```php
+$keyInfo = $userService->getApiKeyInfo('your-api-key');
+
+echo "Тип аккаунта: {$keyInfo->accountType}\n";
+echo "Использовано запросов: {$keyInfo->getTotalQuotaUsed()}\n";
+echo "Лимит запросов: {$keyInfo->getTotalQuotaValue()}\n";
+echo "Осталось запросов: {$keyInfo->getRemainingQuota()}\n";
+```
+
+### getVotes()
+
+Получает оценки пользователя.
+
+```php
+public function getVotes(int $userId, int $page = 1): PaginatedResponse
+```
+
+**API Endpoint:** `/api/v1/kp_users/{userId}/votes`
+
+#### Параметры
+
+- `$userId` (int) - ID пользователя
+- `$page` (int) - Номер страницы для пагинации (по умолчанию 1)
+
+#### Возвращаемое значение
+
+- `PaginatedResponse` - Пагинированный список оценок пользователя
+
+#### Исключения
+
+- `\NotKinopoisk\Exception\ApiException` - При ошибках API
+- `\NotKinopoisk\Exception\ResourceNotFoundException` - Если пользователь не найден
+
+#### Пример использования
+
+```php
+$votes = $userService->getVotes(12345, 1);
+echo "Всего оценок: {$votes->total}\n";
+
+foreach ($votes->items as $vote) {
+ echo "Фильм: {$vote->filmName}, Оценка: {$vote->rating}\n";
+}
+```
+
+## Полный пример использования
+
+```php
+users;
+
+// Получение информации об API ключе
+try {
+ $keyInfo = $userService->getApiKeyInfo('your-api-key');
+
+ echo "=== Информация об API ключе ===\n";
+ echo "Тип аккаунта: {$keyInfo->accountType}\n";
+ echo "Использовано запросов: {$keyInfo->getTotalQuotaUsed()}\n";
+ echo "Лимит запросов: {$keyInfo->getTotalQuotaValue()}\n";
+ echo "Осталось запросов: {$keyInfo->getRemainingQuota()}\n";
+ echo "Использовано сегодня: {$keyInfo->dailyQuota->used}\n";
+ echo "Осталось сегодня: {$keyInfo->getRemainingDailyQuota()}\n";
+
+} catch (\NotKinopoisk\Exception\InvalidApiKeyException $e) {
+ echo "Ошибка: Неверный API ключ\n";
+} catch (\NotKinopoisk\Exception\ApiException $e) {
+ echo "Ошибка API: {$e->getMessage()}\n";
+}
+
+// Получение оценок пользователя (если известен ID)
+try {
+ $votes = $userService->getVotes(12345, 1);
+
+ echo "\n=== Оценки пользователя ===\n";
+ echo "Всего оценок: {$votes->total}\n";
+ echo "Страница {$votes->currentPage} из {$votes->totalPages}\n\n";
+
+ foreach ($votes->items as $vote) {
+ echo "Фильм: {$vote->filmName}\n";
+ echo "Оценка: {$vote->rating}/10\n";
+ echo "Дата: {$vote->date}\n";
+ echo "---\n";
+ }
+
+} catch (\NotKinopoisk\Exception\ResourceNotFoundException $e) {
+ echo "Пользователь не найден\n";
+} catch (\NotKinopoisk\Exception\ApiException $e) {
+ echo "Ошибка API: {$e->getMessage()}\n";
+}
+```
+
+## Мониторинг использования API
+
+```php
+// Функция для проверки лимитов API
+function checkApiLimits(UserService $userService, string $apiKey): void {
+ try {
+ $keyInfo = $userService->getApiKeyInfo($apiKey);
+
+ $remainingTotal = $keyInfo->getRemainingQuota();
+ $remainingDaily = $keyInfo->getRemainingDailyQuota();
+
+ echo "Осталось запросов (всего): {$remainingTotal}\n";
+ echo "Осталось запросов (сегодня): {$remainingDaily}\n";
+
+ if ($remainingDaily < 10) {
+ echo "⚠️ Внимание: Осталось мало запросов на сегодня!\n";
+ }
+
+ if ($remainingTotal < 100) {
+ echo "⚠️ Внимание: Осталось мало запросов в общем!\n";
+ }
+
+ } catch (\Exception $e) {
+ echo "Ошибка при проверке лимитов: {$e->getMessage()}\n";
+ }
+}
+
+// Использование
+checkApiLimits($userService, 'your-api-key');
+```
+
+## Связанные классы
+
+- [`ApiKeyInfo`](../models/api-key-info.md) - Информация об API ключе
+- [`UserVote`](../models/user-vote.md) - Оценка пользователя
+- [`PaginatedResponse`](../responses/paginated-response.md) - Пагинированный ответ
+- [`AccountType`](../enums/account-type.md) - Типы аккаунтов
diff --git a/docs/dev/paid-currencies_rate.md b/docs/dev/paid-currencies_rate.md
index 088e017..6ab06f8 100644
--- a/docs/dev/paid-currencies_rate.md
+++ b/docs/dev/paid-currencies_rate.md
@@ -1,6 +1,23 @@
+---
+tags:
+ - PHP
+ - DLE
+ - Плагин
+ - Платно
+title: "Цены по курсу валют"
+description: "Документация по плагину цены по курсу валют для DLE."
+keywords: "PHP, DLE, Плагин, Платно, цены по курсу валют, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "Цены по курсу валют"
+og:description: "Документация по плагину цены по курсу валют для DLE."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "Цены по курсу валют"
+twitter:description: "Документация по плагину цены по курсу валют для DLE."
+---
+
# Цены по курсу валют
-**Ссылка на разработку**: [ Перейти к разработке](https://devcraft.club/shop/cena-po-kursu-valjut.4/)
+**Ссылка на разработку**: [Перейти к разработке](https://devcraft.club/shop/cena-po-kursu-valjut.4/)
**Версия модификации**: 3.1.1
diff --git a/docs/dev/paid-lastnews.md b/docs/dev/paid-lastnews.md
index a550b63..4d2645b 100644
--- a/docs/dev/paid-lastnews.md
+++ b/docs/dev/paid-lastnews.md
@@ -1,6 +1,24 @@
+---
+tags:
+ - PHP
+ - DLE
+ - Плагин
+ - Платно
+ - Не поддерживается
+title: "LastNews списком аля seasonvar"
+description: "Документация по плагину lastnews списком аля seasonvar для DLE."
+keywords: "PHP, DLE, Плагин, Платно, lastnews списком аля seasonvar, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "LastNews списком аля seasonvar"
+og:description: "Документация по плагину lastnews списком аля seasonvar для DLE."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "LastNews списком аля seasonvar"
+twitter:description: "Документация по плагину lastnews списком аля seasonvar для DLE."
+---
+
# LastNews списком аля seasonvar
-**Ссылка на разработку**: [ Перейти к разработке](https://devcraft.club/shop/lastnews-spiskom.2/)
+**Ссылка на разработку**: [Перейти к разработке](https://devcraft.club/shop/lastnews-spiskom.2/)
**Версия модификации**: 1.1
@@ -13,23 +31,23 @@
## **Пояснения**
-| Тег | Описание |
-| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| **c_id** | Выбираем нужные ID категорий.**По умолчанию выбраны все**. |
-| **day** | Этот параметр для вывода нескольких блоков.**По умолчанию 1**. |
-| **cache** | Включает и выключает кеш блока.**По умолчанию включён**. Можно выбирать либо yes, либо no. |
-| **limit** | Указывает кол-во выводимых новостей.**По умолчанию 100**. |
-| **order** | Это стандартная функция и работает так-же. Однако меняет порядок новостей в блоке по дате, а не сами даты.**По умолчанию стоит date.** |
-| **sort** | Сортирует новости либо по убыванию, либо по возрастанию. Можно использовать**ТОЛЬКО**DESC и ASC! **По умолчанию стоит DESC**. |
-| **temp** | Указываем имя шаблона для блока. Шаблон должен лежать в папке с темой сайта. Не указывайте окончания tpl!**По умолчанию это lastnews**. |
-| **temp2** | Указываем шаблон списка, что выводится в блоке. Действует так-же, как и с temp.**по умолчанию это lastnews_story**. |
-| **von, bis** | Указываем диапазон даты с какого по какое должно показать новости. von это значение для "от", а bis - " до". Указав эти параметры, нельзя использовать параметр datum. Что к чему - ниже! |
-| **datum** | Указываем определённую дату и выводим новости за сей день! |
-| **Вариации даты** | -**heute**: это сегодняшняя дата, выводит новости, что были добавлены именно сегодня, вне зависимости от даты |
-| | -**gestern**: вчерашняя дата, т.е. новости за вчера |
-| | -**vorgestern**: позавчерашняя дата |
-| | -**daym3**: позапозавчерашняя дата, т.е. от сегодня отсчитываем три дня |
-| | -**daym4**: от сегодня отсчитываем четыре дня |
-| | -**daym5**: от сегодня отсчитываем пять дней |
-| | -**daym6**: от сегодня отсчитываем шесть дней |
-| | -**любая определённая дата**: в формате Y-m-d (год-месяц-день, пр: 2016-07-14) |
+| Тег | Описание |
+|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **c_id** | Выбираем нужные ID категорий. **По умолчанию выбраны все**. |
+| **day** | Этот параметр для вывода нескольких блоков. **По умолчанию 1**. |
+| **cache** | Включает и выключает кеш блока. **По умолчанию включён**. Можно выбирать либо yes, либо no. |
+| **limit** | Указывает кол-во выводимых новостей. **По умолчанию 100**. |
+| **order** | Это стандартная функция и работает так-же. Однако меняет порядок новостей в блоке по дате, а не сами даты. **По умолчанию стоит date.** |
+| **sort** | Сортирует новости либо по убыванию, либо по возрастанию. Можно использовать **ТОЛЬКО** DESC и ASC! **По умолчанию стоит DESC**. |
+| **temp** | Указываем имя шаблона для блока. Шаблон должен лежать в папке с темой сайта. Не указывайте окончания tpl! **По умолчанию это lastnews**. |
+| **temp2** | Указываем шаблон списка, что выводится в блоке. Действует так-же, как и с temp. **по умолчанию это lastnews_story**. |
+| **von, bis** | Указываем диапазон даты с какого по какое должно показать новости. von это значение для "от", а bis - " до". Указав эти параметры, нельзя использовать параметр datum. Что к чему - ниже! |
+| **datum** | Указываем определённую дату и выводим новости за сей день! |
+| **Вариации даты** @span | - **heute**: это сегодняшняя дата, выводит новости, что были добавлены именно сегодня, вне зависимости от даты |
+| | -**gestern**: вчерашняя дата, т.е. новости за вчера |
+| | -**vorgestern**: позавчерашняя дата |
+| | -**daym3**: позапозавчерашняя дата, т.е. от сегодня отсчитываем три дня |
+| | -**daym4**: от сегодня отсчитываем четыре дня |
+| | -**daym5**: от сегодня отсчитываем пять дней |
+| | -**daym6**: от сегодня отсчитываем шесть дней |
+| | -**любая определённая дата**: в формате Y-m-d (год-месяц-день, пр: 2016-07-14) |
diff --git a/docs/dev/paid-seasonvar/.nav.yml b/docs/dev/paid-seasonvar/.nav.yml
new file mode 100644
index 0000000..5eb8bc0
--- /dev/null
+++ b/docs/dev/paid-seasonvar/.nav.yml
@@ -0,0 +1,5 @@
+title: Шаблон SeasonVar
+nav:
+ - Установка: install.md
+ - Automatic Related: related.md
+ - F.A.Q.: faq.md
\ No newline at end of file
diff --git a/docs/dev/paid-seasonvar/faq.md b/docs/dev/paid-seasonvar/faq.md
index 8bf273a..33e67d3 100644
--- a/docs/dev/paid-seasonvar/faq.md
+++ b/docs/dev/paid-seasonvar/faq.md
@@ -1,3 +1,20 @@
+---
+tags:
+ - PHP
+ - DLE
+ - Плагин
+ - Платно
+title: "FAQ - SeasonVar"
+description: "Документация по плагину faq для DLE."
+keywords: "PHP, DLE, Плагин, Платно, faq, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "FAQ"
+og:description: "Документация по плагину faq для DLE."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "FAQ"
+twitter:description: "Документация по плагину faq для DLE."
+---
+
# FAQ
Ответы на часто задаваемые вопросы, которые мне задавали после приобретения
diff --git a/docs/dev/paid-seasonvar/install.md b/docs/dev/paid-seasonvar/install.md
index 901f683..b7ece0a 100644
--- a/docs/dev/paid-seasonvar/install.md
+++ b/docs/dev/paid-seasonvar/install.md
@@ -1,3 +1,20 @@
+---
+tags:
+ - PHP
+ - DLE
+ - Плагин
+ - Платно
+title: "Seasonvar - SeasonVar"
+description: "Документация по плагину seasonvar для DLE."
+keywords: "PHP, DLE, Плагин, Платно, seasonvar, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "Seasonvar"
+og:description: "Документация по плагину seasonvar для DLE."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "Seasonvar"
+twitter:description: "Документация по плагину seasonvar для DLE."
+---
+
# Seasonvar
Адаптивный шаблон для DLE
diff --git a/docs/dev/paid-seasonvar/related.md b/docs/dev/paid-seasonvar/related.md
index 04f53be..6111554 100644
--- a/docs/dev/paid-seasonvar/related.md
+++ b/docs/dev/paid-seasonvar/related.md
@@ -1,3 +1,20 @@
+---
+tags:
+ - PHP
+ - DLE
+ - Плагин
+ - Платно
+title: "AutomaticRelated - SeasonVar"
+description: "Документация по плагину automaticrelated для DLE."
+keywords: "PHP, DLE, Плагин, Платно, automaticrelated, DevCraft, документация"
+author: "Maxim Harder"
+og:title: "AutomaticRelated"
+og:description: "Документация по плагину automaticrelated для DLE."
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "AutomaticRelated"
+twitter:description: "Документация по плагину automaticrelated для DLE."
+---
+
# AutomaticRelated
**Автор**: Gameer
diff --git a/docs/dev/php_intl.md b/docs/dev/php_intl.md
index b2e22d0..af85b51 100644
--- a/docs/dev/php_intl.md
+++ b/docs/dev/php_intl.md
@@ -1,3 +1,8 @@
+---
+tags:
+ - Инструкция
+ - PHP
+---
# Установка PHP intl (php-intl)
Для корректной эксплуатации админки, требуется активировать / установить дополнение PHP intl.
diff --git a/docs/dev/releasestatus.md b/docs/dev/releasestatus.md
index 5966c7b..c77585d 100644
--- a/docs/dev/releasestatus.md
+++ b/docs/dev/releasestatus.md
@@ -1,6 +1,22 @@
+---
+title: "Release Status - DevCraft Документации"
+description: "Документация по модулю Release Status для DLE. Управление статусами релизов."
+keywords: "Release Status, DLE, релизы, статусы, модуль"
+author: "Maxim Harder"
+og:title: "Release Status - модуль статусов релизов"
+og:description: "Документация по модулю Release Status для DLE"
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "Release Status - модуль статусов релизов"
+twitter:description: "Документация по модулю Release Status для DLE"
+tags:
+ - DLE
+ - Плагин
+ - Не поддерживается
+---
+
# ReleaseStatus
-**Ссылка на разработку**: [ Перейти к разработке](https://devcraft.club/downloads/releasestatus.6/)
+**Ссылка на разработку**: [ Перейти к разработке](https://devcraft.club/downloads/releasestatus.6/)
**Версия модификации**: 1.0.0
@@ -8,28 +24,13 @@
- Залить файлы из папки uploads в корень сайта (уделите внимание папке Default в папке templates)
- Запустите файл install.php в корне вашего сайта, а затем удалите
-- В шаблонах откройте файл main.tpl и пропишите до
-
-```html
-
-
-
-```
+- В шаблонах откройте файл main.tpl и добавьте стиль
```html
-
+
```
-- В этом же файле, или любом другом файле шаблона, прописываем это для вывода блока
+- В этом же файле, или любом другом файле шаблона, прописываем это для вывода блока
```html
{include file="engine/modules/releasestatus.php"}
@@ -37,10 +38,9 @@
- На файл engine/data/releasestatus.php выставить права 666
-
**Теги для release_block.tpl**
-- {image}, {image-1}, {image-*} - При условии, что изображения выводятся из короткой или полной новости
+- {image}, {image-1}, {image-\*} - При условии, что изображения выводятся из короткой или полной новости
- {poster} - При условии, если изображение выводится из доп. поля
- {title} - Выводит название в зависимости от вывода, настроенного в настройках
- {type} - Выводит тип релиза, полнометражку или сериал
@@ -62,4 +62,4 @@
-
\ No newline at end of file
+
diff --git a/docs/dev/repost/.nav.yml b/docs/dev/repost/.nav.yml
new file mode 100644
index 0000000..b2b5d3d
--- /dev/null
+++ b/docs/dev/repost/.nav.yml
@@ -0,0 +1,3 @@
+title: "Re: Post - Пересылка новостей"
+nav:
+ - Оглавление: index.md
\ No newline at end of file
diff --git a/docs/dev/repost/index.md b/docs/dev/repost/index.md
index 8f52919..1977587 100644
--- a/docs/dev/repost/index.md
+++ b/docs/dev/repost/index.md
@@ -1,3 +1,10 @@
+---
+title: "DLE Re: Post"
+tags:
+ - PHP
+ - DLE
+ - В разработке
+---
# DLE Re: Post
Этот плагин основан на [Telegram Posting](../telegramposting/install.md). Он позволяет пересылать сообщения в социальные сети. Переработав старый плагин, можно динамически создавать несколько шаблонов и настраивать их под разные контексты. Во время разработки я подумал, что было бы здорово дополнить этот плагин различными дополнениями (социальными сетями). Теоретически, его можно настроить на отправку на различные сайты, а также в социальные сети.
diff --git a/docs/dev/schema.md b/docs/dev/schema.md
index 78afbec..8bf3574 100644
--- a/docs/dev/schema.md
+++ b/docs/dev/schema.md
@@ -1,3 +1,22 @@
+---
+title: "Schema.Org - DevCraft Документации"
+description: "Документация по интеграции Schema.Org разметки в проекты DevCraft."
+keywords: "Schema.Org, разметка, SEO, структурированные данные"
+author: "Maxim Harder"
+og:title: "Schema.Org разметка"
+og:description: "Документация по интеграции Schema.Org разметки"
+og:image: "https://devcraft.club/data/assets/logo_default/devcraftx2.png"
+twitter:title: "Schema.Org разметка"
+twitter:description: "Документация по интеграции Schema.Org разметки"
+tags:
+ - DLE
+ - PHP
+ - Плагин
+ - Schema.org
+ - SEO
+ - Не поддерживается
+---
+
# SCHEMA.ORG
**Видеомикроразметка на DLE**
@@ -7,15 +26,15 @@
Для начала, я советую просмотреть саму структуру построения: ** [Movie - schema.org](http://schema.org/Movie)**. Для себя я выбрал следующие поля:
- **contributor**или **countryOfOrigin**(лучше первое) - Страна
-- **copyrightyear**- Год
-- **genre**- Жанр (если у вас категории являются жанром, то пропускаем)
-- **director**- Режиссёр creator - Сценарист
-- **musicBy**- Композитор
-- **editor**- Монтаж
-- **producer**- Продюсер
-- **provider**- Оператор
-- **translator**- Перевод / озвучание
-- **actor**- Актёры
+- **copyrightyear** - Год
+- **genre** - Жанр (если у вас категории являются жанром, то пропускаем)
+- **director** - Режиссёр creator - Сценарист
+- **musicBy** - Композитор
+- **editor** - Монтаж
+- **producer** - Продюсер
+- **provider** - Оператор
+- **translator** - Перевод / озвучание
+- **actor** - Актёры
!!! warning "Внимание!"
Нужно (!) создать следующие поля со следующими названиями (одно поле с функцией "Использовать при желании (можно оставить поле пуcтым)" и "Использовать значения полей как перекрестные гиперссылки ")!
@@ -43,11 +62,20 @@ UPDATE `dle_post` SET `xfields`=REPLACE(`xfields`,'СтароеНазвание'
```html
```
а в конец
@@ -59,24 +87,35 @@ UPDATE `dle_post` SET `xfields`=REPLACE(`xfields`,'СтароеНазвание'
А тут
```html
-
+
```
я использовал [это](http://shop.sandev.pro/post/19.html). Если вы не можете себе этого позволить или не хотите обновить движок, то меняем на это
```html
-
+
```
**Х** меняем на ID категории, которая предназначена для "взрослых" (к.п. Жанр "Эротика"). А если и это вас не устраивает, то вот:
```html
-
+
```
```html
-[xfgiven_trailer][/xfgiven_trailer]
-[xfgiven_video][/xfgiven_video]
+[xfgiven_trailer][/xfgiven_trailer] [xfgiven_video][/xfgiven_video]
```
- **trailer**- это название поля, куда вводится ссылка на трейлер. Меняем на своё.
@@ -94,13 +133,13 @@ UPDATE `dle_post` SET `xfields`=REPLACE(`xfields`,'СтароеНазвание'
Можно и так сделать, в самом начале документа после
```html
-
+
```
добавляем
```html
-
+
```
Однако, при этом теряется описание ссылки, посему выбирать вам.
@@ -127,13 +166,20 @@ UPDATE `dle_post` SET `xfields`=REPLACE(`xfields`,'СтароеНазвание'
ID с кинопоиска
```html
-
+
```
Постер
```html
-
+
```
Описание
@@ -153,31 +199,46 @@ ID с кинопоиска
чтобы обработать рейтинг (рейтинг в звёзды!), делаем следующее
```html
-
-
- [rating]
Рейтинг:
{rating}
(голосов: {vote-num})
[/rating]
-
+
+
+ [rating]
+
Рейтинг:
+ {rating}
+
(голосов: {vote-num})
+ [/rating]
+
```
сделаем сразу разметку для видеофайла (рекомендуется трейлер). После
```html
-
+
```
```html
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
```
поясню:
@@ -193,21 +254,22 @@ ID с кинопоиска
К тегу бади добавляем начальную структуру, должно выглядеть так
```html
-
+
```
## **Комментарии**
-Комментарии (ваш-сайт.ру/templates/шаблон/comments.tpl)**
+Комментарии (ваш-сайт.ру/templates/шаблон/comments.tpl)\*\*
Этот шаг опционален, не столь важен, но всё же рекомендую.
В начало
```html
-
-
- {rating}
+
+
+ {rating}
+
```
в конец
@@ -226,7 +288,14 @@ ID с кинопоиска
К аватарке добавляем значение image, должно выглядеть где-то так:
```html
-
+
```
сам комментарий так-же оборачиваем:
@@ -238,24 +307,36 @@ ID с кинопоиска
если используете рейтинг "нравится" и "не нравится", то оберните его следующим образом (тестировалось на дле 11)
```html
-