- <?php
-
- * Implements hook_help().
- */
- function path_redirect_help($path, $arg) {
- $output = '';
- switch ($path) {
- case 'admin/build/path-redirect':
- case 'admin/build/path-redirect/list':
-
- break;
- case 'admin/build/path-redirect/add':
- case 'admin/build/path-redirect/edit/%':
- $output .= '<p>' . t('If you need advanced redirection functionality (i.e. wildcards, etc.), you should be using a <a href="http://en.wikipedia.org/wiki/Mod_rewrite">webserver rewriting engine</a> rather than this module.') . '</p>';
- break;
- }
- return $output;
- }
-
- * Implements hook_perm().
- */
- function path_redirect_perm() {
- return array(
- 'administer redirects',
- );
- }
-
- * Implements hook_menu().
- */
- function path_redirect_menu() {
- $items['admin/build/path-redirect'] = array(
- 'title' => 'URL redirects',
- 'description' => 'Redirect users from one URL to another.',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('path_redirect_admin_redirects'),
- 'access arguments' => array('administer redirects'),
- 'file' => 'path_redirect.admin.inc',
- );
- $items['admin/build/path-redirect/list'] = array(
- 'title' => 'List',
- 'type' => MENU_DEFAULT_LOCAL_TASK,
- 'weight' => -10,
- );
- $items['admin/build/path-redirect/add'] = array(
- 'title' => 'Add redirect',
- 'description' => 'Add a new URL redirect.',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('path_redirect_edit_form'),
- 'access arguments' => array('administer redirects'),
- 'type' => MENU_LOCAL_TASK,
- 'file' => 'path_redirect.admin.inc',
- );
- $items['admin/build/path-redirect/edit/%path_redirect'] = array(
- 'title' => 'Edit redirect',
- 'description' => 'Edit an existing URL redirect.',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('path_redirect_edit_form', 4),
- 'access arguments' => array('administer redirects'),
- 'type' => MENU_CALLBACK,
- 'file' => 'path_redirect.admin.inc',
- );
- $items['admin/build/path-redirect/delete/%path_redirect'] = array(
- 'title' => 'Delete redirect',
- 'description' => 'Delete an existing URL redirect.',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('path_redirect_delete_form', 4),
- 'access arguments' => array('administer redirects'),
- 'type' => MENU_CALLBACK,
- 'file' => 'path_redirect.admin.inc',
- );
- $items['admin/build/path-redirect/settings'] = array(
- 'title' => 'Settings',
- 'description' => 'Configure behavior for URL redirects.',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('path_redirect_settings_form'),
- 'access arguments' => array('administer redirects'),
- 'type' => MENU_LOCAL_TASK,
- 'weight' => 10,
- 'file' => 'path_redirect.admin.inc',
- );
- $items['js/path_redirect/autocomplete_404'] = array(
- 'page callback' => 'path_redirect_js_autocomplete_404',
- 'access arguments' => array('administer redirects'),
- 'type' => MENU_CALLBACK,
- 'file' => 'path_redirect.admin.inc',
- );
-
- return $items;
- }
-
- * Implements hook_init().
- */
- function path_redirect_init() {
- if (defined('MAINTENANCE_MODE')) {
- return;
- }
-
- path_redirect_goto();
- }
-
- function path_redirect_goto($redirect = NULL) {
- if (!isset($redirect)) {
- $path = path_redirect_get_path();
- $language = $GLOBALS['language']->language;
- $query = path_redirect_get_query();
- $redirect = path_redirect_load_by_source($path, $language, $query);
- }
- elseif (is_numeric($redirect)) {
- $redirect = path_redirect_load($redirect);
- }
-
- if ($redirect) {
-
- $redirect['redirect_url'] = url($redirect['redirect'], array('query' => $redirect['query'], 'fragment' => $redirect['fragment'], 'absolute' => TRUE));
-
-
- db_query("UPDATE {path_redirect} SET last_used = %d WHERE rid = %d", time(), $redirect['rid']);
-
- if (url($redirect['redirect']) == url($_GET['q'])) {
-
- watchdog('path_redirect', 'Redirect to <code>%redirect</code> is causing an infinite loop; redirect cancelled.', array('%redirect' => $redirect['redirect_url']), WATCHDOG_WARNING, l(t('Edit'), 'admin/build/path-redirect/edit/'. $redirect['rid']));
- }
- elseif (variable_get('path_redirect_allow_bypass', 0) && isset($_GET['redirect']) && $_GET['redirect'] === 'no') {
-
- drupal_set_message(t('This page has been moved to <a href="@redirect">@redirect</a>.', array('@redirect' => $redirect['redirect_url'])));
- }
- elseif (variable_get('path_redirect_redirect_warning', 0)) {
-
- 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['redirect_url'])), 'error');
- drupal_set_html_head('<meta http-equiv="refresh" content="10;url=' . $redirect['redirect_url'] . '" />');
- }
- else {
-
- unset($_REQUEST['destination']);
- drupal_goto($redirect['redirect_url'], NULL, NULL, $redirect['type']);
- }
- }
-
-
- return MENU_NOT_FOUND;
- }
-
- * Implements hook_cron().
- */
- function path_redirect_cron() {
-
- if ($purge = variable_get('path_redirect_purge_inactive', 0)) {
- $query = db_query("SELECT rid FROM {path_redirect} WHERE last_used < %d", time() - $purge);
- $rids = array();
- while ($rid = db_result($query)) {
- $rids[] = $rid;
- }
- if ($rids) {
- path_redirect_delete_multiple($rids);
- watchdog('path_redirect', format_plural(count($rids), 'Removed 1 inactive redirect from the database.', 'Removed @count inactive redirects from the database.'));
- }
- }
- }
-
- * Implements hook_path_redirect_operations().
- */
- function path_redirect_path_redirect_operations() {
- $operations = array(
- 'delete' => array(
- 'action' => t('Delete'),
- 'action_past' => t('Deleted'),
- 'callback' => 'path_redirect_delete_multiple',
- 'confirm' => TRUE,
- ),
- );
- return $operations;
- }
-
- * Implements hook_content_extra_fields().
- *
- * This is so that the URL redirect fieldset is sortable on the node edit form.
- */
- function path_redirect_content_extra_fields() {
- $extras['path_redirect'] = array(
- 'label' => t('URL redirects'),
- 'description' => t('Path redirect module listing'),
- 'weight' => 30,
- );
- return $extras;
- }
-
- * Implements hook_form_alter().
- *
- * Add a summary of redirects pointing to a node on its edit form.
- */
- function path_redirect_form_alter(&$form, $form_state, $form_id) {
- if (substr($form_id, -10) == '_node_form' && !empty($form['#node']->nid)) {
- $redirect = array(
- 'redirect' => 'node/' . $form['#node']->nid,
- 'language' => $form['#node']->language,
- );
- $form['path_redirect'] = array(
- '#type' => 'fieldset',
- '#title' => t('URL redirects'),
- '#description' => t('The following are a list of URL redirects that point to this location.'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- '#access' => user_access('administer redirects'),
- '#weight' => 30,
- '#group' => 'additional_settings',
- '#attached' => array(
- 'js' => array(
- 'vertical-tabs' => drupal_get_path('module', 'path_redirect') . '/path_redirect.js',
- ),
- ),
- );
- module_load_include('inc', 'path_redirect', 'path_redirect.admin');
- $form['path_redirect']['table'] = path_redirect_list_redirects(array(), array('redirect' => 'node/' . $form['#node']->nid));
- $form['path_redirect']['add'] = array(
- '#value' => path_redirect_local_actions($redirect),
- );
- }
- }
-
- function path_redirect_local_actions($redirect = array()) {
- $links = array(
- 'add' => array(
- 'title' => $redirect ? t('Add redirect to this location') : t('Add redirect'),
- 'href' => 'admin/build/path-redirect/add',
- 'query' => drupal_get_destination() . ($redirect ? '&' . drupal_query_string_encode($redirect) : ''),
- ),
- );
- return theme('links', $links, array('class' => 'item-list action-links'));
- }
-
- * Implements hook_nodeapi().
- */
- function path_redirect_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
- switch ($op) {
- case 'presave':
- if (!empty($node->nid) && !empty($node->path)) {
- path_redirect_check_alias_changed('node/' . $node->nid, $node->path, $node->language);
- }
- break;
- case 'delete':
-
- path_redirect_delete_multiple(NULL, array('source' => 'node/'. $node->nid));
- path_redirect_delete_multiple(NULL, array('redirect' => 'node/'. $node->nid));
- break;
- }
- }
-
- * Creates a redirect if an URL alias is being changed.
- *
- * @param $path
- * The base (normal) path.
- * @param $new_alias
- * The new alias for the path.
- * @param $language
- * The language of the alias being created.
- * @return
- * TRUE if a redirect was created, or FALSE otherwise.
- */
- function path_redirect_check_alias_changed($path, $new_alias, $language = '') {
- if (!variable_get('path_redirect_auto_redirect', 1) || empty($new_alias)) {
- return FALSE;
- }
-
- $old_alias = drupal_get_path_alias($path, $language);
- if ($old_alias != $path && $old_alias != $new_alias) {
-
- $redirect = array(
- 'source' => $old_alias,
- 'redirect' => $path,
-
- );
- path_redirect_save($redirect);
- return $redirect;
- }
- }
-
- * Implements hook_taxonomy().
- */
- function path_redirect_taxonomy($op, $type, $array = NULL) {
- if ($op == 'delete' && $type == 'term') {
-
- $term = (object) $array;
- $term_uri = taxonomy_term_path($term);
- path_redirect_delete_multiple(NULL, array('source' => $term_uri));
- path_redirect_delete_multiple(NULL, array('redirect' => $term_uri));
- if ($term_uri != "taxonomy/term/{$term->tid}") {
- path_redirect_delete_multiple(NULL, array('source' => "taxonomy/term/{$term->tid}"));
- path_redirect_delete_multiple(NULL, array('redirect' => "taxonomy/term/{$term->tid}"));
- }
- }
- }
-
- * Implements hook_user().
- */
- function path_redirect_user($op, &$edit, &$account, $category = NULL) {
- if ($op == 'delete') {
-
- path_redirect_delete_multiple(NULL, array('source' => 'user/'. $account->uid));
- path_redirect_delete_multiple(NULL, array('redirect' => 'user/'. $account->uid));
- }
- }
-
- * Save an URL redirect to the database.
- */
- function path_redirect_save(&$redirect) {
-
- $redirect += array(
- 'rid' => NULL,
- 'query' => '',
- 'fragment' => '',
- 'language' => '',
- 'type' => variable_get('path_redirect_default_status', 301),
- 'last_used' => time(),
- );
-
-
- if (isset($redirect['source_query']) && is_array($redirect['source_query'])) {
- $redirect['source'] .= '?' . drupal_query_string_encode($redirect['source_query']);
- }
- if (is_array($redirect['query'])) {
- $redirect['query'] = drupal_query_string_encode($redirect['query']);
- }
-
-
-
- $redirect['source'] = str_replace('+', ' ', $redirect['source']);
-
-
-
- $redirect['source'] = trim($redirect['source'], '\/?');
-
- path_redirect_clear_cache();
-
- if (empty($redirect['rid'])) {
- drupal_write_record('path_redirect', $redirect);
- module_invoke_all('path_redirect_insert', $redirect);
- }
- else {
- drupal_write_record('path_redirect', $redirect, array('rid'));
- module_invoke_all('path_redirect_update', $redirect);
- }
-
- return $redirect;
- }
-
- * Load a redirect by ID.
- *
- * @param $rid
- * An integer with the redirect ID.
- */
- function path_redirect_load($rid) {
- $redirect = path_redirect_load_multiple(array($rid));
- return $redirect ? reset($redirect) : FALSE;
- }
-
- * Load a redirect by incoming path and language.
- *
- * @param $source
- * The incoming path.
- * @param $language
- * An optional language code. If not provided this will examine all language-
- * neutral redirects.
- * @param $query
- * An optional query string to match.
- */
- function path_redirect_load_by_source($source, $language = '', $query = array()) {
- $where = $query ? "(source = '%s' OR source LIKE '%s%%')" : "source = '%s'";
- $args = $query ? array($source, $source . '?') : array($source);
- $args[] = $language;
- $rid_query = db_query("SELECT rid FROM {path_redirect} WHERE $where AND language IN ('%s', '') ORDER BY language DESC, source DESC, rid DESC", $args);
- $rids = array();
- while ($rid = db_result($rid_query)) {
- $rids[] = $rid;
- }
-
- if ($rids && $redirects = path_redirect_load_multiple($rids)) {
-
- foreach ($redirects as $rid => $redirect) {
- if (!empty($redirect['source_query'])) {
- if (empty($query) || !path_redirect_compare_array($redirect['source_query'], $query)) {
- unset($redirects[$rid]);
- continue;
- }
- }
-
-
- if ($source !== $redirect['source']) {
- $redirects[$rid]['weight'] = 1;
- }
- }
-
- if (!empty($redirects)) {
-
- uasort($redirects, '_path_redirect_uasort');
-
-
- $context = array('language' => $language, 'query' => $query);
- drupal_alter('path_redirect_load_by_source', $redirects, $source, $context);
-
- return !empty($redirects) ? reset($redirects) : FALSE;
- }
- }
-
- return FALSE;
- }
-
- function path_redirect_load_multiple($rids = NULL, $conditions = array()) {
- if (isset($rids) && empty($rids)) {
- return array();
- }
-
- $query = array();
- _path_redirect_build_conditions($query, $rids, $conditions);
- $sql = "SELECT * FROM {path_redirect} WHERE " . implode(' AND ', $query['conditions']);
- $query = db_query($sql, $query['args']);
-
- $redirects = array();
- while ($redirect = db_fetch_array($query)) {
-
- if (!isset($redirect['source_query']) || !is_array($redirect['source_query'])) {
- $parsed = parse_url($redirect['source']) + array('query' => '');
- $redirect['source_query'] = path_redirect_get_query_array($parsed['query']);
- $redirect['source'] = $parsed['path'];
- }
- $redirect['query'] = path_redirect_get_query_array($redirect['query']);
- $redirects[$redirect['rid']] = $redirect;
- }
-
- return $redirects;
- }
-
- * uasort callback; Compare redirects based on language neutrality and rids.
- */
- function _path_redirect_uasort($a, $b) {
- $a_weight = isset($a['weight']) ? $a['weight'] : 0;
- $b_weight = isset($b['weight']) ? $b['weight'] : 0;
- if ($a_weight != $b_weight) {
-
- return $a_weight > $b_weight;
- }
- elseif ($a['language'] != $b['language']) {
-
- return $a['language'] == '';
- }
- elseif (empty($a['source_query']) != empty($b['source_query'])) {
-
- return empty($a['source_query']);
- }
- else {
-
- return $a['rid'] < $b['rid'];
- }
- }
-
- function _path_redirect_build_conditions(&$query, $rids, $conditions) {
- static $schema;
- if (!isset($schema)) {
- $schema = !defined('MAINTENANCE_MODE') ? drupal_get_schema('path_redirect') : drupal_get_schema_unprocessed('path_redirect', 'path_redirect');
- }
-
- $query += array(
- 'conditions' => array(),
- 'args' => array(),
- );
-
- if ($rids) {
- $conditions += array('rid' => array());
- $conditions['rid'] = array_merge($rids, (array) $conditions['rid']);
- }
- if ($conditions) {
- foreach ($conditions as $field => $value) {
- if (!is_string($field) || !isset($schema['fields'][$field])) {
- continue;
- }
-
-
-
- $type = $schema['fields'][$field]['type'];
- if (is_array($value)) {
- $conditions[$field] = "$field IN (" . db_placeholders($value, $type) . ')';
- $query['args'] = array_merge($query['args'], $value);
- }
- else {
- $conditions[$field] = "$field = " . db_type_placeholder($type);
- $query['args'][] = $value;
- }
- }
- }
- $query['conditions'] = array_merge($query['conditions'], $conditions);
-
- return $query;
- }
-
- function path_redirect_clear_cache() {
- cache_clear_all(NULL, 'cache_page');
- }
-
- * Delete a redirect.
- *
- * @param $rid
- * The ID of the redirect to delete.
- */
- function path_redirect_delete($rid, $deprecated = FALSE) {
-
- if (is_string($rid) && is_string($deprecated)) {
- return path_redirect_delete_multiple(NULL, array('source' => $rid, 'redirect' => $deprecated));
- }
- elseif (is_array($rid) && !isset($rid['rid'])) {
- $rid = $rid['rid'];
- }
-
- return path_redirect_delete_multiple(array($rid));
- }
-
- * Delete multiple redirects.
- *
- * @param $rids
- * An optional array or redirect IDs.
- * @param $conditions
- * An optional array of conditions keyed by field to match.
- * @return
- * The number of deleted redirects.
- */
- function path_redirect_delete_multiple($rids = NULL, $conditions = array()) {
- if ($redirects = path_redirect_load_multiple($rids, $conditions)) {
- foreach ($redirects as $redirect) {
- module_invoke_all('path_redirect_delete', $redirect);
- }
- }
- $query = array();
- _path_redirect_build_conditions($query, $rids, $conditions);
- $sql = 'DELETE FROM {path_redirect} WHERE ' . implode(' AND ', $query['conditions']);
- db_query($sql, $query['args']);
- $deleted = db_affected_rows();
- path_redirect_clear_cache();
- return $deleted;
- }
-
- function path_redirect_get_path($path = NULL) {
- if (!isset($path)) {
- if (drupal_is_front_page()) {
- $path = '<front>';
- }
- else {
- $path = $_GET['q'];
- }
- }
- else {
- if ($path == drupal_get_normal_path(variable_get('site_frontpage', 'node'))) {
- $path = '<front>';
- }
- }
- return $path;
- }
-
- function path_redirect_get_query($query = NULL) {
- if (!isset($query)) {
- $query = $_GET;
- }
- unset($query['q']);
- return $query;
- }
-
- function path_redirect_build_url($path, $query = '', $fragment = '', $clean_url = NULL) {
- if (!isset($clean_url)) {
- $clean_url = variable_get('clean_url', 0);
- }
-
- $url = $path;
- if ($query) {
- $url .= $clean_url ? '?' : '&';
- if (is_array($query)) {
- $url .= drupal_query_string_encode($query);
- }
- else {
- $url .= $query;
- }
- }
- if ($fragment) {
- $url .= '#' . $fragment;
- }
- return $url;
- }
-
- * Compare tha all values and associations in one array match another array.
- *
- * We cannot use array_diff_assoc() here because we need to be recursive.
- *
- * @param $match
- * The array that has the values.
- * @param $haystack
- * The array that will be searched for values.
- */
- function path_redirect_compare_array($match, $haystack) {
- foreach ($match as $key => $value) {
- if (!array_key_exists($key, $haystack)) {
- return FALSE;
- }
- elseif (is_array($value)) {
- if (!is_array($haystack[$key])) {
- return FALSE;
- }
- elseif (!path_redirect_compare_array($value, $haystack[$key])) {
- return FALSE;
- }
- }
- elseif ($value != $haystack[$key]) {
- return FALSE;
- }
- }
- return TRUE;
- }
-
- * Split an URL-encoded query string into an array.
- *
- * @param $query
- * The query string to split.
- *
- * @return
- * An array of url decoded couples $param_name => $value.
- */
- function path_redirect_get_query_array($query) {
- $result = array();
- if (!empty($query)) {
- foreach (explode('&', $query) as $param) {
- $param = explode('=', $param);
- $result[$param[0]] = isset($param[1]) ? rawurldecode($param[1]) : '';
- }
- }
- return $result;
- }
-
- function path_redirect_variables() {
- return array(
- 'path_redirect_redirect_warning' => 0,
- 'path_redirect_allow_bypass' => 0,
- 'path_redirect_auto_redirect' => 1,
- 'path_redirect_purge_inactive' => 0,
- 'path_redirect_default_status' => 301,
- 'path_redirect_nodeapi_enabled' => NULL,
- );
- }
-