--- pathauto.module 2007-09-17 15:31:44.000000000 -0500 +++ pathauto_nt.module 2007-10-08 15:39:11.000000000 -0500 @@ -1,538 +1,558 @@ -Provides a mechanism for modules to automatically generate aliases for the content they manage.

-

Settings

-

The Maximum Alias Length and Maximum component length values - default to 100 and have a limit of 128 from pathauto. This length is limited by the length of the dst - column of the url_alias database table. The default database schema for this column is 128. If you - set a length that is equal to that of the one set in the dst column it will cause problems in situations - where the system needs to append additional words to the aliased URL. For example... URLs generated - for feeds will have '/feed' added to the end. You should enter a value that is the length of the dst - column minus the length of any strings that might get added to the end of the URL. The length of - strings that might get added to the end of your URLs depends on which modules you have enabled and - on your Pathauto settings. The recommended and default value is 100.

"); - break; - } - - return $output; -} - -/** - * Implementation of hook_perm - */ -function pathauto_perm() { - return array('administer pathauto'); -} - -/* - * Implementation of hook_menu - */ -function pathauto_menu($may_cache) { - - $items = array(); - if ($may_cache) { - $items[] = array( - 'path' => 'admin/settings/pathauto', - 'title' => t('Pathauto'), - 'description' => t('Configure how pathauto generates clean URLs for your content.'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('pathauto_admin_settings'), - 'access' => user_access('administer pathauto'), - 'type' => MENU_NORMAL_ITEM, - ); - $items[] = array( - 'path' => 'admin/build/path/delete_bulk', - 'title' => t('Delete aliases'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('pathauto_admin_delete'), - 'access' => user_access('administer url aliases'), - 'type' => MENU_LOCAL_TASK, - ); - } - - return $items; -} - - -/** - * Include all pathauto include files - */ -function _pathauto_include() { - $pathauto_path = drupal_get_path('module', 'pathauto'); - include_once("$pathauto_path/pathauto.inc"); - include_once("$pathauto_path/pathauto_node.inc"); - include_once("$pathauto_path/pathauto_taxonomy.inc"); - include_once("$pathauto_path/pathauto_user.inc"); -} - - -/** - * Callback for admin settings page - * - */ -function pathauto_admin_settings() { - _pathauto_include(); - - // Restrict administration of this module - if (!user_access('administer pathauto')) { - $form["error"] = array('#type' => 'item', - '#title' => t('You are not authorized to access the pathauto settings.')); - return system_settings_form($form); - } - - // Default words to ignore - $ignore_words = array( - "a", "an", "as", "at", "before", "but", "by", "for", "from", "is", "in", - "into", "like", "of", "off", "on", "onto", "per", "since", "than", "the", - "this", "that", "to", "up", "via", "with" - ); - - // Generate the form - settings applying to all patterns first - $group_weight = -20; - $form["general"] = array('#type' => 'fieldset', '#weight' => $group_weight, - '#title' => t('General settings'), '#collapsible' => TRUE, - '#collapsed' => TRUE); - $group_weight++; - - $form["general"]["pathauto_verbose"] = array('#type' => 'checkbox', - '#title' => t('Verbose'), - '#default_value' => variable_get('pathauto_verbose', FALSE), - '#description' => t('Display alias changes (except during bulk updates).')); - - $form["general"]["pathauto_separator"] = array('#type' => 'textfield', - '#title' => t('Separator'), '#size' => 1, '#maxlength' => 1, - '#default_value' => variable_get('pathauto_separator', '-'), - '#description' => t('Character used to separate words in titles. This will replace any spaces and punctuation characters.')); - - $form["general"]["pathauto_quotes"] = array('#type' => 'radios', - '#title' => t('Quotation marks'), - '#default_value' => variable_get('pathauto_quotes', 0), - '#options' => array(t('Remove'), t('Replace by separator')), - ); - - $form["general"]["pathauto_case"] = array('#type' => 'radios', - '#title' => t('Character case'), - '#default_value' => variable_get('pathauto_case', 1), - '#options' => array(t('Leave case the same as source token values.'), t('Change to lower case')), - ); - - - $form["general"]["pathauto_max_length"] = array('#type' => 'textfield', - '#title' => t('Maximum alias length'), '#size' => 3, '#maxlength' => 3, - '#default_value' => variable_get('pathauto_max_length', 100), - '#description' => t('Maximum length of aliases to generate. 100 is recommended. See Pathauto help for details.', array('@pathauto-help' => url('admin/help/pathauto')))); - - $form["general"]["pathauto_max_component_length"] = array('#type' => 'textfield', - '#title' => t('Maximum component length'), '#size' => 3, '#maxlength' => 3, - '#default_value' => variable_get('pathauto_max_component_length', 100), - '#description' => t('Maximum text length of any component in the alias (e.g., [title]). 100 is recommended. See Pathauto help for details.', array('@pathauto-help' => url('admin/help/pathauto')))); - - $form["general"]["pathauto_max_bulk_update"] = array('#type' => 'textfield', - '#title' => t('Maximum number of objects to alias in a bulk update'), '#size' => 3, '#maxlength' => 3, - '#default_value' => variable_get('pathauto_max_bulk_update', 50), - '#description' => t('Maximum number of objects of a given type which should be aliased during a a bulk update. The default is 50 and the recommended number depends on the speed of your server. If bulk updates "time out" or result in a "white screen" then reduce the number.')); - - $form["general"]["pathauto_update_action"] = array('#type' => 'radios', - '#title' => t('Update action'), '#default_value' => variable_get('pathauto_update_action', 2), - '#options' => array(t('Do nothing, leaving the old alias intact'), - t('Create a new alias in addition to the old alias'), - t('Create a new alias, replacing the old one')), - '#description' => t('What should pathauto do when updating an existing content item which already has an alias?')); - - $disable_transliteration = TRUE; - $disable_text = ""; - $path = drupal_get_path('module', 'pathauto'); - $transliteration_help = "When a pattern includes certain characters (such as those with accents) should Pathauto attempt to transliterate them into the ASCII-96 alphabet? Transliteration is determined by the i18n-ascii.txt file in the Pathauto directory. This option is disabled on your site because you do not have an i18n-ascii.txt file in the Pathauto directory."; - if (is_file($path .'/i18n-ascii.txt')) { - $disable_transliteration = FALSE; - $transliteration_help = "When a pattern includes certain characters (such as those with accents) should Pathauto attempt to transliterate them into the ASCII-96 alphabet? Transliteration is determined by the i18n-ascii.txt file in the Pathauto directory."; - } - - $form["general"]["pathauto_transliterate"] = array('#type' => 'checkbox', - '#title' => t('Transliterate prior to creating alias'), - '#default_value' => variable_get('pathauto_transliterate', FALSE), - '#description' => t($transliteration_help), - '#disabled' => $disable_transliteration, - ); - - $form["general"]["pathauto_ignore_words"] = array('#type' => 'textarea', - '#title' => t('Strings to Remove'), '#default_value' => variable_get('pathauto_ignore_words', implode(",", $ignore_words)), - '#description' => t('Words to strip out of the URL alias, separated by commas') - ); - - // Call the hook on all modules - an array of 'settings' objects is returned - $all_settings = module_invoke_all('pathauto', 'settings'); - $modulelist = ''; - $indexcount = 0; - foreach ($all_settings as $settings) { - $items = ''; - $module = $settings->module; - $modulelist[] = $module; - $patterndescr = $settings->patterndescr; - $patterndefault = $settings->patterndefault; - $groupheader = $settings->groupheader; - $supportsfeeds = isset($settings->supportsfeeds) ? $settings->supportsfeeds : NULL; - variable_set('pathauto_'. $module .'_supportsfeeds', $supportsfeeds); - - $form[$module] = array('#type' => 'fieldset', - '#title' => $groupheader, '#weight' => $group_weight, - '#collapsible' => TRUE, '#collapsed' => TRUE); - $group_weight++; - - // Prompt for the default pattern for this module - $variable = 'pathauto_'. $module .'_pattern'; - $form[$module][$variable] = array('#type' => 'textfield', - '#title' => $patterndescr, - '#default_value' => variable_get($variable, $patterndefault), - '#size' => 65, '#maxlength' => 128); - - // If the module supports a set of specialized patterns, set - // them up here - if (isset($settings->patternitems)) { - foreach ($settings->patternitems as $itemname => $itemlabel) { - $variable = 'pathauto_'. $module .'_'. $itemname .'_pattern'; - $form[$module][$variable] = array('#type' => 'textfield', - '#title' => $itemlabel, - '#default_value' => variable_get($variable, ''), - '#size' => 65, '#maxlength' => 128); - } - } - - // Display the user documentation of placeholders supported by - // this module, as a description on the last pattern - $doc = "
\n"; - foreach ($settings->placeholders as $name => $description) { - $doc .= '
'. $name .'
'; - $doc .= '
'. $description .'
'; - } - $doc .= "
\n"; - $form[$module][$variable]["#description"] = $doc; - - // If the module supports bulk updates, offer the update action here - if ($settings->bulkname) { - $variable = 'pathauto_'. $module .'_bulkupdate'; - if (variable_get($variable, FALSE)) { - variable_set($variable, FALSE); - $function = $module .'_pathauto_bulkupdate'; - call_user_func($function); - } - $form[$module][$variable] = array('#type' => 'checkbox', - '#title' => $settings->bulkname, - '#default_value' => FALSE, - '#description' => $settings->bulkdescr); - } - - // Perform bulk updates of indexes for this module, if asked - if ($do_index_bulkupdate) { - $function = $module .'_pathauto_bulkupdate_indexes'; - if (is_callable($function)) { - $indexcount += call_user_func($function); - } - } - - // If the module supports feeds, offer to generate aliases for them - if ($supportsfeeds) { - $variable = 'pathauto_'. $module .'_applytofeeds'; - $form[$module][$variable] = array('#type' => 'checkbox', - '#title' => t('Create feed aliases'), - '#default_value' => variable_get($variable, FALSE), - '#description' => t('Also generate aliases for RSS feeds.')); - } - - } - - if ($do_index_bulkupdate) { - drupal_set_message(format_plural($indexcount, - "Bulk generation of index aliases completed, one alias generated.", - "Bulk generation of index aliases completed, @count aliases generated.")); - } - - // Keep track of which modules currently support pathauto - variable_set('pathauto_modulelist', $modulelist); - - return system_settings_form($form); -} - -/** - * Implementation of hook_token_values() for Pathauto specific tokens - */ -function pathauto_token_values($type, $object = NULL) { - - if (module_exists('taxonomy')) { - switch ($type) { - case 'node': - $vid = db_result(db_query("SELECT t.vid FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.nid = %d ORDER BY v.weight, t.weight, t.name LIMIT 1", $object->nid)); - $category = db_fetch_object(db_query("SELECT t.tid, t.name FROM {term_data} t INNER JOIN {term_node} r ON r.tid = t.tid WHERE t.vid = %d AND r.nid = %d ORDER BY weight LIMIT 1", $vid, $object->nid)); - $category->vid = $vid; - case 'taxonomy': - if (!isset($category)) { - $category = $object; - } - - $parents = taxonomy_get_parents_all($category->tid); - foreach ($parents as $parent) { - // Replace any / characters in individual terms which might create confusing URLs - $separator = variable_get('pathauto_separator', '-'); - $catpath = preg_replace('/\//', '', $parent->name) .'/'. $catpath; - } - $values['catpath'] = $catpath; - - if ($type == 'taxonomy') { - $values['cat'] = $category->name; - } - - $values['catalias'] = drupal_get_path_alias('taxonomy/term/'.$category->tid); - if (!strncasecmp($values['catalias'], 'taxonomy', 8)) { - $values['catalias'] = $values['cat']; - } - - - break; - } - } - // Provide some defaults if they aren't set. - if (!isset($values['catpath'])) { - $values['catpath'] = ''; - $values['catalias'] = ''; - } - - return $values; -} - -/** - * Implementation of hook_token_list() for Pathauto specific tokens - */ -function pathauto_token_list($type = 'all') { - $tokens = array(); - if (module_exists('taxonomy')) { - if ($type == 'taxonomy' || $type == 'all') { - $tokens['taxonomy']['catpath'] = t("As [cat], but including its supercategories separated by /."); - $tokens['taxonomy']['catalias'] = t("URL alias for the category."); - } - if ($type == 'node' || $type == 'all') { - $tokens['node']['catpath'] = t("As [cat], but including its supercategories separated by /."); - $tokens['node']['catalias'] = t("URL alias for the term."); - } - } - return $tokens; -} - -/** - * Menu callback: select certain alias types to delete - */ -function pathauto_admin_delete() { - /* TODO: - 1) all - DONE - 2) all node aliases - DONE - 4) all user aliases - DONE - 5) all taxonomy aliases - DONE - 6) by node type - 7) by taxonomy vocabulary - 8) no longer existing aliases (see http://drupal.org/node/128366 ) - 9) where src like 'pattern' - DON'T DO - 10) where dst like 'pattern' - DON'T DO - */ - - $form = array(); - $form["delete"] = array('#type' => 'fieldset', - '#title' => t('Choose Aliases to Delete'), '#collapsible' => FALSE, - '#collapsed' => FALSE); - - // First we do the "all" case - $total_count = db_result(db_query("SELECT count(1) FROM {url_alias}")); - $form['delete']['all_aliases'] = array('#type' => 'checkbox', - '#title' => t('all aliases'), - '#default_value' => FALSE, - '#description' => t('Delete all aliases. Number of aliases which will be deleted: %count.', array('%count' => $total_count))); - - // Next, iterate over an array of objects/alias types which can be deleted and provide checkboxes - $objects = _pathauto_objects_to_delete(); - foreach ($objects as $internal_name => $label) { - $count = db_result(db_query("SELECT count(1) FROM {url_alias} WHERE src LIKE '%s%%'", $internal_name)); - $form['delete'][$internal_name] = array('#type' => 'checkbox', - '#title' => t($label), - '#default_value' => FALSE, - '#description' => t('Delete aliases for all @label. Number of aliases which will be deleted: %count.', array('@label' => $label, '%count' => $count))); - } - - // Warn them and give a button that shows we mean business - $form["warning"] = array('#value' => t('

