Exemple #1
0
 protected function analyzeScore(array $resultDocument)
 {
     $highScores = array();
     $debugData = $this->search->getDebugResponse()->explain->{$resultDocument['id']};
     /* TODO Provide better parsing
      *
      * parsing could be done line by line,
      * 		* recording indentation level
      * 		* replacing abbreviations
      * 		* replacing phrases like "product of" by mathematical symbols (* or x)
      * 		* ...
      */
     // matches search term weights, ex: 0.42218783 = (MATCH) weight(content:iPod^40.0 in 43), product of:
     $pattern = '/(.*) = \\(MATCH\\) weight\\((.*)\\^/';
     $matches = array();
     preg_match_all($pattern, $debugData, $matches);
     foreach ($matches[0] as $key => $value) {
         // split field from search term
         list($field, $searchTerm) = explode(':', $matches[2][$key]);
         // keep track of highest score per search term
         if (!isset($highScores[$field]) || $highScores[$field]['score'] < $matches[1][$key]) {
             $highScores[$field] = array('score' => $matches[1][$key], 'field' => $field, 'searchTerm' => $searchTerm);
         }
     }
     return $highScores;
 }
Exemple #2
0
 protected function getSortingLinks()
 {
     $sortHelper = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Sorting', $this->configuration['search.']['sorting.']['options.']);
     $query = $this->search->getQuery();
     $queryLinkBuilder = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query\\LinkBuilder', $query);
     $queryLinkBuilder->setLinkTargetPageId($this->parentPlugin->getLinkTargetPageId());
     $sortOptions = array();
     $urlParameters = GeneralUtility::_GP('tx_solr');
     $urlSortParameters = GeneralUtility::trimExplode(',', $urlParameters['sort']);
     $configuredSortOptions = $sortHelper->getSortOptions();
     foreach ($configuredSortOptions as $sortOptionName => $sortOption) {
         $sortDirection = $this->configuration['search.']['sorting.']['defaultOrder'];
         if (!empty($this->configuration['search.']['sorting.']['options.'][$sortOptionName . '.']['defaultOrder'])) {
             $sortDirection = $this->configuration['search.']['sorting.']['options.'][$sortOptionName . '.']['defaultOrder'];
         }
         $sortIndicator = $sortDirection;
         $currentSortOption = '';
         $currentSortDirection = '';
         foreach ($urlSortParameters as $urlSortParameter) {
             $explodedUrlSortParameter = explode(' ', $urlSortParameter);
             if ($explodedUrlSortParameter[0] == $sortOptionName) {
                 list($currentSortOption, $currentSortDirection) = $explodedUrlSortParameter;
                 break;
             }
         }
         // toggle sorting direction for the current sorting field
         if ($currentSortOption == $sortOptionName) {
             switch ($currentSortDirection) {
                 case 'asc':
                     $sortDirection = 'desc';
                     $sortIndicator = 'asc';
                     break;
                 case 'desc':
                     $sortDirection = 'asc';
                     $sortIndicator = 'desc';
                     break;
             }
         }
         if (!empty($this->configuration['search.']['sorting.']['options.'][$sortOptionName . '.']['fixedOrder'])) {
             $sortDirection = $this->configuration['search.']['sorting.']['options.'][$sortOptionName . '.']['fixedOrder'];
         }
         $sortParameter = $sortOptionName . ' ' . $sortDirection;
         $temp = array('link' => $queryLinkBuilder->getQueryLink($sortOption['label'], array('sort' => $sortParameter)), 'url' => $queryLinkBuilder->getQueryUrl(array('sort' => $sortParameter)), 'optionName' => $sortOptionName, 'field' => $sortOption['field'], 'label' => $sortOption['label'], 'is_current' => '0', 'direction' => $sortDirection, 'indicator' => $sortIndicator, 'current_direction' => ' ');
         // set sort indicator for the current sorting field
         if ($currentSortOption == $sortOptionName) {
             $temp['selected'] = 'selected="selected"';
             $temp['current'] = 'current';
             $temp['is_current'] = '1';
             $temp['current_direction'] = $sortIndicator;
         }
         // special case relevance: just reset the search to normal behavior
         if ($sortOptionName == 'relevance') {
             $temp['link'] = $queryLinkBuilder->getQueryLink($sortOption['label'], array('sort' => NULL));
             $temp['url'] = $queryLinkBuilder->getQueryUrl(array('sort' => NULL));
             unset($temp['direction'], $temp['indicator']);
         }
         $sortOptions[] = $temp;
     }
     return $sortOptions;
 }
 /**
  * Resolves the current iteration index (relative) of a loop to the absolute
  * number counting from zero of the total number of results.
  *
  * @param array $arguments
  * @return string
  */
 public function execute(array $arguments = array())
 {
     $numberOfResults = $this->search->getNumberOfResults();
     $currentIterationIndex = $arguments[0];
     $resultsPerPage = $this->search->getResultsPerPage();
     $currentPage = 0;
     $getParameters = GeneralUtility::_GET('tx_solr');
     if (isset($getParameters['page'])) {
         $currentPage = intval($getParameters['page']);
     }
     return $currentPage * $resultsPerPage + $currentIterationIndex;
 }
