363 lines
11 KiB
PHP
Raw Normal View History

2020-08-14 13:36:36 +02:00
<?php
/**
* @file
* Include file for revisioning.module; deals with all theming aspects.
*/
/**
* Implements hook_theme().
*
* Register the theme_hooks() available in this module, with their arguments
* and default values.
*/
function revisioning_theme() {
$theme = array();
$theme['revisioning_revisions_summary'] = array(
// Index in the $variables[] array when
// function theme_revisioning_revisions_summary($variables) gets called.
'render element' => 'form',
);
$theme['revisions_pending_block'] = array(
// Uses revisions-pending-block.tpl.php.
'template' => 'revisions-pending-block',
);
$theme['revisions_summary'] = array(
// Uses revisions-summary.tpl.php.
'template' => 'revisions-summary',
);
return $theme;
}
/**
* Return revisions summary table data.
*
* If the Diff modules is enabled, the
* object returned includes a column of checkboxes allowing the user to select
* two revisions for side-by-side comparison.
*
* @param array $form
* typically an empty array as passed in by drupal_get_form()
* @param array $form_state
* the form state
* @param int $extra
* parameters as passed into drupal_get_form(), see _theme_revisions_summary()
*
* @return array
* updated form containing all data to be themed
*/
function revisioning_revisions_summary($form, &$form_state, $extra) {
// #type=>'value' form field values will not appear in the HTML. Used here
// to pass the node id to theme_revisioning_revisions_summary().
// Or: $form_state['build_info']['args'][0]; ?
$nid = $extra;
$form['nid'] = array('#type' => 'value', '#value' => $nid);
$show_taxonomy_terms = module_exists('taxonomy') &&
variable_get('revisioning_show_taxonomy_terms', TRUE) && (count(taxonomy_get_vocabularies()) > 0);
$revisions = _revisioning_get_all_revisions_for_node($nid, $show_taxonomy_terms);
$revision_ids = array();
$published = FALSE;
foreach ($revisions as $revision) {
$vid = $revision->vid;
if ($vid == $revision->current) {
$title = $revision->title;
$published = $revision->status;
}
// No text next to check boxes (see below).
$revision_ids[$vid] = '';
$base_url = "node/$nid/revisions/$vid";
// First column: saved date + author.
$first_cell = t('Saved !date by !username',
array(
'!date' => l(format_date($revision->timestamp, 'short'), "$base_url/view"),
'!username' => theme('username', array('account' => $revision))))
. (empty($revision->log) ? '' : '<p class="revision-log">' . filter_xss($revision->log) . '</p>');
$form['info'][$vid] = array(
// Was: 'item', see [#1884696].
'#type' => 'markup',
'#markup' => $first_cell,
);
// Third & fourth columns: term (2nd column is handled below).
if (!empty($revision->tags)) {
$form['tags'][$vid] = array(
'#type' => 'item',
'#markup' => $revision->tags,
);
$has_tags = TRUE;
}
if (!empty($revision->term)) {
$form['term'][$vid] = array(
'#type' => 'item',
'#markup' => $revision->term,
);
$has_terms = TRUE;
}
$form['status'][$vid] = array(
'#type' => 'value',
'#value' => $revision->status,
);
}
// Close foreach ($revisions as $revision).
if (empty($has_tags)) {
unset($form['tags']);
}
if (empty($has_terms)) {
unset($form['term']);
}
revisioning_set_status_message(format_plural(count($revisions),
'%title is @publication_status. It has only one revision',
'%title is @publication_status. It has @count revisions.',
array(
'%title' => $title,
'@publication_status' => ($published ? t('published') : t('NOT published')),
)
));
if (count($revisions) >= 2 && module_exists('diff')) {
// Second column: check-boxes to select two revisions to compare
// The default selection is the top two check-boxes
$id1 = key($revision_ids);
next($revision_ids);
$id2 = key($revision_ids);
$form['tickbox'] = array(
'#type' => 'checkboxes',
'#options' => $revision_ids,
'#default_value' => array($id1, $id2),
'#required' => TRUE,
);
// Submit button.
$form['submit'] = array('#value' => t('Compare'), '#type' => 'submit');
}
return $form;
}
/**
* Validation for input form to select two revisions.
*
* @param array $form
* The form
* @param array $form_state
* the form state
*/
function revisioning_revisions_summary_validate($form, &$form_state) {
// Strip out all unchecked boxes.
$form_state['values']['tickbox'] = array_filter($form_state['values']['tickbox']);
$count = count($form_state['values']['tickbox']);
if ($count != 2) {
form_set_error('tickbox', t('Please select 2 revisions rather than @count', array('@count' => $count)));
}
}
/**
* Submit two selected revisions to Diff module.
*
* @param array $form
* The form
* @param array $form_state
* the form state
*/
function revisioning_revisions_summary_submit($form, &$form_state) {
$selected_vids = $form_state['values']['tickbox'];
$vid1 = key($selected_vids);
next($selected_vids);
$vid2 = key($selected_vids);
// Clear existing msgs.
drupal_get_messages();
revisioning_set_status_message(t('Comparing revision #!revision2 against revision #!revision1',
array('!revision2' => $vid2, '!revision1' => $vid1)));
$nid = $form_state['values']['nid'];
$form_state['redirect'] = "node/$nid/revisions/view/$vid2/$vid1";
}
/**
* Theme revision summary table.
*
* Theme the supplied form as a table, then prepend submenu links via
* revisions-summary.tpl.php
*
* Uses the following subthemes:
* o 'table_revisions', falling back to theme.inc/theme_table() if not defined
* o 'placeholder' (to display current revision status)
* o 'username'
* Uses the following style-classes (see revisioning.css)
* o 'table-revisions'
* o 'revision-current' and 'published'
* o 'revision-pending'
*
* @param array $variables
* The variables array
*
* @return string
* The rendered html
*/
function theme_revisioning_revisions_summary($variables) {
$form = $variables['form'];
if (!isset($form['nid'])) {
drupal_set_message(t('theme_revisioning_revisions_summary(): form does not contain nid - aborting.'), 'error');
return;
}
// Need node info, fortunately node_load() employs a cache so is efficient.
$node = node_load($form['nid']['#value']);
drupal_add_css(drupal_get_path('module', 'revisioning') . '/css/revisioning.css');
// Set up the table rows.
$rows = array();
$revision_ids = element_children($form['info']);
$show_diff = count($revision_ids) >= 2 && module_exists('diff');
// Set up the table header.
$header = array(t('Revision'));
if ($show_diff) {
$header[] = array('data' => drupal_render($form['submit']), 'class' => 'form-submit');
}
if (isset($form['tags'])) {
$header[] = t('Tags');
}
if (isset($form['term'])) {
$header[] = t('Terms');
}
$header[] = t('Status');
$is_initial_unpublished_draft = !$node->status && (count($revision_ids) == 1);
// From the $form columns create table $rows.
foreach ($revision_ids as $vid) {
$row = array();
// Column #1: Revision info.
$row[] = drupal_render($form['info'][$vid]);
// Column #2: Compare checkbox.
if ($show_diff) {
$row[] = array('data' => drupal_render($form['tickbox'][$vid]));
}
// Columns #3 & #4: Tags & Terms.
if (isset($form['tags'])) {
$row[] = filter_xss(drupal_render($form['tags'][$vid]));
}
if (isset($form['term'])) {
$row[] = filter_xss(drupal_render($form['term'][$vid]));
}
// Column #4: Publication status.
$is_current = ($vid == $node->vid);
$is_pending = ($vid > $node->vid) || $is_initial_unpublished_draft;
if ($is_pending) {
$status = array('data' => t('in draft/pending publication'));
}
else {
$status = array('data' => $is_current && $node->status ? drupal_placeholder(t('current revision (published)')) : t('archived'));
}
$row[] = $status;
// Apply CSS class.
$row_style = $is_current ? array('revision-current') : ($is_pending ? array('revision-pending') : array());
if ($is_current && $node->status == NODE_PUBLISHED) {
$row_style[] = 'published';
}
$rows[] = array('data' => $row, 'class' => $row_style);
}
// Render $header and $rows as a table.
$table_variables = array(
'header' => $header,
'rows' => $rows,
'attributes' => array('class' => array('table-revisions')),
);
$content = theme(array('table_revisions', 'table'), $table_variables);
// Prepend submenu links.
$submenu_links = _revisioning_generate_node_links_according_to_permissions($node);
// Combine submenu links and rendered table using a template (.tpl.php) file.
$template_variables = array(
'submenu_links' => $submenu_links,
'content' => $content,
);
$output = theme(array('revisions_summary'), $template_variables);
return $output . drupal_render_children($form);
}
/*
* Implement (in your own module) the function below if you want to override
* the way in which the Revisions table is constructed.
* If you do, don't forget to register this theme_hook() via <module>_theme()
* in a manner similar to revisioning_theme() in this file.
*
* @param $header
* @param $rows
* @return themed HTML, see for instance /includes/theme.inc/theme_table() and
* diff.module/theme_diff_table()
*
* @ingroup themeable
*
function theme_table_revisions($header, $rows) {
}
*/
/**
* Theme the revisions summary of the supplied node.
*
* @param object $node
* Node whose revisions to display
*
* @return array
* Render array
*
* @ingroup themeable
*/
function _revisioning_theme_revisions_summary($node) {
drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH);
return drupal_get_form('revisioning_revisions_summary', $node->nid);
}
/**
* Get link operations.
*
* Return an array of hyperlinks representing the operations the logged-in user
* is allowed to perform on the supplied node.
*
* @param object $node
* The node obkect
* @param int $link_type
* The type of link, e.g. MENU_IS_LOCAL_TASK, may affect the rendering via
* theme('menu_item_link'), if overridden (eg zen_theme_menu_item_link()).
*
* @return array
* array of themed hyperlinks
*/
function _revisioning_generate_node_links_according_to_permissions($node, $link_type = 0) {
$nid = $node->nid;
$themed_links = array();
if (!empty($node->revision_moderation)) {
if (_revisioning_access_node_revision('publish revisions', $node)) {
$themed_links[] = l(t('Publish'), "node/$nid/revisions/$node->vid/publish");
}
elseif (_revisioning_access_node_revision('unpublish current revision', $node)) {
$themed_links[] = l(t('Unpublish current revision'), "node/$nid/unpublish-current");
}
}
if (_revisioning_access_node_revision('delete archived revisions', $node)) {
$num_archived = revisioning_get_number_of_archived_revisions($node);
if ($num_archived > 0) {
$themed_links[] = l(t('Delete archived'), "node/$nid/revisions/delete-archived");
}
}
if (_revisioning_access_node_revision('delete node', $node)) {
// Avoiding format_plural see [#557050].
$text = (empty($node->revision_moderation) || $node->num_revisions == 1) ? t('Delete') : t('Delete all');
$themed_links[] = l($text, "node/$nid/delete");
}
return $themed_links;
}