Note: there is no confirmation. Be sure of your action before clicking the "Delete aliases now!" button. You may want to make a backup of the database and/or the url_alias table prior to using this feature.

')); - $form['buttons']['submit'] = array( - '#type' => 'submit', - '#value' => t('Delete aliases now!'), - ); - - return $form; -} - -/** - * Submit handler for the bulk delete form - */ -function pathauto_admin_delete_submit($form_id, $form_values) { - foreach ($form_values as $key => $value) { - if ($value) { - if ($key == 'all_aliases') { - db_query('DELETE FROM {url_alias}'); - drupal_set_message(t('All of your path aliases have been deleted.')); - } - $objects = _pathauto_objects_to_delete(); - if (array_key_exists($key, $objects)) { - drupal_set_message($key); - db_query("DELETE FROM {url_alias} WHERE src LIKE '%s%%'", $key); - drupal_set_message(t('All of your %type path aliases have been deleted.', array('%type' => $objects[$key]))); - } - } - } - return 'admin/build/path/delete_bulk'; -} - -function _pathauto_objects_to_delete() { - return array('user/' => t('users'), 'node/' => t('content') , 'taxonomy/' => t('vocabularies and terms'), 'blog/' => t('user blogs'), 'user/%/track' => t('user trackers')); -} - -//============================================================================== -// Some node related functions. - -/** - * Implementation of hook_nodeapi(). - */ -function pathauto_nodeapi(&$node, $op, $teaser, $page) { - _pathauto_include(); - if (module_exists('path')) { - switch ($op) { - case 'insert': - case 'update': - if ($node->pathauto_perform_alias || !isset($node->pathauto_perform_alias)) { - $placeholders = pathauto_get_placeholders('node', $node); - $src = "node/$node->nid"; - $alias = pathauto_create_alias('node', $op, $placeholders, $src, $node->type); - } - break; - default: - break; - } - } -} - -/** - * Implementation of hook_form_alter(). - * - * This allows alias creators to override Pathauto and specify their - * own aliases (Pathauto will be invisible to other users). Inserted - * into the path module's fieldset in the node form. - */ -function pathauto_form_alter($formid, &$form) { - if (isset($form['#id']) && ($form['#id'] == 'node-form')) { - if (user_access('create url aliases')) { - $output .= t('An alias will be generated for you. If you wish to create your own alias below, untick this option.'); - if (user_access('administer pathauto')) { - $output .= t(' To control the format of the generated aliases, see the Pathauto settings.'); - } - - drupal_add_js(drupal_get_path('module', 'pathauto') . '/pathauto.js'); - - $form['path']['pathauto_perform_alias'] = array('#type' => 'checkbox', - '#title' => t('Automatic alias'), - '#default_value' => TRUE, - '#description' => $output, - '#weight' => 0 - ); - } - } -} - -//============================================================================== -// Taxonomy related functions. -/** - * Implementation of hook_taxonomy(). - */ -function pathauto_taxonomy($op, $type, $object = NULL) { - _pathauto_include(); - - switch ($type) { - case 'term': - switch ($op) { - case 'insert': - case 'update': - /* - ** Use the category info to automatically create an alias - */ - $category = (object) $object; - if ($category->name) { - $count = _taxonomy_pathauto_alias($category, $op); - } - break; - case 'delete': - //If the category is deleted, remove the path aliases - $category = (object) $object; - path_set_alias('taxonomy/term/'. $category->tid); - path_set_alias('forum/'. $category->tid); - path_set_alias('taxonomy/term/'. $category->tid .'/0/feed'); - break; - default: - break; - } - break; - default: - break; - } -} - - -//============================================================================== -// User related functions. - -/** - * Implementation of hook_user() for users, trackers, and blogs - */ -function pathauto_user($op, &$edit, &$user, $category = FALSE) { - _pathauto_include(); - switch ($op) { - case 'insert': - case 'update': - /* - ** Use the username to automatically create an alias - */ - $pathauto_user = (object) array_merge((array) $user, $edit); - if ($user->name) { - $placeholders = pathauto_get_placeholders('user', $pathauto_user); - $src = 'user/'. $user->uid; - $alias = pathauto_create_alias('user', $op, $placeholders, $src); - if (module_exists('blog')) { - $src = 'blog/'. $user->uid; - $alias = pathauto_create_alias('blog', $op, $placeholders, $src); - } - if (module_exists('tracker')) { - $src = 'user/'. $user->uid .'/track'; - $alias = pathauto_create_alias('tracker', $op, $placeholders, $src); - } - } - break; - case 'delete': - /* - ** If the user is deleted, remove the path aliases - ** - */ - $user = (object) $user; - path_set_alias('user/'. $user->uid); - - // They may have enabled these modules and/or feeds when the user was created, so let's try to delete all of them - path_set_alias('blog/'. $user->uid); - path_set_alias('blog/'. $user->uid .'/feed'); - path_set_alias('user/'. $user->uid .'/track'); - path_set_alias('user/'. $user->uid .'/track/feed'); - - break; - default: - break; - } -} +Provides a mechanism for modules to automatically generate aliases for the content they manage.

