rabbit_hole.module in Rabbit Hole 7
Same filename and directory in other branches
Main module file for Rabbit Hole.
This is a module that will prevent users from viewing the full node. This is configurable per content type or node.
File
rabbit_hole.moduleView source
<?php
/**
* @file
* Main module file for Rabbit Hole.
*
* This is a module that will prevent users from viewing the full node. This is
* configurable per content type or node.
*/
define('RABBIT_HOLE_USE_DEFAULT', -1);
define('RABBIT_HOLE_DISPLAY_CONTENT', 0);
define('RABBIT_HOLE_ACCESS_DENIED', 1);
define('RABBIT_HOLE_PAGE_NOT_FOUND', 2);
define('RABBIT_HOLE_PAGE_REDIRECT', 3);
define('RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT', 301);
/**
* Implements hook_permission().
*/
function rabbit_hole_permission() {
return array(
'administer rabbit hole' => array(
'title' => t('Administer Rabbit Hole'),
'description' => t('Configure Rabbit Hole per content type and node.'),
),
'bypass rabbit hole' => array(
'title' => t('Bypass Rabbit Hole'),
'description' => t('Ignore the Rabbit Hole configuration and view any node in a regular way.'),
),
);
}
/**
* Implements hook_form_FORM_ID_alter().
*
* This will add Rabbit Hole options to the node type form. These settings will
* be used as default for every node of this node type.
*/
function rabbit_hole_form_node_type_form_alter(&$form, $form_state) {
if (!user_access('administer rabbit hole')) {
// The user doesn't have access.
return;
}
if (isset($form['type'])) {
$form['rabbit_hole'] = array(
'#type' => 'fieldset',
'#title' => t('Rabbit Hole settings'),
'#collapsed' => TRUE,
'#collapsible' => TRUE,
'#group' => 'additional_settings',
'#attributes' => array(
'class' => array(
'rabbit-hole-settings-form',
),
),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'rabbit_hole') . '/rabbit-hole.js',
array(
'data' => array(
'rabbitHole' => array(
'redirectValue' => RABBIT_HOLE_PAGE_REDIRECT,
),
),
'type' => 'setting',
),
),
),
);
$form['rabbit_hole']['rabbit_hole_action'] = array(
'#type' => 'radios',
'#title' => t('Behavior'),
'#options' => array(
RABBIT_HOLE_DISPLAY_CONTENT => t('Display the content (regular behavior)'),
RABBIT_HOLE_ACCESS_DENIED => t('Access denied'),
RABBIT_HOLE_PAGE_NOT_FOUND => t('Page not found'),
RABBIT_HOLE_PAGE_REDIRECT => t('Page redirect'),
),
'#default_value' => variable_get('rabbit_hole_action_' . $form['#node_type']->type, RABBIT_HOLE_DISPLAY_CONTENT),
'#description' => t('What should happen when someone tries to visit the node page?'),
);
$form['rabbit_hole']['redirect'] = array(
'#type' => 'fieldset',
'#title' => t('Redirect settings'),
'#attributes' => array(
'class' => array(
'rabbit-hole-redirect-options',
),
),
);
$form['rabbit_hole']['redirect']['rabbit_hole_redirect'] = array(
'#type' => 'textfield',
'#title' => t('Redirect path'),
'#size' => 40,
'#default_value' => variable_get('rabbit_hole_redirect_' . $form['#node_type']->type, ''),
'#description' => t('The relative path to were the user should be redirected. Leave this empty, or use %front to redirect to the front page. You may enter tokens in this field.', array(
'%front' => '<front>',
)),
);
// Display a list of tokens if the Token module is enabled.
if (module_exists('token')) {
$form['rabbit_hole']['redirect']['token_info'] = array(
'#theme' => 'token_tree',
'#token_types' => array(
'node',
),
);
}
$form['rabbit_hole']['redirect']['rabbit_hole_redirect_response'] = array(
'#type' => 'select',
'#title' => t('Response code'),
'#options' => array(
301 => t('301 (Moved Permanently)'),
302 => t('302 (Found)'),
303 => t('303 (See other)'),
304 => t('304 (Not modified)'),
305 => t('305 (Use proxy)'),
307 => t('307 (Temporary redirect)'),
),
'#default_value' => variable_get('rabbit_hole_redirect_response_' . $form['#node_type']->type, RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT),
'#description' => t('The response code that should be sent to the users browser. Follow !link for more information on response codes.', array(
'!link' => l(t('this link'), 'http://api.drupal.org/api/drupal/includes--common.inc/function/drupal_goto/7'),
)),
);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* This will add Rabbit Hole options to the node form. The user will be able to
* override the default Rabbit Hole options.
*/
function rabbit_hole_form_node_form_alter(&$form, $form_state) {
if (!user_access('administer rabbit hole')) {
// The user doesn't have access.
return;
}
$node = $form['#node'];
$form['rabbit_hole'] = array(
'#type' => 'fieldset',
'#title' => t('Rabbit Hole settings'),
'#collapsed' => TRUE,
'#collapsible' => TRUE,
'#group' => 'additional_settings',
'#attributes' => array(
'class' => array(
'rabbit-hole-settings-form',
),
),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'rabbit_hole') . '/rabbit-hole.js',
array(
'data' => array(
'rabbitHole' => array(
'redirectValue' => RABBIT_HOLE_PAGE_REDIRECT,
),
),
'type' => 'setting',
),
),
),
);
$form['rabbit_hole']['rabbit_hole_action'] = array(
'#type' => 'radios',
'#title' => t('Behavior'),
'#options' => array(
RABBIT_HOLE_USE_DEFAULT => t('Content type default'),
RABBIT_HOLE_DISPLAY_CONTENT => t('Display the content (regular behavior)'),
RABBIT_HOLE_ACCESS_DENIED => t('Access denied'),
RABBIT_HOLE_PAGE_NOT_FOUND => t('Page not found'),
RABBIT_HOLE_PAGE_REDIRECT => t('Page redirect'),
),
'#default_value' => isset($node->rabbit_hole_action) ? $node->rabbit_hole_action : RABBIT_HOLE_USE_DEFAULT,
'#description' => t('What should happen when someone tries to visit the node page?'),
);
$form['rabbit_hole']['redirect'] = array(
'#type' => 'fieldset',
'#title' => t('Redirect settings'),
'#attributes' => array(
'class' => array(
'rabbit-hole-redirect-options',
),
),
);
$form['rabbit_hole']['redirect']['rabbit_hole_redirect'] = array(
'#type' => 'textfield',
'#title' => t('Redirect path'),
'#size' => 40,
'#default_value' => isset($node->rabbit_hole_redirect) ? $node->rabbit_hole_redirect : variable_get('rabbit_hole_redirect_' . $node->type, ''),
'#description' => t('The relative path to were the user should be redirected. Leave this empty, or use %front to redirect to the front page.', array(
'%front' => '<front>',
)),
);
// Display a list of tokens if the Token module is enabled.
if (module_exists('token')) {
$form['rabbit_hole']['redirect']['token_info'] = array(
'#theme' => 'token_tree',
'#token_types' => array(
'node',
),
);
}
$form['rabbit_hole']['redirect']['rabbit_hole_redirect_response'] = array(
'#type' => 'select',
'#title' => t('Response code'),
'#options' => array(
301 => t('301 (Moved Permanently)'),
302 => t('302 (Found)'),
303 => t('303 (See other)'),
304 => t('304 (Not modified)'),
305 => t('305 (Use proxy)'),
307 => t('307 (Temporary redirect)'),
),
'#default_value' => isset($node->rabbit_hole_redirect_response) ? $node->rabbit_hole_redirect_response : variable_get('rabbit_hole_redirect_response_' . $node->type, RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT),
'#description' => t('The response code that should be sent to the users browser, e.g. 301. Follow !link for more information on response codes.', array(
'!link' => l(t('this link'), 'http://api.drupal.org/api/drupal/includes--common.inc/function/drupal_goto/7'),
)),
);
// Add a custom submit function. This is used to disable the redirect to
// node/123 if Rabbit Hole is enabled.
$form['actions']['submit']['#submit'][] = 'rabbit_hole_node_form_submit';
}
/**
* Custom submit function for the node form.
*
* This will fire after the regular submit function, and it's purpose is to make
* sure that the user doesn't get redirected to node/123 after saving the node,
* if any Rabbit Hole action is enabled. This works by redirecting the user to
* node/123/edit, if a destination parameter hasn't been set.
*
* @see node_form_submit().
*/
function rabbit_hole_node_form_submit($form, &$form_state) {
// Get the action. Either the one specified for this node, or the default
// value for the content type.
$action = $form_state['values']['rabbit_hole_action'] != RABBIT_HOLE_USE_DEFAULT ? $form_state['values']['rabbit_hole_action'] : variable_get('rabbit_hole_action_' . $form_state['values']['type']);
// If the action says anything else than to display the content, make sure
// that the user doesn't land on the node view page. We'll check if a custom
// redirect path has been set, otherwise, we'll redirect the user to the edit
// page again.
if ($action != RABBIT_HOLE_DISPLAY_CONTENT && $form_state['redirect'] == 'node/' . $form_state['values']['nid']) {
$form_state['redirect'] = 'node/' . $form_state['values']['nid'] . '/edit';
}
}
/**
* Implements hook_node_view().
*/
function rabbit_hole_node_view($node, $view_mode, $langcode) {
if ($view_mode != 'full' || !preg_match('/node\\/' . $node->nid . '(\\/view|)$/', current_path()) || user_access('bypass rabbit hole')) {
// The node is not being viewed at it's own page, or the user is able to
// bypass Rabbit Hole, exit early.
return;
}
// Get the action. Use the one specified for this node, or fallback to the
// default value for the content type.
$action = isset($node->rabbit_hole_action) ? $node->rabbit_hole_action != RABBIT_HOLE_USE_DEFAULT ? $node->rabbit_hole_action : variable_get('rabbit_hole_action_' . $node->type) : variable_get('rabbit_hole_action_' . $node->type);
// If we should perform a redirect, we will also get the path and response.
if ($action == RABBIT_HOLE_PAGE_REDIRECT) {
if (isset($node->rabbit_hole_action) && $node->rabbit_hole_action != RABBIT_HOLE_USE_DEFAULT) {
// Get the redirect path and response from the node.
$redirect_path = token_replace($node->rabbit_hole_redirect, array(
'node' => $node,
));
$redirect_response = $node->rabbit_hole_redirect_response;
}
else {
// Get the redirect path and response from the content type.
$redirect_path = token_replace(variable_get('rabbit_hole_redirect_' . $node->type, '<front>'), array(
'node' => $node,
));
$redirect_response = variable_get('rabbit_hole_redirect_response_' . $node->type, RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT);
}
}
// Now, let's see what we should do.
switch ($action) {
case RABBIT_HOLE_ACCESS_DENIED:
// TODO: Is this the proper way to deliver an access denied page?
drupal_access_denied();
exit;
case RABBIT_HOLE_PAGE_NOT_FOUND:
// TODO: Is this the proper way to deliver a not found page?
drupal_not_found();
exit;
case RABBIT_HOLE_PAGE_REDIRECT:
// Redirect the user to the specified path.
drupal_goto($redirect_path, array(), $redirect_response);
}
}
/**
* Implements hook_node_type_delete().
*/
function rabbit_hole_node_type_delete($info) {
// Delete variables connected to this content type.
variable_del('rabbit_hole_action_' . $info->type);
variable_del('rabbit_hole_redirect_' . $info->type);
variable_del('rabbit_hole_redirect_response_' . $info->type);
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function rabbit_hole_menu_local_tasks_alter(&$data, $router_item, $root_path) {
$primary =& $data['tabs'][0];
if (!is_array($primary['output'])) {
// There are no tabs present, exit early.
return;
}
// Iterate through the primary tabs, and look for the View tab for nodes.
foreach ($primary['output'] as $delta => $element) {
if ($element['#link']['path'] == 'node/%/view') {
// Found the View tab, get the Rabbit Hole action for this node, and
// remove the tab if any Rabbit Hole action has been set.
$node = menu_get_object('node', 1, $router_item['tab_root_href']);
$action = isset($node->rabbit_hole_action) ? $node->rabbit_hole_action != RABBIT_HOLE_USE_DEFAULT ? $node->rabbit_hole_action : variable_get('rabbit_hole_action_' . $node->type) : variable_get('rabbit_hole_action_' . $node->type);
if ($action != RABBIT_HOLE_DISPLAY_CONTENT && !user_access('bypass rabbit hole')) {
unset($primary['output'][$delta]);
}
}
}
// Reset the count and keys for the existing tabs.
$primary['output'] = array_values($primary['output']);
$primary['count'] = count($primary['output']);
}
/**
* Implements template_preprocess_search_results().
*
* TODO: Alter the search results in another way. If there is another way.
*/
function rabbit_hole_preprocess_search_results(&$variables) {
$results =& $variables['results'];
// Iterate through the search results, and remove the nodes where Rabbit Hole
// is activated.
foreach ($results as $delta => $item) {
if (isset($item['node'])) {
$node = $item['node'];
$action = isset($node->rabbit_hole_action) ? $node->rabbit_hole_action != RABBIT_HOLE_USE_DEFAULT ? $node->rabbit_hole_action : variable_get('rabbit_hole_action_' . $node->type) : variable_get('rabbit_hole_action_' . $node->type);
if ($action != RABBIT_HOLE_DISPLAY_CONTENT) {
// This node shouldn't be displayed, remove it from the resuts.
unset($results[$delta]);
}
}
}
// Reset the keys for the results.
$results = array_values($results);
// Pass the variables through template_preprocess_search_results() once again.
// This is done because the Search module needs to process the new results
// array. This is not the ideal solution, since this could interfere with
// other modules also implementing template_preprocess_search_results().
$variables['theme_hook_suggestions'] = array();
template_preprocess_search_results($variables);
}
Functions
Name | Description |
---|---|
rabbit_hole_form_node_form_alter | Implements hook_form_FORM_ID_alter(). |
rabbit_hole_form_node_type_form_alter | Implements hook_form_FORM_ID_alter(). |
rabbit_hole_menu_local_tasks_alter | Implements hook_menu_local_tasks_alter(). |
rabbit_hole_node_form_submit | Custom submit function for the node form. |
rabbit_hole_node_type_delete | Implements hook_node_type_delete(). |
rabbit_hole_node_view | Implements hook_node_view(). |
rabbit_hole_permission | Implements hook_permission(). |
rabbit_hole_preprocess_search_results | Implements template_preprocess_search_results(). |
Constants
Name | Description |
---|---|
RABBIT_HOLE_ACCESS_DENIED | |
RABBIT_HOLE_DISPLAY_CONTENT | |
RABBIT_HOLE_PAGE_NOT_FOUND | |
RABBIT_HOLE_PAGE_REDIRECT | |
RABBIT_HOLE_PAGE_REDIRECT_RESPONSE_DEFAULT | |
RABBIT_HOLE_USE_DEFAULT | @file Main module file for Rabbit Hole. |