| 4.6 path.module | path_set_alias($path = NULL, $alias = NULL, $pid = NULL) |
| 4.7 path.module | path_set_alias($path = NULL, $alias = NULL, $pid = NULL) |
| 5 path.module | path_set_alias($path = NULL, $alias = NULL, $pid = NULL) |
| 6 path.module | path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $language = '') |
Set an aliased path for a given Drupal path, preventing duplicates.
Parameters
$path: Path URL. Set to NULL to delete alias.
$alias: Alias URL. Set to NULL to delete alias.
$pid: Path id to update. Set to NULL to create a new alias or to delete a group of aliases.
$language: The language this alias is valid for.
2 calls to path_set_alias()
- path_admin_form_submit in modules/
path/ path.admin.inc - Save a new URL alias to the database.
- path_nodeapi in modules/
path/ path.module - Implementation of hook_nodeapi().
File
- modules/
path/ path.module, line 96 - Enables users to rename URLs.
Code
function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $language = '') {
/* This function claimed to prevent duplicate aliases but has not done
* so since the end of 2007.
* The uniqueness of dst+language pairs was enforced on the database level
* until D6.16 (march 2010); trying to insert duplicate aliass would yield a
* database error.
* From D6.16 onwards, duplicates would silently be inserted, and
* drupal_lookup_path() consistently uses those newer aliases.
* While fixing an issue in D6.23, the behavior was reverted to preventing
* duplicates by the below code. Watchdog errors are now logged instead.
*/
$path = urldecode($path);
$alias = urldecode($alias);
// First we check if we deal with an existing alias and delete or modify it based on pid.
if ($pid) {
// An existing alias.
if (!$path || !$alias) {
// Delete the alias based on pid.
db_query('DELETE FROM {url_alias} WHERE pid = %d', $pid);
}
else {
// Update the existing alias.
// Check if the alias exists already.
$existing = db_fetch_array(db_query("SELECT pid, src FROM {url_alias} WHERE dst = '%s' AND language = '%s' ORDER BY pid DESC", $alias, $language));
if (!$existing || ($existing['pid'] == $pid && $existing['src'] != $path)) {
db_query("UPDATE {url_alias} SET src = '%s', dst = '%s', language = '%s' WHERE pid = %d", $path, $alias, $language, $pid);
}
else {
if ($existing['src'] != $path) {
watchdog('path', "The alias for path '@path' (language '@lang') was not updated to '@alias', because the path '@expath' already has the same alias.", array('@path' => $path, '@lang' => $language, '@alias' => $alias, '@expath' => $existing['src']), WATCHDOG_ERROR);
}
// Don't clear cache if we didn't change anything
return;
}
}
}
elseif ($path && $alias) {
// Add this alias to the database, if it's new & doesn't cause conflicts.
$existing = db_fetch_array(db_query("SELECT src, language, pid FROM {url_alias} WHERE dst = '%s' AND language IN('%s', '') ORDER BY language DESC, pid DESC", $alias, $language));
if (!$existing || ($existing['language'] != $language && $existing['src'] != $path)) {
// A new alias. Add it to the database.
db_query("INSERT INTO {url_alias} (src, dst, language) VALUES ('%s', '%s', '%s')", $path, $alias, $language);
}
elseif ($existing['language'] != $language) {
// This alias already exists ONLY for 'language neutral': update language.
// (We can only get here if $language != '')
db_query("UPDATE {url_alias} SET language = '%s' WHERE pid = %d", $language, $existing['pid']);
}
else {
if ($existing['src'] != $path) {
watchdog('path', "The alias '@alias' for path '@path' (language '@lang') was not created, because the path '@expath' already has the same alias.", array('@path' => $path, '@lang' => $language, '@alias' => $alias, '@expath' => $existing['src']), WATCHDOG_ERROR);
}
// Don't clear cache if we didn't change anything
return;
}
}
else {
// Delete the alias.
if ($alias) {
db_query("DELETE FROM {url_alias} WHERE dst = '%s'", $alias);
}
else {
db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
}
}
drupal_clear_path_cache();
}
Comments
D7: path_save
PermalinkIn Drupal 7, the analogous function is path_save
http://api.drupal.org/api/drupal/includes--path.inc/function/path_save/7
My Edge Case
PermalinkThis is how I used path_set_alias to clean out some bad characters when pathauto was not an option (for various reasons).
$updated = mymodule_clean_aliases('/[^a-zA-Z0-9\/_\-.áíóéñ]/', TRUE);/**
* Clean out bad characters from url aliases.
*
* Opens each url alias and examines each character to ensure its an approved
* character. If the character is not allowed, a clean version of the url
* alias will be generated and the current aliases replaced. Optionally a
* redirect will be established from the old corrupt alias to the new.
*
* @param string $not_pattern
* Regex pattern. Characters not contained in the pattern will be removed.
* If the pattern is '/[^a]/' then everything but the character 'a' will be
* stripped.
* @param bool $redirect
* Set to TRUE if a redirect should be setup for the old alias. Defaults to
* FALSE.
*
* @return
* (int) Number of aliases changed.
*/
function mymodule_clean_aliases($not_pattern, $redirect = FALSE) {
$changed = 0;
$result = db_query('SELECT * FROM url_alias');
while ($url_alias = db_fetch_object($result)) {
$new_alias = preg_replace($not_pattern, '', $url_alias->dst);
if ($new_alias != $url_alias->dst) {
/** Create redirect from old alias to actual node. */
if (function_exists('path_redirect_check_alias_changed')) {
path_redirect_check_alias_changed($url_alias->src, $new_alias);
}
/** Remove the old alias. */
path_set_alias(NULL, $url_alias->dst, NULL);
/** Create new alias. */
path_set_alias($url_alias->src, $new_alias, NULL);
$changed++;
}
}
return $changed;
}