views_bulk_operations.rules.inc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. /**
  3. * @file
  4. * Views Bulk Operations conditions and actions for Rules.
  5. */
  6. /**
  7. * Implements hook_rules_condition_info().
  8. */
  9. function views_bulk_operations_rules_condition_info() {
  10. $conditions = array();
  11. $conditions['views_bulk_operations_condition_result_count'] = array(
  12. 'label' => t('Check number of results returned by a VBO View'),
  13. 'parameter' => array(
  14. 'view' => array(
  15. 'type' => 'text',
  16. 'label' => t('View and display'),
  17. 'options list' => 'views_bulk_operations_views_list',
  18. 'description' => t('Select the VBO view and display you want to check'),
  19. 'restriction' => 'input',
  20. ),
  21. 'args' => array(
  22. 'type' => 'text',
  23. 'label' => t('Arguments'),
  24. 'description' => t('Any arguments to pass to the view, one per line.
  25. You may use token replacement patterns.'),
  26. 'optional' => TRUE,
  27. ),
  28. 'minimum' => array(
  29. 'type' => 'integer',
  30. 'label' => t('Minimum number of results'),
  31. 'description' => t('This condition returns TRUE if the view has at
  32. least the given number of results.'),
  33. ),
  34. ),
  35. 'group' => t('Views Bulk Operations'),
  36. );
  37. return $conditions;
  38. }
  39. /**
  40. * Implements hook_rules_action_info().
  41. */
  42. function views_bulk_operations_rules_action_info() {
  43. $actions = array();
  44. $actions['views_bulk_operations_action_load_list'] = array(
  45. 'label' => t('Load a list of entity objects from a VBO View.'),
  46. 'parameter' => array(
  47. 'view' => array(
  48. 'type' => 'text',
  49. 'label' => t('View and display'),
  50. 'options list' => 'views_bulk_operations_views_list',
  51. 'description' => t('Select the view and display you want to use to
  52. create a list.'),
  53. 'restriction' => 'input',
  54. ),
  55. 'args' => array(
  56. 'type' => 'text',
  57. 'label' => t('Arguments'),
  58. 'description' => t('Any arguments to pass to the view, one per line.
  59. You may use token replacement patterns.'),
  60. 'optional' => TRUE,
  61. ),
  62. ),
  63. 'provides' => array(
  64. 'entity_list' => array(
  65. 'type' => 'list<entity>',
  66. 'label' => t('A list of entities'),
  67. ),
  68. ),
  69. 'group' => t('Views Bulk Operations'),
  70. );
  71. $actions['views_bulk_operations_action_load_id_list'] = array(
  72. 'label' => t('Load a list of entity ids from a VBO View.'),
  73. 'parameter' => array(
  74. 'view' => array(
  75. 'type' => 'text',
  76. 'label' => t('View and display'),
  77. 'options list' => 'views_bulk_operations_views_list',
  78. 'description' => t('Select the view and display you want to use to
  79. create a list.'),
  80. 'restriction' => 'input',
  81. ),
  82. 'args' => array(
  83. 'type' => 'text',
  84. 'label' => t('Arguments'),
  85. 'description' => t('Any arguments to pass to the view, one per line.
  86. You may use token replacement patterns.'),
  87. 'optional' => TRUE,
  88. ),
  89. ),
  90. 'provides' => array(
  91. 'entity_id_list' => array(
  92. 'type' => 'list<integer>',
  93. 'label' => t('A list of entity ids'),
  94. ),
  95. ),
  96. 'group' => t('Views Bulk Operations'),
  97. );
  98. return $actions;
  99. }
  100. /**
  101. * Lists all available VBO Views and their displays.
  102. * Naturally, only the displays that contain a VBO field are listed.
  103. *
  104. * @return array
  105. * An array of all views and their displays on the form 'view|display',
  106. * formatted to be used as an select list.
  107. */
  108. function views_bulk_operations_views_list() {
  109. $selectable_displays = array();
  110. foreach (views_get_enabled_views() as $name => $base_view) {
  111. $view = $base_view->clone_view();
  112. foreach ($base_view->display as $display_name => $display) {
  113. if (!$view->set_display($display_name)) {
  114. continue;
  115. }
  116. // Initialize the style plugin and only continue to initialize handlers
  117. // if the style uses fields.
  118. if (!$view->init_style() || !$view->style_plugin->uses_fields()) {
  119. continue;
  120. }
  121. $view->init_handlers($display_name);
  122. if (_views_bulk_operations_get_field($view)) {
  123. $selectable_displays[$view->name . '|' . $display_name] = check_plain($view->human_name . ' | ' . $display->display_title);
  124. }
  125. }
  126. }
  127. return $selectable_displays;
  128. }
  129. /**
  130. * The 'views_bulk_operations_condition_result_count' condition.
  131. *
  132. * @param $view
  133. * A string in the format "$view_name|$display_name".
  134. * @param $args
  135. * Arguments that should be passed to the View.
  136. * @param $minimum
  137. * An integer representing the minimum number of results that satisfies the
  138. * condition.
  139. *
  140. * @return
  141. * TRUE if the view has more than $minimum results, FALSE otherwise.
  142. */
  143. function views_bulk_operations_condition_result_count($view, $args, $minimum) {
  144. $vbo = _views_bulk_operations_rules_get_field($view, $args);
  145. return (count($vbo->view->result) >= $minimum);
  146. }
  147. /**
  148. * The 'views_bulk_operations_action_views_load_list' action.
  149. *
  150. * @param $view
  151. * A string in the format "$view_name|$display_name".
  152. * @param $args
  153. * Arguments that should be passed to the View.
  154. * @return array
  155. * Array containing the entity_list, an array of entity objects.
  156. * - array('entity_list' => array(...))
  157. */
  158. function views_bulk_operations_action_load_list($view, $args) {
  159. $vbo = _views_bulk_operations_rules_get_field($view, $args);
  160. // Get all entities, pass ids to the wrapper for lazy loading.
  161. $entity_type = $vbo->get_entity_type();
  162. $entities = entity_metadata_wrapper("list<$entity_type>", array());
  163. foreach ($vbo->view->result as $row_index => $result) {
  164. $entities[] = entity_metadata_wrapper($entity_type, $vbo->get_value($result));
  165. }
  166. return array('entity_list' => $entities);
  167. }
  168. /**
  169. * The 'views_bulk_operations_action_views_load_id_list' action.
  170. *
  171. * @param $view
  172. * A string in the format "$view_name|$display_name".
  173. * @param $args
  174. * Arguments that should be passed to the View.
  175. * @return array
  176. * Array containing the entity_id_list, an Array of entity ids as integer
  177. * values.
  178. * - array('entity_list' => array(...))
  179. */
  180. function views_bulk_operations_action_load_id_list($view, $args) {
  181. $vbo = _views_bulk_operations_rules_get_field($view, $args);
  182. // Get all entity ids.
  183. $ids = array();
  184. foreach ($vbo->view->result as $row_index => $result) {
  185. $ids[] = $vbo->get_value($result);
  186. }
  187. return array('entity_id_list' => $ids);
  188. }
  189. /**
  190. * Info alteration callback for the 'views_bulk_operations_action_views_load_list' action.
  191. *
  192. * The info hook specifies that the action returns a generic list of entities
  193. * (list<entity>). All actions that require entities of specific type can't
  194. * use such entities, so this alter hook specifies the exact entity type
  195. * after the action has been configured, allowing the view to be loaded
  196. * and its entity type extracted.
  197. */
  198. function views_bulk_operations_action_load_list_info_alter(&$element_info, RulesAbstractPlugin $element) {
  199. // The action hasn't been configured yet, hence no view. Abort.
  200. if (empty($element->settings['view'])) {
  201. return;
  202. }
  203. $entity_type = _views_bulk_operations_rules_get_entity_type($element->settings['view']);
  204. if ($entity_type) {
  205. $element_info['provides']['entity_list']['type'] = "list<$entity_type>";
  206. }
  207. }
  208. /**
  209. * Helper function that loads and builds (but doesn't execute) the specified view,
  210. * then determines the entity type on which the VBO field operates.
  211. *
  212. * @param $view_target
  213. * A string in the format "$view_name|$display_name".
  214. *
  215. * @return
  216. * The entity type on which the VBO field operates.
  217. */
  218. function _views_bulk_operations_rules_get_entity_type($view_target) {
  219. $entity_types = &drupal_static(__FUNCTION__);
  220. if (!isset($entity_types[$view_target])) {
  221. $views_settings = explode('|', $view_target);
  222. if ($view = views_get_view($views_settings[0])) {
  223. $view->set_display($views_settings[1]);
  224. $view->build();
  225. $vbo = _views_bulk_operations_get_field($view);
  226. }
  227. $entity_type = !empty($vbo) ? $vbo->get_entity_type() : '';
  228. $entity_types[$view_target] = $entity_type;
  229. }
  230. return $entity_types[$view_target];
  231. }
  232. /**
  233. * Helper function that loads, builds and executes the specified view,
  234. * then returns its VBO field.
  235. *
  236. * @param $view_target
  237. * A string in the format "$view_name|$display_name".
  238. * @param $args
  239. * Arguments that should be passed to the View.
  240. *
  241. * @return
  242. * The VBO field. Contains a reference to the View.
  243. */
  244. function _views_bulk_operations_rules_get_field($view_target, $args) {
  245. $views = &drupal_static(__FUNCTION__);
  246. $views_settings = explode('|', $view_target);
  247. $view_name = $views_settings[0];
  248. $display_name = $views_settings[1];
  249. // Create an array of arguments.
  250. $view_arguments = explode("\n", $args);
  251. $view_arguments = array_map('trim', $view_arguments);
  252. $view_arguments = array_filter($view_arguments, 'strlen');
  253. // Append the filtered list of arguments to $views_target, so that the correct
  254. // View is fetched from cache.
  255. if (!empty($view_arguments)) {
  256. $view_target .= '|' . implode('&', $view_arguments);
  257. }
  258. // Don't execute the requested View more than once in a single page request.
  259. if (isset($views[$view_target])) {
  260. $vbo = _views_bulk_operations_get_field($views[$view_target]);
  261. return $vbo;
  262. }
  263. // Load the view and set the properties.
  264. $view = views_get_view($view_name);
  265. $view->set_display($display_name);
  266. $view->set_arguments($view_arguments);
  267. $view->build();
  268. $vbo = _views_bulk_operations_get_field($view);
  269. // Unset every field except the VBO one (which holds the entity id).
  270. // That way the performance hit becomes much smaller, because there is no
  271. // chance of views_handler_field_field::post_execute() firing entity_load().
  272. foreach ($view->field as $field_name => $field) {
  273. if ($field_name != $vbo->options['id']) {
  274. unset($view->field[$field_name]);
  275. }
  276. }
  277. $view->execute($view->current_display);
  278. // Save the view in the static cache.
  279. $views[$view_target] = $view;
  280. return $vbo;
  281. }