Completed
Pull Request — master (#526)
by Michael
11:09 queued 01:05
created

relativedate()   D

Complexity

Conditions 18
Paths 27

Size

Total Lines 56
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 342

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 18
eloc 38
c 2
b 0
f 0
nc 27
nop 1
dl 0
loc 56
ccs 0
cts 49
cp 0
crap 342
rs 4.8666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**************************************************************************
3
 **********      English Wikipedia Account Request Interface      **********
4
 ***************************************************************************
5
 ** Wikipedia Account Request Graphic Design by Charles Melbye,           **
6
 ** which is licensed under a Creative Commons                            **
7
 ** Attribution-Noncommercial-Share Alike 3.0 United States License.      **
8
 **                                                                       **
9
 ** All other code are released under the Public Domain                   **
10
 ** by the ACC Development Team.                                          **
11
 **                                                                       **
12
 ** See CREDITS for the list of developers.                               **
13
 ***************************************************************************/
14
15
global $ACC;
16
global $baseurl;
17
global $dontUseWikiDb;
18
19
if (!defined("ACC")) {
20
	die();
21
} // Invalid entry point
22
23
require_once 'queryBrowser.php';
24
require_once 'includes/session.php';
25
26
// Initialize the class objects.
27
$session = new session();
28
29
/** Initialises the PHP Session */
30
function initialiseSession() {
31
    session_start();
32
}
33
34
/**
35
 * Send a "close pend ticket" email to the end user. (created, taken, etc...)
36
 */
37
function sendemail($messageno, $target, $id)
38
{
39
	$template = EmailTemplate::getById($messageno, gGetDb());
40
	$headers = 'From: [email protected]';
41
	    
42
	// Get the closing user's Email signature and append it to the Email.
43
	if (User::getCurrent()->getEmailSig() != "") {
44
		$emailsig = html_entity_decode(User::getCurrent()->getEmailSig(), ENT_QUOTES, "UTF-8");
45
		mail($target, "RE: [ACC #$id] English Wikipedia Account Request", $template->getText() . "\n\n" . $emailsig, $headers);
0 ignored issues
show
Bug introduced by
The method getText() does not exist on DataObject. It seems like you code against a sub-type of DataObject such as Notification or EmailTemplate. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

45
		mail($target, "RE: [ACC #$id] English Wikipedia Account Request", $template->/** @scrutinizer ignore-call */ getText() . "\n\n" . $emailsig, $headers);
Loading history...
46
	}
47
	else {
48
		mail($target, "RE: [ACC #$id] English Wikipedia Account Request", $template->getText(), $headers);
49
	}
50
}
51
52
/**
53
 * Returns a value indicating whether the current request was issued over HTTPSs
54
 * @return bool true if HTTPS
55
 */
56
function isHttps()
57
{
58
	if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
59
		if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
60
			// Client <=> Proxy is encrypted
61
			return true;
62
		}
63
		else {
64
			// Proxy <=> Server link is encrypted, but not Client <=> Proxy.
65
			return false;
66
		}
67
	}
68
69
	if (isset($_SERVER['HTTPS'])) {
70
		if ($_SERVER['HTTPS'] === 'off') {
71
			// ISAPI on IIS breaks the spec. :(
72
			return false;
73
		}
74
75
		if ($_SERVER['HTTPS'] !== '') {
76
			// Set to a non-empty value
77
			return true;
78
		}
79
	}
80
81
	return false;
82
}
83
84
/**
85
 * Show the login page
86
 */
