search_api.drush.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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-enable'] = array(
  22. 'description' => 'Enable one or all disabled search_api indexes.',
  23. 'examples' => array(
  24. 'drush searchapi-enable' => dt('Enable all disabled indexes.'),
  25. 'drush sapi-en' => dt('Alias to enable all disabled indexes.'),
  26. 'drush sapi-en 1' => dt('Enable index with the ID !id.', array('!id' => 1)),
  27. ),
  28. 'arguments' => array(
  29. 'index_id' => dt('The numeric ID or machine name of an index to enable.'),
  30. ),
  31. 'aliases' => array('sapi-en'),
  32. );
  33. $items['search-api-disable'] = array(
  34. 'description' => 'Disable one or all enabled search_api indexes.',
  35. 'examples' => array(
  36. 'drush searchapi-disable' => dt('Disable all enabled indexes.'),
  37. 'drush sapi-dis' => dt('Alias to disable all enabled indexes.'),
  38. 'drush sapi-dis 1' => dt('Disable index with the ID !id.', array('!id' => 1)),
  39. ),
  40. 'arguments' => array(
  41. 'index_id' => dt('The numeric ID or machine name of an index to disable.'),
  42. ),
  43. 'aliases' => array('sapi-dis'),
  44. );
  45. $items['search-api-status'] = array(
  46. 'description' => 'Show the status of one or all search indexes.',
  47. 'examples' => array(
  48. 'drush searchapi-status' => dt('Show the status of all search indexes.'),
  49. 'drush sapi-s' => dt('Alias to show the status of all search indexes.'),
  50. 'drush sapi-s 1' => dt('Show the status of the search index with the ID !id.', array('!id' => 1)),
  51. 'drush sapi-s default_node_index' => dt('Show the status of the search index with the machine name !name.', array('!name' => 'default_node_index')),
  52. ),
  53. 'arguments' => array(
  54. 'index_id' => dt('The numeric ID or machine name of an index.'),
  55. ),
  56. 'aliases' => array('sapi-s'),
  57. );
  58. $items['search-api-index'] = array(
  59. 'description' => 'Index items for one or all enabled search_api indexes.',
  60. 'examples' => array(
  61. 'drush searchapi-index' => dt('Index items for all enabled indexes.'),
  62. 'drush sapi-i' => dt('Alias to index items for all enabled indexes.'),
  63. 'drush sapi-i 1' => dt('Index items for the index with the ID !id.', array('!id' => 1)),
  64. 'drush sapi-i default_node_index' => dt('Index items for the index with the machine name !name.', array('!name' => 'default_node_index')),
  65. '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)),
  66. '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)),
  67. ),
  68. 'arguments' => array(
  69. 'index_id' => dt('The numeric ID or machine name of an index.'),
  70. '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)."),
  71. '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."),
  72. ),
  73. 'aliases' => array('sapi-i'),
  74. );
  75. $items['search-api-reindex'] = array(
  76. 'description' => 'Force reindexing of one or all search indexes, without clearing existing index data.',
  77. 'examples' => array(
  78. 'drush searchapi-reindex' => dt('Schedule all search indexes for reindexing.'),
  79. 'drush sapi-r' => dt('Alias to schedule all search indexes for reindexing .'),
  80. 'drush sapi-r 1' => dt('Schedule the search index with the ID !id for re-indexing.', array('!id' => 1)),
  81. 'drush sapi-r default_node_index' => dt('Schedule the search index with the machine name !name for re-indexing.', array('!name' => 'default_node_index')),
  82. ),
  83. 'arguments' => array(
  84. 'index_id' => dt('The numeric ID or machine name of an index.'),
  85. ),
  86. 'aliases' => array('sapi-r'),
  87. );
  88. $items['search-api-clear'] = array(
  89. 'description' => 'Clear one or all search indexes and mark them for re-indexing.',
  90. 'examples' => array(
  91. 'drush searchapi-clear' => dt('Clear all search indexes.'),
  92. 'drush sapi-c' => dt('Alias to clear all search indexes.'),
  93. 'drush sapi-c 1' => dt('Clear the search index with the ID !id.', array('!id' => 1)),
  94. 'drush sapi-c default_node_index' => dt('Clear the search index with the machine name !name.', array('!name' => 'default_node_index')),
  95. ),
  96. 'arguments' => array(
  97. 'index_id' => dt('The numeric ID or machine name of an index.'),
  98. ),
  99. 'aliases' => array('sapi-c'),
  100. );
  101. return $items;
  102. }
  103. /**
  104. * List all search indexes.
  105. */
  106. function drush_search_api_list() {
  107. if (search_api_drush_static(__FUNCTION__)) {
  108. return;
  109. }
  110. // See search_api_list_indexes()
  111. $indexes = search_api_index_load_multiple(FALSE);
  112. if (empty($indexes)) {
  113. drush_print(dt('There are no indexes present.'));
  114. return;
  115. }
  116. $rows[] = array(
  117. dt('Id'),
  118. dt('Name'),
  119. dt('Index'),
  120. dt('Server'),
  121. dt('Type'),
  122. dt('Status'),
  123. dt('Limit'),
  124. );
  125. foreach ($indexes as $index) {
  126. $type = search_api_get_item_type_info($index->item_type);
  127. $type = isset($type['name']) ? $type['name'] : $index->item_type;
  128. $server = $index->server();
  129. $server = $server ? $server->name : '(' . t('none') . ')';
  130. $row = array(
  131. $index->id,
  132. $index->name,
  133. $index->machine_name,
  134. $server,
  135. $type,
  136. $index->enabled ? t('enabled') : t('disabled'),
  137. $index->options['cron_limit'],
  138. );
  139. $rows[] = $row;
  140. }
  141. drush_print_table($rows);
  142. }
  143. /**
  144. * Enable index(es).
  145. *
  146. * @param string|integer $index_id
  147. * The index name or id which should be enabled.
  148. */
  149. function drush_search_api_enable($index_id = NULL) {
  150. if (search_api_drush_static(__FUNCTION__)) {
  151. return;
  152. }
  153. $indexes = search_api_drush_get_index($index_id);
  154. if (empty($indexes)) {
  155. return;
  156. }
  157. foreach ($indexes as $index) {
  158. if (!$index->enabled) {
  159. drush_log(dt("Enabling index !index and queueing items for indexing.", array('!index' => $index->name)), 'notice');
  160. if (search_api_index_enable($index->id)) {
  161. drush_log(dt("The index !index was successfully enabled.", array('!index' => $index->name)), 'ok');
  162. }
  163. else {
  164. drush_log(dt("Error enabling index !index.", array('!index' => $index->name)), 'error');
  165. }
  166. }
  167. else {
  168. drush_log(dt("The index !index is already enabled.", array('!index' => $index->name)), 'error');
  169. }
  170. }
  171. }
  172. /**
  173. * Disable index(es).
  174. *
  175. * @param string|integer $index_id
  176. * The index name or id which should be disabled.
  177. */
  178. function drush_search_api_disable($index_id = NULL) {
  179. if (search_api_drush_static(__FUNCTION__)) {
  180. return;
  181. }
  182. $indexes = search_api_drush_get_index($index_id);
  183. if (empty($indexes)) {
  184. return;
  185. }
  186. foreach ($indexes as $index) {
  187. if ($index->enabled) {
  188. if (search_api_index_disable($index->id)) {
  189. drush_log(dt("The index !index was successfully disabled.", array('!index' => $index->name)), 'ok');
  190. }
  191. else {
  192. drush_log(dt("Error disabling index !index.", array('!index' => $index->name)), 'error');
  193. }
  194. }
  195. else {
  196. drush_log(dt("The index !index is already disabled.", array('!index' => $index->name)), 'error');
  197. }
  198. }
  199. }
  200. /**
  201. * Display index status.
  202. */
  203. function drush_search_api_status($index_id = NULL) {
  204. if (search_api_drush_static(__FUNCTION__)) {
  205. return;
  206. }
  207. $indexes = search_api_drush_get_index($index_id);
  208. if (empty($indexes)) {
  209. return;
  210. }
  211. // See search_api_index_status()
  212. $rows = array(array(
  213. dt('Id'),
  214. dt('Index'),
  215. dt('% Complete'),
  216. dt('Indexed'),
  217. dt('Total'),
  218. ));
  219. foreach ($indexes as $index) {
  220. $status = search_api_index_status($index);
  221. $complete = ($status['total'] > 0) ? 100 * round($status['indexed'] / $status['total'], 3) . '%' : '-';
  222. $row = array(
  223. $index->id,
  224. $index->name,
  225. $complete,
  226. $status['indexed'],
  227. $status['total'],
  228. );
  229. $rows[] = $row;
  230. }
  231. drush_print_table($rows);
  232. }
  233. /**
  234. * Index items.
  235. *
  236. * @param string|integer $index_id
  237. * The index name or id for which items should be indexed.
  238. * @param integer $limit
  239. * Maximum number of items to index.
  240. * @param integer $batch_size
  241. * Number of items to index per batch.
  242. */
  243. function drush_search_api_index($index_id = NULL, $limit = NULL, $batch_size = NULL) {
  244. if (search_api_drush_static(__FUNCTION__)) {
  245. return;
  246. }
  247. $indexes = search_api_drush_get_index($index_id);
  248. if (empty($indexes)) {
  249. return;
  250. }
  251. foreach ($indexes as $index) {
  252. // Get the number of remaing items to index.
  253. $datasource = $index->datasource();
  254. $index_status = $datasource->getIndexStatus($index);
  255. $remaining = $index_status['total'] - $index_status['indexed'];
  256. if ($remaining <= 0) {
  257. drush_log(dt("The index !index is up to date.", array('!index' => $index->name)), 'ok');
  258. continue;
  259. }
  260. // Get the number of items to index per batch run.
  261. if (!isset($batch_size)) {
  262. $batch_size = empty($index->options['cron_limit']) ? SEARCH_API_DEFAULT_CRON_LIMIT : $index->options['cron_limit'];
  263. }
  264. elseif ($batch_size <= 0) {
  265. $batch_size = $remaining;
  266. }
  267. // Get the number items to index.
  268. if (!isset($limit) || !is_int($limit += 0) || $limit <= 0) {
  269. $limit = $remaining;
  270. }
  271. 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');
  272. // Create the batch.
  273. if (!_search_api_batch_indexing_create($index, $batch_size, $limit, $remaining, TRUE)) {
  274. drush_log(dt("Couldn't create a batch, please check the batch size and limit parameters."), 'error');
  275. }
  276. else {
  277. // Launch the batch process.
  278. drush_backend_batch_process();
  279. }
  280. }
  281. }
  282. /**
  283. * Copy of formal_plural that works with drush as 't' may not be available.
  284. */
  285. function _search_api_drush_format_plural($count, $singular, $plural, array $args = array(), array $options = array()) {
  286. $args['@count'] = $count;
  287. if ($count == 1) {
  288. return dt($singular, $args, $options);
  289. }
  290. // Get the plural index through the gettext formula.
  291. $index = (function_exists('locale_get_plural')) ? locale_get_plural($count, isset($options['langcode']) ? $options['langcode'] : NULL) : -1;
  292. // If the index cannot be computed, use the plural as a fallback (which
  293. // allows for most flexiblity with the replaceable @count value).
  294. if ($index < 0) {
  295. return dt($plural, $args, $options);
  296. }
  297. else {
  298. switch ($index) {
  299. case "0":
  300. return dt($singular, $args, $options);
  301. case "1":
  302. return dt($plural, $args, $options);
  303. default:
  304. unset($args['@count']);
  305. $args['@count[' . $index . ']'] = $count;
  306. return dt(strtr($plural, array('@count' => '@count[' . $index . ']')), $args, $options);
  307. }
  308. }
  309. }
  310. /**
  311. * Mark for re-indexing.
  312. */
  313. function drush_search_api_reindex($index_id = NULL) {
  314. if (search_api_drush_static(__FUNCTION__)) {
  315. return;
  316. }
  317. $indexes = search_api_drush_get_index($index_id);
  318. if (empty($indexes)) {
  319. return;
  320. }
  321. // See search_api_index_reindex()
  322. foreach ($indexes as $index) {
  323. $index->reindex();
  324. drush_log(dt('!index was successfully marked for re-indexing.', array('!index' => $index->machine_name)), 'ok');
  325. }
  326. }
  327. /**
  328. * Clear an index.
  329. */
  330. function drush_search_api_clear($index_id = NULL) {
  331. if (search_api_drush_static(__FUNCTION__)) {
  332. return;
  333. }
  334. $indexes = search_api_drush_get_index($index_id);
  335. if (empty($indexes)) {
  336. return;
  337. }
  338. // See search_api_index_reindex()
  339. foreach ($indexes as $index) {
  340. $index->clear();
  341. drush_log(dt('!index was successfully cleared.', array('!index' => $index->machine_name)), 'ok');
  342. }
  343. }
  344. /**
  345. * Helper function to return an index or all indexes as an array.
  346. *
  347. * @param $index_id
  348. * (optional) The provided index id.
  349. *
  350. * @return
  351. * An array of indexes.
  352. */
  353. function search_api_drush_get_index($index_id = NULL) {
  354. $ids = isset($index_id) ? array($index_id) : FALSE;
  355. $indexes = search_api_index_load_multiple($ids);
  356. if (empty($indexes)) {
  357. drush_set_error(dt('Invalid index_id or no indexes present. Listing all indexes:'));
  358. drush_print();
  359. drush_search_api_list();
  360. }
  361. return $indexes;
  362. }
  363. /**
  364. * Static lookup to prevent Drush 4 from running twice.
  365. *
  366. * @see http://drupal.org/node/704848
  367. */
  368. function search_api_drush_static($function) {
  369. static $index = array();
  370. if (isset($index[$function])) {
  371. return TRUE;
  372. }
  373. $index[$function] = TRUE;
  374. }