PageRenderTime 69ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Solarium/Query/Select.php

https://github.com/dragos-grosu/solarium
PHP | 634 lines | 264 code | 65 blank | 305 comment | 16 complexity | 6e94650220b85aaef910bb2218aca08b MD5 | raw file
  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. *
  34. * @package Solarium
  35. * @subpackage Query
  36. */
  37. /**
  38. * Select Query
  39. *
  40. * Can be used to select documents and/or facets from Solr. This querytype has
  41. * lots of options and there are many Solarium subclasses for it.
  42. * See the Solr documentation and the relevant Solarium classes for more info.
  43. *
  44. * @package Solarium
  45. * @subpackage Query
  46. */
  47. class Solarium_Query_Select extends Solarium_Query
  48. {
  49. /**
  50. * Solr sort modes
  51. */
  52. const SORT_DESC = 'desc';
  53. const SORT_ASC = 'asc';
  54. /**
  55. * Default options
  56. *
  57. * @var array
  58. */
  59. protected $_options = array(
  60. 'handler' => 'select',
  61. 'resultclass' => 'Solarium_Result_Select',
  62. 'documentclass' => 'Solarium_Document_ReadOnly',
  63. 'query' => '*:*',
  64. 'start' => 0,
  65. 'rows' => 10,
  66. 'fields' => '*,score',
  67. );
  68. /**
  69. * Fields to fetch
  70. *
  71. * @var array
  72. */
  73. protected $_fields = array();
  74. /**
  75. * Fields to sort on
  76. *
  77. * @var array
  78. */
  79. protected $_sortFields = array();
  80. /**
  81. * Filterqueries
  82. *
  83. * @var array
  84. */
  85. protected $_filterQueries = array();
  86. /**
  87. * Facets
  88. *
  89. * @var array
  90. */
  91. protected $_facets = array();
  92. /**
  93. * Initialize options
  94. *
  95. * Several options need some extra checks or setup work, for these options
  96. * the setters are called.
  97. *
  98. * @return void
  99. */
  100. protected function _init()
  101. {
  102. foreach ($this->_options AS $name => $value) {
  103. switch ($name) {
  104. case 'query':
  105. $this->setQuery($value);
  106. break;
  107. case 'filterquery':
  108. $this->addFilterQueries($value);
  109. break;
  110. case 'facet':
  111. $this->addFacets($value);
  112. break;
  113. case 'sort':
  114. $this->addSortFields($value);
  115. break;
  116. case 'fields':
  117. $this->addFields($value);
  118. break;
  119. case 'rows':
  120. $this->setRows((int)$value);
  121. break;
  122. case 'start':
  123. $this->setStart((int)$value);
  124. break;
  125. }
  126. }
  127. }
  128. /**
  129. * Set the query string
  130. *
  131. * Overwrites the current value. You are responsible for the correct
  132. * escaping of user input.
  133. *
  134. * @param string $query
  135. * @return Solarium_Query Provides fluent interface
  136. */
  137. public function setQuery($query)
  138. {
  139. return $this->_setOption('query', trim($query));
  140. }
  141. /**
  142. * Get the query string
  143. *
  144. * @return string
  145. */
  146. public function getQuery()
  147. {
  148. return $this->getOption('query');
  149. }
  150. /**
  151. * Set the start offset
  152. *
  153. * @param integer $start
  154. * @return Solarium_Query Provides fluent interface
  155. */
  156. public function setStart($start)
  157. {
  158. return $this->_setOption('start', $start);
  159. }
  160. /**
  161. * Get the start offset
  162. *
  163. * @return integer
  164. */
  165. public function getStart()
  166. {
  167. return $this->getOption('start');
  168. }
  169. /**
  170. * Set a custom resultclass
  171. *
  172. * @param string $value classname
  173. * @return Solarium_Query Provides fluent interface
  174. */
  175. public function setResultClass($value)
  176. {
  177. return $this->_setOption('resultclass', $value);
  178. }
  179. /**
  180. * Get the current resultclass option
  181. *
  182. * The value is a classname, not an instance
  183. *
  184. * @return string
  185. */
  186. public function getResultClass()
  187. {
  188. return $this->getOption('resultclass');
  189. }
  190. /**
  191. * Set a custom document class
  192. *
  193. * @param string $value classname
  194. * @return Solarium_Query
  195. */
  196. public function setDocumentClass($value)
  197. {
  198. return $this->_setOption('documentclass', $value);
  199. }
  200. /**
  201. * Get the current documentclass option
  202. *
  203. * The value is a classname, not an instance
  204. *
  205. * @return string
  206. */
  207. public function getDocumentClass()
  208. {
  209. return $this->getOption('documentclass');
  210. }
  211. /**
  212. * Set the number of rows to fetch
  213. *
  214. * @param integer $rows
  215. * @return Solarium_Query Provides fluent interface
  216. */
  217. public function setRows($rows)
  218. {
  219. return $this->_setOption('rows', $rows);
  220. }
  221. /**
  222. * Get the number of rows
  223. *
  224. * @return integer
  225. */
  226. public function getRows()
  227. {
  228. return $this->getOption('rows');
  229. }
  230. /**
  231. * Specify a field to return in the resultset
  232. *
  233. * @param string $field
  234. * @return Solarium_Query Provides fluent interface
  235. */
  236. public function addField($field)
  237. {
  238. $this->_fields[$field] = true;
  239. return $this;
  240. }
  241. /**
  242. * Specify multiple fields to return in the resultset
  243. *
  244. * @param string|array $fields can be an array or string with comma
  245. * separated fieldnames
  246. *
  247. * @return Solarium_Query Provides fluent interface
  248. */
  249. public function addFields($fields)
  250. {
  251. if (is_string($fields)) {
  252. $fields = explode(',', $fields);
  253. $fields = array_map('trim', $fields);
  254. }
  255. foreach ($fields AS $field) {
  256. $this->addField($field);
  257. }
  258. return $this;
  259. }
  260. /**
  261. * Remove a field from the field list
  262. *
  263. * @param string $field
  264. * @return Solarium_Query Provides fluent interface
  265. */
  266. public function removeField($field)
  267. {
  268. if (isset($this->_fields[$field])) {
  269. unset($this->_fields[$field]);
  270. }
  271. return $this;
  272. }
  273. /**
  274. * Remove all fields from the field list.
  275. *
  276. * @return Solarium_Query Provides fluent interface
  277. */
  278. public function clearFields()
  279. {
  280. $this->_fields = array();
  281. return $this;
  282. }
  283. /**
  284. * Get the list of fields
  285. *
  286. * @return array
  287. */
  288. public function getFields()
  289. {
  290. return array_keys($this->_fields);
  291. }
  292. /**
  293. * Set multiple fields
  294. *
  295. * This overwrites any existing fields
  296. *
  297. * @param array $fields
  298. * @return Solarium_Query Provides fluent interface
  299. */
  300. public function setFields($fields)
  301. {
  302. $this->clearFields();
  303. $this->addFields($fields);
  304. return $this;
  305. }
  306. /**
  307. * Add a sort field
  308. *
  309. * @param string $field
  310. * @param string $order
  311. * @return Solarium_Query Provides fluent interface
  312. */
  313. public function addSortField($field, $order)
  314. {
  315. $this->_sortFields[$field] = $order;
  316. return $this;
  317. }
  318. /**
  319. * Add multiple sort fields
  320. *
  321. * The input array must contain fieldnames as keys and the order as values.
  322. *
  323. * @param array $sortFields
  324. * @return Solarium_Query Provides fluent interface
  325. */
  326. public function addSortFields(array $sortFields)
  327. {
  328. foreach ($sortFields AS $sortField => $sortOrder) {
  329. $this->addSortField($sortField, $sortOrder);
  330. }
  331. return $this;
  332. }
  333. /**
  334. * Remove a sortfield
  335. *
  336. * @param string $field
  337. * @return Solarium_Query Provides fluent interface
  338. */
  339. public function removeSortField($field)
  340. {
  341. if (isset($this->_sortFields[$field])) {
  342. unset($this->_sortFields[$field]);
  343. }
  344. return $this;
  345. }
  346. /**
  347. * Remove all sortfields
  348. *
  349. * @return Solarium_Query Provides fluent interface
  350. */
  351. public function clearSortFields()
  352. {
  353. $this->_sortFields = array();
  354. return $this;
  355. }
  356. /**
  357. * Get a list of the sortfields
  358. *
  359. * @return array
  360. */
  361. public function getSortFields()
  362. {
  363. return $this->_sortFields;
  364. }
  365. /**
  366. * Set multiple sortfields
  367. *
  368. * This overwrites any existing sortfields
  369. *
  370. * @param array $fields
  371. * @return Solarium_Query Provides fluent interface
  372. */
  373. public function setSortFields($fields)
  374. {
  375. $this->clearSortFields();
  376. $this->addSortFields($fields);
  377. return $this;
  378. }
  379. /**
  380. * Add a filter query
  381. *
  382. * Supports a filterquery instance or a config array, in that case a new
  383. * filterquery instance wil be created based on the options.
  384. *
  385. * @param Solarium_Query_Select_FilterQuery|array $filterQuery
  386. * @return Solarium_Query Provides fluent interface
  387. */
  388. public function addFilterQuery($filterQuery)
  389. {
  390. if (is_array($filterQuery)) {
  391. $filterQuery = new Solarium_Query_Select_FilterQuery($filterQuery);
  392. }
  393. $key = $filterQuery->getKey();
  394. if (0 === strlen($key)) {
  395. throw new Solarium_Exception('A filterquery must have a key value');
  396. }
  397. if (array_key_exists($key, $this->_filterQueries)) {
  398. throw new Solarium_Exception('A filterquery must have a unique key'
  399. . ' value within a query');
  400. }
  401. $this->_filterQueries[$key] = $filterQuery;
  402. return $this;
  403. }
  404. /**
  405. * Add multiple filterqueries
  406. *
  407. * @param array $filterQueries
  408. * @return Solarium_Query Provides fluent interface
  409. */
  410. public function addFilterQueries(array $filterQueries)
  411. {
  412. foreach ($filterQueries AS $filterQuery) {
  413. $this->addFilterQuery($filterQuery);
  414. }
  415. return $this;
  416. }
  417. /**
  418. * Get a filterquery
  419. *
  420. * @param string $key
  421. * @return string
  422. */
  423. public function getFilterQuery($key)
  424. {
  425. if (isset($this->_filterQueries[$key])) {
  426. return $this->_filterQueries[$key];
  427. } else {
  428. return null;
  429. }
  430. }
  431. /**
  432. * Get all filterqueries
  433. *
  434. * @return array
  435. */
  436. public function getFilterQueries()
  437. {
  438. return $this->_filterQueries;
  439. }
  440. /**
  441. * Remove a single filterquery by key
  442. *
  443. * @param string $key
  444. * @return Solarium_Query Provides fluent interface
  445. */
  446. public function removeFilterQuery($key)
  447. {
  448. if (isset($this->_filterQueries[$key])) {
  449. unset($this->_filterQueries[$key]);
  450. }
  451. return $this;
  452. }
  453. /**
  454. * Remove all filterqueries
  455. *
  456. * @return Solarium_Query Provides fluent interface
  457. */
  458. public function clearFilterQueries()
  459. {
  460. $this->_filterQueries = array();
  461. return $this;
  462. }
  463. /**
  464. * Set multiple filterqueries
  465. *
  466. * This overwrites any existing filterqueries
  467. *
  468. * @param array $filterQueries
  469. */
  470. public function setFilterQueries($filterQueries)
  471. {
  472. $this->clearFilterQueries();
  473. $this->addFilterQueries($filterQueries);
  474. }
  475. /**
  476. * Add a facet
  477. *
  478. * @param Solarium_Query_Select_Facet|array $facet
  479. * @return Solarium_Query Provides fluent interface
  480. */
  481. public function addFacet($facet)
  482. {
  483. if (is_array($facet)) {
  484. $className = 'Solarium_Query_Select_Facet_'.ucfirst($facet['type']);
  485. $facet = new $className($facet);
  486. }
  487. $key = $facet->getKey();
  488. if (0 === strlen($key)) {
  489. throw new Solarium_Exception('A facet must have a key value');
  490. }
  491. if (array_key_exists($key, $this->_facets)) {
  492. throw new Solarium_Exception('A facet must have a unique key value'
  493. . ' within a query');
  494. }
  495. $this->_facets[$key] = $facet;
  496. return $this;
  497. }
  498. /**
  499. * Add multiple facets
  500. *
  501. * @param array $facets
  502. * @return Solarium_Query Provides fluent interface
  503. */
  504. public function addFacets(array $facets)
  505. {
  506. foreach ($facets AS $facet) {
  507. $this->addFacet($facet);
  508. }
  509. return $this;
  510. }
  511. /**
  512. * Get a facet
  513. *
  514. * @param string $key
  515. * @return string
  516. */
  517. public function getFacet($key)
  518. {
  519. if (isset($this->_facets[$key])) {
  520. return $this->_facets[$key];
  521. } else {
  522. return null;
  523. }
  524. }
  525. /**
  526. * Get all facets
  527. *
  528. * @return array
  529. */
  530. public function getFacets()
  531. {
  532. return $this->_facets;
  533. }
  534. /**
  535. * Remove a single facet by key
  536. *
  537. * @param string $key
  538. * @return Solarium_Query Provides fluent interface
  539. */
  540. public function removeFacet($key)
  541. {
  542. if (isset($this->_facets[$key])) {
  543. unset($this->_facets[$key]);
  544. }
  545. return $this;
  546. }
  547. /**
  548. * Remove all facets
  549. *
  550. * @return Solarium_Query Provides fluent interface
  551. */
  552. public function clearFacets()
  553. {
  554. $this->_facets = array();
  555. return $this;
  556. }
  557. /**
  558. * Set multiple facets
  559. *
  560. * This overwrites any existing facets
  561. *
  562. * @param array $facets
  563. */
  564. public function setFacets($facets)
  565. {
  566. $this->clearFacets();
  567. $this->addFacets($facets);
  568. }
  569. }