/**
  * Processes incoming search request
  */
 public function readInSearchRequest()
 {
     global $wgCanonicalNamespaceNames, $wgExtraNamespaces, $wgContentNamespaces;
     $this->aOptions['searchStringRaw'] = $this->oSearchRequest->sInput;
     $this->aOptions['searchStringOrig'] = ExtendedSearchBase::preprocessSearchInput($this->oSearchRequest->sInput);
     self::$searchStringRaw = $this->aOptions['searchStringRaw'];
     $sCustomerId = $this->getCustomerId();
     $sLogOp = ' OR ';
     $aFq = array();
     $aBq = array();
     $oRequest = RequestContext::getMain()->getRequest();
     $scope = $oRequest->getVal('search_scope', BsConfig::get('MW::ExtendedSearch::DefScopeUser')) == 'title' ? 'title' : 'text';
     $this->aOptions['scope'] = $scope;
     $vNamespace = $this->checkSearchstringForNamespace($this->aOptions['searchStringRaw'], $this->aOptions['searchStringOrig'], $aFq, BsConfig::get('MW::ExtendedSearch::ShowFacets'));
     $this->aOptions['searchStringWildcarded'] = SearchService::wildcardSearchstring($this->aOptions['searchStringOrig']);
     $this->aOptions['searchStringForStatistics'] = $this->aOptions['searchStringWildcarded'];
     $aSearchTitle = array('title:(' . $this->aOptions['searchStringOrig'] . ')^5', 'titleWord:(' . $this->aOptions['searchStringOrig'] . ')^2', 'titleReverse:(' . $this->aOptions['searchStringWildcarded'] . ')', 'redirects:(' . $this->aOptions['searchStringOrig'] . ')');
     $aSearchText = array('textWord:(' . $this->aOptions['searchStringOrig'] . ')^2', 'textReverse:(' . $this->aOptions['searchStringWildcarded'] . ')', 'sections:(' . $this->aOptions['searchStringOrig'] . ')');
     $sSearchStringTitle = implode($sLogOp, $aSearchTitle);
     $sSearchStringText = implode($sLogOp, $aSearchText);
     $this->aOptions['searchStringFinal'] = $this->aOptions['scope'] === 'title' ? $sSearchStringTitle : $sSearchStringTitle . $sLogOp . $sSearchStringText;
     // filter query
     $aFq[] = 'redirect:0';
     $aFq[] = 'special:0';
     $aFq[] = 'wiki:(' . $sCustomerId . ')';
     // $this->aOptions['namespaces'] HAS TO BE an array with numeric indices of type string!
     $this->aOptions['namespaces'] = $this->oSearchRequest->aNamespaces;
     $aNamespaces = array_slice($wgCanonicalNamespaceNames, 2);
     $aNamespaces = $aNamespaces + $wgExtraNamespaces;
     $bTagNamespace = false;
     if ($vNamespace === false) {
         $this->aOptions['files'] = $this->oSearchRequest->bSearchFiles === true ? true : false;
         $oUser = RequestContext::getMain()->getUser();
         if (!$oUser->getOption('searcheverything')) {
             if (empty($this->aOptions['namespaces']) && $this->oSearchRequest->bNoSelect === false) {
                 $this->aOptions['namespaces'] = array();
                 $aOptions = $oUser->getOptions();
                 foreach ($aOptions as $sOpt => $sValue) {
                     if (strpos($sOpt, 'searchNs') !== false && $sValue == true) {
                         $this->aOptions['namespaces'][] = '' . str_replace('searchNs', '', $sOpt);
                     }
                 }
                 $aAllowedTypes = explode(',', BsConfig::get('MW::ExtendedSearch::IndexFileTypes'));
                 $aAllowedTypes = array_map('trim', $aAllowedTypes);
                 $aSearchFilesFacet = array_intersect($this->oSearchRequest->aType, $aAllowedTypes);
                 if (($this->aOptions['files'] === true || !empty($aSearchFilesFacet)) && $oUser->isAllowed('searchfiles')) {
                     $this->aOptions['namespaces'][] = '999';
                     $this->aOptions['namespaces'][] = '998';
                 }
             } else {
                 $bTagNamespace = true;
                 $aTmp = array();
                 foreach ($this->aOptions['namespaces'] as $iNs) {
                     if (BsNamespaceHelper::checkNamespacePermission($iNs, 'read') === true) {
                         $aTmp[] = $iNs;
                     }
                 }
                 $this->aOptions['namespaces'] = $aTmp;
             }
         } else {
             if (empty($this->aOptions['namespaces'])) {
                 $aTmp = array();
                 foreach ($aNamespaces as $iNs) {
                     if (BsNamespaceHelper::checkNamespacePermission($iNs, 'read') === true) {
                         $this->aOptions['namespaces'][] = $iNs;
                     }
                 }
             } else {
                 $bTagNamespace = true;
                 $aTmp = array();
                 foreach ($this->aOptions['namespaces'] as $iNs) {
                     if (!BsNamespaceHelper::checkNamespacePermission($iNs, 'read')) {
                         $aTmp[] = $iNs;
                     }
                 }
                 if (!empty($aTmp)) {
                     $this->aOptions['namespaces'] = array_diff($this->aOptions['namespaces'], $aTmp);
                 }
             }
         }
     } else {
         $bTagNamespace = true;
         $this->aOptions['namespaces'][] = '' . $vNamespace;
     }
     $this->aOptions['namespaces'] = array_unique($this->aOptions['namespaces']);
     if (!empty($this->aOptions['namespaces'])) {
         $aFqNamespaces = array();
         foreach ($this->aOptions['namespaces'] as $sNamespace) {
             $aFqNamespaces[] = $sNamespace;
             if ($sNamespace == '999') {
                 $filesAlreadyAddedInLoopBefore = true;
             }
         }
         if (!isset($filesAlreadyAddedInLoopBefore) && $this->aOptions['files'] === true && $oUser->isAllowed('searchfiles')) {
             $aFqNamespaces[] = '999';
         }
         $bTagNamespace = true;
         $aFq[] = BsConfig::get('MW::ExtendedSearch::ShowFacets') ? '{!tag=na}namespace:("' . implode('" "', $aFqNamespaces) . '")' : 'namespace:("' . implode('" "', $aFqNamespaces) . '")';
     }
     // $this->aOptions['cats'] = $this->oSearchRequest->sCat; // string, defaults to '' if 'search_cat' not set in REQUEST
     $this->aOptions['cats'] = $this->oSearchRequest->sCategories;
     // array of strings or empty array
     if (!empty($this->aOptions['cats'])) {
         if (isset($this->oSearchRequest->sOperator)) {
             switch ($this->oSearchRequest->sOperator) {
                 case 'AND':
                     $sLogOp = ' AND ';
                     break;
                 default:
             }
         }
         $sFqCategories = BsConfig::get('MW::ExtendedSearch::ShowFacets') ? '{!tag=ca}' : '';
         $sFqCategories .= 'cat:("' . implode('"' . $sLogOp . '"', $this->aOptions['cats']) . '")';
         $aFq[] = $sFqCategories;
     }
     $this->aOptions['type'] = $this->oSearchRequest->aType;
     if (!empty($this->aOptions['type'])) {
         $sFqType = BsConfig::get('MW::ExtendedSearch::ShowFacets') ? '{!tag=ty}' : '';
         $sFqType .= 'type:("' . implode('"' . $sLogOp . '"', $this->aOptions['type']) . '")';
         $aFq[] = $sFqType;
     }
     $this->aOptions['editor'] = $this->oSearchRequest->sEditor;
     if (!empty($this->aOptions['editor'])) {
         // there may be spaces in name of editor. solr analyses those to two
         // terms (editor's names) thus we wrap the name into quotation marks
         // todo: better: in schema.xml define field editor not to be tokenized
         //       at whitespace
         // but: +editor:("Robert V" "Mathias S") is already split correctly!
         $sFqEditor = BsConfig::get('MW::ExtendedSearch::ShowFacets') ? '{!tag=ed}' : '';
         $sFqEditor .= 'editor:("' . implode('"' . $sLogOp . '"', $this->aOptions['editor']) . '")';
         $aFq[] = $sFqEditor;
     }
     // Boost query
     foreach ($wgContentNamespaces as $iNs) {
         $aBq[] = "namespace:{$iNs}^2";
     }
     // We want that files are also seen as a content namespace
     $aBq[] = "namespace:999^2";
     $searchLimit = BsConfig::get('MW::ExtendedSearch::LimitResults');
     $this->aOptions['offset'] = $this->oSearchRequest->iOffset;
     $this->aOptions['order'] = $this->oSearchRequest->sOrder;
     $this->aOptions['asc'] = $this->oSearchRequest->sAsc;
     $this->aOptions['searchLimit'] = $searchLimit == 0 ? 15 : $searchLimit;
     $this->aOptions['titleExists'] = ExtendedSearchBase::titleExists($this->oSearchRequest->sInput, $this->aOptions);
     $this->aOptions['bExtendedForm'] = $this->oSearchRequest->bExtendedForm;
     $this->aSearchOptions['defType'] = 'edismax';
     $this->aSearchOptions['fl'] = 'uid,type,title,path,namespace,cat,ts,redirects,overall_type';
     $this->aSearchOptions['fq'] = $aFq;
     $this->aSearchOptions['sort'] = $this->aOptions['order'] . ' ' . $this->aOptions['asc'];
     $this->aSearchOptions['hl'] = 'on';
     $this->aSearchOptions['hl.fl'] = 'titleWord, titleReverse, sections, textWord, textReverse';
     $this->aSearchOptions['hl.snippets'] = BsConfig::get('MW::ExtendedSearch::HighlightSnippets');
     $this->aSearchOptions['bq'] = implode(' ', $aBq);
     if (BsConfig::get('MW::ExtendedSearch::ShowFacets')) {
         $this->aSearchOptions['facet'] = 'on';
         $this->aSearchOptions['facet.sort'] = 'false';
         $this->aSearchOptions['facet.mincount'] = '1';
         $this->aSearchOptions['facet.missing'] = 'true';
         $this->aSearchOptions['facet.field'] = array();
         $this->aSearchOptions['facet.field'][] = $bTagNamespace === true ? '{!ex=na}namespace' : 'namespace';
         $this->aSearchOptions['facet.field'][] = isset($sFqCategories) ? '{!ex=ca}cat' : 'cat';
         $this->aSearchOptions['facet.field'][] = isset($sFqType) ? '{!ex=ty}type' : 'type';
         $this->aSearchOptions['facet.field'][] = isset($sFqEditor) ? '{!ex=ed}editor' : 'editor';
     }
 }
 /**
  * Creates the facets
  */
 private function createFacets()
 {
     $sSiteUri = $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::MLT);
     // possible orders: count, name, checked
     // possible directions: 1 = desc, -1 = asc
     $aOrder = BsConfig::get('MW::SortAlph') ? array('name' => -1) : array('count' => 1);
     $this->setData('sortorder', $aOrder);
     $aBaseFacets = array('namespace' => array('param' => 'na', 'option' => 'namespaces', 'i18n' => 'bs-extendedsearch-facet-namespace', 'url' => $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::NAMESPACES | SearchUriBuilder::FILES)), 'cat' => array('param' => 'ca', 'option' => 'cats', 'i18n' => 'bs-extendedsearch-facet-category', 'url' => $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::CATS)), 'editor' => array('param' => 'ed', 'option' => 'editor', 'i18n' => 'bs-extendedsearch-facet-editors', 'url' => $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::NAMESPACES | SearchUriBuilder::EDITOR)), 'type' => array('param' => 'ty', 'option' => 'type', 'i18n' => 'bs-extendedsearch-facet-type', 'url' => $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::NAMESPACES | SearchUriBuilder::TYPE)));
     wfRunHooks('BSExtendedSearchBeforeCreateFacets', array(&$aBaseFacets));
     foreach ($aBaseFacets as $sFacet => $aConfig) {
         $oFacet = new ViewSearchFacet();
         if (!is_null($this->oResponse->facet_counts->facet_fields->{$sFacet})) {
             $oFacet->setOption('title', $aConfig['i18n']);
             /* alters to:
              * array(
              *     0 => array( 'checked' => true ),
              *     1 => array( 'count' => 15 ),
              *     999 => array( 'checked' => true, 'count' => 2 )
              * )*/
             $aFacets = array();
             $aData = $this->oSearchOptions->getOption($aConfig['option']);
             if (!empty($aData)) {
                 foreach ($aData as $key => $value) {
                     $aFacets[$value]['checked'] = true;
                 }
                 unset($aData);
             }
             // Get all available facets
             $aFacetsInRespsonse = $this->oResponse->facet_counts->facet_fields->{$sFacet};
             foreach ($aFacetsInRespsonse as $key => $count) {
                 if ($key == '_empty_') {
                     continue;
                 }
                 if ($sFacet === 'namespace') {
                     if (BsNamespaceHelper::checkNamespacePermission($key, 'read') === false || $count == '0') {
                         unset($aFacets[$key]);
                         continue;
                     }
                 } elseif ($sFacet === 'type') {
                     if ($key != 'wiki' && !$this->oContext->getUser()->isAllowed('searchfiles')) {
                         continue;
                     }
                 }
                 $aFacets[$key]['count'] = $count;
             }
             // Prepare available facets. Add some information for each facet
             foreach ($aFacets as $key => $attributes) {
                 if (!isset($aFacets[$key]['count'])) {
                     unset($aFacets[$key]);
                     continue;
                 }
                 if ($sFacet === 'namespace') {
                     if ($key == '999') {
                         $sTitle = wfMessage('bs-extendedsearch-facet-namespace-files')->plain();
                     } elseif ($key == '998') {
                         $sTitle = wfMessage('bs-extendedsearch-facet-namespace-extfiles')->plain();
                     } elseif ($key == '0') {
                         $sTitle = wfMessage('bs-ns_main')->plain();
                     } else {
                         $sTitle = BsNamespaceHelper::getNamespaceName($key, false);
                         if (empty($sTitle)) {
                             unset($aFacets[$key]);
                             continue;
                         }
                     }
                 } elseif ($sFacet === 'cat') {
                     $sTitle = $key == 'notcategorized' ? wfMessage('bs-extendedsearch-facet-uncategorized')->plain() : $key;
                 } elseif ($sFacet === 'editor') {
                     $sTitle = $key === 'unknown' ? wfMessage('bs-extendedsearch-unknown')->plain() : $key;
                 } elseif ($sFacet === 'type') {
                     $sTitle = $key;
                 }
                 $aFacets[$key]['title'] = $this->getFacetTitle($sTitle);
                 $aFacets[$key]['name'] = $this->reduceMaxFacetLength($sTitle);
             }
             uasort($aFacets, array($this, 'compareEntries'));
             $aFacetAll = array();
             foreach ($aFacets as $key => $attributes) {
                 $aDataSet = array();
                 if (isset($attributes['checked'])) {
                     $aDataSet['checked'] = true;
                 }
                 if ($sFacet === 'namespace') {
                     if ($key == '999') {
                         $uri = $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::NAMESPACES | SearchUriBuilder::FILES);
                         $uri .= '&search_files=' . isset($attributes['checked']) ? '0' : '1';
                     } else {
                         $uri = $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::NAMESPACES);
                     }
                 } elseif ($sFacet === 'cat') {
                     $uri = $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::CATS);
                 } elseif ($sFacet === 'editor') {
                     $uri = $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::EDITOR);
                 } elseif ($sFacet === 'type') {
                     $uri = $this->oSearchUriBuilder->buildUri(SearchUriBuilder::ALL, SearchUriBuilder::TYPE);
                 }
                 foreach ($aFacets as $namespaceUrl => $attributesUrl) {
                     $bOwnUrlAndNotAlreadyChecked = $key == $namespaceUrl && !isset($attributesUrl['checked']);
                     $bOtherUrlAndAlreadyChecked = $key != $namespaceUrl && isset($attributesUrl['checked']);
                     if ($bOwnUrlAndNotAlreadyChecked || $bOtherUrlAndAlreadyChecked) {
                         $uri .= "&{$aConfig['param']}[]=" . $namespaceUrl;
                     }
                 }
                 $aDataSet['uri'] = $uri;
                 $aDataSet['diff'] = "{$aConfig['param']}[]=" . $key;
                 $aDataSet['name'] = $attributes['name'];
                 $aDataSet['title'] = $attributes['title'];
                 $aDataSet['count'] = (int) $attributes['count'];
                 $oFacet->setData($aDataSet);
                 $aFacetAll[] = "{$aConfig['param']}[]=" . $key;
             }
             if ($sFacet === 'namespace') {
                 $aReqNs = $this->oSearchOptions->getOption('namespaces');
                 foreach ($aReqNs as $ikey => $value) {
                     if (!array_key_exists($value, $aFacets)) {
                         $aFacetAll[] = "{$aConfig['param']}[]=" . $value;
                         $sSiteUri = str_replace("&{$aConfig['param']}[]={$value}", '', $sSiteUri);
                     }
                 }
             }
             $sFacetAll = implode('&', $aFacetAll);
             $oFacet->setOption('uri-facet-all-diff', $sFacetAll);
         }
         $this->vSearchResult->setFacet($oFacet);
     }
     $this->vSearchResult->setOption('siteUri', $sSiteUri);
 }