87
function showlogin()
88
{
89
	global $smarty;
90
    
91
	// Check whether there are any errors.
92
	$errorbartext = "";
93
	if (isset($_GET['error'])) {
94
		if ($_GET['error'] == 'authfail') {
95
			$errorbartext = BootstrapSkin::displayAlertBox("Username and/or password incorrect. Please try again.", "alert-error", "Auth failure", true, false, true);
96
		}
97
		elseif ($_GET['error'] == 'noid') {
98
			$errorbartext = BootstrapSkin::displayAlertBox("It doesn't look like you've signed the most recent version of the <a href=\"https://meta.wikimedia.org/wiki/Access_to_nonpublic_personal_data_policy\">access to nonpublic personal data policy</a>.</p><p>Please email [email protected] if you believe this is in error.", "alert-error", "Auth failure", true, false, true);
99
		}
100
		elseif ($_GET['error'] == 'newacct') {
101
			$errorbartext = BootstrapSkin::displayAlertBox("I'm sorry, but, your account has not been approved by a site administrator yet. Please stand by.", "alert-info", "Account pending", true, false, true);
102
		}
103
	}
104
	$smarty->assign("errorbar", $errorbartext);   
105
106
	global $strictTransportSecurityExpiry;
107
	if ($strictTransportSecurityExpiry !== false) {
108
		if (isHttps()) {
109
			// Client can clearly use HTTPS, so let's enforce it for all connections.
110
			header("Strict-Transport-Security: max-age=15768000");
111
		}
112
		else {
113
			// This is the login form, not the request form. We need protection here.
114
			$path = 'https://' . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
115
			header("Location: " . $path);
116
		}
117
	}
118
119
	$smarty->display("login.tpl");
120
}
121
122
function defaultpage()
123
{
124
	global $availableRequestStates, $defaultRequestStateKey, $requestLimitShowOnly, $enableEmailConfirm;
125
    
126
	$database = gGetDb();
127
    
128
	$requestSectionData = array();
129
    
130
	if ($enableEmailConfirm == 1) {
131
		$query = "SELECT * FROM request WHERE status = :type AND emailconfirm = 'Confirmed' LIMIT :lim;";
132
		$totalquery = "SELECT COUNT(*) FROM request WHERE status = :type AND emailconfirm = 'Confirmed';";
133
	}
134
	else {
135
		$query = "SELECT * FROM request WHERE status = :type LIMIT :lim;";
136
		$totalquery = "SELECT COUNT(*) FROM request WHERE status = :type;";
137
	}
138
    
139
	$statement = $database->prepare($query);
140
	$statement->bindValue(":lim", $requestLimitShowOnly, PDO::PARAM_INT);
141
    
142
	$totalRequestsStatement = $database->prepare($totalquery);
143
            
144
	// list requests in each section
145
	foreach ($availableRequestStates as $type => $v) {
146
		$statement->bindValue(":type", $type);
147
		$statement->execute();
148
        
149
		$requests = $statement->fetchAll(PDO::FETCH_CLASS, "Request");
150
		foreach ($requests as $req) {
151
			$req->setDatabase($database);   
152
		}
153
154
		$totalRequestsStatement->bindValue(":type", $type);
155
		$totalRequestsStatement->execute();
156
		$totalRequests = $totalRequestsStatement->fetchColumn();
157
		$totalRequestsStatement->closeCursor();
158
        
159
		$requestSectionData[$v['header']] = array(
160
			"requests" => $requests, 
161
			"total" => $totalRequests, 
162
			"api" => $v['api'],
163
            "type" => $type);
164
	}
165
    
166
	global $smarty;
167
	$smarty->assign("requestLimitShowOnly", $requestLimitShowOnly);
168
	
169
	$query = <<<SQL
170
		SELECT request.id, request.name, request.checksum
171
		FROM request 
172
		JOIN log ON log.objectid = request.id and log.objecttype = 'Request'
173
		WHERE log.action LIKE 'Closed%' 
174
		ORDER BY log.timestamp DESC 
175
		LIMIT 5;
176
SQL;
177
    
178
	$statement = $database->prepare($query);
179
	$statement->execute();
180
    
181
	$last5result = $statement->fetchAll(PDO::FETCH_ASSOC);
182
    
183
	$smarty->assign("lastFive", $last5result);
184
	$smarty->assign("requestSectionData", $requestSectionData);
185
	$html = $smarty->fetch("mainpage/mainpage.tpl");
186
    
187
	return $html;
188
}
189
190
function array_search_recursive($needle, $haystack, $path = array())
191
{
192
	foreach ($haystack as $id => $val) {
193
		$path2 = $path;
194
		$path2[] = $id;
195
196
		if ($val === $needle) {
197
				return $path2;
198
		}
199
		else if (is_array($val)) {
200
				if ($ret = array_search_recursive($needle, $val, $path2)) {
201
						return $ret;
202
				}
203
		}
204
	}
205
	return false;
206
}
207
208
require_once('zoompage.php');
209
210
function displayPreview($wikicode)
211
{
212
	$parseresult = unserialize(file_get_contents('http://en.wikipedia.org/w/api.php?action=parse&format=php&text=' . urlencode($wikicode)));
213
	$out = "<br />\n<h3>Preview</h3>\n<div style=\"border: 2px dashed rgb(26, 79, 133);\">\n<div style=\"margin: 20px;\">";
214
	$out .= $parseresult['parse']['text']['*'];
215
	$out .= '</div></div>';
216
	return $out;
217
}
218
219
/**
220
 * Parses an XFF header and client IP to find the last trusted client IP
221
 * 
222
 * @param string $dbip The IP address the request came from
223
 * @param string $dbproxyip The contents of the XFF header of the request
224
 * @return string
225
 */
