draggableviews.module 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. /**
  3. * Implements hook_views_api().
  4. */
  5. function draggableviews_views_api() {
  6. return array(
  7. 'api' => 3,
  8. 'path' => drupal_get_path('module', 'draggableviews') . '/views',
  9. );
  10. }
  11. /**
  12. * Implements hook_form_alter().
  13. *
  14. * Alter views form to change button label.
  15. */
  16. function draggableviews_form_alter(&$form, &$form_state, $form_id) {
  17. if (isset($form['draggableviews']) && !empty($form['draggableviews'])) {
  18. // Check permissions.
  19. if (!user_access('access draggableviews')) {
  20. $form['actions']['submit']['#access'] = FALSE;
  21. return;
  22. }
  23. $view = $form_state['build_info']['args'][0];
  24. $options = $view->field['draggableviews']->options['draggableviews'];
  25. $form['actions']['submit']['#value'] = t($options['save_button_label']);
  26. $form['actions']['submit']['#submit'] = array('draggableviews_views_submit');
  27. if ($options['ajax']) {
  28. $form['actions']['submit']['#ajax'] = array(
  29. 'callback' => 'draggableviews_view_draggabletable_form_ajax'
  30. );
  31. }
  32. // Set action as current path.
  33. global $language;
  34. $lang_code = $language->language;
  35. $my_base_path = base_path();
  36. if ($lang_code != 'en') {
  37. $my_base_path .= $lang_code . '/';
  38. }
  39. $form['#action'] = $my_base_path . current_path();
  40. // $form['#action'] = base_path() . current_path();
  41. }
  42. }
  43. /**
  44. * Save weight records after form submit.
  45. */
  46. function draggableviews_views_submit($form, &$form_state) {
  47. $view = $form_state['build_info']['args'][0];
  48. // Use 'input' instead of mapped 'values' here. This is done because if in
  49. // table display we sort by header then set weights and save, we got
  50. // totally wrong results ($form_state['values']['draggableviews'] mapped
  51. // wrong from $form_state['input']['draggableviews'])
  52. $form_state['values']['draggableviews'] = $form_state['input']['draggableviews'];
  53. // Set the weight.
  54. $handler_object = draggableviews_get_handler_class($view->field['draggableviews']->options['draggableviews']['handler']);
  55. $handler_object->set($form_state);
  56. // Trigger the event "A view has been sorted"
  57. if (module_exists('rules')) {
  58. rules_invoke_event('draggableviews_rules_event_sorted', $view->name, $view->current_display);
  59. }
  60. }
  61. /**
  62. * Implementes hook_preprocess_views_view_table().
  63. */
  64. function draggableviews_preprocess_views_view_table(&$vars) {
  65. // Check whether this table view has draggableview field.
  66. if (!isset($vars['view']->field['draggableviews'])) {
  67. return;
  68. }
  69. // Check permissions.
  70. if (!user_access('access draggableviews')) {
  71. return;
  72. }
  73. // Add table class.
  74. $vars['classes_array'][] = 'draggable';
  75. // Add row class.
  76. foreach ($vars['row_classes'] as &$row_classes) {
  77. $row_classes[] = 'draggable';
  78. }
  79. $vars['attributes_array']['id'] = 'draggableviews-table-' . $vars['view']->name . '-' . $vars['view']->current_display;
  80. // Add javascript.
  81. drupal_add_tabledrag($vars['attributes_array']['id'], 'order', 'sibling', 'draggableviews-weight');
  82. }
  83. /**
  84. * Implementes hook_preprocess_views_view_list().
  85. */
  86. function draggableviews_preprocess_views_view_list(&$vars) {
  87. // Check whether this table view has draggableview field.
  88. if (!isset($vars['view']->field['draggableviews'])) {
  89. return;
  90. }
  91. // Check permissions.
  92. if (!user_access('access draggableviews')) {
  93. return;
  94. }
  95. // Add class to ul item of the view.
  96. $class = 'draggableviews-grid-' . $vars['view']->name . '-' . $vars['view']->current_display;
  97. $vars['list_type_prefix'] = str_replace('>', ' class="' . $class . '">', $vars['list_type_prefix']);
  98. // Add javascript.
  99. drupal_add_library('system', 'ui.sortable');
  100. // Add setting of the row class.
  101. $js_setting = array('draggableviews_row_class' => $class);
  102. // Add setting whether ajax enabled or not.
  103. $js_setting['draggableviews_ajax'] = $vars['view']->field['draggableviews']->options['draggableviews']['ajax'];
  104. drupal_add_js($js_setting, 'setting');
  105. // Add custom js and css.
  106. drupal_add_js(drupal_get_path('module', 'draggableviews') . '/js/draggableviews_list.js');
  107. drupal_add_css(drupal_get_path('module', 'draggableviews') . '/css/draggableviews_list.css');
  108. }
  109. /**
  110. * Implements hook_permission().
  111. */
  112. function draggableviews_permission() {
  113. return array(
  114. 'access draggableviews' => array(
  115. 'title' => t('Access draggable views'),
  116. 'description' => t('Give users the right to sort their views'),
  117. ),
  118. );
  119. }
  120. /**
  121. * Implements hook_ctools_plugin_type().
  122. */
  123. function draggableviews_ctools_plugin_type() {
  124. return array(
  125. 'handler' => array(
  126. 'use hooks' => FALSE,
  127. ),
  128. );
  129. }
  130. /**
  131. * Implements hook_ctools_plugin_directory().
  132. */
  133. function draggableviews_ctools_plugin_directory($module, $plugin) {
  134. if (($module == 'draggableviews') && ($plugin == 'handler')) {
  135. return 'handlers';
  136. }
  137. }
  138. /**
  139. * Implements hook_contextual_links_view_alter().
  140. *
  141. * Adds "Order view" contextual link.
  142. */
  143. function draggableviews_contextual_links_view_alter(&$element, $items) {
  144. // Check permission to use draggable.
  145. if (!user_access('access draggableviews')) {
  146. return;
  147. }
  148. // Do not add contextual link on view preview.
  149. if (module_exists('views_ui') && views_ui_contextual_links_suppress()) {
  150. return;
  151. }
  152. // Add Draggableviews contextual link "Order view".
  153. if ( isset($element['#element']['#views_contextual_links_info']['views_ui']['view_display_id'])
  154. && !empty($element['#element']['#views_contextual_links_info']['views_ui']['view_display_id'])
  155. && isset($element['#element']['#views_contextual_links_info']['views_ui']['view'])) {
  156. $display_id = $element['#element']['#views_contextual_links_info']['views_ui']['view_display_id'];
  157. $view = $element['#element']['#views_contextual_links_info']['views_ui']['view'];
  158. $view->build($display_id);
  159. // Proceed only if there is draggableviews weight sort criteria available.
  160. if (!$sort_key = draggable_views_get_draggable_sort($view)) {
  161. return;
  162. }
  163. // Proceed only if order view is no self.
  164. $order_view_display = $view->sort[$sort_key]->options['draggableviews_setting_view'];
  165. if (empty($order_view_display) || $order_view_display == 'self') {
  166. return;
  167. }
  168. list($order_view_name, $order_view_display_id) = explode(':', $order_view_display);
  169. // Load order view and check its path.
  170. $order_view = views_get_view($order_view_name);
  171. if (isset($order_view->display[$order_view_display_id]->display_options['path'])) {
  172. $path = $order_view->display[$order_view_display_id]->display_options['path'];
  173. // If page expects arguments, we provide arguments set to current view.
  174. if (strpos($path, '%') !== FALSE && !empty($view->args)) {
  175. $placeholders = array();
  176. foreach (explode('/', $path) as $path_part) {
  177. if (strpos($path_part, '%') !== FALSE) {
  178. $placeholders[] = $path_part;
  179. }
  180. }
  181. $path = str_replace($placeholders, $view->args, $path);
  182. }
  183. $element['#links']['draggableviews-order'] = array(
  184. 'title' => t('Order view'),
  185. 'href' => $path,
  186. 'query' => array('destination' => current_path()),
  187. );
  188. }
  189. }
  190. }
  191. /**
  192. * Implements hook_views_post_execute().
  193. */
  194. function draggableviews_views_post_execute(&$view) {
  195. if (isset($view->field['draggableviews'])) {
  196. // Remove 'draggable' field if user has no access to sort a view.
  197. if (!user_access('access draggableviews')) {
  198. unset($view->field['draggableviews']);
  199. }
  200. else {
  201. // Move draggableviews field to last column
  202. // otherwise tabledrag.js doesn't work.
  203. $draggable_field = $view->field['draggableviews'];
  204. unset($view->field['draggableviews']);
  205. $view->field['draggableviews'] = $draggable_field;
  206. }
  207. }
  208. }
  209. /**
  210. * Get class of handler.
  211. *
  212. * @param object
  213. * Handler's class object.
  214. */
  215. function draggableviews_get_handler_class($handler_name) {
  216. $objects = &drupal_static(__FUNCTION__);
  217. if (!isset($objects[$handler_name])) {
  218. ctools_include('plugins');
  219. if ($class = ctools_plugin_load_class('draggableviews', 'handler', $handler_name, 'handler')) {
  220. $objects[$handler_name] = new $class();
  221. }
  222. }
  223. return $objects[$handler_name];
  224. }
  225. /**
  226. * Retrieve all plugins.
  227. *
  228. * Check whether handler class inherits draggablevies_handler.
  229. *
  230. * @return array
  231. * Array of proper draggableviews handlers.
  232. */
  233. function draggableviews_get_handlers() {
  234. ctools_include('plugins');
  235. $handlers = ctools_get_plugins('draggableviews', 'handler');
  236. $return = array();
  237. foreach ($handlers as $handler_id => $handler) {
  238. $handler_object = draggableviews_get_handler_class($handler_id);
  239. if (in_array('draggableviews_handler', class_parents(get_class($handler_object)))) {
  240. $return[$handler_id] = $handler_object;
  241. }
  242. }
  243. return $return;
  244. }
  245. /**
  246. * Ajax draggabletable submit handler.
  247. */
  248. function draggableviews_view_draggabletable_form_ajax($form, $form_state) {
  249. // Find the form element
  250. $form_element = "form:has(input[name=form_build_id][value='{$form['form_build_id']['#value']}'])";
  251. // Remove warning and asterisk.
  252. return array('#type' => 'ajax', '#commands' => array(
  253. ajax_command_remove("$form_element div.tabledrag-changed-warning"),
  254. ajax_command_remove("$form_element span.tabledrag-changed"),
  255. ajax_command_remove("$form_element div.draggableviews-changed-warning"),
  256. ajax_command_invoke("$form_element ul.draggableviews-changed", 'removeClass', array('draggableviews-changed')),
  257. ));
  258. }
  259. /**
  260. * Get the draggable views weight sort of a view if there is one and return its
  261. * ID. If there are multiple of these sorts the first is returned.
  262. *
  263. * @param $view
  264. * The view object.
  265. *
  266. * @return
  267. * The ID of the sort or FALSE if there isn't one.
  268. */
  269. function draggable_views_get_draggable_sort($view) {
  270. foreach ($view->sort as $id => $sort) {
  271. if ($sort->definition['handler'] == 'draggableviews_handler_sort') {
  272. return $id;
  273. }
  274. }
  275. return FALSE;
  276. }
  277. /**
  278. * Evalutes the given PHP code, with the given variables defined.
  279. *
  280. * @param $code
  281. * The PHP code to run, without <?php ?>
  282. * @param $arguments
  283. * Views arguments including values of exposed filters.
  284. *
  285. * @return
  286. * The return value of the evaled code.
  287. */
  288. function draggableviews_eval_return($code, $arguments) {
  289. return eval($code);
  290. }