ApiQueryExtLinksUsage   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 206
Duplicated Lines 7.28 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 15
loc 206
rs 9.6
c 0
b 0
f 0
wmc 32
lcom 1
cbo 7

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A execute() 0 3 1
A getCacheMode() 0 3 1
A executeGenerator() 0 3 1
F run() 15 99 16
B getAllowedParams() 0 43 2
A prepareProtocols() 0 11 3
B getProtocolPrefix() 0 16 5
A getExamplesMessages() 0 6 1
A getHelpUrls() 0 3 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 *
4
 *
5
 * Created on July 7, 2007
6
 *
7
 * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License along
20
 * with this program; if not, write to the Free Software Foundation, Inc.,
21
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
 * http://www.gnu.org/copyleft/gpl.html
23
 *
24
 * @file
25
 */
26
27
/**
28
 * @ingroup API
29
 */
30
class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
31
32
	public function __construct( ApiQuery $query, $moduleName ) {
33
		parent::__construct( $query, $moduleName, 'eu' );
34
	}
35
36
	public function execute() {
37
		$this->run();
38
	}
39
40
	public function getCacheMode( $params ) {
41
		return 'public';
42
	}
43
44
	public function executeGenerator( $resultPageSet ) {
45
		$this->run( $resultPageSet );
46
	}
47
48
	/**
49
	 * @param ApiPageSet $resultPageSet
50
	 * @return void
51
	 */
52
	private function run( $resultPageSet = null ) {
53
		$params = $this->extractRequestParams();
54
55
		$query = $params['query'];
56
		$protocol = self::getProtocolPrefix( $params['protocol'] );
57
58
		$this->addTables( [ 'page', 'externallinks' ] ); // must be in this order for 'USE INDEX'
59
		$this->addOption( 'USE INDEX', 'el_index' );
60
		$this->addWhere( 'page_id=el_from' );
61
62
		$miser_ns = [];
63 View Code Duplication
		if ( $this->getConfig()->get( 'MiserMode' ) ) {
64
			$miser_ns = $params['namespace'];
65
		} else {
66
			$this->addWhereFld( 'page_namespace', $params['namespace'] );
67
		}
68
69
		// Normalize query to match the normalization applied for the externallinks table
70
		$query = Parser::normalizeLinkUrl( $query );
71
72
		$whereQuery = $this->prepareUrlQuerySearchString( $query, $protocol );
73
74
		if ( $whereQuery !== null ) {
75
			$this->addWhere( $whereQuery );
76
		}
77
78
		$prop = array_flip( $params['prop'] );
79
		$fld_ids = isset( $prop['ids'] );
80
		$fld_title = isset( $prop['title'] );
81
		$fld_url = isset( $prop['url'] );
82
83 View Code Duplication
		if ( is_null( $resultPageSet ) ) {
84
			$this->addFields( [
85
				'page_id',
86
				'page_namespace',
87
				'page_title'
88
			] );
89
			$this->addFieldsIf( 'el_to', $fld_url );
90
		} else {
91
			$this->addFields( $resultPageSet->getPageTableFields() );
92
		}
93
94
		$limit = $params['limit'];
95
		$offset = $params['offset'];
96
		$this->addOption( 'LIMIT', $limit + 1 );
97
		if ( isset( $offset ) ) {
98
			$this->addOption( 'OFFSET', $offset );
99
		}
100
101
		$res = $this->select( __METHOD__ );
102
103
		$result = $this->getResult();
104
		$count = 0;
105
		foreach ( $res as $row ) {
106
			if ( ++$count > $limit ) {
107
				// We've reached the one extra which shows that there are
108
				// additional pages to be had. Stop here...
109
				$this->setContinueEnumParameter( 'offset', $offset + $limit );
110
				break;
111
			}
112
113
			if ( count( $miser_ns ) && !in_array( $row->page_namespace, $miser_ns ) ) {
114
				continue;
115
			}
116
117
			if ( is_null( $resultPageSet ) ) {
118
				$vals = [
119
					ApiResult::META_TYPE => 'assoc',
120
				];
121
				if ( $fld_ids ) {
122
					$vals['pageid'] = intval( $row->page_id );
123
				}
124
				if ( $fld_title ) {
125
					$title = Title::makeTitle( $row->page_namespace, $row->page_title );
126
					ApiQueryBase::addTitleInfo( $vals, $title );
127
				}
128
				if ( $fld_url ) {
129
					$to = $row->el_to;
130
					// expand protocol-relative urls
131
					if ( $params['expandurl'] ) {
132
						$to = wfExpandUrl( $to, PROTO_CANONICAL );
133
					}
134
					$vals['url'] = $to;
135
				}
136
				$fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $vals );
137
				if ( !$fit ) {
138
					$this->setContinueEnumParameter( 'offset', $offset + $count - 1 );
139
					break;
140
				}
141
			} else {
142
				$resultPageSet->processDbRow( $row );
0 ignored issues
show
Bug introduced by
It seems like $row defined by $row on line 105 can be null; however, ApiPageSet::processDbRow() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
143
			}
144
		}
