Manual:Modeling pages

Historically, the cocepts of pages, titles, and links have not been modeled clearly in MediaWiki. Several efforts have been made to improve and clarify the modeling, but these efforts are incomplete as of MW 1.41 (July 2023). This page provides an overview of the classes and interfaces that can be used to represent pages, titles, and links in MediaWiki.

The Title class has historically be used to represent both pages on the local wiki, and any kind of target a link may reference. For this reason, calling code cannot be sure what operations are well defined on a given Title object without performing additional checks or imposing additional assumptions and requirements. Titles may represent:


 * A regular editabel wiki page on the local wiki, existing or non-existing.
 * A link to a section on an editable page. Methods intended for use on editable pages have undefined/misleading behavior.
 * A special page on the local wiki. Methods intended for use on editable pages have undefined/misleading behavior.
 * An interwiki (or inter-language) link. Methods intended for use on editable pages have undefined/misleading behavior.
 * A relative subpage link. Methods operating pn the page title and namespace may have undefined/misleading behavior.
 * A relative section jump on the current page. Methods intended for use on editable pages have undefined/misleading behavior.
 * An invalid link target. Most methods have undefined/misleading behavior.

The WikiPage class has historically be used for interacting with the content of editable wiki pages. It used to contain the logic for updating the page table, which has mostly been extracted into other classes like PageStore and PageUpdater.

For this reason, the use of the Title and WikiPage classes have been discouraged since MW 1.36 (2021). Several narrow interfaces have been extracted for the use cases described above:


 * The LinkTarget interface (since MW 1.27) can represent anything a wiki-link can refer to. It is implemented by the TitleValue class.
 * The PageReference interface (since MW 1.37) represents a viewable page, like a wiki page or a special page. It is a WikiAwareEntity, so it may belong to the local wiki or another wiki that can be accessed directly on the database level. It is implemented by the PageReferenceValue class.
 * The PageIdentity interface (since MW 1.36) represents an editable wiki page which may or may not exist. It PageIdentity extends the PageReference interface, and is thus also a WikiAwareEntity. It is implemented by the PageIdentityValue class which extends PageReferenceValue.
 * The PageRecord interface (since MW 1.36) represents an existing editable wiki page, and provides access to the page's meta data.It extends the PageIdentity interface, and is thus also a PageReference and a WikiAwareEntity. It is implemented by the PageRecordValue class which extends PageIdentityValue.

In order to retain backwards compatibility, the Title implement the LinkTarget and PageReference interfaces. Similarly, WikiPage implements PageRecord. However, the intended semantics of these interfaces doesn't hold for all possible instances of Title and WikiPage:


 * Not all Title objects represent editable wiki pages, so not all PageIdentity objects are actually editable wiki pages. The ProperPageIdentity was introduced to allow code to require the guarantee that a PageIdentity is actually an editable wiki page. PageIdentityValue implements ProperPageIdentity, and instances can be optained from Title::toPageIdentity. Once the Title class has been removed, ProperPageIdentity will become an alias for PageIdentity, which will then be guaranteed to represent an editable wiki page.
 * Not all WikiPage objects represent existing wiki pages, so not all PageRecord objects are actually existing wiki pages. The ExistingPageRecord was introduced to allow code to require the guarantee that a Pagerecord is actually an existing wiki page. PageRecordValue implements ExistingPageIdentity, and instances can be optained from WikiPage::toPagerecord. Once the WikiPage class has been removed, ExistingPageRecord will become an alias for PageRecord, which will then be guaranteed to represent an existing wiki page.

Note that LinkTarget and PageReference are incompatible types. While we a number of methods that accept either type as a parameter (as a unition type), they are not interchangeable, and do not share a base class. The reason is that LinkTarget is not a WikiAwareEntity, so all instances of LinkTarget are guaranteed to be local, which is not the case for all PageReferences. PageReference, on the other hand, is guaranteed to refer to a wiki page (either a proper page or a special page), while a LinkTarget might also be a relative section jump or an interwiki link.

So, LinkTarget cannot be a subclass of PageReference: while it adds properties (such as the interwiki prefix), it removes the guarantee of referring to a wiki page, which would violate LSP. Conversely, PageReference cannot be a subclass of LinkTarget, since it would remove the guarantee of the page being on the local wiki (and it would render several properties redundant). A shared base class of LinkTarget and Pagereference could reasonably contain the properties namespace and dbKey. However, in a Pagereference, the namespace ID cannot interpreted without considering the wiki ID, and in a LinkTarget, the the dbKey would be misleading when not considering the interwiki prefix (and it may be empty, which would be illegal for a PageReference).

One solution would be to make LinkTarget wiki-aware. It would then have both a wiki ID and an interwiki prefix. The relationship of the two is not immediately obvious: the interwiki prefix has to be interpreted in the context of the wiki indicated by the wiki ID! For instance, on English Wikipedia, the prefix "fr" refers to the French Wikipedia. However, if getWikiId indicates that the object should be interpreted in the context of English Wiktionary instead, the prefix "fr" would refer to French Wiktionary. All code that instantiates a LinkTagret would need to make sure to get this relationship right.