Search.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <?php
  2. require_once(LIB_PATH . '/lib_date.php');
  3. /**
  4. * Contains a search from the search form.
  5. *
  6. * It allows to extract meaningful bits of the search and store them in a
  7. * convenient object
  8. */
  9. class FreshRSS_Search {
  10. // This contains the user input string
  11. private $raw_input = '';
  12. // The following properties are extracted from the raw input
  13. private $intitle;
  14. private $min_date;
  15. private $max_date;
  16. private $min_pubdate;
  17. private $max_pubdate;
  18. private $inurl;
  19. private $author;
  20. private $tags;
  21. private $search;
  22. public function __construct($input) {
  23. if (strcmp($input, '') == 0) {
  24. return;
  25. }
  26. $this->raw_input = $input;
  27. $input = $this->parseIntitleSearch($input);
  28. $input = $this->parseAuthorSearch($input);
  29. $input = $this->parseInurlSearch($input);
  30. $input = $this->parsePubdateSearch($input);
  31. $input = $this->parseDateSearch($input);
  32. $input = $this->parseTagsSeach($input);
  33. $this->parseSearch($input);
  34. }
  35. public function __toString() {
  36. return $this->getRawInput();
  37. }
  38. public function getRawInput() {
  39. return $this->raw_input;
  40. }
  41. public function getIntitle() {
  42. return $this->intitle;
  43. }
  44. public function getMinDate() {
  45. return $this->min_date;
  46. }
  47. public function getMaxDate() {
  48. return $this->max_date;
  49. }
  50. public function getMinPubdate() {
  51. return $this->min_pubdate;
  52. }
  53. public function getMaxPubdate() {
  54. return $this->max_pubdate;
  55. }
  56. public function getInurl() {
  57. return $this->inurl;
  58. }
  59. public function getAuthor() {
  60. return $this->author;
  61. }
  62. public function getTags() {
  63. return $this->tags;
  64. }
  65. public function getSearch() {
  66. return $this->search;
  67. }
  68. private static function removeEmptyValues($anArray) {
  69. return is_array($anArray) ? array_filter($anArray, function($value) { return $value !== ''; }) : array();
  70. }
  71. /**
  72. * Parse the search string to find intitle keyword and the search related
  73. * to it.
  74. * The search is the first word following the keyword.
  75. *
  76. * @param string $input
  77. * @return string
  78. */
  79. private function parseIntitleSearch($input) {
  80. if (preg_match_all('/intitle:(?P<delim>[\'"])(?P<search>.*)(?P=delim)/U', $input, $matches)) {
  81. $this->intitle = $matches['search'];
  82. $input = str_replace($matches[0], '', $input);
  83. }
  84. if (preg_match_all('/intitle:(?P<search>\w*)/', $input, $matches)) {
  85. $this->intitle = array_merge($this->intitle ? $this->intitle : array(), $matches['search']);
  86. $input = str_replace($matches[0], '', $input);
  87. }
  88. $this->intitle = self::removeEmptyValues($this->intitle);
  89. return $input;
  90. }
  91. /**
  92. * Parse the search string to find author keyword and the search related
  93. * to it.
  94. * The search is the first word following the keyword except when using
  95. * a delimiter. Supported delimiters are single quote (') and double
  96. * quotes (").
  97. *
  98. * @param string $input
  99. * @return string
  100. */
  101. private function parseAuthorSearch($input) {
  102. if (preg_match_all('/author:(?P<delim>[\'"])(?P<search>.*)(?P=delim)/U', $input, $matches)) {
  103. $this->author = $matches['search'];
  104. $input = str_replace($matches[0], '', $input);
  105. }
  106. if (preg_match_all('/author:(?P<search>\w*)/', $input, $matches)) {
  107. $this->author = array_merge($this->author ? $this->author : array(), $matches['search']);
  108. $input = str_replace($matches[0], '', $input);
  109. }
  110. $this->author = self::removeEmptyValues($this->author);
  111. return $input;
  112. }
  113. /**
  114. * Parse the search string to find inurl keyword and the search related
  115. * to it.
  116. * The search is the first word following the keyword.
  117. *
  118. * @param string $input
  119. * @return string
  120. */
  121. private function parseInurlSearch($input) {
  122. if (preg_match_all('/inurl:(?P<search>[^\s]*)/', $input, $matches)) {
  123. $this->inurl = $matches['search'];
  124. $input = str_replace($matches[0], '', $input);
  125. }
  126. $this->inurl = self::removeEmptyValues($this->inurl);
  127. return $input;
  128. }
  129. /**
  130. * Parse the search string to find date keyword and the search related
  131. * to it.
  132. * The search is the first word following the keyword.
  133. *
  134. * @param string $input
  135. * @return string
  136. */
  137. private function parseDateSearch($input) {
  138. if (preg_match_all('/date:(?P<search>[^\s]*)/', $input, $matches)) {
  139. $input = str_replace($matches[0], '', $input);
  140. $dates = self::removeEmptyValues($matches['search']);
  141. if (!empty($dates[0])) {
  142. list($this->min_date, $this->max_date) = parseDateInterval($dates[0]);
  143. }
  144. }
  145. return $input;
  146. }
  147. /**
  148. * Parse the search string to find pubdate keyword and the search related
  149. * to it.
  150. * The search is the first word following the keyword.
  151. *
  152. * @param string $input
  153. * @return string
  154. */
  155. private function parsePubdateSearch($input) {
  156. if (preg_match_all('/pubdate:(?P<search>[^\s]*)/', $input, $matches)) {
  157. $input = str_replace($matches[0], '', $input);
  158. $dates = self::removeEmptyValues($matches['search']);
  159. if (!empty($dates[0])) {
  160. list($this->min_pubdate, $this->max_pubdate) = parseDateInterval($dates[0]);
  161. }
  162. }
  163. return $input;
  164. }
  165. /**
  166. * Parse the search string to find tags keyword (# followed by a word)
  167. * and the search related to it.
  168. * The search is the first word following the #.
  169. *
  170. * @param string $input
  171. * @return string
  172. */
  173. private function parseTagsSeach($input) {
  174. if (preg_match_all('/#(?P<search>[^\s]+)/', $input, $matches)) {
  175. $this->tags = $matches['search'];
  176. $input = str_replace($matches[0], '', $input);
  177. }
  178. $this->tags = self::removeEmptyValues($this->tags);
  179. return $input;
  180. }
  181. /**
  182. * Parse the search string to find search values.
  183. * Every word is a distinct search value, except when using a delimiter.
  184. * Supported delimiters are single quote (') and double quotes (").
  185. *
  186. * @param string $input
  187. * @return string
  188. */
  189. private function parseSearch($input) {
  190. $input = self::cleanSearch($input);
  191. if (strcmp($input, '') == 0) {
  192. return;
  193. }
  194. if (preg_match_all('/(?P<delim>[\'"])(?P<search>.*)(?P=delim)/U', $input, $matches)) {
  195. $this->search = $matches['search'];
  196. $input = str_replace($matches[0], '', $input);
  197. }
  198. $input = self::cleanSearch($input);
  199. if (strcmp($input, '') == 0) {
  200. return;
  201. }
  202. if (is_array($this->search)) {
  203. $this->search = array_merge($this->search, explode(' ', $input));
  204. } else {
  205. $this->search = explode(' ', $input);
  206. }
  207. }
  208. /**
  209. * Remove all unnecessary spaces in the search
  210. *
  211. * @param string $input
  212. * @return string
  213. */
  214. private static function cleanSearch($input) {
  215. $input = preg_replace('/\s+/', ' ', $input);
  216. return trim($input);
  217. }
  218. }