checklistapi.pages.inc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <?php
  2. /**
  3. * @file
  4. * Page callbacks for the Checklist API module.
  5. */
  6. /**
  7. * Page callback: Form constructor for "Clear saved progress" confirmation form.
  8. *
  9. * @param string $id
  10. * The checklist ID.
  11. *
  12. * @see checklistapi_menu()
  13. *
  14. * @ingroup forms
  15. */
  16. function checklistapi_checklist_clear_confirm($form, &$form_state, $id) {
  17. $checklist = checklistapi_checklist_load($id);
  18. $form['#checklist'] = $checklist;
  19. return confirm_form(
  20. $form,
  21. t('Are you sure you want to clear %title saved progress?', array(
  22. '%title' => $checklist->title,
  23. )),
  24. $checklist->path,
  25. t('All progress details will be erased. This action cannot be undone.'),
  26. t('Clear'),
  27. t('Cancel')
  28. );
  29. }
  30. /**
  31. * Form submission handler for checklistapi_checklist_clear_confirm().
  32. */
  33. function checklistapi_checklist_clear_confirm_submit($form, &$form_state) {
  34. if ($form_state['values']['confirm']) {
  35. $form['#checklist']->clearSavedProgress();
  36. }
  37. $form_state['redirect'] = $form['#checklist']->path;
  38. }
  39. /**
  40. * Page callback: Form constructor for the checklist form.
  41. *
  42. * @param string $id
  43. * The checklist ID.
  44. *
  45. * @see checklistapi_checklist_form_submit()
  46. * @see checklistapi_menu()
  47. *
  48. * @ingroup forms
  49. */
  50. function checklistapi_checklist_form($form, &$form_state, $id) {
  51. $form['#checklist'] = $checklist = checklistapi_checklist_load($id);
  52. $form['progress_bar'] = array(
  53. '#type' => 'markup',
  54. '#markup' => theme('checklistapi_progress_bar', array(
  55. 'message' => ($checklist->hasSavedProgress()) ? t('Last updated @date by !user', array(
  56. '@date' => $checklist->getLastUpdatedDate(),
  57. '!user' => $checklist->getLastUpdatedUser(),
  58. )) : '&nbsp;',
  59. 'number_complete' => $checklist->getNumberCompleted(),
  60. 'number_of_items' => $checklist->getNumberOfItems(),
  61. 'percent_complete' => round($checklist->getPercentComplete()),
  62. )),
  63. );
  64. if (checklistapi_compact_mode()) {
  65. $form['#attributes']['class'] = array('compact-mode');
  66. }
  67. $form['compact_mode_link'] = array(
  68. '#markup' => theme('checklistapi_compact_link'),
  69. );
  70. $form['checklistapi'] = array(
  71. '#attached' => array(
  72. 'css' => array(drupal_get_path('module', 'checklistapi') . '/checklistapi.css'),
  73. 'js' => array(drupal_get_path('module', 'checklistapi') . '/checklistapi.js'),
  74. ),
  75. '#tree' => TRUE,
  76. '#type' => 'vertical_tabs',
  77. );
  78. // Loop through groups.
  79. $num_autochecked_items = 0;
  80. $groups = $checklist->items;
  81. foreach (element_children($groups) as $group_key) {
  82. $group = &$groups[$group_key];
  83. $form['checklistapi'][$group_key] = array(
  84. '#title' => filter_xss($group['#title']),
  85. '#type' => 'fieldset',
  86. );
  87. if (!empty($group['#description'])) {
  88. $form['checklistapi'][$group_key]['#description'] = filter_xss_admin($group['#description']);
  89. }
  90. // Loop through items.
  91. foreach (element_children($group) as $item_key) {
  92. $item = &$group[$item_key];
  93. $saved_item = !empty($checklist->savedProgress[$item_key]) ? $checklist->savedProgress[$item_key] : 0;
  94. // Build title.
  95. $title = filter_xss($item['#title']);
  96. if ($saved_item) {
  97. // Append completion details.
  98. $user = user_load($saved_item['#uid']);
  99. $title .= t(
  100. '<span class="completion-details"> - Completed @time by !user</a>',
  101. array(
  102. '@time' => format_date($saved_item['#completed'], 'short'),
  103. '!user' => theme('username', array('account' => $user)),
  104. )
  105. );
  106. }
  107. // Set default value.
  108. $default_value = FALSE;
  109. if ($saved_item) {
  110. $default_value = TRUE;
  111. }
  112. elseif (!empty($item['#default_value'])) {
  113. if ($default_value = $item['#default_value']) {
  114. $num_autochecked_items++;
  115. }
  116. }
  117. // Get description.
  118. $description = (isset($item['#description'])) ? '<p>' . filter_xss_admin($item['#description']) . '</p>' : '';
  119. // Append links.
  120. $links = array();
  121. foreach (element_children($item) as $link_key) {
  122. $link = &$item[$link_key];
  123. $options = (!empty($link['#options']) && is_array($link['#options'])) ? $link['#options'] : array();
  124. $links[] = l($link['#text'], $link['#path'], $options);
  125. }
  126. if (count($links)) {
  127. $description .= '<div class="links">' . implode(' | ', $links) . '</div>';
  128. }
  129. // Compile the list item.
  130. $form['checklistapi'][$group_key][$item_key] = array(
  131. '#attributes' => array('class' => array('checklistapi-item')),
  132. '#default_value' => $default_value,
  133. '#description' => filter_xss_admin($description),
  134. '#disabled' => !($user_has_edit_access = $checklist->userHasAccess('edit')),
  135. '#title' => filter_xss_admin($title),
  136. '#type' => 'checkbox',
  137. );
  138. }
  139. }
  140. $form['actions'] = array(
  141. '#access' => $user_has_edit_access,
  142. '#type' => 'actions',
  143. '#weight' => 100,
  144. 'save' => array(
  145. '#submit' => array('checklistapi_checklist_form_submit'),
  146. '#type' => 'submit',
  147. '#value' => t('Save'),
  148. ),
  149. 'clear' => array(
  150. '#access' => $checklist->hasSavedProgress(),
  151. '#href' => $checklist->path . '/clear',
  152. '#title' => t('Clear saved progress'),
  153. '#type' => 'link',
  154. ),
  155. );
  156. // Alert the user of autochecked items. Only set the message on GET requests
  157. // to prevent it from reappearing after saving the form. (Testing the request
  158. // method may not be the "correct" way to accomplish this.)
  159. if ($num_autochecked_items && $_SERVER['REQUEST_METHOD'] == 'GET') {
  160. drupal_set_message(t(
  161. format_plural(
  162. $num_autochecked_items,
  163. '%checklist found 1 unchecked item that was already completed and checked it for you. Save the form to record the change.',
  164. '%checklist found @num unchecked items that were already completed and checked them for you. Save the form to record the changes.'
  165. ),
  166. array(
  167. '%checklist' => $checklist->title,
  168. '@num' => $num_autochecked_items,
  169. )
  170. ), 'status');
  171. }
  172. return $form;
  173. }
  174. /**
  175. * Form submission handler for checklistapi_checklist_form().
  176. */
  177. function checklistapi_checklist_form_submit($form, &$form_state) {
  178. $form['#checklist']->saveProgress($form_state['values']['checklistapi']);
  179. }
  180. /**
  181. * Determines whether the current user is in compact mode.
  182. *
  183. * Compact mode shows checklist forms with less description text.
  184. *
  185. * Whether the user is in compact mode is determined by a cookie, which is set
  186. * for the user by checklistapi_compact_page().
  187. *
  188. * If the user does not have the cookie, the default value is given by the
  189. * system variable 'checklistapi_compact_mode', which itself defaults to FALSE.
  190. * This does not have a user interface to set it: it is a hidden variable which
  191. * can be set in the settings.php file.
  192. *
  193. * @return bool
  194. * TRUE when in compact mode, FALSE when in expanded mode.
  195. */
  196. function checklistapi_compact_mode() {
  197. return isset($_COOKIE['Drupal_visitor_checklistapi_compact_mode']) ? $_COOKIE['Drupal_visitor_checklistapi_compact_mode'] : variable_get('checklistapi_compact_mode', FALSE);
  198. }
  199. /**
  200. * Menu callback: Sets whether the admin menu is in compact mode or not.
  201. *
  202. * @param string $mode
  203. * Valid values are 'on' and 'off'.
  204. */
  205. function checklistapi_compact_page($mode = 'off') {
  206. user_cookie_save(array('checklistapi_compact_mode' => ($mode == 'on')));
  207. drupal_goto();
  208. }
  209. /**
  210. * Returns HTML for a link to show or hide inline item descriptions.
  211. *
  212. * @ingroup themeable
  213. */
  214. function theme_checklistapi_compact_link() {
  215. $output = '<div class="compact-link">';
  216. if (checklistapi_compact_mode()) {
  217. $output .= l(
  218. t('Show item descriptions'),
  219. current_path() . '/compact/off',
  220. array(
  221. 'attributes' => array(
  222. 'title' => t('Expand layout to include item descriptions.'),
  223. ),
  224. 'query' => drupal_get_destination(),
  225. )
  226. );
  227. }
  228. else {
  229. $output .= l(
  230. t('Hide item descriptions'),
  231. current_path() . '/compact/on',
  232. array(
  233. 'attributes' => array(
  234. 'title' => t('Compress layout by hiding item descriptions.'),
  235. ),
  236. 'query' => drupal_get_destination(),
  237. )
  238. );
  239. }
  240. $output .= '</div>';
  241. return $output;
  242. }