feat(Conflict detection): #3591668 "Text-based Page entity representation via Canvas API"
TL;DR: Adds a new endpoint and related infra that serves Page entities in textual representation using YAML format, using only fields that can be stored in auto-save item.
For people with attention span or AI summary tools:
🤖 Summary
Adds a GET /canvas/api/v0/content/canvas_page/values-as-text/{canvas_page} endpoint that returns a Page entity's storable field values encoded as YAML text. The primary use case is client-side comparison of published and draft Page entities using text-based representation of values that can be stored in an auto-save item. The endpoint accepts an ?autoSaved=true|false query parameter (default true). When true, it reconstructs the entity from the active auto-save item and returns its values alongside the auto-save timestamp. When false, it returns the values of the entity as persisted in storage alongside its revision creation timestamp. This is the same approach that was introduced to layout endpoint in !1194 (merged) .
The returned values are produced by AutoSaveManager::toStorableArray() - the same normalization that is used when writing an auto-save item to storage. This way the YAML output is directly comparable to stored auto-save data, without showing values user has no way to change in Canvas UI. Fields the current user has no permissions to view are omitted from the response. Component-tree fields are placed at the end of the YAML output for better UX. AutoSaveManager::toStorableArray() is promoted from private to public to allow the controller to reuse it without duplication.
Adds new canvas_test_field_view_access helper module for testing access to individual entity type fields using view operation. Used in this MR to test that "fields the user has no permission to access are excluded from the output", but can be used for other controller routes that check individual field permissions as well.
Testing instructions
Testing requires enabling canvas_dev_cd feature flag module.
- Pick existing or create new Page entity and publish it, take write down its title and what its "published at" date / timestamp.
- Open a Canvas Page in the editor, change it's title to
Updated pagewithout publishing and:- confirm that draft (unpublished auto-save item) is created and is being tracked in Canvas
- take note of timestamp (https://unix.click/ or some other method)
- Make
GETcall to/canvas/api/v0/content/canvas_page/values-as-text/{id}(default?autoSaved=true) and confirm:- response contains
entityproperty, that is a encoded YAML blob entityproperty contains the draft title -Updated pageupdatedtimestamp is close to the time that Page entity was updated in Canvas in step 2.
- response contains
- Make
GETcall to/canvas/api/v0/content/canvas_page/values-as-text/{id}?autoSaved=falseand confirm:- response contains the published title written down in step 1
updatedtimestamp matching the time Page entity was published at and taken in step 1.
- Make
GETcall to/canvas/api/v0/content/canvas_page/values-as-text/{id}with no active auto-save and?autoSaved=trueand confirm the result is identical to step 3:- response contains the draft title -
Updated page updatedtimestamp is close to the time that Page entity was updated in Canvas 2.
- response contains the draft title -
- Publish changes to Page entity, take note of timestamp
- Make
GETcall to/canvas/api/v0/content/canvas_page/values-as-text/{id}?autoSaved=falseand confirm:- response contains the title set in step 2 -
Updated page updatedtimestamp is close to the timestamp taken in step 6.
- response contains the title set in step 2 -
- Test
GETcalls to/canvas/api/v0/content/canvas_page/values-as-text/{id}edge cases:- Calling endpoint using
{id}of a Page that doesn't exist results inHTTP 404with[] - Calling endpoint using
{id}of page that is published, bus has no draft / auto-save item, withoutautoSavedargument orautoSaved=trueresults inHTTP 404with response body containingerrorsproperty with single item, which contains error message indetailsand auto-save item identifier - Calling endpoint using
{id}of page that is published, bus has no draft / auto-save item, withautoSaved=falseresults in successful fetching of entity - Calling endpoint using
{id}of page that is published, but contains a field that user has no permission to view, results in that field being absent from theentityproperty in the response
- Calling endpoint using
- Disable
canvas_dev_cdfeature flag module - Make
GETcall to/canvas/api/v0/content/canvas_page/values-as-text/{id}, confirm:
- the response is
HTTP 404 - response body contains
errorswith single item that contains error message"Feature flag modulecanvas_dev_cdis disabled."indetailsproperty and auto-save item identifier - the response is consistent with any permutation of
autoSaved
AI use disclosure
This MR description was drafted with AI assistance (GitHub Copilot) per Drupal.org's policy on AI contributions. It was then reviewed and made worse extensively rewritten by a human anyway
Closes #3591668