|
@@ -72,6 +72,15 @@ function search_api_menu() {
|
|
|
'type' => MENU_LOCAL_TASK,
|
|
|
'context' => MENU_CONTEXT_INLINE | MENU_CONTEXT_PAGE,
|
|
|
);
|
|
|
+ $items[$pre . '/server/%search_api_server/execute-tasks'] = array(
|
|
|
+ 'title' => 'Execute pending tasks',
|
|
|
+ 'description' => 'Attempt to process pending tasks for a given server.',
|
|
|
+ 'page callback' => 'search_api_execute_pending_tasks',
|
|
|
+ 'page arguments' => array(5),
|
|
|
+ 'access callback' => 'search_api_access_execute_tasks_batch',
|
|
|
+ 'access arguments' => array(5),
|
|
|
+ 'type' => MENU_CALLBACK,
|
|
|
+ );
|
|
|
$items[$pre . '/server/%search_api_server/disable'] = array(
|
|
|
'title' => 'Disable',
|
|
|
'description' => 'Disable index.',
|
|
@@ -98,6 +107,13 @@ function search_api_menu() {
|
|
|
'context' => MENU_CONTEXT_INLINE,
|
|
|
'weight' => 10,
|
|
|
);
|
|
|
+ $items[$pre . '/execute-tasks'] = array(
|
|
|
+ 'title' => 'Execute pending tasks',
|
|
|
+ 'description' => 'Attempt to process pending server tasks.',
|
|
|
+ 'page callback' => 'search_api_execute_pending_tasks',
|
|
|
+ 'access callback' => 'search_api_access_execute_tasks_batch',
|
|
|
+ 'type' => MENU_LOCAL_ACTION,
|
|
|
+ );
|
|
|
$items[$pre . '/index/%search_api_index'] = array(
|
|
|
'title' => 'View index',
|
|
|
'title callback' => 'search_api_admin_item_title',
|
|
@@ -1025,6 +1041,28 @@ function search_api_search_api_item_type_info() {
|
|
|
return $types;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Implements hook_module_implements_alter().
|
|
|
+ *
|
|
|
+ * Ensures the item type and service class static caches are invalidated at the
|
|
|
+ * right time.
|
|
|
+ */
|
|
|
+function search_api_module_implements_alter(array &$implementations, $hook) {
|
|
|
+ switch ($hook) {
|
|
|
+ case 'modules_enabled':
|
|
|
+ $group = $implementations['search_api'];
|
|
|
+ unset($implementations['search_api']);
|
|
|
+ $implementations = array('search_api' => $group) + $implementations;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'modules_disabled':
|
|
|
+ $group = $implementations['search_api'];
|
|
|
+ unset($implementations['search_api']);
|
|
|
+ $implementations['search_api'] = $group;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Implements hook_modules_enabled().
|
|
|
*/
|
|
@@ -1103,6 +1141,11 @@ function search_api_search_api_alter_callback_info() {
|
|
|
'description' => t('Exclude unpublished nodes from the index. <strong>Caution:</strong> This only affects the indexed nodes themselves. If an enabled node has references to disabled nodes, those will still be indexed (or displayed) normally.'),
|
|
|
'class' => 'SearchApiAlterNodeStatus',
|
|
|
);
|
|
|
+ $callbacks['search_api_alter_user_content'] = array(
|
|
|
+ 'name' => t('Add user content'),
|
|
|
+ 'description' => t('Allows indexing of nodes (and their fields) created by the indexed user. (Caution: This might lead to performance problems, or even errors during indexing, on larger sites.)'),
|
|
|
+ 'class' => 'SearchApiAlterAddUserContent',
|
|
|
+ );
|
|
|
$callbacks['search_api_alter_user_status'] = array(
|
|
|
'name' => t('Exclude blocked users'),
|
|
|
'description' => t('Exclude blocked users from the index. <strong>Caution:</strong> This only affects the indexed users themselves. If an active user account includes a reference to a disabled user, that reference will still be indexed (or displayed) normally.'),
|
|
@@ -1382,6 +1425,10 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) {
|
|
|
// Sometimes the order of tasks might be important, so make sure to order by
|
|
|
// the task ID (which should be in order of insertion).
|
|
|
$select->orderBy('t.id');
|
|
|
+ // Only retrieve and execute 100 tasks at once, to avoid running out of memory
|
|
|
+ // or time. We just can't do anything else until all tasks have been resolved,
|
|
|
+ // but at least we shouldn't crash sites, or keep piling up tasks, that way.
|
|
|
+ $select->range(0, 100);
|
|
|
$tasks = $select->execute();
|
|
|
|
|
|
$executed_tasks = array();
|
|
@@ -1429,7 +1476,7 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) {
|
|
|
|
|
|
default:
|
|
|
// This should never happen.
|
|
|
- continue;
|
|
|
+ continue 2;
|
|
|
}
|
|
|
$executed_tasks[] = $task->id;
|
|
|
}
|
|
@@ -1438,11 +1485,116 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) {
|
|
|
if (!$executed_tasks) {
|
|
|
return TRUE;
|
|
|
}
|
|
|
- // Otherwise, delete the executed tasks and check if new tasks were created.
|
|
|
+ // Otherwise, delete the executed tasks and check if new tasks were created
|
|
|
+ // (or if we didn't even fetch all due to the 100 tasks limit).
|
|
|
search_api_server_tasks_delete($executed_tasks);
|
|
|
return $count_query->execute()->fetchField() === 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Provides a batch wrapper for search_api_server_tasks_check().
|
|
|
+ *
|
|
|
+ * @param SearchApiServer|null $server
|
|
|
+ * (optional) The server whose tasks should be executed, or NULL to execute
|
|
|
+ * tasks for all servers.
|
|
|
+ */
|
|
|
+function search_api_execute_pending_tasks(SearchApiServer $server = NULL) {
|
|
|
+ batch_set(array(
|
|
|
+ 'title' => t('Processing pending tasks'),
|
|
|
+ 'operations' => array(
|
|
|
+ array(
|
|
|
+ 'search_api_execute_pending_tasks_batch',
|
|
|
+ array(
|
|
|
+ $server,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ 'finished' => 'search_api_execute_pending_tasks_finished'
|
|
|
+ ));
|
|
|
+ if ($server) {
|
|
|
+ $path = 'admin/config/search/search_api/server/' . $server->machine_name;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $path = 'admin/config/search/search_api';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (function_exists('drush_backend_batch_process')) {
|
|
|
+ drush_backend_batch_process();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ batch_process($path);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Executes pending server tasks as part of a batch operation.
|
|
|
+ */
|
|
|
+function search_api_execute_pending_tasks_batch(SearchApiServer $server = NULL, &$context) {
|
|
|
+ if (!isset($context['results']['total'])) {
|
|
|
+ $context['results']['total'] = search_api_server_tasks_count($server);
|
|
|
+ }
|
|
|
+ $total = $context['results']['total'];
|
|
|
+
|
|
|
+ search_api_server_tasks_check($server);
|
|
|
+
|
|
|
+ $remaining = search_api_server_tasks_count($server);
|
|
|
+ $executed = max($total - $remaining, 0);
|
|
|
+
|
|
|
+ $args['@remaining'] = $remaining;
|
|
|
+ $context['message'] = format_plural($executed, 'Successfully executed @count task, @remaining remaining.', 'Successfully executed @count tasks, @remaining remaining.', $args);
|
|
|
+ $context['finished'] = $executed / $total;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Batch finish callback for pending server tasks.
|
|
|
+ */
|
|
|
+function search_api_execute_pending_tasks_finished($success, $results, $operations) {
|
|
|
+ if ($success) {
|
|
|
+ // Clear the previous warning.
|
|
|
+ drupal_get_messages('warning');
|
|
|
+
|
|
|
+ // Alert user to the number of tasks executed.
|
|
|
+ drupal_set_message(format_plural($results['total'], 'Successfully executed @count task.', 'Successfully executed @count tasks.'));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the number of pending tasks.
|
|
|
+ *
|
|
|
+ * @param SearchApiServer|null $server
|
|
|
+ * (optional) The server for which tasks should be counted, or NULL to count
|
|
|
+ * for all enabled servers.
|
|
|
+ *
|
|
|
+ * @return int
|
|
|
+ * The number of pending tasks for the server, or in total.
|
|
|
+ */
|
|
|
+function search_api_server_tasks_count(SearchApiServer $server = NULL) {
|
|
|
+ $query = db_select('search_api_task', 't')
|
|
|
+ ->fields('t');
|
|
|
+
|
|
|
+ if ($server) {
|
|
|
+ $query->condition('server_id', $server->machine_name);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $query->join('search_api_server', 's', 's.machine_name = t.server_id');
|
|
|
+ $query->condition('s.enabled', 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $query->countQuery()->execute()->fetchField();
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Access callback: Checks whether a user can execute pending tasks.
|
|
|
+ *
|
|
|
+ * @param SearchApiServer|null $server
|
|
|
+ * (optional) The server for which tasks would be executed.
|
|
|
+ */
|
|
|
+function search_api_access_execute_tasks_batch(SearchApiServer $server = NULL) {
|
|
|
+ return user_access('administer search_api')
|
|
|
+ && search_api_server_tasks_count($server)
|
|
|
+ && (!$server || $server->enabled);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Adds an entry into a server's list of pending tasks.
|
|
|
*
|