Exemple #4
0
 /**
  * Modifies the given query and returns the modified query as result
  *
  * @param ResultsCommand $resultCommand The search result command
  * @param array $resultDocument Result document
  * @return array The document with fields as array
  */
 public function modifyResultDocument(ResultsCommand $resultCommand, array $resultDocument)
 {
     $this->search = $resultCommand->getParentPlugin()->getSearchResultSetService()->getSearch();
     // only check whether a BE user is logged in, don't need to check
     // for enabled score analysis as we wouldn't be here if it was disabled
     if ($GLOBALS['TSFE']->beUserLogin) {
         $configuration = Util::getSolrConfiguration();
         $queryFields = $configuration->getSearchQueryQueryFields();
         $debugData = $this->search->getDebugResponse()->explain->{$resultDocument['id']};
         $scoreCalculationService = GeneralUtility::makeInstance(ScoreCalculationService::class);
         $resultDocument['score_analysis'] = $scoreCalculationService->getRenderedScores($debugData, $queryFields);
     }
     return $resultDocument;
 }
Exemple #5
0
 /**
  * Creates the HTML for the relevance output
  *
  * @param array $arguments Array of arguments, [0] is expected to contain the result document.
  * @return string The score as percent value.
  */
 public function execute(array $arguments = array())
 {
     $content = '';
     $document = $arguments[0];
     if (count($arguments) > 1) {
         // a pipe character caused the serialized document to be split up
         $document = implode('|', $arguments);
     }
     if ($this->search->hasSearched() && $this->search->getNumberOfResults()) {
         $score = $this->getScore($document);
         $maximumScore = $this->getMaximumScore($document);
         $content = $this->render($score, $maximumScore);
     }
     return $content;
 }
 /**
  * Modifies the given document and returns the modified document as result.
  *
  * @param ResultsCommand $resultCommand The search result command
  * @param array $resultDocument Result document as array
  * @return array The document with fields as array
  */
 public function modifyResultDocument(ResultsCommand $resultCommand, array $resultDocument)
 {
     $this->search = $resultCommand->getParentPlugin()->getSearchResultSetService()->getSearch();
     $highlightedContent = $this->search->getHighlightedContent();
     foreach ($this->highlightFields as $highlightField) {
         if (!empty($highlightedContent->{$resultDocument['id']}->{$highlightField}[0])) {
             $fragments = array();
             foreach ($highlightedContent->{$resultDocument['id']}->{$highlightField} as $fragment) {
                 $fragments[] = Template::escapeMarkers($fragment);
             }
             $resultDocument[$highlightField] = implode(' ' . $this->fragmentSeparator . ' ', $fragments);
         }
     }
     return $resultDocument;
 }
