Completed
Branch master (1b526b)
by
unknown
29:06
created

SpecialBookSources   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 180
rs 10
wmc 25
lcom 1
cbo 11

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A execute() 0 21 4
C isValidISBN() 0 37 11
A cleanIsbn() 0 3 1
A buildForm() 0 19 1
B showList() 0 39 5
A makeListItem() 0 7 1
A getGroupName() 0 3 1
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 <[email protected]>
29
 * @ingroup SpecialPage
30
 */
31
class SpecialBookSources extends SpecialPage {
32
	/**
33
	 * ISBN passed to the page, if any
34
	 */
35
	protected $isbn = '';
36
37
	public function __construct() {
38
		parent::__construct( 'Booksources' );
39
	}
40
41
	/**
42
	 * Show the special page
43
	 *
44
	 * @param string $isbn ISBN passed as a subpage parameter
45
	 */
46
	public function execute( $isbn ) {
47
		$out = $this->getOutput();
48
49
		$this->setHeaders();
50
		$this->outputHeader();
51
52
		$this->isbn = self::cleanIsbn( $isbn ?: $this->getRequest()->getText( 'isbn' ) );
53
54
		$this->buildForm();
55
56
		if ( $this->isbn !== '' ) {
57
			if ( !self::isValidISBN( $this->isbn ) ) {
58
				$out->wrapWikiMsg(
59
					"<div class=\"error\">\n$1\n</div>",
60
					'booksources-invalid-isbn'
61
				);
62
			}
63
64
			$this->showList();
65
		}
66
	}
67
68
	/**
69
	 * Return whether a given ISBN (10 or 13) is valid.
70
	 *
71
	 * @param string $isbn ISBN passed for check
72
	 * @return bool
73
	 */
74
	public static function isValidISBN( $isbn ) {
75
		$isbn = self::cleanIsbn( $isbn );
76
		$sum = 0;
77
		if ( strlen( $isbn ) == 13 ) {
78
			for ( $i = 0; $i < 12; $i++ ) {
79
				if ( $isbn[$i] === 'X' ) {
80
					return false;
81
				} elseif ( $i % 2 == 0 ) {
82
					$sum += $isbn[$i];
83
				} else {
84
					$sum += 3 * $isbn[$i];
85
				}
86
			}
87
88
			$check = ( 10 - ( $sum % 10 ) ) % 10;
89
			if ( (string)$check === $isbn[12] ) {
90
				return true;
91
			}
92
		} elseif ( strlen( $isbn ) == 10 ) {
93
			for ( $i = 0; $i < 9; $i++ ) {
94
				if ( $isbn[$i] === 'X' ) {
95
					return false;
96
				}
97
				$sum += $isbn[$i] * ( $i + 1 );
98
			}
99
100
			$check = $sum % 11;
101
			if ( $check == 10 ) {
102
				$check = "X";
103
			}
104
			if ( (string)$check === $isbn[9] ) {
105
				return true;
106
			}
107
		}
108
109
		return false;
110
	}
111
112
	/**
113
	 * Trim ISBN and remove characters which aren't required
114
	 *
115
	 * @param string $isbn Unclean ISBN
116
	 * @return string
117
	 */
118
	private static function cleanIsbn( $isbn ) {
119
		return trim( preg_replace( '![^0-9X]!', '', $isbn ) );
120
	}
121
122
	/**
123
	 * Generate a form to allow users to enter an ISBN
124
	 */
125
	private function buildForm() {
126
		$formDescriptor = [
127
			'isbn' => [
128
				'type' => 'text',
129
				'name' => 'isbn',
130
				'label-message' => 'booksources-isbn',
131
				'default' => $this->isbn,
132
				'autofocus' => true,
133
				'required' => true,
134
			],
135
		];
136
137
		$htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $htmlForm is correct as \HTMLForm::factory('ooui...m()->displayForm(false) (which targets HTMLForm::displayForm()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Unused Code introduced by
$htmlForm is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
138
			->setWrapperLegendMsg( 'booksources-search-legend' )
139
			->setSubmitTextMsg( 'booksources-search' )
140
			->setMethod( 'get' )
141
			->prepareForm()
142
			->displayForm( false );
143
	}
144
145
	/**
146
	 * Determine where to get the list of book sources from,
147
	 * format and output them
148
	 *
149
	 * @throws MWException
150
	 * @return bool
151
	 */
152
	private function showList() {
153
		$out = $this->getOutput();
154
155
		global $wgContLang;
156
157
		# Hook to allow extensions to insert additional HTML,
158
		# e.g. for API-interacting plugins and so on
159
		Hooks::run( 'BookInformation', [ $this->isbn, $out ] );
160
161
		# Check for a local page such as Project:Book_sources and use that if available
162
		$page = $this->msg( 'booksources' )->inContentLanguage()->text();
163
		$title = Title::makeTitleSafe( NS_PROJECT, $page ); # Show list in content language
164
		if ( is_object( $title ) && $title->exists() ) {
165
			$rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
166
			$content = $rev->getContent();
167
168
			if ( $content instanceof TextContent ) {
169
				// XXX: in the future, this could be stored as structured data, defining a list of book sources
170
171
				$text = $content->getNativeData();
172
				$out->addWikiText( str_replace( 'MAGICNUMBER', $this->isbn, $text ) );
173
174
				return true;
175
			} else {
176
				throw new MWException( "Unexpected content type for book sources: " . $content->getModel() );
177
			}
178
		}
179
180
		# Fall back to the defaults given in the language file
181
		$out->addWikiMsg( 'booksources-text' );
182
		$out->addHTML( '<ul>' );
183
		$items = $wgContLang->getBookstoreList();
184
		foreach ( $items as $label => $url ) {
185
			$out->addHTML( $this->makeListItem( $label, $url ) );
186
		}
187
		$out->addHTML( '</ul>' );
188
189
		return true;
190
	}
191
192
	/**
193
	 * Format a book source list item
194
	 *
195
	 * @param string $label Book source label
196
	 * @param string $url Book source URL
197
	 * @return string
198
	 */
199
	private function makeListItem( $label, $url ) {
200
		$url = str_replace( '$1', $this->isbn, $url );
201
202
		return Html::rawElement( 'li', [],
203
			Html::element( 'a', [ 'href' => $url, 'class' => 'external' ], $label )
204
		);
205
	}
206
207
	protected function getGroupName() {
208
		return 'wiki';
209
	}
210
}
211