kaliop-uk /
ezfindsearchenginebundle
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Kaliop\EzFindSearchEngineBundle\Core\Repository; |
||
| 4 | |||
| 5 | use Closure; |
||
| 6 | use ezfSearchResultInfo; |
||
| 7 | use Psr\Log\LoggerInterface; |
||
| 8 | use eZ\Publish\API\Repository\Values\Content\Search\Facet; |
||
| 9 | use eZ\Publish\API\Repository\SearchService as SearchServiceInterface; |
||
| 10 | use eZ\Publish\API\Repository\ContentService; |
||
| 11 | use eZ\Publish\API\Repository\ContentTypeService; |
||
| 12 | use eZ\Publish\API\Repository\Values\Content\LocationQuery; |
||
| 13 | use eZ\Publish\API\Repository\Values\Content\Query; |
||
| 14 | use eZ\Publish\API\Repository\Values\Content\Query\Criterion; |
||
| 15 | use eZ\Publish\API\Repository\Exceptions\NotFoundException; |
||
| 16 | use eZ\Publish\API\Repository\Exceptions\UnauthorizedException; |
||
| 17 | use eZ\Publish\Core\Base\Exceptions\NotFoundException as CoreNotFoundException; |
||
| 18 | use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException; |
||
| 19 | use Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Content\Query as KaliopQuery; |
||
| 20 | use Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Search\SearchResult as KaliopSearchResult; |
||
| 21 | use Kaliop\EzFindSearchEngineBundle\API\Repository\Values\Search\SearchHit; |
||
| 22 | use Kaliop\EzFindSearchEngineBundle\Core\Base\Exceptions\NotImplementedException; |
||
| 23 | use Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\CriteriaConverter; |
||
| 24 | use Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\SortClauseConverter; |
||
| 25 | use Kaliop\EzFindSearchEngineBundle\Core\Base\Exceptions\eZFindException; |
||
| 26 | use Kaliop\EzFindSearchEngineBundle\Core\Persistence\eZFind\Content\Search\Common\Gateway\FacetConverter; |
||
| 27 | use Kaliop\EzFindSearchEngineBundle\DataCollector\Logger\QueryLogger; |
||
| 28 | |||
| 29 | /// @todo implement LoggerTrait or similar interface |
||
| 30 | class SearchService implements SearchServiceInterface |
||
| 31 | { |
||
| 32 | const DEFAULT_LIMIT = 20; |
||
| 33 | |||
| 34 | const FETCH_ALL = 2147483647; // Max 32-bit signed Integer (limited by SOLR) |
||
| 35 | |||
| 36 | protected $ezFindModule; |
||
| 37 | |||
| 38 | protected $ezFindFunction; |
||
| 39 | |||
| 40 | /** @var Closure */ |
||
| 41 | protected $legacyKernelClosure; |
||
| 42 | |||
| 43 | /** @var ContentService */ |
||
| 44 | protected $contentService; |
||
| 45 | |||
| 46 | /** @var ContentTypeService */ |
||
| 47 | protected $contentTypeService; |
||
| 48 | |||
| 49 | /** @var CriteriaConverter */ |
||
| 50 | protected $filterCriteriaConverter; |
||
| 51 | |||
| 52 | /** @var FacetConverter */ |
||
| 53 | protected $facetConverter; |
||
| 54 | |||
| 55 | /** @var SortClauseConverter */ |
||
| 56 | protected $sortClauseConverter; |
||
| 57 | |||
| 58 | protected $defaultBoostFunctions; |
||
| 59 | |||
| 60 | protected $defaultFieldsToReturn; |
||
| 61 | |||
| 62 | protected $defaultReturnType; |
||
| 63 | |||
| 64 | protected $defaultQueryHandler = 'ezpublish'; |
||
| 65 | |||
| 66 | protected $defaultEnableElevation = true; |
||
| 67 | |||
| 68 | protected $defaultForceElevation = false; |
||
| 69 | |||
| 70 | /** @var bool */ |
||
| 71 | protected $throwErrors; |
||
| 72 | |||
| 73 | /** @var LoggerInterface */ |
||
| 74 | protected $logger; |
||
| 75 | |||
| 76 | /** @var QueryLogger */ |
||
| 77 | protected $queryLogger; |
||
| 78 | |||
| 79 | public function __construct( |
||
| 80 | Closure $legacyKernelClosure, |
||
| 81 | ContentService $contentService, |
||
| 82 | ContentTypeService $contentTypeService, |
||
| 83 | CriteriaConverter $filterCriteriaConverter, |
||
| 84 | FacetConverter $facetConverter, |
||
| 85 | SortClauseConverter $sortClauseConverter, |
||
| 86 | $defaultBoostFunctions, |
||
| 87 | $defaultFieldsToReturn, |
||
| 88 | $defaultReturnType = KaliopQuery::RETURN_CONTENTS, |
||
| 89 | $ezFindModule = 'ezfind', |
||
| 90 | $ezFindFunction = 'search', |
||
| 91 | $throwErrors = true, |
||
| 92 | LoggerInterface $logger = null, |
||
| 93 | QueryLogger $queryLogger = null |
||
| 94 | ) { |
||
| 95 | $this->legacyKernelClosure = $legacyKernelClosure; |
||
| 96 | $this->contentService = $contentService; |
||
| 97 | $this->contentTypeService = $contentTypeService; |
||
| 98 | $this->defaultReturnType = $defaultReturnType; |
||
| 99 | $this->ezFindModule = $ezFindModule; |
||
| 100 | $this->ezFindFunction = $ezFindFunction; |
||
| 101 | $this->throwErrors = $throwErrors; |
||
| 102 | $this->logger = $logger; |
||
| 103 | $this->queryLogger = $queryLogger; |
||
| 104 | |||
| 105 | // Converters |
||
| 106 | $this->filterCriteriaConverter = $filterCriteriaConverter; |
||
| 107 | $this->facetConverter = $facetConverter; |
||
| 108 | $this->sortClauseConverter = $sortClauseConverter; |
||
| 109 | |||
| 110 | // Making sure these are arrays |
||
| 111 | $this->defaultBoostFunctions = (array)$defaultBoostFunctions; |
||
| 112 | $this->defaultFieldsToReturn = (array)$defaultFieldsToReturn; |
||
| 113 | } |
||
| 114 | |||
| 115 | /** |
||
| 116 | * @todo fill in the remaining members: timedOut, spellSuggestion |
||
| 117 | * |
||
| 118 | * @inheritdoc |
||
| 119 | */ |
||
| 120 | public function findContent(Query $query, array $fieldFilters = [], $filterOnUserPermissions = true) |
||
| 121 | { |
||
| 122 | $result = $this->performSearch($query, $fieldFilters, $filterOnUserPermissions); |
||
| 123 | |||
| 124 | $maxScore = null; |
||
| 125 | $time = null; |
||
| 126 | |||
| 127 | // q: is there any case where SearchExtras is not set or of a different type? |
||
| 128 | if (isset($result['SearchExtras']) && $result['SearchExtras'] instanceof ezfSearchResultInfo) { |
||
| 129 | /** @var ezfSearchResultInfo $extras */ |
||
| 130 | $extras = $result['SearchExtras']; |
||
| 131 | $responseHeader = $extras->attribute('responseHeader'); |
||
| 132 | $time = $responseHeader['QTime']; |
||
| 133 | |||
| 134 | // trick to access data from a protected member of ezfSearchResultInfo |
||
| 135 | // @see http://blag.kazeno.net/development/access-private-protected-properties |
||
| 136 | $propGetter = Closure::bind(function($prop){return $this->$prop;}, $extras, $extras); |
||
| 137 | $resultArray = $propGetter('ResultArray'); |
||
| 138 | |||
| 139 | if (isset($resultArray['response']['maxScore'])) { |
||
| 140 | $maxScore = $resultArray['response']['maxScore']; |
||
| 141 | } |
||
| 142 | |||
| 143 | // optimize: remove from SearchExtras 'response' to save memory using the 'Closure::bind' hack |
||
| 144 | /// @todo (!important) make the cutover limit configurable |
||
| 145 | if ($result['SearchCount'] > 100) { |
||
| 146 | $resultsCleaner = Closure::bind(function(){unset($this->ResultArray['response']['docs']);}, $extras, $extras); |
||
| 147 | $resultsCleaner(); |
||
| 148 | } |
||
| 149 | } |
||
| 150 | |||
| 151 | return new KaliopSearchResult( |
||
| 152 | [ |
||
| 153 | 'facets' => $result['Facets'], |
||
| 154 | 'searchHits' => $result['SearchHits'], |
||
| 155 | 'time' => $time, |
||
| 156 | 'maxScore' => $maxScore, |
||
| 157 | 'totalCount' => $result['SearchCount'], |
||
| 158 | 'searchExtras' => $result['SearchExtras'], |
||
| 159 | ] |
||
| 160 | ); |
||
| 161 | } |
||
| 162 | |||
| 163 | /** |
||
| 164 | * @todo Implement this method shrinking the fieldstoreturn to the bare minimum needed to build contentInfo |
||
| 165 | * without having to query the database |
||
| 166 | * @since 5.4.5 |
||
| 167 | */ |
||
| 168 | public function findContentInfo(Query $query, array $languageFilter = [], $filterOnUserPermissions = true) |
||
|
0 ignored issues
–
show
|
|||
| 169 | { |
||
| 170 | throw new NotImplementedException('Intentionally not implemented'); |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * @todo disable asking the total count for speed if possible |
||
| 175 | * |
||
| 176 | * @inheritdoc |
||
| 177 | */ |
||
| 178 | public function findSingle(Criterion $criterion, array $fieldFilters = [], $filterOnUserPermissions = true) |
||
| 179 | { |
||
| 180 | $query = new Query(); |
||
| 181 | $query->criterion = $criterion; |
||
| 182 | $query->limit = 1; |
||
| 183 | $query->offset = 0; |
||
| 184 | |||
| 185 | $result = $this->performSearch($query, $fieldFilters, $filterOnUserPermissions, true); |
||
|
0 ignored issues
–
show
true is of type boolean, but the function expects a null|string.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 186 | |||
| 187 | if (!$result['SearchCount']) { |
||
| 188 | throw new CoreNotFoundException('Content', 'findSingle() found no content for given criterion'); |
||
| 189 | } else { |
||
| 190 | if ($result['SearchCount'] > 1) { |
||
| 191 | throw new InvalidArgumentException( |
||
| 192 | 'totalCount', |
||
| 193 | 'findSingle() found more then one item for given criterion' |
||
| 194 | ); |
||
| 195 | } |
||
| 196 | } |
||
| 197 | |||
| 198 | return reset($result['SearchHits']); |
||
| 199 | } |
||
| 200 | |||
| 201 | public function suggest($prefix, $fieldPaths = [], $limit = 10, Criterion $filter = null) |
||
| 202 | { |
||
| 203 | throw new NotImplementedException('Intentionally not implemented'); |
||
| 204 | } |
||
| 205 | |||
| 206 | public function findLocations(LocationQuery $query, $languageFilter = [], $filterOnUserPermissions = true) |
||
| 207 | { |
||
| 208 | throw new NotImplementedException('Intentionally not implemented'); |
||
| 209 | } |
||
| 210 | |||
| 211 | /** |
||
| 212 | * @return \ezpKernel |
||
| 213 | */ |
||
| 214 | protected function getLegacyKernel() |
||
| 215 | { |
||
| 216 | $legacyKernelClosure = $this->legacyKernelClosure; |
||
| 217 | |||
| 218 | return $legacyKernelClosure(); |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * Perform SOLR search query. |
||
| 223 | * |
||
| 224 | * @param Query $query |
||
| 225 | * @param array $fieldFilters |
||
| 226 | * @param bool $filterOnUserPermissions |
||
| 227 | * @param null|string $forceReturnType When set, it overrides both the service default and the query default |
||
| 228 | * |
||
| 229 | * @return array The same as returned by \eZSolr::Search(), with added members SearchHits and Facets |
||
| 230 | * |
||
| 231 | * @throws eZFindException |
||
| 232 | */ |
||
| 233 | protected function performSearch( |
||
| 234 | Query $query, |
||
| 235 | array $fieldFilters, |
||
| 236 | $filterOnUserPermissions, |
||
| 237 | $forceReturnType = null |
||
| 238 | ) { |
||
| 239 | $returnType = $this->getReturnType($query, $forceReturnType); |
||
| 240 | |||
| 241 | $this->initializeQueryLimit($query); |
||
| 242 | |||
| 243 | $searchParameters = $this->getLegacySearchParameters($query, $fieldFilters, $filterOnUserPermissions, $returnType); |
||
| 244 | //var_dump($searchParameters); |
||
| 245 | /** @var array $searchResult */ |
||
| 246 | $searchResult = $this->getLegacyKernel()->runCallback( |
||
| 247 | function () use ($searchParameters) { |
||
| 248 | return \eZFunctionHandler::execute($this->ezFindModule, $this->ezFindFunction, $searchParameters); |
||
| 249 | }, |
||
| 250 | false |
||
| 251 | ); |
||
| 252 | |||
| 253 | if ($this->queryLogger) { |
||
| 254 | $this->queryLogger->addResultsInfo($searchResult['SearchExtras']); |
||
| 255 | } |
||
| 256 | |||
| 257 | $this->logSearchErrors($searchResult); |
||
| 258 | |||
| 259 | if ($this->throwErrors) { |
||
| 260 | $this->throwIfSearchError($searchResult); |
||
| 261 | } |
||
| 262 | |||
| 263 | $searchResult['SearchHits'] = $this->buildResultObjects($searchResult, $returnType); |
||
| 264 | $searchResult['Facets'] = $this->buildResultFacets($searchResult['SearchExtras'], $query->facetBuilders); |
||
| 265 | |||
| 266 | return $searchResult; |
||
| 267 | } |
||
| 268 | |||
| 269 | /** |
||
| 270 | * Initializes the query limit to ensure it is set. |
||
| 271 | * |
||
| 272 | * @param Query $query |
||
| 273 | */ |
||
| 274 | protected function initializeQueryLimit(Query $query) |
||
| 275 | { |
||
| 276 | if ($query->limit < 0) { |
||
| 277 | $query->limit = self::FETCH_ALL; |
||
| 278 | } elseif ($query->limit === null) { |
||
| 279 | $query->limit = self::DEFAULT_LIMIT; |
||
| 280 | } |
||
| 281 | } |
||
| 282 | |||
| 283 | /** |
||
| 284 | * @see \Solr::search |
||
| 285 | * @see ezfind/modules/ezfind/function_definition.php |
||
| 286 | * @todo should we handle $fieldFilters ? |
||
| 287 | * |
||
| 288 | * @param Query $query |
||
| 289 | * @param array $fieldFilters |
||
| 290 | * @param bool $filterOnUserPermissions |
||
| 291 | * @param string $returnType |
||
| 292 | * @return array |
||
| 293 | */ |
||
| 294 | protected function getLegacySearchParameters(Query $query, array $fieldFilters, $filterOnUserPermissions, $returnType) |
||
|
0 ignored issues
–
show
|
|||
| 295 | { |
||
| 296 | $searchParameters = [ |
||
| 297 | 'offset' => $query->offset, |
||
| 298 | 'limit' => $query->limit, |
||
| 299 | // When we are rebuilding eZ5 objects, no need to load custom fields from Solr. |
||
| 300 | // This 'hack' is the way to get ezfind to generate the minimum field list, plus the score |
||
| 301 | 'fields_to_return' => $returnType == KaliopQuery::RETURN_CONTENTS ? array('meta_score_value:score') : $this->extractLegacyParameter('fields_to_return', $query), |
||
| 302 | // we either load eZ5 objects or return solr data, no need to tell ez4 to load objects as well |
||
| 303 | 'as_objects' => false, //$this->extractLegacyParameter('as_objects', $query), |
||
| 304 | 'query_handler' => $this->extractLegacyParameter('query_handler', $query), |
||
| 305 | 'enable_elevation' => $this->extractLegacyParameter('enable_elevation', $query), |
||
| 306 | 'force_elevation' => $this->extractLegacyParameter('force_elevation', $query), |
||
| 307 | 'boost_functions' => $this->extractLegacyParameter('boost_functions', $query), |
||
| 308 | ]; |
||
| 309 | |||
| 310 | $scoreSort = false; |
||
| 311 | if ($query->sortClauses) { |
||
|
0 ignored issues
–
show
The expression
$query->sortClauses of type eZ\Publish\API\Repositor...tent\Query\SortClause[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
|
|||
| 312 | $searchParameters['sort_by'] = $this->extractSort($query->sortClauses); |
||
| 313 | |||
| 314 | if (array_key_exists('score', $searchParameters['sort_by'])) { |
||
| 315 | $scoreSort = true; |
||
| 316 | } |
||
| 317 | } |
||
| 318 | //var_dump($query->criterion);die(); |
||
| 319 | $criterionFilter = array(); |
||
| 320 | if ($query->criterion) { |
||
| 321 | $criterionFilter = $this->extractFilter($query->criterion); |
||
| 322 | } |
||
| 323 | |||
| 324 | $filterFilter = array(); |
||
| 325 | if ($query->filter) { |
||
| 326 | $filterFilter = $this->extractFilter($query->filter); |
||
| 327 | } |
||
| 328 | |||
| 329 | if ($query->facetBuilders) { |
||
|
0 ignored issues
–
show
The expression
$query->facetBuilders of type eZ\Publish\API\Repositor...nt\Query\FacetBuilder[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
|
|||
| 330 | $searchParameters['facet'] = $this->extractFacet($query->facetBuilders); |
||
| 331 | } |
||
| 332 | |||
| 333 | if ($this->isEzFindCriterion($query->criterion)) { |
||
| 334 | $searchParameters['query'] = reset($criterionFilter); |
||
| 335 | $searchParameters['filter'] = $filterFilter; |
||
| 336 | } elseif ($scoreSort) { |
||
| 337 | // since we are sorting by score, we need to generate the solr query, as that is what is used to calculate score |
||
| 338 | $searchParameters['query'] = $this->filterCriteriaConverter->generateQueryString($criterionFilter); |
||
| 339 | $searchParameters['filter'] = $filterFilter; |
||
| 340 | } else { |
||
| 341 | // since we are not sorting by score, no need to do complex stuff. Only use a solr filter, which should be faster |
||
| 342 | $searchParameters['query'] = ''; |
||
| 343 | $searchParameters['filter'] = array_merge($criterionFilter, $filterFilter); |
||
| 344 | } |
||
| 345 | |||
| 346 | // If we need to filter on permissions, set this to null so eZFind will fill it in. |
||
| 347 | // Otherwise an empty array prevents eZFind from applying limitations |
||
| 348 | if ($filterOnUserPermissions) { |
||
| 349 | $searchParameters['limitation'] = null; |
||
| 350 | } else { |
||
| 351 | $searchParameters['limitation'] = []; |
||
| 352 | } |
||
| 353 | |||
| 354 | return $searchParameters; |
||
| 355 | } |
||
| 356 | |||
| 357 | protected function extractLegacyParameter($paramName, Query $query) |
||
| 358 | { |
||
| 359 | switch ($paramName) { |
||
| 360 | case 'boost_functions': |
||
| 361 | return ($query instanceof KaliopQuery && is_array( |
||
| 362 | $query->boostFunctions |
||
| 363 | )) ? $query->boostFunctions : $this->defaultBoostFunctions; |
||
| 364 | case 'enable_elevation': |
||
| 365 | return ($query instanceof KaliopQuery) ? $query->enableElevation : $this->defaultEnableElevation; |
||
| 366 | case 'fields_to_return': |
||
| 367 | return ($query instanceof KaliopQuery && is_array( |
||
| 368 | $query->fieldsToReturn |
||
| 369 | )) ? $query->fieldsToReturn : $this->defaultFieldsToReturn; |
||
| 370 | case 'force_elevation': |
||
| 371 | return ($query instanceof KaliopQuery) ? $query->forceElevation : $this->defaultForceElevation; |
||
| 372 | case 'query_handler': |
||
| 373 | return ($query instanceof KaliopQuery) ? $query->queryHandler : $this->defaultQueryHandler; |
||
| 374 | } |
||
| 375 | } |
||
| 376 | |||
| 377 | /** |
||
| 378 | * Order of importance: |
||
| 379 | * 1. override (function parameter) |
||
| 380 | * 2. query member (if set) |
||
| 381 | * 3. default for this service |
||
| 382 | * @param Query $query |
||
| 383 | * @param null|string $forceReturnType |
||
| 384 | * @return string |
||
| 385 | */ |
||
| 386 | protected function getReturnType(Query $query, $forceReturnType = null) |
||
| 387 | { |
||
| 388 | if ($forceReturnType !== null) { |
||
| 389 | return $forceReturnType; |
||
| 390 | } |
||
| 391 | |||
| 392 | return ($query instanceof KaliopQuery && $query->returnType !== null) ? $query->returnType : $this->defaultReturnType; |
||
| 393 | } |
||
| 394 | |||
| 395 | /** |
||
| 396 | * Returns true if there is a single search criterion of type EzFindText |
||
| 397 | * @param Query\Criterion|Query\Criterion[] $criteria $criteria |
||
| 398 | * @return bool |
||
| 399 | */ |
||
| 400 | protected function isEzFindCriterion($criteria) |
||
| 401 | { |
||
| 402 | if (!is_array($criteria)) { |
||
| 403 | $criteria = array($criteria); |
||
| 404 | } |
||
| 405 | |||
| 406 | return (count($criteria) == 1 && $criteria[0] instanceof KaliopQuery\Criterion\EzFindText); |
||
| 407 | } |
||
| 408 | |||
| 409 | /** |
||
| 410 | * @param Query\Criterion|Query\Criterion[] $criteria |
||
| 411 | * @return array |
||
| 412 | * @throws NotImplementedException |
||
| 413 | */ |
||
| 414 | protected function extractFilter($criteria) |
||
| 415 | { |
||
| 416 | if (!is_array($criteria)) { |
||
| 417 | $criteria = array($criteria); |
||
| 418 | } |
||
| 419 | |||
| 420 | $result = []; |
||
| 421 | |||
| 422 | foreach ($criteria as $criterion) { |
||
| 423 | $result[] = $this->filterCriteriaConverter->handle($criterion); |
||
| 424 | } |
||
| 425 | |||
| 426 | return $result; |
||
| 427 | } |
||
| 428 | |||
| 429 | /** |
||
| 430 | * Extract FacetBuilders into legacy eZFind facet array. |
||
| 431 | * |
||
| 432 | * @param Query\FacetBuilder[] $facetBuilders |
||
| 433 | * @return array |
||
| 434 | * |
||
| 435 | * @throws NotImplementedException |
||
| 436 | */ |
||
| 437 | protected function extractFacet($facetBuilders) |
||
| 438 | { |
||
| 439 | $facets = []; |
||
| 440 | |||
| 441 | foreach ($facetBuilders as $facetBuilder) { |
||
| 442 | $facets[] = $this->facetConverter->handle($facetBuilder); |
||
| 443 | } |
||
| 444 | |||
| 445 | return $facets; |
||
| 446 | } |
||
| 447 | |||
| 448 | protected function extractSort($sortClauses) |
||
| 449 | { |
||
| 450 | $result = []; |
||
| 451 | |||
| 452 | foreach ($sortClauses as $clause) { |
||
| 453 | $sortClause = $this->sortClauseConverter->handle($clause); |
||
| 454 | if (!empty($sortClause)) { |
||
| 455 | $result = array_merge($result, $sortClause); |
||
| 456 | } |
||
| 457 | } |
||
| 458 | |||
| 459 | return $result; |
||
| 460 | } |
||
| 461 | |||
| 462 | protected function throwIfSearchError($searchResult) |
||
| 463 | { |
||
| 464 | if (!is_array($searchResult)) { |
||
| 465 | throw new eZFindException('The legacy search result is not an array'); |
||
| 466 | } |
||
| 467 | //var_dump($searchResult);die(); |
||
| 468 | if (isset($searchResult['SearchExtras']) && $searchResult['SearchExtras'] instanceof ezfSearchResultInfo) { |
||
| 469 | $errors = $searchResult['SearchExtras']->attribute('error'); |
||
| 470 | /// @todo what if $errors it is an empty string, an array with unexepcted members or not even an array ? |
||
| 471 | if (is_string($errors)) { |
||
| 472 | throw new eZFindException($errors); |
||
| 473 | } elseif (is_array($errors) && isset($errors['msg']) && isset($errors['code'])) { |
||
| 474 | throw new eZFindException($errors['msg'], $errors['code']); |
||
| 475 | } |
||
| 476 | } |
||
| 477 | } |
||
| 478 | |||
| 479 | protected function logSearchErrors($searchResult) |
||
| 480 | { |
||
| 481 | if (!is_array($searchResult)) { |
||
| 482 | if ($this->logger) { |
||
| 483 | $this->logger->error('The legacy search result is not an array'); |
||
| 484 | } |
||
| 485 | |||
| 486 | return; |
||
| 487 | } |
||
| 488 | |||
| 489 | /// @todo allow the query not to return some of these |
||
| 490 | if (!isset($searchResult['SearchResult']) || !isset($searchResult['SearchCount']) || !isset($searchResult['StopWordArray']) || |
||
| 491 | !isset($searchResult['SearchExtras']) || !($searchResult['SearchExtras'] instanceof ezfSearchResultInfo) |
||
| 492 | ) { |
||
| 493 | if ($this->logger) { |
||
| 494 | $this->logger->error('The legacy search result array misses expected members'); |
||
| 495 | } |
||
| 496 | |||
| 497 | return; |
||
| 498 | } |
||
| 499 | |||
| 500 | /** @var ezfSearchResultInfo $searchExtras */ |
||
| 501 | $searchExtras = $searchResult['SearchExtras']; |
||
| 502 | $errors = $searchExtras->attribute('error'); |
||
| 503 | if (!empty($errors) && $this->logger) { |
||
| 504 | $this->logger->error(print_r($errors, true)); |
||
| 505 | } |
||
| 506 | } |
||
| 507 | |||
| 508 | /** |
||
| 509 | * @param array $searchResultsContainer |
||
| 510 | * @param string $returnType |
||
| 511 | * @return SearchHit[]|array depending on $returnObjects |
||
| 512 | */ |
||
| 513 | protected function buildResultObjects($searchResultsContainer, $returnType) |
||
| 514 | { |
||
| 515 | if ($returnType == KaliopQuery::RETURN_CONTENTS || $returnType == KaliopQuery::RETURN_EZFIND_DATA) { |
||
| 516 | $searchResults = $searchResultsContainer['SearchResult']; |
||
| 517 | } else { |
||
| 518 | // we need a little hack to be able to access data in protected members |
||
| 519 | $extras = $searchResultsContainer['SearchExtras']; |
||
| 520 | |||
| 521 | // trick to access data from a protected member of ezfSearchResultInfo |
||
| 522 | // @see http://blag.kazeno.net/development/access-private-protected-properties |
||
| 523 | $propGetter = Closure::bind(function($prop){return $this->$prop;}, $extras, $extras); |
||
| 524 | $resultArray = $propGetter('ResultArray'); |
||
| 525 | $searchResults = $resultArray['response']['docs']; |
||
| 526 | } |
||
| 527 | |||
| 528 | if (!is_array($searchResults)) { |
||
| 529 | return []; |
||
| 530 | } |
||
| 531 | |||
| 532 | $results = array(); |
||
| 533 | |||
| 534 | foreach ($searchResults as $index => $result) { |
||
| 535 | switch($returnType) { |
||
| 536 | |||
| 537 | case KaliopQuery::RETURN_CONTENTS: |
||
| 538 | try { |
||
| 539 | $results[$index] = new SearchHit( |
||
| 540 | [ |
||
| 541 | 'valueObject' => $this->contentService->loadContent($result['id']), |
||
| 542 | 'score' => isset($result['score'])? $result['score'] : null, |
||
| 543 | 'highlight' => isset($result['highlight'])? $result['highlight'] : null, |
||
| 544 | 'elevated' => isset($result['elevated'])? $result['elevated'] : null, |
||
| 545 | /// @todo decide what is the correct value for 'index': guid, installation_id/guid ? |
||
| 546 | //'index' => isset($result['guid'])? $result['guid'] : null, |
||
| 547 | ] |
||
| 548 | ); |
||
| 549 | } catch (NotFoundException $e) { |
||
| 550 | View Code Duplication | if ($this->logger) { |
|
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 551 | // Solr sometimes gets out of sync... make sure users don't see exceptions here |
||
| 552 | $message = sprintf( |
||
| 553 | "Can not access content corresponding to solr record with Content Id: %s, Main Location Id: %s\n%s\n%s", |
||
| 554 | $result['id'], |
||
| 555 | $result['main_node_id'], |
||
| 556 | $e->getMessage(), |
||
| 557 | $e->getTraceAsString() |
||
| 558 | ); |
||
| 559 | |||
| 560 | $this->logger->warning($message); |
||
| 561 | } |
||
| 562 | unset($searchResults[$index]); |
||
| 563 | } catch (UnauthorizedException $e) { |
||
| 564 | /// @todo verify when/if this can happen... |
||
| 565 | View Code Duplication | if ($this->logger) { |
|
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 566 | $message = sprintf( |
||
| 567 | "Can not access content corresponding to solr record with Content Id: %s, Main Location Id: %s\n%s\n%s", |
||
| 568 | $result['id'], |
||
| 569 | $result['main_node_id'], |
||
| 570 | $e->getMessage(), |
||
| 571 | $e->getTraceAsString() |
||
| 572 | ); |
||
| 573 | |||
| 574 | $this->logger->warning($message); |
||
| 575 | } |
||
| 576 | unset($searchResults[$index]); |
||
| 577 | } |
||
| 578 | break; |
||
| 579 | |||
| 580 | case KaliopQuery::RETURN_EZFIND_DATA: |
||
| 581 | case KaliopQuery::RETURN_SOLR_DATA: |
||
| 582 | $results[$index] = new SearchHit( |
||
| 583 | [ |
||
| 584 | 'valueObject' => $result, |
||
| 585 | 'score' => isset($result['score'])? $result['score'] : null, |
||
| 586 | 'highlight' => isset($result['highlight'])? $result['highlight'] : null, |
||
| 587 | 'elevated' => isset($result['elevated'])? $result['elevated'] : null, |
||
| 588 | /// @todo decide what is the correct value for 'index': guid, installation_id/guid ? |
||
| 589 | //'index' => isset($result['guid'])? $result['guid'] : null, |
||
| 590 | ] |
||
| 591 | ); |
||
| 592 | break; |
||
| 593 | } |
||
| 594 | } |
||
| 595 | |||
| 596 | return $results; |
||
| 597 | } |
||
| 598 | |||
| 599 | /** |
||
| 600 | * Create result facets based on SOLR returned results. |
||
| 601 | * |
||
| 602 | * @param ezfSearchResultInfo $searchResultInfo |
||
| 603 | * @param Query\FacetBuilder[] $facetBuilders |
||
| 604 | * |
||
| 605 | * @return Facet[] |
||
| 606 | */ |
||
| 607 | protected function buildResultFacets(ezfSearchResultInfo $searchResultInfo, $facetBuilders) |
||
| 608 | { |
||
| 609 | $facets = []; |
||
| 610 | |||
| 611 | foreach ($facetBuilders as $facetBuilder) { |
||
| 612 | $facets[] = $this->facetConverter->buildFacet( |
||
| 613 | $facetBuilder, |
||
| 614 | $searchResultInfo->attribute('facet_fields'), |
||
| 615 | $searchResultInfo->attribute('facet_queries'), |
||
| 616 | $searchResultInfo->attribute('facet_dates'), |
||
| 617 | $searchResultInfo->attribute('facet_ranges') |
||
| 618 | ); |
||
| 619 | } |
||
| 620 | |||
| 621 | return $facets; |
||
| 622 | } |
||
| 623 | } |
||
| 624 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.