search_api.drush.inc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <?php
  2. /**
  3. * @file
  4. * Drush commands for SearchAPI.
  5. *
  6. * Original file by agentrickard for Palantir.net
  7. */
  8. /**
  9. * Implements hook_drush_command().
  10. */
  11. function search_api_drush_command() {
  12. $items = array();
  13. $items['search-api-list'] = array(
  14. 'description' => 'List all search indexes.',
  15. 'examples' => array(
  16. 'drush searchapi-list' => dt('List all search indexes.'),
  17. 'drush sapi-l' => dt('Alias to list all search indexes.'),
  18. ),
  19. 'aliases' => array('sapi-l'),
  20. );
  21. $items['search-api-status'] = array(
  22. 'description' => 'Show the status of one or all search indexes.',
  23. 'examples' => array(
  24. 'drush searchapi-status' => dt('Show the status of all search indexes.'),
  25. 'drush sapi-s' => dt('Alias to show the status of all search indexes.'),
  26. 'drush sapi-s 1' => dt('Show the status of the search index with the ID !id.', array('!id' => 1)),
  27. 'drush sapi-s default_node_index' => dt('Show the status of the search index with the machine name !name.', array('!name' => 'default_node_index')),
  28. ),
  29. 'arguments' => array(
  30. 'index_id' => dt('The numeric ID or machine name of an index.'),
  31. ),
  32. 'aliases' => array('sapi-s'),
  33. );
  34. $items['search-api-index'] = array(
  35. 'description' => 'Index items for one or all enabled search_api indexes.',
  36. 'examples' => array(
  37. 'drush searchapi-index' => dt('Index items for all enabled indexes.'),
  38. 'drush sapi-i' => dt('Alias to index items for all enabled indexes.'),
  39. 'drush sapi-i 1' => dt('Index items for the index with the ID !id.', array('!id' => 1)),
  40. 'drush sapi-i default_node_index' => dt('Index items for the index with the machine name !name.', array('!name' => 'default_node_index')),
  41. 'drush sapi-i 1 100' => dt("Index a maximum number of !limit items (index's cron batch size items per batch run) for the index with the ID !id.", array('!limit' => 100, '!id' => 1)),
  42. 'drush sapi-i 1 100 10' => dt("Index a maximum number of !limit items (!batch_size items per batch run) for the index with the ID !id.", array('!limit' => 100, '!batch_size' => 10, '!id' => 1)),
  43. ),
  44. 'arguments' => array(
  45. 'index_id' => dt('The numeric ID or machine name of an index.'),
  46. 'limit' => dt("The number of items to index (index's cron batch size items per run). Set to 0 to index all items. Defaults to 0 (index all)."),
  47. 'batch_size' => dt("The number of items to index per batch run. Set to 0 to index all items at once. Defaults to the index's cron batch size."),
  48. ),
  49. 'aliases' => array('sapi-i'),
  50. );
  51. $items['search-api-reindex'] = array(
  52. 'description' => 'Force reindexing of one or all search indexes, without clearing existing index data.',
  53. 'examples' => array(
  54. 'drush searchapi-reindex' => dt('Schedule all search indexes for reindexing.'),
  55. 'drush sapi-r' => dt('Alias to schedule all search indexes for reindexing .'),
  56. 'drush sapi-r 1' => dt('Schedule the search index with the ID !id for re-indexing.', array('!id' => 1)),
  57. 'drush sapi-r default_node_index' => dt('Schedule the search index with the machine name !name for re-indexing.', array('!name' => 'default_node_index')),
  58. ),
  59. 'arguments' => array(
  60. 'index_id' => dt('The numeric ID or machine name of an index.'),
  61. ),
  62. 'aliases' => array('sapi-r'),
  63. );
  64. $items['search-api-clear'] = array(
  65. 'description' => 'Clear one or all search indexes and mark them for re-indexing.',
  66. 'examples' => array(
  67. 'drush searchapi-clear' => dt('Clear all search indexes.'),
  68. 'drush sapi-c' => dt('Alias to clear all search indexes.'),
  69. 'drush sapi-r 1' => dt('Clear the search index with the ID !id.', array('!id' => 1)),
  70. 'drush sapi-r default_node_index' => dt('Clear the search index with the machine name !name.', array('!name' => 'default_node_index')),
  71. ),
  72. 'arguments' => array(
  73. 'index_id' => dt('The numeric ID or machine name of an index.'),
  74. ),
  75. 'aliases' => array('sapi-c'),
  76. );
  77. return $items;
  78. }
  79. /**
  80. * List all search indexes.
  81. */
  82. function drush_search_api_list() {
  83. if (search_api_drush_static(__FUNCTION__)) {
  84. return;
  85. }
  86. // See search_api_list_indexes()
  87. $indexes = search_api_index_load_multiple(FALSE);
  88. if (empty($indexes)) {
  89. drush_print(dt('There are no indexes present.'));
  90. return;
  91. }
  92. $rows[] = array(
  93. dt('Id'),
  94. dt('Name'),
  95. dt('Index'),
  96. dt('Server'),
  97. dt('Type'),
  98. dt('Status'),
  99. dt('Limit'),
  100. );
  101. foreach ($indexes as $index) {
  102. $type = search_api_get_item_type_info($index->item_type);
  103. $type = isset($type['name']) ? $type['name'] : $index->item_type;
  104. $server = $index->server();
  105. $server = $server ? $server->name : '(' . t('none') . ')';
  106. $row = array(
  107. $index->id,
  108. $index->name,
  109. $index->machine_name,
  110. $server,
  111. $type,
  112. $index->enabled ? t('enabled') : t('disabled'),
  113. $index->options['cron_limit'],
  114. );
  115. $rows[] = $row;
  116. }
  117. drush_print_table($rows);
  118. }
  119. /**
  120. * Display index status.
  121. */
  122. function drush_search_api_status($index_id = NULL) {
  123. if (search_api_drush_static(__FUNCTION__)) {
  124. return;
  125. }
  126. $indexes = search_api_drush_get_index($index_id);
  127. if (empty($indexes)) {
  128. return;
  129. }
  130. // See search_api_index_status()
  131. $rows = array(array(
  132. dt('Id'),
  133. dt('Index'),
  134. dt('% Complete'),
  135. dt('Indexed'),
  136. dt('Total'),
  137. ));
  138. foreach ($indexes as $index) {
  139. $status = search_api_index_status($index);
  140. $complete = ($status['total'] > 0) ? 100 * round($status['indexed'] / $status['total'], 3) . '%' : '-';
  141. $row = array(
  142. $index->id,
  143. $index->name,
  144. $complete,
  145. $status['indexed'],
  146. $status['total'],
  147. );
  148. $rows[] = $row;
  149. }
  150. drush_print_table($rows);
  151. }
  152. /**
  153. * Index items.
  154. *
  155. * @param string|integer $index_id
  156. * The index name or id for which items should be indexed.
  157. * @param integer $limit
  158. * Maximum number of items to index.
  159. * @param integer $batch_size
  160. * Number of items to index per batch.
  161. */
  162. function drush_search_api_index($index_id = NULL, $limit = NULL, $batch_size = NULL) {
  163. if (search_api_drush_static(__FUNCTION__)) {
  164. return;
  165. }
  166. $indexes = search_api_drush_get_index($index_id);
  167. if (empty($indexes)) {
  168. return;
  169. }
  170. foreach ($indexes as $index) {
  171. // Get the number of remaing items to index.
  172. $datasource = $index->datasource();
  173. $index_status = $datasource->getIndexStatus($index);
  174. $remaining = $index_status['total'] - $index_status['indexed'];
  175. // Get the number of items to index per batch run.
  176. if (!isset($batch_size)) {
  177. $batch_size = empty($index->options['cron_limit']) ? SEARCH_API_DEFAULT_CRON_LIMIT : $index->options['cron_limit'];
  178. }
  179. elseif ($batch_size <= 0) {
  180. $batch_size = $remaining;
  181. }
  182. // Get the number items to index.
  183. if (!isset($limit) || !is_int($limit += 0) || $limit <= 0) {
  184. $limit = $remaining;
  185. }
  186. drush_log(dt("Indexing a maximum number of !limit items (!batch_size items per batch run) for the index !index.", array('!index' => $index->name, '!limit' => $limit, '!batch_size' => $batch_size)), 'ok');
  187. // Create the batch.
  188. if (!_search_api_batch_indexing_create($index, $batch_size, $limit, $remaining, TRUE)) {
  189. drush_log(dt("Couldn't create a batch, please check the batch size and limit parameters."), 'error');
  190. }
  191. else {
  192. // Launch the batch process.
  193. drush_backend_batch_process();
  194. }
  195. }
  196. }
  197. /**
  198. * Copy of formal_plural that works with drush as 't' may not be available.
  199. */
  200. function _search_api_drush_format_plural($count, $singular, $plural, array $args = array(), array $options = array()) {
  201. $args['@count'] = $count;
  202. if ($count == 1) {
  203. return dt($singular, $args, $options);
  204. }
  205. // Get the plural index through the gettext formula.
  206. $index = (function_exists('locale_get_plural')) ? locale_get_plural($count, isset($options['langcode']) ? $options['langcode'] : NULL) : -1;
  207. // If the index cannot be computed, use the plural as a fallback (which
  208. // allows for most flexiblity with the replaceable @count value).
  209. if ($index < 0) {
  210. return dt($plural, $args, $options);
  211. }
  212. else {
  213. switch ($index) {
  214. case "0":
  215. return dt($singular, $args, $options);
  216. case "1":
  217. return dt($plural, $args, $options);
  218. default:
  219. unset($args['@count']);
  220. $args['@count[' . $index . ']'] = $count;
  221. return dt(strtr($plural, array('@count' => '@count[' . $index . ']')), $args, $options);
  222. }
  223. }
  224. }
  225. /**
  226. * Mark for re-indexing.
  227. */
  228. function drush_search_api_reindex($index_id = NULL) {
  229. if (search_api_drush_static(__FUNCTION__)) {
  230. return;
  231. }
  232. $indexes = search_api_drush_get_index($index_id);
  233. if (empty($indexes)) {
  234. return;
  235. }
  236. // See search_api_index_reindex()
  237. foreach ($indexes as $index) {
  238. $index->reindex();
  239. drush_log(dt('!index was successfully marked for re-indexing.', array('!index' => $index->machine_name)), 'ok');
  240. }
  241. }
  242. /**
  243. * Clear an index.
  244. */
  245. function drush_search_api_clear($index_id = NULL) {
  246. if (search_api_drush_static(__FUNCTION__)) {
  247. return;
  248. }
  249. $indexes = search_api_drush_get_index($index_id);
  250. if (empty($indexes)) {
  251. return;
  252. }
  253. // See search_api_index_reindex()
  254. foreach ($indexes as $index) {
  255. $index->clear();
  256. drush_log(dt('!index was successfully cleared.', array('!index' => $index->machine_name)), 'ok');
  257. }
  258. }
  259. /**
  260. * Helper function to return an index or all indexes as an array.
  261. *
  262. * @param $index_id
  263. * (optional) The provided index id.
  264. *
  265. * @return
  266. * An array of indexes.
  267. */
  268. function search_api_drush_get_index($index_id = NULL) {
  269. $ids = isset($index_id) ? array($index_id) : FALSE;
  270. $indexes = search_api_index_load_multiple($ids);
  271. if (empty($indexes)) {
  272. drush_set_error(dt('Invalid index_id or no indexes present. Listing all indexes:'));
  273. drush_print();
  274. drush_search_api_list();
  275. }
  276. return $indexes;
  277. }
  278. /**
  279. * Static lookup to prevent Drush 4 from running twice.
  280. *
  281. * @see http://drupal.org/node/704848
  282. */
  283. function search_api_drush_static($function) {
  284. static $index = array();
  285. if (isset($index[$function])) {
  286. return TRUE;
  287. }
  288. $index[$function] = TRUE;
  289. }