145
146
		if ( is_null( $resultPageSet ) ) {
147
			$result->addIndexedTagName( [ 'query', $this->getModuleName() ],
148
				$this->getModulePrefix() );
149
		}
150
	}
151
152
	public function getAllowedParams() {
153
		$ret = [
154
			'prop' => [
155
				ApiBase::PARAM_ISMULTI => true,
156
				ApiBase::PARAM_DFLT => 'ids|title|url',
157
				ApiBase::PARAM_TYPE => [
158
					'ids',
159
					'title',
160
					'url'
161
				],
162
				ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
163
			],
164
			'offset' => [
165
				ApiBase::PARAM_TYPE => 'integer',
166
				ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
167
			],
168
			'protocol' => [
169
				ApiBase::PARAM_TYPE => self::prepareProtocols(),
170
				ApiBase::PARAM_DFLT => '',
171
			],
172
			'query' => null,
173
			'namespace' => [
174
				ApiBase::PARAM_ISMULTI => true,
175
				ApiBase::PARAM_TYPE => 'namespace'
176
			],
177
			'limit' => [
178
				ApiBase::PARAM_DFLT => 10,
179
				ApiBase::PARAM_TYPE => 'limit',
180
				ApiBase::PARAM_MIN => 1,
181
				ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
182
				ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
183
			],
184
			'expandurl' => false,
185
		];
186
187
		if ( $this->getConfig()->get( 'MiserMode' ) ) {
188
			$ret['namespace'][ApiBase::PARAM_HELP_MSG_APPEND] = [
189
				'api-help-param-limited-in-miser-mode',
190
			];
191
		}
192
193
		return $ret;
194
	}
195
196
	public static function prepareProtocols() {
197
		global $wgUrlProtocols;
198
		$protocols = [ '' ];
199
		foreach ( $wgUrlProtocols as $p ) {
200
			if ( $p !== '//' ) {
201
				$protocols[] = substr( $p, 0, strpos( $p, ':' ) );
202
			}
203
		}
204
205
		return $protocols;
206
	}
207
208
	public static function getProtocolPrefix( $protocol ) {
209
		// Find the right prefix
210
		global $wgUrlProtocols;
211
		if ( $protocol && !in_array( $protocol, $wgUrlProtocols ) ) {
212
			foreach ( $wgUrlProtocols as $p ) {
213
				if ( substr( $p, 0, strlen( $protocol ) ) === $protocol ) {
214
					$protocol = $p;
215
					break;
216
				}
217
			}
218
219
			return $protocol;
220
		} else {
221
			return null;
222
		}
223
	}
224
225
	protected function getExamplesMessages() {
226
		return [
227
			'action=query&list=exturlusage&euquery=www.mediawiki.org'
228
				=> 'apihelp-query+exturlusage-example-simple',
229
		];
230
	}
231
232
	public function getHelpUrls() {
233
		return 'https://www.mediawiki.org/wiki/API:Exturlusage';
234
	}
235
}
236