]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/specials/SpecialBooksources.php
MediaWiki 1.30.2 renames
[autoinstallsdev/mediawiki.git] / includes / specials / SpecialBooksources.php
1 <?php
2 /**
3  * Implements Special:Booksources
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  * @ingroup SpecialPage
22  */
23
24 /**
25  * Special page outputs information on sourcing a book with a particular ISBN
26  * The parser creates links to this page when dealing with ISBNs in wikitext
27  *
28  * @author Rob Church <robchur@gmail.com>
29  * @ingroup SpecialPage
30  */
31 class SpecialBookSources extends SpecialPage {
32         public function __construct() {
33                 parent::__construct( 'Booksources' );
34         }
35
36         /**
37          * Show the special page
38          *
39          * @param string $isbn ISBN passed as a subpage parameter
40          */
41         public function execute( $isbn ) {
42                 $out = $this->getOutput();
43
44                 $this->setHeaders();
45                 $this->outputHeader();
46
47                 // User provided ISBN
48                 $isbn = $isbn ?: $this->getRequest()->getText( 'isbn' );
49                 $isbn = trim( $isbn );
50
51                 $this->buildForm( $isbn );
52
53                 if ( $isbn !== '' ) {
54                         if ( !self::isValidISBN( $isbn ) ) {
55                                 $out->wrapWikiMsg(
56                                         "<div class=\"error\">\n$1\n</div>",
57                                         'booksources-invalid-isbn'
58                                 );
59                         }
60
61                         $this->showList( $isbn );
62                 }
63         }
64
65         /**
66          * Return whether a given ISBN (10 or 13) is valid.
67          *
68          * @param string $isbn ISBN passed for check
69          * @return bool
70          */
71         public static function isValidISBN( $isbn ) {
72                 $isbn = self::cleanIsbn( $isbn );
73                 $sum = 0;
74                 if ( strlen( $isbn ) == 13 ) {
75                         for ( $i = 0; $i < 12; $i++ ) {
76                                 if ( $isbn[$i] === 'X' ) {
77                                         return false;
78                                 } elseif ( $i % 2 == 0 ) {
79                                         $sum += $isbn[$i];
80                                 } else {
81                                         $sum += 3 * $isbn[$i];
82                                 }
83                         }
84
85                         $check = ( 10 - ( $sum % 10 ) ) % 10;
86                         if ( (string)$check === $isbn[12] ) {
87                                 return true;
88                         }
89                 } elseif ( strlen( $isbn ) == 10 ) {
90                         for ( $i = 0; $i < 9; $i++ ) {
91                                 if ( $isbn[$i] === 'X' ) {
92                                         return false;
93                                 }
94                                 $sum += $isbn[$i] * ( $i + 1 );
95                         }
96
97                         $check = $sum % 11;
98                         if ( $check == 10 ) {
99                                 $check = "X";
100                         }
101                         if ( (string)$check === $isbn[9] ) {
102                                 return true;
103                         }
104                 }
105
106                 return false;
107         }
108
109         /**
110          * Trim ISBN and remove characters which aren't required
111          *
112          * @param string $isbn Unclean ISBN
113          * @return string
114          */
115         private static function cleanIsbn( $isbn ) {
116                 return trim( preg_replace( '![^0-9X]!', '', $isbn ) );
117         }
118
119         /**
120          * Generate a form to allow users to enter an ISBN
121          *
122          * @param string $isbn
123          */
124         private function buildForm( $isbn ) {
125                 $formDescriptor = [
126                         'isbn' => [
127                                 'type' => 'text',
128                                 'name' => 'isbn',
129                                 'label-message' => 'booksources-isbn',
130                                 'default' => $isbn,
131                                 'autofocus' => true,
132                                 'required' => true,
133                         ],
134                 ];
135
136                 $context = new DerivativeContext( $this->getContext() );
137                 $context->setTitle( $this->getPageTitle() );
138                 HTMLForm::factory( 'ooui', $formDescriptor, $context )
139                         ->setWrapperLegendMsg( 'booksources-search-legend' )
140                         ->setSubmitTextMsg( 'booksources-search' )
141                         ->setMethod( 'get' )
142                         ->prepareForm()
143                         ->displayForm( false );
144         }
145
146         /**
147          * Determine where to get the list of book sources from,
148          * format and output them
149          *
150          * @param string $isbn
151          * @throws MWException
152          * @return bool
153          */
154         private function showList( $isbn ) {
155                 $out = $this->getOutput();
156
157                 global $wgContLang;
158
159                 $isbn = self::cleanIsbn( $isbn );
160                 # Hook to allow extensions to insert additional HTML,
161                 # e.g. for API-interacting plugins and so on
162                 Hooks::run( 'BookInformation', [ $isbn, $out ] );
163
164                 # Check for a local page such as Project:Book_sources and use that if available
165                 $page = $this->msg( 'booksources' )->inContentLanguage()->text();
166                 $title = Title::makeTitleSafe( NS_PROJECT, $page ); # Show list in content language
167                 if ( is_object( $title ) && $title->exists() ) {
168                         $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
169                         $content = $rev->getContent();
170
171                         if ( $content instanceof TextContent ) {
172                                 // XXX: in the future, this could be stored as structured data, defining a list of book sources
173
174                                 $text = $content->getNativeData();
175                                 $out->addWikiText( str_replace( 'MAGICNUMBER', $isbn, $text ) );
176
177                                 return true;
178                         } else {
179                                 throw new MWException( "Unexpected content type for book sources: " . $content->getModel() );
180                         }
181                 }
182
183                 # Fall back to the defaults given in the language file
184                 $out->addWikiMsg( 'booksources-text' );
185                 $out->addHTML( '<ul>' );
186                 $items = $wgContLang->getBookstoreList();
187                 foreach ( $items as $label => $url ) {
188                         $out->addHTML( $this->makeListItem( $isbn, $label, $url ) );
189                 }
190                 $out->addHTML( '</ul>' );
191
192                 return true;
193         }
194
195         /**
196          * Format a book source list item
197          *
198          * @param string $isbn
199          * @param string $label Book source label
200          * @param string $url Book source URL
201          * @return string
202          */
203         private function makeListItem( $isbn, $label, $url ) {
204                 $url = str_replace( '$1', $isbn, $url );
205
206                 return Html::rawElement( 'li', [],
207                         Html::element( 'a', [ 'href' => $url, 'class' => 'external' ], $label )
208                 );
209         }
210
211         protected function getGroupName() {
212                 return 'wiki';
213         }
214 }