Выпуск CMS «ГИРВАС» от 3 октября 2026 года на этапе разработки «Сегежа».
Последние изменения
QueryBuilder: поддержка JOIN, CASE-выражений, индексов
Реализовано:
- Добавлен Enum
IndexTypeс типами индексов (BTREE,HASH,GIST,GIN,SPGIST,BRIN,FULLTEXT) - Добавлен класс
ClauseJoinдля JOIN-ов вSELECT(INNER,LEFT,RIGHT,FULL) - Реализована адаптивная генерация JOIN-условий для MySQL и PostgreSQL
- Добавлен класс
CaseExpressionдля построения CASE-выражений - Реализованы методы
whenJsonLike()иwhenJsonArrayContains()для JSON-поиска - Добавлен статический метод
CaseExpression::sum() - Добавлен фабричный метод
createCase()вQueryBuilder - Добавлен класс
StatementCreateIndexдляCREATE INDEX - Добавлен класс
StatementDropIndexдляDROP INDEX - Реализована поддержка
UNIQUE,CONCURRENTLY,IF NOT EXISTS/IF EXISTS, частичных индексов сWHERE - Добавлены методы
setStatementCreateIndex()иsetStatementDropIndex() - В
EntryCategoryдобавлено кеширование инициализированных данных
Исправлено:
- Экранирование CASE-выражений в
addSelections()для PostgreSQL
SQL-диалекты: поддержка MySQL и PostgreSQL на уровне ядра
Реализовано:
- Абстрактный класс
Dialectи реализацииPostgreSql,MySql - Фабрика
DialectFactory - Логические типы (
id,bigint,integer,boolean,string,string:N,text,json,timestamp) - JSON-методы (
jsonExtractBoolean,jsonExtractInt,jsonBuildObject,jsonMergePatch,jsonMergePatches,jsonObjectMergeKey,jsonLike,jsonArrayContainsLike) - Методы дат (
extractYearFromUnixTimestamp,extractMonthFromUnixTimestamp) - Методы
LIKE,IN,LIMIT/OFFSET,getLastInsertedIDCondition - Методы возможностей (
supportsInsertReturning,supportsConcurrently,supportsIfNotExistsForIndex,supportsPartialIndex,supportsDropIndexConcurrently,supportsDropIndexIfExists,supportsIndexType,requiresUsingClause,supportsDefault) - Все Statement"ы переведены на диалект (
CreateTable,CreateIndex,DropIndex,Insert,Select,Update,Delete) - Все Clause"ы переведены на диалект (
Returning,From,Join,Where,OrderBy,Limit,Set) - Инсталлятор адаптирован: 22 таблицы, 64 индекса,
createIndexSafe() - Бизнес-логика переведена на диалект (13 файлов:
Entry,Entries,EntryCategory,EntriesCategories,EntryComment,EntryComments,User,Users,UserGroup,UsersGroups,PageStatic,PageStatic/Version,Pages)
152-ФЗ: полное техническое покрытие на уровне ядра
Реализовано:
- Логирование всех действий с ПДн (записи, страницы, медиа, пользователи, категории, выборки, формы, блоки, комментарии, группы, фиды, настройки CMS)
- Логирование доступа к ПДн (карточка пользователя, список пользователей, чужой профиль, вход/выход, отправка форм, просмотр логов, списка согласий)
- Логирование настроек CMS с фиксацией только реально изменившихся полей
- Версионирование юридических документов (таблица
pages_static_versions, классPageStatic\Version, UI административной панели, чтение?version=X.Yна фронте) - Фиксация согласий в динамических формах (класс
User\Consent, тип поляconsent, привязка к документу и версии) - Фиксация согласий при регистрации (
UserConsent::giveBatch) - Отзыв согласия в профиле пользователя (handler
api/user/patch.handler.php, UI «Мои согласия») - Просмотр и управление согласиями в административной панели (
/admin/usersConsents, правоPERMISSION_ADMIN_USERS_CONSENTS_MANAGEMENT) - CSV-экспорт согласий (14 колонок, BOM для Excel)
- Экспорт данных субъекта по ст. 14 (ZIP:
profile.json,consents.csv,reports.csv,manifest.json) - Защита от подделки IP-адреса (
Client::getRealIPAddress, доверенные прокси, CIDR-проверка IPv4/IPv6) - Анонимизация ПДн по ст. 5 (класс
User\Anonymizer,User::isAnonymized, handler/handler/user/anonymize) - Ротация логов по ст. 5 (таблица
reports_archive, классReports\Rotator,cron/rotateReports.php, UI в/admin/settings/security) - Cookie-баннер для всех посетителей (включая анонимов) с фиксацией согласия и защитой от дубликатов
- Настройка
security_legal_documentsв административной панели (выбор юр. документов) - Мультиязычность отчётов (
entryTitles,pageTitles,categoryTitlesи др. по локалям)
OAuth-провайдер: серверная часть
Реализовано:
- Три таблицы:
oauth_clients,oauth_auth_codes,oauth_access_tokens - Классы
Client,AuthCode,Tokenвcore/PHPLibrary/OAuth/ - Эндпоинты
/handler/oauth/authorize(GET/POST) и/handler/oauth/token(POST) - Поддержка грантов
authorization_codeиrefresh_token - Обязательная поддержка
PKCE(S256) - Строгая валидация
redirect_uri(точное совпадение, запрет не-HTTP схем) - Одноразовые коды авторизации с TTL 60 секунд
- Ротация refresh-токенов при каждом обновлении
- Хеширование
client_secretчерезBCrypt(cost=12) - Верификация клиентов администратором перед выдачей доступа
- Лимиты количества токенов на приложение
- Исключение CSRF-проверки для
/handler/oauth/*(требование протокола) - CLI-тест
oauth_test.php(11 проверок) и HTTP-тестoauth_http_test.sh(полный цикл)
Исправлено:
RegenerateSecret()не сохранял новый секрет- Пустой scope при refresh token
Мультиязычность настроек сайта
Реализовано:
- JSON-хранение настроек по локалям (
base_site_title,seo_site_description,seo_site_keywords) - Хелперы
getAdminLocaleNameиgetLocalizedSettingValue - Поддержка трёх форматов чтения: новый JSON, старый плоский список, старая плоская строка
- Автоматическая миграция старых данных при первом сохранении
- Разделение админской и публичной локали (
Configurator::getSiteTitle/Description/Keywords) - UI: селект локали в шапке страницы настроек, скрытое поле
_settings_locale
Исправлено:
- Баг с выводом «Array» в заголовке/описании/ключевых словах после первого сохранения
- Баг с редкой невозможностью неполучения данных локали
Автоматическое создание индексов при установке CMS
Реализовано:
- Добавлен блок создания индексов на шаге 6 установки после генерации таблиц
- Индексы для таблиц
entries,entries_categories,entries_comments,pages_static - Индексы для таблиц
users,users_sessions,forms_data,web_channels,metrics - Уникальные индексы на
name,login,email - Для PostgreSQL добавлены GIN-индексы на JSONB-поля и частичный индекс для опубликованных записей
- Все индексы создаются с
IF NOT EXISTS, ошибки логируются без прерывания установки
Административная панель: поиск и сортировка
Реализовано:
- Поиск и сортировка в 10 разделах:
users,usersGroups,usersConsents,entries,pages,entriesCategories,entriesComments,entriesSamples,forms,contentBlocks - GET-параметры
?value=...и?sort=...из белого списка - Сохранение параметров в пагинации (
buildQueryString+startPart) - UI:
Choices+Input+Buttonв контейнере#E8548530785 - Методы
getAll($searchValue, $sortRule)иgetCountTotal($searchValue)в репозиториях - 6 правил сортировки (по дате создания/обновления ↑↓, по алфавиту ↑↓)
Исправлено:
- Баг
Users::getCountByGroupID()— лишнийANDв MySQL-ветке - Адаптивное квотирование колонок для PostgreSQL
Яндекс.Метрика
Реализовано:
- Настройка
seo_code_yandex_metrika(только числовой ID) - Поле в
/admin/settings/seo - Вставка скрипта Метрики и
<noscript>в<head>(темаdefault) - Двойная валидация:
preg_replace("/\D/", "")при сохранении,ctype_digit()при выводе - Вставка через
createTextNode+appendChild(иначеsaveHTML()ломает инлайн-скрипт)
Прочее
Исправлено:
- Cookie-баннер показывался повторно при наличии cookie
allowCookies - Batch-вставка на MySQL при
innodb_autoinc_lock_mode = 2 - Утечка чувствительных полей в debug-выводе
Предыдущий выпуск: 0.3.0 «Шуя»
Комментарии