diff options
Diffstat (limited to 'www/wiki/extensions/Translate/specials/SpecialSearchTranslations.php')
-rw-r--r-- | www/wiki/extensions/Translate/specials/SpecialSearchTranslations.php | 208 |
1 files changed, 126 insertions, 82 deletions
diff --git a/www/wiki/extensions/Translate/specials/SpecialSearchTranslations.php b/www/wiki/extensions/Translate/specials/SpecialSearchTranslations.php index 133d4b80..68ac1b2e 100644 --- a/www/wiki/extensions/Translate/specials/SpecialSearchTranslations.php +++ b/www/wiki/extensions/Translate/specials/SpecialSearchTranslations.php @@ -4,7 +4,7 @@ * * @file * @author Niklas Laxström - * @license GPL-2.0+ + * @license GPL-2.0-or-later */ /** @@ -23,7 +23,7 @@ class SpecialSearchTranslations extends SpecialPage { * don't contain any chars that are escaped in html. * @var array */ - protected $hl = array(); + protected $hl = []; /** * How many search results to display per page @@ -33,10 +33,10 @@ class SpecialSearchTranslations extends SpecialPage { public function __construct() { parent::__construct( 'SearchTranslations' ); - $this->hl = array( + $this->hl = [ TranslateUtils::getPlaceholder(), TranslateUtils::getPlaceholder(), - ); + ]; } public function setHeaders() { @@ -64,9 +64,11 @@ class SpecialSearchTranslations extends SpecialPage { $out->addModuleStyles( 'jquery.uls.grid' ); $out->addModuleStyles( 'ext.translate.special.searchtranslations.styles' ); $out->addModuleStyles( 'ext.translate.special.translate.styles' ); + $out->addModuleStyles( [ 'mediawiki.ui.button', 'mediawiki.ui.input', 'mediawiki.ui.checkbox' ] ); $out->addModules( 'ext.translate.special.searchtranslations' ); $out->addModules( 'ext.translate.special.searchtranslations.operatorsuggest' ); $out->addHelpLink( 'Help:Extension:Translate#searching' ); + $out->addJsConfigVars( 'wgTranslateLanguages', TranslateUtils::getLanguageNames( null ) ); $this->opts = $opts = new FormOptions(); $opts->add( 'query', '' ); @@ -86,10 +88,11 @@ class SpecialSearchTranslations extends SpecialPage { if ( $queryString === '' ) { $this->showEmptySearch(); - return; } + $search = $this->getSearchInput( $queryString ); + $options = $params = $opts->getAllValues(); $filter = $opts->getValue( 'filter' ); try { @@ -98,6 +101,11 @@ class SpecialSearchTranslations extends SpecialPage { } $translationSearch = new CrossLanguageTranslationSearchQuery( $options, $server ); if ( in_array( $filter, $translationSearch->getAvailableFilters() ) ) { + if ( $options['language'] === $options['sourcelanguage'] ) { + $this->showSearchError( $search, $this->msg( 'tux-sst-error-language' ) ); + return; + } + $opts->setValue( 'language', $options['language'] ); $documents = $translationSearch->getDocuments(); $total = $translationSearch->getTotalHits(); @@ -108,7 +116,15 @@ class SpecialSearchTranslations extends SpecialPage { $total = $server->getTotalHits( $resultset ); } } catch ( TTMServerException $e ) { - error_log( 'Translation search server unavailable:' . $e->getMessage() ); + $message = $e->getMessage(); + // Known exceptions + if ( preg_match( '/^Result window is too large/', $message ) ) { + $this->showSearchError( $search, $this->msg( 'tux-sst-error-offset' ) ); + return; + } + + // Other exceptions + error_log( 'Translation search server unavailable: ' . $e->getMessage() ); throw new ErrorPageError( 'tux-sst-solr-offline-title', 'tux-sst-solr-offline-body' ); } @@ -116,28 +132,28 @@ class SpecialSearchTranslations extends SpecialPage { $facets = $server->getFacets( $resultset ); $facetHtml = ''; - if ( count( $facets['language'] ) > 0 ) { + if ( $facets['language'] !== [] ) { if ( $filter !== '' ) { $facets['language'] = array_merge( $facets['language'], - array( $opts->getValue( 'language' ) => $total ) + [ $opts->getValue( 'language' ) => $total ] ); } $facetHtml = Html::element( 'div', - array( 'class' => 'row facet languages', + [ 'class' => 'row facet languages', 'data-facets' => FormatJson::encode( $this->getLanguages( $facets['language'] ) ), 'data-language' => $opts->getValue( 'language' ), - ), - $this->msg( 'tux-sst-facet-language' ) + ], + $this->msg( 'tux-sst-facet-language' )->text() ); } - if ( count( $facets['group'] ) > 0 ) { + if ( $facets['group'] !== [] ) { $facetHtml .= Html::element( 'div', - array( 'class' => 'row facet groups', + [ 'class' => 'row facet groups', 'data-facets' => FormatJson::encode( $this->getGroups( $facets['group'] ) ), - 'data-group' => $opts->getValue( 'group' ) ), - $this->msg( 'tux-sst-facet-group' ) + 'data-group' => $opts->getValue( 'group' ) ], + $this->msg( 'tux-sst-facet-group' )->text() ); } @@ -150,11 +166,16 @@ class SpecialSearchTranslations extends SpecialPage { $code = $handle->getCode(); $language = $opts->getValue( 'language' ); if ( $code !== '' && $code !== $language && $handle->isValid() ) { - $groupId = $handle->getGroup()->getId(); - $helpers = new TranslationHelpers( $title, $groupId ); + $dataProvider = new TranslationAidDataProvider( $handle ); + $aid = new CurrentTranslationAid( + $handle->getGroup(), + $handle, + $this->getContext(), + $dataProvider + ); $document['wiki'] = wfWikiID(); $document['localid'] = $handle->getTitleForBase()->getPrefixedText(); - $document['content'] = $helpers->getTranslation(); + $document['content'] = $aid->getData()['value']; $document['language'] = $handle->getCode(); array_unshift( $documents, $document ); $total++; @@ -175,25 +196,19 @@ class SpecialSearchTranslations extends SpecialPage { continue; } - $resultAttribs = array( + $resultAttribs = [ 'class' => 'row tux-message', 'data-title' => $title->getPrefixedText(), 'data-language' => $document['language'], - ); + ]; $handle = new MessageHandle( $title ); if ( $handle->isValid() ) { - $groupId = $handle->getGroup()->getId(); - $helpers = new TranslationHelpers( $title, $groupId ); - $resultAttribs['data-definition'] = $helpers->getDefinition(); - $resultAttribs['data-translation'] = $helpers->getTranslation(); - $resultAttribs['data-group'] = $groupId; - - $uri = $title->getLocalURL( array( 'action' => 'edit' ) ); + $uri = TranslateUtils::getEditorUrl( $handle ); $link = Html::element( 'a', - array( 'href' => $uri ), + [ 'href' => $uri ], $this->msg( 'tux-sst-edit' )->text() ); } else { @@ -201,29 +216,29 @@ class SpecialSearchTranslations extends SpecialPage { $domain = $url['host']; $link = Html::element( 'a', - array( 'href' => $document['uri'] ), + [ 'href' => $document['uri'] ], $this->msg( 'tux-sst-view-foreign', $domain )->text() ); } $access = Html::rawElement( 'div', - array( 'class' => 'row tux-edit tux-message-item' ), + [ 'class' => 'row tux-edit tux-message-item' ], $link ); $titleText = $title->getPrefixedText(); - $titleAttribs = array( + $titleAttribs = [ 'class' => 'row tux-title', 'dir' => 'ltr', - ); + ]; $language = Language::factory( $document['language'] ); - $textAttribs = array( + $textAttribs = [ 'class' => 'row tux-text', 'lang' => $language->getHtmlCode(), 'dir' => $language->getDir(), - ); + ]; $resultsHtml = $resultsHtml . Html::openElement( 'div', $resultAttribs ) @@ -233,41 +248,40 @@ class SpecialSearchTranslations extends SpecialPage { . Html::closeElement( 'div' ); } - $resultsHtml .= Html::rawElement( 'hr', array( 'class' => 'tux-pagination-line' ) ); + $resultsHtml .= Html::rawElement( 'hr', [ 'class' => 'tux-pagination-line' ] ); $prev = $next = ''; $offset = $this->opts->getValue( 'offset' ); $params = $this->opts->getChangedValues(); if ( $total - $offset > $this->limit ) { - $newParams = array( 'offset' => $offset + $this->limit ) + $params; - $attribs = array( + $newParams = [ 'offset' => $offset + $this->limit ] + $params; + $attribs = [ 'class' => 'mw-ui-button pager-next', 'href' => $this->getPageTitle()->getLocalURL( $newParams ), - ); + ]; $next = Html::element( 'a', $attribs, $this->msg( 'tux-sst-next' )->text() ); } if ( $offset ) { - $newParams = array( 'offset' => max( 0, $offset - $this->limit ) ) + $params; - $attribs = array( + $newParams = [ 'offset' => max( 0, $offset - $this->limit ) ] + $params; + $attribs = [ 'class' => 'mw-ui-button pager-prev', 'href' => $this->getPageTitle()->getLocalURL( $newParams ), - ); + ]; $prev = Html::element( 'a', $attribs, $this->msg( 'tux-sst-prev' )->text() ); } - $resultsHtml .= Html::rawElement( 'div', array( 'class' => 'tux-pagination-links' ), + $resultsHtml .= Html::rawElement( 'div', [ 'class' => 'tux-pagination-links' ], "$prev $next" ); - $search = $this->getSearchInput( $queryString ); $count = $this->msg( 'tux-sst-count' )->numParams( $total ); $this->showSearch( $search, $count, $facetHtml, $resultsHtml, $total ); } protected function getLanguages( array $facet ) { - $output = array(); + $output = []; $nondefaults = $this->opts->getChangedValues(); $selected = $this->opts->getValue( 'language' ); @@ -289,10 +303,10 @@ class SpecialSearchTranslations extends SpecialPage { $url = $this->getPageTitle()->getLocalURL( $nondefaults ); $value = $this->getLanguage()->formatNum( $value ); - $output[$key] = array( + $output[$key] = [ 'count' => $value, 'url' => $url - ); + ]; } return $output; @@ -304,7 +318,7 @@ class SpecialSearchTranslations extends SpecialPage { } protected function makeGroupFacetRows( array $groups, $counts, $level = 0, $pathString = '' ) { - $output = array(); + $output = []; $nondefaults = $this->opts->getChangedValues(); $selected = $this->opts->getValue( 'group' ); @@ -316,7 +330,7 @@ class SpecialSearchTranslations extends SpecialPage { if ( is_array( $mixed ) ) { $group = array_shift( $subgroups ); } else { - $subgroups = array(); + $subgroups = []; } $id = $group->getId(); @@ -333,13 +347,13 @@ class SpecialSearchTranslations extends SpecialPage { $nondefaults['grouppath'] = $pathString . $id; } - $value = isset( $counts[$id] ) ? $counts[$id] : 0; + $value = $counts[$id] ?? 0; - $output[$id] = array( + $output[$id] = [ 'id' => $id, 'count' => $value, 'label' => $group->getLabel(), - ); + ]; if ( isset( $path[$level] ) && $path[$level] === $id ) { $output[$id]['groups'] = $this->makeGroupFacetRows( @@ -376,14 +390,14 @@ HTML $size = 100; if ( $total > $size && $match !== 'all' && $hasSpace ) { $params = $this->opts->getChangedValues(); - $params = array( 'match' => 'all' ) + $params; + $params = [ 'match' => 'all' ] + $params; $linkText = $this->msg( 'tux-sst-link-all-match' )->text(); $link = $this->getPageTitle()->getFullURL( $params ); $link = "<span class='plainlinks'>[$link $linkText]</span>"; $this->getOutput()->wrapWikiMsg( '<div class="successbox">$1</div>', - array( 'tux-sst-match-message', $link ) + [ 'tux-sst-match-message', $link ] ); } @@ -409,61 +423,85 @@ HTML ); } - // Build ellipsis to select options + protected function showSearchError( $search, Message $message ) { + $messageSelector = $this->messageSelector(); + $this->getOutput()->addHTML( <<<HTML +<div class="grid tux-searchpage"> + <div class="row tux-searchboxform"> + <div class="tux-search-tabs offset-by-three">$messageSelector</div> + <div class="row tux-search-options"> + <div class="offset-by-three nine columns tux-search-inputs"> + <div class="row searchinput">$search</div> + <div class="row errorbox">{$message->escaped()}</div> + </div> + </div> + </div> +</div> +HTML + ); + } + + /** + * Build ellipsis to select options + * @param string $key + * @param string $value + * @return string + */ protected function ellipsisSelector( $key, $value ) { $nondefaults = $this->opts->getChangedValues(); - $taskParams = array( 'filter' => $value ) + $nondefaults; + $taskParams = [ 'filter' => $value ] + $nondefaults; ksort( $taskParams ); $href = $this->getPageTitle()->getLocalURL( $taskParams ); $link = Html::element( 'a', - array( 'href' => $href ), + [ 'href' => $href ], // Messages for grepping: // tux-sst-ellipsis-untranslated // tux-sst-ellipsis-outdated $this->msg( 'tux-sst-ellipsis-' . $key )->text() ); - $container = Html::rawElement( 'li', array( + $container = Html::rawElement( 'li', [ 'class' => 'column', 'data-filter' => $value, 'data-title' => $key, - ), $link ); + ], $link ); return $container; } - /* + /** * Design the tabs + * @return string */ protected function messageSelector() { $nondefaults = $this->opts->getChangedValues(); - $output = Html::openElement( 'div', array( 'class' => 'row tux-messagetable-header' ) ); - $output .= Html::openElement( 'div', array( 'class' => 'nine columns' ) ); - $output .= Html::openElement( 'ul', array( 'class' => 'row tux-message-selector' ) ); - $tabs = array( + $output = Html::openElement( 'div', [ 'class' => 'row tux-messagetable-header' ] ); + $output .= Html::openElement( 'div', [ 'class' => 'nine columns' ] ); + $output .= Html::openElement( 'ul', [ 'class' => 'row tux-message-selector' ] ); + $tabs = [ 'default' => '', 'translated' => 'translated', 'untranslated' => 'untranslated' - ); + ]; - $ellipsisOptions = array( + $ellipsisOptions = [ 'outdated' => 'fuzzy' - ); + ]; $selected = $this->opts->getValue( 'filter' ); $keys = array_keys( $tabs ); if ( in_array( $selected, array_values( $ellipsisOptions ) ) ) { $key = $keys[count( $keys ) - 1]; - $ellipsisOptions = array( $key => $tabs[$key] ); + $ellipsisOptions = [ $key => $tabs[$key] ]; // Remove the last tab unset( $tabs[$key] ); - $tabs = array_merge( $tabs, array( 'outdated' => $selected ) ); + $tabs = array_merge( $tabs, [ 'outdated' => $selected ] ); } elseif ( !in_array( $selected, array_values( $tabs ) ) ) { $selected = ''; } - $container = Html::openElement( 'ul', array( 'class' => 'column tux-message-selector' ) ); + $container = Html::openElement( 'ul', [ 'class' => 'column tux-message-selector' ] ); foreach ( $ellipsisOptions as $optKey => $optValue ) { $container .= $this->ellipsisSelector( $optKey, $optValue ); } @@ -477,19 +515,19 @@ HTML // tux-sst-untranslated // tux-sst-outdated $tabClass = "tux-sst-$tab"; - $taskParams = array( 'filter' => $filter ) + $nondefaults; + $taskParams = [ 'filter' => $filter ] + $nondefaults; ksort( $taskParams ); $href = $this->getPageTitle()->getLocalURL( $taskParams ); if ( $tab === 'default' ) { $link = Html::element( 'a', - array( 'href' => $href ), + [ 'href' => $href ], $this->msg( $tabClass )->text() ); } else { $link = Html::element( 'a', - array( 'href' => $href ), + [ 'href' => $href ], $this->msg( $tabClass, $sourcelanguage )->text() ); } @@ -497,15 +535,15 @@ HTML if ( $selected === $filter ) { $tabClass = $tabClass . ' selected'; } - $output .= Html::rawElement( 'li', array( - 'class' => array( 'column', $tabClass ), + $output .= Html::rawElement( 'li', [ + 'class' => [ 'column', $tabClass ], 'data-filter' => $filter, 'data-title' => $tab, - ), $link ); + ], $link ); } // More column - $output .= Html::openElement( 'li', array( 'class' => 'column more' ) ) . + $output .= Html::openElement( 'li', [ 'class' => 'column more' ] ) . '...' . $container . Html::closeElement( 'li' ); @@ -518,15 +556,18 @@ HTML } protected function getSearchInput( $query ) { - $attribs = array( + $attribs = [ 'placeholder' => $this->msg( 'tux-sst-search-ph' ), - 'class' => 'searchinputbox', + 'class' => 'searchinputbox mw-ui-input', 'dir' => $this->getLanguage()->getDir(), - ); + ]; $title = Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ); $input = Xml::input( 'query', false, $query, $attribs ); - $submit = Xml::submitButton( $this->msg( 'tux-sst-search' ), array( 'class' => 'button' ) ); + $submit = Xml::submitButton( + $this->msg( 'tux-sst-search' ), + [ 'class' => 'mw-ui-button' ] + ); $nondefaults = $this->opts->getChangedValues(); $checkLabel = Xml::checkLabel( @@ -535,14 +576,17 @@ HTML 'tux-case-sensitive', isset( $nondefaults['case'] ) ); - $checkLabel = Html::openElement( 'div', array( 'class' => 'tux-search-operators' ) ) . + $checkLabel = Html::openElement( + 'div', + [ 'class' => 'tux-search-operators mw-ui-checkbox' ] + ) . $checkLabel . Html::closeElement( 'div' ); $lang = $this->getRequest()->getVal( 'language' ); $language = is_null( $lang ) ? '' : Html::hidden( 'language', $lang ); - $form = Html::rawElement( 'form', array( 'action' => wfScript(), 'name' => 'searchform' ), + $form = Html::rawElement( 'form', [ 'action' => wfScript(), 'name' => 'searchform' ], $title . $input . $submit . $checkLabel . $language ); |