search_api_page.admin.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <?php
  2. /**
  3. * Displays an overview of all defined search pages.
  4. */
  5. function search_api_page_admin_overview() {
  6. $base_path = drupal_get_path('module', 'search_api') . '/';
  7. drupal_add_css($base_path . 'search_api.admin.css');
  8. $header = array(t('Status'), t('Configuration'), t('Name'), t('Path'), t('Index'), t('Operations'));
  9. $rows = array();
  10. $t_enabled['data'] = array(
  11. '#theme' => 'image',
  12. '#path' => $base_path . 'enabled.png',
  13. '#alt' => t('enabled'),
  14. '#title' => t('enabled'),
  15. );
  16. $t_enabled['class'] = array('search-api-status');
  17. $t_disabled['data'] = array(
  18. '#theme' => 'image',
  19. '#path' => $base_path . 'disabled.png',
  20. '#alt' => t('disabled'),
  21. '#title' => t('disabled'),
  22. );
  23. $t_disabled['class'] = array('search-api-status');
  24. $t_enable = t('enable');
  25. $t_disable = t('disable');
  26. $t_edit = t('edit');
  27. $t_delete = t('delete');
  28. $pre = 'admin/config/search/search_api/page/';
  29. $pre_index = 'admin/config/search/search_api/index/';
  30. $enable = '/enable';
  31. $disable = '/disable';
  32. $edit = '/edit';
  33. $delete = '/delete';
  34. foreach (search_api_page_load_multiple() as $page) {
  35. $url = $pre . $page->machine_name;
  36. $index = search_api_index_load($page->index_id);
  37. $rows[] = array(
  38. $page->enabled ? $t_enabled : $t_disabled,
  39. theme('entity_status', array('status' => $page->status)),
  40. l($page->name, $page->path),
  41. l($page->path, $page->path),
  42. l($index->name, $pre_index . $index->machine_name),
  43. l($t_edit, $url . $edit),
  44. );
  45. }
  46. return array(
  47. '#theme' => 'table',
  48. '#header' => $header,
  49. '#rows' => $rows,
  50. '#empty' => t('There are no search pages defined yet.'),
  51. );
  52. }
  53. /**
  54. * Displays a form for adding a search page.
  55. */
  56. function search_api_page_admin_add(array $form, array &$form_state) {
  57. $form = array();
  58. if (empty($form_state['step_one'])) {
  59. $indexes = search_api_index_load_multiple(FALSE);
  60. if (!$indexes) {
  61. drupal_set_message(t('There are no searches indexes which can be searched. Please <a href="@url">create an index</a> first.', array('@url' => url('admin/config/search/search_api/add_index'))), 'warning');
  62. return array();
  63. }
  64. $index_options = array();
  65. foreach ($indexes as $index) {
  66. if ($index->enabled) {
  67. $index_options[$index->machine_name] = $index->name;
  68. }
  69. }
  70. foreach ($indexes as $index) {
  71. if (!$index->enabled) {
  72. $index_options[$index->machine_name] = $index->name . ' (' . t('disabled') . ')';
  73. }
  74. }
  75. $form['name'] = array(
  76. '#type' => 'textfield',
  77. '#title' => t('Search name'),
  78. '#maxlength' => 50,
  79. '#required' => TRUE,
  80. );
  81. $form['machine_name'] = array(
  82. '#type' => 'machine_name',
  83. '#maxlength' => 51,
  84. '#machine_name' => array(
  85. 'exists' => 'search_api_index_load',
  86. ),
  87. );
  88. $form['index_id'] = array(
  89. '#type' => 'select',
  90. '#title' => t('Index'),
  91. '#description' => t('Select the index this page should search. This cannot be changed later.'),
  92. '#options' => $index_options,
  93. '#required' => TRUE,
  94. );
  95. $form['enabled'] = array(
  96. '#type' => 'checkbox',
  97. '#title' => t('Enabled'),
  98. '#description' => t('This will only take effect if the selected index is also enabled.'),
  99. '#default_value' => TRUE,
  100. );
  101. $form['description'] = array(
  102. '#type' => 'textarea',
  103. '#title' => t('Search description'),
  104. );
  105. $form['path'] = array(
  106. '#type' => 'textfield',
  107. '#title' => t('Path'),
  108. '#description' => t('Set the path under which the search page will be accessible, when enabled.'),
  109. '#maxlength' => 50,
  110. '#required' => TRUE,
  111. );
  112. $form['submit'] = array(
  113. '#type' => 'submit',
  114. '#value' => t('Create page'),
  115. );
  116. return $form;
  117. }
  118. $index = search_api_index_load($form_state['step_one']['index_id']);
  119. if ($index->enabled) {
  120. $modes = array();
  121. foreach ($index->query()->parseModes() as $mode => $info) {
  122. $modes[$mode] = $info['name'];
  123. }
  124. }
  125. else {
  126. $modes = array();
  127. $modes['direct'] = t('Direct query');
  128. $modes['single'] = t('Single term');
  129. $modes['terms'] = t('Multiple terms');
  130. }
  131. $form['mode'] = array(
  132. '#type' => 'select',
  133. '#title' => t('Query type'),
  134. '#description' => t('Select how the query will be parsed.'),
  135. '#options' => $modes,
  136. '#default_value' => 'terms',
  137. );
  138. $fields = array();
  139. $index_fields = $index->getFields();
  140. foreach ($index->getFulltextFields() as $name) {
  141. $fields[$name] = $index_fields[$name]['name'];
  142. }
  143. if (count($fields) > 1) {
  144. $form['fields'] = array(
  145. '#type' => 'select',
  146. '#title' => t('Searched fields'),
  147. '#description' => t('Select the fields that will be searched. If no fields are selected, all available fulltext fields will be searched.'),
  148. '#options' => $fields,
  149. '#size' => min(4, count($fields)),
  150. '#multiple' => TRUE,
  151. );
  152. }
  153. else {
  154. $form['fields'] = array(
  155. '#type' => 'value',
  156. '#value' => array(),
  157. );
  158. }
  159. $form['per_page'] = array(
  160. '#type' => 'select',
  161. '#title' => t('Results per page'),
  162. '#description' => t('Select how many items will be displayed on one page of the search result.'),
  163. '#options' => drupal_map_assoc(array(5, 10, 20, 30, 40, 50, 60, 80, 100)),
  164. '#default_value' => 10,
  165. );
  166. $form['result_page_search_form'] = array(
  167. '#type' => 'radios',
  168. '#title' => t('Search form on result page'),
  169. '#default_value' => 1,
  170. '#options' => array('1' => t('Enabled'), '0' => t('Disabled')),
  171. '#description' => t('Enable or disable the search form on the result page'),
  172. );
  173. $form['get_per_page'] = array(
  174. '#type' => 'checkbox',
  175. '#title' => t('Allow GET override'),
  176. '#description' => t('Allow the „Results per page“ setting to be overridden from the URL, using the "per_page" GET parameter.<br />' .
  177. 'Example: http://example.com/search_results?per_page=7'),
  178. '#default_value' => TRUE,
  179. );
  180. $view_modes = array(
  181. 'search_api_page_result' => t('Themed as search results'),
  182. );
  183. // For entities, we also add all entity view modes.
  184. if ($entity_info = entity_get_info($index->item_type)) {
  185. foreach ($entity_info['view modes'] as $mode => $mode_info) {
  186. $view_modes[$mode] = $mode_info['label'];
  187. }
  188. }
  189. if (count($view_modes) > 1) {
  190. $form['view_mode'] = array(
  191. '#type' => 'select',
  192. '#title' => t('View mode'),
  193. '#options' => $view_modes,
  194. '#description' => t('Select how search results will be displayed.'),
  195. '#size' => 1,
  196. '#default_value' => 'search_api_page_result',
  197. );
  198. }
  199. else {
  200. $form['view_mode'] = array(
  201. '#type' => 'value',
  202. '#value' => reset($view_modes),
  203. );
  204. }
  205. if (module_exists('search_api_spellcheck') && ($server = $index->server()) && $server->supportsFeature('search_api_spellcheck')) {
  206. $form['search_api_spellcheck'] = array(
  207. '#type' => 'checkbox',
  208. '#title' => t('Enable spell check'),
  209. '#description' => t('Display "Did you mean … ?" above search results.'),
  210. '#default_value' => TRUE,
  211. );
  212. }
  213. $form['submit'] = array(
  214. '#type' => 'submit',
  215. '#value' => t('Create page'),
  216. );
  217. return $form;
  218. }
  219. /**
  220. * Validation callback for search_api_page_admin_add().
  221. */
  222. function search_api_page_admin_add_validate(array $form, array &$form_state) {
  223. if (empty($form_state['step_one'])) {
  224. $form_state['values']['path'] = drupal_strtolower(trim($form_state['values']['path']));
  225. if (search_api_page_load_multiple(FALSE, array('path' => $form_state['values']['path']))) {
  226. form_set_error('path', t('The entered path is already in use. Please enter a unique path.'));
  227. }
  228. }
  229. }
  230. /**
  231. * Submit callback for search_api_page_admin_add().
  232. */
  233. function search_api_page_admin_add_submit(array $form, array &$form_state) {
  234. form_state_values_clean($form_state);
  235. if (empty($form_state['step_one'])) {
  236. $form_state['step_one'] = $form_state['values'];
  237. $form_state['rebuild'] = TRUE;
  238. return;
  239. }
  240. $values = $form_state['step_one'];
  241. $values['options'] = $form_state['values'];
  242. search_api_page_insert($values);
  243. drupal_set_message(t('The search page was successfully created.'));
  244. $form_state['redirect'] = 'admin/config/search/search_api/page';
  245. }
  246. /**
  247. * Displays a form for editing or deleting a search page.
  248. */
  249. function search_api_page_admin_edit(array $form, array &$form_state, Entity $page) {
  250. $index = search_api_index_load($page->index_id);
  251. $form_state['page'] = $page;
  252. $form['name'] = array(
  253. '#type' => 'textfield',
  254. '#title' => t('Search name'),
  255. '#maxlength' => 50,
  256. '#required' => TRUE,
  257. '#default_value' => $page->name,
  258. );
  259. $form['enabled'] = array(
  260. '#type' => 'checkbox',
  261. '#title' => t('Enabled'),
  262. '#description' => t('This will only take effect if the selected index is also enabled.'),
  263. '#default_value' => $page->enabled,
  264. '#disabled' => !$index->enabled,
  265. );
  266. $form['description'] = array(
  267. '#type' => 'textarea',
  268. '#title' => t('Search description'),
  269. '#default_value' => $page->description,
  270. );
  271. $form['index'] = array(
  272. '#type' => 'item',
  273. '#title' => t('Index'),
  274. '#description' => l($index->name, 'admin/config/search/search_api/index/' . $index->machine_name),
  275. );
  276. $form['path'] = array(
  277. '#type' => 'textfield',
  278. '#title' => t('Path'),
  279. '#description' => t('Set the path under which the search page will be accessible, when enabled.'),
  280. '#maxlength' => 50,
  281. '#default_value' => $page->path,
  282. );
  283. if ($index->enabled) {
  284. $modes = array();
  285. foreach ($index->query()->parseModes() as $mode => $info) {
  286. $modes[$mode] = $info['name'];
  287. }
  288. }
  289. else {
  290. $modes = array();
  291. $modes['direct'] = array(
  292. 'name' => t('Direct query'),
  293. 'description' => t("Don't parse the query, just hand it to the search server unaltered. " .
  294. "Might fail if the query contains syntax errors in regard to the specific server's query syntax."),
  295. );
  296. $modes['single'] = array(
  297. 'name' => t('Single term'),
  298. 'description' => t('The query is interpreted as a single keyword, maybe containing spaces or special characters.'),
  299. );
  300. $modes['terms'] = array(
  301. 'name' => t('Multiple terms'),
  302. 'description' => t('The query is interpreted as multiple keywords seperated by spaces. ' .
  303. 'Keywords containing spaces may be "quoted". Quoted keywords must still be seperated by spaces.'),
  304. );
  305. }
  306. $form['options']['#tree'] = TRUE;
  307. $form['options']['mode'] = array(
  308. '#type' => 'select',
  309. '#title' => t('Query type'),
  310. '#description' => t('Select how the query will be parsed.'),
  311. '#options' => $modes,
  312. '#default_value' => $page->options['mode'],
  313. );
  314. $fields = array();
  315. $index_fields = $index->getFields();
  316. foreach ($index->getFulltextFields() as $name) {
  317. $fields[$name] = $index_fields[$name]['name'];
  318. }
  319. if (count($fields) > 1) {
  320. $form['options']['fields'] = array(
  321. '#type' => 'select',
  322. '#title' => t('Searched fields'),
  323. '#description' => t('Select the fields that will be searched. If no fields are selected, all available fulltext fields will be searched.'),
  324. '#options' => $fields,
  325. '#size' => min(4, count($fields)),
  326. '#multiple' => TRUE,
  327. '#default_value' => $page->options['fields'],
  328. );
  329. }
  330. else {
  331. $form['options']['fields'] = array(
  332. '#type' => 'value',
  333. '#value' => array(),
  334. );
  335. }
  336. $form['options']['per_page'] = array(
  337. '#type' => 'select',
  338. '#title' => t('Results per page'),
  339. '#description' => t('Select how many items will be displayed on one page of the search result.'),
  340. '#options' => drupal_map_assoc(array(5, 10, 20, 30, 40, 50, 60, 80, 100)),
  341. '#default_value' => $page->options['per_page'],
  342. );
  343. $form['result_page_search_form'] = array(
  344. '#type' => 'radios',
  345. '#title' => t('Search form on result page'),
  346. '#default_value' => isset($page->options['result_page_search_form']) ? $page->options['result_page_search_form'] : 1,
  347. '#options' => array('1' => t('Enabled'), '0' => t('Disabled')),
  348. '#description' => t('Enable or disable the search form on the result page'),
  349. );
  350. $form['options']['get_per_page'] = array(
  351. '#type' => 'checkbox',
  352. '#title' => t('Allow GET override'),
  353. '#description' => t('Allow the „Results per page“ setting to be overridden from the URL, using the "per_page" GET parameter.<br />' .
  354. 'Example: <code>http://example.com/search_results?per_page=7</code>'),
  355. '#default_value' => !empty($page->options['get_per_page']),
  356. );
  357. $view_modes = array(
  358. 'search_api_page_result' => t('Themed as search results'),
  359. );
  360. // For entities, we also add all entity view modes.
  361. if ($entity_info = entity_get_info($index->item_type)) {
  362. foreach ($entity_info['view modes'] as $mode => $mode_info) {
  363. $view_modes[$mode] = $mode_info['label'];
  364. }
  365. }
  366. if (count($view_modes) > 1) {
  367. $form['options']['view_mode'] = array(
  368. '#type' => 'select',
  369. '#title' => t('View mode'),
  370. '#options' => $view_modes,
  371. '#description' => t('Select how search results will be displayed.'),
  372. '#size' => 1,
  373. '#default_value' => isset($page->options['view_mode']) ? $page->options['view_mode'] : 'search_api_page_result',
  374. );
  375. }
  376. else {
  377. $form['options']['view_mode'] = array(
  378. '#type' => 'value',
  379. '#value' => reset($view_modes),
  380. );
  381. }
  382. if (module_exists('search_api_spellcheck') && ($server = $index->server()) && $server->supportsFeature('search_api_spellcheck')) {
  383. $form['options']['search_api_spellcheck'] = array(
  384. '#type' => 'checkbox',
  385. '#title' => t('Enable spell check'),
  386. '#description' => t('Display "Did you mean … ?" above search results.'),
  387. '#default_value' => !empty($page->options['search_api_spellcheck']),
  388. );
  389. }
  390. $form['actions']['#type'] = 'actions';
  391. $form['actions']['submit'] = array(
  392. '#type' => 'submit',
  393. '#value' => t('Save changes'),
  394. );
  395. if ($page->hasStatus(ENTITY_OVERRIDDEN)) {
  396. $form['actions']['revert'] = array(
  397. '#type' => 'fieldset',
  398. '#title' => t('Revert search page'),
  399. '#description' => t('This will revert all settings on this search page back to the defaults. This action cannot be undone.'),
  400. '#collapsible' => TRUE,
  401. '#collapsed' => TRUE,
  402. 'revert' => array(
  403. '#type' => 'submit',
  404. '#value' => t('Revert search page'),
  405. ),
  406. );
  407. }
  408. elseif ($page->hasStatus(ENTITY_CUSTOM)) {
  409. $form['actions']['delete'] = array(
  410. '#type' => 'fieldset',
  411. '#title' => t('Delete search page'),
  412. '#description' => t('This will delete the search page along with all of its settings.'),
  413. '#collapsible' => TRUE,
  414. '#collapsed' => TRUE,
  415. 'delete' => array(
  416. '#type' => 'submit',
  417. '#value' => t('Delete search page'),
  418. ),
  419. );
  420. }
  421. return $form;
  422. }
  423. /**
  424. * Validation callback for search_api_page_admin_edit().
  425. */
  426. function search_api_page_admin_edit_validate(array $form, array &$form_state) {
  427. if ($form_state['values']['op'] == t('Save changes')) {
  428. $form_state['values']['path'] = drupal_strtolower(trim($form_state['values']['path']));
  429. $pages = search_api_page_load_multiple(FALSE, array('path' => $form_state['values']['path']));
  430. if (count($pages) > 1 || (($page = array_shift($pages)) && $page->machine_name != $form_state['page']->machine_name)) {
  431. form_set_error('path', t('The entered path is already in use. Please enter a unique path.'));
  432. }
  433. }
  434. }
  435. /**
  436. * Submit callback for search_api_page_admin_edit().
  437. */
  438. function search_api_page_admin_edit_submit(array $form, array &$form_state) {
  439. $op = $form_state['values']['op'];
  440. form_state_values_clean($form_state);
  441. $form_state['redirect'] = 'admin/config/search/search_api/page';
  442. if ($op == t('Delete search page') || $op == t('Revert search page')) {
  443. $form_state['page']->delete();
  444. if ($op == t('Revert search page')) {
  445. drupal_set_message(t('The search page was successfully reverted.'));
  446. }
  447. else {
  448. drupal_set_message(t('The search page was successfully deleted.'));
  449. }
  450. return;
  451. }
  452. search_api_page_edit($form_state['page']->machine_name, $form_state['values']);
  453. drupal_set_message(t('The changes were successfully saved.'));
  454. }