search_api_test.module 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /**
  3. * Implements hook_menu().
  4. */
  5. function search_api_test_menu() {
  6. return array(
  7. 'search_api_test/insert' => array(
  8. 'title' => 'Insert item',
  9. 'page callback' => 'drupal_get_form',
  10. 'page arguments' => array('search_api_test_insert_item'),
  11. 'access callback' => TRUE,
  12. ),
  13. 'search_api_test/%search_api_test' => array(
  14. 'title' => 'View item',
  15. 'page callback' => 'search_api_test_view',
  16. 'page arguments' => array(1),
  17. 'access callback' => TRUE,
  18. ),
  19. 'search_api_test/query/%search_api_index' => array(
  20. 'title' => 'Search query',
  21. 'page callback' => 'search_api_test_query',
  22. 'page arguments' => array(2),
  23. 'access callback' => TRUE,
  24. ),
  25. );
  26. }
  27. /**
  28. * Form callback for inserting an item.
  29. */
  30. function search_api_test_insert_item(array $form, array &$form_state) {
  31. return array(
  32. 'id' => array(
  33. '#type' => 'textfield',
  34. ),
  35. 'title' => array(
  36. '#type' => 'textfield',
  37. ),
  38. 'body' => array(
  39. '#type' => 'textarea',
  40. ),
  41. 'type' => array(
  42. '#type' => 'textfield',
  43. ),
  44. 'keywords' => array(
  45. '#type' => 'textfield',
  46. ),
  47. 'submit' => array(
  48. '#type' => 'submit',
  49. '#value' => t('Save'),
  50. ),
  51. );
  52. }
  53. /**
  54. * Submit callback for search_api_test_insert_item().
  55. */
  56. function search_api_test_insert_item_submit(array $form, array &$form_state) {
  57. form_state_values_clean($form_state);
  58. db_insert('search_api_test')->fields(array_filter($form_state['values']))->execute();
  59. module_invoke_all('entity_insert', search_api_test_load($form_state['values']['id']), 'search_api_test');
  60. }
  61. /**
  62. * Load handler for search_api_test entities.
  63. */
  64. function search_api_test_load($id) {
  65. $ret = entity_load('search_api_test', array($id));
  66. return $ret ? array_shift($ret) : NULL;
  67. }
  68. /**
  69. * Menu callback for displaying search_api_test entities.
  70. */
  71. function search_api_test_view($entity) {
  72. return array('text' => nl2br(check_plain(print_r($entity, TRUE))));
  73. }
  74. /**
  75. * Menu callback for executing a search.
  76. */
  77. function search_api_test_query(SearchApiIndex $index, $keys = 'foo bar', $offset = 0, $limit = 10, $fields = NULL, $sort = NULL, $filters = NULL) {
  78. $query = $index->query()
  79. ->keys($keys ? $keys : NULL)
  80. ->range($offset, $limit);
  81. if ($fields) {
  82. $query->fields(explode(',', $fields));
  83. }
  84. if ($sort) {
  85. $sort = explode(',', $sort);
  86. $query->sort($sort[0], $sort[1]);
  87. }
  88. else {
  89. $query->sort('search_api_id', 'ASC');
  90. }
  91. if ($filters) {
  92. $filters = explode(',', $filters);
  93. foreach ($filters as $filter) {
  94. $filter = explode('=', $filter);
  95. $query->condition($filter[0], $filter[1]);
  96. }
  97. }
  98. $result = $query->execute();
  99. $ret = '';
  100. $ret .= 'result count = ' . (int) $result['result count'] . '<br/>';
  101. $ret .= 'results = (' . (empty($result['results']) ? '' : implode(', ', array_keys($result['results']))) . ')<br/>';
  102. $ret .= 'warnings = (' . (empty($result['warnings']) ? '' : '"' . implode('", "', $result['warnings']) . '"') . ')<br/>';
  103. $ret .= 'ignored = (' . (empty($result['ignored']) ? '' : implode(', ', $result['ignored'])) . ')<br/>';
  104. $ret .= nl2br(check_plain(print_r($result['performance'], TRUE)));
  105. return $ret;
  106. }
  107. /**
  108. * Implements hook_entity_info().
  109. */
  110. function search_api_test_entity_info() {
  111. return array(
  112. 'search_api_test' => array(
  113. 'label' => 'Search API test entity',
  114. 'base table' => 'search_api_test',
  115. 'uri callback' => 'search_api_test_uri',
  116. 'entity keys' => array(
  117. 'id' => 'id',
  118. ),
  119. ),
  120. );
  121. }
  122. /**
  123. * Implements hook_entity_property_info().
  124. */
  125. function search_api_test_entity_property_info() {
  126. $info['search_api_test']['properties'] = array(
  127. 'id' => array(
  128. 'label' => 'ID',
  129. 'type' => 'integer',
  130. 'description' => 'The primary identifier for a server.',
  131. ),
  132. 'title' => array(
  133. 'label' => 'Title',
  134. 'type' => 'text',
  135. 'description' => 'The title of the item.',
  136. 'required' => TRUE,
  137. ),
  138. 'body' => array(
  139. 'label' => 'Body',
  140. 'type' => 'text',
  141. 'description' => 'A text belonging to the item.',
  142. 'sanitize' => 'filter_xss',
  143. 'required' => TRUE,
  144. ),
  145. 'type' => array(
  146. 'label' => 'Type',
  147. 'type' => 'text',
  148. 'description' => 'A string identifying the type of item.',
  149. 'required' => TRUE,
  150. ),
  151. 'parent' => array(
  152. 'label' => 'Parent',
  153. 'type' => 'search_api_test',
  154. 'description' => "The item's parent.",
  155. 'getter callback' => 'search_api_test_parent',
  156. ),
  157. 'keywords' => array(
  158. 'label' => 'Keywords',
  159. 'type' => 'list<string>',
  160. 'description' => 'An optional collection of keywords describing the item.',
  161. 'getter callback' => 'search_api_test_list_callback',
  162. ),
  163. );
  164. return $info;
  165. }
  166. /**
  167. * URI callback for test entity.
  168. */
  169. function search_api_test_uri($entity) {
  170. return array(
  171. 'path' => 'search_api_test/' . $entity->id,
  172. );
  173. }
  174. /**
  175. * Parent callback.
  176. */
  177. function search_api_test_parent($entity) {
  178. return search_api_test_load($entity->id - 1);
  179. }
  180. /**
  181. * List callback.
  182. */
  183. function search_api_test_list_callback($data) {
  184. //return is_array($entity->keywords) ? $entity->keywords : explode(',', $entity->keywords);
  185. if (is_array($data)) {
  186. $res = is_array($data['keywords']) ? $data['keywords'] : explode(',', $data['keywords']);
  187. }
  188. else {
  189. $res = is_array($data->keywords) ? $data->keywords : explode(',', $data->keywords);
  190. }
  191. return array_filter($res);
  192. }
  193. /**
  194. * Implements hook_search_api_service_info().
  195. */
  196. function search_api_test_search_api_service_info() {
  197. $services['search_api_test_service'] = array(
  198. 'name' => 'search_api_test_service',
  199. 'description' => 'search_api_test_service description',
  200. 'class' => 'SearchApiTestService',
  201. );
  202. return $services;
  203. }
  204. /**
  205. * Test service class.
  206. */
  207. class SearchApiTestService extends SearchApiAbstractService {
  208. public function configurationForm(array $form, array &$form_state) {
  209. $form = array(
  210. 'test' => array(
  211. '#type' => 'textfield',
  212. '#title' => 'Test option',
  213. ),
  214. );
  215. if (!empty($this->options)) {
  216. $form['test']['#default_value'] = $this->options['test'];
  217. }
  218. return $form;
  219. }
  220. public function indexItems(SearchApiIndex $index, array $items) {
  221. // Refuse to index items with IDs that are multiples of 8 unless the
  222. // "search_api_test_index_all" variable is set.
  223. if (variable_get('search_api_test_index_all', FALSE)) {
  224. return $this->index($index, array_keys($items));
  225. }
  226. $ret = array();
  227. foreach ($items as $id => $item) {
  228. if ($id % 8) {
  229. $ret[] = $id;
  230. }
  231. }
  232. return $this->index($index, $ret);
  233. }
  234. protected function index(SearchApiIndex $index, array $ids) {
  235. $this->options += array('indexes' => array());
  236. $this->options['indexes'] += array($index->machine_name => array());
  237. $this->options['indexes'][$index->machine_name] += drupal_map_assoc($ids);
  238. sort($this->options['indexes'][$index->machine_name]);
  239. $this->server->save();
  240. return $ids;
  241. }
  242. /**
  243. * Override so deleteItems() isn't called which would otherwise lead to the
  244. * server being updated and, eventually, to a notice because there is no
  245. * server to be updated anymore.
  246. */
  247. public function preDelete() {}
  248. public function deleteItems($ids = 'all', SearchApiIndex $index = NULL) {
  249. if ($ids == 'all') {
  250. if ($index) {
  251. $this->options['indexes'][$index->machine_name] = array();
  252. }
  253. else {
  254. $this->options['indexes'] = array();
  255. }
  256. }
  257. else {
  258. foreach ($ids as $id) {
  259. unset($this->options['indexes'][$index->machine_name][$id]);
  260. }
  261. }
  262. $this->server->save();
  263. }
  264. public function search(SearchApiQueryInterface $query) {
  265. $options = $query->getOptions();
  266. $ret = array();
  267. $index_id = $query->getIndex()->machine_name;
  268. if (empty($this->options['indexes'][$index_id])) {
  269. return array(
  270. 'result count' => 0,
  271. 'results' => array(),
  272. );
  273. }
  274. $items = $this->options['indexes'][$index_id];
  275. $min = isset($options['offset']) ? $options['offset'] : 0;
  276. $max = $min + (isset($options['limit']) ? $options['limit'] : count($items));
  277. $i = 0;
  278. $ret['result count'] = count($items);
  279. $ret['results'] = array();
  280. foreach ($items as $id) {
  281. ++$i;
  282. if ($i > $max) {
  283. break;
  284. }
  285. if ($i > $min) {
  286. $ret['results'][$id] = array(
  287. 'id' => $id,
  288. 'score' => 1,
  289. );
  290. }
  291. }
  292. return $ret;
  293. }
  294. public function fieldsUpdated(SearchApiIndex $index) {
  295. return db_query('SELECT COUNT(*) FROM {search_api_test}')->fetchField() > 0;
  296. }
  297. }