SpecialSearchTranslations.php

Go to the documentation of this file.
00001 <?php
00016 class SpecialSearchTranslations extends SpecialPage {
00018     protected $opts;
00019 
00027     protected $hl = array();
00028 
00033     protected $limit = 25;
00034 
00035     public function __construct() {
00036         parent::__construct( 'SearchTranslations' );
00037         $this->hl = array(
00038             TranslateUtils::getPlaceholder(),
00039             TranslateUtils::getPlaceholder(),
00040         );
00041     }
00042 
00043     public function setHeaders() {
00044         // Overwritten the parent because it sucks!
00045         // We want to set <title> but not <h1>
00046         $out = $this->getOutput();
00047         $out->setArticleRelated( false );
00048         $out->setRobotPolicy( 'noindex,nofollow' );
00049         $name = $this->msg( 'searchtranslations' );
00050         $name = Sanitizer::stripAllTags( $name );
00051         $out->setHTMLTitle( $this->msg( 'pagetitle' )->rawParams( $name ) );
00052     }
00053 
00054     public function execute( $par ) {
00055         $this->setHeaders();
00056         $this->checkPermissions();
00057 
00058         $server = TTMServer::primary();
00059         if ( !$server instanceof SolrTTMServer ) {
00060             throw new ErrorPageError( 'tux-sst-nosolr-title', 'tux-sst-nosolr-body' );
00061         }
00062 
00063         $out = $this->getOutput();
00064         $out->addModules( 'ext.translate.special.searchtranslations' );
00065 
00066         $this->opts = $opts = new FormOptions();
00067         $opts->add( 'query', '' );
00068         $opts->add( 'language', '' );
00069         $opts->add( 'group', '' );
00070         $opts->add( 'grouppath', '' );
00071 
00072         $opts->fetchValuesFromRequest( $this->getRequest() );
00073 
00074         $queryString = $opts->getValue( 'query' );
00075 
00076         if ( $queryString === '' ) {
00077             $this->showEmptySearch();
00078 
00079             return;
00080         }
00081 
00082         try {
00083             $resultset = $this->doSearch( $server->getSolarium(), $queryString );
00084         } catch ( Solarium_Client_HttpException $e ) {
00085             error_log( 'Translate: Solr search server unavailable' );
00086             throw new ErrorPageError( 'tux-sst-solr-offline-title', 'tux-sst-solr-offline-body' );
00087         }
00088 
00089         // Part 1: facets
00090         $facets = '';
00091 
00092         $facet = $resultset->getFacetSet()->getFacet( 'language' );
00093 
00094         $facets .= Html::element( 'div',
00095             array( 'class' => 'row facet languages',
00096                 'data-facets' => FormatJson::encode( $this->getLanguages( $facet ) ),
00097                 'data-language' => $opts->getValue( 'language' ),
00098             ),
00099             $this->msg( 'tux-sst-facet-language' )
00100         );
00101 
00102         $facet = $resultset->getFacetSet()->getFacet( 'group' );
00103         $facets .= Html::element( 'div',
00104             array( 'class' => 'row facet groups',
00105                 'data-facets' => FormatJson::encode( $this->getGroups( $facet ) ),
00106                 'data-group' => $opts->getValue( 'group' ), ),
00107             $this->msg( 'tux-sst-facet-group' )
00108         );
00109 
00110         // Part 2: results
00111         $results = '';
00112 
00113         $highlighting = $resultset->getHighlighting();
00114         foreach ( $resultset as $document ) {
00115 
00116             $hdoc = $highlighting->getResult( $document->globalid );
00117             $text = $hdoc->getField( 'text' );
00118             if ( $text === array() ) {
00119                 $text = $document->text;
00120                 $text = htmlspecialchars( $text );
00121             } else {
00122                 $text = $text[0];
00123                 $text = htmlspecialchars( $text );
00124 
00125                 list( $pre, $post ) = $this->hl;
00126                 $text = str_replace( $pre, '<strong class="tux-highlight">', $text );
00127                 $text = str_replace( $post, '</strong>', $text );
00128             }
00129 
00130             $title = Title::newFromText( $document->messageid . '/' . $document->language );
00131             if ( !$title ) {
00132                 // Should not ever happen but who knows...
00133                 continue;
00134             }
00135 
00136             $resultAttribs = array(
00137                 'class' => 'row tux-message',
00138                 'data-title' => $title->getPrefixedText(),
00139                 'data-language' => $document->language,
00140             );
00141 
00142             $handle = new MessageHandle( $title );
00143             if ( $handle->isValid() ) {
00144                 $groupId = $handle->getGroup()->getId();
00145                 $helpers = new TranslationHelpers( $title, $groupId );
00146                 $resultAttribs['data-definition'] = $helpers->getDefinition();
00147                 $resultAttribs['data-translation'] = $helpers->getTranslation();
00148                 $resultAttribs['data-group'] = $groupId;
00149             }
00150 
00151             $result = Html::openElement( 'div', $resultAttribs );
00152             $result .= Html::rawElement( 'div', array( 'class' => 'row tux-text' ), $text );
00153             $result .= Html::element(
00154                 'div',
00155                 array( 'class' => 'row tux-title' ),
00156                 $document->messageid
00157             );
00158 
00159             if ( $handle->isValid() ) {
00160                 $uri = wfAppendQuery( $document->uri, array( 'action' => 'edit' ) );
00161                 $link = Html::element( 'a', array(
00162                     'href' => $uri,
00163                 ), $this->msg( 'tux-sst-edit' )->text() );
00164                 $result .= Html::rawElement(
00165                     'div',
00166                     array( 'class' => 'row tux-edit tux-message-item' ),
00167                     $link
00168                 );
00169             }
00170 
00171             $result .= Html::closeElement( 'div' );
00172             $results .= $result;
00173         }
00174 
00175         $prev = $next = '';
00176         $total = $resultset->getNumFound();
00177         $offset = $this->getRequest()->getInt( 'offset' );
00178         $params = $this->getRequest()->getValues();
00179 
00180         if ( $total - $offset > $this->limit ) {
00181             $newParams = array( 'offset' => $offset + $this->limit ) + $params;
00182             $attribs = array(
00183                 'class' => 'pager-next',
00184                 'href' => $this->getTitle()->getLocalUrl( $newParams ),
00185             );
00186             $next = Html::element( 'a', $attribs, $this->msg( 'tux-sst-next' )->text() );
00187         }
00188         if ( $offset ) {
00189             $newParams = array( 'offset' => max( 0, $offset - $this->limit ) ) + $params;
00190             $attribs = array(
00191                 'class' => 'pager-prev',
00192                 'href' => $this->getTitle()->getLocalUrl( $newParams ),
00193             );
00194             $prev = Html::element( 'a', $attribs, $this->msg( 'tux-sst-prev' )->text() );
00195         }
00196 
00197         $results .= Html::rawElement( 'div', array(), "$prev $next" );
00198 
00199         $search = $this->getSearchInput( $queryString );
00200         $count = $this->msg( 'tux-sst-count' )->numParams( $resultset->getNumFound() );
00201 
00202         $this->showSearch( $search, $count, $facets, $results );
00203     }
00204 
00205     protected function doSearch( Solarium_Client $client, $queryString ) {
00206         $query = $client->createSelect();
00207         $dismax = $query->getDisMax();
00208         $dismax->setQueryParser( 'edismax' );
00209         $query->setQuery( $queryString );
00210         $query->setRows( $this->limit );
00211         $query->setStart( $this->getRequest()->getInt( 'offset' ) );
00212 
00213         list( $pre, $post ) = $this->hl;
00214         $hl = $query->getHighlighting();
00215         $hl->setFields( 'text' );
00216         $hl->setSimplePrefix( $pre );
00217         $hl->setSimplePostfix( $post );
00218         $hl->setMaxAnalyzedChars( '5000' );
00219         $hl->setFragSize( '5000' );
00220         $hl->setSnippets( 1 );
00221 
00222         $languageFilter = $this->opts->getValue( 'language' );
00223         if ( $languageFilter !== '' ) {
00224             $query->createFilterQuery( 'languageFilter' )
00225                 ->setQuery( 'language:%P1%', array( $languageFilter ) )
00226                 ->addTag( 'filter' );
00227         }
00228 
00229         $groupFilter = $this->opts->getValue( 'group' );
00230         if ( $groupFilter !== '' ) {
00231             $query->createFilterQuery( 'groupFilter' )
00232                 ->setQuery( 'group:%P1%', array( $groupFilter ) )
00233                 ->addTag( 'filter' );
00234         }
00235 
00236         $facetSet = $query->getFacetSet();
00237 
00238         $language = $facetSet->createFacetField( 'language' );
00239         $language->setField( 'language' );
00240         $language->setMincount( 1 );
00241         $language->addExclude( 'filter' );
00242 
00243         $group = $facetSet->createFacetField( 'group' );
00244         $group->setField( 'group' );
00245         $group->setMincount( 1 );
00246         $group->setMissing( true );
00247         $group->addExclude( 'filter' );
00248 
00249         return $client->select( $query );
00250     }
00251 
00252     protected function getLanguages( Solarium_Result_Select_Facet_Field $facet ) {
00253         $output = array();
00254 
00255         $nondefaults = $this->opts->getChangedValues();
00256         $selected = $this->opts->getValue( 'language' );
00257 
00258         foreach ( $facet as $key => $value ) {
00259             if ( $key === $selected ) {
00260                 unset( $nondefaults['language'] );
00261             } else {
00262                 $nondefaults['language'] = $key;
00263             }
00264 
00265             $url = $this->getTitle()->getLocalUrl( $nondefaults );
00266             $value = $this->getLanguage()->formatNum( $value );
00267 
00268             $output[$key] = array(
00269                 'count' => $value,
00270                 'url' => $url
00271             );
00272         }
00273 
00274         return $output;
00275     }
00276 
00277     protected function getGroups( Solarium_Result_Select_Facet_Field $facet ) {
00278         $structure = MessageGroups::getGroupStructure();
00279         $counts = iterator_to_array( $facet );
00280 
00281         return $this->makeGroupFacetRows( $structure, $counts );
00282     }
00283 
00284     protected function makeGroupFacetRows( array $groups, $counts, $level = 0, $pathString = '' ) {
00285         $output = array();
00286 
00287         $nondefaults = $this->opts->getChangedValues();
00288         $selected = $this->opts->getValue( 'group' );
00289         $path = explode( '|', $this->opts->getValue( 'grouppath' ) );
00290 
00291         foreach ( $groups as $mixed ) {
00292             $subgroups = $group = $mixed;
00293 
00294             if ( is_array( $mixed ) ) {
00295                 $group = array_shift( $subgroups );
00296             } else {
00297                 $subgroups = array();
00298             }
00299 
00300             $id = $group->getId();
00301 
00302             if ( $id !== $selected && !isset( $counts[$id] ) ) {
00303                 continue;
00304             }
00305 
00306             if ( $id === $selected ) {
00307                 unset( $nondefaults['group'] );
00308                 $nondefaults['grouppath'] = $pathString;
00309             } else {
00310                 $nondefaults['group'] = $id;
00311                 $nondefaults['grouppath'] = $pathString . $id;
00312             }
00313 
00314             $url = $this->getTitle()->getLocalUrl( $nondefaults );
00315 
00316             $value = isset( $counts[$id] ) ? $counts[$id] : 0;
00317             $count = $this->getLanguage()->formatNum( $value );
00318 
00319             $output[$id] = array(
00320                 'id' => $id,
00321                 'count' => $count,
00322                 'url' => $url,
00323                 'label' => $group->getLabel(),
00324                 'description' => $group->getDescription(),
00325                 'icon' => TranslateUtils::getIcon( $group, 100 ),
00326             );
00327 
00328             if ( isset( $path[$level] ) && $path[$level] === $id ) {
00329                 $output[$id]['groups'] = $this->makeGroupFacetRows(
00330                     $subgroups,
00331                     $counts,
00332                     $level + 1,
00333                     "$pathString$id|"
00334                 );
00335             }
00336         }
00337 
00338         return $output;
00339     }
00340 
00341     protected function showSearch( $search, $count, $facets, $results ) {
00342         $this->getOutput()->addHtml( <<<HTML
00343 <div class="grid tux-searchpage">
00344     <div class="row searchinput">
00345         <div class="nine columns offset-by-three">$search</div>
00346     </div>
00347     <div class="row count">
00348         <div class="nine columns offset-by-three">$count</div>
00349     </div>
00350     <div class="row searchcontent">
00351         <div class="three columns facets">$facets</div>
00352         <div class="nine columns results">$results</div>
00353     </div>
00354 </div>
00355 HTML
00356         );
00357     }
00358 
00359     protected function showEmptySearch() {
00360         $search = $this->getSearchInput( '' );
00361         $this->getOutput()->addHtml( <<<HTML
00362 <div class="grid tux-searchpage">
00363     <div class="row searchinput">
00364         <div class="nine columns offset-by-three">$search</div>
00365     </div>
00366 </div>
00367 HTML
00368         );
00369     }
00370 
00371     protected function getSearchInput( $query ) {
00372         $attribs = array(
00373             'placeholder' => $this->msg( 'tux-sst-search-ph' ),
00374             'class' => 'searchinputbox',
00375         );
00376 
00377         $title = Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
00378         $input = Xml::input( 'query', false, $query, $attribs );
00379         $submit = Xml::submitButton( $this->msg( 'tux-sst-search' ), array( 'class' => 'button' ) );
00380 
00381         $form = Html::rawElement( 'form', array( 'action' => wfScript() ),
00382             $title . $input . $submit
00383         );
00384 
00385         return $form;
00386     }
00387 }
Generated on Tue Oct 29 00:00:24 2013 for MediaWiki Translate Extension by  doxygen 1.6.3