Exemple #7
0
 /**
  * Creates a link to a given page with a given link text with the current
  * tx_solr parameters appended to the URL
  *
  * @param array Array of arguments, [0] is the link text, [1] is the (optional) page Id to link to (otherwise TSFE->id), [2] are additional URL parameters, [3] use cache, defaults to FALSE
  * @return string complete anchor tag with URL and link text
  */
 public function execute(array $arguments = array())
 {
     $linkText = $arguments[0];
     $pageId = $this->determinePageId(trim($arguments[1]));
     $additionalUrlParameters = $arguments[2] ? $arguments[2] : '';
     $useCache = $arguments[3] ? true : false;
     $returnOnlyUrl = $arguments[4] ? true : false;
     // FIXME pass anything not prefixed with tx_solr in $additionalParameters as 4th parameter
     $additionalUrlParameters = GeneralUtility::explodeUrl2Array($additionalUrlParameters, true);
     $solrUrlParameters = array();
     if (!empty($additionalUrlParameters['tx_solr'])) {
         $solrUrlParameters = $additionalUrlParameters['tx_solr'];
     }
     $linkConfiguration = array('useCacheHash' => $useCache);
     if ($returnOnlyUrl) {
         $linkConfiguration['returnLast'] = 'url';
     }
     if ($this->search->hasSearched()) {
         $query = $this->search->getQuery();
     } else {
         $query = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query', '');
     }
     $linkBuilder = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query\\LinkBuilder', $query);
     $linkBuilder->setLinkTargetPageId($pageId);
     $queryLink = $linkBuilder->getQueryLink($linkText, $solrUrlParameters, $linkConfiguration);
     return $queryLink;
 }
 /**
  * Modifies the given document and returns the modified document as result.
  *
  * @param ResultsCommand $resultCommand The search result command
  * @param array $resultDocument Result document as array
  * @return array The document with fields as array
  */
 public function modifyResultDocument(ResultsCommand $resultCommand, array $resultDocument)
 {
     $this->search = $resultCommand->getParentPlugin()->getSearch();
     $configuration = Util::getSolrConfiguration();
     $highlightedContent = $this->search->getHighlightedContent();
     $highlightFields = GeneralUtility::trimExplode(',', $configuration['search.']['results.']['resultsHighlighting.']['highlightFields'], true);
     foreach ($highlightFields as $highlightField) {
         if (!empty($highlightedContent->{$resultDocument['id']}->{$highlightField}[0])) {
             $fragments = array();
             foreach ($highlightedContent->{$resultDocument['id']}->{$highlightField} as $fragment) {
                 $fragments[] = Template::escapeMarkers($fragment);
             }
             $resultDocument[$highlightField] = implode(' ' . $configuration['search.']['results.']['resultsHighlighting.']['fragmentSeparator'] . ' ', $fragments);
         }
     }
     return $resultDocument;
 }
Exemple #9
0
 /**
  * Query link with a suggested/corrected query
  *
  * @return string Suggestion/spell checked query link
  */
 public function getSuggestionQueryLink()
 {
     $suggestions = $this->getSuggestions();
     $query = clone $this->search->getQuery();
     $query->setKeywords($suggestions['collation']);
     $queryLinkBuilder = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query\\LinkBuilder', $query);
     $queryLinkBuilder->setLinkTargetPageId($GLOBALS['TSFE']->id);
     return $queryLinkBuilder->getQueryLink(htmlspecialchars($query->getKeywordsRaw()));
 }
 /**
  * Retrieves a single document from solr by document id.
  *
  * @param string $documentId
  * @return \ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\SearchResult
  */
 public function getDocumentById($documentId)
 {
     /* @var $query Query */
     $query = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query', $documentId);
     $query->setQueryFieldsFromString('id');
     $response = $this->search->search($query, 0, 1);
     $this->processResponse($documentId, $query, $response);
     $resultDocument = isset($response->response->docs[0]) ? $response->response->docs[0] : null;
     return $resultDocument;
 }
 /**
  * Constructor.
  *
  * @param Facet $facet The facet to render.
  */
 public function __construct(Facet $facet)
 {
     $this->search = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Search');
     $this->facet = $facet;
     $this->facetName = $facet->getName();
     $this->solrConfiguration = Util::getSolrConfiguration();
     $this->facetConfiguration = $this->solrConfiguration['search.']['faceting.']['facets.'][$this->facetName . '.'];
     $this->linkTargetPageId = $GLOBALS['TSFE']->id;
     $this->queryLinkBuilder = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query\\LinkBuilder', $this->search->getQuery());
 }
