PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/framework/vendor/Zend/Search/Lucene/Search/Query/Range.php

https://github.com/Ezku/xi-framework
PHP | 374 lines | 171 code | 50 blank | 153 comment | 48 complexity | 9e4c2aee83cb063ebdc874f0e772af1d MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Search_Lucene
  17. * @subpackage Search
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Range.php 16971 2009-07-22 18:05:45Z mikaelkael $
  21. */
  22. /** Zend_Search_Lucene_Search_Query */
  23. require_once 'Zend/Search/Lucene/Search/Query.php';
  24. /** Zend_Search_Lucene_Search_Query_MultiTerm */
  25. require_once 'Zend/Search/Lucene/Search/Query/MultiTerm.php';
  26. /**
  27. * @category Zend
  28. * @package Zend_Search_Lucene
  29. * @subpackage Search
  30. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_Search_Lucene_Search_Query_Range extends Zend_Search_Lucene_Search_Query
  34. {
  35. /**
  36. * Lower term.
  37. *
  38. * @var Zend_Search_Lucene_Index_Term
  39. */
  40. private $_lowerTerm;
  41. /**
  42. * Upper term.
  43. *
  44. * @var Zend_Search_Lucene_Index_Term
  45. */
  46. private $_upperTerm;
  47. /**
  48. * Search field
  49. *
  50. * @var string
  51. */
  52. private $_field;
  53. /**
  54. * Inclusive
  55. *
  56. * @var boolean
  57. */
  58. private $_inclusive;
  59. /**
  60. * Matched terms.
  61. *
  62. * Matched terms list.
  63. * It's filled during the search (rewrite operation) and may be used for search result
  64. * post-processing
  65. *
  66. * Array of Zend_Search_Lucene_Index_Term objects
  67. *
  68. * @var array
  69. */
  70. private $_matches = null;
  71. /**
  72. * Zend_Search_Lucene_Search_Query_Range constructor.
  73. *
  74. * @param Zend_Search_Lucene_Index_Term|null $lowerTerm
  75. * @param Zend_Search_Lucene_Index_Term|null $upperTerm
  76. * @param boolean $inclusive
  77. * @throws Zend_Search_Lucene_Exception
  78. */
  79. public function __construct($lowerTerm, $upperTerm, $inclusive)
  80. {
  81. if ($lowerTerm === null && $upperTerm === null) {
  82. require_once 'Zend/Search/Lucene/Exception.php';
  83. throw new Zend_Search_Lucene_Exception('At least one term must be non-null');
  84. }
  85. if ($lowerTerm !== null && $upperTerm !== null && $lowerTerm->field != $upperTerm->field) {
  86. require_once 'Zend/Search/Lucene/Exception.php';
  87. throw new Zend_Search_Lucene_Exception('Both terms must be for the same field');
  88. }
  89. $this->_field = ($lowerTerm !== null)? $lowerTerm->field : $upperTerm->field;
  90. $this->_lowerTerm = $lowerTerm;
  91. $this->_upperTerm = $upperTerm;
  92. $this->_inclusive = $inclusive;
  93. }
  94. /**
  95. * Get query field name
  96. *
  97. * @return string|null
  98. */
  99. public function getField()
  100. {
  101. return $this->_field;
  102. }
  103. /**
  104. * Get lower term
  105. *
  106. * @return Zend_Search_Lucene_Index_Term|null
  107. */
  108. public function getLowerTerm()
  109. {
  110. return $this->_lowerTerm;
  111. }
  112. /**
  113. * Get upper term
  114. *
  115. * @return Zend_Search_Lucene_Index_Term|null
  116. */
  117. public function getUpperTerm()
  118. {
  119. return $this->_upperTerm;
  120. }
  121. /**
  122. * Get upper term
  123. *
  124. * @return boolean
  125. */
  126. public function isInclusive()
  127. {
  128. return $this->_inclusive;
  129. }
  130. /**
  131. * Re-write query into primitive queries in the context of specified index
  132. *
  133. * @param Zend_Search_Lucene_Interface $index
  134. * @return Zend_Search_Lucene_Search_Query
  135. */
  136. public function rewrite(Zend_Search_Lucene_Interface $index)
  137. {
  138. $this->_matches = array();
  139. if ($this->_field === null) {
  140. // Search through all fields
  141. $fields = $index->getFieldNames(true /* indexed fields list */);
  142. } else {
  143. $fields = array($this->_field);
  144. }
  145. $maxTerms = Zend_Search_Lucene::getTermsPerQueryLimit();
  146. foreach ($fields as $field) {
  147. $index->resetTermsStream();
  148. if ($this->_lowerTerm !== null) {
  149. $lowerTerm = new Zend_Search_Lucene_Index_Term($this->_lowerTerm->text, $field);
  150. $index->skipTo($lowerTerm);
  151. if (!$this->_inclusive &&
  152. $index->currentTerm() == $lowerTerm) {
  153. // Skip lower term
  154. $index->nextTerm();
  155. }
  156. } else {
  157. $index->skipTo(new Zend_Search_Lucene_Index_Term('', $field));
  158. }
  159. if ($this->_upperTerm !== null) {
  160. // Walk up to the upper term
  161. $upperTerm = new Zend_Search_Lucene_Index_Term($this->_upperTerm->text, $field);
  162. while ($index->currentTerm() !== null &&
  163. $index->currentTerm()->field == $field &&
  164. $index->currentTerm()->text < $upperTerm->text) {
  165. $this->_matches[] = $index->currentTerm();
  166. if ($maxTerms != 0 && count($this->_matches) > $maxTerms) {
  167. require_once 'Zend/Search/Lucene/Exception.php';
  168. throw new Zend_Search_Lucene_Exception('Terms per query limit is reached.');
  169. }
  170. $index->nextTerm();
  171. }
  172. if ($this->_inclusive && $index->currentTerm() == $upperTerm) {
  173. // Include upper term into result
  174. $this->_matches[] = $upperTerm;
  175. }
  176. } else {
  177. // Walk up to the end of field data
  178. while ($index->currentTerm() !== null && $index->currentTerm()->field == $field) {
  179. $this->_matches[] = $index->currentTerm();
  180. if ($maxTerms != 0 && count($this->_matches) > $maxTerms) {
  181. require_once 'Zend/Search/Lucene/Exception.php';
  182. throw new Zend_Search_Lucene_Exception('Terms per query limit is reached.');
  183. }
  184. $index->nextTerm();
  185. }
  186. }
  187. $index->closeTermsStream();
  188. }
  189. if (count($this->_matches) == 0) {
  190. return new Zend_Search_Lucene_Search_Query_Empty();
  191. } else if (count($this->_matches) == 1) {
  192. return new Zend_Search_Lucene_Search_Query_Term(reset($this->_matches));
  193. } else {
  194. $rewrittenQuery = new Zend_Search_Lucene_Search_Query_MultiTerm();
  195. foreach ($this->_matches as $matchedTerm) {
  196. $rewrittenQuery->addTerm($matchedTerm);
  197. }
  198. return $rewrittenQuery;
  199. }
  200. }
  201. /**
  202. * Optimize query in the context of specified index
  203. *
  204. * @param Zend_Search_Lucene_Interface $index
  205. * @return Zend_Search_Lucene_Search_Query
  206. */
  207. public function optimize(Zend_Search_Lucene_Interface $index)
  208. {
  209. require_once 'Zend/Search/Lucene/Exception.php';
  210. throw new Zend_Search_Lucene_Exception('Range query should not be directly used for search. Use $query->rewrite($index)');
  211. }
  212. /**
  213. * Return query terms
  214. *
  215. * @return array
  216. * @throws Zend_Search_Lucene_Exception
  217. */
  218. public function getQueryTerms()
  219. {
  220. if ($this->_matches === null) {
  221. require_once 'Zend/Search/Lucene/Exception.php';
  222. throw new Zend_Search_Lucene_Exception('Search or rewrite operations have to be performed before.');
  223. }
  224. return $this->_matches;
  225. }
  226. /**
  227. * Constructs an appropriate Weight implementation for this query.
  228. *
  229. * @param Zend_Search_Lucene_Interface $reader
  230. * @return Zend_Search_Lucene_Search_Weight
  231. * @throws Zend_Search_Lucene_Exception
  232. */
  233. public function createWeight(Zend_Search_Lucene_Interface $reader)
  234. {
  235. require_once 'Zend/Search/Lucene/Exception.php';
  236. throw new Zend_Search_Lucene_Exception('Range query should not be directly used for search. Use $query->rewrite($index)');
  237. }
  238. /**
  239. * Execute query in context of index reader
  240. * It also initializes necessary internal structures
  241. *
  242. * @param Zend_Search_Lucene_Interface $reader
  243. * @param Zend_Search_Lucene_Index_DocsFilter|null $docsFilter
  244. * @throws Zend_Search_Lucene_Exception
  245. */
  246. public function execute(Zend_Search_Lucene_Interface $reader, $docsFilter = null)
  247. {
  248. require_once 'Zend/Search/Lucene/Exception.php';
  249. throw new Zend_Search_Lucene_Exception('Range query should not be directly used for search. Use $query->rewrite($index)');
  250. }
  251. /**
  252. * Get document ids likely matching the query
  253. *
  254. * It's an array with document ids as keys (performance considerations)
  255. *
  256. * @return array
  257. * @throws Zend_Search_Lucene_Exception
  258. */
  259. public function matchedDocs()
  260. {
  261. require_once 'Zend/Search/Lucene/Exception.php';
  262. throw new Zend_Search_Lucene_Exception('Range query should not be directly used for search. Use $query->rewrite($index)');
  263. }
  264. /**
  265. * Score specified document
  266. *
  267. * @param integer $docId
  268. * @param Zend_Search_Lucene_Interface $reader
  269. * @return float
  270. * @throws Zend_Search_Lucene_Exception
  271. */
  272. public function score($docId, Zend_Search_Lucene_Interface $reader)
  273. {
  274. require_once 'Zend/Search/Lucene/Exception.php';
  275. throw new Zend_Search_Lucene_Exception('Range query should not be directly used for search. Use $query->rewrite($index)');
  276. }
  277. /**
  278. * Query specific matches highlighting
  279. *
  280. * @param Zend_Search_Lucene_Search_Highlighter_Interface $highlighter Highlighter object (also contains doc for highlighting)
  281. */
  282. protected function _highlightMatches(Zend_Search_Lucene_Search_Highlighter_Interface $highlighter)
  283. {
  284. $words = array();
  285. $docBody = $highlighter->getDocument()->getFieldUtf8Value('body');
  286. $tokens = Zend_Search_Lucene_Analysis_Analyzer::getDefault()->tokenize($docBody, 'UTF-8');
  287. $lowerTermText = ($this->_lowerTerm !== null)? $this->_lowerTerm->text : null;
  288. $upperTermText = ($this->_upperTerm !== null)? $this->_upperTerm->text : null;
  289. if ($this->_inclusive) {
  290. foreach ($tokens as $token) {
  291. $termText = $token->getTermText();
  292. if (($lowerTermText == null || $lowerTermText <= $termText) &&
  293. ($upperTermText == null || $termText <= $upperTermText)) {
  294. $words[] = $termText;
  295. }
  296. }
  297. } else {
  298. foreach ($tokens as $token) {
  299. $termText = $token->getTermText();
  300. if (($lowerTermText == null || $lowerTermText < $termText) &&
  301. ($upperTermText == null || $termText < $upperTermText)) {
  302. $words[] = $termText;
  303. }
  304. }
  305. }
  306. $highlighter->highlight($words);
  307. }
  308. /**
  309. * Print a query
  310. *
  311. * @return string
  312. */
  313. public function __toString()
  314. {
  315. // It's used only for query visualisation, so we don't care about characters escaping
  316. return (($this->_field === null)? '' : $this->_field . ':')
  317. . (($this->_inclusive)? '[' : '{')
  318. . (($this->_lowerTerm !== null)? $this->_lowerTerm->text : 'null')
  319. . ' TO '
  320. . (($this->_upperTerm !== null)? $this->_upperTerm->text : 'null')
  321. . (($this->_inclusive)? ']' : '}')
  322. . (($this->getBoost() != 1)? '^' . round($this->getBoost(), 4) : '');
  323. }
  324. }