+

Settings

+

The Maximum Alias Length and Maximum component length values + default to 100 and have a limit of 128 from pathauto. This length is limited by the length of the dst + column of the url_alias database table. The default database schema for this column is 128. If you + set a length that is equal to that of the one set in the dst column it will cause problems in situations + where the system needs to append additional words to the aliased URL. For example... URLs generated + for feeds will have '/feed' added to the end. You should enter a value that is the length of the dst + column minus the length of any strings that might get added to the end of the URL. The length of + strings that might get added to the end of your URLs depends on which modules you have enabled and + on your Pathauto settings. The recommended and default value is 100.

"); + break; + } + + return $output; +} + +/** + * Implementation of hook_perm + */ +function pathauto_perm() { + return array('administer pathauto'); +} + +/* + * Implementation of hook_menu + */ +function pathauto_menu($may_cache) { + + $items = array(); + if ($may_cache) { + $items[] = array( + 'path' => 'admin/settings/pathauto', + 'title' => t('Pathauto'), + 'description' => t('Configure how pathauto generates clean URLs for your content.'), + 'callback' => 'drupal_get_form', + 'callback arguments' => array('pathauto_admin_settings'), + 'access' => user_access('administer pathauto'), + 'type' => MENU_NORMAL_ITEM, + ); + $items[] = array( + 'path' => 'admin/build/path/delete_bulk', + 'title' => t('Delete aliases'), + 'callback' => 'drupal_get_form', + 'callback arguments' => array('pathauto_admin_delete'), + 'access' => user_access('administer url aliases'), + 'type' => MENU_LOCAL_TASK, + ); + } + + return $items; +} + + +/** + * Include all pathauto include files + */ +function _pathauto_include() { + $pathauto_path = drupal_get_path('module', 'pathauto'); + include_once("$pathauto_path/pathauto.inc"); + include_once("$pathauto_path/pathauto_node.inc"); + include_once("$pathauto_path/pathauto_taxonomy.inc"); + include_once("$pathauto_path/pathauto_user.inc"); +} + + +/** + * Callback for admin settings page + * + */ +function pathauto_admin_settings() { + _pathauto_include(); + + // Restrict administration of this module + if (!user_access('administer pathauto')) { + $form["error"] = array('#type' => 'item', + '#title' => t('You are not authorized to access the pathauto settings.')); + return system_settings_form($form); + } + + // Default words to ignore + $ignore_words = array( + "a", "an", "as", "at", "before", "but", "by", "for", "from", "is", "in", + "into", "like", "of", "off", "on", "onto", "per", "since", "than", "the", + "this", "that", "to", "up", "via", "with" + ); + + // Generate the form - settings applying to all patterns first + $group_weight = -20; + $form["general"] = array('#type' => 'fieldset', '#weight' => $group_weight, + '#title' => t('General settings'), '#collapsible' => TRUE, + '#collapsed' => TRUE); + $group_weight++; + + $form["general"]["pathauto_verbose"] = array('#type' => 'checkbox', + '#title' => t('Verbose'), + '#default_value' => variable_get('pathauto_verbose', FALSE), + '#description' => t('Display alias changes (except during bulk updates).')); + + $form["general"]["pathauto_separator"] = array('#type' => 'textfield', + '#title' => t('Separator'), '#size' => 1, '#maxlength' => 1, + '#default_value' => variable_get('pathauto_separator', '-'), + '#description' => t('Character used to separate words in titles. This will replace any spaces and punctuation characters.')); + + $form["general"]["pathauto_quotes"] = array('#type' => 'radios', + '#title' => t('Quotation marks'), + '#default_value' => variable_get('pathauto_quotes', 0), + '#options' => array(t('Remove'), t('Replace by separator')), + ); + + $form["general"]["pathauto_case"] = array('#type' => 'radios', + '#title' => t('Character case'), + '#default_value' => variable_get('pathauto_case', 1), + '#options' => array(t('Leave case the same as source token values.'), t('Change to lower case')), + ); + + + $form["general"]["pathauto_max_length"] = array('#type' => 'textfield', + '#title' => t('Maximum alias length'), '#size' => 3, '#maxlength' => 3, + '#default_value' => variable_get('pathauto_max_length', 100), + '#description' => t('Maximum length of aliases to generate. 100 is recommended. See Pathauto help for details.', array('@pathauto-help' => url('admin/help/pathauto')))); + + $form["general"]["pathauto_max_component_length"] = array('#type' => 'textfield', + '#title' => t('Maximum component length'), '#size' => 3, '#maxlength' => 3, + '#default_value' => variable_get('pathauto_max_component_length', 100), + '#description' => t('Maximum text length of any component in the alias (e.g., [title]). 100 is recommended. See Pathauto help for details.', array('@pathauto-help' => url('admin/help/pathauto')))); + + $form["general"]["pathauto_max_bulk_update"] = array('#type' => 'textfield', + '#title' => t('Maximum number of objects to alias in a bulk update'), '#size' => 3, '#maxlength' => 3, + '#default_value' => variable_get('pathauto_max_bulk_update', 50), + '#description' => t('Maximum number of objects of a given type which should be aliased during a a bulk update. The default is 50 and the recommended number depends on the speed of your server. If bulk updates "time out" or result in a "white screen" then reduce the number.')); + + $form["general"]["pathauto_update_action"] = array('#type' => 'radios', + '#title' => t('Update action'), '#default_value' => variable_get('pathauto_update_action', 2), + '#options' => array(t('Do nothing, leaving the old alias intact'), + t('Create a new alias in addition to the old alias'), + t('Create a new alias, replacing the old one')), + '#description' => t('What should pathauto do when updating an existing content item which already has an alias?')); + + $disable_transliteration = TRUE; + $disable_text = ""; + $path = drupal_get_path('module', 'pathauto'); + $transliteration_help = "When a pattern includes certain characters (such as those with accents) should Pathauto attempt to transliterate them into the ASCII-96 alphabet? Transliteration is determined by the i18n-ascii.txt file in the Pathauto directory. This option is disabled on your site because you do not have an i18n-ascii.txt file in the Pathauto directory."; + if (is_file($path .'/i18n-ascii.txt')) { + $disable_transliteration = FALSE; + $transliteration_help = "When a pattern includes certain characters (such as those with accents) should Pathauto attempt to transliterate them into the ASCII-96 alphabet? Transliteration is determined by the i18n-ascii.txt file in the Pathauto directory."; + } + + $form["general"]["pathauto_transliterate"] = array('#type' => 'checkbox', + '#title' => t('Transliterate prior to creating alias'), + '#default_value' => variable_get('pathauto_transliterate', FALSE), + '#description' => t($transliteration_help), + '#disabled' => $disable_transliteration, + ); + + $form["general"]["pathauto_ignore_words"] = array('#type' => 'textarea', + '#title' => t('Strings to Remove'), '#default_value' => variable_get('pathauto_ignore_words', implode(",", $ignore_words)), + '#description' => t('Words to strip out of the URL alias, separated by commas') + ); + + // Call the hook on all modules - an array of 'settings' objects is returned + $all_settings = module_invoke_all('pathauto', 'settings'); + $modulelist = ''; + $indexcount = 0; + foreach ($all_settings as $settings) { + $items = ''; + $module = $settings->module; + $modulelist[] = $module; + $patterndescr = $settings->patterndescr; + $patterndefault = $settings->patterndefault; + $groupheader = $settings->groupheader; + $supportsfeeds = isset($settings->supportsfeeds) ? $settings->supportsfeeds : NULL; + variable_set('pathauto_'. $module .'_supportsfeeds', $supportsfeeds); + + $form[$module] = array('#type' => 'fieldset', + '#title' => $groupheader, '#weight' => $group_weight, + '#collapsible' => TRUE, '#collapsed' => TRUE); + $group_weight++; + + // Prompt for the default pattern for this module + $variable = 'pathauto_'. $module .'_pattern'; + $form[$module][$variable] = array('#type' => 'textfield', + '#title' => $patterndescr, + '#default_value' => variable_get($variable, $patterndefault), + '#size' => 65, '#maxlength' => 128); + + // If the module supports a set of specialized patterns, set + // them up here + if (isset($settings->patternitems)) { + foreach ($settings->patternitems as $itemname => $itemlabel) { + $variable = 'pathauto_'. $module .'_'. $itemname .'_pattern'; + $form[$module][$variable] = array('#type' => 'textfield', + '#title' => $itemlabel, + '#default_value' => variable_get($variable, ''), + '#size' => 65, '#maxlength' => 128); + } + } + + // Display the user documentation of placeholders supported by + // this module, as a description on the last pattern + $doc = "
\n"; + foreach ($settings->placeholders as $name => $description) { + $doc .= '
'. $name .'
'; + $doc .= '
'. $description .'
'; + } + $doc .= "
\n"; + $form[$module][$variable]["#description"] = $doc; + + // If the module supports bulk updates, offer the update action here + if ($settings->bulkname) { + $variable = 'pathauto_'. $module .'_bulkupdate'; + if (variable_get($variable, FALSE)) { + variable_set($variable, FALSE); + $function = $module .'_pathauto_bulkupdate'; + call_user_func($function); + } + $form[$module][$variable] = array('#type' => 'checkbox', + '#title' => $settings->bulkname, + '#default_value' => FALSE, + '#description' => $settings->bulkdescr); + } + + // Perform bulk updates of indexes for this module, if asked + if ($do_index_bulkupdate) { + $function = $module .'_pathauto_bulkupdate_indexes'; + if (is_callable($function)) { + $indexcount += call_user_func($function); + } + } + + // If the module supports feeds, offer to generate aliases for them + if ($supportsfeeds) { + $variable = 'pathauto_'. $module .'_applytofeeds'; + $form[$module][$variable] = array('#type' => 'checkbox', + '#title' => t('Create feed aliases'), + '#default_value' => variable_get($variable, FALSE), + '#description' => t('Also generate aliases for RSS feeds.')); + } + + } + + if ($do_index_bulkupdate) { + drupal_set_message(format_plural($indexcount, + "Bulk generation of index aliases completed, one alias generated.", + "Bulk generation of index aliases completed, @count aliases generated.")); + } + + // Keep track of which modules currently support pathauto + variable_set('pathauto_modulelist', $modulelist); + + return system_settings_form($form); +} + +/** + * Implementation of hook_token_values() for Pathauto specific tokens + */ +function pathauto_token_values($type, $object = NULL) { + + if (module_exists('taxonomy')) { + switch ($type) { + case 'node': + $vid = db_result(db_query("SELECT t.vid FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.nid = %d ORDER BY v.weight, t.weight, t.name LIMIT 1", $object->nid)); + $category = db_fetch_object(db_query("SELECT t.tid, t.name FROM {term_data} t INNER JOIN {term_node} r ON r.tid = t.tid WHERE t.vid = %d AND r.nid = %d ORDER BY weight LIMIT 1", $vid, $object->nid)); + $category->vid = $vid; + case 'taxonomy': + if (!isset($category)) { + $category = $object; + } + + $parents = taxonomy_get_parents_all($category->tid); + foreach ($parents as $parent) { + // Replace any / characters in individual terms which might create confusing URLs + $separator = variable_get('pathauto_separator', '-'); + $catpath = preg_replace('/\//', '', $parent->name) .'/'. $catpath; + } + $values['catpath'] = $catpath; + + if ($type == 'taxonomy') { + $values['cat'] = $category->name; + } + + $values['catalias'] = drupal_get_path_alias('taxonomy/term/'.$category->tid); + if (!strncasecmp($values['catalias'], 'taxonomy', 8)) { + $values['catalias'] = $values['cat']; + } + + + break; + } + } + // Provide some defaults if they aren't set. + if (!isset($values['catpath'])) { + $values['catpath'] = ''; + $values['catalias'] = ''; + } + + return $values; +} + +/** + * Implementation of hook_token_list() for Pathauto specific tokens + */ +function pathauto_token_list($type = 'all') { + $tokens = array(); + if (module_exists('taxonomy')) { + if ($type == 'taxonomy' || $type == 'all') { + $tokens['taxonomy']['catpath'] = t("As [cat], but including its supercategories separated by /."); + $tokens['taxonomy']['catalias'] = t("URL alias for the category."); + } + if ($type == 'node' || $type == 'all') { + $tokens['node']['catpath'] = t("As [cat], but including its supercategories separated by /."); + $tokens['node']['catalias'] = t("URL alias for the term."); + } + } + return $tokens; +} + +/** + * Menu callback: select certain alias types to delete + */ +function pathauto_admin_delete() { + /* TODO: + 1) all - DONE + 2) all node aliases - DONE + 4) all user aliases - DONE + 5) all taxonomy aliases - DONE + 6) by node type + 7) by taxonomy vocabulary + 8) no longer existing aliases (see http://drupal.org/node/128366 ) + 9) where src like 'pattern' - DON'T DO + 10) where dst like 'pattern' - DON'T DO + */ + + $form = array(); + $form["delete"] = array('#type' => 'fieldset', + '#title' => t('Choose Aliases to Delete'), '#collapsible' => FALSE, + '#collapsed' => FALSE); + + // First we do the "all" case + $total_count = db_result(db_query("SELECT count(1) FROM {url_alias}")); + $form['delete']['all_aliases'] = array('#type' => 'checkbox', + '#title' => t('all aliases'), + '#default_value' => FALSE, + '#description' => t('Delete all aliases. Number of aliases which will be deleted: %count.', array('%count' => $total_count))); + + + // Next, iterate over an array of objects/alias types which can be deleted and provide checkboxes + $objects = _pathauto_objects_to_delete(); + foreach ($objects as $internal_name => $label) { + $count = db_result(db_query("SELECT count(1) FROM {url_alias} WHERE src LIKE '%s%%'", $internal_name)); + $form['delete'][$internal_name] = array('#type' => 'checkbox', + '#title' => t($label), + '#default_value' => FALSE, + '#description' => t('Delete aliases for all @label. Number of aliases which will be deleted: %count.', array('@label' => $label, '%count' => $count))); + } + + $node_types = node_get_types(); + foreach($node_types as $node_type) { + $node_type_total_count = db_result(db_query("SELECT count(1) FROM {url_alias} INNER JOIN node ON url_alias.src = CONCAT('node/', node.nid) WHERE node.type = '%s'", $node_type->type)); + $node_type_options[$node_type->type] = $node_type->name .' ('. $node_type_total_count .')'; + } + + $form['delete']['node_type_aliases'] = array('#type' => 'checkboxes', + '#title' => t('Node type'), + '#description' => t('Delete aliases by node type.'), + '#options' => $node_type_options); + + // Warn them and give a button that shows we mean business + $form["warning"] = array('#value' => t('

