Bind the context parse to the revision and clarify provider docs - #1031
Closed
malberts wants to merge 3 commits into
Closed
Bind the context parse to the revision and clarify provider docs#1031malberts wants to merge 3 commits into
malberts wants to merge 3 commits into
Conversation
Fixes #979 PagePropertiesBuilder already loaded the revision's main slot content and parsed it to extract categories, but threw everything else away. Providers wanting to derive Page Properties from the content had to re-fetch and re-parse it themselves - and since the context carries no revision ID, they could only look up the latest revision of the page, which is redundant work and subtly racy. The context now additionally exposes: * `content` - the serialized main slot content, e.g. the wikitext * `contentModel` - e.g. "wikitext" * `parserProperties` - the MediaWiki page properties recorded while parsing the content (e.g. "defaultsort", or values set by parser hooks via ParserOutput::setPageProperty) Design notes: * The context is a Domain value object holding only scalars and arrays. Exposing RevisionRecord, Content, or ParserOutput directly would put MediaWiki core classes into the Domain layer and make provider tests heavyweight. The relevant data is flattened instead, following the approach already used for `categories`. * `parserProperties` covers the template-expansion-safe path: extensions whose parser hooks already record values during the parse can read them back in their provider instead of re-analyzing raw markup. The parse NeoWiki already performs for categories is reused, so no additional parse happens. * When the content is unavailable (e.g. suppressed), `content` and `contentModel` are empty strings and `parserProperties` is empty, matching the existing behavior of `categories`. Note: content-derived properties refresh only when a new revision is stored, so values coming from transcluded templates can go stale - the same existing limitation as categories. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follow-up polish on the extending.md guidance for the new context fields: recommend deriving Page Properties from the robust parse products (categories, parserProperties) and frame raw content/contentModel as the escape hatch for custom, non-wikitext content models rather than the default. Also carries the "parserProperties is a parse input, not the NeoWiki Page Properties you return" disambiguation into the docs, where provider authors actually read it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
malberts
marked this pull request as ready for review
July 15, 2026 13:48
The parse that fills categories and parserProperties ran without a
revision id, i.e. as a preview-like parse: revision-context magic words
({{REVISIONID}}, {{REVISIONUSER}}, ...) and parser hooks that read the
revision while recording page properties resolved against nothing, so
the recorded values could diverge from what core stored for the same
revision. That mattered little while the parse only fed categories, but
the parse products are now published to providers as the recommended
derivation path. The fix passes the revision id through
ContentParseParams. The new test pins the behavior with a
{{DEFAULTSORT:Rev{{REVISIONID}}}} page: it records Rev without the fix
and Rev<id> with it, and a second stored revision ensures resolving the
page's latest revision instead of the provided one also fails.
The content-unavailable sentinels (content and contentModel empty,
parserProperties and categories empty when the main-slot content is
hidden) had no covering test, so type-clean drift such as switching the
builder to getContentOrThrow would pass the whole suite while making
undeletion of a page with rev-deleted history fatal in production; the
new test suppresses a real revision and asserts what a provider
receives. The contentModel test only exercised wikitext, the one value
a hardcode would also produce, so a JSON page now pins that the model
comes from the actual content.
In extending.md, the sentence introducing the context now names the
content and parse products, and the section states when providers
actually run: when a revision is stored for a page carrying Subject
data (including undeletions) and during RebuildGraphDatabases runs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
malberts
force-pushed
the
pr-982-review-fixes
branch
from
July 15, 2026 13:50
114b10f to
2116ae6
Compare
JeroenDeDauw
force-pushed
the
provide-content-to-page-property-providers
branch
from
August 20, 2026 23:01
ec599b9 to
489a30f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows-up to #982, delivering review fixes onto that PR's
branch (this diff contains only the fixes).
Bind the context parse to the stored revision. The parse that fills
categoriesandparserPropertiesran without a revision id, i.e. as a preview-like parse: revision-context magic words (
{{REVISIONID}},{{REVISIONUSER}}, ...) and parser hooks that read the revision while recording page properties resolvedagainst nothing, so the recorded values could diverge from what core stored for the same revision. That
mattered little while the parse only fed
categories, but the PR publishes the parse products to providersas the recommended derivation path. The fix passes
$revision->getId()throughContentParseParams. Thetest pins the behavior with a
{{DEFAULTSORT:Rev{{REVISIONID}}}}page: it recordsRevwithout the fix andRev<id>with it, and a second stored revision ensures resolving the page's latest revision instead of theprovided one also fails. Verified end to end on a dev stack, where the graph property carries the actual
revision id.
Pin the remaining documented contracts with tests. The content-unavailable sentinels (
content,contentModelempty andparserProperties,categoriesempty when the main-slot content is hidden) had nocovering test, so type-clean drift such as switching the builder to
getContentOrThrowwould pass the wholesuite while making undeletion of a page with rev-deleted history fatal in production; the new test suppresses
a real revision and asserts what a provider receives. The
contentModeltest only exercised wikitext, theone value a hardcode would also produce, so a JSON page now pins that the model comes from the actual
content. Each test was verified against a production mutation that only it catches.
Docs accuracy in extending.md. The sentence introducing the context now names the content and parse
products (previously it promised content derivation while enumerating only the pre-existing fields), and the
section states when providers actually run: when a revision is stored for a page carrying Subject data
(including undeletions) and during
RebuildGraphDatabasesruns, with pages whose last Subject was deletedstill qualifying via their subject slot.