|
@@ -47,24 +47,6 @@ function redirect_entity_info() {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Controller class for redirects.
|
|
|
- *
|
|
|
- * This extends the DrupalDefaultEntityController class, adding required
|
|
|
- * special handling for redirect objects.
|
|
|
- */
|
|
|
-class RedirectController extends DrupalDefaultEntityController {
|
|
|
-
|
|
|
- protected function attachLoad(&$redirects, $revision_id = FALSE) {
|
|
|
- // Unserialize the URL option fields.
|
|
|
- foreach ($redirects as $key => $redirect) {
|
|
|
- $redirects[$key]->source_options = unserialize($redirect->source_options);
|
|
|
- $redirects[$key]->redirect_options = unserialize($redirect->redirect_options);
|
|
|
- }
|
|
|
- parent::attachLoad($redirects, $revision_id);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
* Implements hook_hook_info().
|
|
|
*/
|
|
|
function redirect_hook_info() {
|
|
@@ -245,11 +227,12 @@ function redirect_url_inbound_alter(&$path, $original_path, $path_language) {
|
|
|
}
|
|
|
|
|
|
// Redirect to canonical URLs.
|
|
|
- if ($path && variable_get('redirect_canonical', 1)) {
|
|
|
- $alias = drupal_get_path_alias($path, $path_language);
|
|
|
- if ($alias != $path && $alias != $original_path) {
|
|
|
+ // Commented out per https://www.drupal.org/node/2048137.
|
|
|
+ //if ($path && variable_get('redirect_canonical', 1)) {
|
|
|
+ //$alias = drupal_get_path_alias($path, $path_language);
|
|
|
+ //if ($alias != $path && $alias != $original_path) {
|
|
|
//return redirect_redirect(array('redirect' => $alias, 'type' => 'global'));
|
|
|
- }
|
|
|
+ //}
|
|
|
|
|
|
// Redirect from default entity paths to the proper entity path.
|
|
|
//if ($path_entity = redirect_load_entity_from_path($path)) {
|
|
@@ -259,7 +242,7 @@ function redirect_url_inbound_alter(&$path, $original_path, $path_language) {
|
|
|
// }
|
|
|
// }
|
|
|
//}
|
|
|
- }
|
|
|
+ //}
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -394,6 +377,8 @@ function redirect_path_update(array $path) {
|
|
|
}
|
|
|
|
|
|
if (!empty($path['original']['pid']) && $path['original']['pid'] == $path['pid'] && $path['original']['alias'] != $path['alias']) {
|
|
|
+ // Disable all redirects having the same source as this alias.
|
|
|
+ redirect_disable_by_path($path['alias'], $path['language']);
|
|
|
$redirect = new stdClass();
|
|
|
redirect_object_prepare($redirect);
|
|
|
$redirect->source = $path['original']['alias'];
|
|
@@ -401,9 +386,25 @@ function redirect_path_update(array $path) {
|
|
|
$redirect->language = $path['original']['language'];
|
|
|
// Check if the redirect exists before saving.
|
|
|
$hash = redirect_hash($redirect);
|
|
|
- if (!redirect_load_by_hash($hash)) {
|
|
|
+ $existing = redirect_load_by_hash($hash);
|
|
|
+ if (!$existing) {
|
|
|
redirect_save($redirect);
|
|
|
}
|
|
|
+ // If the existing redirect is disabled, re-enable it.
|
|
|
+ elseif (isset($existing->status) && $existing->status == 0) {
|
|
|
+ $existing->status = 1;
|
|
|
+ redirect_save($existing);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Implements hook_path_insert().
|
|
|
+ */
|
|
|
+function redirect_path_insert(array $path) {
|
|
|
+ if (!empty($path['alias'])) {
|
|
|
+ // Disable all redirects having the same source as this alias.
|
|
|
+ redirect_disable_by_path($path['alias'], $path['language']);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -542,24 +543,26 @@ function redirect_load_by_hash($hash, $reset = FALSE) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Load multiple URL redirects from the database by {redirect}.source.
|
|
|
+ * Fetches multiple URL redirect IDs from the database by {redirect}.source.
|
|
|
*
|
|
|
* @param $source
|
|
|
* The source of the URL redirect.
|
|
|
+ * @param $language
|
|
|
+ * Language of the source URL.
|
|
|
+ * @param $enabled_only
|
|
|
+ * Boolean that indicates whether to only load enabled redirects.
|
|
|
*
|
|
|
- * @return
|
|
|
- * An array of URL redirect objects indexed by redirect IDs.
|
|
|
- *
|
|
|
- * @see redirect_load_multiple()
|
|
|
- * @see _redirect_uasort()
|
|
|
- * @see redirect_compare_array_recursive()
|
|
|
- *
|
|
|
- * @ingroup redirect_api
|
|
|
+ * @return array
|
|
|
+ * An indexed array of IDs, or an empty array if there is no result set.
|
|
|
*/
|
|
|
-function redirect_load_by_source($source, $language = LANGUAGE_NONE, array $query = array()) {
|
|
|
+function redirect_fetch_rids_by_path($source, $language, $enabled_only = FALSE) {
|
|
|
// Run a case-insensitive query for matching RIDs first.
|
|
|
$rid_query = db_select('redirect');
|
|
|
$rid_query->addField('redirect', 'rid');
|
|
|
+ // Prevent errors if redirect_update_7101() has not yet been run.
|
|
|
+ if ($enabled_only && db_field_exists('redirect', 'status')) {
|
|
|
+ $rid_query->condition('status', 1);
|
|
|
+ }
|
|
|
if ($source != variable_get('site_frontpage', 'node')) {
|
|
|
$rid_query->condition('source', db_like($source), 'LIKE');
|
|
|
}
|
|
@@ -571,7 +574,33 @@ function redirect_load_by_source($source, $language = LANGUAGE_NONE, array $quer
|
|
|
}
|
|
|
$rid_query->condition('language', array($language, LANGUAGE_NONE));
|
|
|
$rids = $rid_query->execute()->fetchCol();
|
|
|
+ return $rids;
|
|
|
+}
|
|
|
|
|
|
+
|
|
|
+/**
|
|
|
+ * Load multiple URL redirects from the database by {redirect}.source.
|
|
|
+ *
|
|
|
+ * @param $source
|
|
|
+ * The source of the URL redirect.
|
|
|
+ * @param $language
|
|
|
+ * Language of the source URL.
|
|
|
+ * @param $query
|
|
|
+ * Array of URL query parameters.
|
|
|
+ * @param $enabled_only
|
|
|
+ * Boolean that indicates whether to only load enabled redirects.
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * The first matched URL redirect object, or FALSE if there aren't any.
|
|
|
+ *
|
|
|
+ * @see redirect_load_multiple()
|
|
|
+ * @see _redirect_uasort()
|
|
|
+ * @see redirect_compare_array_recursive()
|
|
|
+ *
|
|
|
+ * @ingroup redirect_api
|
|
|
+ */
|
|
|
+function redirect_load_by_source($source, $language = LANGUAGE_NONE, array $query = array(), $enabled_only = TRUE) {
|
|
|
+ $rids = redirect_fetch_rids_by_path($source, $language, $enabled_only);
|
|
|
if ($rids && $redirects = redirect_load_multiple($rids)) {
|
|
|
// Narrow down the list of candidates.
|
|
|
foreach ($redirects as $rid => $redirect) {
|
|
@@ -700,11 +729,11 @@ function redirect_validate($redirect, $form, &$form_state) {
|
|
|
redirect_hash($redirect);
|
|
|
if ($existing = redirect_load_by_hash($redirect->hash)) {
|
|
|
if ($redirect->rid != $existing->rid) {
|
|
|
- form_set_error('source', t('The source path %source is already being redirected. Do you want to <a href="@edit-page">edit the existing redirect</a>?', array('%source' => redirect_url($redirect->source, $redirect->source_options), '@edit-page' => url('admin/config/search/redirect/edit/'. $existing->rid))));
|
|
|
+ form_set_error('source', t('A redirect already exists for the source path %source. Do you want to <a href="@edit-page">edit the existing redirect</a>?', array('%source' => redirect_url($redirect->source, $redirect->source_options), '@edit-page' => url('admin/config/search/redirect/edit/'. $existing->rid))));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Allow other modules to validate the SSH public key.
|
|
|
+ // Allow other modules to validate the redirect.
|
|
|
foreach (module_implements('redirect_validate') as $module) {
|
|
|
$function = $module . '_redirect_validate';
|
|
|
$function($redirect, $form, $form_state);
|
|
@@ -723,6 +752,7 @@ function redirect_object_prepare($redirect, $defaults = array()) {
|
|
|
'count' => 0,
|
|
|
'access' => 0,
|
|
|
'hash' => '',
|
|
|
+ 'status' => 1,
|
|
|
);
|
|
|
|
|
|
foreach ($defaults as $key => $default) {
|
|
@@ -866,6 +896,28 @@ function redirect_delete_by_path($path) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * Disable any redirects associated with a path.
|
|
|
+ *
|
|
|
+ * Given a source like 'node/1' this function will delete any redirects that
|
|
|
+ * have that specific source.
|
|
|
+ *
|
|
|
+ * @param $path
|
|
|
+ * An string with an internal Drupal path.
|
|
|
+ *
|
|
|
+ * @param @langauge
|
|
|
+ * The langcode of the path.
|
|
|
+ *
|
|
|
+ * @ingroup redirect_api
|
|
|
+ */
|
|
|
+function redirect_disable_by_path($path, $language) {
|
|
|
+ $rids = redirect_fetch_rids_by_path($path, $language, FALSE);
|
|
|
+
|
|
|
+ if ($rids) {
|
|
|
+ return redirect_change_status_multiple($rids, 0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
* Delete an entity URL alias and any of its sub-paths.
|
|
|
*
|
|
|
* This function also checks to see if the default entity URI is different from
|
|
@@ -879,7 +931,8 @@ function redirect_delete_by_path($path) {
|
|
|
* @ingroup redirect_api
|
|
|
*/
|
|
|
function redirect_delete_by_entity_path($entity_type, $entity) {
|
|
|
- if ($uri = entity_uri($entity_type, $entity)) {
|
|
|
+ $uri = entity_uri($entity_type, $entity);
|
|
|
+ if (!empty($uri['path'])) {
|
|
|
redirect_delete_by_path($uri['path']);
|
|
|
}
|
|
|
|
|
@@ -894,6 +947,48 @@ function redirect_delete_by_entity_path($entity_type, $entity) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * Change the status of multiple URL redirects.
|
|
|
+ *
|
|
|
+ * @param array $rids
|
|
|
+ * An array of redirect IDs to disable.
|
|
|
+ * @param int|string $status
|
|
|
+ * The status to set the redirect to: either disabled (0) or enabled (1).
|
|
|
+ *
|
|
|
+ * @ingroup redirect_api
|
|
|
+ */
|
|
|
+function redirect_change_status_multiple(array $rids, $status) {
|
|
|
+ if ($status !== 0 && $status !== 1 && $status !== '0' && $status !== '1') {
|
|
|
+ watchdog('Cannot change redirect status to %status', array('%status' => $status));
|
|
|
+ drupal_set_message(t('Cannot change redirect status to %status', array('%status' => $status)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!empty($rids)) {
|
|
|
+ $redirects = redirect_load_multiple($rids, array(), TRUE);
|
|
|
+
|
|
|
+ foreach ($redirects as $rid => $redirect) {
|
|
|
+ if (isset($redirect->status) && $redirect->status == $status) {
|
|
|
+ // We no-op if the redirect is not actually changing status.
|
|
|
+ // So if a disabled redirect is disabled, neither redirect_save() is
|
|
|
+ // triggered, nor do we log any message.
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $redirect->status = $status;
|
|
|
+ redirect_save($redirect);
|
|
|
+
|
|
|
+ if ($status) {
|
|
|
+ $redirect_link = l($redirect->redirect, $redirect->redirect) . '=> ' . l($redirect->source, $redirect->source);
|
|
|
+ watchdog('redirect', 'Enabled redirect: !redirect_source_link', array('!redirect_link' => $redirect_link));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $redirect_link = l($redirect->redirect, $redirect->redirect) . '=> ' . l($redirect->source, $redirect->source);
|
|
|
+ watchdog('redirect', 'Disabled redirect: !redirect_source_link', array('!redirect_link' => $redirect_link));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
* Delete multiple URL redirects.
|
|
|
*
|
|
|
* @param $rids
|
|
@@ -947,10 +1042,15 @@ function redirect_purge_inactive_redirects(array $types = array('redirect'), $in
|
|
|
$interval = variable_get('redirect_purge_inactive', 0);
|
|
|
}
|
|
|
|
|
|
- if (!$interval || !variable_get('redirect_page_cache', 0) || !variable_get('page_cache_invoke_hooks', TRUE)) {
|
|
|
+ if (!$interval) {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (variable_get('redirect_page_cache', 0) && !variable_get('page_cache_invoke_hooks', TRUE)) {
|
|
|
// If serving redirects from the page cache is enabled and hooks are not
|
|
|
// executed during page caching, then we cannot track when a redirect is
|
|
|
// used. Therefore, we cannot remove unused redirects.
|
|
|
+ watchdog('redirect', 'Due to existing settings, could not track when a redirect is used, so could not remove unused redirects.');
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
@@ -979,17 +1079,6 @@ function redirect_purge_inactive_redirects(array $types = array('redirect'), $in
|
|
|
* @ingroup redirect_api
|
|
|
*/
|
|
|
function redirect_redirect($redirect = NULL) {
|
|
|
- // First check if we're in an infinite loop.
|
|
|
- $session_id = session_id();
|
|
|
- if (flood_is_allowed('redirection', 5, 15, $session_id ? $session_id : NULL)) {
|
|
|
- flood_register_event('redirection', 60, $session_id ? $session_id : NULL);
|
|
|
- }
|
|
|
- else {
|
|
|
- watchdog('redirect', 'Infinite loop stopped.');
|
|
|
- drupal_set_message('Oops, looks like this request tried to create an infinite loop. We do not allow such things here. We are a professional website!');
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
if (!isset($redirect)) {
|
|
|
$redirect = new stdClass();
|
|
|
}
|
|
@@ -1017,6 +1106,10 @@ function redirect_redirect($redirect = NULL) {
|
|
|
|
|
|
// Continue if the redirect has not been disabled by hook_redirect_alter().
|
|
|
if (isset($redirect->redirect) && isset($redirect->callback) && $redirect->redirect !== FALSE && function_exists($redirect->callback)) {
|
|
|
+ // Prevent circular redirects.
|
|
|
+ if ($GLOBALS['base_root'] . request_uri() == url($redirect->redirect, array('absolute' => TRUE) + $redirect->redirect_options)) {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
// Perform the actual redirect.
|
|
|
$callback = $redirect->callback;
|
|
|
$callback($redirect);
|
|
@@ -1150,7 +1243,7 @@ function redirect_can_redirect() {
|
|
|
$path = current_path();
|
|
|
$can_redirect = TRUE;
|
|
|
|
|
|
- if ($_SERVER['SCRIPT_NAME'] != $GLOBALS['base_path'] . 'index.php') {
|
|
|
+ if (!preg_match('/index\.php$/', $_SERVER['SCRIPT_NAME'])) {
|
|
|
// Do not redirect if the root script is not /index.php.
|
|
|
$can_redirect = FALSE;
|
|
|
}
|
|
@@ -1162,7 +1255,7 @@ function redirect_can_redirect() {
|
|
|
// If this is a command line request (Drush, etc), skip processing.
|
|
|
$can_redirect = FALSE;
|
|
|
}
|
|
|
- elseif (variable_get('maintenance_mode', 0) || defined('MAINTENANCE_MODE')) {
|
|
|
+ elseif ((variable_get('maintenance_mode', 0) || defined('MAINTENANCE_MODE')) && !user_access('access site in maintenance mode')) {
|
|
|
// Do not redirect in offline or maintenance mode.
|
|
|
$can_redirect = FALSE;
|
|
|
}
|
|
@@ -1176,7 +1269,7 @@ function redirect_can_redirect() {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Compare tha all values and associations in one array match another array.
|
|
|
+ * Compare that all values and associations in one array match another array.
|
|
|
*
|
|
|
* We cannot use array_diff_assoc() here because we need to be recursive.
|
|
|
*
|
|
@@ -1457,7 +1550,7 @@ function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state,
|
|
|
}
|
|
|
|
|
|
$uri = entity_uri($entity_type, $entity);
|
|
|
- if (empty($uri)) {
|
|
|
+ if (empty($uri['path'])) {
|
|
|
// If the entity has no source path, then we cannot lookup the existing
|
|
|
// redirects.
|
|
|
return;
|
|
@@ -1467,7 +1560,6 @@ function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state,
|
|
|
$form['redirect'] = array(
|
|
|
'#type' => 'fieldset',
|
|
|
'#title' => t('URL redirects'),
|
|
|
- '#description' => t('The following are a list of URL redirects that point to this @entitytype.', array('@entitytype' => drupal_strtolower($info['label']))),
|
|
|
'#collapsible' => TRUE,
|
|
|
'#collapsed' => TRUE,
|
|
|
'#access' => user_access('administer redirects'),
|
|
@@ -1483,13 +1575,6 @@ function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // We don't have to put our include in $form_state['build_info']['files']
|
|
|
- // since the build array will already be cached.
|
|
|
- module_load_include('inc', 'redirect', 'redirect.admin');
|
|
|
- $redirects = redirect_load_multiple(FALSE, array('redirect' => $uri['path']));
|
|
|
- $header = array('source', 'status_code', 'language', 'count', 'access', 'operations');
|
|
|
- $form['redirect'] += redirect_list_table($redirects, $header);
|
|
|
-
|
|
|
$redirect = array(
|
|
|
'redirect' => $uri['path'],
|
|
|
'redirect_options' => array_diff_key($uri['options'], array('entity_type' => '', 'entity' => '')),
|
|
@@ -1508,6 +1593,13 @@ function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state,
|
|
|
'query' => array_filter($redirect) + drupal_get_destination(),
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ // We don't have to put our include in $form_state['build_info']['files']
|
|
|
+ // since the build array will already be cached.
|
|
|
+ module_load_include('inc', 'redirect', 'redirect.admin');
|
|
|
+ $redirects = redirect_load_multiple(FALSE, array('redirect' => $uri['path']));
|
|
|
+ $header = array('source', 'status', 'status_code', 'language', 'count', 'access', 'operations');
|
|
|
+ $form['redirect'] += redirect_list_table($redirects, $header);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1516,8 +1608,8 @@ function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state,
|
|
|
function redirect_field_extra_fields() {
|
|
|
$entity_info = entity_get_info();
|
|
|
foreach (array_keys($entity_info) as $entity_type) {
|
|
|
- if ($entity_type == 'comment') {
|
|
|
- // The comment entity type supports URIs, but they're not real.
|
|
|
+ if (!redirect_entity_type_supports_redirects($entity_type)) {
|
|
|
+ // Redirect is explicitly disabled for this entity type.
|
|
|
continue;
|
|
|
}
|
|
|
foreach (array_keys($entity_info[$entity_type]['bundles']) as $bundle) {
|
|
@@ -1564,5 +1656,19 @@ function redirect_redirect_operations() {
|
|
|
'callback' => 'redirect_delete_multiple',
|
|
|
'confirm' => TRUE,
|
|
|
);
|
|
|
+ $operations['disable'] = array(
|
|
|
+ 'action' => t('Disable'),
|
|
|
+ 'action_past' => t('Disabled'),
|
|
|
+ 'callback' => 'redirect_change_status_multiple',
|
|
|
+ 'callback arguments' => array(0),
|
|
|
+ 'confirm' => TRUE,
|
|
|
+ );
|
|
|
+ $operations['enable'] = array(
|
|
|
+ 'action' => t('Enable'),
|
|
|
+ 'action_past' => t('Enabled'),
|
|
|
+ 'callback' => 'redirect_change_status_multiple',
|
|
|
+ 'callback arguments' => array(1),
|
|
|
+ 'confirm' => TRUE,
|
|
|
+ );
|
|
|
return $operations;
|
|
|
}
|