gotwo.module in Go - url redirects 7
Same filename and directory in other branches
Module that provides easy to use redirection links. A redirection link would be like: http://examples.org/go/a_label http://examples.org/go/123546 http://examples.org/go/or/like/this
It's much like url aliases except these are redirects
File
gotwo.moduleView source
<?php
/**
* @file
* Module that provides easy to use redirection links. A redirection link
* would be like:
* http://examples.org/go/a_label
* http://examples.org/go/123546
* http://examples.org/go/or/like/this
*
* It's much like url aliases except these are redirects
*/
define('GOTWO_CREATE', 1);
/**
* Implements hook_permission().
*/
function gotwo_permission() {
return array(
'administer gotwo' => array(
'title' => t('Administer gotwo'),
'description' => t('Perform maintenance tasks for Gotwo module.'),
),
'edit gotwo redirects' => array(
'title' => t('Edit gotwo redirects'),
'description' => t("Allow users to add or edit 'go' URLs."),
),
'view gotwo redirects' => array(
'title' => t('View gotwo redirects'),
'description' => t("Allow users to view the existing 'go' URLs."),
),
);
}
/**
* Implements hook_menu().
*/
function gotwo_menu() {
$items['go'] = array(
'page callback' => '_gotwo_do_redir',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['admin/structure/gotwo'] = array(
'title' => 'Go redirects',
'description' => 'You can use the <go> tags just like the <a> for nicer urls.',
'page callback' => '_gotwo_list',
'access arguments' => array(
'view gotwo redirects',
),
'file' => 'gotwo.admin.inc',
);
$items['admin/structure/gotwo/list'] = array(
'title' => 'List',
'access arguments' => array(
'view gotwo redirects',
),
'file' => 'gotwo.admin.inc',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/structure/gotwo/add'] = array(
'title' => 'Add redirect',
'description' => 'Add a new Go redirect',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'gotwo_add_form',
),
'access arguments' => array(
'edit gotwo redirects',
),
'file' => 'gotwo.admin.inc',
'type' => MENU_LOCAL_TASK,
);
$items['admin/structure/gotwo/delete/%gotwo'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array(
'gotwo_delete_form',
4,
),
'access arguments' => array(
'edit gotwo redirects',
),
'file' => 'gotwo.admin.inc',
'type' => MENU_CALLBACK,
);
$items['admin/structure/gotwo/reset/%gotwo'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array(
'gotwo_reset_form',
4,
),
'access arguments' => array(
'edit gotwo redirects',
),
'file' => 'gotwo.admin.inc',
'type' => MENU_CALLBACK,
);
$items['admin/config/search/gotwo'] = array(
'title' => 'Go settings',
'description' => 'Configure URL parameters and disclaimer options.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'gotwo_admin_settings_form',
),
'access arguments' => array(
'administer gotwo',
),
'file' => 'gotwo.admin.inc',
);
return $items;
}
/**
* Menu helper function to verify if gotwo id exists.
*/
function gotwo_load($gid) {
return db_query("SELECT * FROM {gotwo} WHERE gid = :gid", array(
':gid' => $gid,
))
->fetchObject();
}
/**
* Redirect the user to the given location.
*/
function _gotwo_do_redir() {
$args = func_get_args();
$src = implode('/', $args);
// $src may be an GID or a source URL.
$result = db_query("SELECT * FROM {gotwo} WHERE src = :src OR gid = :gid", array(
':src' => $src,
':gid' => intval($src),
))
->fetchObject();
if (!$result) {
drupal_not_found();
}
else {
// Count up the current click counter +1.
db_update('gotwo')
->fields(array(
'cnt' => NULL,
))
->expression('cnt', 'cnt + 1')
->condition('gid', $result->gid)
->execute();
if (variable_get('gotwo_disclaimer_boolean', FALSE)) {
// Display the Disclaimer
$disclaimer_title = variable_get('gotwo_disclaimer_title', 'Disclaimer');
$disclaimer_text = variable_get('gotwo_disclaimer_text', '');
$disclaimer_time = variable_get('gotwo_disclaimer_time', 0);
drupal_set_title($disclaimer_title);
$tokens = array(
'%url',
'%seconds',
);
$token_values = array(
check_url($result->dst),
$disclaimer_time,
);
$page_content = filter_xss_admin(str_replace($tokens, $token_values, $disclaimer_text));
// Should we refresh?
if ($disclaimer_time > 0) {
$disclaimer_meta = array(
'#tag' => 'meta',
'#attributes' => array(
'http-equiv' => 'refresh',
'content' => $disclaimer_time . ';url=' . check_url($result->dst),
),
);
drupal_add_html_head($disclaimer_meta, 'gotwo_disclaimer_refresh');
}
return $page_content;
}
else {
// Parse the URL.
$uri = drupal_parse_url($result->dst);
drupal_goto($uri['path'], array(
'query' => $uri['query'],
'fragment' => $uri['fragment'],
));
}
}
}
/**
* Implements hook_filter_info().
*/
function gotwo_filter_info() {
$filters['gotwo_link'] = array(
'title' => t('"Go" redirection filter'),
'description' => t('Automatically creates redirection urls. <go href=""></go> tags are nicely translated to <a href=""></a> tags.'),
'process callback' => '_gotwo_link',
/* 'settings callback' => '_gotwo_link_settings',
'default settings' => array(
'gotwo_numeric' => variable_get('gotwo_numeric', FALSE),
'gotwo_transliteration' => variable_get('gotwo_transliteration', TRUE),
'gotwo_separator' => variable_get('gotwo_separator', '-'),
'gotwo_max_length' => variable_get('gotwo_max_length', 128),
), */
'tips callback' => '_gotwo_link_tips',
);
return $filters;
}
/**
* Process callback for the GO filter.
*
* This function will load the text into a DOM object, search for <go> elements,
* saves non-existent href's and title's to the {gowto} table and replace the
* <go> tags with it's real <a> links. If defined in the <go> link the href is
* altered as requested. The full text with all links replaced is returned.
*
* @param $text
* A raw text with all <go> links to be processed.
* @return
* A raw text with all <go> links replaced with real <a> links.
*/
function _gotwo_link($text, $filter) {
$html_dom = filter_dom_load($text);
$goNodesToRemove = array();
foreach ($html_dom
->getElementsByTagName('go') as $goNode) {
// Clone <go> link to <a> link and keep all attributes intact.
$linkNode = $goNode->ownerDocument
->createElement('a');
if ($goNode->attributes->length) {
foreach ($goNode->attributes as $attribute) {
$linkNode
->setAttribute($attribute->nodeName, $attribute->nodeValue);
}
}
// Clone all <go> child nodes inside the new <a> tag.
while ($goNode
->hasChildNodes()) {
$childNodes = $goNode->childNodes;
$linkNode
->appendChild($childNodes
->item(0));
}
// Verify if the url exists in the {gotwo} table. If the url is missing,
// add the url with link title to the {gotwo} table.
$href = $goNode
->getAttribute('href');
$title = $goNode
->getAttribute('title');
if (!empty($href)) {
$linkNode
->setAttribute('href', _gotwo_get_url($href, empty($title) ? NULL : $title));
}
// Insert the new $linkNode before the previous $goNode.
$goNode->parentNode
->insertBefore($linkNode, $goNode);
// Save $goNode to remove array. We cannot remove the child here or the DOM
// index will be cluttered and every second <go> link is not replacement.
$goNodesToRemove[] = $goNode;
}
// Now we are able to remove the child's without loosing the index.
foreach ($goNodesToRemove as $goNode) {
$goNode->parentNode
->removeChild($goNode);
}
$text = filter_dom_serialize($html_dom);
return trim($text);
}
/**
* Settings callback for the GO filter.
*/
/*
function _gotwo_link_settings($form, &$form_state, $filter, $format, $defaults) {
$filter->settings += $defaults;
$settings['gotwo_numeric'] = array(
'#type' => 'checkbox',
'#title' => t('Create numerical URLs'),
'#description' => t('Use numbers instead of a human readable URL. Use "go/1234" instead of "go/some/location".'),
'#default_value' => $filter->settings['gotwo_numeric'],
);
$transliterate_dependencies = '<div class="admin-dependencies">';
$transliterate_dependencies .= t('Depends on: !dependencies', array('!dependencies' => (module_exists('transliteration') ? t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => 'Transliteration')) : t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => 'Transliteration')))));
$transliterate_dependencies .= '</div>';
$settings['gotwo_transliteration'] = array(
'#type' => 'checkbox',
'#title' => t('Transliterate URLs'),
'#description' => t('Enables <a href="!url">transliteration</a> of URLs. Generally spoken, it takes Unicode text and tries to represent it in US-ASCII characters (universally displayable, unaccented characters) by attempting to transliterate the pronunciation expressed by the text in some other writing system to Roman letters.', array('!url' => 'http://drupal.org/project/transliteration')) . $transliterate_dependencies,
'#default_value' => $filter->settings['gotwo_transliteration'],
'#disabled' => (module_exists('transliteration') ? FALSE : TRUE),
);
$settings['gotwo_separator'] = array(
'#type' => 'select',
'#title' => t('URL separator'),
'#description' => t('All spaces in URLs can be replaced with an underscore or hyphen. If set to "-", an URL of "Lorem ipsum dolor" becomes "Lorem-ipsum-dolor".'),
'#default_value' => $filter->settings['gotwo_separator'],
'#options' => array(
'-' => t('Hyphen (-)'),
'_' => t('Underscore (_)'),
),
);
$settings['gotwo_max_length'] = array(
'#type' => 'textfield',
'#title' => t('Maximum length of target labels'),
'#description' => t('Target labels are the parts after the "go/" part of the shown url. The absolute maximum is 128.'),
'#default_value' => $filter->settings['gotwo_max_length'],
'#element_validate' => array('_gotwo_element_max_length_validate'),
'#size' => 10,
);
return $settings;
}
*/
/**
* Filter tips callback for GO filter.
*/
function _gotwo_link_tips($filter, $format, $long = FALSE) {
return t('You can use the <go> tags just like the <a> for nicer urls.');
}
/**
* Element settings validation.
*/
function _gotwo_element_max_length_validate(&$element, &$form_state) {
$value = isset($element['#value']) ? $element['#value'] : $element['#default_value'];
if ($value < 10 || $value > 128) {
form_error($element, t('The value for %element-title cannot be less than 10 and not more than 128.', array(
'%element-title' => $element['#title'],
)));
}
return $element;
}
/**
* Return the GO url for a given link.
*/
function _gotwo_get_url($url, $src = NULL, $flags = GOTWO_CREATE) {
$res = _gotwo_get($url, $src, $flags);
if (!$res) {
return url($url);
}
if (variable_get('gotwo_numeric', FALSE)) {
return url('go/' . $res->gid);
}
return url('go/' . $res->src);
}
/**
* Return the GO object url for a given link.
*/
function _gotwo_get($url, $src = NULL, $flags = GOTWO_CREATE) {
// Only add valid URLs to the database. Otherwise the disclaimer reload may fail.
if (!valid_url($url)) {
return FALSE;
}
// If there is no title to mangle, use the url without schema instead.
if (!$src) {
$src = preg_replace('#^(http(s)?://)#', '', $url);
}
$src = _gotwo_cleanstring($src);
$maxlength = variable_get('gotwo_max_length', 128);
$res = db_query("SELECT * FROM {gotwo} WHERE src = :src AND dst = :dst", array(
':src' => $src,
':dst' => $url,
))
->fetchObject();
if ($res === FALSE) {
$res = db_query("SELECT * FROM {gotwo} WHERE src = gid+:src AND dst = :dst", array(
':src' => '/' . $src,
':dst' => $url,
))
->fetchObject();
if (!empty($res)) {
$src_old = substr($res->gid . '/' . $src, 0, $maxlength);
if ($src_old != $res->src) {
$res == FALSE;
}
}
}
if ($res === FALSE) {
$res = new stdClass();
if ($flags & GOTWO_CREATE) {
// Force unique src.
$res = db_query("SELECT * FROM {gotwo} WHERE src = :src", array(
':src' => $src,
))
->fetchObject();
if (!empty($res)) {
// TODO: find a better solution.
// Insert a dummy first with an uniqe src value to get the 'gid' value.
$gid = db_insert('gotwo')
->fields(array(
'src' => uniqid(),
'dst' => $url,
))
->execute();
$src = substr($gid . '/' . $src, 0, $maxlength);
db_update('gotwo')
->fields(array(
'src' => $src,
))
->condition('gid', $gid)
->execute();
$res->gid = $gid;
$res->src = $src;
$res->dst = $url;
}
else {
$gid = db_insert('gotwo')
->fields(array(
'src' => $src,
'dst' => $url,
))
->execute();
$res->gid = $gid;
$res->src = $src;
$res->dst = $url;
}
}
else {
return FALSE;
}
}
return $res;
}
/**
* Mangle the input for url friendlyness. Based on pathauto_cleanstring from pathauto.module
*/
function _gotwo_cleanstring($string) {
// Transliterate the URL with transliteration module.
if (module_exists('transliteration') && variable_get('gotwo_transliteration', TRUE)) {
$string = transliteration_get($string, '?', language_default('language'));
}
$output = str_replace("'", "", $string);
$pattern = '#[^a-zA-Z0-9./]+# ';
$separator = variable_get('gotwo_separator', '-');
$output = preg_replace($pattern, $separator, $output);
if ($separator) {
if (ctype_alnum($separator)) {
$seppattern = $separator;
}
else {
$seppattern = '\\' . $separator;
}
$output = preg_replace("/^{$seppattern}+|{$seppattern}+\$/", "", $output);
}
$maxlength = variable_get('gotwo_max_length', 128);
$output = substr($output, 0, $maxlength);
return $output;
}
Functions
Name![]() |
Description |
---|---|
gotwo_filter_info | Implements hook_filter_info(). |
gotwo_load | Menu helper function to verify if gotwo id exists. |
gotwo_menu | Implements hook_menu(). |
gotwo_permission | Implements hook_permission(). |
_gotwo_cleanstring | Mangle the input for url friendlyness. Based on pathauto_cleanstring from pathauto.module |
_gotwo_do_redir | Redirect the user to the given location. |
_gotwo_element_max_length_validate | Element settings validation. |
_gotwo_get | Return the GO object url for a given link. |
_gotwo_get_url | Return the GO url for a given link. |
_gotwo_link | Process callback for the GO filter. |
_gotwo_link_tips | Filter tips callback for GO filter. |
Constants
Name![]() |
Description |
---|---|
GOTWO_CREATE | @file Module that provides easy to use redirection links. A redirection link would be like: http://examples.org/go/a_label http://examples.org/go/123546 http://examples.org/go/or/like/this |