silverstripe / versioned-snapshots
SilverStripe版本化快照
Requires
- php: ^7.4 || ^8
- silverstripe/cms-events: ^1
- silverstripe/event-dispatcher: ^0.1.3
- silverstripe/framework: ^4.7
- silverstripe/vendor-plugin: ^1.6
- silverstripe/versioned: ^1.7
Requires (Dev)
Suggests
- silverstripe/versioned-snapshot-admin: Provides a version history user interface based on snapshots
Conflicts
- dnadesign/elemental: < 3.2.1
- silverstripe/graphql: < 3.2.3
This package is auto-updated.
Last update: 2024-09-22 03:51:58 UTC
README
概述
启用快照,以增强深层嵌套所有者结构的版本历史和修改状态。它解决了版本化中的一个重要用户体验问题,这在内容块实现中尤其明显。
此模块启用快照的数据模型。要充分利用其核心功能,您应该安装silverstripe/versioned-snapshot-admin,通过CMS的“历史”选项卡公开这些快照。
警告:此模块是实验性的,不被认为是稳定的。
安装
$ composer require silverstripe/versioned-snapshots
您还需要运行dev/build
。
这是做什么的?
假设您有一个依赖于所有者结构的内容模型,使用$owns
设置。
BlockPage
(has_many) Blocks
(has_one) Gallery
(many_many) Image
每个节点之间的所有者关系允许通过一条命令(或点击按钮)发布整个图。但用户不清楚哪些所有者内容(如果有的话)将被发布。如果相册被修改,BlockPage
将不会显示修改后的状态。
此模块旨在使这些修改状态和隐式编辑历史更加透明。
它不做什么?
目前,不支持回滚拥有其他内容的记录,并将产生意外结果。此外,不支持比较父版本的两次版本之间的所有者更改。
我可以在我的当前项目中使用这个吗?
是的,但有几点要注意
many_many
关系必须使用“通过”对象(隐式many_many
不可版本化)。- 您必须将所有版本化内容迁移到快照中(请参阅从版本化迁移)。
- 某些编辑事件可能无法捕获,尤其是第三方模块提供的某些事件。请参阅(添加您自己的快照创建器)
- 它(目前)与Postgres不完全兼容。欢迎提交拉取请求!
API
虽然SnapshotPublishable
扩展提供了大量的API接口,但只有少数几个主要方法是针对最终用户的
$myDataObject->hasOwnedModifications(): bool
如果记录拥有已更改的记录返回true$myDataObject->getPublishableObjects(): ArrayList
返回一个与所有者一起发布的DataObject
实例列表$myDataObject->getActivityFeed(): ArrayList
提供了一组可以在模板上渲染的对象,以创建可读的活动流。返回一个包含以下内容的ActivityEntry
对象数组Subject
:触发活动的DataObject
记录Action
:以下之一:CREATED
、MODIFIED
、DELETED
、ADDED
或REMOVED
。Owner
:仅在many_many
关系定义中。提供有关记录链接到什么的详细信息。通知ADDED
和REMOVED
操作。
扩展
快照功能是通过SnapshotPublishable
扩展提供的,该扩展是RecursivePublishable
的替代品。默认情况下,此模块将用这个自定义子类替换添加到所有数据对象中的RecursivePublishable
。
工作原理
快照是在CMS中由silverstripe/cms-events
模块触发的用户事件所注册的处理程序创建的。
自定义快照消息
默认情况下,这些事件将触发语言文件中定义的消息,例如:_t('SilverStripe\Snapshots\Handler\Form\FormSubmissionHandler.HANDLER_publish', 'Publish page')
。然而,如果您想在此配置级别自定义此消息,只需在处理程序类中覆盖消息即可。
SilverStripe\Snapshots\Handler\Form\FormSubmissionHandler: messages: publish: 'My publish message'
在这种情况下,“publish”是动作标识符(处理表单的函数)。
自定义现有快照创建者
所有处理程序都由注入器注册,因此自定义它们的最简单方法是覆盖配置中的定义。
例如,如果您在页面保存时需要自定义与快照相关的内容
use SilverStripe\Snapshots\Handler\Form\SaveHandler; use SilverStripe\EventDispatcher\Event\EventContextInterface; use SilverStripe\Snapshots\Snapshot; class MySaveHandler extends SaveHandler { protected function createSnapshot(EventContextInterface $context): ?Snapshot { //... } }
SilverStripe\Core\Injector\Injector: SilverStripe\Snapshots\Handler\Form\SaveHandler: class: MyProject\MySaveHandler
添加自己的快照创建者
如果您已将自定义动作或表单处理程序添加到CMS中,您可能希望确保它们被默认快照创建者跟踪,或者甚至为它们构建自己的快照创建者。在这种情况下,您可以使用Dispatcher
的声明性API来订阅您需要的事件。
假设我们有一个提交到函数的表单:public function myFormHandler($data, $form)
。
SilverStripe\Core\Injector\Injector: SilverStripe\Snapshots\Dispatch\Dispatcher: properties: handlers: myForm: on: - 'formSubmitted.myFormHandler' handler: %$MyProject\Handlers\MyHandler
注意,事件名称是配置键的一部分。这使得另一个配置层能够禁用它。请参见以下内容。
移除快照创建者
要从一个处理程序中移除事件,只需将其添加到off
数组中。
SilverStripe\Core\Injector\Injector: SilverStripe\Snapshots\Dispatch\Dispatcher: properties: handlers: myForm: off: - 'formSubmitted.myFormHandler'
程序化添加事件处理程序
您可以将EventHandlerLoader
实现注册到Dispatcher
,以程序化注册和注销事件。
SilverStripe\Core\Injector\Injector: SilverStripe\Snapshots\Dispatch\Dispatcher: properties: loaders: myLoader: %$MyProject\MyEventLoader
use SilverStripe\Snapshots\Dispatch\DispatcherLoaderInterface; use SilverStripe\Snapshots\Dispatch\Dispatcher; use SilverStripe\Snapshots\Handler\Form\SaveHandler; class MyEventLoader implements DispatcherLoaderInterface { public function addToDispatcher(Dispatcher $dispatcher): void { $dispatcher->removeListenerByClassName('formSubmitted.save', SaveHandler::class); } }
快照创建API
为了涵盖所有情况,此模块允许您在代码中的任何部分调用快照创建,而无需正常动作流程。
当您想要创建快照时,只需像这样调用createSnapshot
函数
Snapshot::singleton()->createSnapshot(DataObject $origin, array $extraObjects = []);
$origin
是要匹配动作的对象,即动作正在更改原始对象。
$extraObjects
是您希望在快照中的额外数据对象数组。每次调用createSnapshot
都会隐式包括以下记录,除了原始记录外
- 原始记录“拥有”的所有记录,例如:
BlockImage > BaseElement > ElementalArea > Page
- 原始记录隐式修改的所有记录。(见隐式修改)
没有“原始记录”时
对您的内容的一些修改不一定是由编辑特定实体的编辑事件触发的。对于这些情况,您可以使用createSnapshotFromEvent
API。
Snapshot::singleton()->createSnapshotFromEvent('Description of event');
通用事件的示例包括重新排列网站树、复制翻译、导入内容等。将其视为您内容的简单“git提交”消息。它为您的时间线创建了一个标记,内容编辑员可以在未来的某个时间点引用。
隐式修改
有时对看似“原始”记录的编辑实际上是其他记录的隐式编辑。这种情况最常见的情况是添加相关记录。例如,如果用户更改了管理many_many
关系的CheckboxSetField
,则显示这些复选框的记录保持不变,并不需要新的版本。但是,添加或删除新相关记录则值得创建一个新的快照,因为所有权链已更新。
createSnapshot
API知道这类修改,并尝试使用RelationDiffer
服务来检测它们。当一个修改包括对关系的更改时,createSnapshot
将回退到创建一个通用事件来描述发生了什么更改,例如:'添加了两个类别'
。
这种关系差异比较昂贵,每次保存每个关系时都需要运行,因此,您需要通过$snapshot_relation_tracking
设置来启用它。
class Product extends DataObject { private static $many_many = [ 'Categories' => Category::class, ]; private static $snapshot_relation_tracking = ['Categories']; }
另一个隐式修改的常见例子是 silverstripe-elemental 版本 4.x 中的 ElementalEditor
字段。当页面保存时,它实际上保存了编辑器中的所有块,这些块是 has_many
关系。因为它是一个如此常见的用例,所以块默认情况下会通过 snapshot_relation_tracking
跟踪,这样页面保存就会产生适当的“修改/添加/删除块”快照。
从 Versioned 迁移
要迁移所有您的 _versions
表到快照,请使用 snapshot-migration
任务
$ vendor/bin/sake dev/tasks/snapshot-migration
或者,此任务作为 排队作业 提供。
此任务的影响应该相当小,因为它只写入新的(可能为空的)快照表。它应该能够扩展,因为它不对PHP中的记录进行处理。迁移是纯SQL。
第三方模块支持
一些常见的第三方模块默认支持。最著名的是 silverstripe-elemental,它默认安装了几个特定的快照创建器,包括
- 存档元素
- 保存单个元素
- 创建元素(GraphQL查询)
- 编辑单个元素
- 通过页面保存保存所有元素
- 排序元素
- ModelAdmin 和 GridField CSV 导入
如上所述,元素默认在其页面上也接收 snapshot_relation_tracking
。
另一个默认支持的模块是 GridFieldExtensions。为它的 GridFieldOrderableRows
组件提供了一个处理程序。
本地化
此模块可以配置为与 Fluent 模块一起工作。遵循 Fluent 版本历史的范式,我们不允许在版本历史中继承任何内容。我们的 Snapshot
和 SnpashotItem
模型代表更详细的版本历史,因此我们需要应用以下配置来符合 Fluent 范式
SilverStripe\Snapshots\Snapshot: cms_localisation_required: 'exact' frontend_publish_required: 'exact' extensions: - TractorCow\Fluent\Extension\FluentExtension translate: - OriginHash SilverStripe\Snapshots\SnapshotItem: cms_localisation_required: 'exact' frontend_publish_required: 'exact' extensions: - TractorCow\Fluent\Extension\FluentExtension translate: - ObjectHash
升级到 1.x.x
1.x.x
版本包含一些破坏性变更。我们为两者都提供了升级路径。
对象版本 DB 字段重命名
在 SnapshotItem
上的 DB 字段 Version
已重命名为 ObjectVersion
,以防止命名冲突。请按照以下步骤进行升级。
- 运行
composer update
以升级到此模块的所需1.x.x
版本 - 运行
dev/build flush=all
- 运行
dev/tasks/migrate-object-version-task
,通过 CLI 运行
遗留 Fluent 设置
这对于使用 Fluent 模块 并使用本地化快照模型的项目相关。
- 运行
composer update
以升级到此模块的所需1.x.x
版本 - 根据此说明书的 本地化 部分审查和更新您的 Fluent 配置
- 运行
dev/build flush=all
- 运行
dev/tasks/migrate-fluent-object-hash-task
,通过 CLI 运行
重新计算哈希值
对象哈希值可能已过时。建议更新它们,否则预更新历史记录项可能不会在历史查看器中显示。运行 dev/tasks/recalculate-hashes-task
,通过 CLI 运行
此开发任务默认支持 Fluent
语义版本控制
此库遵循 Semver。根据 Semver,您将能够升级到此库的任何次要或补丁版本,而无需对公共 API 进行任何破坏性更改。Semver 还要求我们明确定义此库的公共 API。
所有具有public
可见性的方法都属于公共API。其他所有方法不属于公共API。在可能的情况下,我们会尽量在次要版本/修补程序版本中保持protected
方法的向后兼容性,但如果你正在重写方法,请在升级之前测试你的工作。
报告问题
请创建一个问题,用于报告你发现的任何错误或缺少的功能。
许可证
本模块在BSD 3-Clause License下发布。