| 1 |
<?php
|
| 2 |
// $Id: path_redirect.module,v 1.5 2009/03/11 03:49:25 davereid Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* Implementation of hook_help().
|
| 6 |
*/
|
| 7 |
function path_redirect_help($path, $arg) {
|
| 8 |
switch ($path) {
|
| 9 |
case 'admin/build/path-redirect':
|
| 10 |
case 'admin/build/path-redirect/list':
|
| 11 |
return '<p>' . t('Here you can set up URL redirecting for this site. Any existing or non-existing path within this site can redirect to any internal or external URL.') . '</p>';
|
| 12 |
//case 'admin/build/path-redirect/add':
|
| 13 |
//case 'admin/build/path-redirect/edit/'. $arg[3]:
|
| 14 |
//case 'admin/build/path-redirect/settings':
|
| 15 |
}
|
| 16 |
}
|
| 17 |
|
| 18 |
/**
|
| 19 |
* Implementation of hook_perm().
|
| 20 |
*/
|
| 21 |
function path_redirect_perm() {
|
| 22 |
return array(
|
| 23 |
'administer redirects' => array(
|
| 24 |
'title' => t('Administer URL redirections'),
|
| 25 |
'description' => t('Add, edit or delete URL redirections.'),
|
| 26 |
),
|
| 27 |
);
|
| 28 |
}
|
| 29 |
|
| 30 |
/**
|
| 31 |
* Implementation of hook_menu().
|
| 32 |
*/
|
| 33 |
function path_redirect_menu() {
|
| 34 |
$items['admin/build/path-redirect'] = array(
|
| 35 |
'title' => 'URL redirects',
|
| 36 |
'description' => 'Redirect users from one URL to another.',
|
| 37 |
'page callback' => 'path_redirect_admin',
|
| 38 |
'access arguments' => array('administer redirects'),
|
| 39 |
);
|
| 40 |
$items['admin/build/path-redirect/list'] = array(
|
| 41 |
'title' => 'List',
|
| 42 |
'description' => 'List all URL redirects.',
|
| 43 |
'access arguments' => array('administer redirects'),
|
| 44 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 45 |
'weight' => -3,
|
| 46 |
);
|
| 47 |
$items['admin/build/path-redirect/add'] = array(
|
| 48 |
'title' => 'Add redirect',
|
| 49 |
'description' => 'Add a new URL redirect.',
|
| 50 |
'page callback' => 'drupal_get_form',
|
| 51 |
'page arguments' => array('path_redirect_edit'),
|
| 52 |
'access arguments' => array('administer redirects'),
|
| 53 |
'type' => MENU_LOCAL_TASK,
|
| 54 |
);
|
| 55 |
$items['admin/build/path-redirect/edit'] = array(
|
| 56 |
'title' => 'Edit',
|
| 57 |
'description' => 'Edit an existing URL redirect.',
|
| 58 |
'page callback' => 'drupal_get_form',
|
| 59 |
'page arguments' => array('path_redirect_edit'),
|
| 60 |
'access arguments' => array('administer redirects'),
|
| 61 |
'type' => MENU_CALLBACK,
|
| 62 |
);
|
| 63 |
$items['admin/build/path-redirect/delete'] = array(
|
| 64 |
'title' => 'Delete redirect',
|
| 65 |
'description' => 'Delete an existing URL redirect.',
|
| 66 |
'page callback' => 'drupal_get_form',
|
| 67 |
'page arguments' => array('path_redirect_delete_confirm'),
|
| 68 |
'access arguments' => array('administer redirects'),
|
| 69 |
'type' => MENU_CALLBACK,
|
| 70 |
);
|
| 71 |
$items['admin/build/path-redirect/settings'] = array(
|
| 72 |
'title' => 'Settings',
|
| 73 |
'description' => 'Configure behavior for URL redirects.',
|
| 74 |
'page callback' => 'drupal_get_form',
|
| 75 |
'page arguments' => array('path_redirect_settings_form'),
|
| 76 |
'access arguments' => array('administer redirects'),
|
| 77 |
'type' => MENU_LOCAL_TASK,
|
| 78 |
);
|
| 79 |
//$items['admin/build/path-redirect/import'] = array(
|
| 80 |
// 'title' => 'Import',
|
| 81 |
// 'description' => 'Import URL redirects.',
|
| 82 |
// 'page callback' => 'drupal_get_form',
|
| 83 |
// 'page arguments' => array('path_redirect_import_form'),
|
| 84 |
// 'access arguments' => array('administer redirects'),
|
| 85 |
// 'type' => MENU_LOCAL_TASK,
|
| 86 |
// 'weight' => 20,
|
| 87 |
//);
|
| 88 |
$items['admin/build/path-redirect/export'] = array(
|
| 89 |
'title' => 'Export',
|
| 90 |
'description' => 'Export URL redirects.',
|
| 91 |
'page callback' => 'drupal_get_form',
|
| 92 |
'page arguments' => array('path_redirect_export_form'),
|
| 93 |
'access arguments' => array('administer redirects'),
|
| 94 |
'type' => MENU_LOCAL_TASK,
|
| 95 |
'weight' => 30,
|
| 96 |
);
|
| 97 |
//$items['admin/build/path-redirect/export/csv'] = array(
|
| 98 |
// 'page callback' => 'path_redirect_export_csv',
|
| 99 |
// 'access arguments' => array('administer redirects'),
|
| 100 |
// 'type' => MENU_CALLBACK,
|
| 101 |
//);
|
| 102 |
//$items['admin/build/path-redirect/export/xml'] = array(
|
| 103 |
// 'page callback' => 'path_redirect_export_xml',
|
| 104 |
// 'access arguments' => array('administer redirects'),
|
| 105 |
// 'type' => MENU_CALLBACK,
|
| 106 |
//);
|
| 107 |
$items['admin/build/path-redirect/autocomplete'] = array(
|
| 108 |
'page callback' => 'path_redirect_autocomplete',
|
| 109 |
'access arguments' => array('administer redirects'),
|
| 110 |
'type' => MENU_CALLBACK,
|
| 111 |
);
|
| 112 |
|
| 113 |
return $items;
|
| 114 |
}
|
| 115 |
|
| 116 |
/**
|
| 117 |
* Implementation of hook_init().
|
| 118 |
*/
|
| 119 |
function path_redirect_init() {
|
| 120 |
_path_redirect_check();
|
| 121 |
}
|
| 122 |
|
| 123 |
/**
|
| 124 |
* Implementation of hook_cron().
|
| 125 |
*/
|
| 126 |
function path_redirect_cron() {
|
| 127 |
// Purge inactive redirects from the database.
|
| 128 |
if ($purge = path_redirect_var('purge_inactive')) {
|
| 129 |
db_delete('path_redirect')
|
| 130 |
->condition('last_used', REQUEST_TIME - $purge, '<')
|
| 131 |
->execute();
|
| 132 |
if ($count = db_affected_rows()) {
|
| 133 |
watchdog('path_redirect', format_plural($count, 'Removed 1 inactive redirect from the database.', 'Removed @count inactive redirects from the database.'));
|
| 134 |
}
|
| 135 |
}
|
| 136 |
}
|
| 137 |
|
| 138 |
/**
|
| 139 |
* If a redirect is found for the current path, perform the redirect.
|
| 140 |
*/
|
| 141 |
function _path_redirect_check() {
|
| 142 |
global $language;
|
| 143 |
|
| 144 |
$query = db_select('path_redirect', 'pr')
|
| 145 |
->fields('pr', array('rid', 'path', 'redirect', 'query', 'fragment', 'language', 'type'))
|
| 146 |
->range(0, 1);
|
| 147 |
|
| 148 |
// Add query arguments.
|
| 149 |
$query_string = $_GET;
|
| 150 |
unset($query_string['q']); // Use array_diff or array_diff_assoc?
|
| 151 |
if ($query_string) {
|
| 152 |
$path = urldecode(request_uri());
|
| 153 |
$path = drupal_substr($path, drupal_strlen(base_path()));
|
| 154 |
// Remove ($language->language .'/') via preg_replace?
|
| 155 |
$path = _path_redirect_split_path($path);
|
| 156 |
$query->condition(db_or()
|
| 157 |
->condition('path', $_GET['q'])
|
| 158 |
->condition('path', $_GET['q'] . '?' . $path['query'])
|
| 159 |
)
|
| 160 |
->orderBy('path', 'DESC');
|
| 161 |
}
|
| 162 |
else {
|
| 163 |
$query->condition('path', $_GET['q']);
|
| 164 |
}
|
| 165 |
|
| 166 |
// Add language arguments.
|
| 167 |
$query->condition(db_or()
|
| 168 |
->condition('language', $language->language)
|
| 169 |
->condition('language', '')
|
| 170 |
)
|
| 171 |
->orderBy('language', 'DESC');
|
| 172 |
|
| 173 |
$r = $query->execute()->fetchObject();
|
| 174 |
|
| 175 |
if ($r) {
|
| 176 |
// Update the last used timestamp so that unused redirects can be purged.
|
| 177 |
db_update('path_redirect')
|
| 178 |
->fields(array('last_used' => REQUEST_TIME))
|
| 179 |
->condition('rid', $r->rid)
|
| 180 |
->execute();
|
| 181 |
|
| 182 |
$redirect = url($r->redirect, array('query' => $r->query, 'fragment' => $r->fragment, 'absolute' => TRUE));
|
| 183 |
|
| 184 |
if (url($r->redirect) == url($_GET['q'])) {
|
| 185 |
// Prevent infinite loop redirection.
|
| 186 |
watchdog('path_redirect', 'Redirect to <code>%redirect</code> is causing an infinite loop; redirect cancelled.', array('%redirect' => $r->redirect), WATCHDOG_WARNING, l(t('Edit'), 'admin/build/path-redirect/edit/' . $r->rid));
|
| 187 |
}
|
| 188 |
elseif (path_redirect_var('allow_bypass') && isset($_GET['redirect']) && $_GET['redirect'] === 'no') {
|
| 189 |
// If the user has requested not to be redirected, show a message.
|
| 190 |
drupal_set_message(t('This page has been moved to <a href="@redirect">@redirect</a>.', array('@redirect' => $redirect)));
|
| 191 |
}
|
| 192 |
elseif (path_redirect_var('redirect_warning')) {
|
| 193 |
// Show a message and automatically redirect after 10 seconds.
|
| 194 |
drupal_set_message(t('This page has been moved to <a href="@redirect">@redirect</a>. You will be automatically redirected in 10 seconds.', array('@redirect' => $redirect)), 'error');
|
| 195 |
drupal_set_html_head("<meta http-equiv=\"refresh\" content=\"10;url=$redirect\" />");
|
| 196 |
}
|
| 197 |
else {
|
| 198 |
// Perform the redirect.
|
| 199 |
unset($_REQUEST['destination']);
|
| 200 |
drupal_goto($r->redirect, $r->query, $r->fragment, $r->type);
|
| 201 |
}
|
| 202 |
}
|
| 203 |
}
|
| 204 |
|
| 205 |
/**
|
| 206 |
* Implementation of hook_node_presave().
|
| 207 |
*
|
| 208 |
* Creates automatic redirects when URL aliases are manually changed.
|
| 209 |
*/
|
| 210 |
function path_redirect_node_presave($node) {
|
| 211 |
if (path_redirect_var('auto_redirect') && !empty($node->path)) {
|
| 212 |
$node_path = 'node/' . $node->nid;
|
| 213 |
$old_alias = drupal_get_path_alias($node_path, ($node->language ? $node->language : ''));
|
| 214 |
if ($old_alias != $node_path && $node->path != $old_alias) {
|
| 215 |
// If the user is manually changing the path alias, add a redirect from the old alias to the node.
|
| 216 |
path_redirect_save(array('path' => $old_alias, 'redirect' => $node_path));
|
| 217 |
}
|
| 218 |
}
|
| 219 |
}
|
| 220 |
|
| 221 |
/**
|
| 222 |
* Implementation of hook_node_presave().
|
| 223 |
*/
|
| 224 |
function path_redirect_node_delete($node) {
|
| 225 |
// When a node is deleted, also delete the redirects to it (they will result in a 404).
|
| 226 |
path_redirect_delete(array('redirect' => 'node/' . $node->nid));
|
| 227 |
}
|
| 228 |
|
| 229 |
/**
|
| 230 |
* Save an URL redirect to the database.
|
| 231 |
*/
|
| 232 |
function path_redirect_save($edit) {
|
| 233 |
// Merge default values.
|
| 234 |
$edit += array(
|
| 235 |
'type' => path_redirect_var('default_status'),
|
| 236 |
'last_used' => REQUEST_TIME,
|
| 237 |
);
|
| 238 |
|
| 239 |
// Remove beginning and trailing slashes from path.
|
| 240 |
// @todo Move to validation.
|
| 241 |
$edit['path'] = preg_replace('/^\/|\/\?|\/$/', '', $edit['path']);
|
| 242 |
|
| 243 |
if (empty($edit['rid'])) {
|
| 244 |
return drupal_write_record('path_redirect', $edit);
|
| 245 |
}
|
| 246 |
else {
|
| 247 |
return drupal_write_record('path_redirect', $edit, 'rid');
|
| 248 |
}
|
| 249 |
}
|
| 250 |
|
| 251 |
/**
|
| 252 |
* Retrieve a specific URL redirect from the database.
|
| 253 |
*/
|
| 254 |
function path_redirect_load($where = array()) {
|
| 255 |
if (is_numeric($where)) {
|
| 256 |
$where = array('rid' => $where);
|
| 257 |
}
|
| 258 |
|
| 259 |
$query = db_select('path_redirect')->fields('path_redirect');
|
| 260 |
foreach ($where as $key => $value) {
|
| 261 |
$query->condition($key, $value);
|
| 262 |
}
|
| 263 |
$query->range(0, 1);
|
| 264 |
return $query->execute()->fetchObject();
|
| 265 |
}
|
| 266 |
|
| 267 |
/**
|
| 268 |
* Delete a specific URL redirect from the database.
|
| 269 |
*/
|
| 270 |
function path_redirect_delete($where = array()) {
|
| 271 |
if (is_numeric($where)) {
|
| 272 |
$where = array('rid' => $where);
|
| 273 |
}
|
| 274 |
|
| 275 |
$query = db_delete('path_redirect');
|
| 276 |
foreach ($where as $key => $value) {
|
| 277 |
$query->condition($key, $value);
|
| 278 |
}
|
| 279 |
$query->execute();
|
| 280 |
}
|
| 281 |
|
| 282 |
/**
|
| 283 |
* Internal function to split a path string into path, query and fragment.
|
| 284 |
*/
|
| 285 |
function _path_redirect_split_path($path) {
|
| 286 |
//$path = strtr($path, array('<front>' => variable_get('site_frontpage', 'node')));
|
| 287 |
if (variable_get('clean_url', 0) && strpos($path, '?q=') === 0) {
|
| 288 |
$path = preg_replace('/^\?q=/', '', $path, 1);
|
| 289 |
}
|
| 290 |
if (strpos($path, '?') === FALSE && strpos($path, '&') !== FALSE) {
|
| 291 |
$path = preg_replace('/&/', '?', $path, 1);
|
| 292 |
}
|
| 293 |
|
| 294 |
$result = array(
|
| 295 |
'path' => preg_replace('/[\?\#].*$/', '', $path),
|
| 296 |
'query' => parse_url($path, PHP_URL_QUERY),
|
| 297 |
'fragment' => parse_url($path, PHP_URL_FRAGMENT),
|
| 298 |
);
|
| 299 |
return $result;
|
| 300 |
}
|
| 301 |
|
| 302 |
/**
|
| 303 |
* Internal default variables for template_var().
|
| 304 |
*/
|
| 305 |
function path_redirect_variables() {
|
| 306 |
return array(
|
| 307 |
'path_redirect_redirect_warning' => 0,
|
| 308 |
'path_redirect_allow_bypass' => 0,
|
| 309 |
'path_redirect_auto_redirect' => 1,
|
| 310 |
'path_redirect_purge_inactive' => 4838400,
|
| 311 |
'path_redirect_default_status' => 301,
|
| 312 |
// Unused variables set to NULL so they will still be uninstalled.
|
| 313 |
'path_redirect_nodeapi_enabled' => NULL,
|
| 314 |
);
|
| 315 |
}
|
| 316 |
|
| 317 |
/**
|
| 318 |
* Internal implementation of variable_get().
|
| 319 |
*/
|
| 320 |
function path_redirect_var($name, $default = NULL) {
|
| 321 |
static $defaults = NULL;
|
| 322 |
if (!isset($defaults)) {
|
| 323 |
$defaults = path_redirect_variables();
|
| 324 |
}
|
| 325 |
|
| 326 |
$name = 'path_redirect_' . $name;
|
| 327 |
|
| 328 |
// @todo Remove when stable.
|
| 329 |
if (!isset($defaults[$name])) {
|
| 330 |
trigger_error(t('Default variable for %variable not found.', array('%variable' => $name)));
|
| 331 |
}
|
| 332 |
|
| 333 |
return variable_get($name, isset($default) || !isset($defaults[$name]) ? $default : $defaults[$name]);
|
| 334 |
}
|