Release of CMS “GIRVAS” dated October 3, 2026, at the “Segezha” development stage.
Latest Changes
QueryBuilder: JOIN, CASE expression, and index support
Implemented:
- Added the
IndexTypeEnum with index types (BTREE,HASH,GIST,GIN,SPGIST,BRIN,FULLTEXT) - Added the
ClauseJoinclass for JOINs inSELECT(INNER,LEFT,RIGHT,FULL) - Implemented adaptive generation of JOIN conditions for MySQL and PostgreSQL
- Added the
CaseExpressionclass for building CASE expressions - Implemented the
whenJsonLike()andwhenJsonArrayContains()methods for JSON search - Added the static method
CaseExpression::sum() - Added the factory method
createCase()inQueryBuilder - Added the
StatementCreateIndexclass forCREATE INDEX - Added the
StatementDropIndexclass forDROP INDEX - Implemented support for
UNIQUE,CONCURRENTLY,IF NOT EXISTS/IF EXISTS, and partial indexes withWHERE - Added the
setStatementCreateIndex()andsetStatementDropIndex()methods - Added caching of initialized data in
EntryCategory
Fixed:
- Escaping of CASE expressions in
addSelections()for PostgreSQL
SQL dialects: MySQL and PostgreSQL support at the core level
Implemented:
- Abstract class
Dialectand implementationsPostgreSql,MySql DialectFactoryfactory- Logical types (
id,bigint,integer,boolean,string,string:N,text,json,timestamp) - JSON methods (
jsonExtractBoolean,jsonExtractInt,jsonBuildObject,jsonMergePatch,jsonMergePatches,jsonObjectMergeKey,jsonLike,jsonArrayContainsLike) - Date methods (
extractYearFromUnixTimestamp,extractMonthFromUnixTimestamp) LIKE,IN,LIMIT/OFFSET,getLastInsertedIDConditionmethods- Capability methods (
supportsInsertReturning,supportsConcurrently,supportsIfNotExistsForIndex,supportsPartialIndex,supportsDropIndexConcurrently,supportsDropIndexIfExists,supportsIndexType,requiresUsingClause,supportsDefault) - All Statements migrated to the dialect (
CreateTable,CreateIndex,DropIndex,Insert,Select,Update,Delete) - All Clauses migrated to the dialect (
Returning,From,Join,Where,OrderBy,Limit,Set) - Installer adapted: 22 tables, 64 indexes,
createIndexSafe() - Business logic migrated to the dialect (13 files:
Entry,Entries,EntryCategory,EntriesCategories,EntryComment,EntryComments,User,Users,UserGroup,UsersGroups,PageStatic,PageStatic/Version,Pages)
152-FZ: full technical coverage at the core level
Implemented:
- Logging of all actions involving personal data (entries, pages, media, users, categories, selections, forms, blocks, comments, groups, feeds, CMS settings)
- Logging of access to personal data (user card, user list, another user"s profile, login/logout, form submission, viewing logs, list of consents)
- Logging of CMS settings with recording of only actually changed fields
- Versioning of legal documents (
pages_static_versionstable,PageStatic\Versionclass, administrative panel UI, reading?version=X.Yon the frontend) - Recording of consents in dynamic forms (
User\Consentclass,consentfield type, binding to document and version) - Recording of consents during registration (
UserConsent::giveBatch) - Withdrawal of consent in the user profile (
api/user/patch.handler.phphandler, “My Consents” UI) - Viewing and managing consents in the administrative panel (
/admin/usersConsents,PERMISSION_ADMIN_USERS_CONSENTS_MANAGEMENTpermission) - CSV export of consents (14 columns, BOM for Excel)
- Export of data subject data under Art. 14 (ZIP:
profile.json,consents.csv,reports.csv,manifest.json) - Protection against IP address spoofing (
Client::getRealIPAddress, trusted proxies, IPv4/IPv6 CIDR check) - Anonymization of personal data under Art. 5 (
User\Anonymizerclass,User::isAnonymized,/handler/user/anonymizehandler) - Log rotation under Art. 5 (
reports_archivetable,Reports\Rotatorclass,cron/rotateReports.php, UI at/admin/settings/security) - Cookie banner for all visitors (including anonymous users) with consent recording and duplicate protection
security_legal_documentssetting in the administrative panel (selection of legal documents)- Multilingual reports (
entryTitles,pageTitles,categoryTitles, etc. by locale)
OAuth provider: server side
Implemented:
- Three tables:
oauth_clients,oauth_auth_codes,oauth_access_tokens Client,AuthCode,Tokenclasses incore/PHPLibrary/OAuth/- Endpoints
/handler/oauth/authorize(GET/POST) and/handler/oauth/token(POST) - Support for
authorization_codeandrefresh_tokengrants - Mandatory
PKCEsupport (S256) - Strict
redirect_urivalidation (exact match, prohibition of non-HTTP schemes) - One-time authorization codes with a 60-second TTL
- Refresh token rotation on every refresh
client_secrethashing viaBCrypt(cost=12)- Client verification by an administrator before granting access
- Limits on the number of tokens per application
- Exclusion of CSRF verification for
/handler/oauth/*(protocol requirement) - CLI test
oauth_test.php(11 checks) and HTTP testoauth_http_test.sh(full cycle)
Fixed:
RegenerateSecret()did not save the new secret- Empty scope on refresh token
Multilingual website settings
Implemented:
- JSON storage of settings by locale (
base_site_title,seo_site_description,seo_site_keywords) - Helpers
getAdminLocaleNameandgetLocalizedSettingValue - Support for three read formats: new JSON, old flat list, old flat string
- Automatic migration of old data on first save
- Separation of admin and public locale (
Configurator::getSiteTitle/Description/Keywords) - UI: locale select in the settings page header, hidden
_settings_localefield
Fixed:
- Bug with “Array” output in the title/description/keywords after the first save
- Bug with a rare inability to retrieve locale data
Automatic index creation during CMS installation
Implemented:
- Added an index creation block at installation step 6 after table generation
- Indexes for the
entries,entries_categories,entries_comments,pages_statictables - Indexes for the
users,users_sessions,forms_data,web_channels,metricstables - Unique indexes on
name,login,email - For PostgreSQL, GIN indexes on JSONB fields and a partial index for published entries were added
- All indexes are created with
IF NOT EXISTS; errors are logged without interrupting installation
Administrative panel: search and sorting
Implemented:
- Search and sorting in 10 sections:
users,usersGroups,usersConsents,entries,pages,entriesCategories,entriesComments,entriesSamples,forms,contentBlocks - GET parameters
?value=...and?sort=...from a whitelist - Preservation of parameters in pagination (
buildQueryString+startPart) - UI:
Choices+Input+Buttonin the#E8548530785container getAll($searchValue, $sortRule)andgetCountTotal($searchValue)methods in repositories- 6 sorting rules (by creation/update date ↑↓, alphabetically ↑↓)
Fixed:
Users::getCountByGroupID()bug — extraANDin the MySQL branch- Adaptive column quoting for PostgreSQL
Yandex.Metrica
Implemented:
seo_code_yandex_metrikasetting (numeric ID only)- Field at
/admin/settings/seo - Insertion of the Metrica script and
<noscript>into<head>(themedefault) - Double validation:
preg_replace("/\D/", "")on save,ctype_digit()on output - Insertion via
createTextNode+appendChild(otherwisesaveHTML()breaks the inline script)
Other
Fixed:
- Cookie banner was shown again when the
allowCookiescookie was present - Batch insert on MySQL with
innodb_autoinc_lock_mode = 2 - Leakage of sensitive fields in debug output
Previous release: 0.3.0 “Shuya”
Comments