}
function execute( $par ) {
- global $wgQueryPageDefaultLimit;
$out = $this->getOutput();
$this->setHeaders();
$opts->add( 'target', '' );
$opts->add( 'namespace', '', FormOptions::INTNULL );
- $opts->add( 'limit', $wgQueryPageDefaultLimit );
+ $opts->add( 'limit', $this->getConfig()->get( 'QueryPageDefaultLimit' ) );
$opts->add( 'from', 0 );
$opts->add( 'back', 0 );
$opts->add( 'hideredirs', false );
$opts->add( 'hidetrans', false );
$opts->add( 'hidelinks', false );
$opts->add( 'hideimages', false );
+ $opts->add( 'invert', false );
$opts->fetchValuesFromRequest( $this->getRequest() );
$opts->validateIntBounds( 'limit', 0, 5000 );
* @param int $back Display from this article ID at backwards scrolling (default: 0)
*/
function showIndirectLinks( $level, $target, $limit, $from = 0, $back = 0 ) {
- global $wgMaxRedirectLinksRetrieved, $wgUseLinkNamespaceDBFields;
-
$out = $this->getOutput();
$dbr = wfGetDB( DB_SLAVE );
'il_to' => $target->getDBkey(),
);
+ $useLinkNamespaceDBFields = $this->getConfig()->get( 'UseLinkNamespaceDBFields' );
$namespace = $this->opts->getValue( 'namespace' );
+ $invert = $this->opts->getValue( 'invert' );
+ $nsComparison = ( $invert ? '!= ' : '= ' ) . $dbr->addQuotes( $namespace );
if ( is_int( $namespace ) ) {
- if ( $wgUseLinkNamespaceDBFields ) {
- $conds['pagelinks']['pl_from_namespace'] = $namespace;
- $conds['templatelinks']['tl_from_namespace'] = $namespace;
- $conds['imagelinks']['il_from_namespace'] = $namespace;
+ if ( $useLinkNamespaceDBFields ) {
+ $conds['pagelinks'][] = "pl_from_namespace $nsComparison";
+ $conds['templatelinks'][] = "tl_from_namespace $nsComparison";
+ $conds['imagelinks'][] = "il_from_namespace $nsComparison";
} else {
- $conds['pagelinks']['page_namespace'] = $namespace;
- $conds['templatelinks']['page_namespace'] = $namespace;
- $conds['imagelinks']['page_namespace'] = $namespace;
+ $conds['pagelinks'][] = "page_namespace $nsComparison";
+ $conds['templatelinks'][] = "page_namespace $nsComparison";
+ $conds['imagelinks'][] = "page_namespace $nsComparison";
}
}
$conds['pagelinks'][] = 'rd_from is NOT NULL';
}
- $queryFunc = function ( $dbr, $table, $fromCol ) use ( $conds, $target, $limit ) {
- global $wgUseLinkNamespaceDBFields;
+ $queryFunc = function ( $dbr, $table, $fromCol ) use (
+ $conds, $target, $limit, $useLinkNamespaceDBFields
+ ) {
// Read an extra row as an at-end check
$queryLimit = $limit + 1;
$on = array(
'rd_title' => $target->getDBkey(),
'rd_interwiki = ' . $dbr->addQuotes( '' ) . ' OR rd_interwiki IS NULL'
);
- if ( $wgUseLinkNamespaceDBFields ) { // migration check
+ if ( $useLinkNamespaceDBFields ) { // migration check
$on['rd_namespace'] = $target->getNamespace();
}
- // Inner LIMIT is 2X in case of stale backlinks with no page
+ // Inner LIMIT is 2X in case of stale backlinks with wrong namespaces
$subQuery = $dbr->selectSqlText(
- array( $table, 'redirect' ),
+ array( $table, 'page', 'redirect' ),
array( $fromCol, 'rd_from' ),
$conds[$table],
__CLASS__ . '::showIndirectLinks',
array( 'ORDER BY' => $fromCol, 'LIMIT' => 2 * $queryLimit ),
- array( 'redirect' => array( 'LEFT JOIN', $on ) )
+ array(
+ 'page' => array( 'INNER JOIN', "$fromCol = page_id" ),
+ 'redirect' => array( 'LEFT JOIN', $on )
+ )
);
return $dbr->select(
array( 'page', 'temp_backlink_range' => "($subQuery)" ),
- array( 'page_id', 'page_namespace', 'page_title', 'rd_from' ),
+ array( 'page_id', 'page_namespace', 'page_title', 'rd_from', 'page_is_redirect' ),
array(),
__CLASS__ . '::showIndirectLinks',
array( 'ORDER BY' => 'page_id', 'LIMIT' => $queryLimit ),
}
$errMsg = is_int( $namespace ) ? 'nolinkshere-ns' : 'nolinkshere';
$out->addWikiMsg( $errMsg, $this->target->getPrefixedText() );
+ $out->setStatusCode( 404 );
}
}
if ( $row->rd_from && $level < 2 ) {
$out->addHTML( $this->listItem( $row, $nt, $target, true ) );
- $this->showIndirectLinks( $level + 1, $nt, $wgMaxRedirectLinksRetrieved );
+ $this->showIndirectLinks(
+ $level + 1,
+ $nt,
+ $this->getConfig()->get( 'MaxRedirectLinksRetrieved' )
+ );
$out->addHTML( Xml::closeElement( 'li' ) );
} else {
$out->addHTML( $this->listItem( $row, $nt, $target ) );
$link = Linker::linkKnown(
$nt,
null,
- array(),
+ $row->page_is_redirect ? array( 'class' => 'mw-redirect' ) : array(),
$query
);
$props[] = $msgcache['isimage'];
}
- wfRunHooks( 'WhatLinksHereProps', array( $row, $nt, $target, &$props ) );
+ Hooks::run( 'WhatLinksHereProps', array( $row, $nt, $target, &$props ) );
if ( count( $props ) ) {
$propsText = $this->msg( 'parentheses' )
}
function whatlinkshereForm() {
- global $wgScript;
-
// We get nicer value from the title object
$this->opts->consumeValue( 'target' );
// Reset these for new requests
$target = $this->target ? $this->target->getPrefixedText() : '';
$namespace = $this->opts->consumeValue( 'namespace' );
+ $nsinvert = $this->opts->consumeValue( 'invert' );
# Build up the form
- $f = Xml::openElement( 'form', array( 'action' => $wgScript ) );
+ $f = Xml::openElement( 'form', array( 'action' => wfScript() ) );
# Values that should not be forgotten
$f .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() );
$f .= Xml::fieldset( $this->msg( 'whatlinkshere' )->text() );
- # Target input
+ # Target input (.mw-searchInput enables suggestions)
$f .= Xml::inputLabel( $this->msg( 'whatlinkshere-page' )->text(), 'target',
- 'mw-whatlinkshere-target', 40, $target );
+ 'mw-whatlinkshere-target', 40, $target, array( 'class' => 'mw-searchInput' ) );
$f .= ' ';
)
);
+ $f .= ' ' .
+ Xml::checkLabel(
+ $this->msg( 'invert' )->text(),
+ 'invert',
+ 'nsinvert',
+ $nsinvert,
+ array( 'title' => $this->msg( 'tooltip-whatlinkshere-invert' )->text() )
+ );
+
$f .= ' ';
# Submit
);
}
+ /**
+ * Return an array of subpages beginning with $search that this special page will accept.
+ *
+ * @param string $search Prefix to search for
+ * @param int $limit Maximum number of results to return (usually 10)
+ * @param int $offset Number of results to skip (usually 0)
+ * @return string[] Matching subpages
+ */
+ public function prefixSearchSubpages( $search, $limit, $offset ) {
+ if ( $search === '' ) {
+ return array();
+ }
+ // Autocomplete subpage the same as a normal search
+ $prefixSearcher = new StringPrefixSearch;
+ $result = $prefixSearcher->search( $search, $limit, array(), $offset );
+ return $result;
+ }
+
protected function getGroupName() {
return 'pagetools';
}