PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Solarium/QueryType/Select/Query/Component/FacetSet.php

http://github.com/basdenooijer/solarium
PHP | 547 lines | 198 code | 57 blank | 292 comment | 18 complexity | c9e389dc00a45ecd25d510eac306994b MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Copyright 2011 Bas de Nooijer. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this listof conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. * The views and conclusions contained in the software and documentation are
  28. * those of the authors and should not be interpreted as representing official
  29. * policies, either expressed or implied, of the copyright holder.
  30. *
  31. * @copyright Copyright 2011 Bas de Nooijer <solarium@raspberry.nl>
  32. * @license http://github.com/basdenooijer/solarium/raw/master/COPYING
  33. * @link http://www.solarium-project.org/
  34. */
  35. /**
  36. * @namespace
  37. */
  38. namespace Solarium\QueryType\Select\Query\Component;
  39. use Solarium\QueryType\Select\Query\Query as SelectQuery;
  40. use Solarium\QueryType\Select\RequestBuilder\Component\FacetSet as RequestBuilder;
  41. use Solarium\QueryType\Select\ResponseParser\Component\FacetSet as ResponseParser;
  42. use Solarium\Exception\InvalidArgumentException;
  43. use Solarium\Exception\OutOfBoundsException;
  44. use Solarium\QueryType\Select\Query\Component\Facet\Facet;
  45. /**
  46. * MoreLikeThis component
  47. *
  48. * @link http://wiki.apache.org/solr/MoreLikeThis
  49. */
  50. class FacetSet extends Component
  51. {
  52. /**
  53. * Facet type field
  54. */
  55. const FACET_FIELD = 'field';
  56. /**
  57. * Facet type query
  58. */
  59. const FACET_QUERY = 'query';
  60. /**
  61. * Facet type multiquery
  62. */
  63. const FACET_MULTIQUERY = 'multiquery';
  64. /**
  65. * Facet type range
  66. */
  67. const FACET_RANGE = 'range';
  68. /**
  69. * Facet type pivot
  70. */
  71. const FACET_PIVOT = 'pivot';
  72. /**
  73. * Facet type interval
  74. */
  75. const FACET_INTERVAL = 'interval';
  76. /**
  77. * Facet type mapping
  78. *
  79. * @var array
  80. */
  81. protected $facetTypes = array(
  82. self::FACET_FIELD => 'Solarium\QueryType\Select\Query\Component\Facet\Field',
  83. self::FACET_QUERY => 'Solarium\QueryType\Select\Query\Component\Facet\Query',
  84. self::FACET_MULTIQUERY => 'Solarium\QueryType\Select\Query\Component\Facet\MultiQuery',
  85. self::FACET_RANGE => 'Solarium\QueryType\Select\Query\Component\Facet\Range',
  86. self::FACET_PIVOT => 'Solarium\QueryType\Select\Query\Component\Facet\Pivot',
  87. self::FACET_INTERVAL => 'Solarium\QueryType\Select\Query\Component\Facet\Interval',
  88. );
  89. /**
  90. * Default options
  91. *
  92. * @var array
  93. */
  94. protected $options = array();
  95. /**
  96. * Facets
  97. *
  98. * @var Facet[]
  99. */
  100. protected $facets = array();
  101. /**
  102. * Get component type
  103. *
  104. * @return string
  105. */
  106. public function getType()
  107. {
  108. return SelectQuery::COMPONENT_FACETSET;
  109. }
  110. /**
  111. * Get a requestbuilder for this query
  112. *
  113. * @return RequestBuilder
  114. */
  115. public function getRequestBuilder()
  116. {
  117. return new RequestBuilder;
  118. }
  119. /**
  120. * Get a response parser for this query
  121. *
  122. * @return ResponseParser
  123. */
  124. public function getResponseParser()
  125. {
  126. return new ResponseParser;
  127. }
  128. /**
  129. * Initialize options
  130. *
  131. * Several options need some extra checks or setup work, for these options
  132. * the setters are called.
  133. *
  134. * @return void
  135. */
  136. protected function init()
  137. {
  138. if (isset($this->options['facet'])) {
  139. foreach ($this->options['facet'] as $key => $config) {
  140. if (!isset($config['key'])) {
  141. $config['key'] = $key;
  142. }
  143. $this->addFacet($config);
  144. }
  145. }
  146. }
  147. /**
  148. * Allow extraction of facets without having to define
  149. * them on the query
  150. *
  151. * @param boolean $extract
  152. * @return self Provides fluent interface
  153. */
  154. public function setExtractFromResponse($extract)
  155. {
  156. return $this->setOption('extractfromresponse', $extract);
  157. }
  158. /**
  159. * Get the extractfromresponse option value
  160. *
  161. * @return boolean
  162. */
  163. public function getExtractFromResponse()
  164. {
  165. return $this->getOption('extractfromresponse');
  166. }
  167. /**
  168. * Limit the terms for faceting by a prefix
  169. *
  170. * This is a global value for all facets in this facetset
  171. *
  172. * @param string $prefix
  173. * @return self Provides fluent interface
  174. */
  175. public function setPrefix($prefix)
  176. {
  177. return $this->setOption('prefix', $prefix);
  178. }
  179. /**
  180. * Get the facet prefix
  181. *
  182. * This is a global value for all facets in this facetset
  183. *
  184. * @return string
  185. */
  186. public function getPrefix()
  187. {
  188. return $this->getOption('prefix');
  189. }
  190. /**
  191. * Set the facet sort order
  192. *
  193. * Use one of the SORT_* constants as the value
  194. *
  195. * This is a global value for all facets in this facetset
  196. *
  197. * @param string $sort
  198. * @return self Provides fluent interface
  199. */
  200. public function setSort($sort)
  201. {
  202. return $this->setOption('sort', $sort);
  203. }
  204. /**
  205. * Get the facet sort order
  206. *
  207. * This is a global value for all facets in this facetset
  208. *
  209. * @return string
  210. */
  211. public function getSort()
  212. {
  213. return $this->getOption('sort');
  214. }
  215. /**
  216. * Set the facet limit
  217. *
  218. * This is a global value for all facets in this facetset
  219. *
  220. * @param int $limit
  221. * @return self Provides fluent interface
  222. */
  223. public function setLimit($limit)
  224. {
  225. return $this->setOption('limit', $limit);
  226. }
  227. /**
  228. * Get the facet limit
  229. *
  230. * This is a global value for all facets in this facetset
  231. *
  232. * @return string
  233. */
  234. public function getLimit()
  235. {
  236. return $this->getOption('limit');
  237. }
  238. /**
  239. * Set the facet mincount
  240. *
  241. * This is a global value for all facets in this facetset
  242. *
  243. * @param int $minCount
  244. * @return self Provides fluent interface
  245. */
  246. public function setMinCount($minCount)
  247. {
  248. return $this->setOption('mincount', $minCount);
  249. }
  250. /**
  251. * Get the facet mincount
  252. *
  253. * This is a global value for all facets in this facetset
  254. *
  255. * @return int
  256. */
  257. public function getMinCount()
  258. {
  259. return $this->getOption('mincount');
  260. }
  261. /**
  262. * Set the missing count option
  263. *
  264. * This is a global value for all facets in this facetset
  265. *
  266. * @param boolean $missing
  267. * @return self Provides fluent interface
  268. */
  269. public function setMissing($missing)
  270. {
  271. return $this->setOption('missing', $missing);
  272. }
  273. /**
  274. * Get the facet missing option
  275. *
  276. * This is a global value for all facets in this facetset
  277. *
  278. * @return boolean
  279. */
  280. public function getMissing()
  281. {
  282. return $this->getOption('missing');
  283. }
  284. /**
  285. * Add a facet
  286. *
  287. * @throws InvalidArgumentException
  288. * @param \Solarium\QueryType\Select\Query\Component\Facet\Facet|array $facet
  289. * @return self Provides fluent interface
  290. */
  291. public function addFacet($facet)
  292. {
  293. if (is_array($facet)) {
  294. $facet = $this->createFacet($facet['type'], $facet, false);
  295. }
  296. $key = $facet->getKey();
  297. if (0 === strlen($key)) {
  298. throw new InvalidArgumentException('A facet must have a key value');
  299. }
  300. //double add calls for the same facet are ignored, but non-unique keys cause an exception
  301. //@todo add trigger_error with a notice for double add calls?
  302. if (array_key_exists($key, $this->facets) && $this->facets[$key] !== $facet) {
  303. throw new InvalidArgumentException('A facet must have a unique key value within a query');
  304. } else {
  305. $this->facets[$key] = $facet;
  306. }
  307. return $this;
  308. }
  309. /**
  310. * Add multiple facets
  311. *
  312. * @param array $facets
  313. * @return self Provides fluent interface
  314. */
  315. public function addFacets(array $facets)
  316. {
  317. foreach ($facets as $key => $facet) {
  318. // in case of a config array: add key to config
  319. if (is_array($facet) && !isset($facet['key'])) {
  320. $facet['key'] = $key;
  321. }
  322. $this->addFacet($facet);
  323. }
  324. return $this;
  325. }
  326. /**
  327. * Get a facet
  328. *
  329. * @param string $key
  330. * @return string
  331. */
  332. public function getFacet($key)
  333. {
  334. if (isset($this->facets[$key])) {
  335. return $this->facets[$key];
  336. } else {
  337. return null;
  338. }
  339. }
  340. /**
  341. * Get all facets
  342. *
  343. * @return Facet[]
  344. */
  345. public function getFacets()
  346. {
  347. return $this->facets;
  348. }
  349. /**
  350. * Remove a single facet
  351. *
  352. * You can remove a facet by passing its key or the facet instance
  353. *
  354. * @param string|\Solarium\QueryType\Select\Query\Component\Facet\Facet $facet
  355. * @return self Provides fluent interface
  356. */
  357. public function removeFacet($facet)
  358. {
  359. if (is_object($facet)) {
  360. $facet = $facet->getKey();
  361. }
  362. if (isset($this->facets[$facet])) {
  363. unset($this->facets[$facet]);
  364. }
  365. return $this;
  366. }
  367. /**
  368. * Remove all facets
  369. *
  370. * @return self Provides fluent interface
  371. */
  372. public function clearFacets()
  373. {
  374. $this->facets = array();
  375. return $this;
  376. }
  377. /**
  378. * Set multiple facets
  379. *
  380. * This overwrites any existing facets
  381. *
  382. * @param array $facets
  383. */
  384. public function setFacets($facets)
  385. {
  386. $this->clearFacets();
  387. $this->addFacets($facets);
  388. }
  389. /**
  390. * Create a facet instance
  391. *
  392. * If you supply a string as the first arguments ($options) it will be used as the key for the facet
  393. * and it will be added to this query.
  394. * If you supply an options array/object that contains a key the facet will also be added to the query.
  395. *
  396. * When no key is supplied the facet cannot be added, in that case you will need to add it manually
  397. * after setting the key, by using the addFacet method.
  398. *
  399. * @throws OutOfBoundsException
  400. * @param string $type
  401. * @param array|object|null $options
  402. * @param boolean $add
  403. * @return \Solarium\QueryType\Select\Query\Component\Facet\Facet
  404. */
  405. public function createFacet($type, $options = null, $add = true)
  406. {
  407. $type = strtolower($type);
  408. if (!isset($this->facetTypes[$type])) {
  409. throw new OutOfBoundsException("Facettype unknown: " . $type);
  410. }
  411. $class = $this->facetTypes[$type];
  412. if (is_string($options)) {
  413. /** @var \Solarium\QueryType\Select\Query\Component\Facet\Facet $facet */
  414. $facet = new $class;
  415. $facet->setKey($options);
  416. } else {
  417. $facet = new $class($options);
  418. }
  419. if ($add && $facet->getKey() !== null) {
  420. $this->addFacet($facet);
  421. }
  422. return $facet;
  423. }
  424. /**
  425. * Get a facet field instance
  426. *
  427. * @param mixed $options
  428. * @param bool $add
  429. * @return \Solarium\QueryType\Select\Query\Component\Facet\Field
  430. */
  431. public function createFacetField($options = null, $add = true)
  432. {
  433. return $this->createFacet(self::FACET_FIELD, $options, $add);
  434. }
  435. /**
  436. * Get a facet query instance
  437. *
  438. * @param mixed $options
  439. * @param bool $add
  440. * @return \Solarium\QueryType\Select\Query\Component\Facet\Query
  441. */
  442. public function createFacetQuery($options = null, $add = true)
  443. {
  444. return $this->createFacet(self::FACET_QUERY, $options, $add);
  445. }
  446. /**
  447. * Get a facet multiquery instance
  448. *
  449. * @param mixed $options
  450. * @param bool $add
  451. * @return \Solarium\QueryType\Select\Query\Component\Facet\MultiQuery
  452. */
  453. public function createFacetMultiQuery($options = null, $add = true)
  454. {
  455. return $this->createFacet(self::FACET_MULTIQUERY, $options, $add);
  456. }
  457. /**
  458. * Get a facet range instance
  459. *
  460. * @param mixed $options
  461. * @param bool $add
  462. * @return \Solarium\QueryType\Select\Query\Component\Facet\Range
  463. */
  464. public function createFacetRange($options = null, $add = true)
  465. {
  466. return $this->createFacet(self::FACET_RANGE, $options, $add);
  467. }
  468. /**
  469. * Get a facet pivot instance
  470. *
  471. * @param mixed $options
  472. * @param bool $add
  473. * @return \Solarium\QueryType\Select\Query\Component\Facet\Pivot
  474. */
  475. public function createFacetPivot($options = null, $add = true)
  476. {
  477. return $this->createFacet(self::FACET_PIVOT, $options, $add);
  478. }
  479. /**
  480. * Get a facet interval instance
  481. *
  482. * @param mixed $options
  483. * @param bool $add
  484. * @return \Solarium\QueryType\Select\Query\Component\Facet\Interval
  485. */
  486. public function createFacetInterval($options = null, $add = true)
  487. {
  488. return $this->createFacet(self::FACET_INTERVAL, $options, $add);
  489. }
  490. }