Index: includes/SpecialWhatlinkshere.php =================================================================== --- includes/SpecialWhatlinkshere.php (revision 23311) +++ includes/SpecialWhatlinkshere.php (working copy) @@ -24,8 +24,18 @@ var $selfTitle, $skin; private $namespace; + + /** + * An array specifying which of links, inclusions, redirects to display. + * Format is self-explanatory. + */ + private $mShow = array( + 'link' => true, + 'inclusion' => true, + 'redirect' => true + ); - function WhatLinksHerePage( &$request, $par = null ) { + function __construct( &$request, $par = null ) { global $wgUser; $this->request =& $request; $this->skin = $wgUser->getSkin(); @@ -41,6 +51,14 @@ } $this->from = $this->request->getInt( 'from' ); $this->back = $this->request->getInt( 'back' ); + + // Ideally we'd have checkboxes saying something like "show X", not + // "hide X", but due to the vagaries of HTML, that would cause issues + // if the user visited the page without checking anything (say by + // direct link), since then we would have to assume they're false. + foreach( array_keys( $this->mShow ) as $key ) { + $this->mShow[$key] = !$this->request->getCheck( "hide$key" ); + } $targetString = isset($this->par) ? $this->par : $this->request->getVal( 'target' ); @@ -74,9 +92,7 @@ */ function showIndirectLinks( $level, $target, $limit, $from = 0, $back = 0 ) { global $wgOut; - $fname = 'WhatLinksHerePage::showIndirectLinks'; $dbr = wfGetDB( DB_READ ); - $options = array(); $ns = $this->request->getIntOrNull( 'namespace' ); if ( isset( $ns ) ) { @@ -86,49 +102,67 @@ $options['namespace'] = ''; } - // Make the query - $plConds = array( - 'page_id=pl_from', - 'pl_namespace' => $target->getNamespace(), - 'pl_title' => $target->getDBkey(), - ); + // Make sure options are sane + if( !$this->mShow['link'] and !$this->mShow['inclusion'] + and !$this->mShow['redirect'] ) { + // Uh, why are you viewing the page in the first place? + $this->mShow['link'] = $this->mShow['inclusion'] = + $this->mShow['redirect'] = true; + } - $tlConds = array( - 'page_id=tl_from', - 'tl_namespace' => $target->getNamespace(), - 'tl_title' => $target->getDBkey(), - ); + // Make the queries. + // templatelinks comes second so that the templatelinks row overwrites + // the pagelinks row, so we get (inclusion) rather than nothing when we + // merge the two later. + $queries = array(); - if ( $this->namespace !== null ){ - $plConds['page_namespace'] = (int)$this->namespace; - $tlConds['page_namespace'] = (int)$this->namespace; + if( $this->mShow['link'] or $this->mShow['redirect'] ) { + $queries['page'] = 'pl_'; } + if( $this->mShow['inclusion'] ) { + $queries['template'] = 'tl_'; + } - if ( $from ) { - $from = (int)$from; // just in case - $tlConds[] = "tl_from >= $from"; - $plConds[] = "pl_from >= $from"; - } + foreach( $queries as $linksType => $tablePrefix ) { + $options = array(); + $conds = array( + "page_id={$tablePrefix}from", + "{$tablePrefix}namespace" => $target->getNamespace(), + "{$tablePrefix}title" => $target->getDBkey(), + ); + // Read an extra row as an at-end check + $options['limit'] = $limit + 1; + // enforce join order, sometimes namespace selector may trigger + // filesorts which are far less efficient than scanning many + // entries + $options[] = 'STRAIGHT_JOIN'; + $options['ORDER BY'] = "{$tablePrefix}from"; - // Read an extra row as an at-end check - $queryLimit = $limit + 1; - - // enforce join order, sometimes namespace selector may - // trigger filesorts which are far less efficient than scanning many entries - $options[] = 'STRAIGHT_JOIN'; - - $options['LIMIT'] = $queryLimit; - $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ); + if ( $this->namespace !== null ){ + $conds['page_namespace'] = (int)$this->namespace; + } + if ( $from ) { + $from = (int)$from; // just in case + $query['conds'][] = "{$tablePrefix}from >= $from"; + } + if( !$this->mShow['redirect'] ) { + $conds[] = 'page_is_redirect != 1'; + } - $options['ORDER BY'] = 'pl_from'; - $plRes = $dbr->select( array( 'pagelinks', 'page' ), $fields, - $plConds, $fname, $options ); - - $options['ORDER BY'] = 'tl_from'; - $tlRes = $dbr->select( array( 'templatelinks', 'page' ), $fields, - $tlConds, $fname, $options ); - - if ( !$dbr->numRows( $plRes ) && !$dbr->numRows( $tlRes ) ) { + $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ); + $res = $dbr->select( array( "{$linksType}links", 'page' ), $fields, $conds, __METHOD__, $options ); + + // Read the rows into an array and remove duplicates. This is + // where page before template matters! + while ( $row = $dbr->fetchObject( $res ) ) { + $row->is_template = $linksType == 'template'; + $rows[$row->page_id] = $row; + } + $dbr->freeResult( $res ); + } + + // Are there any links at all? If not, abort. + if ( !count($rows) ) { if ( 0 == $level && !isset( $this->namespace ) ) { // really no links to here $wgOut->addWikiText( wfMsg( 'nolinkshere', $this->target->getPrefixedText() ) ); @@ -144,35 +178,6 @@ return; } - $options = array(); - list( $options['limit'], $options['offset']) = wfCheckLimits(); - if ( ( $ns = $this->request->getVal( 'namespace', null ) ) !== null && $ns !== '' && ctype_digit($ns) ) { - $options['namespace'] = intval( $ns ); - $this->setNamespace( $options['namespace'] ); - } else { - $options['namespace'] = ''; - $this->setNamespace( null ); - } - $options['offset'] = $this->request->getVal( 'offset' ); - /* Offset must be an integral. */ - if ( !strlen( $options['offset'] ) || !preg_match( '/^[0-9]+$/', $options['offset'] ) ) - $options['offset'] = ''; - $options['target'] = $this->target->getPrefixedDBkey(); - - // Read the rows into an array and remove duplicates - // templatelinks comes second so that the templatelinks row overwrites the - // pagelinks row, so we get (inclusion) rather than nothing - while ( $row = $dbr->fetchObject( $plRes ) ) { - $row->is_template = 0; - $rows[$row->page_id] = $row; - } - $dbr->freeResult( $plRes ); - while ( $row = $dbr->fetchObject( $tlRes ) ) { - $row->is_template = 1; - $rows[$row->page_id] = $row; - } - $dbr->freeResult( $tlRes ); - // Sort by key and then change the keys to 0-based indices ksort( $rows ); $rows = array_values( $rows ); @@ -192,6 +197,21 @@ } $prevId = $from; + // Set up options for the new Whatlinkshere form to display with the + // results + $options = array(); + list( $options['limit'], $options['offset']) = wfCheckLimits(); + if ( ( $ns = $this->request->getIntOrNull( 'namespace' ) ) !== null ) { + $options['namespace'] = $ns; + $this->setNamespace( $options['namespace'] ); + } else { + $options['namespace'] = ''; + $this->setNamespace( null ); + } + $options['offset'] = $this->request->getInt( 'offset' ); + $options['target'] = $this->target->getPrefixedDBkey(); + // End options setup + if ( $level == 0 ) { $wgOut->addHTML( $this->whatlinkshereForm( $options ) ); $wgOut->addWikiText( wfMsg( 'linkshere', $this->target->getPrefixedText() ) );