CMS WebSource: api
Актуальная версия CMS: 0.973.
Источник содержит документы, актуальные для указанной версии CMS. Если отдельный документ не изменялся, используется его ближайшая предыдущая версия.
Документы со статусом deprecated описывают устаревший API. Документы со статусом removed описывают удалённый API, который нельзя рекомендовать для нового кода.
Account
Путь: api/classes/account
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: Account
slug: account
doc-id: account
lang: ru
version: v0.973
updated-in: 0.973
section: api
type: classes
status: stable
description: Регистрация, авторизация и завершение пользовательской сессии.
---
# Account
`Account` предоставляет статические методы для основных пользовательских сценариев работы с учётной записью.
Создавать экземпляр класса не нужно.
## Поддерживает
- регистрацию пользователя
- авторизацию по логину или email
- сохранение авторизации между посещениями
- получение основных данных авторизованного пользователя
- завершение пользовательской сессии
- указание email и телефона при регистрации
## Авторизация
### authorization(string $login, string $password, bool $remember = false): array
Авторизует пользователя по логину или email:
```php
$result = Account::authorization('user@example.com', 'Example_123', true);
if (($result['status'] ?? false) === true) {
$user = $result['user'];
}
```
Параметр `$remember` определяет, нужно ли сохранять авторизацию между посещениями.
Метод возвращает массив:
| Поле | Тип | Описание |
|---|---|---|
| `status` | `bool` | Результат авторизации. |
| `error` | `array` | Обнаруженные ошибки. |
| `warning` | `array` | Предупреждения. |
| `remember` | `bool` | Была ли сохранена авторизация. |
| `user` | `array \| null` | Основные данные авторизованного пользователя. |
При успешной авторизации поле `user` содержит:
| Поле | Тип | Описание |
|---|---|---|
| `id` | `int` | Идентификатор пользователя. |
| `login` | `string` | Логин пользователя. |
| `email` | `string` | Email пользователя. |
| `role` | `string` | Роль пользователя. |
## Регистрация
### registration(...): array
Для пользовательской регистрации передавайте именованные аргументы:
```php
$result = Account::registration(login: 'example-user', password: 'Example_123', confirmPassword: 'Example_123', email: 'user@example.com', phone: '+375291234567');
if (($result['status'] ?? false) === true) {
$userId = $result['user-id'];
}
```
Поддерживаемые параметры пользовательской регистрации:
| Параметр | Описание |
|---|---|
| `login` | Логин пользователя. |
| `password` | Пароль. |
| `confirmPassword` | Подтверждение пароля. |
| `email` | Email пользователя. Может быть пустым. |
| `phone` | Телефон пользователя. Может быть пустым. |
Метод возвращает массив:
| Поле | Тип | Описание |
|---|---|---|
| `status` | `bool` | Результат регистрации. |
| `errors` | `array` | Обнаруженные ошибки. |
| `user-id` | `int \| null` | Идентификатор созданного пользователя. |
Именованные аргументы позволяют явно указать нужные данные и не зависят от порядка необязательных параметров метода.
## Завершение авторизации
### logout(): void
Завершает пользовательскую сессию:
```php
Account::logout();
```
Метод ничего не возвращает.
## Важные замечания
- класс используется статически
- успешная авторизация определяется строгой проверкой `status === true`
- значения из `error`, `warning` и `errors` следует преобразовывать в понятные локализованные сообщения
CurrentLanguage
Путь: api/classes/current-language
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: CurrentLanguage
slug: current-language
doc-id: current-language
lang: ru
version: v0.95
section: api
type: classes
status: stable
description: Данные текущего языка и формирование локализованных URL.
introduced-in: 0.95
---
# CurrentLanguage
`CurrentLanguage` предоставляет данные текущего языка сайта и формирует внутренние URL с языковым префиксом.
`CurrentLanguage` является статическим классом и автоматически доступен при работе CMS. Создавать его объект не нужно.
## Поддерживает
- определение текущего языка по URL
- получение кода и префикса языка
- формирование ссылок для текущего или указанного языка
- добавление и замену query-параметров
- сохранение URL-фрагмента
- получение маршрута без языкового префикса
- работу с сайтами без мультиязычности
## Быстрый старт
```php
$language = CurrentLanguage::code();
$url = CurrentLanguage::url('/catalog');
```
Использование в HTML:
```php
<html lang="<?php echo CurrentLanguage::htmlLang(); ?>">
```
```php
<a href="<?php echo CurrentLanguage::url('/contacts'); ?>">Контакты</a>
```
## Состояние языка
| Метод | Возвращает | Описание |
|---|---|---|
| `isEnabled()` | `bool` | Включена ли мультиязычность. |
| `isResolved()` | `bool` | Определён ли текущий язык. |
| `get()` | `?array` | Полные данные текущего языка. |
| `code()` | `?string` | Код текущего языка. |
| `prefix()` | `?string` | Префикс текущего языка в URL. |
| `defaultPrefix()` | `string` | Префикс языка по умолчанию. |
| `htmlLang()` | `string` | Безопасное значение для атрибута `lang`. |
### Данные языка
`get()` возвращает массив настроек текущего языка:
```php
$language = CurrentLanguage::get();
```
Массив может содержать:
| Ключ | Описание |
|---|---|
| `code` | Код языка. |
| `label` | Отображаемое название. |
| `prefix` | Префикс в URL. |
| `default` | Язык используется по умолчанию. |
| `active` | Язык доступен на сайте. |
| `order` | Порядок языка в настройках. |
Если язык не определён, `get()`, `code()` и `prefix()` возвращают `null`.
## Код и префикс
Код языка и URL-префикс являются разными настройками:
```php
$code = CurrentLanguage::code();
$prefix = CurrentLanguage::prefix();
```
Например:
```text
code -> ru
prefix -> ru
```
Обычно значения совпадают, но полагаться на это не следует.
Для HTML используйте `htmlLang()`. Для формирования ссылки текущего языка используйте `url()`, а для указанного языка — `urlFor()`.
## Локализованные URL
### url(string $url = '/', array $query = []): string
Формирует внутренний URL для текущего языка:
```php
$url = CurrentLanguage::url('/developer');
```
При включённой мультиязычности результат может выглядеть так:
```text
/ru/developer
```
При отключённой мультиязычности языковой префикс не добавляется:
```text
/developer
```
### urlFor(string $languageCode, string $url = '/', array $query = []): ?string
Формирует внутренний URL для указанного языка:
```php
$url = CurrentLanguage::urlFor('en', '/developer');
```
При включённой мультиязычности результат может выглядеть так:
```text
/en/developer
```
Первым параметром передаётся код языка, а не его URL-префикс.
Если язык не существует или неактивен, метод возвращает `null`:
```php
$url = CurrentLanguage::urlFor('unknown', '/developer');
if ($url === null) {
// Ссылка для этого языка недоступна.
}
```
Query-параметры передаются третьим аргументом:
```php
$url = CurrentLanguage::urlFor('en', '/catalog', ['page' => 2]);
```
Если мультиязычность отключена, URL без префикса возвращается только для языка сайта по умолчанию.
### Замена существующего префикса
Если путь уже начинается с префикса активного языка, он заменяется текущим:
```php
$url = CurrentLanguage::url('/en/developer');
```
Для русского языка результат:
```text
/ru/developer
```
Это позволяет переключать язык без накопления префиксов.
## Query-параметры
Второй аргумент добавляет или заменяет query-параметры:
```php
$url = CurrentLanguage::url(
'/catalog?page=1',
[
'page' => 2,
'filter' => 'new',
]
);
```
Результат:
```text
/ru/catalog?page=2&filter=new
```
Параметры кодируются по правилам RFC 3986.
## URL-фрагменты
Фрагмент сохраняется:
```php
$url = CurrentLanguage::url('/developer#examples');
```
Результат:
```text
/ru/developer#examples
```
Ссылки, начинающиеся с `#`, возвращаются без изменений:
```php
$url = CurrentLanguage::url('#examples');
```
## Внешние ссылки
Абсолютные и служебные ссылки возвращаются без изменений:
```php
$external = CurrentLanguage::url('https://example.com/page');
$email = CurrentLanguage::url('mailto:info@example.com');
$phone = CurrentLanguage::url('tel:+375000000000');
```
Ссылки, начинающиеся с `//`, также не изменяются.
## Маршрут без языка
При включённой мультиязычности методы маршрута исключают первый языковой сегмент.
Для URL:
```text
/ru/developer/api/classes
```
результат будет следующим:
```php
$path = CurrentLanguage::routePath();
$segments = CurrentLanguage::routeSegments();
$section = CurrentLanguage::routeSegment(0);
```
```text
routePath() -> developer/api/classes
routeSegment(0) -> developer
```
### Методы маршрута
| Метод | Возвращает | Описание |
|---|---|---|
| `routePath()` | `string` | Маршрут без языкового префикса. |
| `routeSegments()` | `array` | Все сегменты маршрута. |
| `routeSegment($index)` | `?string` | Сегмент по индексу или `null`. |
Если мультиязычность отключена, методы возвращают путь текущего запроса без дополнительного удаления первого сегмента.
## Ограничения и замечания
- `url()` предназначен для внутренних ссылок сайта
- сегменты `.` и `..` считаются недопустимыми
- неизвестный языковой префикс не удаляется как активный язык
- при неразрешённом языке `url()` использует префикс языка по умолчанию
- `urlFor()` принимает код активного языка, а не URL-префикс
- для неизвестного или неактивного языка `urlFor()` возвращает `null`
CurrentTheme
Путь: api/classes/current-theme
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: CurrentTheme
slug: current-theme
doc-id: current-theme
lang: ru
version: v0.97
updated-in: 0.97
section: api
type: classes
status: stable
introduced-in: 0.95
description: Доступ к активной теме, её файлам, ресурсам и настройкам.
---
# CurrentTheme
`CurrentTheme` является статическим классом для работы с активной темой сайта. Он автоматически доступен в файлах темы.
## Поддерживает
- получение данных активной темы
- получение публичного и файлового пути темы
- безопасный поиск файлов и каталогов внутри темы
- формирование URL ресурсов с версией темы
- получение файлов шаблонов и вложенных общих частей
- автоматическое подключение CSS и JavaScript
- получение значений настроек темы
## Быстрый старт
```php
<?php include CurrentTheme::header(); ?>
<img src="<?php echo CurrentTheme::assetUrl('images', 'logo.svg'); ?>" alt="Логотип">
<?php include CurrentTheme::footer(); ?>
```
Для получения настройки темы используйте `data()`:
```php
$logo = CurrentTheme::data('logo');
if ($logo !== '') {
echo '<img src="' . $logo . '" alt="Логотип">';
}
```
## Данные темы
### directory(): string
Возвращает название папки активной темы.
```php
$directory = CurrentTheme::directory();
```
Пример результата:
```text
cmswebsource
```
### name(): string
Возвращает название темы из `theme-info.json`.
```php
$name = CurrentTheme::name();
```
### data(string $key, mixed $default = ''): mixed
Возвращает значение настройки активной темы.
```php
$logo = CurrentTheme::data('logo');
$legal = CurrentTheme::data('legal');
```
Если ключ отсутствует, возвращается значение второго параметра:
```php
$phone = CurrentTheme::data('phone', 'Телефон не указан');
```
Значения формируются из настроек темы и значений, сохранённых для активной темы в базе данных.
## Пути темы
### path(): string
Возвращает абсолютный путь к папке активной темы в файловой системе.
```php
$themePath = CurrentTheme::path();
```
Используйте `path()` только когда нужен путь к самой папке темы. Для поиска вложенных файлов безопаснее применять `filePath()` или `directoryPath()`.
### url(): string
Возвращает публичный URL папки активной темы с завершающим `/`.
```php
$themeUrl = CurrentTheme::url();
```
Пример результата:
```text
/resource/themes/cmswebsource/
```
## Файлы и каталоги
### directoryPath(string ...$segments): string
Возвращает абсолютный путь к существующему читаемому каталогу внутри активной темы.
Каждую часть пути передавайте отдельным аргументом:
```php
$docsPath = CurrentTheme::directoryPath(
'docs',
'ru',
'api',
'classes'
);
```
Если каталог не существует, недоступен для чтения или находится за пределами темы, метод возвращает пустую строку.
### filePath(string ...$segments): string
Возвращает абсолютный путь к существующему читаемому файлу внутри активной темы.
```php
$file = CurrentTheme::filePath(
'includes',
'sidebar.php'
);
if ($file !== '') {
include $file;
}
```
Если файл не найден или находится за пределами темы, метод возвращает пустую строку.
### hasFile(string ...$segments): bool
Проверяет наличие доступного файла внутри активной темы.
```php
if (CurrentTheme::hasFile('template', '404.php')) {
// Файл существует и доступен для чтения.
}
```
### templatePath(string $template, ?string $type = null): string
Возвращает путь к файлу шаблона.
Для общего шаблона:
```php
$template = CurrentTheme::templatePath('404');
```
Будет проверен файл:
```text
template/404.php
```
Для шаблона страницы или записи передайте тип:
```php
$pageTemplate = CurrentTheme::templatePath('developer', 'page');
$postTemplate = CurrentTheme::templatePath('news', 'post');
```
Поддерживаемые типы:
- `page`
- `post`
Если имя шаблона содержит недопустимые символы, тип не поддерживается или файл отсутствует, метод возвращает пустую строку.
## Общие части шаблона
### part(string ...$segments): string
Возвращает путь к PHP-файлу внутри папки `includes`.
Для файла в корне папки передайте его имя без расширения:
```php
$sidebar = CurrentTheme::part('sidebar');
```
Будет проверен файл:
```text
includes/sidebar.php
```
Для вложенного файла передавайте каждую часть пути отдельным аргументом:
```php
$navigation = CurrentTheme::part(
'navigation',
'sidebar'
);
```
Будет проверен файл:
```text
includes/navigation/sidebar.php
```
Расширение `.php` автоматически добавляется к последнему сегменту. Если аргументы не переданы, содержат недопустимые символы или файл отсутствует, метод возвращает пустую строку.
### header(): string
Возвращает путь к файлу `includes/header.php`.
```php
include CurrentTheme::header();
```
### footer(): string
Возвращает путь к файлу `includes/footer.php`.
```php
include CurrentTheme::footer();
```
## Ресурсы темы
### assetUrl(string ...$segments): string
Возвращает публичный URL существующего файла внутри папки `assets`.
```php
$logoUrl = CurrentTheme::assetUrl(
'images',
'logo.svg'
);
```
Пример результата:
```text
/resource/themes/cmswebsource/assets/images/logo.svg?v=0.1.0
```
К URL автоматически добавляется версия темы из `theme-info.json`.
Если файл отсутствует, метод возвращает пустую строку.
Не добавляйте `assets` в аргументы: метод подставляет эту папку самостоятельно.
## Подключение CSS
### getCSS(): string
Возвращает HTML-теги `<link>` для стилей активной темы.
Метод не выводит результат самостоятельно:
```php
echo CurrentTheme::getCSS();
```
Автоматически подключаются существующие файлы:
- `assets/css/style.css`
- `assets/css/index.css` для главной страницы
- `assets/css/{template}.css` для текущего шаблона
- дополнительные CSS-файлы, привязанные к текущему шаблону
Дополнительный файл должен начинаться с `!` и содержать имя шаблона между `!`.
Например, для шаблона `developer` будет подключён файл:
```text
assets/css/!developer!print.css
```
Отсутствующие файлы пропускаются.
## Подключение JavaScript
### getJS(?array $modules = null): string
Возвращает HTML-теги `<script>` для JavaScript активной темы и данные окружения для браузера.
Метод не выводит результат самостоятельно:
```php
echo CurrentTheme::getJS();
```
Автоматически подключаются существующие файлы:
- `assets/js/script.js`
- `assets/js/modules/script.js`
- `assets/js/{template}.js`
- `assets/js/modules/{template}.js`
- дополнительные JavaScript-файлы, привязанные к текущему шаблону
Для подключения JavaScript-модулей ядра передайте их названия массивом:
```php
echo CurrentTheme::getJS([
'gallery',
'editor',
]);
```
Название модуля должно содержать только латинские буквы, цифры, `_` или `-`. Несуществующие модули пропускаются.
## Данные JavaScript
`getJS()` создаёт неизменяемый объект `window.wsSite`.
Он содержит:
| Свойство | Описание |
|---|---|
| `siteUrl` | Публичный адрес сайта. |
| `currentUrl` | URL текущего запроса. |
| `coreUrl` | Публичный URL ядра CMS. |
| `themeUrl` | Публичный URL активной темы. |
| `themeAssetsUrl` | Публичный URL папки `assets`. |
| `lang` | Текущий язык страницы. |
| `page.type` | Тип текущей страницы. |
| `page.template` | Название текущего шаблона. |
| `page.url` | Полный URL текущей страницы. |
| `page.postType` | Тип текущей записи. |
Пример использования в ES-модуле:
```js
const moduleUrl = `${window.wsSite.coreUrl}/modules/example/assets/js/example.js`;
console.log(window.wsSite.page.template);
```
## Состояние темы
### isValid(): bool
Возвращает `true`, если активная тема прошла проверку.
```php
if (!CurrentTheme::isValid()) {
return;
}
```
При проверке учитываются папка темы, `theme-info.json` и основной файл `index.php`.
### status(): string
Возвращает строковый статус проверки активной темы.
```php
$status = CurrentTheme::status();
```
Для корректной темы метод возвращает:
```text
valid
```
Другие значения описывают причину, по которой тема не прошла проверку.
## Важные замечания
- используйте `assetUrl()` для URL файлов из папки `assets`
- используйте `filePath()` и `directoryPath()` для безопасной работы с файлами
- `getCSS()` и `getJS()` возвращают HTML строкой и требуют `echo`
- `header()`, `footer()`, `part()` и `templatePath()` возвращают файловые пути
- методы поиска файлов возвращают пустую строку, если путь недоступен
- `data()` не изменяет настройки темы и используется только для их чтения
CurrentUser
Путь: api/classes/current-url
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: CurrentUser
slug: current-user
doc-id: current-user
lang: ru
version: v0.971
updated-in: 0.971
section: api
type: classes
status: stable
introduced-in: 0.95
description: Данные текущего авторизованного пользователя.
---
# CurrentUser
`CurrentUser` является статическим классом для получения данных пользователя текущего запроса. Класс автоматически доступен после запуска CMS.
## Поддерживает
- проверку наличия авторизованного пользователя
- получение основных данных пользователя
- получение номера телефона
- получение пользовательских метаданных
- указание значения по умолчанию
## Проверка авторизации
### isAuthenticated(): bool
Возвращает `true`, если в текущем запросе доступен авторизованный пользователь:
```php
if (!CurrentUser::isAuthenticated()) {
return;
}
```
Для неавторизованного посетителя возвращается `false`.
## Данные пользователя
### get(string $name, mixed $default = null): mixed
Возвращает значение поля текущего пользователя:
```php
$email = CurrentUser::get('email');
$phone = CurrentUser::get('phone', '');
```
Вторым аргументом можно передать значение по умолчанию:
```php
$avatar = CurrentUser::get(
'avatar',
'/assets/images/avatar.svg'
);
```
Если пользователь не авторизован, поле отсутствует или содержит `null`, метод возвращает значение по умолчанию.
### Основные поля
| Поле | Тип | Описание |
|---|---|---|
| `id` | `int` | Идентификатор пользователя. |
| `login` | `string` | Логин пользователя. |
| `email` | `string` | Адрес электронной почты. |
| `phone` | `string` | Номер телефона. Может быть пустым. |
| `register` | `string` | Дата регистрации. |
| `role` | `string` | Роль пользователя. |
| `avatar` | `string` | Путь к изображению аватара. |
## Метаданные пользователя
### meta(string $name, mixed $default = null): mixed
Возвращает значение пользовательского метаполя:
```php
$displayName = CurrentUser::meta('display_name');
$city = CurrentUser::meta('city');
```
Для отсутствующего метаполя можно указать значение по умолчанию:
```php
$displayName = CurrentUser::meta(
'display_name',
CurrentUser::get('login', 'Пользователь')
);
```
## Важные замечания
- перед получением данных проверяйте `isAuthenticated()`
- набор метаданных зависит от настроек пользователя и установленных модулей
- класс предоставляет данные только пользователя текущего запроса
- изменение полученного значения не сохраняет его в CMS
- создавать экземпляр `CurrentUser` не нужно
CurrentUser
Путь: api/classes/current-user
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: CurrentUser
slug: current-user
doc-id: current-user
lang: ru
version: v0.971
updated-in: 0.971
section: api
type: classes
status: stable
introduced-in: 0.95
description: Данные текущего авторизованного пользователя.
---
# CurrentUser
`CurrentUser` является статическим классом для получения данных пользователя текущего запроса. Класс автоматически доступен после запуска CMS.
## Поддерживает
- проверку наличия авторизованного пользователя
- получение основных данных пользователя
- получение номера телефона
- получение пользовательских метаданных
- указание значения по умолчанию
## Проверка авторизации
### isAuthenticated(): bool
Возвращает `true`, если в текущем запросе доступен авторизованный пользователь:
```php
if (!CurrentUser::isAuthenticated()) {
return;
}
```
Для неавторизованного посетителя возвращается `false`.
## Данные пользователя
### get(string $name, mixed $default = null): mixed
Возвращает значение поля текущего пользователя:
```php
$email = CurrentUser::get('email');
$phone = CurrentUser::get('phone', '');
```
Вторым аргументом можно передать значение по умолчанию:
```php
$avatar = CurrentUser::get(
'avatar',
'/assets/images/avatar.svg'
);
```
Если пользователь не авторизован, поле отсутствует или содержит `null`, метод возвращает значение по умолчанию.
### Основные поля
| Поле | Тип | Описание |
|---|---|---|
| `id` | `int` | Идентификатор пользователя. |
| `login` | `string` | Логин пользователя. |
| `email` | `string` | Адрес электронной почты. |
| `phone` | `string` | Номер телефона. Может быть пустым. |
| `register` | `string` | Дата регистрации. |
| `role` | `string` | Роль пользователя. |
| `avatar` | `string` | Путь к изображению аватара. |
## Метаданные пользователя
### meta(string $name, mixed $default = null): mixed
Возвращает значение пользовательского метаполя:
```php
$displayName = CurrentUser::meta('display_name');
$city = CurrentUser::meta('city');
```
Для отсутствующего метаполя можно указать значение по умолчанию:
```php
$displayName = CurrentUser::meta(
'display_name',
CurrentUser::get('login', 'Пользователь')
);
```
## Важные замечания
- перед получением данных проверяйте `isAuthenticated()`
- набор метаданных зависит от настроек пользователя и установленных модулей
- класс предоставляет данные только пользователя текущего запроса
- изменение полученного значения не сохраняет его в CMS
- создавать экземпляр `CurrentUser` не нужно
Form
Путь: api/classes/form
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: Form
slug: form
doc-id: form
lang: ru
version: v0.971
updated-in: 0.971
section: api
type: classes
status: stable
description: Проверка логинов, паролей, email-адресов и телефонных номеров.
introduced-in: 0.7
---
# Form
`Form` предоставляет статические методы для проверки значений, полученных из форм.
Создавать экземпляр класса не нужно.
## Поддерживает
- проверку допустимых символов и длины логина
- проверку пароля и его подтверждения
- проверку телефонного номера в международном формате
- проверку формата email-адреса
## Быстрый старт
```php
$result = Form::isEmail('user@example.com');
if ($result !== true) {
echo $result;
}
```
Методы проверки логина, пароля и email возвращают `true`, если значение прошло проверку. При ошибке возвращается локализованное сообщение.
## Проверка логина
### isLogin($login, $min = 3, $max = 99): true|string
Проверяет допустимые символы и длину логина:
```php
$result = Form::isLogin('example-user');
if ($result !== true) {
echo $result;
}
```
Допускаются:
- буквы
- цифры
- символы `-`, `_`, `$`, `.`, `?` и `%`
- один символ `+` в начале логина
По умолчанию длина логина должна составлять от `3` до `99` символов включительно.
Другие ограничения можно передать вторым и третьим аргументами:
```php
$result = Form::isLogin('example-user', 5, 30);
```
Если нарушено несколько правил, метод может вернуть объединённый текст нескольких ошибок.
## Проверка пароля
### isPassword($password, $passwordConfirm = false, $min = 4, $max = 99): true|string
Проверяет допустимые символы и длину пароля:
```php
$result = Form::isPassword('Example_123');
if ($result !== true) {
echo $result;
}
```
Допускаются латинские и кириллические буквы, цифры и символы `-`, `_`, `@`, `$`, `.`, `?`, `%`.
По умолчанию длина пароля должна составлять от `4` до `99` символов включительно.
Для проверки подтверждения передайте второй пароль:
```php
$result = Form::isPassword(
'Example_123',
'Example_123'
);
```
Сравнение выполняется только при передаче непустого значения `$passwordConfirm`.
Другие ограничения длины передаются третьим и четвёртым аргументами:
```php
$result = Form::isPassword('Example_123', false, 8, 40);
```
## Проверка email
### isEmail($email): true|string
Проверяет базовый формат email-адреса:
```php
$result = Form::isEmail('user@example.com');
if ($result !== true) {
echo $result;
}
```
Корректный адрес должен содержать имя, символ `@` и доменную часть с точкой. Пробелы и дополнительные символы `@` не допускаются.
При успешной проверке метод возвращает `true`, иначе возвращается локализованное сообщение об ошибке.
## Проверка телефона
### isPhone($phone, $min = 3, $max = 15): string|false
Проверяет номер телефона в международном формате:
```php
$phone = Form::isPhone('+375291234567');
if ($phone !== false) {
echo $phone;
}
```
Корректный номер:
- начинается с символа `+`
- содержит после `+` только цифры
- не начинается с цифры `0`
- не содержит пробелы, скобки или дефисы
При успешной проверке метод возвращает переданный номер с символом `+`.
По умолчанию номер должен содержать от `3` до `15` цифр после `+`. Другие ограничения можно передать дополнительными аргументами:
```php
$phone = Form::isPhone('+375291234567', 10, 12);
```
Если формат или длина номера не соответствуют требованиям, метод возвращает `false`.
## Важные замечания
- класс используется статически
- результат `isLogin()`, `isPassword()` и `isEmail()` нужно сравнивать с `true`
- `isPhone()` возвращает проверенный номер с символом `+` или `false`
Menu
Путь: api/classes/menu
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: Menu
slug: menu
doc-id: menu
lang: ru
version: v0.97
section: api
type: classes
status: stable
introduced-in: 0.85
updated-in: 0.961
description: Класс для вывода HTML-меню, созданного через административную панель.
---
# Menu
`Menu` формирует и выводит HTML-меню, созданное через административную панель.
## Поддерживает
- вывод корневых и вложенных пунктов
- выделение пунктов по ключу
- исключение корневых и вложенных пунктов
- вывод ссылок, текстовых пунктов и иконок
- повторный вывод меню с уникальным HTML-идентификатором
- автоматическое преобразование старого формата меню
## Быстрый старт
```php
$menu = new Menu('1');
$menu->insertMenu();
```
Первым параметром передаётся идентификатор меню.
`insertMenu()` не возвращает строку, а сразу выводит готовый HTML.
## Выделение пунктов
Ключи выделенных пунктов передаются вторым параметром:
```php
$menu = new Menu(
'1',
['developer']
);
$menu->insertMenu();
```
Если поле `key` пункта содержит `developer`, к его классу добавляется `selected`.
Для выделения пункта по текущему шаблону можно использовать `PageData`:
```php
$menu = new Menu(
'1',
[PageData::getTemplate()]
);
$menu->insertMenu();
```
## Исключение пунктов
Ключи исключаемых пунктов передаются третьим параметром:
```php
$menu = new Menu(
'1',
[],
[
'profile',
'logout',
]
);
$menu->insertMenu();
```
Каждый корневой или вложенный пункт проверяется по собственному полю `key`.
Если исключён родительский пункт, его дочерние пункты также не попадают в HTML.
## Активные пункты
Пункт выводится только тогда, когда его поле `active` содержит строку `true`.
Булево значение `true` не считается эквивалентным строке:
```text
true
```
Скрытые пункты и их дочерние элементы в HTML не попадают.
## Структура HTML
Корневой контейнер получает класс `ws-menu` и уникальный идентификатор:
```html
<div class="ws-menu" id="ws-menu-1-1">
<div class="item selected">
<a href="/developer">Документация</a>
</div>
</div>
```
Вложенные пункты помещаются в контейнер `sub-menu`:
```html
<div class="sub-menu child-1">
<div class="item">
<a href="/developer/api">API</a>
</div>
</div>
```
Если поле `link` заполнено, название выводится внутри ссылки. Иначе используется элемент `p`.
При наличии `icon` перед названием добавляется изображение:
```html
<img src="/assets/images/icon.svg" alt="Документация">
```
## Повторный вывод
Один объект можно вывести несколько раз:
```php
$menu = new Menu('1');
$menu->insertMenu();
$menu->insertMenu();
```
Каждый вызов увеличивает счётчик в идентификаторе:
```text
ws-menu-1-1
ws-menu-1-2
```
## Поля пункта меню
| Поле | Описание |
|---|---|
| `name` | Название пункта. |
| `link` | Ссылка. Если пустая, используется элемент `p`. |
| `icon` | URL изображения пункта. |
| `class` | Дополнительный CSS-класс. |
| `key` | Ключ для выделения и исключения. |
| `active` | Строка `true` для отображения пункта. |
| `parent` | Идентификатор родительского пункта. |
| `order` | Сохранённое значение порядка пункта. |
## Публичный API
### __construct(string $id, array $selected = [], array $exceptions = [])
Подготавливает указанное меню к выводу.
```php
$menu = new Menu(
'1',
['developer'],
['hidden-item']
);
```
### insertMenu(): void
Выводит сформированный HTML:
```php
$menu->insertMenu();
```
### legacyToNew(array $array): array
Преобразует старую структуру меню с ключом `parents` в текущий плоский формат.
Конструктор выполняет преобразование автоматически. В новом коде вызывать метод вручную не требуется.
## Важные замечания
- меню должно существовать до создания объекта
- значения `selected` и `exceptions` сопоставляются с полем `key`
- пункт отображается только при строковом значении `active: true`
- `insertMenu()` выводит HTML через `echo`
- значения `name`, `link`, `icon` и `class` попадают в HTML без дополнительного экранирования
- порядок вывода соответствует порядку элементов в сохранённом меню
Page
Путь: api/classes/page
Версия документа: 0.973
Статус: deprecated
Открыть документ
---
title: Page
slug: page
doc-id: page
lang: ru
version: v0.95
section: api
type: classes
status: deprecated
deprecated-in: 0.95
description: Устаревший класс для получения страниц CMS по идентификатору или URL.
---
# Page
`Page` является устаревшим классом. Он сохранён в CMS, но не должен использоваться в новом коде.
Единой полной замены у класса нет:
- для получения опубликованной страницы по URL используйте `PageManager`
- для данных текущей страницы используйте `PageData`
## Получение страницы по URL
Вместо `Page::getPageByUrl()` используйте `PageManager`:
```php
$page = (new PageManager())->getPublishedByUrl('contacts');
if ($page === null) {
return;
}
$title = $page['title'];
$content = $page['content'];
```
`PageManager` возвращает только опубликованные страницы и может дополнительно проверить поддержку свободной ссылки.
## Данные текущей страницы
Если CMS уже определила страницу текущего запроса, используйте `PageData`:
```php
$title = PageData::getTitle();
$content = PageData::getContent();
$pageId = PageData::getId();
```
`PageData` не выполняет поиск произвольной страницы. Он предоставляет данные текущего запроса.
## Сохранённый API
Методы класса остаются доступными для поддержки старого кода.
### getPage($id): array|false
Получает страницу по идентификатору.
Если страница найдена, метод преобразует её метаданные:
- исходная структура сохраняется в `post_data`
- в `meta` записываются значения метаполей
Если страница не найдена, возвращается `false`.
### getPageByUrl($url, $publish = false, $freeLink = false): array|false
Получает страницу по URL.
| Параметр | Тип | Описание |
|---|---|---|
| `$url` | `string` | URL страницы. |
| `$publish` | `bool` | Ограничить поиск опубликованными страницами. |
| `$freeLink` | `bool` | Требовать непустое значение `free_link`. |
Метод возвращает поле `meta` без дополнительного преобразования.
## Ограничения
- класс использует устаревший объект базы данных
- параметры подставляются в SQL-запрос без подготовленных выражений
- не передавайте методам данные, полученные от пользователя
- ветка `getPageByUrl()` с `$publish = false` может сформировать некорректный SQL-запрос
- `PageManager` не заменяет получение страницы по идентификатору
- для нового кода используйте актуальные классы CMS
PageData
Путь: api/classes/page-data
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: PageData
slug: page-data
doc-id: page-data
lang: ru
version: v0.97
updated-in: 0.97
section: api
type: classes
status: stable
description: Данные страницы или записи, определённой CMS для текущего запроса.
introduced-in: 0.95
---
# PageData
`PageData` предоставляет данные страницы или записи текущего HTTP-запроса.
CMS автоматически предоставляет данные текущего запроса через `PageData`. Создавать экземпляр класса вручную не нужно.
## Поддерживает
- получение содержимого текущей страницы или записи
- получение данных маршрута и шаблона
- работу с обычными и составными метаполями
- получение категорий и связанных записей
- формирование SEO-тегов, Open Graph, Twitter Cards и Schema.org
- получение комментариев
- получение языковых вариантов страниц и записей с формированием hreflang
- временную подмену данных текущего запроса
## Быстрый старт
```php
$title = PageData::getTitle();
$content = PageData::getContent();
$image = PageData::getImage();
```
Получение метаполя:
```php
$subtitle = PageData::getMeta('subtitle');
```
## Основные данные
| Метод | Возвращает | Описание |
|---|---|---|
| `getId()` | `int` | Идентификатор страницы или записи. |
| `getTitle()` | `string` | Заголовок. |
| `getPostName()` | `string` | Название типа записи. |
| `getContent()` | `string` | Основное содержимое. |
| `getImage()` | `string` | Путь к изображению. |
| `getAuthorId()` | `int` | Идентификатор автора. |
| `getCreateDate()` | `string` | Дата создания. |
| `getPublishDate()` | `string` | Дата публикации. |
| `getModifiedDate()` | `string` | Дата последнего изменения. |
| `getViews()` | `int` | Количество просмотров. |
| `getMore()` | `string` | Дополнительное содержимое записи. |
Если значение отсутствует, строковые методы возвращают пустую строку, а числовые методы возвращают `0`.
### getImage(bool $domain = false): string
Без аргумента возвращает сохранённый путь:
```php
$image = PageData::getImage();
```
Для получения полного URL передайте `true`:
```php
$image = PageData::getImage(true);
```
## Данные маршрута
| Метод | Возвращает | Описание |
|---|---|---|
| `getPageKey()` | `?string` | Базовый ключ страницы или типа записи. |
| `getPageUrl()` | `?string` | Оставшаяся часть маршрута после базового ключа. |
| `getPage()` | `?string` | Значение параметра текущей административной страницы или `null`. |
| `getPostTypeId()` | `int` | Идентификатор типа текущей записи или `0`. |
| `getPostType()` | `?string` | Системное имя типа записи. |
| `getPageFullUrl()` | `string` | Полный путь текущей страницы. |
| `getTemplate()` | `string` | Название активного шаблона. |
| `getType()` | `string` | Тип текущего запроса. |
Для URL записи `/ru/news/release-notes` значения могут выглядеть так:
```text
getPageKey() -> news
getPageUrl() -> release-notes
getPostType() -> news
```
### getPageFullUrl(bool $domain = false): string
Возвращает путь с учётом языкового префикса:
```php
$url = PageData::getPageFullUrl();
```
Пример:
```text
/ru/news/release-notes
```
Для получения адреса с доменом передайте `true`:
```php
$url = PageData::getPageFullUrl(true);
```
## Языковые варианты
### getLanguageVersions(): array
Возвращает языковые варианты текущей страницы, записи или главной страницы:
```php
$versions = PageData::getLanguageVersions();
foreach ($versions as $version) {
echo '<a href="' . $version['url'] . '">' . $version['label'] . '</a>';
}
```
Каждый элемент содержит:
| Поле | Тип | Описание |
|---|---|---|
| `code` | `string` | Код языка. |
| `label` | `string` | Отображаемое название языка. |
| `url` | `string` | Локализованный путь страницы. |
| `absolute-url` | `string` | Полный URL с доменом. |
| `current` | `bool` | Является ли язык текущим. |
| `default` | `bool` | Является ли язык языком сайта по умолчанию. |
| `indexable` | `bool` | Разрешена ли индексация языкового варианта. |
| `canonical` | `string` | Сохранённый canonical языкового варианта. |
В результат включаются только активные языки, для которых существует соответствующий вариант содержимого. Для обычных страниц и записей используются только опубликованные варианты.
Для записи языковые варианты определяются по её типу и общему значению `translation_key`.
Для запроса без включённой мультиязычности, обычной страницы или записи без `translation_key` метод возвращает пустой массив. Если существует только один языковой вариант, массив содержит один элемент, но `hreflang` не формируется.
## Метаполя
### getMeta($key, $row = false, $column = false): mixed
Возвращает значение метаполя:
```php
$subtitle = PageData::getMeta('subtitle');
```
Если метаполе содержит составное значение, без дополнительных аргументов возвращается весь массив:
```php
$sections = PageData::getMeta('sections');
```
Для получения отдельной ячейки передайте номер строки и столбца:
```php
$title = PageData::getMeta(
'sections',
0,
0
);
```
Если метаполе или указанная ячейка отсутствует, возвращается пустая строка.
### Данные метаполей
Для методов объекта используйте текущий экземпляр:
```php
$pageData = PageData::current();
$meta = $pageData->getMetaList();
$name = $pageData->getMetaName('subtitle');
$type = $pageData->getMetaType('subtitle');
```
| Метод | Описание |
|---|---|
| `getMetaList()` | Возвращает все значения метаполей. |
| `getMetaName($key)` | Возвращает название метаполя. |
| `getMetaType($key)` | Возвращает тип метаполя. |
## Связанные записи
### getRelations($key)
Возвращает опубликованные записи, выбранные в метаполе типа `relations`:
```php
$relations = PageData::current()->getRelations('related-posts');
```
Результат группируется по типу записи и идентификатору:
```php
$post = $relations['news'][15] ?? null;
```
Если связь не определена, метод возвращает пустую строку.
## Категории и глобальные данные
```php
$pageData = PageData::current();
$category = $pageData->getCategory('important');
$globalMeta = $pageData->getGlobalMeta('contacts', 'phone');
$globalCategory = $pageData->getGlobalCategory('regions', 'minsk');
$categoryList = $pageData->getGlobalCategoryList('regions');
```
| Метод | Описание |
|---|---|
| `getCategory($key)` | Возвращает локальную категорию текущей записи. |
| `getGlobalMeta($category, $key)` | Возвращает значение глобального метаполя. |
| `getGlobalCategory($category, $key)` | Возвращает значение глобальной категории. |
| `getGlobalCategoryList($category)` | Возвращает список глобальных категорий группы. |
Перед вызовом `getGlobalCategory()` убедитесь, что нужный ключ существует в группе.
## SEO
| Метод | Возвращает | Описание |
|---|---|---|
| `getSeoTitle()` | `string` | SEO-заголовок. |
| `getSeoDescription()` | `string` | SEO-описание. |
| `getSeoKeys()` | `string` | Ключевые слова. |
| `getNoIndex()` | `string` | Признак запрета индексации. |
| `getCanonical()` | `string` | Сохранённый canonical. |
| `getSeoHead()` | `string` | Готовые SEO-теги и социальная разметка для `head`. |
| `getFaviconUrl()` | `string` | URL favicon. |
| `getFaviconHead()` | `string` | Готовый тег favicon. |
Вывод тегов в шаблоне:
```php
echo PageData::getSeoHead();
echo PageData::getFaviconHead();
```
`getSeoHead()` может сформировать:
- заголовок страницы
- description и keywords
- robots
- canonical
- hreflang для языковых вариантов текущей страницы или записи
- Open Graph
- Twitter Cards
- JSON-LD-разметку Schema.org
`hreflang` формируется автоматически, если существует не менее двух индексируемых языковых вариантов и среди них присутствует текущая страница или запись.
Если отдельный SEO-заголовок, описание или ключевые слова не заданы, используются данные страницы и глобальные настройки сайта.
Для социальной разметки сначала используется изображение текущей страницы, а при его отсутствии — изображение по умолчанию из настроек SEO.
Open Graph и Twitter Cards учитывают состояние соответствующих настроек. Для страницы `404` социальная разметка, canonical и Schema.org не выводятся.
Базовая Schema.org-разметка описывает сайт и текущую страницу. Если странице или типу записей назначена отдельная схема, она дополняет данные текущей страницы.
## Комментарии
### getComments(): array
Возвращает исходный массив комментариев текущей записи:
```php
$comments = PageData::getComments();
```
### comments(): ?CommentsList
Возвращает объект для работы с комментариями:
```php
$comments = PageData::current()->comments();
$count = $comments?->publishCommentCount() ?? 0;
```
Для страницы без объекта комментариев метод возвращает `null`.
## Текущий экземпляр
### current(): PageData
Возвращает текущий экземпляр:
```php
$pageData = PageData::current();
```
## Подмена данных текущего запроса
Для изменения данных используйте текущий экземпляр:
```php
$pageData = PageData::current();
```
Изменения действуют только во время текущего запроса и не сохраняются в базе данных.
### Основные значения
| Метод | Изменяемое значение |
|---|---|
| `setTitle($title)` | Заголовок, возвращаемый `getTitle()`. |
| `setContent($content)` | Содержимое, возвращаемое `getContent()`. |
| `setImage($img)` | Изображение, возвращаемое `getImage()`. |
| `setTemplate($template)` | Название, возвращаемое `getTemplate()`. |
| `setType($type)` | Тип, возвращаемый `getType()`. |
```php
$pageData->setTitle('Временный заголовок');
$pageData->setContent('<p>Временное содержимое</p>');
$pageData->setImage('/upload/preview.jpg');
```
Методы изменяют только данные `PageData`. Они не запускают маршрутизацию повторно и не сохраняют страницу.
### setPostData($post)
Подменяет основные данные текущей записи:
```php
$pageData->setPostData([
'post_type' => 'news',
'url' => 'preview',
'title' => 'Предварительный просмотр',
'content' => '<p>Содержимое записи</p>',
'img' => '/upload/preview.jpg',
'more' => '',
'meta' => [],
'comment' => [],
'global_meta' => [],
'category' => [],
'global_category' => [],
]);
```
Передаваемый массив должен содержать все перечисленные ключи.
| Ключ | Описание |
|---|---|
| `post_type` | Системное имя типа записи. |
| `url` | Идентификатор записи в URL. |
| `title` | Заголовок. |
| `content` | Основное содержимое. |
| `img` | Изображение. |
| `more` | Дополнительное содержимое. |
| `meta` | Значения метаполей. |
| `comment` | Массив комментариев. |
| `global_meta` | Глобальные метаполя. |
| `category` | Категории записи. |
| `global_category` | Глобальные категории записи. |
Метод изменяет только перечисленные данные. Идентификатор, автор, даты, SEO и остальные значения текущего объекта сохраняются без изменений.
Массив `comment` становится доступен через `getComments()`. Объект, возвращаемый `comments()`, автоматически не пересоздаётся.
### setMeta($meta): void
Подменяет определения и значения метаполей:
```php
$pageData->setMeta([
'post_meta' => [
'subtitle' => [
'name' => 'Подзаголовок',
'type' => 'text',
],
],
'meta' => [
'subtitle' => 'Новый подзаголовок',
],
]);
$subtitle = PageData::getMeta('subtitle');
```
`post_meta` содержит определения полей, а `meta` — их значения. Метод также принимает JSON-строку с определениями метаполей.
Переданные поля добавляются или заменяются. Остальные метаполя текущего объекта не удаляются.
## Важные замечания
- класс описывает только текущий запрос
- для произвольной страницы используйте `PageManager`
- для произвольных опубликованных записей используйте `PostManager`
- не создавайте экземпляр `PageData` вручную
- отсутствующие строковые значения обычно возвращаются как пустая строка
- методы подмены не сохраняют изменения в базе данных
- методы подмены не запускают маршрутизацию и выбор шаблона повторно
- `setPostData()` требует полный набор перечисленных ключей
PageManager
Путь: api/classes/page-manager
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: PageManager
slug: page-manager
doc-id: page-manager
lang: ru
version: v0.95
section: api
type: classes
status: stable
description: Получение опубликованных страниц CMS и их языковых вариантов.
introduced-in: 0.95
---
# PageManager
`PageManager` получает опубликованные страницы независимо от страницы текущего HTTP-запроса.
## Поддерживает
- получение страницы по URL и языку
- использование текущего языка CMS
- проверку поддержки свободной ссылки
- получение переводов страницы
- получение языковых вариантов главной страницы
- работу с основной или переданной базой данных
## Быстрый старт
```php
$pageManager = new PageManager();
$page = $pageManager->getPublishedByUrl('contacts');
if ($page === null) {
return;
}
$title = $page['title'];
$content = $page['content'];
```
## Получение страницы
### getPublishedByUrl(string $url, bool $freeLink = false, ?string $language = null): ?array
Возвращает опубликованную страницу по её URL и языку:
```php
$page = (new PageManager())->getPublishedByUrl('contacts');
```
Начальные и конечные символы `/` удаляются:
```php
$page = (new PageManager())->getPublishedByUrl('/contacts/');
```
Для получения страницы определённого языка передайте его код третьим параметром:
```php
$page = (new PageManager())->getPublishedByUrl('contacts', false, 'en');
```
Если язык не передан, используется текущий язык CMS. Если текущий язык недоступен, используется язык сайта по умолчанию.
| Параметр | Тип | Описание |
|---|---|---|
| `$url` | `string` | URL страницы без языкового префикса. |
| `$freeLink` | `bool` | Требовать непустое значение `free_link`. |
| `$language` | `string\|null` | Код языка страницы. |
Если URL пустой или подходящая страница не найдена, метод возвращает `null`.
Данные страницы возвращаются без дополнительного преобразования полей `meta` и `seo`.
## Свободная ссылка
Чтобы получить только страницу со свободной ссылкой, передайте `true` вторым параметром:
```php
$page = (new PageManager())->getPublishedByUrl('developer', true);
```
Поиск также учитывает выбранный язык.
## Переводы страницы
### getPublishedTranslations(string $translationKey): array
Возвращает опубликованные переводы, объединённые одним значением `translation_key`:
```php
$pageManager = new PageManager();
$page = $pageManager->getPublishedByUrl('contacts');
$translations = $page === null ? [] : $pageManager->getPublishedTranslations((string) ($page['translation_key'] ?? ''));
```
Каждый элемент содержит:
| Поле | Описание |
|---|---|
| `id` | Идентификатор страницы. |
| `url` | URL страницы без языкового префикса. |
| `language` | Код языка. |
| `template` | Название шаблона. |
| `seo` | SEO-настройки в виде массива. |
Если ключ пустой или имеет неверный формат, метод возвращает пустой массив.
## Языковые варианты главной страницы
### getMainPageVersions(): array
Возвращает сохранённые языковые варианты главной страницы:
```php
$versions = (new PageManager())->getMainPageVersions();
```
Каждый элемент содержит `id`, `language` и `seo`. Поле `seo` возвращается в виде массива.
## База данных
### __construct(?Database $db = null)
Без аргументов менеджер использует основной объект базы данных CMS:
```php
$pageManager = new PageManager();
```
При необходимости можно передать другой экземпляр `Database`:
```php
$pageManager = new PageManager($database);
```
## Отличие от PageData
`PageManager` используется для поиска произвольной страницы и получения её языковых вариантов.
`PageData` содержит данные страницы или записи, уже определённой CMS для текущего запроса.
## Важные замечания
- `getPublishedByUrl()` и `getPublishedTranslations()` возвращают только страницы со статусом `publish`
- пустой URL возвращает `null`
- отсутствующая страница возвращает `null`
- `getPublishedByUrl()` возвращает поля `meta` и `seo` без преобразования
- `getPublishedTranslations()` и `getMainPageVersions()` преобразуют поле `seo` в массив
- получение страницы по идентификатору класс не поддерживает
- для данных текущей страницы используйте `PageData`
Post
Путь: api/classes/post
Версия документа: 0.973
Статус: deprecated
Открыть документ
---
title: Post
slug: post
doc-id: post
lang: ru
version: v0.95
section: api
type: classes
status: deprecated
deprecated-in: 0.95
description: Устаревший класс для получения и изменения записей CMS.
---
# Post
`Post` является устаревшим классом. Он сохранён для поддержки старого кода, но не должен использоваться в новой разработке.
Единой полной замены у класса нет:
- для чтения опубликованных записей используйте `PostManager`
- для данных записи текущего запроса используйте `PageData`
- для устаревших операций изменения и произвольных SQL-запросов прямой высокоуровневой замены нет
## Чтение опубликованных записей
Вместо методов получения публичных записей используйте `PostManager`:
```php
$postManager = new PostManager('news');
$posts = $postManager->getPublishedList(
limit: 10
);
```
Получение записи по URL:
```php
$post = $postManager->getPublishedByUrl('release-notes');
if ($post === null) {
return;
}
```
Получение нескольких записей по идентификаторам:
```php
$posts = $postManager->getPublishedByIds([
15,
27,
]);
```
`PostManager` проверяет статус и дату публикации, ограничивает сортировку и не принимает произвольные SQL-условия.
## Данные текущей записи
Если CMS уже определила запись текущего запроса, используйте `PageData`:
```php
$postId = PageData::getId();
$title = PageData::getTitle();
$content = PageData::getContent();
$postType = PageData::getPostType();
```
## Сохранённый API
Методы класса остаются доступными для поддержки старого кода.
### Получение записей
| Метод | Назначение |
|---|---|
| `getPost()` | Получает запись по идентификатору и типу. |
| `getAllPost()` | Получает список независимо от статуса публикации. |
| `getPublishPost()` | Получает опубликованные записи. |
| `getPostQuery()` | Выполняет выборку по SQL-условию. |
| `getPostQueryUnion()` | Объединяет выборку нескольких типов. |
| `getPublishPostUnion()` | Получает опубликованные записи нескольких типов. |
| `getPublishPostCategory()` | Получает опубликованные записи с активной локальной категорией. |
### Подсчёт записей
| Метод | Назначение |
|---|---|
| `postCount()` | Подсчитывает записи одного типа. |
| `postCountUnion()` | Подсчитывает записи нескольких типов. |
### Изменение записей
| Метод | Назначение |
|---|---|
| `addPost()` | Добавляет запись из SQL-фрагмента. |
| `updatePost()` | Обновляет запись из SQL-фрагмента. |
| `updateMeta()` | Изменяет одно метаполе. |
| `updateMetaAll()` | Полностью заменяет метаданные. |
| `updateCategory()` | Изменяет одну локальную категорию. |
| `updateCategoryAll()` | Полностью заменяет локальные категории. |
## Формат результатов legacy API
Списочные методы класса `Post` используют индексы начиная с `1`.
Методы преобразуют структурированные поля в массивы:
- `meta`
- `category`
- `global_meta`
- `global_category`
- `comment`
Записи также могут получать поле `post_type`. Метод `getPost()` дополнительно получает логин автора в поле `author_login`.
Формат результатов отличается от `PostManager`, списки которого индексируются начиная с `0`.
## Ограничения
- класс использует устаревший объект базы данных
- типы записей и условия подставляются в SQL-запросы строками
- некоторые методы принимают готовые SQL-фрагменты
- не передавайте методам данные, полученные от пользователя
- методы изменения не используют актуальный безопасный API базы данных
- часть методов может вернуть пустой массив или `null` без единого строгого формата
- `getPublishPostCategory()` не использует переданный ключ категории в условии выборки
- для нового кода используйте актуальные классы CMS
PostManager
Путь: api/classes/post-manager
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: PostManager
slug: post-manager
doc-id: post-manager
lang: ru
version: v0.973
updated-in: 0.973
section: api
type: classes
status: stable
description: Менеджер для безопасного получения опубликованных записей.
introduced-in: 0.95
---
# PostManager
`PostManager` получает опубликованные записи одного или нескольких типов, учитывает дату публикации и подготавливает данные для вывода в шаблоне.
Для работы с одним типом создаётся экземпляр менеджера. Общий список нескольких типов можно получить статическим методом.
## Поддерживает
- получение опубликованной записи по URL и языку
- получение списка для выбранного языка или всех языков
- получение общего списка записей нескольких типов
- получение записей по идентификаторам и языку
- получение опубликованных переводов записи
- подсчёт опубликованных записей по языку
- формирование локализованных URL записей
- учёт просмотров
- создание краткого описания из содержимого
- выбор возвращаемых полей
- безопасную работу без произвольных SQL-фрагментов
## Быстрый старт
```php
$postManager = new PostManager('news');
$posts = $postManager->getPublishedList(
orderBy: 'publish_date',
limit: 10,
columns: [
'id',
'title',
'url',
'content',
]
);
foreach ($posts as $post) {
?>
<article>
<h2>
<a href="<?php echo $post['post_url']; ?>">
<?php echo $post['title']; ?>
</a>
</h2>
<p><?php echo $post['short_description']; ?></p>
</article>
<?php
}
```
Поля `post_url` и `short_description` создаются менеджером на основе выбранных `url` и `content`.
## Создание менеджера
### __construct(string $postType, ?Database $db = null)
Первым параметром передаётся системное имя типа записей:
```php
$postManager = new PostManager('news');
```
Допустимы латинские буквы, цифры, `_` и `-`.
Если имя имеет недопустимый формат, выбрасывается `InvalidArgumentException`.
Без второго аргумента используется основная база данных CMS. При необходимости можно передать другой экземпляр `Database`:
```php
$postManager = new PostManager(
'news',
$database
);
```
## Получение записи по URL
### getPublishedByUrl(string $url, ?string $language = null): ?array
Возвращает опубликованную запись по её URL и языку:
```php
$post = $postManager->getPublishedByUrl('release-notes');
$englishPost = $postManager->getPublishedByUrl('release-notes', 'en');
```
Если язык не передан, используется текущий язык CMS, а при его отсутствии — язык сайта по умолчанию. Передаётся код языка, а не URL-префикс.
Начальные и конечные `/` удаляются. Вложенные сегменты не поддерживаются.
Метод возвращает `null`, если URL пустой, содержит вложенные сегменты, запись не найдена, не опубликована или её дата публикации ещё не наступила.
Результат получает поля `post_type`, `post_url` и, при наличии `content`, `short_description`. Структурированные поля возвращаются в исходном формате базы данных.
## Формирование URL
### getUrl(string $slug, ?string $language = null): string
Формирует локализованный публичный URL записи:
```php
$url = $postManager->getUrl('release-notes');
$englishUrl = $postManager->getUrl('release-notes', 'en');
```
Если язык не передан, используется текущий язык CMS, а при его отсутствии — язык сайта по умолчанию.
Если идентификатор пустой или содержит `/`, выбрасывается `InvalidArgumentException`.
`RuntimeException` выбрасывается, если для типа записей не настроен публичный URL или ссылка недоступна для выбранного языка.
## Получение списка
### getPublishedList(string $orderBy = 'id', string $order = 'DESC', ?int $limit = null, int $offset = 0, array $columns = ..., ?string $language = null, bool $allLanguages = false): array
Возвращает список опубликованных записей:
```php
$posts = $postManager->getPublishedList(
orderBy: 'publish_date',
order: 'DESC',
limit: 10,
offset: 0
);
```
### Параметры
| Параметр | Тип | Описание |
|---|---|---|
| `$orderBy` | `string` | Поле сортировки. По умолчанию `id`. |
| `$order` | `string` | Направление `ASC` или `DESC`. |
| `$limit` | `int\|null` | Максимальное количество записей. |
| `$offset` | `int` | Смещение. Используется только вместе с `$limit`. |
| `$columns` | `array` | Список возвращаемых полей. |
| `$language` | `string\|null` | Код языка или `null` для автоматического определения. |
| `$allLanguages` | `bool` | Получить записи всех языков без языкового фильтра. |
Если язык не передан, используется текущий язык CMS, а при его отсутствии — язык сайта по умолчанию:
```php
$englishPosts = $postManager->getPublishedList(
limit: 10,
language: 'en'
);
```
Чтобы получить записи всех языков, передайте `true` в `$allLanguages`:
```php
$posts = $postManager->getPublishedList(
limit: 10,
allLanguages: true
);
```
`$allLanguages` отключает фильтрацию по языку и имеет приоритет над `$language`. При явном выборе полей менеджер автоматически добавляет поле `language`.
Допустимые поля сортировки:
- `id`
- `title`
- `date`
- `publish_date`
- `modified_date`
- `views`
По умолчанию из базы данных выбираются:
- `id`
- `title`
- `url`
- `img`
- `author`
- `date`
- `publish_date`
- `modified_date`
- `views`
Каждый результат дополнительно получает поле `post_type`.
Если выбранное поле `url` содержит корректный идентификатор записи, результат также получает `post_url`.
Чтобы получить дополнительные поля, передайте их последним параметром:
```php
$posts = $postManager->getPublishedList(
limit: 10,
columns: [
'id',
'title',
'url',
'content',
'meta',
]
);
```
При выборе `content` менеджер добавляет поле `short_description`.
Если выбраны структурированные поля, они преобразуются в массивы:
- `meta`
- `category`
- `global_meta`
- `global_category`
- `comment`
- `seo`
## Получение записей нескольких типов
### getPublishedListByTypes(array $postTypes, string $orderBy = 'id', string $order = 'DESC', ?int $limit = null, int $offset = 0, array $columns = ..., ?string $language = null, bool $allLanguages = false, ?Database $db = null): array
Статический метод возвращает общий список опубликованных записей нескольких типов:
```php
$columns = ['id', 'title', 'url'];
$posts = PostManager::getPublishedListByTypes(['news', 'articles'], orderBy: 'publish_date', limit: 10, columns: $columns);
```
Создавать отдельные экземпляры `PostManager` для этого вызова не нужно.
Первым параметром передаётся массив системных имён типов записей. Повторяющиеся имена учитываются один раз. Если передан пустой массив, метод возвращает пустой список.
Остальные параметры сортировки, ограничения, выбора полей и языка работают так же, как в `getPublishedList()`.
Каждая запись дополнительно получает поле `post_type`, содержащее системное имя её типа. Передавать `post_type` в `$columns` не нужно: менеджер добавляет его автоматически.
Сортировка и ограничение применяются к общему результату всех переданных типов, а не отдельно к каждому типу.
При необходимости последним параметром можно передать другой экземпляр `Database`.
## Переводы записи
### getPublishedTranslations(string $translationKey): array
Возвращает опубликованные языковые варианты, объединённые одним значением `translation_key`:
```php
$translations = $postManager->getPublishedTranslations(
$post['translation_key']
);
```
Каждый элемент содержит `id`, `url`, `language`, `seo` и добавленное поле `post_type`. Поле `seo` преобразуется в массив. Если для языка можно сформировать ссылку, также добавляется `post_url`.
Результат сортируется по `id` по возрастанию. Если ключ пустой, имеет недопустимый формат или опубликованные варианты не найдены, метод возвращает пустой массив.
## Получение записей по ID
### getPublishedByIds(array $ids, array $columns = ..., ?string $language = null): array
Возвращает опубликованные записи по идентификаторам:
```php
$posts = $postManager->getPublishedByIds([
15,
27,
42,
]);
```
Идентификаторы приводятся к целым числам. Нулевые, отрицательные и повторяющиеся значения исключаются.
Результат сортируется по `id` по возрастанию.
Если язык не передан, используется текущий язык CMS, а при его отсутствии — язык сайта по умолчанию.
Для получения записей определённого языка передайте его код:
```php
$englishPosts = $postManager->getPublishedByIds(
[15, 27],
language: 'en'
);
```
Для выбора дополнительных полей передайте второй параметр:
```php
$posts = $postManager->getPublishedByIds(
[15, 27],
[
'id',
'title',
'url',
'content',
'meta',
]
);
```
Правила добавления `post_url`, `short_description` и преобразования структурированных полей совпадают с правилами списка.
Если после проверки не осталось допустимых идентификаторов, метод возвращает пустой массив.
## Дополнительные поля
### post_type
Добавляется к каждой записи и содержит системное имя типа:
```php
$postType = $post['post_type'];
```
### post_url
Добавляется, если в результате присутствует поле `url` с непустым идентификатором без вложенных сегментов:
```php
$url = $post['post_url'];
```
URL учитывает публичный путь типа записей и язык, выбранный при вызове метода. При выборке всех языков или переводов используется язык каждой отдельной записи.
### short_description
Добавляется, если в результате присутствует поле `content`:
```php
$description = $post['short_description'];
```
При подготовке краткого описания:
- декодируются HTML-сущности
- удаляются HTML-теги
- удаляется содержимое `script`, `style`, `noscript` и `template`
- переносы и повторяющиеся пробелы заменяются одним пробелом
- текст сокращается примерно до `180` символов
- при сокращении текст по возможности завершается на границе слова
- к сокращённому тексту добавляется `...`
Если текст короче установленного ограничения, многоточие не добавляется.
## Подсчёт записей
### countPublished(?string $language = null): int
Возвращает количество опубликованных записей выбранного типа и языка:
```php
$count = $postManager->countPublished();
$englishCount = $postManager->countPublished('en');
```
Если язык не передан, используется текущий язык CMS, а при его отсутствии — язык сайта по умолчанию.
При подсчёте учитываются статус и дата публикации.
## Учёт просмотров
### recordView(int $id): void
Увеличивает значение `views` указанной записи на единицу:
```php
$postManager->recordView(15);
```
Метод ничего не возвращает. Если идентификатор меньше `1`, выбрасывается `InvalidArgumentException`.
## Правила публикации
Запись считается опубликованной, если:
- поле `status` содержит `publish`
- `publish_date` не задана или не превышает текущее время
Эти правила используются в `getPublishedByUrl()`, `getPublishedList()`, `getPublishedListByTypes()`, `getPublishedTranslations()`, `getPublishedByIds()` и `countPublished()`.
`recordView()` только увеличивает счётчик просмотров и не проверяет статус или дату публикации.
## Исключения
| Исключение | Когда возникает |
|---|---|
| `InvalidArgumentException` | Тип записи содержит недопустимые символы. |
| `InvalidArgumentException` | Идентификатор для `getUrl()` пустой или содержит `/`. |
| `InvalidArgumentException` | Передано неподдерживаемое поле сортировки. |
| `InvalidArgumentException` | Направление сортировки отличается от `ASC` и `DESC`. |
| `InvalidArgumentException` | Лимит меньше `1`. |
| `InvalidArgumentException` | Смещение отрицательное или передано без лимита. |
| `InvalidArgumentException` | Массив выбираемых полей пуст. |
| `InvalidArgumentException` | Поле `post_type` вручную добавлено в `$columns` метода `getPublishedListByTypes()`. |
| `InvalidArgumentException` | В `recordView()` передан идентификатор меньше `1`. |
| `RuntimeException` | Для типа записей не настроен публичный URL или ссылка недоступна для выбранного языка. |
`RuntimeException` также может возникнуть при получении записей с полем `url`, поскольку менеджер автоматически формирует для них `post_url`.
## Важные замечания
- один экземпляр работает только с одним типом записей
- методы получения и подсчёта учитывают только опубликованные записи
- без явного языка используется текущий язык CMS или язык сайта по умолчанию
- списки индексируются начиная с `0`
- каждый результат получает поле `post_type`
- `post_url` добавляется только при наличии корректного поля `url` и доступной ссылки для языка записи
- `short_description` добавляется только при наличии поля `content`
- `recordView()` не проверяет статус публикации записи
- произвольные SQL-условия не поддерживаются
- для данных записи текущего запроса используйте `PageData`
QueryGet
Путь: api/classes/query-get
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: QueryGet
slug: query-get
doc-id: query-get
lang: ru
version: v0.95
section: api
type: classes
status: stable
description: Получение параметров GET-запроса.
introduced-in: 0.7
---
# QueryGet
`QueryGet` предоставляет статические методы для получения параметров текущего GET-запроса.
Создавать экземпляр класса не нужно.
## Поддерживает
- проверку наличия параметра
- получение значения с экранированными HTML-символами
- получение исходного значения без обработки
## Быстрый старт
```php
if (QueryGet::isset('page')) {
$page = QueryGet::getValue('page');
}
```
Для URL `/catalog?page=2` переменная `$page` будет содержать строку `2`.
## Проверка параметра
### isset($key): bool
Возвращает `true`, если параметр присутствует в GET-запросе:
```php
if (QueryGet::isset('search')) {
// Параметр search передан.
}
```
Проверяйте наличие параметра перед вызовом `getOriginalValue()`.
## Получение значения
### getValue($key): ?string
Возвращает значение с экранированными специальными HTML-символами:
```php
$search = QueryGet::getValue('search');
if ($search !== null) {
echo '<p>' . $search . '</p>';
}
```
Символы `<`, `>`, `&`, одинарные и двойные кавычки преобразуются в HTML-сущности.
Если параметр отсутствует, метод возвращает `null`.
Метод не проверяет назначение и формат значения. Например, числовой параметр нужно дополнительно привести к числу:
```php
$page = (int) QueryGet::getValue('page');
if ($page < 1) {
$page = 1;
}
```
## Исходное значение
### getOriginalValue($key): mixed
Возвращает значение без экранирования:
```php
if (QueryGet::isset('search')) {
$search = QueryGet::getOriginalValue('search');
}
```
Используйте этот метод только тогда, когда требуется самостоятельно обработать исходное значение.
Не выводите полученное значение в HTML без дополнительного экранирования.
Если вызвать метод для отсутствующего параметра, PHP сформирует предупреждение о неизвестном ключе. Поэтому сначала используйте `isset()`.
## Параметры-массивы
`getValue()` предназначен для строковых значений. Если GET-параметр передан как массив, используйте `getOriginalValue()` и проверьте его тип:
```php
$tags = [];
if (QueryGet::isset('tags')) {
$value = QueryGet::getOriginalValue('tags');
$tags = is_array($value) ? $value : [];
}
```
Каждый элемент такого массива нужно проверять и обрабатывать отдельно.
## Важные замечания
- класс используется статически
- `getValue()` возвращает `null`, если параметр отсутствует
- `getValue()` экранирует HTML-символы, но не проверяет формат значения
- `getValue()` предназначен только для строковых параметров
- `getOriginalValue()` возвращает данные без обработки
- перед вызовом `getOriginalValue()` проверяйте параметр через `isset()`
- все данные GET-запроса считаются пользовательским вводом и требуют проверки в зависимости от назначения
QueryPost
Путь: api/classes/query-post
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: QueryPost
slug: query-post
doc-id: query-post
lang: ru
version: v0.95
section: api
type: classes
status: stable
description: Получение параметров POST-запроса.
introduced-in: 0.7
---
# QueryPost
`QueryPost` предоставляет статические методы для получения параметров текущего POST-запроса.
Создавать экземпляр класса не нужно.
## Поддерживает
- проверку наличия параметра
- получение значения с экранированными HTML-символами
- получение исходного значения без обработки
- получение всех параметров POST-запроса
## Быстрый старт
```php
if (QueryPost::isset('title')) {
$title = QueryPost::getValue('title');
}
```
## Проверка параметра
### isset($key): bool
Возвращает `true`, если параметр присутствует в POST-запросе:
```php
if (QueryPost::isset('publish')) {
// Параметр publish передан.
}
```
Проверяйте наличие параметра перед вызовом `getOriginalValue()`.
## Получение значения
### getValue($key): ?string
Возвращает значение с экранированными специальными HTML-символами:
```php
$title = QueryPost::getValue('title');
if ($title !== null) {
echo '<h1>' . $title . '</h1>';
}
```
Символы `<`, `>`, `&`, одинарные и двойные кавычки преобразуются в HTML-сущности.
Если параметр отсутствует, метод возвращает `null`.
Метод не проверяет назначение и формат значения. Числовые параметры нужно дополнительно приводить к нужному типу:
```php
$page = (int) QueryPost::getValue('page');
```
## Все обработанные значения
### getPostArray(): array
Возвращает все параметры POST-запроса с экранированными HTML-символами:
```php
$values = QueryPost::getPostArray();
$title = $values['title'] ?? '';
$content = $values['content'] ?? '';
```
Если POST-запрос не содержит параметров, метод возвращает пустой массив.
Метод предназначен для плоского набора строковых значений. Если форма передаёт массивы, используйте `getOriginalPostArray()` и обрабатывайте каждый элемент отдельно.
## Исходные значения
### getOriginalValue($key): mixed
Возвращает значение параметра без обработки:
```php
if (QueryPost::isset('content')) {
$content = QueryPost::getOriginalValue('content');
}
```
Если вызвать метод для отсутствующего параметра, PHP сформирует предупреждение о неизвестном ключе. Поэтому сначала используйте `isset()`.
### getOriginalPostArray(): array
Возвращает исходный массив POST-запроса:
```php
$values = QueryPost::getOriginalPostArray();
```
Значения возвращаются без экранирования и дополнительной проверки.
## Параметры-массивы
Для параметров, переданных как массив, используйте исходное значение и проверяйте его тип:
```php
$categories = [];
if (QueryPost::isset('categories')) {
$value = QueryPost::getOriginalValue('categories');
$categories = is_array($value) ? $value : [];
}
```
Каждый элемент массива нужно проверять и обрабатывать отдельно.
## Важные замечания
- класс используется статически
- `getValue()` возвращает `null`, если параметр отсутствует
- `getValue()` экранирует HTML-символы, но не проверяет формат значения
- `getValue()` и `getPostArray()` предназначены для строковых параметров
- методы с `Original` в названии возвращают данные без обработки
- перед вызовом `getOriginalValue()` проверяйте параметр через `isset()`
- все данные POST-запроса считаются пользовательским вводом и требуют проверки в зависимости от назначения
SiteLang
Путь: api/classes/site-lang
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: SiteLang
slug: site-lang
doc-id: site-lang
lang: ru
version: v0.95
section: api
type: classes
status: stable
description: Получение локализованных строк активной темы.
introduced-in: 0.95
---
# SiteLang
`SiteLang` является статическим классом для получения локализованных строк активной темы. Он автоматически доступен в обычных шаблонах сайта.
## Поддерживает
- общие переводы для всей темы
- отдельные переводы страниц и записей
- вложенные ключи через точку
- резервные значения
- наследование переводов языка по умолчанию
- безопасный вывод текста в HTML
## Быстрый старт
```php
<h1><?php echo SiteLang::html('catalog.title', 'Каталог'); ?></h1>
```
Первый аргумент содержит путь к переводу, второй используется, если перевод не найден.
## Файлы переводов
Переводы хранятся в папке `lang` активной темы. Название языковой папки соответствует префиксу языка:
```text
lang/
ru/
common.php
index.php
404.php
page/
catalog.php
post/
news.php
en/
common.php
```
Каждый файл должен возвращать массив:
```php
<?php
return [
'catalog' => [
'title' => 'Каталог',
'description' => 'Товары нашего магазина',
],
];
```
Получение вложенного значения:
```php
$title = SiteLang::get('catalog.title');
```
## Загружаемые файлы
| Контекст | Файл |
|---|---|
| Все страницы сайта | `lang/{prefix}/common.php` |
| Главная страница | `lang/{prefix}/index.php` |
| Страница ошибки | `lang/{prefix}/404.php` |
| Шаблон страницы | `lang/{prefix}/page/{template}.php` |
| Шаблон записи | `lang/{prefix}/post/{template}.php` |
Сначала загружаются общие переводы, затем переводы текущего шаблона.
Переводы текущего языка дополняют переводы языка по умолчанию. Поэтому необязательно повторять в каждом языке все существующие ключи.
## Получение перевода
### get(string $path, string $default = ''): string
Возвращает перевод без дополнительной обработки:
```php
$title = SiteLang::get('catalog.title');
```
Если ключ может отсутствовать, передайте резервное значение:
```php
$title = SiteLang::get('catalog.title', 'Каталог');
```
Если перевод не найден или найденное значение является массивом, метод возвращает резервное значение.
Путь к вложенному значению записывается через точку:
```php
$text = SiteLang::get('navigation.catalog.title');
```
## Вывод в HTML
### html(string $path, string $default = ''): string
Возвращает перевод с экранированными специальными HTML-символами:
```php
<p><?php echo SiteLang::html('catalog.description'); ?></p>
```
Резервное значение также экранируется:
```php
<p><?php echo SiteLang::html('catalog.description', 'Описание каталога'); ?></p>
```
Метод предназначен для вывода обычного текста. HTML-теги внутри перевода будут показаны как текст, а не обработаны браузером.
## Все переводы
### all(): array
Возвращает массив всех переводов, загруженных для текущей страницы:
```php
$translations = SiteLang::all();
```
В массив входят общие переводы и переводы текущего шаблона с учётом текущего языка и языка по умолчанию.
## Важные замечания
- файлы переводов должны возвращать массив
- вложенные ключи разделяются точкой
- `get()` возвращает только строковые и другие скалярные значения
- для безопасного вывода текста в HTML используйте `html()`
- контекстный файл шаблона дополняет и переопределяет общие переводы
- отсутствующие переводы берутся из языка по умолчанию
SiteLanguages
Путь: api/classes/site-languages
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: SiteLanguages
slug: site-languages
doc-id: site-languages
lang: ru
version: v0.95
section: api
type: classes
status: stable
description: Получение настроенных языков сайта и определение языка по коду или префиксу.
introduced-in: 0.95
---
# SiteLanguages
`SiteLanguages` предоставляет список языков сайта и помогает выбирать язык по коду или URL-префиксу.
Для работы создайте экземпляр класса:
```php
$languages = new SiteLanguages();
```
## Поддерживает
- проверку состояния языковых настроек
- получение всех или только активных языков
- получение языка по умолчанию
- поиск языка по коду
- поиск активного языка по URL-префиксу
- проверку и нормализацию переданного кода языка
- работу с основной или переданной базой данных
## Быстрый старт
```php
$languages = new SiteLanguages();
if (!$languages->isValid()) {
return;
}
foreach ($languages->all(true) as $language) {
echo $language['code'] . ': ' . $language['label'];
}
```
Аргумент `true` передаётся в `all()`, чтобы получить только активные языки.
## Состояние настроек
### isValid(): bool
Возвращает `true`, если языковые настройки заполнены корректно:
```php
if (!$languages->isValid()) {
return;
}
```
Корректные настройки должны содержать активные языки и один активный язык по умолчанию.
### isEnabled(): bool
Возвращает состояние мультиязычности:
```php
if ($languages->isEnabled()) {
// На сайте используются языковые URL.
}
```
`false` может означать, что мультиязычность отключена или языковые настройки недействительны. Для проверки настроек отдельно используйте `isValid()`.
## Формат данных языка
Методы, возвращающие один язык, предоставляют массив следующего вида:
| Ключ | Тип | Описание |
|---|---|---|
| `code` | `string` | Код языка. |
| `label` | `string` | Отображаемое название языка. |
| `prefix` | `string` | Префикс языка в URL. |
| `default` | `bool` | Является ли язык языком по умолчанию. |
| `active` | `bool` | Активен ли язык. |
| `order` | `int` | Порядок языка в списке. |
Код и URL-префикс являются отдельными значениями и могут различаться.
## Получение списка
### all(bool $activeOnly = false): array
Без аргумента возвращает все настроенные языки:
```php
$allLanguages = $languages->all();
```
Чтобы получить только активные языки, передайте `true`:
```php
$activeLanguages = $languages->all(true);
```
Языки возвращаются в настроенном порядке.
Если языковые настройки недействительны, метод возвращает пустой массив.
## Язык по умолчанию
### getDefault(): ?array
Возвращает активный язык сайта по умолчанию:
```php
$defaultLanguage = $languages->getDefault();
if ($defaultLanguage !== null) {
echo $defaultLanguage['label'];
}
```
Если язык по умолчанию недоступен, метод возвращает `null`.
### defaultCode(string $fallback = 'ru'): string
Возвращает код языка по умолчанию:
```php
$code = $languages->defaultCode();
```
Можно передать резервный код:
```php
$code = $languages->defaultCode('en');
```
Резервное значение используется, если код языка по умолчанию получить невозможно. Недопустимое резервное значение заменяется на `ru`.
## Поиск по коду
### getByCode(string $code, bool $activeOnly = true): ?array
Возвращает активный язык по его коду:
```php
$language = $languages->getByCode('en');
```
По умолчанию неактивные языки не возвращаются. Для поиска среди всех настроенных языков передайте `false`:
```php
$language = $languages->getByCode('en', false);
```
Если язык не найден, метод возвращает `null`.
Код перед поиском приводится к нижнему регистру, а пробелы по краям удаляются.
## Поиск по префиксу
### getByPrefix(string $prefix): ?array
Возвращает активный язык по URL-префиксу:
```php
$language = $languages->getByPrefix('en');
```
Передавайте префикс без символов `/`.
Если активный язык с таким префиксом не найден, метод возвращает `null`.
## Определение кода
### resolveCode(?string $code, bool $activeOnly = true, string $fallback = 'ru'): string
Проверяет переданный код и возвращает его, если соответствующий язык существует:
```php
$code = $languages->resolveCode('en');
```
Если код пустой, имеет неверный формат или язык недоступен, возвращается код языка по умолчанию:
```php
$code = $languages->resolveCode(null);
```
Чтобы разрешить неактивный язык, передайте `false` вторым параметром:
```php
$code = $languages->resolveCode('en', false);
```
Третий параметр задаёт резервный код на случай, если язык по умолчанию получить невозможно:
```php
$code = $languages->resolveCode(null, true, 'en');
```
## База данных
### __construct(?Database $db = null)
Без аргументов класс использует основную базу данных CMS:
```php
$languages = new SiteLanguages();
```
При необходимости можно передать другой экземпляр `Database`:
```php
$languages = new SiteLanguages($database);
```
## Важные замечания
- экземпляр получает состояние языков при создании
- `isValid()` проверяет настройки, а `isEnabled()` — состояние мультиязычности
- `all()` без аргумента включает неактивные языки
- `getDefault()` возвращает только активный язык
- `getByCode()` по умолчанию ищет только активные языки
- `getByPrefix()` всегда ищет только среди активных языков
- код языка и его URL-префикс могут различаться
SiteOptions
Путь: api/classes/site-options
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: SiteOptions
slug: site-options
doc-id: site-options
lang: ru
version: v0.95
section: api
type: classes
status: stable
introduced-in: 0.95
description: Статический класс для получения глобальных настроек сайта.
---
# SiteOptions
`SiteOptions` предоставляет доступ к глобальным настройкам сайта.
Класс статический и автоматически доступен после запуска CMS. Создавать его экземпляр не нужно.
## Поддерживает
- получение глобальной настройки по имени
- указание значения по умолчанию
- безопасную работу с отсутствующими настройками
## Быстрый старт
```php
$siteName = SiteOptions::get('sitename');
$description = SiteOptions::get('description');
```
Для отсутствующей настройки можно указать значение по умолчанию:
```php
$siteName = SiteOptions::get(
'sitename',
'Мой сайт'
);
```
## Получение настройки
### get(string $name, string $default = ''): string
Возвращает значение глобальной настройки.
| Параметр | Описание |
|---|---|
| `$name` | Имя настройки. |
| `$default` | Значение, возвращаемое при отсутствии настройки. |
```php
$debug = SiteOptions::get('debug');
if ($debug === 'on') {
echo 'Режим разработки включён';
}
```
Если настройка существует, но содержит пустую строку, метод возвращает пустую строку, а не значение по умолчанию.
## Допустимые имена
Имя настройки может содержать:
- латинские буквы
- цифры
- дефис
- нижнее подчёркивание
Первым символом должна быть буква или цифра.
При недопустимом имени метод выбрасывает `InvalidArgumentException`:
```php
try {
$value = SiteOptions::get('invalid option');
} catch (InvalidArgumentException $exception) {
echo $exception->getMessage();
}
```
## Важные замечания
- метод всегда возвращает строку
- класс предназначен только для чтения настроек
- изменение полученного значения не сохраняет настройку
- не создавайте экземпляр `SiteOptions`
- вызывайте класс только после запуска CMS
- для текущего URL используйте `CurrentUrl`
- для текущего языка используйте `CurrentLanguage`
- для активной темы используйте `CurrentTheme`
TextHandler
Путь: api/classes/text-handler
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: TextHandler
slug: text-handler
doc-id: text-handler
lang: ru
version: v0.97
section: api
type: classes
status: stable
description: Сокращение текста по количеству символов или слов.
introduced-in: 07
---
# TextHandler
`TextHandler` является статическим классом для сокращения обычного текста. Создавать экземпляр класса не нужно.
## Поддерживает
- ограничение текста по количеству символов
- ограничение текста по количеству слов
- удаление HTML-тегов из результата
- удаление пробелов по краям результата
## Быстрый старт
```php
$preview = TextHandler::trimWord(
'CMS WebSource помогает создавать сайты',
3
);
```
Результат:
```text
CMS WebSource помогает
```
## Ограничение по символам
### trimString($text, $count = 100)
Ограничивает исходную строку указанным количеством символов, удаляет HTML-теги и пробелы по краям:
```php
$preview = TextHandler::trimString(
'Документация WebSource',
12
);
```
Результат:
```text
Документация
```
Ограничение применяется до удаления HTML-тегов, поэтому символы разметки также входят в `count`.
## Ограничение по словам
### trimWord($text, $count = 10)
Удаляет HTML-теги и возвращает первые слова, разделённые обычными пробелами:
```php
$preview = TextHandler::trimWord(
'CMS WebSource помогает создавать сайты',
3
);
```
Результат:
```text
CMS WebSource помогает
```
### trimWordBySymbol($text, $count = 100)
Сначала ограничивает строку по количеству символов через `trimString()`, затем обрабатывает полученный текст через `trimWord()`:
```php
$preview = TextHandler::trimWordBySymbol(
'CMS WebSource помогает создавать сайты',
13
);
```
Результат:
```text
CMS WebSource
```
Метод не гарантирует сохранение последнего слова целиком: если граница `count` проходит внутри слова, оно будет обрезано.
## Важные замечания
- методы не добавляют многоточие к сокращённому тексту
- `trimWord()` использует обычный пробел как разделитель слов
- HTML-теги удаляются, но результат не экранируется для вывода в HTML
- для безопасного вывода пользовательского текста применяйте подходящее контексту экранирование
WSDB
Путь: api/classes/wsdb
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: WSDB
slug: wsdb
doc-id: wsdb
lang: ru
version: v0.97
updated-in: 0.97
section: api
type: classes
status: stable
introduced-in: 0.95
description: Статический доступ к подключениям и операциям базы данных CMS.
---
# WSDB
`WSDB` предоставляет статический доступ к основному подключению базы данных CMS.
Класс автоматически доступен после запуска CMS. Создавать его экземпляр не нужно.
## Поддерживает
- статический доступ к основному подключению
- регистрацию дополнительных подключений
- выборку, добавление, обновление и удаление данных
- атомарное увеличение числовых значений
- выбор одной приоритетной строки из каждой группы
- подсчёт уникальных значений столбца
- условия, сортировку и ограничение выборки
- работу с JSON-полями
- транзакции с автоматическим откатом
- блокировку параллельного выполнения операций
- проверку существования таблиц, столбцов и индексов
- автоматическое использование префикса таблиц
## Быстрый старт
Получение одной строки:
```php
$page = WSDB::fetchOne(
'page',
['id' => 15],
['id', 'title', 'url']
);
```
Получение списка:
```php
$pages = WSDB::fetchAll(
table: 'page',
where: ['status' => 'publish'],
columns: ['id', 'title', 'url'],
order: ['id' => 'DESC'],
limit: 10
);
```
Добавление данных:
```php
$id = WSDB::insert(
'page',
[
'title' => 'Новая страница',
'status' => 'draft',
]
);
```
## Подключения
Основное подключение регистрируется CMS автоматически. Для обычной работы дополнительно настраивать его не нужно.
### on(string $name = 'default'): Database
Возвращает объект `Database` для выполнения запросов:
```php
$database = WSDB::on();
$page = $database->fetchOne('page', ['id' => 15]);
```
Для основного подключения методы `Database` можно вызывать напрямую через `WSDB`:
```php
$page = WSDB::fetchOne('page', ['id' => 15]);
```
### connection(string $name = 'default'): DatabaseConnection
Возвращает параметры зарегистрированного подключения:
```php
$connection = WSDB::connection();
$pdo = $connection->pdo();
$prefix = $connection->prefix();
```
Обычно получать `DatabaseConnection` вручную не требуется.
### isRegistered(string $name = 'default'): bool
Проверяет, зарегистрировано ли подключение с указанным именем:
```php
if (WSDB::isRegistered('analytics')) {
$database = WSDB::on('analytics');
}
```
### register(DatabaseConnection $connection, string $name = 'default'): void
Регистрирует дополнительное подключение:
```php
$connection = DatabaseConnection::connect('localhost', 'analytics', 'user', 'password', 'ANALYTICS_');
WSDB::register($connection, 'analytics');
```
После регистрации запросы выполняются через выбранное подключение:
```php
$events = WSDB::on('analytics')->fetchAllFrom('events', ['id', 'name']);
```
Имя подключения приводится к нижнему регистру. Оно должно начинаться с латинской буквы или цифры и может содержать цифры, `_` и `-`.
## Получение данных
| Метод | Возвращает | Описание |
|---|---|---|
| `fetchOne()` | `array\|null` | Возвращает первую найденную строку. |
| `fetchAll()` | `array` | Возвращает строки по условиям. |
| `fetchGroupedRepresentatives()` | `array` | Возвращает одну представительную строку из каждой группы. |
| `fetchAllFrom()` | `array` | Возвращает все строки таблицы. |
| `count()` | `int` | Возвращает количество строк. |
| `countDistinct()` | `int` | Возвращает количество уникальных значений столбца. |
### fetchOne(string $table, array $where, array $columns = ['*'], ?array $order = null, array $jsonFields = []): ?array
```php
$user = WSDB::fetchOne(
'user',
['id' => 7],
['id', 'login', 'email']
);
```
Если строка не найдена, возвращается `null`.
### fetchAll(string $table, array $where, array $columns = ['*'], ?array $order = null, ?int $limit = null, ?int $offset = null, array $jsonFields = []): array
```php
$posts = WSDB::fetchAll(
table: 'post_news',
where: ['status' => 'publish'],
columns: ['id', 'title'],
order: ['publish_date' => 'DESC'],
limit: 20
);
```
Условия обязательны. `offset` можно использовать только вместе с `limit`.
### fetchGroupedRepresentatives(string $table, string $groupColumn, string $preferredColumn, mixed $preferredValue, array $where = [], array $columns = ['*'], ?array $order = null, ?int $limit = null, ?int $offset = null, array $jsonFields = []): array
Возвращает одну строку из каждой группы, отдавая предпочтение заданному значению:
```php
$posts = WSDB::fetchGroupedRepresentatives(
table: 'post_news',
groupColumn: 'translation_key',
preferredColumn: 'language',
preferredValue: 'ru',
where: ['status' => 'publish'],
columns: ['id', 'title', 'language', 'translation_key'],
order: ['id' => 'DESC'],
limit: 20
);
```
Сначала применяются условия `where`, затем строки объединяются по `groupColumn`. Если приоритетному значению соответствуют несколько строк, выбирается строка с наименьшим `id` среди них. Если совпадений нет, выбирается строка с наименьшим `id` во всей группе.
Таблица должна содержать столбец `id`. Сортировка, ограничение и смещение применяются к уже выбранным строкам. `offset` можно использовать только вместе с `limit`.
### fetchAllFrom(string $table, array $columns = ['*'], ?array $order = null, array $jsonFields = []): array
Используйте этот метод для выборки без условий:
```php
$languages = WSDB::fetchAllFrom(
'languages',
['id', 'code', 'name'],
['id' => 'ASC']
);
```
### count(string $table, array $where = []): int
```php
$total = WSDB::count(
'page',
['status' => 'publish']
);
```
Без условий подсчитываются все строки таблицы:
```php
$total = WSDB::count('page');
```
### countDistinct(string $table, string $column, array $where = []): int
Возвращает количество уникальных значений столбца:
```php
$total = WSDB::countDistinct(
'post_news',
'translation_key',
['status' => 'publish']
);
```
Без условий проверяются все строки таблицы. Значения `null` при подсчёте не учитываются.
## Условия
Простое значение проверяет равенство:
```php
$where = ['status' => 'publish'];
```
Поддерживаемые операторы:
| Оператор | Описание |
|---|---|
| `in` | Значение входит в список. |
| `like` | Сравнение через `LIKE`. |
| `>` | Больше. |
| `<` | Меньше. |
| `>=` | Больше или равно. |
| `<=` | Меньше или равно. |
| `!=` | Не равно. |
| `is-null` | Значение равно `NULL`. |
| `is-not-null` | Значение не равно `NULL`. |
| `json-search` | Поиск значения внутри JSON-массива. |
```php
$pages = WSDB::fetchAll(
'page',
[
'status' => [
'in' => ['publish', 'draft'],
],
]
);
```
Для объединения групп доступны `$or` и `$and`:
```php
$users = WSDB::fetchAll(
'user',
[
'$or' => [
['role' => 'admin'],
['role' => 'editor'],
],
]
);
```
## Сортировка
Сортировка передаётся массивом `поле => направление`:
```php
$order = [
'publish_date' => 'DESC',
'id' => 'ASC',
];
```
Поддерживаются только `ASC` и `DESC`.
## Выбор столбцов
По умолчанию возвращаются все столбцы. Для ограничения результата передайте список:
```php
$page = WSDB::fetchOne(
'page',
['id' => 15],
['id', 'title', 'url']
);
```
Для псевдонима используйте `исходное поле => новое имя`:
```php
$page = WSDB::fetchOne(
'page',
['id' => 15],
[
'title' => 'name',
]
);
```
## Изменение данных
| Метод | Возвращает | Описание |
|---|---|---|
| `insert()` | `int` | Добавляет строку и возвращает её идентификатор. |
| `update()` | `int` | Обновляет строки и возвращает их количество. |
| `increment()` | `int` | Увеличивает числовое значение и возвращает количество изменённых строк. |
| `upsert()` | `int` | Добавляет или обновляет строку. |
| `delete()` | `int` | Удаляет строки и возвращает их количество. |
### insert(string $table, array $data): int
```php
$id = WSDB::insert(
'user',
[
'login' => 'new-user',
'email' => 'user@example.com',
'role' => 'user',
]
);
```
### update(string $table, array $data, array $where): int
```php
$updated = WSDB::update(
'page',
['status' => 'publish'],
['id' => 15]
);
```
### increment(string $table, string $column, array $where, int $amount = 1): int
Увеличивает значение числового столбца и возвращает количество изменённых строк:
```php
$updated = WSDB::increment(
'post_news',
'views',
['id' => 15]
);
```
По умолчанию значение увеличивается на `1`. Другую величину можно передать через `amount`:
```php
$updated = WSDB::increment(
'post_news',
'views',
['id' => 15],
5
);
```
Изменение выполняется одним запросом без предварительного получения текущего значения. Если столбец содержит `null`, исходным значением считается `0`.
Условия `where` обязательны. Значение `amount` должно быть больше `0`; уменьшение значений метод не поддерживает.
### upsert(string $table, array $data, array $update = []): int
```php
$id = WSDB::upsert(
'options',
[
'type' => 'global',
'name' => 'sitename',
'value' => 'Мой сайт',
],
[
'value' => 'Мой сайт',
]
);
```
Метод обновляет строку при конфликте уникального ключа.
### delete(string $table, array $where): int
```php
$deleted = WSDB::delete(
'page',
['id' => 15]
);
```
Удаление без условий запрещено.
## JSON-поля
Для преобразования JSON-полей в массивы передайте их через `jsonFields`:
```php
$page = WSDB::fetchOne(
table: 'page',
where: ['id' => 15],
columns: ['id', 'meta'],
jsonFields: ['meta']
);
```
Пустое значение преобразуется в пустой массив.
### updateJson(string $table, string $jsonColumn, array $set, array $where): int
Обновляет отдельные значения JSON-поля:
```php
$updated = WSDB::updateJson(
'user',
'meta',
[
'profile.name' => 'Иван',
'profile.phone' => '+375000000000',
],
['id' => 7]
);
```
### upsertJson(string $table, array $keyData, string $jsonColumn, array $jsonSet): int
Создаёт строку или обновляет отдельные значения JSON-поля:
```php
$id = WSDB::upsertJson(
'options',
[
'type' => 'themes',
'name' => 'example',
],
'value',
[
'color' => '#1251b7',
]
);
```
Массивы, переданные в обычные методы записи, автоматически сохраняются как JSON.
## Транзакции
### transaction(callable $callback): mixed
Выполняет несколько операций как единое целое:
```php
$pageId = WSDB::transaction(function (Database $database) {
$pageId = $database->insert('page', ['title' => 'Новая страница', 'status' => 'draft']);
$database->insert('page_meta', ['page_id' => $pageId, 'name' => 'layout', 'value' => 'default']);
return $pageId;
});
```
Если callback завершился успешно, транзакция сохраняется. Если возникло исключение, изменения отменяются, а исключение передаётся вызывающему коду.
Вложенные транзакции не поддерживаются. Изменение структуры таблиц внутри транзакции использовать нельзя.
## Блокировка операций
### withAdvisoryLock(string $name, int $timeout, callable $callback): mixed
Не позволяет нескольким процессам одновременно выполнять одну операцию:
```php
$result = WSDB::withAdvisoryLock('product-import', 10, function (Database $database) {
return $database->fetchAllFrom('products');
});
```
`$timeout` задаёт время ожидания блокировки в секундах. Блокировка освобождается после завершения callback, в том числе при возникновении исключения.
Имя блокировки должно содержать от 1 до 64 латинских букв, цифр или символов `_`, `.`, `:`, `-`.
## Информация о базе данных
| Метод | Возвращает | Описание |
|---|---|---|
| `getPrefix()` | `string` | Возвращает префикс таблиц подключения. |
| `getServerVersion()` | `string` | Возвращает версию сервера базы данных. |
| `listTables()` | `array` | Возвращает список таблиц. |
| `describeTable(string $table)` | `array` | Возвращает описание столбцов таблицы. |
| `showIndexes(string $table)` | `array` | Возвращает индексы таблицы. |
| `tableExists(string $table)` | `bool` | Проверяет существование таблицы. |
| `columnExists(string $table, string $column)` | `bool` | Проверяет существование столбца. |
| `indexExists(string $table, string $index)` | `bool` | Проверяет существование индекса. |
Имена таблиц передаются без системного префикса:
```php
if (WSDB::tableExists('page')) {
$columns = WSDB::describeTable('page');
}
```
## Префикс таблиц
Передавайте имя таблицы без системного префикса:
```php
$page = WSDB::fetchOne('page', ['id' => 15]);
```
Префикс текущего подключения добавляется автоматически.
## Исключения
| Исключение | Когда возникает |
|---|---|
| `InvalidArgumentException` | Передано недопустимое имя, пустые данные или неверный аргумент запроса. |
| `LogicException` | Подключение отсутствует, уже зарегистрировано или выполняется вложенная транзакция либо блокировка. |
| `RuntimeException` | Не удалось подключиться, завершить транзакцию или получить блокировку. |
| `BadMethodCallException` | Через `WSDB` вызван неизвестный метод `Database`. |
| `PDOException` | Сервер базы данных отклонил запрос. |
| `JsonException` | Переданное значение невозможно преобразовать в JSON. |
## Важные замечания
- не создавайте экземпляр `WSDB`
- основное подключение регистрируется CMS автоматически
- статические методы используют основное подключение
- для дополнительного подключения используйте `WSDB::on($name)`
- `fetchOne()`, `fetchAll()`, `update()`, `increment()` и `delete()` требуют непустые условия
- для получения всех строк используйте `fetchAllFrom()`
- `count()` без условий подсчитывает все строки таблицы
- значения запросов передаются через подготовленные выражения
- имена таблиц и столбцов должны задаваться разработчиком
WSMailer
Путь: api/classes/wsmailer
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: WSMailer
slug: wsmailer
doc-id: wsmailer
lang: ru
version: v0.87
section: api
type: classes
status: stable
description: Класс для отправки email сообщений через SMTP или mail().
introduced-in: 0.87
---
# WSMailer
`WSMailer` — встроенный почтовый класс CMS WebSource для отправки email сообщений через SMTP или встроенную функцию PHP `mail()`.
## Поддерживает
- отправку через SMTP с авторизацией
- автоматический fallback на `mail()`, если SMTP недоступен
- текстовые и HTML-письма
- автоматическую генерацию текстовой версии для HTML-писем
- вложения
- MIME-заголовки и кодировку UTF-8
- проверку SMTP-соединения через `ping()`
- получение информации о последнем транспорте и SMTP-ошибке
## Быстрый старт
```php
$mailer = new WSMailer([
'smtp-host' => 'smtp.example.com',
'smtp-login' => 'robot@example.com',
'smtp-pass' => 'secret',
'from-email' => 'robot@example.com',
'from-name' => 'WebSource',
'smtp-secure' => 'tls',
'smtp-port' => 587
]);
$mailer->sendHtml(
'user@example.com',
'Добро пожаловать',
'<h1>Здравствуйте!</h1><p>Ваш аккаунт создан.</p>'
);
```
## Конфигурация
Конфигурация формируется из двух источников:
- настроек из базы данных `options` с типом `email`
- массива `$config`, переданного в `__construct()`
Переданные параметры объединяются с настройками из базы данных. Для предсказуемого переопределения используйте те же имена ключей, которые сохранены в настройках.
### Параметры конфигурации
| Параметр | Тип | Описание |
|----------|-----|----------|
| `smtp` / `smtp-host` | `string` | Адрес SMTP-сервера. |
| `login` / `smtp-login` | `string` | Логин SMTP. |
| `pass` / `smtp-pass` | `string` | Пароль SMTP. |
| `email` / `from-email` | `string` | Email отправителя. Обязателен в итоговой конфигурации. |
| `name` / `from-name` | `string` | Имя отправителя. |
| `reply-to` | `string` | Email для ответа. По умолчанию совпадает с `from-email`. |
| `smtp-secure` | `string` | Тип шифрования: `ssl`, `tls` или пустое значение. |
| `smtp-port` | `number` | Порт SMTP. По умолчанию `465` для `ssl`, в остальных случаях `587`. |
| `charset` / `input-charset` | `string` | Исходная кодировка текста. По умолчанию `utf-8`. |
| `timeout` | `number` | Таймаут SMTP-соединения в секундах. Минимум `5`. |
| `ehlo-host` | `string` | Значение для команды `EHLO`. Если не задано, вычисляется автоматически. |
Если `smtp-secure` не задан, порт `465` автоматически включает `ssl`, а порт `587` включает `tls`. Для другого порта пустое значение оставляет соединение без шифрования.
## Инициализация
### __construct(array $config = [])
Создаёт экземпляр класса и подготавливает итоговую конфигурацию.
```php
$mailer = new WSMailer();
```
```php
$mailer = new WSMailer([
'from-email' => 'robot@example.com',
'from-name' => 'WebSource'
]);
```
## Отправка писем
### sendText(string $to, string $subject, string $text, array $attachments = []) : void
Отправляет текстовое письмо.
Параметры:
| Параметр | Тип | Описание |
|----------|-----|----------|
| `to` | `string` | Email получателя. |
| `subject` | `string` | Тема письма. |
| `text` | `string` | Текст письма. |
| `attachments` | `array` | Массив вложений. |
Пример:
```php
$mailer->sendText(
'user@example.com',
'Проверка почты',
'Это тестовое письмо.'
);
```
### sendHtml(string $to, string $subject, string $html, array $attachments = [], ?string $text = null) : void
Отправляет HTML-письмо.
Параметры:
| Параметр | Тип | Описание |
|----------|-----|----------|
| `to` | `string` | Email получателя. |
| `subject` | `string` | Тема письма. |
| `html` | `string` | HTML-содержимое письма. |
| `attachments` | `array` | Массив вложений. |
| `text` | `string\|null` | Текстовая версия письма. Если не передана, будет создана автоматически из HTML. |
Пример:
```php
$html = $mailer->mailHtmlTemplate(
'<h1>Восстановление доступа</h1><p>Перейдите по ссылке для продолжения.</p>',
'Если вы не запрашивали это письмо, просто проигнорируйте его.'
);
$mailer->sendHtml(
'user@example.com',
'Восстановление доступа',
$html
);
```
## Проверка соединения
### ping() : void
Проверяет доступность SMTP-сервера.
Если SMTP не настроен, метод просто завершится без ошибки.
Пример:
```php
$mailer->ping();
```
## Получение состояния
### getLastTransport() : string
Возвращает транспорт, через который было отправлено последнее письмо.
Возможные значения:
- `smtp`
- `mail`
Пример:
```php
$mailer->sendText('user@example.com', 'Test', 'Hello');
$transport = $mailer->getLastTransport();
```
### getLastSmtpError() : ?string
Возвращает текст последней SMTP-ошибки, если во время отправки через SMTP произошёл сбой.
Если SMTP-ошибки не было, возвращает `null`.
Пример:
```php
try {
$mailer->sendText('user@example.com', 'Test', 'Hello');
} catch (Throwable $e) {
$smtpError = $mailer->getLastSmtpError();
}
```
## HTML-шаблон письма
### mailHtmlTemplate(string $html, ?string $footerText = null) : string
Формирует HTML-обёртку письма в стиле WebSource.
Параметры:
| Параметр | Тип | Описание |
|----------|-----|----------|
| `html` | `string` | Основное HTML-содержимое письма. |
| `footerText` | `string\|null` | Текст в нижней части письма. |
Возвращает:
| Параметр | Тип | Описание |
|----------|-----|----------|
| `return` | `string` | Готовый HTML-шаблон письма. |
Пример:
```php
$html = $mailer->mailHtmlTemplate(
'<h1>Добро пожаловать</h1><p>Спасибо за регистрацию.</p>',
'Команда WebSource'
);
```
## Вложения
Каждое вложение передаётся как элемент массива.
Формат:
```php
[
'path' => '/absolute/path/to/file.pdf',
'name' => 'manual.pdf',
'mime' => 'application/pdf'
]
```
Поддерживаемые ключи:
| Ключ | Тип | Описание |
|------|-----|----------|
| `path` / `url` | `string` | Путь к файлу. Обязательный параметр. |
| `name` | `string` | Имя файла в письме. Если не задано, используется имя исходного файла. |
| `mime` / `type` | `string` | MIME-тип файла. Если не задан, определяется автоматически. |
Пример:
```php
$mailer->sendText(
'user@example.com',
'Документы',
'Во вложении находится файл.',
[
[
'path' => '/var/www/files/report.pdf',
'name' => 'report.pdf',
'mime' => 'application/pdf'
]
]
);
```
## Исключения
Класс может выбрасывать стандартные исключения PHP:
| Исключение | Когда возникает |
|------------|-----------------|
| `InvalidArgumentException` | Неверный email, пустая тема, неверная конфигурация, отсутствует путь к вложению. |
| `RuntimeException` | Не удалось подключиться к SMTP, прочитать вложение, записать данные в сокет или отправить письмо через `mail()`. |
## Ограничения и замечания
- класс работает только с одним получателем за один вызов
- в публичном API нет отдельных методов для `CC` и `BCC`
- SMTP-аутентификация реализована через `AUTH LOGIN`
- `ping()` проверяет соединение и запуск TLS, но не проверяет SMTP-авторизацию и отправку письма
- при HTML-отправке текстовая версия письма создаётся автоматически, если `text` не передан
- вложения должны существовать на диске и быть доступны для чтения
- если `from-email` не задан явно, класс пытается определить его из `smtp-login` или `sendmail_from`
## Что использовать
Используйте `sendText()`, если:
- письмо должно содержать только обычный текст
- не нужна HTML-вёрстка
Используйте `sendHtml()`, если:
- письмо должно содержать HTML-разметку
- нужна шаблонная обёртка письма
- нужна автоматическая текстовая версия
WSUrl
Путь: api/classes/wsurl
Версия документа: 0.973
Статус: deprecated
Открыть документ
---
title: WSUrl
slug: wsurl
doc-id: wsurl
lang: ru
version: v0.89
section: api
type: classes
status: deprecated
introduced-in: 0.8
deprecated-in: 0.89
description: Устаревший класс для разбора произвольного URL.
---
# WSUrl
`WSUrl` является устаревшим классом и не должен использоваться в новом коде.
Единой полной замены у класса нет:
- для URL текущего запроса используйте `CurrentUrl`
- для разбора произвольного URL используйте нативные функции PHP
## URL текущего запроса
`CurrentUrl` предоставляет уже разобранные данные текущего HTTP-запроса:
```php
$url = CurrentUrl::url();
$host = CurrentUrl::host();
$path = CurrentUrl::path();
$segment = CurrentUrl::segment(0);
$parameter = CurrentUrl::parameter('page');
```
`CurrentUrl` учитывает обычные и AJAX-запросы WebSource, но не принимает произвольный URL для разбора.
## Произвольный URL
Для произвольного URL используйте `parse_url()`:
```php
$url = 'https://example.com/catalog/item?page=2';
$parts = parse_url($url);
if ($parts === false) {
return;
}
$scheme = (string) ($parts['scheme'] ?? '');
$host = (string) ($parts['host'] ?? '');
$path = trim((string) ($parts['path'] ?? ''), '/');
```
Query-строку можно разобрать через `parse_str()`:
```php
$parameters = [];
parse_str(
(string) ($parts['query'] ?? ''),
$parameters
);
$page = $parameters['page'] ?? null;
```
`parse_url()` выполняет разбор, но не подтверждает безопасность или допустимость внешнего URL. Проверяйте входные данные отдельно.
## Сохранённый API
Класс остаётся доступным для поддержки старого кода.
| Метод | Назначение |
|---|---|
| `host()` | Возвращает хост. |
| `scheme()` | Возвращает схему. |
| `fullHost()` | Возвращает схему и хост. |
| `url()` | Возвращает сформированный URL. |
| `path()` | Возвращает путь. |
| `fullPath()` | Возвращает URL без query-строки. |
| `query()` | Возвращает query-строку. |
| `getParameter()` | Возвращает обработанный query-параметр. |
| `getOriginalParameter()` | Возвращает исходный query-параметр. |
| `getPathPart()` | Возвращает сегмент пути. |
| `getPostType()` | Возвращает путь без последнего сегмента. |
| `getPageUrl()` | Возвращает последний сегмент пути. |
| `getBaseUrl()` | Возвращает путь URL. |
## Ограничения legacy API
- конструктор ожидает абсолютный URL со схемой и хостом
- неполный или некорректный URL может вызвать предупреждение PHP
- весь URL декодируется до вызова `parse_url()`
- путь приводится к нижнему регистру
- query-строка разбирается простым разделением по `&` и `=`
- массивы и сложные query-параметры не поддерживаются
- отсутствующий параметр в `getOriginalParameter()` вызывает предупреждение
- порт URL не сохраняется при повторном формировании адреса
- `getOriginalParameter()` возвращает значение без дополнительной обработки
- для нового кода используйте `CurrentUrl` или нативные функции PHP
DOM Events
Путь: api/modules/dom-events
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: DOM Events
slug: dom-events
doc-id: dom-events
lang: ru
version: v0.95
section: api
type: modules
status: stable
description: Делегирование DOM-событий через области, действия и единый обработчик.
---
# DOM Events
`DOM Events` делегирует события от общего корневого элемента и связывает их с областями и действиями, заданными через HTML-атрибуты.
Для работы используется класс `DOMEvents`.
## Поддерживает
- делегирование событий от одного корневого элемента
- обработку динамически добавленных элементов
- разделение интерфейса на области и действия
- несколько обработчиков одного действия
- глобальные обработчики событий
- удаление отдельных или всех обработчиков
- автоматическое удаление неиспользуемых DOM-слушателей
- собственные названия HTML-атрибутов
- полное уничтожение экземпляра
## Подключение
В JavaScript-модуле темы импортируйте `DOMEvents` из ядра:
```js
const { DOMEvents } = await import(
`${window.wsSite.coreUrl}/assets/js/dom-events.js`
);
```
Создайте экземпляр:
```js
const events = new DOMEvents(document);
```
`window.wsSite.coreUrl` создаётся при выводе `CurrentTheme::getJS()`.
## Быстрый старт
Добавьте область и действие в HTML:
```html
<div data-ws-scope="catalog">
<button type="button" data-ws-action="open">
Открыть каталог
</button>
</div>
```
Зарегистрируйте обработчик:
```js
events.on('click', 'catalog', 'open', (event, button) => {
console.log(button);
});
```
Обработчик сработает при клике по кнопке или по вложенному в неё элементу.
## Области и действия
По умолчанию используются два атрибута:
| Атрибут | Назначение |
|---|---|
| `data-ws-scope` | Область интерфейса. |
| `data-ws-action` | Действие внутри области. |
Пример:
```html
<section data-ws-scope="profile">
<button type="button" data-ws-action="edit">
Редактировать
</button>
<button type="button" data-ws-action="delete">
Удалить
</button>
</section>
```
Регистрация разных действий одной области:
```js
events.on('click', 'profile', 'edit', (event, button) => {
console.log('Редактирование', button);
});
events.on('click', 'profile', 'delete', (event, button) => {
console.log('Удаление', button);
});
```
Названия областей и действий сравниваются как обычные строки и должны совпадать с HTML-атрибутами.
## Делегирование событий
Для каждого типа события экземпляр добавляет один слушатель к корневому элементу.
Когда событие достигает корня, модуль:
1. Находит ближайший элемент с атрибутом области.
2. Получает значение области.
3. Находит ближайший элемент с атрибутом действия.
4. Получает название действия.
5. Вызывает подходящие обработчики.
6. Вызывает глобальные обработчики этого типа события.
Поиск выполняется через `closest()` от `event.target`.
Благодаря делегированию обработчики работают и для элементов, добавленных после создания экземпляра:
```js
events.on('click', 'notifications', 'close', (event, button) => {
button.closest('.notification')?.remove();
});
document.body.insertAdjacentHTML(
'beforeend',
`
<div class="notification" data-ws-scope="notifications">
Сообщение
<button type="button" data-ws-action="close">Закрыть</button>
</div>
`
);
```
Повторно регистрировать обработчик не нужно.
## Создание экземпляра
### constructor(root = document, options = {})
Параметры:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| `root` | `Document \| Element \| Window` | `document` | Объект, на котором размещаются DOM-слушатели. |
| `options` | `object` | `{}` | Настройки атрибутов. |
Пример для отдельного контейнера:
```js
const modal = document.querySelector('[data-modal]');
const modalEvents = new DOMEvents(modal);
```
События должны доходить до переданного корневого объекта.
## Собственные атрибуты
Названия атрибутов можно изменить:
```js
const events = new DOMEvents(document, {
scopeAttribute: 'data-app-scope',
actionAttribute: 'data-app-action'
});
```
HTML:
```html
<div data-app-scope="dialog">
<button type="button" data-app-action="close">
Закрыть
</button>
</div>
```
Обработчик:
```js
events.on('click', 'dialog', 'close', () => {
console.log('Диалог закрыт');
});
```
### Параметры options
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| `scopeAttribute` | `string` | `data-ws-scope` | Атрибут области. |
| `actionAttribute` | `string` | `data-ws-action` | Атрибут действия. |
Пустая строка не заменяет стандартное значение.
## Обработчик действия
### on(type, scope, action, handler)
Регистрирует обработчик действия:
```js
events.on('click', 'catalog', 'open', (event, actionTarget) => {
actionTarget.classList.add('active');
});
```
Параметры:
| Параметр | Тип | Описание |
|---|---|---|
| `type` | `string` | Тип DOM-события. |
| `scope` | `string` | Значение атрибута области. |
| `action` | `string` | Значение атрибута действия. |
| `handler` | `function` | Функция-обработчик. |
Обработчик получает:
| Аргумент | Тип | Описание |
|---|---|---|
| `event` | `Event` | Исходное DOM-событие. |
| `actionTarget` | `Element \| null` | Ближайший элемент с атрибутом действия. |
Метод возвращает текущий экземпляр `DOMEvents`, поэтому вызовы можно объединять:
```js
events
.on('click', 'dialog', 'open', openDialog)
.on('click', 'dialog', 'close', closeDialog);
```
## Несколько обработчиков
Для одного сочетания события, области и действия можно зарегистрировать несколько функций:
```js
events.on('click', 'cart', 'add', updateCart);
events.on('click', 'cart', 'add', showNotification);
```
Они вызываются в порядке регистрации.
Одинаковая функция также может быть зарегистрирована несколько раз. Каждый зарегистрированный обработчик будет вызван отдельно.
## Действие без атрибута
Пустая строка действия позволяет обработать событие внутри области, если ближайший элемент действия не найден:
```js
events.on('click', 'site-header', '', (event) => {
if (event.target.closest('nav a')) {
console.log('Переход по ссылке меню');
}
});
```
Если найден элемент с непустым `data-ws-action`, обработчик пустого действия не вызывается.
## Удаление обработчика
### off(type, scope, action, handler = null)
Удаляет зарегистрированный обработчик:
```js
function handleOpen(event, button) {
button.classList.add('active');
}
events.on('click', 'catalog', 'open', handleOpen);
events.off('click', 'catalog', 'open', handleOpen);
```
Для удаления конкретного обработчика необходимо передать ту же функцию, которая использовалась при регистрации.
Анонимную функцию нельзя удалить через другую анонимную функцию:
```js
events.on('click', 'catalog', 'open', () => {
console.log('Открытие');
});
```
Если четвёртый аргумент не передан, удаляются все обработчики выбранного события, области и действия:
```js
events.off('click', 'catalog', 'open');
```
Метод возвращает текущий экземпляр.
Когда для типа события больше не остаётся обработчиков, соответствующий DOM-слушатель удаляется с корневого объекта.
## Глобальный обработчик
### onGlobal(type, handler)
Глобальный обработчик получает каждое событие указанного типа, дошедшее до корневого объекта:
```js
events.onGlobal('click', (event, meta) => {
console.log(meta);
});
```
Он вызывается после обработчиков области и действия.
Обработчик получает исходное событие и объект `meta`.
### Объект meta
| Свойство | Тип | Описание |
|---|---|---|
| `scope` | `string` | Найденная область или пустая строка. |
| `action` | `string` | Найденное действие или пустая строка. |
| `matched` | `boolean` | Был ли найден хотя бы один обработчик действия. |
| `actionTarget` | `Element \| null` | Элемент с атрибутом действия. |
Пример закрытия меню по клику снаружи:
```js
events.onGlobal('click', (event, meta) => {
const menu = document.querySelector('[data-menu]');
if (!menu?.classList.contains('open')) {
return;
}
if (meta.matched || menu.contains(event.target)) {
return;
}
menu.classList.remove('open');
});
```
`matched` сообщает о наличии подходящих обработчиков, но не означает, что обработчик изменил интерфейс или отменил событие.
## Удаление глобального обработчика
### offGlobal(type, handler = null)
Удаляет глобальный обработчик:
```js
function handleKeydown(event) {
if (event.key === 'Escape') {
console.log('Закрытие');
}
}
events.onGlobal('keydown', handleKeydown);
events.offGlobal('keydown', handleKeydown);
```
Если функция не передана, удаляются все глобальные обработчики этого типа:
```js
events.offGlobal('keydown');
```
Метод возвращает текущий экземпляр.
DOM-слушатель удаляется только тогда, когда для типа события не осталось ни глобальных обработчиков, ни обработчиков действий.
## События клавиатуры
Для интерактивных элементов можно зарегистрировать несколько типов событий:
```html
<div
data-ws-scope="site-header"
data-ws-action="menu-toggle"
role="button"
tabindex="0"
aria-expanded="false"
>
Меню
</div>
```
```js
function toggleMenu() {
console.log('Переключение меню');
}
events.on('click', 'site-header', 'menu-toggle', () => {
toggleMenu();
});
events.on('keydown', 'site-header', 'menu-toggle', (event) => {
if (event.key !== 'Enter' && event.key !== ' ') {
return;
}
event.preventDefault();
toggleMenu();
});
```
Модуль не вызывает `preventDefault()` автоматически.
## Глобальные события Window
Экземпляр можно создать для `window`:
```js
const windowEvents = new DOMEvents(window);
windowEvents.onGlobal('scroll', () => {
console.log(window.scrollY);
});
windowEvents.onGlobal('resize', () => {
console.log(window.innerWidth);
});
```
Для событий `scroll` и `resize` обычно используются глобальные обработчики, поскольку их `event.target` не обязан быть DOM-элементом.
## Уничтожение экземпляра
### destroy()
Удаляет все DOM-слушатели, зарегистрированные экземпляром, и очищает обработчики:
```js
events.destroy();
```
После уничтожения экземпляр больше не обрабатывает ранее зарегистрированные события.
Если экземпляр больше не нужен, вызывайте `destroy()` при удалении связанного интерфейса:
```js
class Dialog {
constructor(root) {
this.events = new DOMEvents(root);
}
init() {
this.events.on('click', 'dialog', 'close', () => {
this.close();
});
}
destroy() {
this.events.destroy();
}
close() {
console.log('Закрытие');
}
}
```
## Порядок выполнения
Для одного события обработчики вызываются в следующем порядке:
1. Обработчики подходящего действия в порядке регистрации.
2. Глобальные обработчики в порядке регистрации.
Возвращаемое значение обработчика не влияет на дальнейший вызов функций.
Асинхронные обработчики запускаются как обычные функции и не ожидаются модулем.
## Поддерживаемые события
`DOMEvents` использует стандартный `addEventListener()` и не ограничивает список типов событий.
Для делегирования подходят события, которые всплывают до корневого элемента:
- `click`
- `input`
- `change`
- `keydown`
- `keyup`
- `pointerdown`
- `pointermove`
- `pointerup`
- `mouseover`
- `mouseout`
- `focusin`
- `focusout`
События `focus`, `blur`, `mouseenter` и `mouseleave` обычно не всплывают. Для делегирования используйте их всплывающие аналоги.
## Важные замечания
- один экземпляр добавляет не более одного DOM-слушателя каждого типа
- модуль не изменяет DOM самостоятельно
- модуль не вызывает `preventDefault()` или `stopPropagation()`
- обработчик должен быть функцией
- для удаления конкретного обработчика сохраняйте ссылку на функцию
- события должны доходить до корневого объекта
- обработчик, вызвавший `stopPropagation()` ниже корня, может не дать событию попасть в модуль
- параметры `capture`, `passive`, `once` и `signal` не поддерживаются
- вложенные элементы действий разрешаются через ближайший `data-ws-action`
- область и действие определяются независимо через `closest()`
WS Slider
Путь: api/modules/ws-slider
Версия документа: 0.973
Статус: stable
Открыть документ
---
title: WS Slider
slug: ws-slider
doc-id: ws-slider
lang: ru
version: v0.88
section: api
type: modules
status: stable
description: Модуль для создания слайдеров и непрерывных горизонтальных лент.
introduced-in: 0.87
---
# WS Slider
`WS Slider` создаёт слайдеры с пошаговым переключением или непрерывным движением элементов.
## Поддерживает
- режимы `carousel` и `ticker`
- слайды фиксированной или собственной ширины
- циклическое переключение
- автоматическое переключение слайдов
- пагинацию и кнопки навигации
- управление свайпом
- адаптивные параметры
- паузу при наведении и взаимодействии
- автоматическое обновление при изменении размеров
- переопределение селекторов DOM-элементов
## Подключение
Импортируйте функцию `wsSlider` из начального файла модуля:
```js
import { wsSlider } from '/core/modules/ws-slider/assets/js/initial.js';
```
## Быстрый старт
Подготовьте корневой элемент, видимую область и дорожку со слайдами:
```html
<div class="slider" data-slider>
<div class="slider-viewport" data-slider-viewport>
<div class="slider-track" data-slider-track>
<div class="slider-slide" data-slider-slide>Первый слайд</div>
<div class="slider-slide" data-slider-slide>Второй слайд</div>
<div class="slider-slide" data-slider-slide>Третий слайд</div>
</div>
</div>
<button type="button" data-slider-prev>Назад</button>
<button type="button" data-slider-next>Вперёд</button>
<div data-slider-pagination></div>
</div>
```
Скройте содержимое за пределами видимой области:
```css
.slider-viewport {
overflow: hidden;
}
```
Передайте корневой элемент и параметры в `wsSlider()`:
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'carousel',
autoWidth: false,
perView: 1,
gap: 20,
loop: true,
swipe: true
});
```
При `autoWidth: false` ширина слайдов рассчитывается по значению `perView`.
## HTML-структура
Корневой элемент передаётся первым аргументом в `wsSlider()` и не требует обязательного data-атрибута.
Обязательные элементы:
- `data-slider-viewport` — видимая область слайдера
- `data-slider-track` — дорожка со слайдами
- `data-slider-slide` — один или несколько слайдов
Необязательные элементы:
- `data-slider-prev` — кнопка перехода назад
- `data-slider-next` — кнопка перехода вперёд
- `data-slider-pagination` — контейнер пагинации
Модуль самостоятельно создаёт кнопки внутри контейнера пагинации.
Стандартные селекторы можно изменить через параметр `selectors`.
## Параметры
### Общие параметры
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| `mode` | `string` | `carousel` | Режим работы: `carousel` или `ticker`. |
| `gap` | `number` | `0` | Расстояние между слайдами в пикселях. |
| `breakpoints` | `object` | `{}` | Адаптивные параметры по ширине окна. |
| `pauseOnHover` | `boolean` | `true` | Приостанавливает autoplay или движение ticker при наведении. |
| `pauseOnInteraction` | `boolean` | `true` | Учитывает взаимодействие пользователя при управлении движением. |
| `selectors` | `object` | стандартные селекторы | Переопределяет селекторы внутренних элементов. |
Если передано неизвестное значение `mode`, используется режим `carousel`.
### Параметры carousel
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| `startIndex` | `number` | `0` | Начальный индекс слайда. |
| `autoWidth` | `boolean` | `true` | Сохраняет собственную ширину каждого слайда. |
| `perView` | `number` | `1` | Количество одновременно видимых слайдов при `autoWidth: false`. |
| `step` | `number \| null` | `null` | Количество слайдов за одно переключение. |
| `transition` | `number` | `400` | Продолжительность анимации в миллисекундах. |
| `loop` | `boolean` | `false` | Включает циклическое переключение. |
| `autoplay` | `boolean` | `false` | Включает автоматическое переключение. |
| `autoplayDelay` | `number` | `3000` | Задержка между переключениями в миллисекундах. |
| `pagination` | `boolean` | `true` | Включает создание и обновление пагинации. |
| `swipe` | `boolean` | `false` | Включает переключение с помощью свайпа. |
| `swipeThreshold` | `number` | `24` | Минимальное горизонтальное смещение для свайпа. |
| `preventScrollOnSwipe` | `boolean` | `true` | Предотвращает прокрутку страницы во время горизонтального свайпа. |
Если `step` не задан:
- при `autoWidth: true` используется шаг `1`
- при `autoWidth: false` используется значение `perView`
Параметр `loop` применяется только при наличии нескольких страниц слайдера.
### Параметры ticker
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| `speed` | `number` | `0.5` | Скорость движения ленты в пикселях за миллисекунду. |
| `direction` | `string` | `left` | Направление движения: `left` или `right`. |
Минимальное значение `speed` после нормализации равно `0.1`.
## Селекторы
Параметр `selectors` позволяет использовать собственные классы или data-атрибуты.
| Свойство | По умолчанию | Назначение |
|---|---|---|
| `viewport` | `[data-slider-viewport]` | Видимая область. |
| `track` | `[data-slider-track]` | Дорожка со слайдами. |
| `slide` | `[data-slider-slide]` | Отдельный слайд. |
| `prev` | `[data-slider-prev]` | Кнопка перехода назад. |
| `next` | `[data-slider-next]` | Кнопка перехода вперёд. |
| `pagination` | `[data-slider-pagination]` | Контейнер пагинации. |
Пример:
```js
wsSlider(document.querySelector('.gallery'), {
selectors: {
viewport: '.gallery-viewport',
track: '.gallery-track',
slide: '.gallery-item',
prev: '.gallery-prev',
next: '.gallery-next',
pagination: '.gallery-pagination'
}
});
```
Обязательными остаются элементы, соответствующие селекторам `viewport`, `track` и `slide`.
## Адаптивные параметры
Ключи объекта `breakpoints` обозначают минимальную ширину окна в пикселях.
В режиме `carousel` можно переопределять:
- `perView`
- `autoWidth`
- `gap`
- `step`
Пример:
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'carousel',
autoWidth: false,
perView: 1,
gap: 12,
breakpoints: {
768: {
perView: 2,
gap: 20
},
1200: {
perView: 3,
gap: 32
}
}
});
```
При ширине окна от `768` пикселей отображаются два слайда, а от `1200` пикселей — три.
В режиме `ticker` через `breakpoints` изменяется только `gap`:
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'ticker',
gap: 16,
breakpoints: {
768: {
gap: 24
},
1200: {
gap: 32
}
}
});
```
## Режим carousel
`carousel` переключает слайды отдельными шагами.
Используйте его, если нужны:
- кнопки перехода назад и вперёд
- пагинация
- автоматическое переключение
- управление свайпом
- отображение заданного количества слайдов
- слайды разной ширины
- циклическое переключение
### Слайды одинаковой ширины
Установите `autoWidth: false` и укажите количество видимых слайдов:
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'carousel',
autoWidth: false,
perView: 3,
step: 1,
gap: 24
});
```
Ширина каждого слайда рассчитывается по ширине видимой области, значению `perView` и расстоянию `gap`.
### Слайды собственной ширины
При `autoWidth: true` модуль сохраняет ширину, заданную стилями слайда:
```css
.slider-slide {
width: 280px;
}
```
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'carousel',
autoWidth: true,
gap: 20
});
```
Этот режим включён по умолчанию.
### Автоматическое переключение
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'carousel',
autoWidth: false,
perView: 1,
autoplay: true,
autoplayDelay: 4000,
pauseOnHover: true
});
```
Autoplay запускается только при наличии нескольких страниц.
## Режим ticker
`ticker` непрерывно перемещает горизонтальную ленту.
Используйте его для:
- логотипов
- карточек партнёров
- коротких сообщений
- непрерывно движущихся списков
Пример:
```js
wsSlider(document.querySelector('[data-slider]'), {
mode: 'ticker',
gap: 32,
speed: 0.5,
direction: 'left',
pauseOnHover: true,
pauseOnInteraction: true
});
```
В режиме `ticker`:
- ширина слайдов определяется их содержимым или CSS
- кнопки навигации отключаются
- пагинация не создаётся
- параметры `autoplay` и `autoplayDelay` не используются
- для непрерывного движения модуль создаёт служебные копии слайдов
## Публичный API
### wsSlider(sliderNode, options)
Создаёт и сразу инициализирует слайдер.
Параметры:
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| `sliderNode` | `Element` | да | Корневой DOM-элемент слайдера. |
| `options` | `object` | нет | Параметры инициализации. |
Функция возвращает инициализированный экземпляр слайдера.
Пример:
```js
import { wsSlider } from '/core/modules/ws-slider/assets/js/initial.js';
wsSlider(document.querySelector('[data-slider]'), {
mode: 'carousel'
});
```
## Ошибки и ограничения
Модуль выбрасывает ошибку, если:
- первым аргументом не передан DOM-элемент
- внутри корневого элемента отсутствует viewport
- внутри корневого элемента отсутствует track
- внутри track отсутствуют слайды
Дополнительные ограничения:
- модуль работает только с горизонтальным расположением слайдов
- CSS-стили внешнего вида необходимо добавлять отдельно
- для скрытия содержимого за пределами слайдера установите `overflow: hidden` у viewport
- автоматического наблюдения за добавлением и удалением слайдов в DOM нет
- адаптивные параметры рассчитываются по ширине окна браузера
- пагинация и кнопки навигации предназначены для режима `carousel`
$WS_Options
Путь: api/variables/ws-options
Версия документа: 0.973
Статус: removed
Открыть документ
---
title: $WS_Options
slug: ws-options
doc-id: ws-options
lang: ru
version: v0.95
section: api
type: variables
status: removed
introduced-in: 0.1
removed-in: 0.95
replacement-title: SiteOptions
replacement-section: api
replacement-type: classes
replacement-slug: site-options
description: Удалённая глобальная переменная настроек CMS.
---
# $WS_Options
Начиная с версии `0.95`, глобальная переменная `$WS_Options` удалена из публичного API.
Для получения глобальных настроек сайта используйте статический класс `SiteOptions`.
## Переход на SiteOptions
Старый вариант:
```php
$siteName = $WS_Options['sitename'] ?? '';
```
Актуальный вариант:
```php
$siteName = SiteOptions::get('sitename');
```
Значение по умолчанию передаётся вторым аргументом:
```php
$siteName = SiteOptions::get(
'sitename',
'Мой сайт'
);
```
## Замена специальных значений
Некоторые значения теперь предоставляет отдельный специализированный API:
| Старый вариант | Актуальный вариант |
|---|---|
| `$WS_Options['siteurl']` | `CurrentUrl::origin()` |
| `$WS_Options['language']` | `CurrentLanguage::code()` |
| `$WS_Options['template']` | `CurrentTheme::directory()` |
| `$WS_Options['sitename']` | `SiteOptions::get('sitename')` |
| `$WS_Options['description']` | `SiteOptions::get('description')` |
| `$WS_Options['debug']` | `SiteOptions::get('debug')` |
| `$WS_Options['rusurl']` | `SiteOptions::get('rusurl')` |
## Важные замечания
- не объявляйте `$WS_Options` через `global`
- не изменяйте настройки через возвращённые значения
- `SiteOptions::get()` возвращает строку
- для отсутствующей настройки используется переданное значение по умолчанию
- `$WS_Options` может временно использоваться внутри ядра для совместимости, но не является частью публичного API
$WS_Theme
Путь: api/variables/ws-theme
Версия документа: 0.973
Статус: removed
Открыть документ
---
title: $WS_Theme
slug: ws-theme
doc-id: ws-theme
lang: ru
version: v0.95
section: api
type: variables
status: removed
introduced-in: 0.7
removed-in: 0.95
replacement-title: CurrentTheme
replacement-type: classes
replacement-slug: current-theme
description: Удалённая глобальная переменная активной темы.
---
# $WS_Theme
Глобальная переменная `$WS_Theme` удалена и недоступна в актуальной версии CMS.
Для работы с активной темой используйте статические методы класса `CurrentTheme`.
## Переход на CurrentTheme
| Устаревший вызов | Актуальный вызов |
|---|---|
| `$WS_Theme->root()` | `CurrentTheme::url()` |
| `$WS_Theme->path()` | `CurrentTheme::path()` |
| `$WS_Theme->header()` | `CurrentTheme::header()` |
| `$WS_Theme->footer()` | `CurrentTheme::footer()` |
| `$WS_Theme->getData($key)` | `CurrentTheme::data($key)` |
| `$WS_Theme->getCSS()` | `echo CurrentTheme::getCSS()` |
| `$WS_Theme->getJS()` | `echo CurrentTheme::getJS()` |
## Подключение шаблона
Старый вариант:
```php
include $WS_Theme->header();
include $WS_Theme->footer();
```
Актуальный вариант:
```php
include CurrentTheme::header();
include CurrentTheme::footer();
```
## Ресурсы темы
Старый вариант формировал URL вручную:
```php
$logo = $WS_Theme->root() . 'assets/images/logo.svg';
```
Используйте `assetUrl()`, который проверяет существование файла и добавляет версию темы:
```php
$logo = CurrentTheme::assetUrl(
'images',
'logo.svg'
);
```
## Настройки темы
Старый вариант:
```php
$logo = $WS_Theme->getData('logo');
```
Актуальный вариант:
```php
$logo = CurrentTheme::data('logo');
```
Для отсутствующего ключа можно указать значение по умолчанию:
```php
$phone = CurrentTheme::data(
'phone',
'Телефон не указан'
);
```
## CSS и JavaScript
Методы `CurrentTheme::getCSS()` и `CurrentTheme::getJS()` возвращают HTML строкой и не выводят её самостоятельно.
```php
echo CurrentTheme::getCSS();
echo CurrentTheme::getJS();
```
## SEO-метаданные
Работа с SEO больше не относится к активной теме.
Используйте данные текущей страницы:
```php
echo PageData::getSeoHead();
echo PageData::getFaviconHead();
```
## Методы без прямой замены
Методы `$WS_Theme->getPanel()` и `$WS_Theme->setMeta()` не входят в API `CurrentTheme`.
`CurrentTheme` предоставляет доступ к файлам и настройкам активной темы, но не изменяет их и не управляет административной панелью.
## Важные замечания
- не проверяйте наличие `$WS_Theme`: переменная больше не создаётся
- не создавайте объект `CurrentTheme`
- используйте только статические методы `CurrentTheme`
- для URL ресурсов используйте `assetUrl()`
- для файловых путей используйте `filePath()` и `directoryPath()`
- для настроек темы используйте `data()`
$WS_User
Путь: api/variables/ws-user
Версия документа: 0.973
Статус: removed
Открыть документ
---
title: $WS_User
slug: ws-user
doc-id: ws-user
lang: ru
version: v0.95
section: api
type: variables
status: removed
removed-in: 0.95
replacement-title: CurrentUser
replacement-section: api
replacement-type: classes
replacement-slug: current-user
description: Удалённая глобальная переменная текущего пользователя.
---
# $WS_User
Начиная с версии `0.95`, глобальная переменная `$WS_User` удалена из публичного API.
Для проверки авторизации и получения данных текущего пользователя используйте статический класс `CurrentUser`.
## Проверка авторизации
Старый вариант:
```php
if (isset($WS_User['id'])) {
// Пользователь авторизован.
}
```
Актуальный вариант:
```php
if (CurrentUser::isAuthenticated()) {
// Пользователь авторизован.
}
```
## Получение данных
Старый вариант:
```php
$userId = $WS_User['id'] ?? 0;
$login = $WS_User['login'] ?? '';
```
Актуальный вариант:
```php
$userId = CurrentUser::get('id', 0);
$login = CurrentUser::get('login', '');
```
## Получение метаданных
Старый вариант:
```php
$phone = $WS_UserMeta['phone'] ?? '';
```
Актуальный вариант:
```php
$phone = CurrentUser::meta('phone', '');
```
## Соответствие вызовов
| Старый вариант | Актуальный вариант |
|---|---|
| `isset($WS_User['id'])` | `CurrentUser::isAuthenticated()` |
| `$WS_User['id']` | `CurrentUser::get('id')` |
| `$WS_User['login']` | `CurrentUser::get('login')` |
| `$WS_User['email']` | `CurrentUser::get('email')` |
| `$WS_User['role']` | `CurrentUser::get('role')` |
| `$WS_User['avatar']` | `CurrentUser::get('avatar')` |
| `$WS_UserMeta[$key]` | `CurrentUser::meta($key)` |
## Важные замечания
- не объявляйте `$WS_User` и `$WS_UserMeta` через `global`
- всегда проверяйте авторизацию перед выполнением защищённого действия
- `CurrentUser` автоматически доступен после запуска CMS
- не создавайте экземпляр `CurrentUser`
- временный массив совместимости содержит не все прежние поля
- наличие `$WS_User` внутри движка не делает переменную частью публичного API