Exemple #12
0
 /**
  * Generates a link with spell checking suggestions if it is activated and
  * spell checking suggestions are returned by Solr.
  *
  * @return string A link to start over with a new search using the suggested keywords.
  */
 public function getSpellCheckingSuggestions()
 {
     $suggestionsLink = '';
     if ($this->configuration['search.']['spellchecking'] && $this->search->hasSearched()) {
         $suggestions = $this->getSuggestions();
         if ($suggestions && !$suggestions['correctlySpelled'] && !empty($suggestions['collation'])) {
             $suggestionsLink = $GLOBALS['TSFE']->cObj->noTrimWrap($this->getSuggestionQueryLink(), $this->configuration['search.']['spellchecking.']['wrap']);
         }
     }
     return $suggestionsLink;
 }
 /**
  * Queries Solr for the current page's documents.
  *
  * @return array An array of Apache_Solr_Document objects
  */
 protected function getIndexDocuments()
 {
     /* @var Query $query */
     $query = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query', '');
     $query->setQueryType('standard');
     $query->useRawQueryString(true);
     $query->setQueryString('*:*');
     $query->addFilter('(type:pages AND uid:' . $this->pageId . ') OR (*:* AND pid:' . $this->pageId . ' NOT type:pages)');
     $query->addFilter('siteHash:' . Site::getSiteByPageId($this->pageId)->getSiteHash());
     $query->setFieldList('*');
     $query->setSorting('type asc, title asc');
     $this->search->search($query, 0, 10000);
     return $this->search->getResultDocumentsEscaped();
 }
 /**
  * Creates an Apache_Solr_Document from a raw stdClass object as parsed by
  * SolrPhpClient.
  *
  * For compatibility reasons taken from Apache_Solr_Response->_parseData()
  *
  * @param \stdClass $rawDocument The raw document as initially returned by SolrPhpClient
  * @return \Apache_Solr_Document Apache Solr Document
  */
 private function createApacheSolrDocument(\stdClass $rawDocument)
 {
     $collapseSingleValueArrays = $this->search->getSolrConnection()->getCollapseSingleValueArrays();
     $document = new \Apache_Solr_Document();
     foreach ($rawDocument as $key => $value) {
         // If a result is an array with only a single value
         // then its nice to be able to access it
         // as if it were always a single value
         if ($collapseSingleValueArrays && is_array($value) && count($value) <= 1) {
             $value = array_shift($value);
         }
         $document->{$key} = $value;
     }
     return $document;
 }
Exemple #15
0
 /**
  * Gets the facet's options
  *
  * @return array An array with facet options.
  */
 public function getOptionsRaw()
 {
     $facetOptions = array();
     switch ($this->type) {
         case self::TYPE_FIELD:
             $facetOptions = $this->search->getFacetFieldOptions($this->field);
             break;
         case self::TYPE_QUERY:
             $facetOptions = $this->search->getFacetQueryOptions($this->field);
             break;
         case self::TYPE_RANGE:
             $facetOptions = $this->search->getFacetRangeOptions($this->field);
             break;
     }
     return $facetOptions;
 }
