Merge "make XmlDumpwriter more resilient to blob store corruption"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 24 Jul 2019 12:13:53 +0000 (12:13 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 24 Jul 2019 12:13:53 +0000 (12:13 +0000)
includes/cache/localisation/LocalisationCache.php
includes/specials/SpecialSearch.php
languages/i18n/en.json
languages/i18n/qqq.json
tests/phpunit/includes/specials/SpecialSearchTest.php

index a0f3d8e..ffc7cd0 100644 (file)
@@ -407,7 +407,7 @@ class LocalisationCache {
         */
        public function isExpired( $code ) {
                if ( $this->forceRecache && !isset( $this->recachedLangs[$code] ) ) {
-                       $this->logger->debug( __METHOD__ . "($code): forced reload\n" );
+                       $this->logger->debug( __METHOD__ . "($code): forced reload" );
 
                        return true;
                }
@@ -417,7 +417,7 @@ class LocalisationCache {
                $preload = $this->store->get( $code, 'preload' );
                // Different keys may expire separately for some stores
                if ( $deps === null || $keys === null || $preload === null ) {
-                       $this->logger->debug( __METHOD__ . "($code): cache missing, need to make one\n" );
+                       $this->logger->debug( __METHOD__ . "($code): cache missing, need to make one" );
 
                        return true;
                }
@@ -429,7 +429,7 @@ class LocalisationCache {
                        // When this happens, always expire the cache
                        if ( !$dep instanceof CacheDependency || $dep->isExpired() ) {
                                $this->logger->debug( __METHOD__ . "($code): cache for $code expired due to " .
-                                       get_class( $dep ) . "\n" );
+                                       get_class( $dep ) );
 
                                return true;
                        }
@@ -836,10 +836,10 @@ class LocalisationCache {
                # Load the primary localisation from the source file
                $data = $this->readSourceFilesAndRegisterDeps( $code, $deps );
                if ( $data === false ) {
-                       $this->logger->debug( __METHOD__ . ": no localisation file for $code, using fallback to en\n" );
+                       $this->logger->debug( __METHOD__ . ": no localisation file for $code, using fallback to en" );
                        $coreData['fallback'] = 'en';
                } else {
-                       $this->logger->debug( __METHOD__ . ": got localisation for $code from source\n" );
+                       $this->logger->debug( __METHOD__ . ": got localisation for $code from source" );
 
                        # Merge primary localisation
                        foreach ( $data as $key => $value ) {
index eacc7a0..ad045e4 100644 (file)
@@ -79,7 +79,7 @@ class SpecialSearch extends SpecialPage {
        /**
         * @var string
         */
-       protected $sort;
+       protected $sort = SearchEngine::DEFAULT_SORT;
 
        /**
         * @var bool
@@ -92,6 +92,12 @@ class SpecialSearch extends SpecialPage {
         */
        protected $searchConfig;
 
+       /**
+        * @var Status Holds any parameter validation errors that should
+        *  be displayed back to the user.
+        */
+       private $loadStatus;
+
        const NAMESPACES_CURRENT = 'sense';
 
        public function __construct() {
@@ -204,6 +210,8 @@ class SpecialSearch extends SpecialPage {
         * @see tests/phpunit/includes/specials/SpecialSearchTest.php
         */
        public function load() {
+               $this->loadStatus = new Status();
+
                $request = $this->getRequest();
                list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, '' );
                $this->mPrefix = $request->getVal( 'prefix', '' );
@@ -211,8 +219,13 @@ class SpecialSearch extends SpecialPage {
                        $this->setExtraParam( 'prefix', $this->mPrefix );
                }
 
-               $this->sort = $request->getVal( 'sort', SearchEngine::DEFAULT_SORT );
-               if ( $this->sort !== SearchEngine::DEFAULT_SORT ) {
+               $sort = $request->getVal( 'sort', SearchEngine::DEFAULT_SORT );
+               $validSorts = $this->getSearchEngine()->getValidSorts();
+               if ( !in_array( $sort, $validSorts ) ) {
+                       $this->loadStatus->warning( 'search-invalid-sort-order', $sort,
+                               implode( ', ', $validSorts ) );
+               } elseif ( $sort !== $this->sort ) {
+                       $this->sort = $sort;
                        $this->setExtraParam( 'sort', $this->sort );
                }
 
@@ -247,6 +260,7 @@ class SpecialSearch extends SpecialPage {
                        $this->namespaces = $profiles[$profile]['namespaces'];
                } else {
                        // Unknown profile requested
+                       $this->loadStatus->warning( 'search-unknown-profile', $profile );
                        $profile = 'default';
                        $this->namespaces = $profiles['default']['namespaces'];
                }
@@ -375,7 +389,7 @@ class SpecialSearch extends SpecialPage {
                        $out->addHTML( $dymWidget->render( $term, $textMatches ) );
                }
 
-               $hasErrors = $textStatus && $textStatus->getErrors() !== [];
+               $hasSearchErrors = $textStatus && $textStatus->getErrors() !== [];
                $hasOtherResults = $textMatches &&
                        $textMatches->hasInterwikiResults( ISearchResultSet::INLINE_RESULTS );
 
@@ -385,7 +399,12 @@ class SpecialSearch extends SpecialPage {
                        $out->addHTML( '<div class="searchresults">' );
                }
 
-               if ( $hasErrors ) {
+               if ( $hasSearchErrors || $this->loadStatus->getErrors() ) {
+                       if ( $textStatus === null ) {
+                               $textStatus = $this->loadStatus;
+                       } else {
+                               $textStatus->merge( $this->loadStatus );
+                       }
                        list( $error, $warning ) = $textStatus->splitByErrorType();
                        if ( $error->getErrors() ) {
                                $out->addHTML( Html::errorBox(
@@ -405,7 +424,7 @@ class SpecialSearch extends SpecialPage {
                Hooks::run( 'SpecialSearchResults', [ $term, &$titleMatches, &$textMatches ] );
 
                // If we have no results and have not already displayed an error message
-               if ( $num === 0 && !$hasErrors ) {
+               if ( $num === 0 && !$hasSearchErrors ) {
                        $out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>", [
                                $hasOtherResults ? 'search-nonefound-thiswiki' : 'search-nonefound',
                                wfEscapeWikiText( $term )
index d654a52..01e1007 100644 (file)
        "search-interwiki-more": "(more)",
        "search-interwiki-more-results": "more results",
        "search-relatedarticle": "Related",
+       "search-invalid-sort-order": "Sort order of $1 is unrecognized, default sorting will be applied. Valid sort orders are: $2",
+       "search-unknown-profile": "Search profile of $1 is unrecognized, default search profile will be applied.",
        "searchrelated": "related",
        "searchall": "all",
        "showingresults": "Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} starting with #<strong>$2</strong>.",
index c831a71..081bb66 100644 (file)
        "search-interwiki-more": "{{Identical|More}}",
        "search-interwiki-more-results": "Label for a link that leads to more search results from a given wiki.",
        "search-relatedarticle": "This is a search result (and I guess search engine) dependent messages. I do not know how to trigger the feature. The message is displayed if the search result contains information that related pages can also be provided from the search engine. I assume this is \"More Like This\" functionality. Microsoft glossary defines MLT as \"A way to refine search by identifying the right set of documents and then locating similar documents. This allows the searcher to control the direction of the search and focus on the most fruitful lines of inquiry.\"[http://www.microsoft.com/enterprisesearch/en/us/search-glossary.aspx]\n{{Identical|Related}}",
+       "search-invalid-sort-order": "Warning displayed on Special:Search when an unrecognized sorting order is requested.",
+       "search-unknown-profile": "Warning displayed on Special:Search when an unrecognized search profile is requested.",
        "searchrelated": "This is a search result (and I guess search engine) dependent messages. I do not know how to trigger the feature. The message is displayed if the search result contains information that related pages can also be provided from the search engine. I assume this is \"More Like This\" functionality. Microsoft glossary defines MLT as \"A way to refine search by identifying the right set of documents and then locating similar documents. This allows the searcher to control the direction of the search and focus on the most fruitful lines of inquiry.\"[http://www.microsoft.com/enterprisesearch/en/us/search-glossary.aspx]\n{{Identical|Related}}",
        "searchall": "{{Identical|All}}",
        "showingresults": "This message is used on some special pages such as [[Special:WantedCategories]]. Parameters:\n* $1 - the total number of results in the batch shown\n* $2 - the number of the first item listed\nSee also:\n* {{msg-mw|Showingresultsnum}}",
index 4dd6c80..eeb4b00 100644 (file)
@@ -11,6 +11,27 @@ use MediaWiki\MediaWikiServices;
  */
 class SpecialSearchTest extends MediaWikiTestCase {
 
+       /**
+        * @covers SpecialSearch::load
+        * @covers SpecialSearch::showResults
+        */
+       public function testValidateSortOrder() {
+               $ctx = new RequestContext();
+               $ctx->setRequest( new FauxRequest( [
+                       'search' => 'foo',
+                       'fulltext' => 1,
+                       'sort' => 'invalid',
+               ] ) );
+               $sp = Title::makeTitle( NS_SPECIAL, 'Search' );
+               MediaWikiServices::getInstance()
+                       ->getSpecialPageFactory()
+                       ->executePath( $sp, $ctx );
+               $html = $ctx->getOutput()->getHTML();
+               $this->assertRegExp( '/class="warningbox"/', $html, 'must contain warnings' );
+               $this->assertRegExp( '/Sort order of invalid is unrecognized/',
+                       $html, 'must tell user sort order is invalid' );
+       }
+
        /**
         * @covers SpecialSearch::load
         * @dataProvider provideSearchOptionsTests