Krinkle has uploaded a new change for review. https://gerrit.wikimedia.org/r/174894
Change subject: Enforce coding style ...................................................................... Enforce coding style * Trim trailing whitespace. * Convert Windows (CR) to Git native new lines (LF). * Set up composer-test and enforce phpcs rules (added a few exceptions to keep clean up minimal). Change-Id: I4c61ce67c60569b47462ac4525d6ffcbeb55e3e3 --- A .gitignore M app.php A composer.json M index.php M lb/exception.php M lb/guc.php M lb/wikicontribs.php A phpcs.xml M settings.php 9 files changed, 565 insertions(+), 476 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/labs/tools/guc refs/changes/94/174894/1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7579f74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor +composer.lock diff --git a/app.php b/app.php index 5687de6..3ccbdab 100644 --- a/app.php +++ b/app.php @@ -1,46 +1,48 @@ <?php - -/* +/** * Copyright 2014 by Luxo - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -class lb_app { +class lb_app +{ private $times = array(); private $clusters = array(); + /** - * Öffnet eine Verbindung zur Datenbank - * @param type $database - * @return PDO Verbindung + * Open a connection to the database. + * + * @param string $database + * @param int|string $cluster + * @return PDO */ - private function openDB($database = 'wikidatawiki',$cluster = null) { + private function openDB($database = 'wikidatawiki', $cluster = null) { $this->aTP('Open new Connection to '.$cluster); - if(is_string($database)) { + if (is_string($database)) { $host = $database.'.labsdb'; $dbname = $database.'_p'; } - if(is_int($cluster)) { + if (is_int($cluster)) { $host = 's'.$cluster.'.labsdb'; - $dbname = (is_string($database)) ? $database.'_p': 'information_schema'; + $dbname = (is_string($database)) ? $database.'_p': 'information_schema'; } - - if(is_string($cluster)) { + + if (is_string($cluster)) { $host = $cluster; - $dbname = (is_string($database)) ? $database.'_p': 'information_schema'; + $dbname = (is_string($database)) ? $database.'_p': 'information_schema'; } - + //Verbindung aufbauen try { $pdo = new PDO('mysql:host='.$host.';dbname='.$dbname.';', settings::getSetting('user'), settings::getSetting('password')); @@ -49,96 +51,98 @@ } return $pdo; } - + /** * Gibt die Verbindung zu einem Wiki zurück (cache) - * @staticvar array $cluster + * * @param string $database - * @return PDO Verbindung + * @param $clusterNr + * @return PDO */ - public function getDB($database = 'meta',$clusterNr = 's1.labsdb') { + public function getDB($database = 'meta', $clusterNr = 's1.labsdb') { $con = null; - - if(!$clusterNr) { + + if (!$clusterNr) { throw new lb_Exception("try to open DB without cluster specification"); - } - //bereits vorhanden? - if(key_exists($clusterNr, $this->clusters)) { + } + // Bereits vorhanden? + if (key_exists($clusterNr, $this->clusters)) { $con = $this->clusters[$clusterNr]; } else { - //Datenbankverbindung öffnen + // Datenbankverbindung öffnen $con = $this->openDB($database, $clusterNr); } - //Datenbank auswählen + // Datenbank auswählen $m = $con->prepare('USE `'.$database.'_p`;'); $m->execute(); unset($m); - - //Verbindung ablegen + + // Verbindung ablegen $this->clusters[$clusterNr] = $con; - + return $con; } - + public function aTP($text) { $this->times[] = array(microtime(true), $text); } - + public function printTimes() { $this->aTP("Finish"); $timebefore = null; $first = null; - foreach($this->times as $nr => $data) { - + foreach ($this->times as $nr => $data) { + $diff = ($timebefore === null) ? 0.0 : $data[0] - $timebefore; - if($timebefore === null) $first = $data[0]; - print('+'.round($diff,2).'s: '.$data[1].'<br />'); - + if ($timebefore === null) { + $first = $data[0]; + } + print('+' . round($diff, 2) . 's: ' . $data[1] . '<br />'); + $timebefore = $data[0]; } - print('<br />Allover:'.round((microtime(true) - $first),2).'s.<br />'); + print('<br />Allover:'.round((microtime(true) - $first), 2).'s.<br />'); print('the time now is '.date('r')); } - - + + /** * Take a mediawiki timestamp and returns a unix timestamp * @param string $tstime * @return int unixtimestamp */ - public function TsToUnixTime($tstime) - { - $regYear = substr($tstime,0,4); - $regMonth = substr($tstime,4,2); - $regDay = substr($tstime,6,2); - $regHour = substr($tstime,8,2); - $regMin = substr($tstime,10,2); - $regSec = substr($tstime,12,2); + public function TsToUnixTime($tstime) { + $regYear = substr($tstime, 0, 4); + $regMonth = substr($tstime, 4, 2); + $regDay = substr($tstime, 6, 2); + $regHour = substr($tstime, 8, 2); + $regMin = substr($tstime, 10, 2); + $regSec = substr($tstime, 12, 2); - return mktime($regHour,$regMin,$regSec,$regMonth,$regDay,$regYear); + return mktime($regHour, $regMin, $regSec, $regMonth, $regDay, $regYear); } - + /** * returns a formated timestamp * @param string $tstime * @param array $months - * @return string + * @return string */ - public function TStoUserTime($tstime,$timeformat,$months) { - if($tstime == "infinity") { + public function TStoUserTime($tstime, $timeformat, $months) { + if ($tstime == "infinity") { return $tstime; } else { - $regYear = substr($tstime,0,4); - $regMonth = substr($tstime,4,2); + $regYear = substr($tstime, 0, 4); + $regMonth = substr($tstime, 4, 2); - $tempdates = array("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12" ); + $tempdates = array("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"); $regMonthW = str_replace($tempdates, $months, $regMonth); - $regDay = substr($tstime,6,2); - $regHour = substr($tstime,8,2); - $regMin = substr($tstime,10,2); - $regSec = substr($tstime,12,2); + $regDay = substr($tstime, 6, 2); + $regHour = substr($tstime, 8, 2); + $regMin = substr($tstime, 10, 2); + $regSec = substr($tstime, 12, 2); /* variables: Y = year, eg. "2008" @@ -149,13 +153,13 @@ i = minute, eg. "08" s = second, eg. "10" */ - + return str_replace(array('Y','m','F','d','H','i','s'), array($regYear, $regMonth, $regMonthW, $regDay, $regHour, $regMin, $regSec), $timeformat); } } - + /** * parses the summary of contributions * @param type $sum @@ -163,9 +167,9 @@ * @param type $project * @return type */ - public function wikiparser($sum,$page,$project) + public function wikiparser($sum, $page, $project) { - + $page = htmlspecialchars($page, ENT_QUOTES); $sum = htmlspecialchars($sum); // Sektionen /* SEKTION */ parsen @@ -174,60 +178,66 @@ //Interne Links parsen //[[LINK]] //nichts ersetzen falls es ein | enthält - $sum =preg_replace("/\[\[([^\|\[\]]*)\]\]/e", "'<a href=\'//$project/w/index.php?title='._wpurldecode('\\1').'\'>\\1</a>'", $sum); + $sum =preg_replace("/\[\[([^\|\[\]]*)\]\]/e", "'<a href=\'//$project/w/index.php?title='._wpurldecode('\\1').'\'>\\1</a>'", $sum); //[LINK|BESCHREIBUNG]] $sum =preg_replace("/\[\[([^\|\[\]]*)\|{1}([^\|\[\]]*)\]\]/e", "'<a href=\'//$project/w/index.php?title='._wpurldecode('\\1').'\'>\\2</a>'", $sum); - //$sum = preg_replace("/(<\/?)(\w+)([^>]*>)/e", "'\\1'.strtoupper('\\2').'\\3'",$sum); - - return $sum; } - + /** - * Returns the Name of a Namespace, performs a api request if not already cached. + * Returns the Name of a Namespace, performs a api request if not already cached. * @staticvar string $cache * @param int $id * @param string $dbName * @param string $url - * @return string Namespacename + * @return string Namespace name */ public function getNamespaceName($id, $dbName, $url) { static $cache = ''; $id = intval($id); - - //Initialize cache - if(!is_array($cache)) { + + // Initialize cache + if (!is_array($cache)) { $rawCache = file_get_contents(settings::getSetting('cacheFile')); - if($rawCache) $cache = json_decode($rawCache, true); - else $cache = array(); + if ($rawCache) { + $cache = json_decode($rawCache, true); + } else { + $cache = array(); + } } - - //Wiki exist in cache? - if(key_exists($dbName, $cache)) { - //Namespace exist in cache? - if(key_exists($id, $cache[$dbName])) return $cache[$dbName][$id]; + + // Wiki exist in cache? + if (key_exists($dbName, $cache)) { + // Namespace exist in cache? + if (key_exists($id, $cache[$dbName])) { + return $cache[$dbName][$id]; + } } - - //get information from API + + // Get information from API $apiData = $this->apiRequest($url, array('meta' => 'siteinfo', 'siprop' => 'namespaces')); - if(!is_array($apiData['query']['namespaces'])) throw new Exception('Error on namespace resolution for '.$url); - + if (!is_array($apiData['query']['namespaces'])) { + throw new Exception('Error on namespace resolution for '.$url); + } + $cache[$dbName] = array(); - foreach($apiData['query']['namespaces'] as $ns) { + foreach ($apiData['query']['namespaces'] as $ns) { $cache[$dbName][intval($ns['id'])] = $ns['*']; } - + //save cache file_put_contents(settings::getSetting('cacheFile'), json_encode($cache)); - + //return namespace name - if(!key_exists($dbName, $cache) || !key_exists($id, $cache[$dbName]))throw new Exception('Unknown namespace numer '.$id.' for '.$url); + if (!key_exists($dbName, $cache) || !key_exists($id, $cache[$dbName])) { + throw new Exception('Unknown namespace numer '.$id.' for '.$url); + } return $cache[$dbName][$id]; } - - + + /** * Performs a api request (post) * @param string $url @@ -235,20 +245,26 @@ * @return array or string */ public function apiRequest($url, $params) { - if(!is_array($params)) throw new Exception('invalid api parameters.'); + if (!is_array($params)) { + throw new Exception('invalid api parameters.'); + } $url = 'https://'.$url.'/w/api.php'; //set defaults - if(!key_exists('format', $params)) $params['format'] = 'json'; - if(!key_exists('action', $params)) $params['action'] = 'query'; - + if (!key_exists('format', $params)) { + $params['format'] = 'json'; + } + if (!key_exists('action', $params)) { + $params['action'] = 'query'; + } + $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = curl_exec($ch); curl_close($ch); - if($params['format'] == 'json') { + if ($params['format'] == 'json') { return json_decode($data, true); } else { return $data; @@ -265,10 +281,10 @@ */ function _wpsectdecode($str){ $str = trim($str); - $str = str_replace(" ","_",$str); + $str = str_replace(" ", "_", $str); $str = urlencode($str); $str = ucwords($str); - $str = str_replace("%",".",$str); + $str = str_replace("%", ".", $str); return $str; } @@ -277,10 +293,9 @@ * Decode Mediawiki url's * @param string $str * @return string - */ + */ function _wpurldecode($str) { $str = trim($str); - $str = str_replace(" ","_",$str); + $str = str_replace(" ", "_", $str); return ucwords($str); } -?> diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..b4ef744 --- /dev/null +++ b/composer.json @@ -0,0 +1,8 @@ +{ + "require-dev": { + "squizlabs/php_codesniffer": "1.*" + }, + "scripts": { + "test": "phpcs . --standard=phpcs.xml --ignore=vendor/* --extensions=php" + } +} diff --git a/index.php b/index.php index e495ecc..c22d4c0 100644 --- a/index.php +++ b/index.php @@ -1,37 +1,37 @@ <?php -/* +/** * Copyright 2014 by Luxo - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -//Standard-Dateien + +// Standard-Dateien require_once 'settings.php'; require_once 'app.php'; error_reporting(E_ALL ^ E_NOTICE); -ini_set('display_errors', 1); +ini_set('display_errors', 1); -//Komponenten einbinden +// Komponenten einbinden foreach (settings::getSetting('components') as $cmp) { - if(is_file('lb/'.$cmp.'.php')) { + if (is_file('lb/'.$cmp.'.php')) { require_once 'lb/'.$cmp.'.php'; } } -//create app +// Create app $app = new lb_app(); -if(key_exists('user', $_POST)) { +if (key_exists('user', $_POST)) { $app->aTP('got username, start search.'); $guc = new guc($app); } else { @@ -52,7 +52,7 @@ <script src="lib/prototype.js"></script> <title>Global user contributions</title> <script type="text/javascript"> - var data = <?php print(json_encode($jsData)); ?>; + var data = <?php print json_encode($jsData); ?>; </script> </head> <body> @@ -62,34 +62,46 @@ <p>Tool to search contributions of a user in the wikimedia-wikis. Additional features like blocklog, sul-info or translation will follow in the future.</p> </div> <form method="POST" class="searchField" id="searchForm"> - <p> IP Address or username: <input name="user" value="<?php if($guc){print(htmlspecialchars($guc->getUsername()));}elseif(key_exists('user', $_GET)){ print(htmlspecialchars($_GET['user'])); } ?>" class="usernameOrIp"></p> + <p> IP Address or username: <input name="user" value="<?php + if ($guc) { + print htmlspecialchars($guc->getUsername()); + } elseif (key_exists('user', $_GET)) { + print htmlspecialchars($_GET['user']); + } + ?>" class="usernameOrIp"></p> <input type="submit" value="Search" class="submitbutton" id="submitButton" onclick="onSearchClick(this);"> <div id="loadLine" style="display: none;"> </div> </form> <?php - if($guc) { - print('<p class="statistics">'.$guc->wikisCount." wikis searched. "); - if($guc->getAlloverCount() > 0) print($guc->getAlloverCount().' edits found in '.$guc->wikisWithEditscount.' projects.'); - print('</p>'); - print('<div class="results">'); - if($guc->getHostname()) print('<div class="hostname">'.$guc->getUsername().' = '.$guc->getHostname().'</div>'); + if ($guc) { + print '<p class="statistics">'.$guc->wikisCount." wikis searched. "; + if ($guc->getAlloverCount() > 0) { + print $guc->getAlloverCount().' edits found in '.$guc->wikisWithEditscount.' projects.'; + } + print '</p>'; + print '<div class="results">'; + if ($guc->getHostname()) { + print '<div class="hostname">'.$guc->getUsername().' = '.$guc->getHostname().'</div>'; + } foreach ($guc->getData() as $wiki) { - if(is_object($wiki['data'])){ - if($wiki['data']->hasContribs()){ - print('<div class="wiki'.(($wiki['data']->markAsNotUnified())?' noSul':'').'">'); - print($wiki['data']->getDataHtml()); - print('</div>'); + if (is_object($wiki['data'])) { + if ($wiki['data']->hasContribs()) { + print '<div class="wiki'.(($wiki['data']->markAsNotUnified())?' noSul':'').'">'; + print $wiki['data']->getDataHtml(); + print '</div>'; } - } else if($wiki['error']) { + } elseif ($wiki['error']) { print('<div class="error">'); - if($wiki['url']) print('<h1>'.htmlspecialchars ($wiki['url']).'</h1>'); - print($wiki['error']); - print('</div>'); + if ($wiki['url']) { + print'<h1>'.htmlspecialchars($wiki['url']).'</h1>'; + } + print $wiki['error']; + print '</div>'; } } - print('</div>'); - } + print '</div>'; + } ?> <div class="footer"> by <a href="https://wikitech.wikimedia.org/wiki/User:Luxo">Luxo</a> diff --git a/lb/exception.php b/lb/exception.php index 0f16e8f..2fa61ba 100644 --- a/lb/exception.php +++ b/lb/exception.php @@ -1,25 +1,26 @@ -<?php - -class lb_Exception extends Exception { - - public function __construct($message = '', $code = 0, Exception $previous = null) { - parent::__construct($message, $code, $previous); - } - - public function printDieMessageHTML() { - $html = '<html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - <title>Sorry - Error</title> - </head> - <body style="font-family: sans-serif, arial;text-align:center;"> - <img src="resources/img/tool_Labs_logo_notworking.png" /> - <h1>Sorry</h1> - <p>Something is not working. Try again later.</p> - <p style="font-style:italic">'.$this->getCode().': '.$this->getMessage().'</p> - </body> - </html>'; - print($html); - die(); - } -} \ No newline at end of file +<?php + +class lb_Exception extends Exception +{ + + public function __construct($message = '', $code = 0, Exception $previous = null) { + parent::__construct($message, $code, $previous); + } + + public function printDieMessageHTML() { + $html = '<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <title>Sorry - Error</title> + </head> + <body style="font-family: sans-serif, arial;text-align:center;"> + <img src="resources/img/tool_Labs_logo_notworking.png" /> + <h1>Sorry</h1> + <p>Something is not working. Try again later.</p> + <p style="font-style:italic">'.$this->getCode().': '.$this->getMessage().'</p> + </body> + </html>'; + print $html ; + die(); + } +} diff --git a/lb/guc.php b/lb/guc.php index 076fa57..757896d 100644 --- a/lb/guc.php +++ b/lb/guc.php @@ -1,175 +1,187 @@ -<?php -/* - * Copyright 2014 by Luxo - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -class guc { - private $app; - private $isIP; - private $hostname; - private $username; - private $wikis; - private $alloverCount=0; - public $wikisCount=0; - public $wikisWithEditscount=0; - - function __construct(lb_app $app, $closedWikis=false, $justLastHour=false) { - $this->app = $app; - $this->username = str_replace("_", " ", ucfirst(trim($_POST['user']))); - $wikis = $this->_getWikis($closedWikis); - $WikisCountribsCounter = $this->_getWikisWithContribs($wikis); - $this->wikisCount = count($wikis); - try { - $this->hostname = @gethostbyaddr($this->username); - } catch(Exception $e) { - $this->hostname = ''; - } - $this->isIP = !!$this->hostname; - //check if input is a IP - foreach($wikis as &$wiki) { - if($WikisCountribsCounter[$wiki['dbname']] > 0) { - $wiki['url'] = mb_substr($wiki['url'], 7); //cut http:// - try { - $wiki['data'] = new lb_wikicontribs($this->app,$this->username,$wiki['dbname'],$wiki['url'],$wiki['slice'],$wiki['family'], $this->_getCentralauthData($wiki['dbname']), $this->isIP, $justLastHour); - $wiki['error'] = null; - } catch (Exception $e) { - $wiki['data'] = null; - $wiki['error'] = "Error with ".$wiki['url'].': '.$e->getMessage().'<br>'; - } - } else { - //no contribs - $wiki['data'] = null; - $wiki['error'] = null; - } - - } - $this->wikis = $wikis; - } - - /** - * return all wikis - * @return mixed - */ - private function _getWikis($closedIncluded = false) { - $this->app->aTP('get wiki list..'); - $family = array( - 'wikipedia' => 1, - 'wikibooks' => 1, - 'wiktionary' => 1, - 'special' => 1, - 'wikiquote' => 1, - 'wikisource' => 1, - 'wikimedia' => 1, - 'wikinews' => 1, - 'wikiversity' => 1, - 'centralauth' => 0, - 'wikivoyage' => 1, - 'wikidata' => 1, - 'wikimania' => 1 - ); - $f_where = array(); - if(!$closedIncluded) $f_where[] = 'is_closed = 0'; - foreach($family as $name => $include) { - if($include == 0) $f_where[] = '`family` != \''.$name.'\''; - } - $f_where = implode(" AND ", $f_where); - $qry = 'SELECT * FROM `meta_p`.`wiki` WHERE '.$f_where.' LIMIT 1500;'; - $con = $this->app->getDB()->prepare($qry); - $con->execute(); - $r = $con->fetchAll(); - unset($con); - return $r; - } - - /** - * return the wikis with contribs - * @param type $wikis - * @return type - */ - private function _getWikisWithContribs($wikis) { - $return = array(); - $slices = array(); - $wikisWithEditCount = 0; - foreach($wikis as $wiki) { - if(!is_array($slices[$wiki['slice']])) $slices[$wiki['slice']] = array(); - $slices[$wiki['slice']][] = 'SELECT COUNT(rev_id) AS counter, \''.$wiki['dbname'].'\' AS dbname FROM '.$wiki['dbname'].'_p.revision_userindex WHERE rev_user_text = :username'; - } - foreach($slices as $slicename => $sql) { - if($sql) { - $sql = implode(' UNION ALL ', $sql); - $qry = $this->app->getDB('meta', $slicename); - $con = $qry->prepare($sql); - $con->bindParam(':username', $this->username); - $con->execute(); - $r = $con->fetchAll(PDO::FETCH_ASSOC); - foreach($r as $re) { - $return[$re['dbname']] = intval($re['counter']); - if($re['counter'] > 0) $wikisWithEditCount++; - } - unset($con); - } - } - $this->alloverCount = array_sum($return); - $this->wikisWithEditscount = $wikisWithEditCount; - return $return; - } - - /** - * returns centralauth information - * @staticvar null $centralauthData - * @param string $dbname - * @return array or null or false if no centralauth - */ - private function _getCentralauthData($dbname) { - static $centralauthData = NULL; - if($centralauthData === NULL) { - $centralauthData = array(); - $db = $this->app->getDB('centralauth', 'centralauth.labsdb'); - $qry = $db->prepare('SELECT * FROM localuser WHERE lu_name = :luName;'); - $qry->bindParam(':luName', $this->username, PDO::PARAM_STR); - $qry->execute(); - $rows = $qry->fetchAll(PDO::FETCH_ASSOC); - unset($qry); - if(!$rows) return false; - foreach($rows as $row) { - $centralauthData[$row['lu_wiki']] = $row; - } - } - if(key_exists($dbname, $centralauthData)) return $centralauthData[$dbname]; - else return null; - } - - /** - * Gibt die Daten zurück - * @return array - */ - public function getData() { - return $this->wikis; - } - - public function getUsername() { - return $this->username; - } - - public function getHostname() { - return $this->hostname; - } - - public function getAlloverCount() { - return $this->alloverCount; - } -} -?> +<?php +/** + * Copyright 2014 by Luxo + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +class guc +{ + private $app; + private $isIP; + private $hostname; + private $username; + private $wikis; + private $alloverCount = 0; + public $wikisCount = 0; + public $wikisWithEditscount = 0; + + public function __construct(lb_app $app, $closedWikis = false, $justLastHour = false) { + $this->app = $app; + $this->username = str_replace("_", " ", ucfirst(trim($_POST['user']))); + $wikis = $this->_getWikis($closedWikis); + $WikisCountribsCounter = $this->_getWikisWithContribs($wikis); + $this->wikisCount = count($wikis); + try { + $this->hostname = @gethostbyaddr($this->username); + } catch (Exception $e) { + $this->hostname = ''; + } + $this->isIP = !!$this->hostname; + // Check if input is a IP + foreach ($wikis as &$wiki) { + if ($WikisCountribsCounter[$wiki['dbname']] > 0) { + // Strip http:// + $wiki['url'] = mb_substr($wiki['url'], 7); + try { + $wiki['data'] = new lb_wikicontribs($this->app, $this->username, $wiki['dbname'], $wiki['url'], $wiki['slice'], $wiki['family'], $this->_getCentralauthData($wiki['dbname']), $this->isIP, $justLastHour); + $wiki['error'] = null; + } catch (Exception $e) { + $wiki['data'] = null; + $wiki['error'] = "Error with ".$wiki['url'].': '.$e->getMessage().'<br>'; + } + } else { + // No contribs + $wiki['data'] = null; + $wiki['error'] = null; + } + + } + $this->wikis = $wikis; + } + + /** + * return all wikis + * @return mixed + */ + private function _getWikis($closedIncluded = false) { + $this->app->aTP('get wiki list..'); + $family = array( + 'wikipedia' => 1, + 'wikibooks' => 1, + 'wiktionary' => 1, + 'special' => 1, + 'wikiquote' => 1, + 'wikisource' => 1, + 'wikimedia' => 1, + 'wikinews' => 1, + 'wikiversity' => 1, + 'centralauth' => 0, + 'wikivoyage' => 1, + 'wikidata' => 1, + 'wikimania' => 1 + ); + $f_where = array(); + if (!$closedIncluded) { + $f_where[] = 'is_closed = 0'; + } + foreach ($family as $name => $include) { + if ($include == 0) { + $f_where[] = '`family` != \''.$name.'\''; + } + } + $f_where = implode(" AND ", $f_where); + $qry = 'SELECT * FROM `meta_p`.`wiki` WHERE '.$f_where.' LIMIT 1500;'; + $con = $this->app->getDB()->prepare($qry); + $con->execute(); + $r = $con->fetchAll(); + unset($con); + return $r; + } + + /** + * return the wikis with contribs + * @param type $wikis + * @return type + */ + private function _getWikisWithContribs($wikis) { + $return = array(); + $slices = array(); + $wikisWithEditCount = 0; + foreach ($wikis as $wiki) { + if (!is_array($slices[$wiki['slice']])) { + $slices[$wiki['slice']] = array(); + } + $slices[$wiki['slice']][] = 'SELECT COUNT(rev_id) AS counter, \''.$wiki['dbname'].'\' AS dbname FROM '.$wiki['dbname'].'_p.revision_userindex WHERE rev_user_text = :username'; + } + foreach ($slices as $slicename => $sql) { + if ($sql) { + $sql = implode(' UNION ALL ', $sql); + $qry = $this->app->getDB('meta', $slicename); + $con = $qry->prepare($sql); + $con->bindParam(':username', $this->username); + $con->execute(); + $r = $con->fetchAll(PDO::FETCH_ASSOC); + foreach ($r as $re) { + $return[$re['dbname']] = intval($re['counter']); + if ($re['counter'] > 0) { + $wikisWithEditCount++; + } + } + unset($con); + } + } + $this->alloverCount = array_sum($return); + $this->wikisWithEditscount = $wikisWithEditCount; + return $return; + } + + /** + * returns centralauth information + * @staticvar null $centralauthData + * @param string $dbname + * @return array|null|bool False if no centralauth + */ + private function _getCentralauthData($dbname) { + static $centralauthData = null; + if ($centralauthData === null) { + $centralauthData = array(); + $db = $this->app->getDB('centralauth', 'centralauth.labsdb'); + $qry = $db->prepare('SELECT * FROM localuser WHERE lu_name = :luName;'); + $qry->bindParam(':luName', $this->username, PDO::PARAM_STR); + $qry->execute(); + $rows = $qry->fetchAll(PDO::FETCH_ASSOC); + unset($qry); + if (!$rows) { + return false; + } + foreach ($rows as $row) { + $centralauthData[$row['lu_wiki']] = $row; + } + } + if (!key_exists($dbname, $centralauthData)) { + return null; + } + return $centralauthData[$dbname]; + } + + /** + * Gibt die Daten zurück + * @return array + */ + public function getData() { + return $this->wikis; + } + + public function getUsername() { + return $this->username; + } + + public function getHostname() { + return $this->hostname; + } + + public function getAlloverCount() { + return $this->alloverCount; + } +} diff --git a/lb/wikicontribs.php b/lb/wikicontribs.php index b431002..0b43ffe 100644 --- a/lb/wikicontribs.php +++ b/lb/wikicontribs.php @@ -1,24 +1,24 @@ <?php -/* +/** * Copyright 2014 by Luxo - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -class lb_wikicontribs { +class lb_wikicontribs +{ private $contribLimit = 20; - + private $hasContribs = false; private $isIp; private $registeredUser = false; @@ -28,22 +28,24 @@ private $url; private $slice; private $family; - + private $username; private $usernameUnterlined; private $userId; private $userEditCount; private $userRegistration; private $centralAuth; - + /** - * + * * @param string $dbname * @param string $url * @param string $slice */ - public function __construct(lb_app $app,$username, $dbname, $url, $slice, $family, $centralAuth, $isIP, $justLastHour) { - if(!$username) throw new Exception("No Username or IP"); + public function __construct(lb_app $app, $username, $dbname, $url, $slice, $family, $centralAuth, $isIP, $justLastHour) { + if (!$username) { + throw new Exception("No Username or IP"); + } $this->app = $app; $this->dbname = $dbname; $this->url = $url; @@ -55,17 +57,17 @@ $this->isIp = $isIP; $this->justLastHour = $justLastHour; $this->centralAuth = $centralAuth; - - if($this->isIp !== true) { + + if ($this->isIp !== true) { //get user data - $this->app->aTP('search user data at '.$url); + $this->app->aTP('search user data at ' . $url); $db = $this->app->getDB($dbname, $slice)->prepare("SELECT `user_id`, `user_editcount`, `user_registration` FROM `user` WHERE `user_name` = :username LIMIT 1;"); $db->bindParam(':username', $this->username); $db->execute(); $res = $db->fetch(PDO::FETCH_ASSOC); unset($db); - if($res) { + if ($res) { //set data $this->registeredUser = true; $this->userId = $res['user_id']; @@ -76,60 +78,65 @@ //Beiträge Abfragen $this->_getRecentChanges(); } - - + + /** * gibt die letzten 20 änderungen zurück * @return mixed; */ private function _getRecentChanges() { - $this->app->aTP('search recent changes at '.$this->url); + $this->app->aTP('search recent changes at ' . $this->url); date_default_timezone_set('UTC'); $where = ''; - if($this->justLastHour) $where = " `rev_timestamp` >= '".date('YmdHis')."' AND "; - - $qry = "SELECT + if ($this->justLastHour) { + $where = " `rev_timestamp` >= '" . date('YmdHis') . "' AND "; + } + + $qry = "SELECT `rev_comment`, `rev_timestamp`, `rev_minor_edit`, - `rev_len`, + `rev_len`, `rev_id`, `rev_parent_id`, - `page_title`, + `page_title`, `page_namespace`, `page_latest` = `rev_id` AS `rev_cur` - FROM - `revision_userindex` - INNER JOIN - `page` ON `rev_page` = `page_id` + FROM + `revision_userindex` + INNER JOIN + `page` ON `rev_page` = `page_id` WHERE ".$where." - `rev_deleted` = 0 AND + `rev_deleted` = 0 AND ".(($this->isIP()) ? "`rev_user_text` = :username" : "`rev_user` = :userid")." ORDER BY `revision_userindex`.`rev_timestamp` DESC LIMIT 0,".$this->contribLimit.";"; $db = $this->app->getDB($this->dbname, $this->slice)->prepare($qry); - if($this->isIP()) $db->bindParam(':username', $this->username); - else $db->bindParam(':userid', $this->userId); + if ($this->isIP()) { + $db->bindParam(':username', $this->username); + } else { + $db->bindParam(':userid', $this->userId); + } $db->execute(); - $this->recentchanges = $db->fetchAll(PDO::FETCH_ASSOC); + $this->recentchanges = $db->fetchAll(PDO::FETCH_ASSOC); $this->hasContribs = !!$this->recentchanges; - //get namespace - unset($db); - foreach($this->recentchanges as &$rc) { + // Get namespace + unset($db); + foreach ($this->recentchanges as &$rc) { $rc['page_namespace_name'] = $this->app->getNamespaceName($rc['page_namespace'], $this->dbname, $this->url); $rc['full_page_title'] = ($rc['page_namespace_name']) ? $rc['page_namespace_name'].":".$rc['page_title'] : $rc['page_title']; $rc['full_page_title'] = str_replace(" ", "_", $rc['full_page_title']); } } - + /** * Gibt zurück ob der Benutzer eine IP ist oder nicht. * @return boolean */ public function isIP() { return $this->isIp; - } - + } + /** * Gibt alle letzten 20 Beiträge zurück * @return type @@ -137,11 +144,11 @@ public function getRecentChanges() { return $this->recentchanges; } - + public function getUserRegistration() { return ($this->registeredUser) ? null : $this->userRegistration; } - + public function getUserEditcount() { return ($this->registeredUser) ? null : $this->userEditCount; } @@ -154,43 +161,47 @@ public function getBlocks() { return ($this->isIP()) ? $this->getIpBlocks() : $this->getUserBlocks(); } - + private function getIpBlocks() { - if(!$this->isIP()) return null; - $qry = "SELECT - ipblocks.*, - `user`.user_name AS admin_username - FROM ipblocks - INNER JOIN `user` ON ipb_by = `user`.user_id + if (!$this->isIP()) { + return null; + } + $qry = "SELECT + ipblocks.*, + `user`.user_name AS admin_username + FROM ipblocks + INNER JOIN `user` ON ipb_by = `user`.user_id WHERE ipblocks.ipb_address = :ipadresse LIMIT 0,100;"; $db = $this->app->getDB($this->dbname, $this->slice)->prepare($qry); $db->bindParam(':ipadresse', $this->username); $db->execute(); - $res = $db->fetchAll(PDO::FETCH_ASSOC); + $res = $db->fetchAll(PDO::FETCH_ASSOC); unset($db); return $res; } - + private function getUserBlocks() { - if($this->isIP()) return null; - $qry = "SELECT - ipblocks.*, - `user`.user_name AS admin_username - FROM ipblocks - INNER JOIN `user` ON ipb_by = `user`.user_id + if ($this->isIP()) { + return null; + } + $qry = "SELECT + ipblocks.*, + `user`.user_name AS admin_username + FROM ipblocks + INNER JOIN `user` ON ipb_by = `user`.user_id WHERE ipblocks.ipb_user = :userid LIMIT 0,100;"; $db = $this->app->getDB($this->dbname, $this->slice)->prepare($qry); $db->bindParam(':userid', $this->userId); $db->execute(); - $res = $db->fetchAll(PDO::FETCH_ASSOC); + $res = $db->fetchAll(PDO::FETCH_ASSOC); unset($db); - return $res; + return $res; } - + public function hasContribs() { return $this->hasContribs; } - + public function getDataHtml() { $return = ''; $return .= '<h1>'.$this->url.'</h1>'; @@ -201,43 +212,53 @@ . '<a href="//'.$this->url.'/wiki/Special:ListFiles/'.htmlspecialchars($this->usernameUnterlined).'" title="Special:ListFiles">uploads</a> | ' . '<a href="//'.$this->url.'/wiki/Special:Log/'.htmlspecialchars($this->usernameUnterlined).'" title="Special:Log">logs</a> | ' . '<a href="//'.$this->url.'/w/index.php?title=Special:AbuseLog&wpSearchUser='. urlencode($this->usernameUnterlined).'" title="Edit Filter log for this user">filter log</a>'; - if($this->userEditCount > 0)$return .= ' | '. $this->userEditCount.' edits'; - if($this->centralAuth) $return .= ' | '.'SUL: Account attached at '.$this->app->TStoUserTime($this->centralAuth['lu_attached_timestamp'], 'H:i, d.m.Y', array()); - if($this->centralAuth === NULL) $return .= ' | '.'SUL: Account not attached.'; + if ($this->userEditCount > 0) { + $return .= ' | '. $this->userEditCount.' edits'; + } + if ($this->centralAuth) { + $return .= ' | '.'SUL: Account attached at '.$this->app->TStoUserTime($this->centralAuth['lu_attached_timestamp'], 'H:i, d.m.Y', array()); + } + if ($this->centralAuth === null) { + $return .= ' | '.'SUL: Account not attached.'; + } $return .= ')</p>'; $return .= '<ul>'; - foreach($this->recentchanges as $w_data) { + foreach ($this->recentchanges as $w_data) { $return .= '<li>'; - //Zeit + // Zeit $return .= $this->app->TStoUserTime($w_data['rev_timestamp'], 'H:i, d.m.Y', array()).' '; - //diff-Link full_page_title + // diff-Link full_page_title $return .= '(<a href="//'.$this->url.'/w/index.php?title='.urlencode($w_data['full_page_title']).'&diff=prev&oldid='.urlencode($w_data['rev_id']).'">diff</a>'; $return .= ' | '; - //history + // History $return .= '<a href="//'.$this->url.'/w/index.php?title='.urlencode($w_data['full_page_title']).'&action=history">hist</a>)'; - //minor Edit - if($w_data['rev_minor_edit']) $return .= ' <span class="minor">M</span>'; - - //Link to the page + // Minor Edit + if ($w_data['rev_minor_edit']) { + $return .= ' <span class="minor">M</span>'; + } + + // Link to the page $return .= ' <a href="//'.$this->url.'/w/index.php?title='.urlencode($w_data['full_page_title']).'">'; - if($w_data['page_namespace_name']) $return .= htmlspecialchars ($w_data['page_namespace_name'].":"); + if ($w_data['page_namespace_name']) { + $return .= htmlspecialchars($w_data['page_namespace_name'].":"); + } $return .= htmlspecialchars($w_data['page_title'])."</a>"; - - //Comment - if($w_data['rev_comment']) { + + // Comment + if ($w_data['rev_comment']) { $return .= ' ('.$this->app->wikiparser($w_data['rev_comment'], $w_data['full_page_title'], $this->url).')'; } - - //cur revision - if($w_data['rev_cur']) { + + // Cur revision + if ($w_data['rev_cur']) { $return .= ' <span class="rev_cur">(current)</span>'; - } + } $return .= '</li>'; } $return .= '</ul>'; return $return; } - + /** * Gibt zurück ob der Beitrag als nicht CentralAuth markiert werden soll. * @return boolen @@ -245,13 +266,14 @@ public function markAsNotUnified() { return $this->centralAuth === null; } - + private function _wikiTimestampToNormal($wp_time) { - return $wp_time; //TODO:Umwandeln + // TODO: Umwandeln + return $wp_time; } - - private function _formatComment($unformated, $pageLink=null) { - return $unformated; //TODO + + private function _formatComment($unformated, $pageLink = null) { + // TODO + return $unformated; } } -?> diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..709cfd6 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<ruleset> + <rule ref="PSR2"> + <exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace" /> + <exclude name="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine" /> + <!-- Buggy for inline php tags in html --> + <exclude name="Generic.WhiteSpace.ScopeIndent.Incorrect" /> + <!-- TODO: --> + <exclude name="Generic.Files.LineLength.TooLong" /> + <exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps" /> + <exclude name="Squiz.Classes.ValidClassName.NotCamelCaps" /> + <exclude name="PSR2.Methods.MethodDeclaration.Underscore" /> + </rule> +</ruleset> diff --git a/settings.php b/settings.php index 57a720d..2d809c8 100644 --- a/settings.php +++ b/settings.php @@ -1,47 +1,50 @@ <?php -class settings { - +class settings +{ + /** * Gibt eine Einstellung zurück. * @param string $setting * @return string wert */ - static public function getSetting($setting) { + public static function getSetting($setting) { $settings = array( - - //Database - 'user' => 'x', - 'password' => 'x', - - - //Components - 'components' => array( - 'guc', - 'wikicontribs', - 'exception' - ), - - //Paths - 'cacheFile' => 'cache/namespaces.json' - ); + + // Database + 'user' => 'x', + 'password' => 'x', + + + // Components + 'components' => array( + 'guc', + 'wikicontribs', + 'exception', + ), + + // Paths + 'cacheFile' => 'cache/namespaces.json', + ); return $settings[$setting]; - } - - + } + + private static function _getMySQLloginFromFile() { - //TODO: Fix + // TODO: Fix $path = '../replica.my.cnf'; - + $raw = file($path); $return = new stdClass(); - foreach($raw as $line) { - preg_match('/^([a-zA-Z0-9]+)\=\'([a-zA-Z0-9]+)\'$/',$line, $result); - if($result[1]) $return->$result[1] = $result[2]; + foreach ($raw as $line) { + preg_match('/^([a-zA-Z0-9]+)\=\'([a-zA-Z0-9]+)\'$/', $line, $result); + if ($result[1]) { + $return->$result[1] = $result[2]; + } } - if(!$return->username || $return->password) throw new Exception("Got no MySQL login data. I'm at".$_SERVER["CONTEXT_DOCUMENT_ROOT"]); + if (!$return->username || $return->password) { + throw new Exception("Got no MySQL login data. I'm at" . $_SERVER['CONTEXT_DOCUMENT_ROOT']); + } return $return; } } - -?> -- To view, visit https://gerrit.wikimedia.org/r/174894 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I4c61ce67c60569b47462ac4525d6ffcbeb55e3e3 Gerrit-PatchSet: 1 Gerrit-Project: labs/tools/guc Gerrit-Branch: master Gerrit-Owner: Krinkle <krinklem...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits