If the user leaves the path alias field empty, this module will auto-generate the path. Optionaly information about creation date can be included in the path.
There is a lot of opinions on the best way to do this generation. Everyone seams to have their own idea on what should be included in the path and how it should be ordered. So I wrote the code so that it's fairly easy to add new methods for path generation.
One problem with this module is that it may wake expections that it does not fill. In a url like this www.domain.com/2004/10/23/a-title users may expect that shortening the url to www.domain.com/2004/10 will show the nodes from october.
In order to use the module, copy the code into a file named "path_automatic.module" and drop into your module folder.
// $Id: path_automatic_automatic.module,v 0.1 2004/12/21 21:22:26 Tommy Sundström Exp $
/**
* This module auto-generates a path alias.
*
* It needs path.module in order to work.
*/
/**
* Implementation of hook_help().
*
*/
function path_automatic_help($section) {
switch ($section) {
case 'admin/modules#description':
// This description is shown in the listing at admin/modules.
return t('If the path module is active, renames the URLs automaticly.');
}
}
/**
* Settings for how the path will get generated.
*/
function path_automatic_settings() {
if (module_exist(path)) {
if (user_access('create url aliases') || user_access('administer url aliases')) {
$methods = array(
array('value' => 'default',
'label' => 'Just title',
'descr' => '<p>'.t('If Path Alias field is left blank, generates a path from the title.').'</p>'
),
array('value' => 'yearmonth',
'label' => 'Include year and month',
'descr' => '<p>'.t('Includes the creation month in the path, in addition to the title.').'</p>'
),
array('value' => 'yearmonthday',
'label' => 'Include year, month and day',
'descr' => '<p>'.t('Includes the creation date in the path, in addition to the title.').'</p>'
),
);
$options = array();
$description = '<br /><dl>';
foreach($methods as $method) {
$options[$method['value']] = $method['label'];
$description .= '<dt>'.$method['label'].'</dt>';
$description .= '<dd>'.$method['descr'].'</dd>';
}
$description .= '</dl>';
$output = form_select(t('Choose path generation method'),
'path_automatic_method',
variable_get('path_automatic_method','default'),
$options,
$description
);
//)
//$extra = 0, $multiple = FALSE, $required = FALSE);
}
else {
$output = t('You need permission from the path module to <i>create url aliases</i> or <i>administer url aliases</i> for this module to work');
}
}
else {
$output = t('This module requires that the path module <a href="/admin/modules">is activated</a>.');
}
return $output;
}
/**
* Implementation of hook_nodeapi().
*
* Allows URL aliases for nodes to be specified at node edit time rather
* than through the administrative interface.
*/
function path_automatic_nodeapi(&$node, $op, $arg) {
if (module_exist(path) && (user_access('create url aliases') || user_access('administer url aliases'))) {
switch ($op) {
case 'validate':
// (This is not realy validation, but this is the best place to patch in this funtionality.)
$node->path = trim($node->path);
// If no path alias is given and autogenerate is true (in settings), auto generates a path alias from the title.
if (!$node->path) {
// No alias, generating it
if ($node->title) {
$method = variable_get('path_automatic_method','default');
$pathstart = '';
// generate pathstart
switch ($method) {
case 'default':
// No need to do anything
break;
case 'yearmonth':
$pathstart = date('Y/m',$node->created) . '/';
break;
case 'yearmonthday':
$pathstart = date('Y/m/d',$node->created) . '/';
break;
default:
$pathstart = die('Error: the method given path_automatic does not exist');
}
if (strstr($pathstart,'***NOT_VALID***')) {
// One (or more) of the stringToPath has failed.
break;
}
// generate the path equivalent of the title
$pathtitle = stringToPath($node->title);
if ($pathtitle == '***NOT_VALID***') {
// The stringToPath has failed.
break;
}
// validate the path
if (path_automatic_check_if_already_in_use($pathstart.$pathtitle, "node/$node->nid")) {
// If in use, leave path blank
break;
}
// create path
$node->path = $pathstart.$pathtitle;
}
}
}
}
}
/**
* Clean a string so that it can be used as a path.
*/
function stringToPath($str) {
$str = strip_tags($str);
// Accented characters
$from = 'ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ';
$to = 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';
for ($n=0; $n < strlen($to); $n++) {
$str=str_replace(utf8_encode(substr($from, $n, 1)), substr($to, $n, 1), $str);
}
// Interpunction etc
$str = preg_replace("/[ \/_]/", "-", $str); // replace with dash
$str = preg_replace("/[.,:;!?¤%&(){}@£$€<>|=*[\]\"\'\\\\]/", "", $str); // remove
$str = preg_replace("/-+/", "-", $str); // collapse mulitple dashes into one
$str = trim($str);
$str = strtolower($str);
$str = urlencode($str);
if (!valid_url($str)) {
// valid_url will not accept all urls that urlencode can generate (it does not seam to accept the %-encoding)
// This should be a rare problem, but to be sure, skip path generation when this is the case.
// (It will only be the case when the title contains other characters than a-z and the ones transformed above.)
return ('***NOT_VALID***'); //$str = '';
}
return ($str);
}
/**
* Check that a path alias is not already in use.
*/
function path_automatic_check_if_already_in_use($aliaspath, $realpath) {
if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND src != '%s'", $aliaspath, $realpath))) {
return TRUE; // In use
}
else {
return FALSE; // Free to use
}
}