Exemple #16
0
 /**
  * Renders facets selected by the user.
  *
  * @return string rendered selected facets subpart
  */
 protected function renderUsedFacets()
 {
     $template = clone $this->parentPlugin->getTemplate();
     $template->workOnSubpart('used_facets');
     $query = $this->search->getQuery();
     $queryLinkBuilder = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query\\LinkBuilder', $this->search->getQuery());
     /* @var $queryLinkBuilder LinkBuilder */
     $queryLinkBuilder->setLinkTargetPageId($this->parentPlugin->getLinkTargetPageId());
     // URL parameters added to facet URLs may not need to be added to the facets reset URL
     $facetLinkUrlParameters = $this->configuration->getSearchFacetingFacetLinkUrlParametersAsArray();
     $useForFacetResetLink = $this->configuration->getSearchFacetingFacetLinkUrlParametersUseForFacetResetLinkUrl();
     if (count($facetLinkUrlParameters) > 0 && $useForFacetResetLink) {
         $addedUrlParameterKeys = array_keys($facetLinkUrlParameters);
         foreach ($addedUrlParameterKeys as $addedUrlParameterKey) {
             if (GeneralUtility::isFirstPartOfStr($addedUrlParameterKey, 'tx_solr')) {
                 $addedUrlParameterKey = substr($addedUrlParameterKey, 8, -1);
                 $queryLinkBuilder->addUnwantedUrlParameter($addedUrlParameterKey);
             }
         }
     }
     $resultParameters = GeneralUtility::_GET('tx_solr');
     $filterParameters = array();
     if (isset($resultParameters['filter'])) {
         $filterParameters = (array) array_map('urldecode', $resultParameters['filter']);
     }
     $facetsInUse = array();
     foreach ($filterParameters as $filter) {
         // only split by the first ":" to allow the use of colons in the filter value
         list($filterName, $filterValue) = explode(':', $filter, 2);
         $facetConfiguration = $this->configuration->getSearchFacetingFacetByName($filterName);
         // don't render facets that should not be included in used facets
         if (isset($facetConfiguration['includeInUsedFacets']) && $facetConfiguration['includeInUsedFacets'] == '0') {
             continue;
         }
         $usedFacetRenderer = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Facet\\UsedFacetRenderer', $filterName, $filterValue, $filter, $this->parentPlugin->getTemplate(), $query);
         $usedFacetRenderer->setLinkTargetPageId($this->parentPlugin->getLinkTargetPageId());
         $facetToRemove = $usedFacetRenderer->render();
         $facetsInUse[] = $facetToRemove;
     }
     $template->addLoop('facets_in_use', 'remove_facet', $facetsInUse);
     $template->addVariable('remove_all_facets', array('url' => $queryLinkBuilder->getQueryUrl(array('filter' => array())), 'text' => '###LLL:faceting_removeAllFilters###'));
     $content = '';
     if (count($facetsInUse)) {
         $content = $template->render();
     }
     return $content;
 }
 /**
  * Performs a search and returns a SearchResultSet.
  *
  * @param SearchRequest $searchRequest
  * @return SearchResultSet
  */
 public function search(SearchRequest $searchRequest)
 {
     /** @var $resultSet SearchResultSet */
     $resultSetClass = $this->getResultSetClassName();
     $resultSet = GeneralUtility::makeInstance($resultSetClass);
     $resultSet->setUsedSearchRequest($searchRequest);
     $this->lastResultSet = $resultSet;
     $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
     if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
         // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
         return $resultSet;
     }
     if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
         // the user entered an empty query string "" or "  " and empty querystring is not allowed
         return $resultSet;
     }
     $rawQuery = $searchRequest->getRawUserQuery();
     $resultsPerPage = $this->getNumberOfResultsPerPage($rawQuery, $searchRequest->getResultsPerPage());
     $query = $this->getPreparedQuery($rawQuery, $resultsPerPage);
     $resultSet->setUsedQuery($query);
     $currentPage = max(0, $searchRequest->getPage());
     // if the number of results per page has been changed by the current request, reset the pagebrowser
     if ($this->resultsPerPageChanged) {
         $currentPage = 0;
     }
     $offSet = $currentPage * $resultsPerPage;
     // performing the actual search, sending the query to the Solr server
     $response = $this->search->search($query, $offSet, null);
     $this->processResponse($rawQuery, $query, $response);
     $resultSet->setResponse($response);
     $resultSet->setUsedPage($currentPage);
     $resultSet->setUsedResultsPerPage($resultsPerPage);
     $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
     $resultSet->setUsedSearch($this->search);
     return $this->handleSearchHook('afterSearch', $resultSet);
 }
Exemple #18
0
 /**
  * Constructor
  *
  * @param array $arguments
  */
 public function __construct(array $arguments = array())
 {
     $this->search = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Search');
     $this->configuration = Util::getSolrConfiguration();
     $this->queryLinkBuilder = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Query\\LinkBuilder', $this->search->getQuery());
 }
Exemple #19
0
 /**
  * Initializes the Solr connection and tests the connection through a ping.
  *
  */
 protected function initializeSearch()
 {
     $solrConnection = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\ConnectionManager')->getConnectionByPageId($GLOBALS['TSFE']->id, $GLOBALS['TSFE']->sys_language_uid, $GLOBALS['TSFE']->MP);
     $this->search = GeneralUtility::makeInstance('ApacheSolrForTypo3\\Solr\\Search', $solrConnection);
     $this->solrAvailable = $this->search->ping();
 }
 /**
  * @param string $expextedQueryString
  * @param int $expectedOffset
  * @param \Apache_Solr_Response $fakeResponse
  */
 public function assertOneSearchWillBeTriggeredWithQueryAndShouldReturnFakeResponse($expextedQueryString, $expectedOffset, \Apache_Solr_Response $fakeResponse)
 {
     $this->searchMock->expects($this->once())->method('search')->with($expextedQueryString, $expectedOffset, null)->will($this->returnValue($fakeResponse));
 }
Exemple #21
0
 /**
  * Determines whether filters have been applied to the query or not.
  *
  * @return string 1 if filters are applied, 0 if not (for use in templates)
  */
 protected function isFiltered()
 {
     $filters = $this->search->getQuery()->getFilters();
     $filtered = !empty($filters);
     return $filtered ? '1' : '0';
 }