search_api_saved_searches.pages.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <?php
  2. /**
  3. * @file
  4. * User UI functions and form callbacks for saved searches.
  5. */
  6. /**
  7. * Page callback for listing all saved searches of a user.
  8. *
  9. * @param $account
  10. * The user of which to list saved searches.
  11. */
  12. function search_api_saved_searches_user_listing($account) {
  13. $base_path = 'search-api/saved-search/';
  14. $header = array(
  15. t('Name'),
  16. t('Created'),
  17. t('Last executed'),
  18. t('Interval'),
  19. t('Operations'),
  20. );
  21. $searches = search_api_saved_search_load_multiple(FALSE, array('uid' => $account->uid));
  22. $rows = array();
  23. foreach ($searches as $search) {
  24. $settings = $search->settings();
  25. if (empty($search->options['page'])) {
  26. $name = check_plain($search->name);
  27. }
  28. else {
  29. $name = $search->l($search->name);
  30. }
  31. $created = format_date($search->created, 'short');
  32. $last_execute = t('@time ago', array('@time' => format_interval(REQUEST_TIME - $search->last_execute)));
  33. // Get the translated label for the interval.
  34. $available_intervals = $settings->getTranslatedOption('interval_options');
  35. if (isset($available_intervals[$search->notify_interval])) {
  36. $interval = $available_intervals[$search->notify_interval];
  37. }
  38. elseif ($search->notify_interval < 0) {
  39. $interval = t('Never');
  40. }
  41. else {
  42. $interval = format_interval($search->notify_interval, 1);
  43. }
  44. $enable_options['attributes']['class'][] = 'saved-search-enable';
  45. $edit_options['attributes']['class'][] = 'saved-search-edit';
  46. $delete_options['attributes']['class'][] = 'saved-search-delete';
  47. if ($search->enabled) {
  48. $enable_action = '/disable';
  49. $enable_label = t('disable');
  50. }
  51. else {
  52. $enable_action = '/enable';
  53. $enable_label = t('enable');
  54. $enable_options['query']['token'] = drupal_get_token($search->id);
  55. }
  56. $path = $base_path . $search->id;
  57. $enable_link = l($enable_label, $path . $enable_action, $enable_options);
  58. $edit_link = l(t('edit'), $path . '/edit', $edit_options);
  59. $delete_link = l(t('delete'), $path . '/delete', $delete_options);
  60. $rows[] = array(
  61. $name,
  62. $created,
  63. $last_execute,
  64. $interval,
  65. $enable_link . ' | ' . $edit_link . ' | ' . $delete_link,
  66. );
  67. }
  68. $render = array(
  69. '#theme' => 'table',
  70. '#header' => $header,
  71. '#rows' => $rows,
  72. '#empty' => t('No searches were saved yet.'),
  73. '#sticky' => TRUE,
  74. );
  75. return $render;
  76. }
  77. /**
  78. * Page callback for manually creating a new saved search.
  79. *
  80. * @param SearchApiSavedSearchesSettings $settings
  81. * (optional) The settings to use. If not present, either the only available
  82. * settings will be used, or a form for selecting one will be displayed.
  83. */
  84. function search_api_saved_searches_create_manual(SearchApiSavedSearchesSettings $settings = NULL) {
  85. if (!isset($settings)) {
  86. foreach (search_api_saved_searches_settings_load_multiple(FALSE, array('enabled' => TRUE)) as $settings) {
  87. if (!empty($settings->options['manual']['allow'])) {
  88. $available_settings[$settings->delta] = $settings;
  89. }
  90. }
  91. if (empty($available_settings)) {
  92. return t('There are no searches for which saved searches can be created manually.');
  93. }
  94. if (count($available_settings) == 1) {
  95. $settings = reset($available_settings);
  96. }
  97. else {
  98. $render = array();
  99. $render['question']['#markup'] = t('For which search do you want to create a saved search?');
  100. $render['list']['#theme'] = 'list';
  101. $render['list']['#items'] = array();
  102. $base = 'search-api/saved-searches/add/';
  103. foreach ($available_settings as $id => $settings) {
  104. $name = $settings->index()->name;
  105. if (!empty($settings->options['manual']['page']['path'])) {
  106. $item = menu_get_item($settings->options['manual']['page']['path']);
  107. if (!empty($item['title'])) {
  108. $name = $item['title'];
  109. }
  110. }
  111. $render['list']['#items'][]['#markup'] = l($name, $base . $id);
  112. }
  113. return $render;
  114. }
  115. }
  116. return drupal_get_form('search_api_saved_searches_save_form', $settings);
  117. }
  118. /**
  119. * Page callback that activates a saved search.
  120. *
  121. * This is mostly necessary for anonymous users, but also when a user enters a
  122. * different mail address than the one he registered with.
  123. *
  124. * @param SearchApiSavedSearch $search
  125. * The search to activate.
  126. * @param string $key
  127. * The secret access key for this search, used to authenticate the user.
  128. */
  129. function search_api_saved_searches_activate_page(SearchApiSavedSearch $search, $key) {
  130. $ret = array(
  131. 'message' => array(
  132. '#markup' => '',
  133. ),
  134. 'link' => array(
  135. '#markup' => '<p>' . $search->l(t('View this saved search')) . '</p>',
  136. ),
  137. );
  138. if ($search->enabled) {
  139. $msg = t('This saved search has already been activated.');
  140. }
  141. else {
  142. $search->enabled = TRUE;
  143. $success = $search->save();
  144. if (!$success) {
  145. drupal_set_message(t('An error occurred while trying to activate the search. Please contact the site administrator.'), 'error');
  146. return $ret;
  147. }
  148. $msg = t('Your saved search was successfully activated.');
  149. }
  150. if ($search->notify_interval >= 0) {
  151. $msg .= ' ' . t('You will receive e-mail notifications for new results in the future.');
  152. }
  153. $ret['message']['#markup'] = '<p>' . $msg . '</p>';
  154. return $ret;
  155. }
  156. /**
  157. * Form builder for editing a saved search.
  158. *
  159. * @param SearchApiSavedSearch $search
  160. * The search to edit.
  161. *
  162. * @see search_api_saved_searches_search_edit_form_submit()
  163. * @ingroup forms
  164. */
  165. function search_api_saved_searches_search_edit_form(array $form, array &$form_state, SearchApiSavedSearch $search) {
  166. $form_state['search'] = $search;
  167. $settings = $search->settings();
  168. if ($search->uid) {
  169. $form_state['destination']['path'] = 'user/' . $search->uid . '/saved-searches';
  170. }
  171. elseif (!empty($search->options['page'])) {
  172. $form_state['destination'] = array($search->options['page']['path'], $search->options['page']);
  173. }
  174. $form['enabled'] = array(
  175. '#type' => 'checkbox',
  176. '#title' => t('Enabled'),
  177. '#description' => t('Disable to stop receiving notifications from this saved search.'),
  178. '#default_value' => $search->enabled,
  179. );
  180. $form['name'] = array(
  181. '#type' => 'textfield',
  182. '#title' => t('Name'),
  183. '#description' => t('The name that will be displayed for this saved search.'),
  184. '#maxlength' => 255,
  185. '#required' => TRUE,
  186. '#default_value' => $search->name,
  187. );
  188. if (!empty($settings->options['allow_keys_change'])) {
  189. $keywords = $search->query['keys'];
  190. if (is_array($keywords)) {
  191. $keywords = search_api_saved_searches_unparse_keys($keywords);
  192. }
  193. $form['keys'] = array(
  194. '#type' => 'textfield',
  195. '#title' => t('Keywords'),
  196. '#description' => t('The keywords to use for this search.'),
  197. '#default_value' => $keywords,
  198. );
  199. }
  200. if ($settings->options['user_select_interval'] && count($settings->options['interval_options']) > 1) {
  201. $form['notify_interval'] = array(
  202. '#type' => 'select',
  203. '#title' => t('Notification interval'),
  204. '#options' => $settings->getTranslatedOption('interval_options'),
  205. '#required' => TRUE,
  206. '#default_value' => $search->notify_interval,
  207. );
  208. }
  209. $form['actions']['#type'] = 'actions';
  210. $form['actions']['submit'] = array(
  211. '#type' => 'submit',
  212. '#value' => t('Save changes'),
  213. );
  214. if (!empty($form_state['destination'])) {
  215. $form['actions']['cancel'] = array(
  216. '#type' => 'link',
  217. '#title' => t('Cancel'),
  218. '#href' => $form_state['destination']['path'],
  219. '#options' => $form_state['destination'],
  220. );
  221. }
  222. return $form;
  223. }
  224. /**
  225. * Reverses the search keywords parsing to get string keywords.
  226. *
  227. * @param array $keys
  228. * An array with search keys, as defined by
  229. * SearchApiQueryInterface::getKeys().
  230. *
  231. * @return string
  232. * A guess regarding the original keys used to come up with the given keys
  233. * array.
  234. */
  235. function search_api_saved_searches_unparse_keys(array $keys) {
  236. $simple_keys = array();
  237. foreach (element_children($keys) as $i) {
  238. $key = $keys[$i];
  239. if (is_scalar($key)) {
  240. if (strpos($key, ' ')) {
  241. $key = '"' . $key . '"';
  242. }
  243. $simple_keys[] = $key;
  244. }
  245. }
  246. return implode(' ', $simple_keys);
  247. }
  248. /**
  249. * Submission handler for search_api_saved_searches_search_edit_form().
  250. *
  251. * @see search_api_saved_searches_search_edit_form()
  252. */
  253. function search_api_saved_searches_search_edit_form_submit(array $form, array &$form_state) {
  254. $values = $form_state['values'];
  255. /** @var SearchApiSavedSearch $search */
  256. $search = $form_state['search'];
  257. $search->name = $values['name'];
  258. $search->enabled = $values['enabled'];
  259. if (isset($values['notify_interval'])) {
  260. $search->notify_interval = $values['notify_interval'];
  261. }
  262. if (!empty($form['keys']) && $values['keys'] != $form['keys']['#default_value']) {
  263. $search->query['keys'] = ($values['keys'] === '') ? NULL : $values['keys'];
  264. // Unsetting the results array will automatically re-calculate the current
  265. // results when saving.
  266. $search->results = NULL;
  267. }
  268. if ($search->save()) {
  269. drupal_set_message(t('Successfully saved your changes.'));
  270. if (!empty($form_state['destination'])) {
  271. $form_state['redirect'] = $form_state['destination'];
  272. }
  273. }
  274. else {
  275. drupal_set_message(t('An error occurred while trying to save the changes.'), 'error');
  276. }
  277. }
  278. /**
  279. * Page callback: Enables a saved search.
  280. *
  281. * @param SearchApiSavedSearch $search
  282. * The search to enable.
  283. */
  284. function search_api_saved_searches_search_enable(SearchApiSavedSearch $search = NULL) {
  285. if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], $search->id)) {
  286. return MENU_ACCESS_DENIED;
  287. }
  288. $search->enabled = TRUE;
  289. if ($search->save()) {
  290. drupal_set_message(t('The saved search was successfully enabled.'));
  291. }
  292. else {
  293. drupal_set_message(t('The saved search could not be enabled.'), 'error');
  294. }
  295. drupal_goto(_search_api_saved_searches_admin_redirect_url($search));
  296. return NULL;
  297. }
  298. /**
  299. * Page callback: Constructs a form for disabling a saved search.
  300. *
  301. * @param SearchApiSavedSearch $search
  302. * The search to disable.
  303. *
  304. * @see search_api_saved_searches_search_disable_form_submit()
  305. *
  306. * @ingroup forms
  307. */
  308. function search_api_saved_searches_search_disable_form(array $form, array &$form_state, SearchApiSavedSearch $search) {
  309. $form_state['search'] = $search;
  310. $url = _search_api_saved_searches_admin_redirect_url($search);
  311. return confirm_form($form, t('Do you really want to disable this saved search?'), $url, t('You will not receive any updates for this saved search until it is re-enabled.'));
  312. }
  313. /**
  314. * Form submission handler for search_api_saved_searches_search_disable_form().
  315. */
  316. function search_api_saved_searches_search_disable_form_submit(array $form, array &$form_state) {
  317. $search = $form_state['search'];
  318. $search->enabled = FALSE;
  319. $search->save();
  320. drupal_set_message(t('The saved search was successfully disabled.'));
  321. $form_state['redirect'] = _search_api_saved_searches_admin_redirect_url($search);
  322. }
  323. /**
  324. * Form builder for confirming the deletion of a saved search.
  325. *
  326. * @param SearchApiSavedSearch $search
  327. * The search to delete.
  328. *
  329. * @see search_api_saved_searches_search_delete_form_submit()
  330. * @ingroup forms
  331. */
  332. function search_api_saved_searches_search_delete_form(array $form, array &$form_state, SearchApiSavedSearch $search) {
  333. $form_state['search'] = $search;
  334. $url = _search_api_saved_searches_admin_redirect_url($search);
  335. return confirm_form($form, t('Do you really want to delete this saved search?'), $url);
  336. }
  337. /**
  338. * Submission handler for search_api_saved_searches_search_delete_form().
  339. *
  340. * @see search_api_saved_searches_search_delete_form()
  341. */
  342. function search_api_saved_searches_search_delete_form_submit(array $form, array &$form_state) {
  343. $search = $form_state['search'];
  344. $search->delete();
  345. drupal_set_message(t('The saved search was successfully deleted.'));
  346. $form_state['redirect'] = _search_api_saved_searches_admin_redirect_url($search);
  347. }
  348. /**
  349. * Returns the correct redirect URL after changing a saved search.
  350. *
  351. * This will be the user's "Saved searches" overview tab, if it is accessible;
  352. * otherwise, if the search has a page associated with it, that page; and if
  353. * none of the two are the case, the front page.
  354. *
  355. * @param SearchApiSavedSearch $search
  356. * The saved search that was edited, deleted or otherwise changed.
  357. *
  358. * @return string
  359. * The URL to redirect to.
  360. */
  361. function _search_api_saved_searches_admin_redirect_url(SearchApiSavedSearch $search) {
  362. if ($search->uid && search_api_saved_search_edit_access(user_load($search->uid))) {
  363. return 'user/' . $search->uid . '/saved-searches';
  364. }
  365. elseif (!empty($search->options['page'])) {
  366. return $search->options['page'];
  367. }
  368. return '<front>';
  369. }