views_bulk_operations.rules.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. foreach ($base_view->display as $display_name => $display) {
  112. $view = $base_view->clone_view();
  113. $view->build($display_name);
  114. $vbo = _views_bulk_operations_get_field($view);
  115. if ($vbo) {
  116. $selectable_displays[$view->name . '|' . $display_name] = check_plain($view->human_name) . ' | ' . check_plain($display->display_title);
  117. }
  118. }
  119. }
  120. return $selectable_displays;
  121. }
  122. /**
  123. * The 'views_bulk_operations_condition_result_count' condition.
  124. *
  125. * @param $view
  126. * A string in the format "$view_name|$display_name".
  127. * @param $args
  128. * Arguments that should be passed to the View.
  129. * @param $minimum
  130. * An integer representing the minimum number of results that satisfies the
  131. * condition.
  132. *
  133. * @return
  134. * TRUE if the view has more than $minimum results, FALSE otherwise.
  135. */
  136. function views_bulk_operations_condition_result_count($view, $args, $minimum) {
  137. $vbo = _views_bulk_operations_rules_get_field($view, $args);
  138. return (count($vbo->view->result) >= $minimum);
  139. }
  140. /**
  141. * The 'views_bulk_operations_action_views_load_list' action.
  142. *
  143. * @param $view
  144. * A string in the format "$view_name|$display_name".
  145. * @param $args
  146. * Arguments that should be passed to the View.
  147. * @return array
  148. * Array containing the entity_list, an array of entity objects.
  149. * - array('entity_list' => array(...))
  150. */
  151. function views_bulk_operations_action_load_list($view, $args) {
  152. $vbo = _views_bulk_operations_rules_get_field($view, $args);
  153. // Get all entities, pass ids to the wrapper for lazy loading.
  154. $entity_type = $vbo->get_entity_type();
  155. $entities = entity_metadata_wrapper("list<$entity_type>", array());
  156. foreach ($vbo->view->result as $row_index => $result) {
  157. $entities[] = entity_metadata_wrapper($entity_type, $vbo->get_value($result));
  158. }
  159. return array('entity_list' => $entities);
  160. }
  161. /**
  162. * The 'views_bulk_operations_action_views_load_id_list' action.
  163. *
  164. * @param $view
  165. * A string in the format "$view_name|$display_name".
  166. * @param $args
  167. * Arguments that should be passed to the View.
  168. * @return array
  169. * Array containing the entity_id_list, an Array of entity ids as integer
  170. * values.
  171. * - array('entity_list' => array(...))
  172. */
  173. function views_bulk_operations_action_load_id_list($view, $args) {
  174. $vbo = _views_bulk_operations_rules_get_field($view, $args);
  175. // Get all entity ids.
  176. $ids = array();
  177. foreach ($vbo->view->result as $row_index => $result) {
  178. $ids[] = $vbo->get_value($result);
  179. }
  180. return array('entity_id_list' => $ids);
  181. }
  182. /**
  183. * Info alteration callback for the 'views_bulk_operations_action_views_load_list' action.
  184. *
  185. * The info hook specifies that the action returns a generic list of entities
  186. * (list<entity>). All actions that require entities of specific type can't
  187. * use such entities, so this alter hook specifies the exact entity type
  188. * after the action has been configured, allowing the view to be loaded
  189. * and its entity type extracted.
  190. */
  191. function views_bulk_operations_action_load_list_info_alter(&$element_info, RulesAbstractPlugin $element) {
  192. // The action hasn't been configured yet, hence no view. Abort.
  193. if (empty($element->settings['view'])) {
  194. return;
  195. }
  196. $entity_type = _views_bulk_operations_rules_get_entity_type($element->settings['view']);
  197. if ($entity_type) {
  198. $element_info['provides']['entity_list']['type'] = "list<$entity_type>";
  199. }
  200. }
  201. /**
  202. * Helper function that loads and builds (but doesn't execute) the specified view,
  203. * then determines the entity type on which the VBO field operates.
  204. *
  205. * @param $view_target
  206. * A string in the format "$view_name|$display_name".
  207. *
  208. * @return
  209. * The entity type on which the VBO field operates.
  210. */
  211. function _views_bulk_operations_rules_get_entity_type($view_target) {
  212. $entity_types = &drupal_static(__FUNCTION__);
  213. if (!isset($entity_types[$view_target])) {
  214. $views_settings = explode('|', $view_target);
  215. if ($view = views_get_view($views_settings[0])) {
  216. $view->set_display($views_settings[1]);
  217. $view->build();
  218. $vbo = _views_bulk_operations_get_field($view);
  219. }
  220. $entity_type = !empty($vbo) ? $vbo->get_entity_type() : '';
  221. $entity_types[$view_target] = $entity_type;
  222. }
  223. return $entity_types[$view_target];
  224. }
  225. /**
  226. * Helper function that loads, builds and executes the specified view,
  227. * then returns its VBO field.
  228. *
  229. * @param $view_target
  230. * A string in the format "$view_name|$display_name".
  231. * @param $args
  232. * Arguments that should be passed to the View.
  233. *
  234. * @return
  235. * The VBO field. Contains a reference to the View.
  236. */
  237. function _views_bulk_operations_rules_get_field($view_target, $args) {
  238. $views = &drupal_static(__FUNCTION__);
  239. $views_settings = explode('|', $view_target);
  240. $view_name = $views_settings[0];
  241. $display_name = $views_settings[1];
  242. // Create an array of arguments.
  243. $view_arguments = explode("\n", $args);
  244. $view_arguments = array_map('trim', $view_arguments);
  245. $view_arguments = array_filter($view_arguments, 'strlen');
  246. // Append the filtered list of arguments to $views_target, so that the correct
  247. // View is fetched from cache.
  248. if (!empty($view_arguments)) {
  249. $view_target .= '|' . implode('&', $view_arguments);
  250. }
  251. // Don't execute the requested View more than once in a single page request.
  252. if (isset($views[$view_target])) {
  253. $vbo = _views_bulk_operations_get_field($views[$view_target]);
  254. return $vbo;
  255. }
  256. // Load the view and set the properties.
  257. $view = views_get_view($view_name);
  258. $view->set_display($display_name);
  259. $view->set_arguments($view_arguments);
  260. $view->build();
  261. $vbo = _views_bulk_operations_get_field($view);
  262. // Unset every field except the VBO one (which holds the entity id).
  263. // That way the performance hit becomes much smaller, because there is no
  264. // chance of views_handler_field_field::post_execute() firing entity_load().
  265. foreach ($view->field as $field_name => $field) {
  266. if ($field_name != $vbo->options['id']) {
  267. unset($view->field[$field_name]);
  268. }
  269. }
  270. $view->execute($view->current_display);
  271. // Save the view in the static cache.
  272. $views[$view_target] = $view;
  273. return $vbo;
  274. }