1 | <?php |
---|
2 | |
---|
3 | /** |
---|
4 | * @file |
---|
5 | * Include file for revisioning.module; deals with all theming aspects. |
---|
6 | */ |
---|
7 | |
---|
8 | /** |
---|
9 | * Implementation of hook_theme(). |
---|
10 | * Register the theme_hooks() available in this module, with their arguments |
---|
11 | * and default values. |
---|
12 | */ |
---|
13 | function revisioning_theme() { |
---|
14 | return array( |
---|
15 | 'revisioning_revisions_summary' => array( |
---|
16 | 'arguments' => array('form' => array()), |
---|
17 | ), |
---|
18 | 'revisions_pending_block' => array( |
---|
19 | 'arguments' => array('content' => NULL), |
---|
20 | 'template' => 'revisions-pending-block', // revisions-pending-block.tpl.php |
---|
21 | ), |
---|
22 | 'revisions_summary' => array( |
---|
23 | 'arguments' => array('submenu_links' => NULL, 'content' => NULL), |
---|
24 | 'template' => 'revisions-summary', // revisions-summary.tpl.php |
---|
25 | ), |
---|
26 | ); |
---|
27 | } |
---|
28 | |
---|
29 | /** |
---|
30 | * Return revisions summary table data. If the Diff modules is enabled, the |
---|
31 | * object returned includes a column of checkboxes allowing the user to select |
---|
32 | * two revisions for side-by-side comparison. |
---|
33 | * |
---|
34 | * @param $form_state |
---|
35 | * @param $nid, the id of the node |
---|
36 | * @return form containing all data to be themed |
---|
37 | */ |
---|
38 | function revisioning_revisions_summary($form_state, $nid) { |
---|
39 | $form = array(); |
---|
40 | |
---|
41 | // #type=>'value' form field values will not appear in the HTML. Used to pass |
---|
42 | // the node id to revisioning_revisions_summary_submit() and |
---|
43 | // theme_revisioning_revisions_summary(). |
---|
44 | $form['nid'] = array('#type' => 'value', '#value' => $nid); |
---|
45 | |
---|
46 | $show_taxonomy_terms = module_exists('taxonomy') && |
---|
47 | (count(taxonomy_get_vocabularies()) > 0) && variable_get("show_taxonomy_terms", TRUE); |
---|
48 | |
---|
49 | $revisions = _revisioning_get_all_revisions_for_node($nid, $show_taxonomy_terms); |
---|
50 | |
---|
51 | $revision_ids = array(); |
---|
52 | foreach ($revisions as $revision) { |
---|
53 | if (!empty($revision->type)) { |
---|
54 | // This is the current revision, holding publication status and content type |
---|
55 | $content_type = $revision->type; |
---|
56 | $title = $revision->title; |
---|
57 | $published = $revision->status; |
---|
58 | } |
---|
59 | $vid = $revision->vid; |
---|
60 | $revision_ids[$vid] = ''; // no text next to check box |
---|
61 | $base_url = "node/$nid/revisions/$vid"; |
---|
62 | |
---|
63 | // First column: saved date + author |
---|
64 | $first_cell = t('Saved !date by !username', |
---|
65 | array('!date' => l(format_date($revision->timestamp, 'small'), "$base_url/view"), |
---|
66 | '!username' => theme('username', $revision))) |
---|
67 | . (empty($revision->log) ? '' : '<p class="revision-log">'. filter_xss($revision->log) .'</p>'); |
---|
68 | $form['info'][$vid] = array('#value' => $first_cell); |
---|
69 | |
---|
70 | // Third column: term (2nd column is handled below) |
---|
71 | if ($show_taxonomy_terms) { |
---|
72 | $form['term'][$vid] = array('#value' => $revision->term); |
---|
73 | } |
---|
74 | } |
---|
75 | drupal_set_message(format_plural(count($revisions), |
---|
76 | '@publication_status @content_type %title has only one revision', |
---|
77 | '@publication_status @content_type %title has @count revisions.', |
---|
78 | array( |
---|
79 | '@publication_status' => ($published ? t('Published') : t('Unpublished')), |
---|
80 | '@content_type' => $content_type, |
---|
81 | '%title' => $title, |
---|
82 | ) |
---|
83 | )); |
---|
84 | if (count($revisions) >= 2 && module_exists('diff')) { |
---|
85 | // Second column: check-boxes to select two revisions to compare |
---|
86 | $id1 = key($revision_ids); |
---|
87 | next($revision_ids); |
---|
88 | $id2 = key($revision_ids); |
---|
89 | $form['tickbox'] = array( |
---|
90 | '#type' => 'checkboxes', |
---|
91 | '#options' => $revision_ids, |
---|
92 | '#default_value' => array($id1, $id2), |
---|
93 | '#required' => TRUE, |
---|
94 | ); |
---|
95 | // Submit button |
---|
96 | $form['submit'] = array('#value' => t('Compare'), '#type' => 'submit'); |
---|
97 | } |
---|
98 | return $form; |
---|
99 | } |
---|
100 | |
---|
101 | /** |
---|
102 | * Validation for input form to select two revisions. |
---|
103 | * |
---|
104 | * @param $form |
---|
105 | * @param $form_state |
---|
106 | * @return void |
---|
107 | */ |
---|
108 | function revisioning_revisions_summary_validate($form, &$form_state) { |
---|
109 | // Strip out all unchecked boxes |
---|
110 | $form_state['values']['tickbox'] = array_filter($form_state['values']['tickbox']); |
---|
111 | $count = count($form_state['values']['tickbox']); |
---|
112 | if ($count != 2) { |
---|
113 | form_set_error('tickbox', t('Please select 2 revisions rather than !count', array('!count' => $count))); |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | /** |
---|
118 | * Submit two selected revisions to Diff module. |
---|
119 | * |
---|
120 | * @param $form |
---|
121 | * @param $form_state |
---|
122 | * @return void |
---|
123 | */ |
---|
124 | function revisioning_revisions_summary_submit($form, &$form_state) { |
---|
125 | $selected_vids = $form_state['values']['tickbox']; |
---|
126 | $vid1 = key($selected_vids); |
---|
127 | next($selected_vids); |
---|
128 | $vid2 = key($selected_vids); |
---|
129 | drupal_get_messages(); // clear existing msgs |
---|
130 | drupal_set_message( |
---|
131 | t('Comparing revision #!revision2 against revision #!revision1', |
---|
132 | array('!revision2' => $vid2, '!revision1' => $vid1))); |
---|
133 | $destination = ''; |
---|
134 | if (isset($_REQUEST['destination'])) { |
---|
135 | $destination = drupal_get_destination(); |
---|
136 | unset($_REQUEST['destination']); |
---|
137 | } |
---|
138 | $nid = $form_state['values']['nid']; |
---|
139 | $form_state['redirect'] = array("node/$nid/revisions/view/$vid2/$vid1", $destination); |
---|
140 | } |
---|
141 | |
---|
142 | /** |
---|
143 | * Theme the supplied form. |
---|
144 | * |
---|
145 | * Uses the following subthemes: |
---|
146 | * o 'table_revisions', falling back to theme.inc/theme_table() if not defined |
---|
147 | * o 'placeholder' (to display current revision status) |
---|
148 | * o 'username' |
---|
149 | * Uses the following style-classes (see revisioning.css) |
---|
150 | * o 'table-revisions' |
---|
151 | * o 'revision-current' and 'published' |
---|
152 | * o 'revision-pending' |
---|
153 | * @param $form |
---|
154 | * @return unknown_type |
---|
155 | */ |
---|
156 | function theme_revisioning_revisions_summary($form) { |
---|
157 | |
---|
158 | // Need node info, fortunately node_load() employs a cache so is efficient |
---|
159 | $node = node_load($form['nid']['#value']); |
---|
160 | |
---|
161 | $css_path = drupal_get_path('module', 'revisioning') .'/revisioning.css'; |
---|
162 | drupal_add_css($css_path, 'module', 'all', FALSE); |
---|
163 | |
---|
164 | // Set up the table rows |
---|
165 | $rows = array(); |
---|
166 | $revision_ids = element_children($form['info']); |
---|
167 | |
---|
168 | $show_diff = count($revision_ids) >= 2 && module_exists('diff'); |
---|
169 | $show_taxonomy_terms = module_exists('taxonomy') && |
---|
170 | (count(taxonomy_get_vocabularies()) > 0) && variable_get("show_taxonomy_terms", TRUE); |
---|
171 | |
---|
172 | // Set up the table header |
---|
173 | $header = array(t('Revision')); |
---|
174 | if ($show_diff) { |
---|
175 | $header[] = array('data' => drupal_render($form['submit']), 'class' => 'form-submit'); |
---|
176 | } |
---|
177 | if ($show_taxonomy_terms) { |
---|
178 | $header[] = t('Term'); |
---|
179 | } |
---|
180 | $header[] = t('Status'); |
---|
181 | |
---|
182 | $is_initial_unpublished_draft = !$node->status && (count($revision_ids) == 1); |
---|
183 | foreach ($revision_ids as $vid) { |
---|
184 | $row = array(); |
---|
185 | // Revision info |
---|
186 | $row[] = drupal_render($form['info'][$vid]); |
---|
187 | // Compare checkbox |
---|
188 | if ($show_diff) { |
---|
189 | $row[] = array('data' => drupal_render($form['tickbox'][$vid])); |
---|
190 | } |
---|
191 | // Term |
---|
192 | if ($show_taxonomy_terms) { |
---|
193 | $row[] = filter_xss(drupal_render($form['term'][$vid])); |
---|
194 | } |
---|
195 | // Publication status |
---|
196 | $is_current = ($vid == $node->vid); |
---|
197 | $is_pending = ($vid > $node->vid) || $is_initial_unpublished_draft; |
---|
198 | if ($is_pending) { |
---|
199 | $row[] = array('data' => t('in draft/pending publication')); |
---|
200 | } |
---|
201 | else { |
---|
202 | $row[] = array('data' => $is_current && $node->status ? theme('placeholder', t('current revision (published)')) : t('archived')); |
---|
203 | } |
---|
204 | // Apply css |
---|
205 | $row_style = $is_current ? 'revision-current' : ($is_pending ? 'revision-pending' : NULL); |
---|
206 | if ($is_current && $node->status) { |
---|
207 | $row_style .= ' published'; |
---|
208 | } |
---|
209 | $rows[] = array('data' => $row, 'class' => $row_style); |
---|
210 | } |
---|
211 | $attributes = array('class' => 'table-revisions'); |
---|
212 | $content = theme(array('table_revisions', 'table'), $header, $rows, $attributes, $caption = NULL); |
---|
213 | $submenu_links = _revisioning_generate_node_links_according_to_permissions($node); |
---|
214 | return theme(array('revisions_summary'), $submenu_links, $content) . drupal_render($form); |
---|
215 | } |
---|
216 | |
---|
217 | /** |
---|
218 | * Implement (in your own module) the function below if you want to override |
---|
219 | * the way in which the Revisions table is constructed. |
---|
220 | * If you do, don't forget to register this theme_hook() via <your_module>_theme() |
---|
221 | * in a manner similar to revisioning_theme() in this file. |
---|
222 | * |
---|
223 | * @param $header |
---|
224 | * @param $rows |
---|
225 | * @return themed HTML, see for instance /includes/theme.inc/theme_table() and |
---|
226 | * diff.module/theme_diff_table() |
---|
227 | * |
---|
228 | * @ingroup themeable |
---|
229 | * |
---|
230 | function theme_table_revisions($header, $rows) { |
---|
231 | } |
---|
232 | */ |
---|
233 | |
---|
234 | /** |
---|
235 | * Theme the revisions summary of the supplied node. |
---|
236 | * |
---|
237 | * @param $node |
---|
238 | * Node whose revisions to display |
---|
239 | * @return |
---|
240 | * Themed table HTML |
---|
241 | * |
---|
242 | * @ingroup themeable |
---|
243 | */ |
---|
244 | function _theme_revisions_summary(&$node) { |
---|
245 | drupal_set_title(t('Revisions for %title', array('%title' => $node->title))); |
---|
246 | return drupal_get_form('revisioning_revisions_summary', $node->nid); |
---|
247 | } |
---|
248 | |
---|
249 | function _theme_revisions_pending_block($nodes) { |
---|
250 | $max_num_shown = variable_get('revisioning_block_num_pending', 5); |
---|
251 | $nodes_to_display = array_slice($nodes, 0, $max_num_shown); |
---|
252 | $links = array(); |
---|
253 | foreach ($nodes_to_display as $node) { |
---|
254 | $vid = revisioning_get_latest_revision_id($node->nid); |
---|
255 | $links[] = l($node->title, "node/$node->nid/revisions/$vid/view"); |
---|
256 | } |
---|
257 | $css_path = drupal_get_path('module', 'revisioning') .'/revisioning.css'; |
---|
258 | drupal_add_css($css_path, 'module', 'all', FALSE); // also loads /revisioning-rtl.css |
---|
259 | $block = array(); |
---|
260 | $title_link = trim(variable_get('revisioning_content_summary_page', '')); |
---|
261 | if (empty($title_link)) { |
---|
262 | if (module_exists('module_grants_monitor') && user_tools_user_any_access(module_grants_monitor_perm())) { |
---|
263 | $title_link = 'accessible-content'; |
---|
264 | } |
---|
265 | else { |
---|
266 | $title_link = 'admin/content/node'; |
---|
267 | } |
---|
268 | } |
---|
269 | $block['subject'] = l(t('!num_revisions pending', |
---|
270 | array('!num_revisions' => format_plural(count($nodes), '1 revision', '@count revisions'))), |
---|
271 | $title_link); |
---|
272 | $block['content'] = theme('item_list', $links); |
---|
273 | return $block; |
---|
274 | } |
---|
275 | |
---|
276 | |
---|
277 | /** |
---|
278 | * Return an array of hyperlinks representing the operations the logged-in user |
---|
279 | * is allowed to perform on the supplied node. |
---|
280 | * |
---|
281 | * @param $node |
---|
282 | * @param $link_type |
---|
283 | * The type of link, e.g. MENU_IS_LOCAL_TASK, may affect the rendering via |
---|
284 | * theme('menu_item_link'), if overridden (eg zen_theme_menu_item_link()). |
---|
285 | * @return array of themed hyperlinks |
---|
286 | */ |
---|
287 | function _revisioning_generate_node_links_according_to_permissions($node, $link_type = 0) { |
---|
288 | $nid = $node->nid; |
---|
289 | $links = array(); |
---|
290 | if (_revisioning_node_revision_access('publish revisions', $node)) { |
---|
291 | $link['title'] = t('Publish'); |
---|
292 | $link['href'] = "node/$nid/revisions/$node->vid/publish"; |
---|
293 | //$link['localized_options']['query'] = drupal_get_destination(); |
---|
294 | $links[] = $link; |
---|
295 | } |
---|
296 | elseif (_revisioning_node_revision_access('unpublish current revision', $node)) { |
---|
297 | $link['title'] = t('Unpublish current revision'); |
---|
298 | $link['href'] = "node/$nid/unpublish"; |
---|
299 | //$link['localized_options']['query'] = drupal_get_destination(); |
---|
300 | $links[] = $link; |
---|
301 | } |
---|
302 | if (_revisioning_node_revision_access('delete archived revisions', $node)) { |
---|
303 | $num_archived = revisioning_get_number_of_archived_revisions($node); |
---|
304 | if ($num_archived > 0) { |
---|
305 | $link['title'] = t('Delete archived'); |
---|
306 | $link['href'] = "node/$nid/revisions/delete-archived"; |
---|
307 | $links[] = $link; |
---|
308 | } |
---|
309 | } |
---|
310 | if (_revisioning_node_revision_access('delete node', $node)) { |
---|
311 | $link['title'] = // avoiding format_plural [#557050] |
---|
312 | ($node->num_revisions == 1) |
---|
313 | ? t('Delete') |
---|
314 | : ($node->num_revisions == 2 ? t('Delete both revisions') : t('Delete all @count revisions', array('@count' => $node->num_revisions))); |
---|
315 | $link['href'] = "node/$nid/delete"; |
---|
316 | //$link['localized_options']['query'] = ''; |
---|
317 | $links[] = $link; |
---|
318 | } |
---|
319 | $themed_links = array(); |
---|
320 | foreach ($links as $link) { |
---|
321 | $link['type'] = $link_type; |
---|
322 | $themed_links[] = theme('menu_item_link', $link); |
---|
323 | } |
---|
324 | return $themed_links; |
---|
325 | } |
---|