1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\Page;
22
23use MediaWiki\DAO\WikiAwareEntity;
24use RuntimeException;
25use Wikimedia\Assert\PreconditionException;
26
27/**
28 * Interface for objects (potentially) representing an editable wiki page.
29 *
30 * The identity of any PageIdentity object is defined by the
31 * namespace, the dbkey, and the wiki ID.
32 * The page ID together with the wiki ID also identifies the page,
33 * unless the page ID is 0.
34 * If the wiki ID is self::LOCAL, the identity is relative to the local wiki.
35 *
36 * @note For compatibility with the Title class, PageIdentity instances
37 *   may for now not only represent non-existing pages, but also things
38 *   that are not actually pages, such as interwiki links, section links,
39 *   or Special pages (which exist, but are not proper editable pages).
40 *   This is intended to change in the future, so that a PageIdentity always
41 *   represents a "proper" page. Until then, code that requires a proper page
42 *   should call canExist() to check, or require a ProperPageIdentity.
43 *   Eventually, ProperPageIdentity is intended to become an alias for
44 *   PageIdentity.
45 *
46 * @note For compatibility with the Title class, PageIdentity instances may
47 *   be mutable, and return different values from methods such as getId() or exist()
48 *   at different times. In the future, the contract of this interface is intended
49 *   to be changed to disallow this.
50 *
51 * @note Instances of Title shall be the only instances of PageIdentity that are not
52 *   proper pages. Other classes implementing PageIdentity must represent proper pages,
53 *   and also implement ProperPageIdentity. The idea is that once Title has been removed,
54 *   all PageIdentities are then proper pages, and the distinction between PageIdentity
55 *   and ProperPageIdentity becomes redundant.
56 *
57 * @note  Code that deserializes instances of PageIdentity must ensure that the original
58 *   meaning of the "local" Wiki ID is preserved if the PageIdentity originated on
59 *   another wiki.
60 *
61 * @stable to type
62 *
63 * @since 1.36
64 */
65interface PageIdentity extends WikiAwareEntity {
66
67	/**
68	 * Get the ID of the wiki this page belongs to.
69	 *
70	 * @note When getId() would throw, the behavior of this method is undefined.
71	 * This is necessary to allow the Title class to implement this interface.
72	 *
73	 * @see RevisionRecord::getWikiId()
74	 *
75	 * @return string|false The wiki's logical name,
76	 *         or self::LOCAL to indicate the local wiki.
77	 */
78	public function getWikiId();
79
80	/**
81	 * Returns the page ID.
82	 *
83	 * If this ID is 0, this means the page does not exist.
84	 *
85	 * Implementations must call assertWiki().
86	 *
87	 * @note As a concession to allowing Title to implement this interface,
88	 *       PageIdentity instances may represent things that are not pages,
89	 *       such as relative section links or interwiki links. If getId()
90	 *       is called on a PageIdentity that does not actually represent a
91	 *       page, it must throw a RuntimeException. The idea is that code that
92	 *       expects a PageIdentity is expecting an actual page.
93	 *       The canExist() method can be used to ensure that it is.
94	 *
95	 * @param string|false $wikiId Must be provided when accessing the ID of a non-local
96	 *        PageIdentity, to prevent data corruption when using a PageIdentity belonging
97	 *        to one wiki in the context of another. Should be omitted if expecting the local wiki.
98	 *
99	 * @return int
100	 * @throws RuntimeException if this PageIdentity is not a "proper"
101	 *         page identity, but e.g. a relative section link, an interwiki
102	 *         link, etc.
103	 * @throws PreconditionException if this PageIdentity does not belong to the wiki
104	 *         identified by $wikiId.
105	 * @see Title::getArticleID()
106	 * @see Title::toPageIdentity()
107	 * @see canExist()
108	 *
109	 */
110	public function getId( $wikiId = self::LOCAL ): int;
111
112	/**
113	 * Checks whether this PageIdentity represents a "proper" page,
114	 * meaning that it could exist as an editable page on the wiki.
115	 *
116	 * @note This method only exists to allow Title to implement this interface.
117	 *       Title instances may represent things that are not pages,
118	 *       such as relative section links or interwiki links.
119	 *       The idea is that code that expects a PageIdentity is expecting an
120	 *       actual page. The canExist() method can be used to ensure that it is.
121	 *
122	 * @note Eventually, this method should be guaranteed to return true,
123	 *       then be deprecated, and then removed.
124	 *
125	 * @return bool
126	 * @see Title::getArticleID()
127	 * @see Title::toPageIdentity()
128	 *
129	 * @see getId()
130	 */
131	public function canExist(): bool;
132
133	/**
134	 * Checks if the page currently exists.
135	 *
136	 * Implementations must ensure that this method returns false
137	 * when getId() would throw or return 0.
138	 * This also implies that this method must return false
139	 * if canExist() would return false.
140	 *
141	 * @see Title::exists()
142	 *
143	 * @return bool
144	 */
145	public function exists(): bool;
146
147	/**
148	 * Returns the page's namespace number.
149	 *
150	 * The value returned by this method should represent a valid namespace,
151	 * but this cannot be guaranteed in all cases.
152	 *
153	 * @note When getId() would throw, the behavior of this method is undefined.
154	 * This is necessary to allow the Title class to implement this interface.
155	 *
156	 * @return int
157	 */
158	public function getNamespace(): int;
159
160	/**
161	 * Get the page title in DB key form.
162	 *
163	 * @note When getId() would throw, the behavior of this method is undefined.
164	 * This is necessary to allow the Title class to implement this interface.
165	 *
166	 * @return string
167	 */
168	public function getDBkey(): string;
169
170	/**
171	 * Checks whether the given PageIdentity refers to the same page as this PageIdentity.
172	 *
173	 * Two PageIdentity instances are considered to refer to the same page if
174	 * the page exists, they belong to the same wiki, and have the same ID;
175	 * or the page does not exist, they belong to the same wiki, and have the
176	 * same namespace and DB key.
177	 *
178	 * @param PageIdentity $other
179	 *
180	 * @return bool
181	 */
182	public function isSamePageAs( PageIdentity $other );
183
184	/**
185	 * Returns an informative human readable representation of the page identity,
186	 * for use in logging and debugging.
187	 *
188	 * @return string
189	 */
190	public function __toString(): string;
191
192}
193