PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ThinkCreative/SearchBundle/Services/SearchService.php

https://gitlab.com/contextualcode/symfony-ez5-search-bundle
PHP | 428 lines | 267 code | 69 blank | 92 comment | 40 complexity | a058683fae1ad9160f3fa8931aa55229 MD5 | raw file
  1. <?php
  2. namespace ThinkCreative\SearchBundle\Services;
  3. use ThinkCreative\SearchBundle\Solr\SolrQuery;
  4. use ThinkCreative\SearchBundle\Exception\SearchTypeNotAvailableException;
  5. use ThinkCreative\SearchBundle\Classes\SearchResults;
  6. use eZSolr;
  7. use ThinkCreative\SearchBundle\Classes\ezfeZPSolrQueryBuilder;
  8. /**
  9. * Service for performing SOLR searches
  10. */
  11. class SearchService
  12. {
  13. /**
  14. * Solr configuration
  15. * @var array
  16. */
  17. protected $solrConfig;
  18. /**
  19. * Search configuration
  20. * @var array
  21. */
  22. protected $searchConfig;
  23. /**
  24. * eZ Publish Legacy Kernel
  25. * @var ezLegacyKernel
  26. */
  27. protected $ezLegacyKernel;
  28. /**
  29. * Filter service
  30. * @var object
  31. */
  32. protected $filter;
  33. protected $logger;
  34. /**
  35. * Constructor.
  36. * @param array $solr_config
  37. *
  38. */
  39. public function __construct(array $solr_config, array $search_config, \Closure $ez_legacy_kernel, $logger = null)
  40. {
  41. // set solr config
  42. $this->solrConfig = $solr_config;
  43. // set search config
  44. $this->setSearchConfig($search_config);
  45. $this->ezLegacyKernel = $ez_legacy_kernel;
  46. $this->logger = $logger;
  47. }
  48. /**
  49. * Set search configuration.
  50. * @param array $search_config
  51. */
  52. public function setSearchConfig(array $search_config)
  53. {
  54. $this->searchConfig = $search_config;
  55. }
  56. /**
  57. * Set a filter service to use with search
  58. * queries
  59. * @param object $filter_service
  60. */
  61. public function setFilter($filter_service)
  62. {
  63. $this->filter = $filter_service;
  64. }
  65. /**
  66. * Get array of available sort options
  67. * @param string $search_type
  68. */
  69. public function getSortOptions($search_type = "default")
  70. {
  71. // get search conf for given search type
  72. $searchConfig = null;
  73. foreach ($this->searchConfig as $searchConfig) {
  74. if ($searchConfig['name'] == $search_type) {
  75. break;
  76. }
  77. }
  78. if (!$searchConfig || $searchConfig['name'] != $search_type) {
  79. throw new SearchTypeNotAvailableException("Search type '{$search_type}' was requested but not provided in search configuration.");
  80. }
  81. return $searchConfig['sort'];
  82. }
  83. /**
  84. * Perform a search.
  85. * @param string $search_type
  86. * @param string $query
  87. * @param integer $limit
  88. * @param integer $offset
  89. * @param integer $sort
  90. * @param array $facet_values
  91. * @param array $solr_params Extra parameters for SOLR query
  92. * @return array
  93. */
  94. public function search($search_type = "default", $query, $limit = null, $offset = 0, $sort = "", array $facet_values = array(), $solr_params = array())
  95. {
  96. // get search conf for given search type
  97. $searchConfig = null;
  98. foreach ($this->searchConfig as $searchConfig) {
  99. if ($searchConfig['name'] == $search_type) {
  100. break;
  101. }
  102. }
  103. if (!$searchConfig || $searchConfig['name'] != $search_type) {
  104. throw new SearchTypeNotAvailableException("Search type '{$search_type}' was requested but not provided in search configuration.");
  105. }
  106. // set default sort
  107. if (!$sort && array_key_exists("sort", $searchConfig)) {
  108. $sort = $searchConfig['sort'][0]['value'];
  109. }
  110. // set default limit
  111. if ($limit === null) {
  112. $limit = 10;
  113. if (array_key_exists("limit", $searchConfig)) {
  114. $limit = $searchConfig['limit'];
  115. }
  116. }
  117. // init SolrQuery
  118. $solr = new SolrQuery(
  119. $this->solrConfig['host'],
  120. $this->solrConfig['core'],
  121. $this->solrConfig['port'],
  122. $this->solrConfig['protocol'],
  123. $this->solrConfig['path'],
  124. $this->filter,
  125. $this->logger
  126. );
  127. // set query
  128. $solr->query($query);
  129. // iterate searchConfig and build query
  130. foreach ($searchConfig as $key => $value) {
  131. switch($key) {
  132. // search query
  133. case "query":
  134. $solr->fq($value);
  135. break;
  136. // search query
  137. case "query_handler":
  138. $solr->qt($value);
  139. break;
  140. // search query
  141. case "query_fields":
  142. if( $value === 'all_searchable' ) {
  143. $kernel = $this->ezLegacyKernel;
  144. $value = $kernel()->runCallback(
  145. function()
  146. {
  147. $ezSolr = new eZSolr();
  148. $qBuilder = new ezfeZPSolrQueryBuilder($ezSolr);
  149. return $qBuilder->publicGetClassAttributes();
  150. }
  151. );
  152. $value = implode( ' ', $value );
  153. }
  154. $solr->qf($value);
  155. break;
  156. // highlighting
  157. case "highlighting":
  158. case "highlight":
  159. case "hl":
  160. $solr->highlighting($value);
  161. break;
  162. case "highlight_fields":
  163. $solr->highlightingFields($value);
  164. break;
  165. // facet field
  166. case "facet_fields":
  167. foreach ($value as $facetFieldConfig) {
  168. $facetField = $solr->facetField();
  169. foreach ($facetFieldConfig as $ffKey => $ffValue) {
  170. switch ($ffKey) {
  171. // identifier
  172. case "identifier":
  173. $facetField->identifier($ffValue);
  174. break;
  175. // display name
  176. case "display_name":
  177. case "displayName":
  178. case "displayname":
  179. $facetField->displayName($ffValue);
  180. break;
  181. // field
  182. case "field":
  183. $facetField->field($ffValue);
  184. break;
  185. // operator
  186. case "operator":
  187. $facetField->operator($ffValue);
  188. break;
  189. // basic facet field parameter
  190. default:
  191. if ($facetField->field()) {
  192. $facetField->param("f." . $facetField->field() . ".facet.{$ffKey}", var_export($ffValue, true));
  193. } else {
  194. $facetField->param("facet.{$ffKey}", var_export($ffValue, true));
  195. }
  196. break;
  197. }
  198. }
  199. $facetField->limit(200);
  200. // get facet values
  201. if ($facet_values && array_key_exists($facetField->identifier, $facet_values)) {
  202. $facetValue = $facet_values[$facetField->identifier];
  203. if (gettype($facetValue) != "array") {
  204. $facetValue = array($facetValue);
  205. }
  206. $facetField->values($facetValue);
  207. }
  208. }
  209. break;
  210. // facet range
  211. case "facet_ranges":
  212. foreach ($value as $facetRangeConfig) {
  213. $facetRange = $solr->facetRange();
  214. foreach ($facetRangeConfig as $frKey => $frValue) {
  215. switch ($frKey) {
  216. // identifier
  217. case "identifier":
  218. $facetRange->identifier($frValue);
  219. break;
  220. // display name
  221. case "display_name":
  222. case "displayName":
  223. case "displayname":
  224. $facetRange->displayName($frValue);
  225. break;
  226. // fields
  227. case "fields":
  228. $facetRange->fields($frValue);
  229. break;
  230. // start
  231. case "start":
  232. $facetRange->start($frValue);
  233. break;
  234. // end
  235. case "end":
  236. $facetRange->end($frValue);
  237. break;
  238. // gaps
  239. case "gaps":
  240. case "ranges":
  241. $facetRange->gaps($frValue);
  242. break;
  243. // default, do nothing
  244. default:
  245. break;
  246. }
  247. }
  248. // get facet values
  249. if ($facet_values && array_key_exists($facetRange->identifier, $facet_values)) {
  250. $facetValue = $facet_values[$facetRange->identifier];
  251. if (gettype($facetValue) == "array") {
  252. $facetValue = $facetValue[0];
  253. }
  254. $facetRange->value($facetValue);
  255. }
  256. }
  257. break;
  258. // facet queries
  259. case "facet_queries":
  260. foreach ($value as $facetQueryConfig) {
  261. $facetQuery = $solr->facetQuery();
  262. foreach ($facetQueryConfig as $fqKey => $fqValue) {
  263. switch ($fqKey) {
  264. // identifier
  265. case "identifier":
  266. $facetQuery->identifier($fqValue);
  267. break;
  268. // display name
  269. case "display_name":
  270. case "displayName":
  271. case "displayname":
  272. $facetQuery->displayName($fqValue);
  273. break;
  274. // operator
  275. case "operator":
  276. $facetQuery->operator($fqValue);
  277. break;
  278. // queries
  279. case "queries":
  280. foreach ($fqValue as $fquery) {
  281. if (gettype($fquery) == "string") {
  282. $facetQuery->addQuery($fquery['query']);
  283. } else {
  284. $facetQuery->addQuery(
  285. $fquery['query'],
  286. isset($fquery['identifier']) ? $fquery['identifier'] : "",
  287. isset($fquery['display_name']) ? $fquery['display_name'] : ""
  288. );
  289. }
  290. }
  291. break;
  292. }
  293. }
  294. // get facet values
  295. if ($facet_values && array_key_exists($facetQuery->identifier, $facet_values)) {
  296. $facetValue = $facet_values[$facetQuery->identifier];
  297. if (gettype($facetValue) != "array") {
  298. $facetValue = array($facetValue);
  299. }
  300. $facetQuery->values($facetValue);
  301. }
  302. }
  303. break;
  304. // fl
  305. case "fl":
  306. $solr->param("fl", $value);
  307. break;
  308. // facet query operator
  309. case "facet_query_operator":
  310. $solr->setFacetQueryOperator($value);
  311. break;
  312. // sort
  313. case "sort":
  314. $solr->sort($sort);
  315. break;
  316. // basic parameters
  317. default:
  318. $solr->param($key, $value);
  319. break;
  320. }
  321. }
  322. // offset
  323. if ($offset > 0) {
  324. $solr->offset($offset);
  325. }
  326. // limit
  327. if ($limit > 0) {
  328. $solr->limit($limit);
  329. }
  330. // sort
  331. if ($sort) {
  332. $solr->sort($sort);
  333. }
  334. // set solr_params
  335. foreach ($solr_params as $key=>$value) {
  336. if (!$key || !$value) {
  337. continue;
  338. }
  339. $solr->param($key, $value);
  340. }
  341. // perform search
  342. return new SearchResults(
  343. array_merge(
  344. array(
  345. "params" => array_merge(
  346. $facet_values,
  347. array(
  348. "query" => $query,
  349. "offset" => $offset,
  350. "limit" => $limit,
  351. "sort" => $sort,
  352. )
  353. )
  354. ),
  355. $solr->search()
  356. )
  357. );
  358. }
  359. }