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; + } +}