Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.174
diff -u -p -r1.174 locale.module
--- modules/locale/locale.module	22 May 2007 07:42:37 -0000	1.174
+++ modules/locale/locale.module	28 May 2007 10:47:19 -0000
@@ -224,6 +224,7 @@ function locale_form_alter(&$form, $form
         '#title' => t('Language'),
         '#options' => array('' => t('All languages')) + locale_language_list('name'),
         '#default_value' => $form['language']['#value'],
+        '#attributes' => $form['language']['#attributes'],
         '#weight' => -10,
         '#description' => t('Path aliases added for languages take precedence over path aliases added for all languages for the same Drupal path.'),
       );
Index: modules/path/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path/path.module,v
retrieving revision 1.119
diff -u -p -r1.119 path.module
--- modules/path/path.module	16 May 2007 13:45:16 -0000	1.119
+++ modules/path/path.module	28 May 2007 10:47:21 -0000
@@ -34,6 +34,17 @@ function path_help($section) {
 }
 
 /**
+ * Implementation of hook_theme().
+ */
+function path_theme() {
+  return array(
+    'path_admin_edit' => array(
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
+/**
  * Implementation of hook_menu().
  */
 function path_menu() {
@@ -72,19 +83,172 @@ function path_menu() {
 }
 
 /**
- * Menu callback; handles pages for creating and editing URL aliases.
+ * Menu callback; returns form for creating and editing URL aliases.
  */
-function path_admin_edit($pid = 0) {
-  if ($pid) {
-    $alias = path_load($pid);
-    drupal_set_title(check_plain($alias['dst']));
-    $output = path_form($alias);
+function path_admin_edit() {
+  $args = func_get_args();
+  $language = (isset($args[0]) && $args[0] != 'all') ? $args[0] : '';
+
+  // Unset the first language argument.
+  unset($args[0]);
+
+  $src = implode('/', $args);
+  if (!empty($src)) {
+    $aliases = path_load('', $src, $language);
   }
   else {
-    $output = path_form();
+    $aliases = array();
   }
 
-  return $output;
+  $active_alias = 0;
+  $form = array();
+
+  $form['alias']['#tree'] = TRUE;
+  $form['alias'][0] = array(
+     '#type' => 'textfield',
+     '#title' => t('Existing system path'),
+     '#default_value' => $src,
+     '#maxlength' => 64,
+     '#size' => 45,
+     '#required' => TRUE,
+     '#description' => t('Specify the existing path you wish to alias. For example: node/28, forum/1, taxonomy/term/1+2.'),
+     '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+  );
+  $options[0] = '';
+
+  if (!empty($aliases)) {
+    $required = FALSE;
+    $attributes= array('disabled' => 'disabled');
+    // Disable system path field when editing.
+    $form['alias'][0]['#attributes'] = $attributes;
+    $count = 1;
+    foreach ($aliases as $alias) {
+      if (!empty($alias['active'])) {
+        $active_alias = $alias['pid'];
+      }
+      $form['alias'][$alias['pid']] = array(
+        '#type' => 'textfield',
+        '#title' => t('Alias @number', array('@number' => ($count++))),
+        '#default_value' => $alias['dst'],
+        '#maxlength' => 64,
+        '#size' => 45,
+        '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+      );
+      $options[$alias['pid']] = '';
+    }
+  }
+  else {
+    $attributes = array();
+    $required = TRUE;
+    // Select new path as active on add alias form.
+    $active_alias = -1;
+  }
+
+  $form['alias'][-1] = array(
+     '#type' => 'textfield',
+     '#title' => t('New alias'),
+     '#maxlength' => 64,
+     '#size' => 45,
+     '#required' => $required,
+     '#weight' => 1,
+     '#description' => t('Specify a new alternative path by which this data can be accessed. For example: about, faq, etc.'),
+     '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+  );
+  $options[-1] = '';
+
+  $form['active'] = array(
+    '#type' => 'radios',
+    '#options' => $options,
+    '#required' => $required,
+    '#default_value' => $active_alias
+  );
+
+  // This will be a hidden value unless locale module is enabled
+  $form['language'] = array(
+    '#type' => 'value',
+    '#value' => $language,
+    '#attributes' => $attributes
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save')
+  );
+
+  return $form;
+}
+
+/**
+ * Theme the path creating and editing form.
+ */
+function theme_path_admin_edit($form) {
+  $header = array(t('Active'), t('Alias'));
+  $rows = array();
+  foreach (element_children($form['alias']) as $key) {
+    $rows[] = array(
+      drupal_render($form['active'][$key]),
+      drupal_render($form['alias'][$key]),
+    );
+  }
+  $output = theme('table', $header, $rows);
+  $output .= drupal_render($form);
+  return $output;
+}
+
+/**
+ * Verify that URL aliases are valid.
+ */
+function path_admin_edit_validate($form, &$form_state, $form_values) {
+  $active = $form_values['active'];
+  if ($active == -1 && empty($form_values['alias'][$active])) {
+    form_set_error('alias][-1', t('You can not set an empty field as an active alias.'));
+  }
+
+  // Language is only set if locale module is enabled, otherwise save for all languages.
+  $language = isset($form_values['language']) ? $form_values['language'] : '';
+
+  foreach ($form_values['alias'] as $pid => $alias) {
+    if ($alias && db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE pid != %d AND dst = '%s' AND language = '%s'", $pid, $alias, $language))) {
+      form_set_error('alias]['. $pid, t('The alias %alias is already in use in this language.', array('%alias' => $alias)));
+    }
+  }
+}
+
+/**
+ * Save a URL aliases to the database.
+ */
+function path_admin_edit_submit($form, &$form_state, $form_values) {
+  $src = $form_values['alias'][0];
+  $new = $form_values['alias'][-1];
+
+  // Language is only set if locale module is enabled, otherwise save for all languages.
+  $language = isset($form_values['language']) ? $form_values['language'] : '';
+
+  unset($form_values['alias'][0], $form_values['alias'][-1]);
+  // Unset source and new alias, preparing a list of existing aliases.
+
+  if (!empty($form_values['alias'])) {
+    foreach ($form_values['alias'] as $pid => $alias) {
+      if (!empty($alias)) {
+        path_set_alias($src, $alias, $pid, ($pid == $form_values['active']), $language);
+      }
+      else {
+        // Delete based on alias
+        db_query("DELETE FROM {url_alias} WHERE pid = %d", $pid);
+        drupal_clear_path_cache();
+      }
+    }
+  }
+
+  if (!empty($new)) {
+    path_set_alias($src, $new, NULL, ($form_values['active'] == -1), $language);
+  }
+
+  menu_rebuild();
+  drupal_set_message(t('The aliases have been saved.'));
+
+  $form_state['redirect'] = 'admin/build/path';
+  return;
 }
 
 /**
@@ -105,7 +269,7 @@ function path_admin_delete_confirm($pid)
 /**
  * Execute URL alias deletion
  **/
-function path_admin_delete_confirm_submit($form_values, $form, &$form_state) {
+function path_admin_delete_confirm_submit($form, &$form_state, $form_values) {
   if ($form_values['confirm']) {
     path_admin_delete($form_values['pid']);
     $form_state['redirect'] = 'admin/build/path';
@@ -124,7 +288,7 @@ function path_admin_delete($pid = 0) {
 /**
  * Set an aliased path for a given Drupal path, preventing duplicates.
  */
-function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $language = '') {
+function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $active = NULL, $language = '') {
   if ($path && !$alias) {
     // Delete based on path
     db_query("DELETE FROM {url_alias} WHERE src = '%s' AND language = '%s'", $path, $language);
@@ -145,11 +309,14 @@ function path_set_alias($path = NULL, $a
     if ($alias_count == 0) {
       if ($pid) {
         // Existing path changed data
-        db_query("UPDATE {url_alias} SET src = '%s', dst = '%s', language = '%s' WHERE pid = %d", $path, $alias, $language, $pid);
+        db_query("UPDATE {url_alias} SET src = '%s', dst = '%s', active = %d, language = '%s' WHERE pid = %d", $path, $alias, $active, $language, $pid);
       }
       else {
         // No such alias yet in this language
-        db_query("INSERT INTO {url_alias} (src, dst, language) VALUES ('%s', '%s', '%s')", $path, $alias, $language);
+        if ($active) {
+          db_query("UPDATE {url_alias} SET active = 0 WHERE src = '%s' AND language = '%s'", $path, $language);
+        }
+        db_query("INSERT INTO {url_alias} (src, dst, active, language) VALUES ('%s', '%s', %d, '%s')", $path, $alias, $active, $language);
       }
     }
     // The alias exists.
@@ -160,10 +327,8 @@ function path_set_alias($path = NULL, $a
       }
       else {
         // This will delete the path that alias was originally pointing to.
-        path_set_alias(NULL, $alias, NULL, $language);
-        // This will remove the current aliases of the path.
-        path_set_alias($path, NULL, NULL, $language);
-        path_set_alias($path, $alias, NULL, $language);
+        path_set_alias(NULL, $alias, NULL, $active, $language);
+        path_set_alias($path, $alias, NULL, $active, $language);
       }
     }
     if ($alias_count == 0 || $path_count == 0) {
@@ -173,48 +338,6 @@ function path_set_alias($path = NULL, $a
 }
 
 /**
- * Return a form for editing or creating an individual URL alias.
- */
-function path_form($edit = array('src' => '', 'dst' => '', 'language' => '', 'pid' => NULL)) {
-  $form['#submit'][] = 'path_form_submit';
-  $form['#validate'][] = 'path_form_validate';
-  $form['#alias'] = $edit;
-
-  $form['src'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Existing system path'),
-    '#default_value' => $edit['src'],
-    '#maxlength' => 64,
-    '#size' => 45,
-    '#description' => t('Specify the existing path you wish to alias. For example: node/28, forum/1, taxonomy/term/1+2.'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
-  );
-  $form['dst'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Path alias'),
-    '#default_value' => $edit['dst'],
-    '#maxlength' => 64,
-    '#size' => 45,
-    '#description' => t('Specify an alternative path by which this data can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
-  );
-  // This will be a hidden value unless locale module is enabled
-  $form['language'] = array(
-    '#type' => 'value',
-    '#value' => $edit['language']
-  );
-  if ($edit['pid']) {
-    $form['pid'] = array('#type' => 'hidden', '#value' => $edit['pid']);
-    $form['submit'] = array('#type' => 'submit', '#value' => t('Update alias'));
-  }
-  else {
-    $form['submit'] = array('#type' => 'submit', '#value' => t('Create new alias'));
-  }
-
-  return $form;
-}
-
-/**
  * Implementation of hook_nodeapi().
  *
  * Allows URL aliases for nodes to be specified at node edit time rather
@@ -266,7 +389,7 @@ function path_nodeapi(&$node, $op, $arg)
 /**
  * Implementation of hook_form_alter().
  */
-function path_form_alter(&$form, $form_id) {
+function path_form_alter(&$form, $form_state, $form_id) {
   if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id) {
     $path = isset($form['#node']->path) ? $form['#node']->path : NULL;
     $form['path'] = array(
@@ -307,7 +430,10 @@ function path_perm() {
  * When filter key passed, perform a standard search on the given key,
  * and return the list of matching URL aliases.
  */
-function path_admin_overview($keys = NULL) {
+function path_admin_overview() {
+  $args = func_get_args();
+  $keys = implode('/', $args);
+
   // Add the filter form above the overview table.
   $output = drupal_get_form('path_admin_filter_form', $keys);
   // Enable language column if locale is enabled or if we have any alias with language
@@ -337,7 +463,8 @@ function path_admin_overview($keys = NUL
   $rows = array();
   $destination = drupal_get_destination();
   while ($data = db_fetch_object($result)) {
-    $row = array(check_plain($data->dst), check_plain($data->src), l(t('edit'), "admin/build/path/edit/$data->pid", array('query' => $destination)), l(t('delete'), "admin/build/path/delete/$data->pid", array('query' => $destination)));
+    $language = !empty($data->language) ? $data->language : 'all' ;
+    $row = array(check_plain($data->dst), check_plain($data->src), l(t('edit'), "admin/build/path/edit/$language/$data->src", array('query' => $destination)), l(t('delete'), "admin/build/path/delete/$data->pid", array('query' => $destination)));
     if ($multilanguage) {
       $row[4] = $row[3];
       $row[3] = $row[2];
@@ -360,57 +487,61 @@ function path_admin_overview($keys = NUL
 /**
  * Fetch a specific URL alias from the database.
  */
-function path_load($pid) {
-  return db_fetch_array(db_query('SELECT * FROM {url_alias} WHERE pid = %d', $pid));
-}
-
-/**
- * Verify that a new URL alias is valid
- */
-function path_form_validate($form_values, $form, &$form_state) {
-  $src = $form_values['src'];
-  $dst = $form_values['dst'];
-  $pid = isset($form_values['pid']) ? $form_values['pid'] : 0;
-  // Language is only set if locale module is enabled, otherwise save for all languages.
-  $language = isset($form_values['language']) ? $form_values['language'] : '';
-
-  if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE pid != %d AND dst = '%s' AND language = '%s'", $pid, $dst, $language))) {
-    form_set_error('dst', t('The alias %alias is already in use in this language.', array('%alias' => $dst)));
+function path_load($pid, $src = '', $language = '') {
+  if (!empty($pid)) {
+    return db_fetch_array(db_query('SELECT * FROM {url_alias} WHERE pid = %d', $pid));
+  }
+  else if (!empty($src)) {
+    $result = db_query("SELECT * FROM {url_alias} WHERE src = '%s' AND language = '%s'", $src, $language);
+    while ($row = db_fetch_array($result)) {
+      $output[] = $row;
+    }
+    return $output;
   }
 }
 
 /**
- * Save a new URL alias to the database.
- */
-function path_form_submit($form_values, $form, &$form_state) {
-  // Language is only set if locale module is enabled
-  path_set_alias($form_values['src'], $form_values['dst'], isset($form_values['pid']) ? $form_values['pid'] : 0, isset($form_values['language']) ? $form_values['language'] : '');
-
-  drupal_set_message(t('The alias has been saved.'));
-  $form_state['redirect'] = 'admin/build/path';
-  return;
-}
-
-/**
  * Return a form to filter URL aliases.
  */
-function path_admin_filter_form($keys = '') {
+function path_admin_filter_form() {
+  $args = func_get_args();
+  $keys = implode('/', $args);
+
   $form['#attributes'] = array('class' => 'search-form');
-  $form['basic'] = array('#type' => 'fieldset',
-    '#title' => t('Filter aliases')
-  );
-  $form['basic']['inline'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
-  $form['basic']['inline']['filter'] = array(
+
+  $form['inline'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
+  $form['inline']['filter'] = array(
     '#type' => 'textfield',
-    '#title' => '',
+    '#title' => t('Filter aliases'),
     '#default_value' => $keys,
     '#maxlength' => 64,
     '#size' => 25,
   );
-  $form['basic']['inline']['submit'] = array('#type' => 'submit', '#value' => t('Filter'));
+  $form['inline']['submit'] = array('#type' => 'submit', '#value' => t('Filter'));
+  $form['#submit'][] = 'path_admin_filter_form_submit';
 
   return $form;
 }
+
+/**
+ * Implementation of hook_user.
+ */
+function path_user($op, $edit, $user) {
+  if ($op == 'delete') {
+    $path = "user/$user->uid";
+    path_set_alias($path);
+  }
+}
+
+/**
+ * Implementation of hook_comment.
+ */
+function path_comment($comment, $op) {
+  if ($op == 'delete') {
+    $path = "comment/$comment->cid";
+    path_set_alias($path);
+  }
+}
 
 /**
  * Process filter form submission.
@@ -419,12 +550,3 @@ function path_admin_filter_form_submit($
   return 'admin/build/path/list/'. trim($form_values['filter']);
 }
 
-/**
- * Helper function for grabbing filter keys.
- */
-function path_admin_filter_get_keys() {
-  // Extract keys as remainder of path
-  $path = explode('/', $_GET['q'], 5);
-  return count($path) == 5 ? $path[4] : '';
-}
-
Index: modules/system/system.schema
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.schema,v
retrieving revision 1.2
diff -u -p -r1.2 system.schema
--- modules/system/system.schema	25 May 2007 15:47:57 -0000	1.2
+++ modules/system/system.schema	28 May 2007 10:47:41 -0000
@@ -118,6 +118,7 @@ function system_schema() {
       'pid'      => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
       'src'      => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
       'dst'      => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
+      'active'    => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
       'language' => array('type' => 'varchar', 'length' => 12, 'not null' => TRUE, 'default' => '')
     ),
     'unique keys' => array('dst_language' => array('dst', 'language')),
