views_bulk_operations.drush.inc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. /**
  3. * @file
  4. * Contains code providing drush commands functionality.
  5. */
  6. use Drupal\views\Views;
  7. use Drupal\views_bulk_operations\ViewsBulkOperationsBatch;
  8. /**
  9. * Implements hook_drush_command().
  10. */
  11. function views_bulk_operations_drush_command() {
  12. return [
  13. 'views-bulk-operations-execute' => [
  14. 'description' => 'Execute an action on all results of the given view.',
  15. 'aliases' => ['vbo-execute', 'vbo-exec'],
  16. 'arguments' => [
  17. 'view_id' => 'The ID of the view to use',
  18. 'action_id' => 'The ID of the action to execute',
  19. ],
  20. 'options' => [
  21. 'display-id' => 'ID of the display to use (default: default)',
  22. 'args' => 'View arguments (slash is a delimeter, default: none)',
  23. 'exposed' => 'Exposed filters (query string format)',
  24. 'batch-size' => 'Processing batch size (default: 100)',
  25. 'config' => 'Action configuration (query string format)',
  26. 'debug' => 'Include additional debugging information.',
  27. ],
  28. 'examples' => [
  29. 'drush vbo-execute some_view some_action --user=1' => 'Execute some action on some view as the superuser.',
  30. 'drush vbo-execute some_view some_action --args=arg1/arg2 --batch-size=50' => 'Execute some action on some view with arg1 and arg2 as view arguments and 50 entities processed per batch.',
  31. 'drush vbo-execute some_view some_action --config="key1=value1&key2=value2"' => 'Execute some action on some view with action configuration set.',
  32. ],
  33. ],
  34. ];
  35. }
  36. /**
  37. * Helper function to set / get timer.
  38. *
  39. * @param bool $debug
  40. * Should the function do anything at all?
  41. * @param string $id
  42. * ID of a specific timer span.
  43. *
  44. * @return mixed
  45. * NULL or value of a specific timer if set.
  46. */
  47. function _views_bulk_operations_timer($debug = TRUE, $id = NULL) {
  48. if (!$debug) {
  49. return;
  50. }
  51. static $timers = [];
  52. if (!isset($id)) {
  53. $timers['start'] = microtime(TRUE);
  54. }
  55. else {
  56. if (isset($timers[$id])) {
  57. end($timers);
  58. do {
  59. if (key($timers) === $id) {
  60. return round((current($timers) - prev($timers)) * 1000, 3);
  61. }
  62. else {
  63. $result = prev($timers);
  64. }
  65. } while ($result);
  66. }
  67. else {
  68. $timers[$id] = microtime(TRUE);
  69. }
  70. }
  71. }
  72. /**
  73. * The vbo-exec command executtion function.
  74. *
  75. * @param string $view_id
  76. * The ID of the view to use.
  77. * @param string $action_id
  78. * The ID of the action to execute.
  79. */
  80. function drush_views_bulk_operations_execute($view_id, $action_id) {
  81. $debug = drush_get_option('debug', FALSE);
  82. _views_bulk_operations_timer($debug);
  83. // Prepare parameters.
  84. $arguments = drush_get_option('args', FALSE);
  85. if ($arguments) {
  86. $arguments = explode('/', $arguments);
  87. }
  88. $qs_config = [
  89. 'config' => [],
  90. 'exposed' => [],
  91. ];
  92. foreach ($qs_config as $name => $value) {
  93. $config_data = drush_get_option($name, []);
  94. if (!empty($config_data)) {
  95. parse_str($config_data, $qs_config[$name]);
  96. }
  97. }
  98. $vbo_data = [
  99. 'list' => [],
  100. 'view_id' => $view_id,
  101. 'display_id' => drush_get_option('display-id', 'default'),
  102. 'action_id' => $action_id,
  103. 'preconfiguration' => $qs_config['config'],
  104. 'batch' => TRUE,
  105. 'arguments' => $arguments,
  106. 'exposed_input' => $qs_config['exposed'],
  107. 'batch_size' => drush_get_option('batch-size', 100),
  108. 'relationship_id' => 'none',
  109. ];
  110. // Initialize the view to check if parameters are correct.
  111. if (!$view = Views::getView($vbo_data['view_id'])) {
  112. drush_set_error('Incorrect view ID provided.');
  113. return;
  114. }
  115. if (!$view->setDisplay($vbo_data['display_id'])) {
  116. drush_set_error('Incorrect view display ID provided.');
  117. return;
  118. }
  119. if (!empty($vbo_data['arguments'])) {
  120. $view->setArguments($vbo_data['arguments']);
  121. }
  122. if (!empty($vbo_data['exposed_input'])) {
  123. $view->setExposedInput($vbo_data['exposed_input']);
  124. }
  125. // We need total rows count for proper progress message display.
  126. $view->get_total_rows = TRUE;
  127. $view->execute();
  128. // Get relationship ID if VBO field exists.
  129. $vbo_data['relationship_id'] = 'none';
  130. foreach ($view->field as $field) {
  131. if ($field->options['id'] === 'views_bulk_operations_bulk_form') {
  132. $vbo_data['relationship_id'] = $field->options['relationship'];
  133. }
  134. }
  135. // Get total rows count.
  136. $viewDataService = \Drupal::service('views_bulk_operations.data');
  137. $viewDataService->init($view, $view->getDisplay(), $vbo_data['relationship_id']);
  138. $vbo_data['total_results'] = $viewDataService->getTotalResults();
  139. // Get action definition and check if action ID is correct.
  140. try {
  141. $action_definition = \Drupal::service('plugin.manager.views_bulk_operations_action')->getDefinition($action_id);
  142. }
  143. catch (\Exception $e) {
  144. drush_set_error($e->getMessage());
  145. return;
  146. }
  147. $vbo_data['action_label'] = (string) $action_definition['label'];
  148. _views_bulk_operations_timer($debug, 'init');
  149. // Populate entity list.
  150. $context = [];
  151. do {
  152. $context['finished'] = 1;
  153. $context['message'] = '';
  154. ViewsBulkOperationsBatch::getList($vbo_data, $context);
  155. if (!empty($context['message'])) {
  156. drush_log($context['message'], 'ok');
  157. }
  158. } while ($context['finished'] < 1);
  159. $vbo_data = $context['results'];
  160. _views_bulk_operations_timer($debug, 'list');
  161. // Execute the selected action.
  162. $context = [];
  163. do {
  164. $context['finished'] = 1;
  165. $context['message'] = '';
  166. ViewsBulkOperationsBatch::operation($vbo_data, $context);
  167. if (!empty($context['message'])) {
  168. drush_log($context['message'], 'ok');
  169. }
  170. } while ($context['finished'] < 1);
  171. // Output a summary message.
  172. $operations = array_count_values($context['results']['operations']);
  173. $details = [];
  174. foreach ($operations as $op => $count) {
  175. $details[] = $op . ' (' . $count . ')';
  176. }
  177. drush_log(dt('Action processing results: @results.', ['@results' => implode(', ', $details)]), 'ok');
  178. // Display debug information.
  179. if ($debug) {
  180. _views_bulk_operations_timer($debug, 'execute');
  181. drush_print(sprintf('Initialization time: %d ms.', _views_bulk_operations_timer($debug, 'init')));
  182. drush_print(sprintf('Entity list generation time: %d ms.', _views_bulk_operations_timer($debug, 'list')));
  183. drush_print(sprintf('Execution time: %d ms.', _views_bulk_operations_timer($debug, 'execute')));
  184. }
  185. }