Note: there is no confirmation. Be sure of your action before clicking the "Delete aliases now!" button. You may want to make a backup of the database and/or the url_alias table prior to using this feature.

')); + $form['buttons']['submit'] = array( + '#type' => 'submit', + '#value' => t('Delete aliases now!'), + ); + + return $form; +} + +/** + * Submit handler for the bulk delete form + */ +function pathauto_admin_delete_submit($form_id, $form_values) { + foreach ($form_values as $key => $value) { + if ($value) { + if ($key == 'all_aliases') { + db_query('DELETE FROM {url_alias}'); + drupal_set_message(t('All of your path aliases have been deleted.')); + } + $objects = _pathauto_objects_to_delete(); + if (array_key_exists($key, $objects)) { + drupal_set_message($key); + db_query("DELETE FROM {url_alias} WHERE src LIKE '%s%%'", $key); + drupal_set_message(t('All of your %type path aliases have been deleted.', array('%type' => $objects[$key]))); + } + if ($key == 'node_type_aliases') { + foreach ($value as $node_type) { + if ($node_type) { + db_query("DELETE {url_alias} FROM {url_alias} INNER JOIN node ON url_alias.src = CONCAT('node/', node.nid) WHERE node.type = '%s'", $node_type); + drupal_set_message(t('All of your %node_type path aliases have been deleted.', array('%node_type' => $node_type))); + } + } + } + } + } + return 'admin/build/path/delete_bulk'; +} + +function _pathauto_objects_to_delete() { + return array('user/' => t('users'), 'node/' => t('content') , 'taxonomy/' => t('vocabularies and terms'), 'blog/' => t('user blogs'), 'user/%/track' => t('user trackers')); +} + +//============================================================================== +// Some node related functions. + +/** + * Implementation of hook_nodeapi(). + */ +function pathauto_nodeapi(&$node, $op, $teaser, $page) { + _pathauto_include(); + if (module_exists('path')) { + switch ($op) { + case 'insert': + case 'update': + if ($node->pathauto_perform_alias || !isset($node->pathauto_perform_alias)) { + $placeholders = pathauto_get_placeholders('node', $node); + $src = "node/$node->nid"; + $alias = pathauto_create_alias('node', $op, $placeholders, $src, $node->type); + } + break; + default: + break; + } + } +} + +/** + * Implementation of hook_form_alter(). + * + * This allows alias creators to override Pathauto and specify their + * own aliases (Pathauto will be invisible to other users). Inserted + * into the path module's fieldset in the node form. + */ +function pathauto_form_alter($formid, &$form) { + if (isset($form['#id']) && ($form['#id'] == 'node-form')) { + if (user_access('create url aliases')) { + $output .= t('An alias will be generated for you. If you wish to create your own alias below, untick this option.'); + if (user_access('administer pathauto')) { + $output .= t(' To control the format of the generated aliases, see the Pathauto settings.'); + } + + drupal_add_js(drupal_get_path('module', 'pathauto') . '/pathauto.js'); + + $form['path']['pathauto_perform_alias'] = array('#type' => 'checkbox', + '#title' => t('Automatic alias'), + '#default_value' => TRUE, + '#description' => $output, + '#weight' => 0 + ); + } + } +} + +//============================================================================== +// Taxonomy related functions. +/** + * Implementation of hook_taxonomy(). + */ +function pathauto_taxonomy($op, $type, $object = NULL) { + _pathauto_include(); + + switch ($type) { + case 'term': + switch ($op) { + case 'insert': + case 'update': + /* + ** Use the category info to automatically create an alias + */ + $category = (object) $object; + if ($category->name) { + $count = _taxonomy_pathauto_alias($category, $op); + } + break; + case 'delete': + //If the category is deleted, remove the path aliases + $category = (object) $object; + path_set_alias('taxonomy/term/'. $category->tid); + path_set_alias('forum/'. $category->tid); + path_set_alias('taxonomy/term/'. $category->tid .'/0/feed'); + break; + default: + break; + } + break; + default: + break; + } +} + + +//============================================================================== +// User related functions. + +/** + * Implementation of hook_user() for users, trackers, and blogs + */ +function pathauto_user($op, &$edit, &$user, $category = FALSE) { + _pathauto_include(); + switch ($op) { + case 'insert': + case 'update': + /* + ** Use the username to automatically create an alias + */ + $pathauto_user = (object) array_merge((array) $user, $edit); + if ($user->name) { + $placeholders = pathauto_get_placeholders('user', $pathauto_user); + $src = 'user/'. $user->uid; + $alias = pathauto_create_alias('user', $op, $placeholders, $src); + if (module_exists('blog')) { + $src = 'blog/'. $user->uid; + $alias = pathauto_create_alias('blog', $op, $placeholders, $src); + } + if (module_exists('tracker')) { + $src = 'user/'. $user->uid .'/track'; + $alias = pathauto_create_alias('tracker', $op, $placeholders, $src); + } + } + break; + case 'delete': + /* + ** If the user is deleted, remove the path aliases + ** + */ + $user = (object) $user; + path_set_alias('user/'. $user->uid); + + // They may have enabled these modules and/or feeds when the user was created, so let's try to delete all of them + path_set_alias('blog/'. $user->uid); + path_set_alias('blog/'. $user->uid .'/feed'); + path_set_alias('user/'. $user->uid .'/track'); + path_set_alias('user/'. $user->uid .'/track/feed'); + + break; + default: + break; + } +}