Repository navigation
Releases
2.0.0-beta.1: Page history with restores through Neos publishing
NEOSidekick Revisions adds page history to Neos. Every publish to live creates a revision that editors can compare and restore from the inspector. Version 2.0 sends restores through Neos publishing, so search indexing, caches, redirects and every other package that listens to Neos publishing react to a restore the way they react to a publish.
Every publish is a savepoint
Open the Revisions tab in the inspector, pick a point in time, and see what changed since then: highlighted text changes, images side by side, dates, references, added and removed content blocks, in every language of the page. One click restores the page to that state. No database backup, no developer, no guessing which version of the text the customer approved.
2.0 sends every restore through Neos publishing
With 1.x, a restore wrote the old content into the live database directly. The page came back, but the rest of the site did not notice: the search index kept the newer text, a headless frontend kept serving the old page, and redirects were not created.
2.0 stages the revision in a private workspace and has Neos publish it to live. The same hooks run as for any publish: search indexing, frontend revalidation, redirects, the event log, cache flushing, and translation packages that listen to publishing. Anything that goes wrong before the publish, a permission denial or a revision that no longer fits, leaves live untouched. Neos attributes the restore to the editor, and by default the package records the result as a new revision, so a restore can itself be undone.
Images and documents come back too
A restore also covers the media a page references. The package matches each image and document by identity, so existing assets keep the metadata stored in the media library today: title, caption, copyright notice and tags. If someone deleted an asset after the revision was created, 2.0 recreates it on restore with its original metadata, as long as the same file content still exists under another asset in the same resource collection.
The diff reports changes without writing data
The diff no longer lists a date as changed when only its time zone representation differs. It shows deleted content blocks as removed instead of changed to empty. It handles revisions that contain blocks no longer in live, and it ignores leftover node data rows. Showing a diff only reads.
Restores can enforce permissions and node type rules
By default 2.0 keeps the permission behavior of 1.x: anyone with access to the Revisions tab can restore the whole page, including languages they may not edit by hand. Set applyWithoutAuthorizationChecks: false to enforce the editor's node privileges. The package then rejects the whole restore if it would change protected content, and the inspector shows why.
The package also rejects a revision before publishing if it no longer fits the node type configuration: a content type that no longer exists, or a node to create, move back or retype where the current constraints no longer allow it. The inspector lists the reasons. Integrators get two signals, revisionApplying and revisionApplied, to observe a restore.
Use this beta on staging first
Scripted tests in a Neos 8.4 distribution cover permissions, multi-language content, moved content, deleted assets and failure cases. The new restore flow still lacks weeks of use in real editorial projects, and the package runs static checks but has no functional test suite yet. Use the beta on staging before production. Please report findings in the issue tracker.
Changes since 1.1.0
Breaking changes
- Applying a revision is a publish through a temporary workspace and Neos'
PublishingService. All node and publishing signals fire; modification and publication dates are set to the apply time; failures before the publish leave live untouched. (#19, #28) - Applying a revision can enforce node privileges. The new setting
NEOSidekick.Revisions.revisions.applyWithoutAuthorizationChecksdefaults totrue, which keeps the 1.x behavior. Set it tofalseto reject a restore that would change protected content with HTTP 403. (#28) - Revisions are validated against the current node type configuration before staging. Missing node types, and nodes that would be created, moved back or retyped where the current constraints no longer allow them, are rejected with HTTP 422 and the reasons; the CLI exits with status 1. (#19, #28)
- Removed public methods:
NodeImportService::getPersistedNodeIdentifiers(),NodeService::removeNodes().NodeImportService::persistNodeData()no longer persists;NodeImportService::parseNodes()is new.RevisionService::applyRevision()throwsRevisionNotApplicableExceptionandRevisionApplyDeniedExceptioninstead of returningfalsein those cases. (#28) - Image variants keep their current crop on apply; 1.x restored the crop stored in the revision. (#18, #27)
- The diff no longer writes data and therefore no longer recreates deleted image variants. (#27, #33)
Upgrade notes
- Run
./flow doctrine:migrate(two new nullable columns on the revision table) and flush caches with./flow flow:cache:flush. - Adapt integrations that used
getPersistedNodeIdentifiers(),removeNodes(), the third$emptyargument of the protectedcreateRevisionInternal(), or relied onapplyRevision()returningfalsefor every failure. - Decide whether editors may restore content they cannot edit by hand:
applyWithoutAuthorizationChecks. - Restores use Neos' regular publishing path, so integrations listening to its signals (search, headless revalidation, automatic translation) react without configuration; verify integration-specific behavior on staging.
- Restores bypass review workflows, including packages that route publishes through a review workspace. As in 1.x, applying a revision publishes directly to live, because a revision is content that was live before. With the default permission setting, anyone with access to the Revisions tab can restore the whole page.
Known limitations
- Properties the current node type no longer declares are dropped on apply by Neos' property cleanup.
- Node types that became abstract since the revision pass the validation (#31).
- The publish itself is Neos' regular publish and has no rollback; a failure inside it leaves a partially published page, as a manual publish would.
- Assets are recreated while the revision is read, before the publish; if the apply fails afterwards, the recreated asset stays as an unreferenced asset in the media library.
- The migration is written for MySQL and MariaDB, like the package's existing migrations.
- Hidden documents cannot get or apply revisions (#37).
- In distributions with networkteam/neos-next,
./flow revision:applycan exit with status 1 after a successful apply, because the revalidation notifier cannot initialize the security context outside a request.
Fixed
- Showing a diff or applying a revision now resolves referenced assets by identity. These operations no longer change asset metadata or thumbnails. (#18, #27)
- DateTime properties lost their named time zone on apply and were always listed as changed in the diff; revisions created with 1.1.0 still apply. (#20, #25)
revision:comparefailed withUndefined array key "identifier"for revisions containing a node deleted since. (#21, #22)- Content nodes missing from a revision were shown as changed with every property emptied instead of as removed. (#23, #24)
- Showing a diff failed with
Call to a member function getDimensions() on nullwhen the live workspace contained removed node data; such rows are now ignored in the diff, as they are on apply. (#26, #30)
Added
- On apply, a deleted asset is recreated with its previous identity when the file content still exists under another asset. (#33)
- Signals
revisionApplyingandrevisionAppliedonRevisionService. (#28) - The inspector shows why a revision cannot be applied. (#28)
- The revision created after an apply references the applied revision instead of storing a rendered label; the inspector shows "Applied revision …" in the viewer's language. (#32, #35)
- A CI workflow: PHP lint on 7.4 and 8.3, PHPStan, inspector build reproducibility, ESLint, composer validate, XLIFF well-formedness. (#34, #36)
Requires PHP 7.4 or later and Neos 8.x.
Version 1.1.0 - FEATURE: Support Neos 8.x
The package has been updated to support Neos 8.x only. Along, a minor bug was fixed, and the build process was switched to esbuild.
Full Changelog: 1.0.2...1.1.0
Version 1.0.2: Fix empty revisions due to core bug, update readme
Full Changelog: 1.0.1...1.0.2
Version 1.0.1: Fixes naming issues
Full Changelog: 1.0.0...1.0.1
Version 1.0.0
What's Changed
- FEATURE: View and allow to ignore conflicts before applying revision by @Sebobo in #3
- FEATURE: Make package disable-able via configuration by @gradinarufelix in #12
- BUGFIX: Don’t strip false values during export by @Sebobo in #15
- BUGFIX: Skip identical values and improve arrays in diff view by @Sebobo in #16
New Contributors
- @Sebobo made their first contribution in #3
- @gradinarufelix made their first contribution in #12
Full Changelog: https://github.com/NEOSidekick/NEOSidekick.Revisions/commits/1.0.0