diff --git plugins/access/view_revisions.inc plugins/access/view_revisions.inc
new file mode 100644
index 0000000..4694161
--- /dev/null
+++ plugins/access/view_revisions.inc
@@ -0,0 +1,80 @@
+ t("User can view revisions of the node"),
+ 'description' => t('Check if user can view revisions, i.e. check corresponding permissions and "view" node access.'),
+ 'callback' => 'revisioning_view_revisions_ctools_access_check',
+ 'default' => array('type' => 'view'),
+ 'summary' => 'revisioning_view_revisions_ctools_access_summary',
+ 'required context' => array(
+ new ctools_context_required(t('User'), 'user'),
+ new ctools_context_required(t('Node'), 'node'),
+ ),
+ );
+
+ return $args;
+}
+
+/**
+ * Check for access.
+ */
+function revisioning_view_revisions_ctools_access_check($conf, $context) {
+ // As far as I know there should always be a context at this point, but this
+ // is safe.
+ list($user_context, $node_context) = $context;
+ if (empty($node_context) || empty($node_context->data) || empty($node_context->data->type)) {
+ return FALSE;
+ }
+
+ if (empty($user_context) || empty($user_context->data)) {
+ return FALSE;
+ }
+
+ $node = &$node_context->data;
+ $user = &$user_context->data;
+
+ // 'View' access on node is required for all "view revisions" permissions.
+ if (!module_grants_node_access('view', $node, $user)) {
+ return FALSE;
+ }
+
+ $name = check_plain($node->type);
+
+ // Check 'view revisions of any $nodetype content' permission.
+ if (user_access('view revisions of any '. $name .' content', $user)) {
+ return TRUE;
+ }
+
+ // Check 'view revisions of own $nodetype content' permission, meaning
+ // 'view all revisions of $nodetype content I created the first draft of'.
+ if ($node->uid == $user->uid && user_access('view revisions of own '. $name .' content', $user)) {
+ return TRUE;
+ }
+
+ // Fall back to global 'view revisions' permission.
+ return user_access('view revisions', $user);
+}
+
+/**
+ * Provide a summary description based upon the checked node_access.
+ */
+function revisioning_view_revisions_ctools_access_summary($conf, $context) {
+ list($user_context, $node_context) = $context;
+ $replacement = array('@user' => $user_context->identifier, '@node' => $node_context->identifier);
+ return t('@user can view revisions of @node.', $replacement);
+}
diff --git plugins/content_types/revision_info/icon_node.png plugins/content_types/revision_info/icon_node.png
new file mode 100644
index 0000000..f0417cb
Binary files /dev/null and plugins/content_types/revision_info/icon_node.png differ
diff --git plugins/content_types/revision_info/revision_info.inc plugins/content_types/revision_info/revision_info.inc
new file mode 100644
index 0000000..470e5d6
--- /dev/null
+++ plugins/content_types/revision_info/revision_info.inc
@@ -0,0 +1,77 @@
+ TRUE,
+ 'title' => t('Revision information'),
+ 'icon' => 'icon_node.png',
+ 'description' => t('Information about loaded revision of node context.'),
+ 'required context' => new ctools_context_required(t('Node'), 'node'),
+ 'category' => t('Revisioning'),
+ 'defaults' => array(
+ 'override_title' => FALSE,
+ 'override_title_text' => '',
+ 'teaser' => TRUE,
+ 'identifier' => '',
+ 'link' => TRUE,
+ ),
+ );
+}
+
+/**
+ * Output node revision information provided by Revisioning module.
+ */
+function revisioning_revision_info_content_type_render($subtype, $conf, $panel_args, $context) {
+ if (!empty($context) && empty($context->data)) {
+ return;
+ }
+ $node = isset($context->data) ? drupal_clone($context->data) : NULL;
+ $block = new stdClass();
+ $block->module = 'node';
+ $block->delta = $node->nid;
+
+ if (empty($node)) {
+ $block->delta = 'placeholder';
+ $block->subject = '';
+ $block->content = t('Node revision info.');
+ }
+ else {
+ $block->subject = t('Revision Information');
+ $block->content = _get_node_info_msg($node);
+ }
+ return $block;
+}
+
+/**
+ * Returns an edit form for the custom type.
+ */
+function revisioning_revision_info_content_type_edit_form(&$form, &$form_state) {
+ $conf = $form_state['conf'];
+ $form['link'] = array(
+ '#title' => t('Link title to node'),
+ '#type' => 'checkbox',
+ '#default_value' => $conf['link'],
+ '#description' => t('Check here to make the title link to the node.'),
+ );
+ return $form;
+}
+
+function revisioning_revision_info_content_type_edit_form_submit(&$form, &$form_state) {
+ // Copy everything from our defaults.
+ foreach (array_keys($form_state['plugin']['defaults']) as $key) {
+ $form_state['conf'][$key] = $form_state['values'][$key];
+ }
+}
+
+function revisioning_revision_info_content_type_admin_title($subtype, $conf, $context) {
+ return t('"@s" revision information', array('@s' => $context->identifier));
+}
diff --git plugins/tasks/node_revision_view.inc plugins/tasks/node_revision_view.inc
new file mode 100644
index 0000000..51aecef
--- /dev/null
+++ plugins/tasks/node_revision_view.inc
@@ -0,0 +1,108 @@
+ 'page',
+ 'title' => t('Node revision template'),
+ 'description' => t('The node revision view task allows you to control what handler will handle the job of rendering a node view at the path node/%node/revisions/%vid/view. If no handler is set or matches the criteria, the default Drupal node renderer will be used.'),
+ 'admin title' => 'Node revision view', // translated by menu system
+ 'admin description' => 'Overrides for the node revision view handler at node/%node/revisions/%vid/view.',
+ 'admin path' => 'node/%node/revisions/%vid/view',
+ 'hook menu alter' => 'revisioning_node_revision_view_menu_alter',
+
+ // This task uses 'context' handlers and must implement these to give the
+ // handler data it needs.
+ 'handler type' => 'context',
+ 'get arguments' => 'revisioning_node_revision_view_get_arguments',
+ 'get context placeholders' => 'revisioning_node_revision_view_get_contexts',
+ );
+}
+
+/**
+ * Callback defined by page_manager_node_view_page_manager_tasks().
+ *
+ * Alter the node view input so that node view comes to us rather than the
+ * normal node view process.
+ */
+function revisioning_node_revision_view_menu_alter(&$items, $task) {
+ if ($items['node/%node/revisions/%vid/view']['page callback'] == 'node_page_view') {
+ $items['node/%node/revisions/%vid/view']['page callback'] = 'revisioning_node_revision_view_task';
+ $items['node/%node/revisions/%vid/view']['file path'] = $task['path'];
+ $items['node/%node/revisions/%vid/view']['file'] = $task['file'];
+ }
+}
+
+/**
+ * Entry point for our overridden node view.
+ *
+ * This function asks its assigned handlers who, if anyone, would like
+ * to run with it. If no one does, it passes through to Drupal core's
+ * node view, which is node_page_view().
+ */
+function revisioning_node_revision_view_task($node) {
+ // Load my task plugin
+ $task = page_manager_get_task('node_revision_view');
+
+ // Load the node into a context.
+ ctools_include('context');
+ ctools_include('context-task-handler');
+ $contexts = ctools_context_handler_get_task_contexts($task, '', array($node));
+
+ $output = ctools_context_handler_render($task, '', $contexts, array($node->nid));
+ if ($output !== FALSE) {
+ node_tag_new($node->nid);
+ return $output;
+ }
+
+ $function = 'node_page_view';
+ foreach (module_implements('page_manager_override') as $module) {
+ $call = $module . '_page_manager_override';
+ if (($rc = $call('node_view')) && function_exists($rc)) {
+ $function = $rc;
+ break;
+ }
+ }
+
+ // Otherwise, fall back.
+ return $function($node);
+}
+
+/**
+ * Callback to get arguments provided by this task handler.
+ *
+ * Since this is the node view and there is no UI on the arguments, we
+ * create dummy arguments that contain the needed data.
+ */
+function revisioning_node_revision_view_get_arguments($task, $subtask_id) {
+ return array(
+ array(
+ 'keyword' => 'node',
+ 'identifier' => t('Node revision being viewed'),
+ 'id' => 1,
+ 'name' => 'nid',
+ 'settings' => array(),
+ ),
+ );
+}
+
+/**
+ * Callback to get context placeholders provided by this handler.
+ */
+function revisioning_node_revision_view_get_contexts($task, $subtask_id) {
+ return ctools_context_get_placeholders_from_argument(revisioning_node_revision_view_get_arguments($task, $subtask_id));
+}
diff --git revisioning.module revisioning.module
index ceec321..e9be00f 100755
--- revisioning.module
+++ revisioning.module
@@ -968,3 +968,13 @@ function revisioning_views_api() {
'path' => drupal_get_path('module', 'revisioning')
);
}
+
+/**
+ * Implementation of hook_ctools_plugin_directory().
+ */
+function revisioning_ctools_plugin_directory($module, $plugin) {
+ if (($module == 'ctools' && ($plugin == 'content_types' || $plugin == 'access'))
+ || ($module == 'page_manager' && $plugin == 'tasks')) {
+ return 'plugins/'. $plugin;
+ }
+}