From f1dc78ac2de561801f3bd30e0755e91d6a92e7dc Mon Sep 17 00:00:00 2001 From: Alex Shih-Han Lin Date: Thu, 23 Jul 2009 16:25:31 +0000 Subject: [PATCH] +Add BrokenRedirects and DoubleRedirects API script for bot development. --- includes/AutoLoader.php | 2 + includes/api/ApiQuery.php | 2 + includes/api/ApiQueryBrokenRedirects.php | 149 +++++++++++++++++++++ includes/api/ApiQueryDoubleRedirects.php | 163 +++++++++++++++++++++++ 4 files changed, 316 insertions(+) create mode 100644 includes/api/ApiQueryBrokenRedirects.php create mode 100644 includes/api/ApiQueryDoubleRedirects.php diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 180beeb859..97aa525246 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -295,12 +295,14 @@ $wgAutoloadLocalClasses = array( 'ApiQueryBacklinks' => 'includes/api/ApiQueryBacklinks.php', 'ApiQueryBase' => 'includes/api/ApiQueryBase.php', 'ApiQueryBlocks' => 'includes/api/ApiQueryBlocks.php', + 'ApiQueryBrokenRedirects' => 'includes/api/ApiQueryBrokenRedirects.php', 'ApiQueryCategories' => 'includes/api/ApiQueryCategories.php', 'ApiQueryCategoryInfo' => 'includes/api/ApiQueryCategoryInfo.php', 'ApiQueryCategoryMembers' => 'includes/api/ApiQueryCategoryMembers.php', 'ApiQueryContributions' => 'includes/api/ApiQueryUserContributions.php', 'ApiQueryDeletedrevs' => 'includes/api/ApiQueryDeletedrevs.php', 'ApiQueryDisabled' => 'includes/api/ApiQueryDisabled.php', + 'ApiQueryDoubleRedirects' => 'includes/api/ApiQueryDoubleRedirects.php', 'ApiQueryDuplicateFiles' => 'includes/api/ApiQueryDuplicateFiles.php', 'ApiQueryExtLinksUsage' => 'includes/api/ApiQueryExtLinksUsage.php', 'ApiQueryExternalLinks' => 'includes/api/ApiQueryExternalLinks.php', diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index e3719e0d50..9e526a4621 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -67,7 +67,9 @@ class ApiQuery extends ApiBase { 'allusers' => 'ApiQueryAllUsers', 'backlinks' => 'ApiQueryBacklinks', 'blocks' => 'ApiQueryBlocks', + 'brokenredirects' => 'ApiQueryBrokenRedirects', 'categorymembers' => 'ApiQueryCategoryMembers', + 'doubleredirects' => 'ApiQueryDoubleRedirects', 'deletedrevs' => 'ApiQueryDeletedrevs', 'embeddedin' => 'ApiQueryBacklinks', 'imageusage' => 'ApiQueryBacklinks', diff --git a/includes/api/ApiQueryBrokenRedirects.php b/includes/api/ApiQueryBrokenRedirects.php new file mode 100644 index 0000000000..bcc7b008d1 --- /dev/null +++ b/includes/api/ApiQueryBrokenRedirects.php @@ -0,0 +1,149 @@ +@gmail.com + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiQueryBase.php'); +} + +/** + * Query module to enumerate all available pages. + * + * @ingroup API + */ +class ApiQueryBrokenRedirects extends ApiQueryGeneratorBase { + public function __construct($query, $moduleName) { + parent :: __construct($query, $moduleName, 'br'); + } + + public function execute() { + $this->run(); + } + + public function executeGenerator($resultPageSet) { + if ($resultPageSet->isResolvingRedirects()) + $this->dieUsage('Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params'); + + $this->run($resultPageSet); + } + + private function run($resultPageSet = null) { + $db = $this->getDB(); + $params = $this->extractRequestParams(); + list( $page, $redirect ) = $db->tableNamesN( 'page', 'redirect' ); + + $this->addFields( array( + "'BrokenRedirects' AS type", + "p1.page_namespace AS namespace", + "p1.page_title AS title", + "p1.page_id AS pageid", + "rd_namespace", + "rd_title", + )); + $this->addTables("redirect AS rd JOIN page p1 ON (rd.rd_from=p1.page_id) LEFT JOIN page AS p2 ON (rd_namespace=p2.page_namespace AND rd_title=p2.page_title )"); + # I don't know why these two not work ~~Alexsh + #$this->addJoinConds(array("$page AS p1" => array('JOIN', 'rd.rd_from=p1.page_id'))); + #$this->addJoinConds(array("$page AS p2" => array('LEFT JOIN', 'rd_namespace=p2.page_namespace AND rd_title=p2.page_title'))); + $this->addWhere( array( + "rd_namespace >= 0", + "p2.page_namespace IS NULL", + )); + + $limit = $params['limit']; + $this->addOption('LIMIT', $limit+1); + if(!is_null($params['offset'])) + $this->addOption('OFFSET', $params['offset']); + + $res = $this->select(__METHOD__); + $result = $this->getResult(); + $count = 0; + while ($row = $db->fetchObject($res)) { + if (++ $count > $limit) { + // We've reached the one extra which shows that there are additional pages to be had. Stop here... + // TODO: Security issue - if the user has no right to view next title, it will still be shown + $this->setContinueEnumParameter('offset', @$params['offset'] + $params['limit']); + break; + } + if (is_null($resultPageSet)) { + $title = Title :: makeTitle($row->page_namespace, $row->title); + $rdtitle = Title :: makeTitle($row->page_namespace, $row->rd_title); + $vals = array( + 'pageid' => intval($row->pageid), + 'ns' => intval($row->namespace), + 'title' => $title->getPrefixedText(), + 'target' => $rdtitle->getPrefixedText() + ); + $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); + if(!$fit) + { + $this->setContinueEnumParameter('offset', @$params['offset'] + $count - 1); + break; + } + } else { + $resultPageSet->processDbRow($row); + } + } + $db->freeResult($res); + + if (is_null($resultPageSet)) { + $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'p'); + } + } + + public function getAllowedParams() { + return array ( + 'limit' => array( + ApiBase :: PARAM_DFLT => 10, + ApiBase :: PARAM_TYPE => 'limit', + ApiBase :: PARAM_MIN => 1, + ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1, + ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2 + ), + 'offset' => null, + ); + } + + public function getParamDescription() { + return array( + 'limit' => 'How many links to return', + 'offset' => 'When more results are available, use this to continue', + ); + } + + public function getDescription() { + return 'Enumerate all broken redirects'; + } + + protected function getExamples() { + return array ( + 'api.php?action=query&list=brokenredirects', + ); + } + + public function getVersion() { + return __CLASS__ . ': $Id: ApiQueryBrokenRedirects.php 46845 2009-07-23 14:00:00Z alexsh $'; + } + +} \ No newline at end of file diff --git a/includes/api/ApiQueryDoubleRedirects.php b/includes/api/ApiQueryDoubleRedirects.php new file mode 100644 index 0000000000..1f3401833b --- /dev/null +++ b/includes/api/ApiQueryDoubleRedirects.php @@ -0,0 +1,163 @@ +@gmail.com + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiQueryBase.php'); +} + +/** + * Query module to enumerate all available pages. + * + * @ingroup API + */ +class ApiQueryDoubleRedirects extends ApiQueryGeneratorBase { + public function __construct($query, $moduleName) { + parent :: __construct($query, $moduleName, 'do'); + } + + public function execute() { + $this->run(); + } + + public function executeGenerator($resultPageSet) { + if ($resultPageSet->isResolvingRedirects()) + $this->dieUsage('Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params'); + + $this->run($resultPageSet); + } + + private function run($resultPageSet = null) { + $db = $this->getDB(); + $params = $this->extractRequestParams(); + + list( $page, $redirect ) = $db->tableNamesN( 'page', 'redirect' ); + $this->addFields( array( + "pa.page_namespace as namespace", + "pa.page_title as title", + "pa.page_id as pageid", + "pb.page_namespace as nsb", + "pb.page_title as tb", + "pb.page_id as idb", + "pc.page_namespace as nsc", + "pc.page_title as tc", + "pc.page_id as idc", + ) + ); + $this->addTables($redirect, 'ra'); + $this->addTables($redirect, 'rb'); + $this->addTables($page, 'pa'); + $this->addTables($page, 'pb'); + $this->addTables($page, 'pc'); + $this->addWhere(array( + "ra.rd_from=pa.page_id", + "ra.rd_namespace=pb.page_namespace", + "ra.rd_title=pb.page_title", + "rb.rd_from=pb.page_id", + "rb.rd_namespace=pc.page_namespace", + "rb.rd_title=pc.page_title" + ) + ); + $limit = $params['limit']; + $this->addOption('LIMIT', $limit+1); + if(!is_null($params['offset'])) + $this->addOption('OFFSET', $params['offset']); + $res = $this->select(__METHOD__); + $result = $this->getResult(); + $count = 0; + while ($row = $db->fetchObject($res)) { + if (++ $count > $limit) { + // We've reached the one extra which shows that there are additional pages to be had. Stop here... + // TODO: Security issue - if the user has no right to view next title, it will still be shown + $this->setContinueEnumParameter('offset', @$params['offset'] + $params['limit']); + break; + } + if (is_null($resultPageSet)) { + $title = Title :: makeTitle($row->page_namespace, $row->title); + $titleB = Title :: makeTitle($row->page_namespace, $row->tb); + $titleC = Title :: makeTitle($row->page_namespace, $row->tc); + $vals = array( + 'pageid' => $row->pageid, + 'ns' => intval($row->namespace), + 'title' => $title->getPrefixedText(), + 'idb' => intval($row->idb), + 'nsb' => intval($row->nsb), + 'tb' => $titleB->getPrefixedText(), + 'idc' => intval($row->idc), + 'nsc' => intval($row->nsc), + 'tc' => $titleC->getPrefixedText(), + ); + $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); + if(!$fit) + { + $this->setContinueEnumParameter('offset', @$params['offset'] + $count - 1); + break; + } + } else { + $resultPageSet->processDbRow($row); + } + } + $db->freeResult($res); + + if (is_null($resultPageSet)) { + $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'p'); + } + } + + public function getAllowedParams() { + return array ( + 'limit' => array( + ApiBase :: PARAM_DFLT => 10, + ApiBase :: PARAM_TYPE => 'limit', + ApiBase :: PARAM_MIN => 1, + ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1, + ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2 + ), + 'offset' => null, + ); + } + + public function getParamDescription() { + return array( + 'limit' => 'How many links to return', + 'offset' => 'When more results are available, use this to continue', + ); + } + + public function getDescription() { + return 'Enumerate all double redirects'; + } + + protected function getExamples() { + return array ( + 'api.php?action=query&list=doubleredirects', + ); + } + + public function getVersion() { + return __CLASS__ . ': $Id: ApiQueryDoubleRedirects.php 46845 2009-07-24 14:00:00Z alexsh $'; + } + +} \ No newline at end of file -- 2.20.1