226
function getTrustedClientIP($dbip, $dbproxyip)
227
{
228
	global $xffTrustProvider;
229
    
230
	$clientIpAddr = $dbip;
231
	if ($dbproxyip) {
232
		$ipList = explode(",", $dbproxyip);
233
		$ipList[] = $clientIpAddr;
234
		$ipList = array_reverse($ipList);
235
		
236
		foreach ($ipList as $ipnumber => $ip) {
237
			if ($xffTrustProvider->isTrusted(trim($ip)) && $ipnumber < (count($ipList) - 1)) {
238
				continue;
239
			}
240
			
241
			$clientIpAddr = $ip;
242
			break;
243
		}
244
	}
245
	
246
	return $clientIpAddr;
247
}
248
249
/**
250
 * Explodes a CIDR range into an array of addresses
251
 * 
252
 * @param string $range A CIDR-format range
253
 * @return array An array containing every IP address in the range
254
 */
255
function explodeCidr($range)
256
{
257
	$ip_arr = explode('/', $range);
258
259
	if (!isset($ip_arr[1])) {
260
		return array($range);
261
	}
262
	
263
	$blow = ( 
264
		str_pad(decbin(ip2long($ip_arr[0])), 32, "0", STR_PAD_LEFT) &
0 ignored issues
show
Bug introduced by
Are you sure you want to use the bitwise & or did you mean &&?
Loading history...
265
		str_pad(str_pad("", $ip_arr[1], "1"), 32, "0") 
0 ignored issues
show
Bug introduced by
$ip_arr[1] of type string is incompatible with the type integer expected by parameter $pad_length of str_pad(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

265
		str_pad(str_pad("", /** @scrutinizer ignore-type */ $ip_arr[1], "1"), 32, "0") 
Loading history...
266
		);
267
	$bhigh = ($blow | str_pad(str_pad("", $ip_arr[1], "0"), 32, "1"));
0 ignored issues
show
Bug introduced by
Are you sure you want to use the bitwise | or did you mean ||?
Loading history...
268
269
	$list = array();
270
271
	$bindecBHigh = bindec($bhigh);
272
	for ($x = bindec($blow); $x <= $bindecBHigh; $x++) {
273
		$list[] = long2ip($x);
274
	}
275
276
	return $list;
277
}
278
279
/**
280
 * Takes an array( "low" => "high" ) values, and returns true if $needle is in at least one of them.
281
 * @param string $ip
282
 * @param array $haystack
283
 */
284
function ipInRange($haystack, $ip)
285
{
286
	$needle = ip2long($ip);
287
288
	foreach ($haystack as $low => $high) {
289
		if (ip2long($low) <= $needle && ip2long($high) >= $needle) {
290
			return true;
291
		}
292
	}
293
    
294
	return false;
295
}
296
297
/**
298
 * @return string
299
 */
300
function welcomerbotRenderSig($creator, $sig)
301
{
302
	$signature = html_entity_decode($sig) . ' ~~~~~';
303
	if (!preg_match("/((\[\[[ ]*(w:)?[ ]*(en:)?)|(\{\{subst:))[ ]*User[ ]*:[ ]*" . $creator . "[ ]*(\]\]|\||\}\}|\/)/i", $signature)) {
304
		$signature = "--[[User:$creator|$creator]] ([[User talk:$creator|talk]]) ~~~~~";
305
	}
306
	return $signature;
307
}
308
309
/**
310
 * Transforms a date string into a relative representation of the date ("2 weeks ago").
311
 * @param string $input A string representing a date
312
 * @return string
313
 * @example {$variable|relativedate} from Smarty
314
 */
315
function relativedate($input)
316
{
317
	$now = new DateTime();
318
	$then = new DateTime($input);
319
    
320
	$secs = $now->getTimestamp() - $then->getTimestamp();
321
    
322
	$second = 1;
323
	$minute = 60 * $second;
324
	$minuteCut = 60 * $second;
325
	$hour = 60 * $minute;
326
	$hourCut = 60 * $minute;
327
	$day = 24 * $hour;
328
	$dayCut = 48 * $hour;
329
	$week = 7 * $day;
330
	$weekCut = 14 * $day;
331
	$month = 30 * $day;
332
	$year = 365 * $day;
333
    
334
	$pluralise = true;
335
    
336
	if ($secs <= 10) {
337
		$output = "just now";
338
		$pluralise = false;
339
	}
340
	elseif ($secs > 10 && $secs < $minuteCut) {
341
		$output = round($secs / $second) . " second";
342
	}
343
	elseif ($secs >= $minuteCut && $secs < $hourCut) {
344
		$output = round($secs / $minute) . " minute";
345
	}
346
	elseif ($secs >= $hourCut && $secs < $dayCut) {
347
		$output = round($secs / $hour) . " hour";
348
	}
349
	elseif ($secs >= $dayCut && $secs < $weekCut) {
350
		$output = round($secs / $day) . " day";
351
	}
352
	elseif ($secs >= $weekCut && $secs < $month) {
353
		$output = round($secs / $week) . " week";
354
	}
355
	elseif ($secs >= $month && $secs < $year) {
356
		$output = round($secs / $month) . " month";
357
	}
358
	elseif ($secs >= $year && $secs < $year * 10) {
359
		$output = round($secs / $year) . " year";
360
	}
361
	else {
362
		$output = "a long time ago";
363
		$pluralise = false;
364
	}
365
    
366
	if ($pluralise) {
367
		$output = (substr($output, 0, 2) <> "1 ") ? $output . "s ago" : $output . " ago";
368
	}
369
370
	return $output;
371
}
372
373
/**
374
 * Summary of reattachOAuthAccount
375
 * @param User $user 
376
 * @throws TransactionException 
377
 */
378
function reattachOAuthAccount(User $user)
379
{
380
	global $oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal;
381
382
	try {
383
		// Get a request token for OAuth
384
		$util = new OAuthUtility($oauthConsumerToken, $oauthSecretToken, $oauthBaseUrl, $oauthBaseUrlInternal);
385
		$requestToken = $util->getRequestToken();
386
387
		// save the request token for later
388
		$user->setOAuthRequestToken($requestToken->key);
389
		$user->setOAuthRequestSecret($requestToken->secret);
390
		$user->save();
391
            
392
		$redirectUrl = $util->getAuthoriseUrl($requestToken);
393
            
394
		header("Location: {$redirectUrl}");
395
		die();
396
	}
397
	catch (Exception $ex) {
398
		throw new TransactionException($ex->getMessage(), "Connection to Wikipedia failed.", "alert-error", 0, $ex);
399
	}     
400
}
401
402
/**
403
 * Generates the JavaScript source for XSS-safe typeahead autocompletion for usernames.  This output is expected to be
404
 * passed as the $tailscript argument to \BootstrapSkin::displayInternalFooter().
405
 *
406
 * @param $users string[] Array of usernames as strings
407
 * @return string
408
 */
409
function getTypeaheadSource($users)
410
{
411
	$userList = "";
412
	foreach ($users as $v) {
413
		$userList .= "\"" . htmlentities($v) . "\", ";
414
	}
415
	$userList = "[" . rtrim($userList, ", ") . "]";
416
	$tailscript = <<<JS
417
$('.username-typeahead').typeahead({
418
	source: {$userList}
419
});
420
JS;
421
	return $tailscript;
422
}
423