]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/WikiMap.php
MediaWiki 1.30.2-scripts2
[autoinstalls/mediawiki.git] / includes / WikiMap.php
1 <?php
2 /**
3  * Tools for dealing with other locally-hosted wikis.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  */
22
23 use MediaWiki\MediaWikiServices;
24 use Wikimedia\Rdbms\DatabaseDomain;
25
26 /**
27  * Helper tools for dealing with other locally-hosted wikis.
28  */
29 class WikiMap {
30
31         /**
32          * Get a WikiReference object for $wikiID
33          *
34          * @param string $wikiID Wiki'd id (generally database name)
35          * @return WikiReference|null WikiReference object or null if the wiki was not found
36          */
37         public static function getWiki( $wikiID ) {
38                 $wikiReference = self::getWikiReferenceFromWgConf( $wikiID );
39                 if ( $wikiReference ) {
40                         return $wikiReference;
41                 }
42
43                 // Try sites, if $wgConf failed
44                 return self::getWikiWikiReferenceFromSites( $wikiID );
45         }
46
47         /**
48          * @param string $wikiID
49          * @return WikiReference|null WikiReference object or null if the wiki was not found
50          */
51         private static function getWikiReferenceFromWgConf( $wikiID ) {
52                 global $wgConf;
53
54                 $wgConf->loadFullData();
55
56                 list( $major, $minor ) = $wgConf->siteFromDB( $wikiID );
57                 if ( $major === null ) {
58                         return null;
59                 }
60                 $server = $wgConf->get( 'wgServer', $wikiID, $major,
61                         [ 'lang' => $minor, 'site' => $major ] );
62
63                 $canonicalServer = $wgConf->get( 'wgCanonicalServer', $wikiID, $major,
64                         [ 'lang' => $minor, 'site' => $major ] );
65                 if ( $canonicalServer === false || $canonicalServer === null ) {
66                         $canonicalServer = $server;
67                 }
68
69                 $path = $wgConf->get( 'wgArticlePath', $wikiID, $major,
70                         [ 'lang' => $minor, 'site' => $major ] );
71
72                 // If we don't have a canonical server or a path containing $1, the
73                 // WikiReference isn't going to function properly. Just return null in
74                 // that case.
75                 if ( !is_string( $canonicalServer ) || !is_string( $path ) || strpos( $path, '$1' ) === false ) {
76                         return null;
77                 }
78
79                 return new WikiReference( $canonicalServer, $path, $server );
80         }
81
82         /**
83          * @param string $wikiID
84          * @return WikiReference|null WikiReference object or null if the wiki was not found
85          */
86         private static function getWikiWikiReferenceFromSites( $wikiID ) {
87                 $siteLookup = MediaWikiServices::getInstance()->getSiteLookup();
88                 $site = $siteLookup->getSite( $wikiID );
89
90                 if ( !$site instanceof MediaWikiSite ) {
91                         // Abort if not a MediaWikiSite, as this is about Wikis
92                         return null;
93                 }
94
95                 $urlParts = wfParseUrl( $site->getPageUrl() );
96                 if ( $urlParts === false || !isset( $urlParts['path'] ) || !isset( $urlParts['host'] ) ) {
97                         // We can't create a meaningful WikiReference without URLs
98                         return null;
99                 }
100
101                 // XXX: Check whether path contains a $1?
102                 $path = $urlParts['path'];
103                 if ( isset( $urlParts['query'] ) ) {
104                         $path .= '?' . $urlParts['query'];
105                 }
106
107                 $canonicalServer = isset( $urlParts['scheme'] ) ? $urlParts['scheme'] : 'http';
108                 $canonicalServer .= '://' . $urlParts['host'];
109
110                 return new WikiReference( $canonicalServer, $path );
111         }
112
113         /**
114          * Convenience to get the wiki's display name
115          *
116          * @todo We can give more info than just the wiki id!
117          * @param string $wikiID Wiki'd id (generally database name)
118          * @return string|int Wiki's name or $wiki_id if the wiki was not found
119          */
120         public static function getWikiName( $wikiID ) {
121                 $wiki = self::getWiki( $wikiID );
122
123                 if ( $wiki ) {
124                         return $wiki->getDisplayName();
125                 }
126                 return $wikiID;
127         }
128
129         /**
130          * Convenience to get a link to a user page on a foreign wiki
131          *
132          * @param string $wikiID Wiki'd id (generally database name)
133          * @param string $user User name (must be normalised before calling this function!)
134          * @param string $text Link's text; optional, default to "User:$user"
135          * @return string HTML link or false if the wiki was not found
136          */
137         public static function foreignUserLink( $wikiID, $user, $text = null ) {
138                 return self::makeForeignLink( $wikiID, "User:$user", $text );
139         }
140
141         /**
142          * Convenience to get a link to a page on a foreign wiki
143          *
144          * @param string $wikiID Wiki'd id (generally database name)
145          * @param string $page Page name (must be normalised before calling this function!)
146          * @param string $text Link's text; optional, default to $page
147          * @return string|false HTML link or false if the wiki was not found
148          */
149         public static function makeForeignLink( $wikiID, $page, $text = null ) {
150                 if ( !$text ) {
151                         $text = $page;
152                 }
153
154                 $url = self::getForeignURL( $wikiID, $page );
155                 if ( $url === false ) {
156                         return false;
157                 }
158
159                 return Linker::makeExternalLink( $url, $text );
160         }
161
162         /**
163          * Convenience to get a url to a page on a foreign wiki
164          *
165          * @param string $wikiID Wiki'd id (generally database name)
166          * @param string $page Page name (must be normalised before calling this function!)
167          * @param string|null $fragmentId
168          *
169          * @return string|bool URL or false if the wiki was not found
170          */
171         public static function getForeignURL( $wikiID, $page, $fragmentId = null ) {
172                 $wiki = self::getWiki( $wikiID );
173
174                 if ( $wiki ) {
175                         return $wiki->getFullUrl( $page, $fragmentId );
176                 }
177
178                 return false;
179         }
180
181         /**
182          * Get canonical server info for all local wikis in the map that have one
183          *
184          * @return array Map of (local wiki ID => map of (url,parts))
185          * @since 1.30
186          */
187         public static function getCanonicalServerInfoForAllWikis() {
188                 $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
189
190                 return $cache->getWithSetCallback(
191                         $cache->makeGlobalKey( 'wikimap', 'canonical-urls' ),
192                         $cache::TTL_DAY,
193                         function () {
194                                 global $wgLocalDatabases, $wgCanonicalServer;
195
196                                 $infoMap = [];
197                                 // Make sure at least the current wiki is set, for simple configurations.
198                                 // This also makes it the first in the map, which is useful for common cases.
199                                 $infoMap[wfWikiID()] = [
200                                         'url' => $wgCanonicalServer,
201                                         'parts' => wfParseUrl( $wgCanonicalServer )
202                                 ];
203
204                                 foreach ( $wgLocalDatabases as $wikiId ) {
205                                         $wikiReference = self::getWiki( $wikiId );
206                                         if ( $wikiReference ) {
207                                                 $url = $wikiReference->getCanonicalServer();
208                                                 $infoMap[$wikiId] = [ 'url' => $url, 'parts' => wfParseUrl( $url ) ];
209                                         }
210                                 }
211
212                                 return $infoMap;
213                         }
214                 );
215         }
216
217         /**
218          * @param string $url
219          * @return bool|string Wiki ID or false
220          * @since 1.30
221          */
222         public static function getWikiFromUrl( $url ) {
223                 $urlPartsCheck = wfParseUrl( $url );
224                 if ( $urlPartsCheck === false ) {
225                         return false;
226                 }
227
228                 $urlPartsCheck = array_intersect_key( $urlPartsCheck, [ 'host' => 1, 'port' => 1 ] );
229                 foreach ( self::getCanonicalServerInfoForAllWikis() as $wikiId => $info ) {
230                         $urlParts = $info['parts'];
231                         if ( $urlParts === false ) {
232                                 continue; // sanity
233                         }
234
235                         $urlParts = array_intersect_key( $urlParts, [ 'host' => 1, 'port' => 1 ] );
236                         if ( $urlParts == $urlPartsCheck ) {
237                                 return $wikiId;
238                         }
239                 }
240
241                 return false;
242         }
243
244         /**
245          * Get the wiki ID of a database domain
246          *
247          * This is like DatabaseDomain::getId() without encoding (for legacy reasons)
248          *
249          * @param string|DatabaseDomain $domain
250          * @return string
251          */
252         public static function getWikiIdFromDomain( $domain ) {
253                 if ( !( $domain instanceof DatabaseDomain ) ) {
254                         $domain = DatabaseDomain::newFromId( $domain );
255                 }
256
257                 return strlen( $domain->getTablePrefix() )
258                         ? "{$domain->getDatabase()}-{$domain->getTablePrefix()}"
259                         : $domain->getDatabase();
260         }
261 }