diff options
Diffstat (limited to 'includes/specials/SpecialLinkSearch.php')
-rw-r--r-- | includes/specials/SpecialLinkSearch.php | 114 |
1 files changed, 79 insertions, 35 deletions
diff --git a/includes/specials/SpecialLinkSearch.php b/includes/specials/SpecialLinkSearch.php index 5b0c56e5..371469bb 100644 --- a/includes/specials/SpecialLinkSearch.php +++ b/includes/specials/SpecialLinkSearch.php @@ -27,6 +27,12 @@ * @ingroup SpecialPage */ class LinkSearchPage extends QueryPage { + + /** + * @var PageLinkRenderer + */ + protected $linkRenderer = null; + function setParams( $params ) { $this->mQuery = $params['query']; $this->mNs = $params['namespace']; @@ -35,6 +41,36 @@ class LinkSearchPage extends QueryPage { function __construct( $name = 'LinkSearch' ) { parent::__construct( $name ); + + // Since we don't control the constructor parameters, we can't inject services that way. + // Instead, we initialize services in the execute() method, and allow them to be overridden + // using the setServices() method. + } + + /** + * Initialize or override the PageLinkRenderer LinkSearchPage collaborates with. + * Useful mainly for testing. + * + * @todo query logic and rendering logic should be split and also injected + * + * @param PageLinkRenderer $linkRenderer + */ + public function setPageLinkRenderer( + PageLinkRenderer $linkRenderer + ) { + $this->linkRenderer = $linkRenderer; + } + + /** + * Initialize any services we'll need (unless it has already been provided via a setter). + * This allows for dependency injection even though we don't control object creation. + */ + private function initServices() { + if ( !$this->linkRenderer ) { + $lang = $this->getContext()->getLanguage(); + $titleFormatter = new MediaWikiTitleCodec( $lang, GenderCache::singleton() ); + $this->linkRenderer = new MediaWikiPageLinkRenderer( $titleFormatter ); + } } function isCacheable() { @@ -42,7 +78,7 @@ class LinkSearchPage extends QueryPage { } function execute( $par ) { - global $wgUrlProtocols, $wgMiserMode, $wgScript; + $this->initServices(); $this->setHeaders(); $this->outputHeader(); @@ -55,32 +91,26 @@ class LinkSearchPage extends QueryPage { $namespace = $request->getIntorNull( 'namespace', null ); $protocols_list = array(); - foreach ( $wgUrlProtocols as $prot ) { + foreach ( $this->getConfig()->get( 'UrlProtocols' ) as $prot ) { if ( $prot !== '//' ) { $protocols_list[] = $prot; } } $target2 = $target; - $protocol = ''; - $pr_sl = strpos( $target2, '//' ); - $pr_cl = strpos( $target2, ':' ); - if ( $pr_sl ) { - // For protocols with '//' - $protocol = substr( $target2, 0, $pr_sl + 2 ); - $target2 = substr( $target2, $pr_sl + 2 ); - } elseif ( !$pr_sl && $pr_cl ) { - // For protocols without '//' like 'mailto:' - $protocol = substr( $target2, 0, $pr_cl + 1 ); - $target2 = substr( $target2, $pr_cl + 1 ); - } elseif ( $protocol == '' && $target2 != '' ) { - // default - $protocol = 'http://'; - } - if ( $protocol != '' && !in_array( $protocol, $protocols_list ) ) { - // unsupported protocol, show original search request - $target2 = $target; - $protocol = ''; + // Get protocol, default is http:// + $protocol = 'http://'; + $bits = wfParseUrl( $target ); + if ( isset( $bits['scheme'] ) && isset( $bits['delimiter'] ) ) { + $protocol = $bits['scheme'] . $bits['delimiter']; + // Make sure wfParseUrl() didn't make some well-intended correction in the + // protocol + if ( strcasecmp( $protocol, substr( $target, 0, strlen( $protocol ) ) ) === 0 ) { + $target2 = substr( $target, strlen( $protocol ) ); + } else { + // If it did, let LinkFilter::makeLikeArray() handle this + $protocol = ''; + } } $out->addWikiMsg( @@ -90,9 +120,9 @@ class LinkSearchPage extends QueryPage { ); $s = Html::openElement( 'form', - array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $wgScript ) + array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => wfScript() ) ) . "\n" . - Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n" . + Html::hidden( 'title', $this->getPageTitle()->getPrefixedDBkey() ) . "\n" . Html::openElement( 'fieldset' ) . "\n" . Html::element( 'legend', array(), $this->msg( 'linksearch' )->text() ) . "\n" . Xml::inputLabel( @@ -100,10 +130,14 @@ class LinkSearchPage extends QueryPage { 'target', 'target', 50, - $target + $target, + array( + // URLs are always ltr + 'dir' => 'ltr', + ) ) . "\n"; - if ( !$wgMiserMode ) { + if ( !$this->getConfig()->get( 'MiserMode' ) ) { $s .= Html::namespaceSelector( array( 'selected' => $namespace, @@ -145,18 +179,26 @@ class LinkSearchPage extends QueryPage { /** * Return an appropriately formatted LIKE query and the clause * - * @param string $query - * @param string $prot + * @param string $query Search pattern to search for + * @param string $prot Protocol, e.g. 'http://' + * * @return array */ static function mungeQuery( $query, $prot ) { $field = 'el_index'; - $rv = LinkFilter::makeLikeArray( $query, $prot ); + $dbr = wfGetDB( DB_SLAVE ); + + if ( $query === '*' && $prot !== '' ) { + // Allow queries like 'ftp://*' to find all ftp links + $rv = array( $prot, $dbr->anyString() ); + } else { + $rv = LinkFilter::makeLikeArray( $query, $prot ); + } + if ( $rv === false ) { // LinkFilter doesn't handle wildcard in IP, so we'll have to munge here. $pattern = '/^(:?[0-9]{1,3}\.)+\*\s*$|^(:?[0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]*\*\s*$/'; if ( preg_match( $pattern, $query ) ) { - $dbr = wfGetDB( DB_SLAVE ); $rv = array( $prot . rtrim( $query, " \t*" ), $dbr->anyString() ); $field = 'el_to'; } @@ -166,10 +208,9 @@ class LinkSearchPage extends QueryPage { } function linkParameters() { - global $wgMiserMode; $params = array(); $params['target'] = $this->mProt . $this->mQuery; - if ( isset( $this->mNs ) && !$wgMiserMode ) { + if ( $this->mNs !== null && !$this->getConfig()->get( 'MiserMode' ) ) { $params['namespace'] = $this->mNs; } @@ -177,7 +218,6 @@ class LinkSearchPage extends QueryPage { } function getQueryInfo() { - global $wgMiserMode; $dbr = wfGetDB( DB_SLAVE ); // strip everything past first wildcard, so that // index-based-only lookup would be done @@ -204,7 +244,7 @@ class LinkSearchPage extends QueryPage { 'options' => array( 'USE INDEX' => $clause ) ); - if ( isset( $this->mNs ) && !$wgMiserMode ) { + if ( $this->mNs !== null && !$this->getConfig()->get( 'MiserMode' ) ) { $retval['conds']['page_namespace'] = $this->mNs; } @@ -217,9 +257,10 @@ class LinkSearchPage extends QueryPage { * @return string */ function formatResult( $skin, $result ) { - $title = Title::makeTitle( $result->namespace, $result->title ); + $title = new TitleValue( (int)$result->namespace, $result->title ); + $pageLink = $this->linkRenderer->renderHtmlLink( $title ); + $url = $result->url; - $pageLink = Linker::linkKnown( $title ); $urlLink = Linker::makeExternalLink( $url, $url ); return $this->msg( 'linksearch-line' )->rawParams( $urlLink, $pageLink )->escaped(); @@ -227,6 +268,9 @@ class LinkSearchPage extends QueryPage { /** * Override to check query validity. + * + * @param mixed $offset Numerical offset or false for no offset + * @param mixed $limit Numerical limit or false for no limit */ function doQuery( $offset = false, $limit = false ) { list( $this->mMungedQuery, ) = LinkSearchPage::mungeQuery( $this->mQuery, $this->mProt ); |