]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/title/NamespaceAwareForeignTitleFactory.php
MediaWiki 1.30.2-scripts2
[autoinstalls/mediawiki.git] / includes / title / NamespaceAwareForeignTitleFactory.php
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  * @license GPL 2+
20  */
21
22 /**
23  * A parser that translates page titles on a foreign wiki into ForeignTitle
24  * objects, using information about the namespace setup on the foreign site.
25  */
26 class NamespaceAwareForeignTitleFactory implements ForeignTitleFactory {
27         /**
28          * @var array
29          */
30         protected $foreignNamespaces;
31         /**
32          * @var array
33          */
34         private $foreignNamespacesFlipped;
35
36         /**
37          * Normalizes an array name for $foreignNamespacesFlipped.
38          * @param string $name
39          * @return string
40          */
41         private function normalizeNamespaceName( $name ) {
42                 return strtolower( str_replace( ' ', '_', $name ) );
43         }
44
45         /**
46          * @param array|null $foreignNamespaces An array 'id' => 'name' which contains
47          * the complete namespace setup of the foreign wiki. Such data could be
48          * obtained from siteinfo/namespaces in an XML dump file, or by an action API
49          * query such as api.php?action=query&meta=siteinfo&siprop=namespaces. If
50          * this data is unavailable, use NaiveForeignTitleFactory instead.
51          */
52         public function __construct( $foreignNamespaces ) {
53                 $this->foreignNamespaces = $foreignNamespaces;
54                 if ( !is_null( $foreignNamespaces ) ) {
55                         $this->foreignNamespacesFlipped = [];
56                         foreach ( $foreignNamespaces as $id => $name ) {
57                                 $newKey = self::normalizeNamespaceName( $name );
58                                 $this->foreignNamespacesFlipped[$newKey] = $id;
59                         }
60                 }
61         }
62
63         /**
64          * Creates a ForeignTitle object based on the page title, and optionally the
65          * namespace ID, of a page on a foreign wiki. These values could be, for
66          * example, the <title> and <ns> attributes found in an XML dump.
67          *
68          * @param string $title The page title
69          * @param int|null $ns The namespace ID, or null if this data is not available
70          * @return ForeignTitle
71          */
72         public function createForeignTitle( $title, $ns = null ) {
73                 // Export schema version 0.5 and earlier (MW 1.18 and earlier) does not
74                 // contain a <ns> tag, so we need to be able to handle that case.
75                 if ( is_null( $ns ) ) {
76                         return self::parseTitleNoNs( $title );
77                 } else {
78                         return self::parseTitleWithNs( $title, $ns );
79                 }
80         }
81
82         /**
83          * Helper function to parse the title when the namespace ID is not specified.
84          *
85          * @param string $title
86          * @return ForeignTitle
87          */
88         protected function parseTitleNoNs( $title ) {
89                 $pieces = explode( ':', $title, 2 );
90                 $key = self::normalizeNamespaceName( $pieces[0] );
91
92                 // Does the part before the colon match a known namespace? Check the
93                 // foreign namespaces
94                 $isNamespacePartValid = isset( $this->foreignNamespacesFlipped[$key] );
95
96                 if ( count( $pieces ) === 2 && $isNamespacePartValid ) {
97                         list( $namespaceName, $pageName ) = $pieces;
98                         $ns = $this->foreignNamespacesFlipped[$key];
99                 } else {
100                         $namespaceName = '';
101                         $pageName = $title;
102                         $ns = 0;
103                 }
104
105                 return new ForeignTitle( $ns, $namespaceName, $pageName );
106         }
107
108         /**
109          * Helper function to parse the title when the namespace value is known.
110          *
111          * @param string $title
112          * @param int $ns
113          * @return ForeignTitle
114          */
115         protected function parseTitleWithNs( $title, $ns ) {
116                 $pieces = explode( ':', $title, 2 );
117
118                 // Is $title of the form Namespace:Title (true), or just Title (false)?
119                 $titleIncludesNamespace = ( $ns != '0' && count( $pieces ) === 2 );
120
121                 if ( isset( $this->foreignNamespaces[$ns] ) ) {
122                         $namespaceName = $this->foreignNamespaces[$ns];
123                 } else {
124                         // If the foreign wiki is misconfigured, XML dumps can contain a page with
125                         // a non-zero namespace ID, but whose title doesn't contain a colon
126                         // (T114115). In those cases, output a made-up namespace name to avoid
127                         // collisions. The ImportTitleFactory might replace this with something
128                         // more appropriate.
129                         $namespaceName = $titleIncludesNamespace ? $pieces[0] : "Ns$ns";
130                 }
131
132                 // We assume that the portion of the page title before the colon is the
133                 // namespace name, except in the case of namespace 0.
134                 if ( $titleIncludesNamespace ) {
135                         $pageName = $pieces[1];
136                 } else {
137                         $pageName = $title;
138                 }
139
140                 return new ForeignTitle( $ns, $namespaceName, $pageName );
141         }
142 }