CMS“GIRVAS” 版本,2026 年 10 月 3 日,处于“谢格扎”开发阶段。
最新变更
QueryBuilder:支持 JOIN、CASE 表达式和索引
已实现:
- 添加了带索引类型的 Enum
IndexType(BTREE、HASH、GIST、GIN、SPGIST、BRIN、FULLTEXT) - 添加了用于
SELECT中 JOIN 的ClauseJoin类(INNER、LEFT、RIGHT、FULL) - 实现了针对 MySQL 和 PostgreSQL 的 JOIN 条件自适应生成
- 添加了用于构建 CASE 表达式的
CaseExpression类 - 实现了用于 JSON 搜索的
whenJsonLike()和whenJsonArrayContains()方法 - 添加了静态方法
CaseExpression::sum() - 在
QueryBuilder中添加了工厂方法createCase() - 添加了用于
CREATE INDEX的StatementCreateIndex类 - 添加了用于
DROP INDEX的StatementDropIndex类 - 实现了对
UNIQUE、CONCURRENTLY、IF NOT EXISTS/IF EXISTS、带WHERE的部分索引的支持 - 添加了
setStatementCreateIndex()和setStatementDropIndex()方法 - 在
EntryCategory中添加了初始化数据缓存
已修复:
- PostgreSQL 中
addSelections()的 CASE 表达式转义
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-FZ:核心层面的完整技术覆盖
已实现:
- 记录所有个人数据相关操作(条目、页面、媒体、用户、分类、筛选、表单、区块、评论、群组、订阅源、CMS 设置)
- 记录个人数据访问(用户卡片、用户列表、他人资料、登录/退出、提交表单、查看日志、同意列表)
- 记录 CMS 设置,仅记录实际发生变化的字段
- 法律文件版本化(表
pages_static_versions、类PageStatic\Version、管理面板 UI、前端读取?version=X.Y) - 在动态表单中记录同意(类
User\Consent、字段类型consent、绑定到文档和版本) - 注册时记录同意(
UserConsent::giveBatch) - 在用户资料中撤回同意(处理器
api/user/patch.handler.php、UI“我的同意”) - 在管理面板中查看和管理同意(
/admin/usersConsents、权限PERMISSION_ADMIN_USERS_CONSENTS_MANAGEMENT) - 同意 CSV 导出(14 列,为 Excel 添加 BOM)
- 根据第 14 条导出数据主体数据(ZIP:
profile.json、consents.csv、reports.csv、manifest.json) - 防止 IP 地址伪造(
Client::getRealIPAddress、可信代理、IPv4/IPv6 CIDR 检查) - 根据第 5 条对个人数据进行匿名化(类
User\Anonymizer、User::isAnonymized、处理器/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 core/PHPLibrary/OAuth/中的类Client、AuthCode、Token- 端点
/handler/oauth/authorize(GET/POST)和/handler/oauth/token(POST) - 支持
authorization_code和refresh_token授权类型 - 强制支持
PKCE(S256) - 严格验证
redirect_uri(精确匹配,禁止非 HTTP 方案) - 一次性授权码,TTL 为 60 秒
- 每次刷新时轮换 refresh token
- 通过
BCrypt对client_secret进行哈希(cost=12) - 管理员在授予访问权限前验证客户端
- 每个应用的 token 数量限制
- 对
/handler/oauth/*排除 CSRF 检查(协议要求) - CLI 测试
oauth_test.php(11 项检查)和 HTTP 测试oauth_http_test.sh(完整流程)
已修复:
RegenerateSecret()未保存新密钥- refresh token 中 scope 为空
网站设置多语言化
已实现:
- 按语言区域以 JSON 存储设置(
base_site_title、seo_site_description、seo_site_keywords) - 辅助方法
getAdminLocaleName和getLocalizedSettingValue - 支持三种读取格式:新 JSON、旧扁平列表、旧扁平字符串
- 首次保存时自动迁移旧数据
- 分离管理语言区域和公开语言区域(
Configurator::getSiteTitle/Description/Keywords) - UI:设置页头部的语言区域选择器、隐藏字段
_settings_locale
已修复:
- 首次保存后标题/描述/关键词显示“Array”的 Bug
- 偶发无法获取语言区域数据的 Bug
CMS 安装时自动创建索引
已实现:
- 在生成表之后的安装第 6 步添加创建索引区块
- 为表
entries、entries_categories、entries_comments、pages_static创建索引 - 为表
users、users_sessions、forms_data、web_channels、metrics创建索引 - 在
name、login、email上创建唯一索引 - 为 PostgreSQL 添加 JSONB 字段上的 GIN 索引以及已发布条目的部分索引
- 所有索引均使用
IF NOT EXISTS创建;错误会记录日志且不会中断安装
管理面板:搜索和排序
已实现:
- 在 10 个分区中支持搜索和排序:
users、usersGroups、usersConsents、entries、pages、entriesCategories、entriesComments、entriesSamples、forms、contentBlocks - GET 参数
?value=...和?sort=...来自白名单 - 在分页中保留参数(
buildQueryString+startPart) - UI:容器
#E8548530785中的Choices+Input+Button - 仓储中的方法
getAll($searchValue, $sortRule)和getCountTotal($searchValue) - 6 条排序规则(按创建/更新时间 ↑↓、按字母顺序 ↑↓)
已修复:
Users::getCountByGroupID()Bug — MySQL 分支中多余的AND- PostgreSQL 的列名自适应引用
Yandex.Metrica
已实现:
- 设置
seo_code_yandex_metrika(仅数字 ID) - 字段位于
/admin/settings/seo - 将 Metrica 脚本和
<noscript>插入<head>(主题default) - 双重验证:保存时
preg_replace("/\D/", ""),输出时ctype_digit() - 通过
createTextNode+appendChild插入(否则saveHTML()会破坏内联脚本)
其他
已修复:
- 存在
allowCookiescookie 时 Cookie 横幅会重复显示 - MySQL 在
innodb_autoinc_lock_mode = 2时的批量插入 - 调试输出中敏感字段泄漏
上一版本:0.3.0“舒亚”
评论