? sites/default/settings.php
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.169
diff -u -p -r1.169 bootstrap.inc
--- includes/bootstrap.inc 30 May 2007 08:08:57 -0000 1.169
+++ includes/bootstrap.inc 5 Jun 2007 03:42:26 -0000
@@ -912,6 +912,7 @@ function _drupal_bootstrap($phase) {
break;
case DRUPAL_BOOTSTRAP_PATH:
+ require_once './modules/filter/filter.module';
require_once './includes/path.inc';
// Initialize $_GET['q'] prior to loading modules and invoking hook_init().
drupal_init_path();
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.651
diff -u -p -r1.651 common.inc
--- includes/common.inc 4 Jun 2007 07:22:16 -0000 1.651
+++ includes/common.inc 5 Jun 2007 03:42:37 -0000
@@ -185,50 +185,6 @@ function drupal_get_feeds($delimiter = "
}
/**
- * @name HTTP handling
- * @{
- * Functions to properly handle HTTP responses.
- */
-
-/**
- * Parse an array into a valid urlencoded query string.
- *
- * @param $query
- * The array to be processed e.g. $_GET
- * @param $exclude
- * The array filled with keys to be excluded. Use parent[child] to exclude nested items.
- * @param $urlencode
- * If TRUE, the keys and values are both urlencoded.
- * @param $parent
- * Should not be passed, only used in recursive calls
- * @return
- * urlencoded string which can be appended to/as the URL query string
- */
-function drupal_query_string_encode($query, $exclude = array(), $parent = '') {
- $params = array();
-
- foreach ($query as $key => $value) {
- $key = drupal_urlencode($key);
- if ($parent) {
- $key = $parent .'['. $key .']';
- }
-
- if (in_array($key, $exclude)) {
- continue;
- }
-
- if (is_array($value)) {
- $params[] = drupal_query_string_encode($value, $exclude, $key);
- }
- else {
- $params[] = $key .'='. drupal_urlencode($value);
- }
- }
-
- return implode('&', $params);
-}
-
-/**
* Prepare a destination query string for use in combination with
* drupal_goto(). Used to direct the user back to the referring page
* after completing a form. By default the current URL is returned.
@@ -254,69 +210,6 @@ function drupal_get_destination() {
}
/**
- * Send the user to a different Drupal page.
- *
- * This issues an on-site HTTP redirect. The function makes sure the redirected
- * URL is formatted correctly.
- *
- * Usually the redirected URL is constructed from this function's input
- * parameters. However you may override that behavior by setting a
- * destination in either the $_REQUEST-array (i.e. by using
- * the query string of an URI) or the $_REQUEST['edit']-array (i.e. by
- * using a hidden form field). This is used to direct the user back to
- * the proper page after completing a form. For example, after editing
- * a post on the 'admin/content/node'-page or after having logged on using the
- * 'user login'-block in a sidebar. The function drupal_get_destination()
- * can be used to help set the destination URL.
- *
- * It is advised to use drupal_goto() instead of PHP's header(), because
- * drupal_goto() will append the user's session ID to the URI when PHP is
- * compiled with "--enable-trans-sid".
- *
- * This function ends the request; use it rather than a print theme('page')
- * statement in your menu callback.
- *
- * @param $path
- * A Drupal path or a full URL.
- * @param $query
- * The query string component, if any.
- * @param $fragment
- * The destination fragment identifier (named anchor).
- * @param $http_response_code
- * Valid values for an actual "goto" as per RFC 2616 section 10.3 are:
- * - 301 Moved Permanently (the recommended value for most redirects)
- * - 302 Found (default in Drupal and PHP, sometimes used for spamming search
- * engines)
- * - 303 See Other
- * - 304 Not Modified
- * - 305 Use Proxy
- * - 307 Temporary Redirect (an alternative to "503 Site Down for Maintenance")
- * Note: Other values are defined by RFC 2616, but are rarely used and poorly
- * supported.
- * @see drupal_get_destination()
- */
-function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
- if (isset($_REQUEST['destination'])) {
- extract(parse_url(urldecode($_REQUEST['destination'])));
- }
- else if (isset($_REQUEST['edit']['destination'])) {
- extract(parse_url(urldecode($_REQUEST['edit']['destination'])));
- }
-
- $url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE));
-
- // Before the redirect, allow modules to react to the end of the page request.
- module_invoke_all('exit', $url);
-
- header('Location: '. $url, TRUE, $http_response_code);
-
- // The "Location" header sends a REDIRECT status code to the http
- // daemon. In some cases this can go wrong, so we make sure none
- // of the code below the drupal_goto() call gets executed when we redirect.
- exit();
-}
-
-/**
* Generates a site off-line message
*/
function drupal_site_offline() {
@@ -1145,122 +1038,6 @@ function format_date($timestamp, $type =
*/
/**
- * Generate a URL from a Drupal menu path. Will also pass-through existing URLs.
- *
- * @param $path
- * The Drupal path being linked to, such as "admin/content/node", or an existing URL
- * like "http://drupal.org/".
- * @param $options
- * An associative array of additional options, with the following keys:
- * 'query'
- * A query string to append to the link, or an array of query key/value
- * properties.
- * 'fragment'
- * A fragment identifier (or named anchor) to append to the link.
- * Do not include the '#' character.
- * 'absolute' (default FALSE)
- * Whether to force the output to be an absolute link (beginning with
- * http:). Useful for links that will be displayed outside the site, such
- * as in an RSS feed.
- * 'alias' (default FALSE)
- * Whether the given path is an alias already.
- * @return
- * a string containing a URL to the given path.
- *
- * When creating links in modules, consider whether l() could be a better
- * alternative than url().
- */
-function url($path = NULL, $options = array()) {
- // Merge in defaults
- $options += array(
- 'fragment' => '',
- 'query' => '',
- 'absolute' => FALSE,
- 'alias' => FALSE,
- );
-
- // May need language dependant rewriting if language.inc is present
- if (function_exists('language_url_rewrite')) {
- language_url_rewrite($path, $options);
- }
- if ($options['fragment']) {
- $options['fragment'] = '#'. $options['fragment'];
- }
- if (is_array($options['query'])) {
- $options['query'] = drupal_query_string_encode($options['query']);
- }
-
- // Return an external link if $path contains an allowed absolute URL.
- // Only call the slow filter_xss_bad_protocol if $path contains a ':' before any / ? or #.
- $colonpos = strpos($path, ':');
- if ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path)) {
- // Split off the fragment
- if (strpos($path, '#') !== FALSE) {
- list($path, $old_fragment) = explode('#', $path, 2);
- if (isset($old_fragment) && !$options['fragment']) {
- $options['fragment'] = '#'. $old_fragment;
- }
- }
- // Append the query
- if ($options['query']) {
- $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . $options['query'];
- }
- // Reassemble
- return $path . $options['fragment'];
- }
-
- global $base_url;
- static $script;
- static $clean_url;
-
- if (!isset($script)) {
- // On some web servers, such as IIS, we can't omit "index.php". So, we
- // generate "index.php?q=foo" instead of "?q=foo" on anything that is not
- // Apache.
- $script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : '';
- }
-
- // Cache the clean_url variable to improve performance.
- if (!isset($clean_url)) {
- $clean_url = (bool)variable_get('clean_url', '0');
- }
-
- $base = $options['absolute'] ? $base_url .'/' : base_path();
-
- // The special path '' links to the default front page.
- if (!empty($path) && $path != '') {
- if (!$options['alias']) {
- $path = drupal_get_path_alias($path);
- }
- $path = drupal_urlencode($path);
- if (!$clean_url) {
- if ($options['query']) {
- return $base . $script .'?q='. $path .'&'. $options['query'] . $options['fragment'];
- }
- else {
- return $base . $script .'?q='. $path . $options['fragment'];
- }
- }
- else {
- if ($options['query']) {
- return $base . $path .'?'. $options['query'] . $options['fragment'];
- }
- else {
- return $base . $path . $options['fragment'];
- }
- }
- }
- else {
- if ($options['query']) {
- return $base . $script .'?'. $options['query'] . $options['fragment'];
- }
- else {
- return $base . $options['fragment'];
- }
- }
-}
-
-/**
* Format an attribute string to insert in a tag.
*
* @param $attributes
@@ -2105,34 +1882,6 @@ function drupal_to_js($var) {
}
/**
- * Wrapper around urlencode() which avoids Apache quirks.
- *
- * Should be used when placing arbitrary data in an URL. Note that Drupal paths
- * are urlencoded() when passed through url() and do not require urlencoding()
- * of individual components.
- *
- * Notes:
- * - For esthetic reasons, we do not escape slashes. This also avoids a 'feature'
- * in Apache where it 404s on any path containing '%2F'.
- * - mod_rewrite's unescapes %-encoded ampersands and hashes when clean URLs
- * are used, which are interpreted as delimiters by PHP. These characters are
- * double escaped so PHP will still see the encoded version.
- *
- * @param $text
- * String to encode
- */
-function drupal_urlencode($text) {
- if (variable_get('clean_url', '0')) {
- return str_replace(array('%2F', '%26', '%23'),
- array('/', '%2526', '%2523'),
- urlencode($text));
- }
- else {
- return str_replace('%2F', '/', urlencode($text));
- }
-}
-
-/**
* Ensure the private key variable used to generate tokens is set.
*
* @return
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.102
diff -u -p -r1.102 module.inc
--- includes/module.inc 25 May 2007 12:46:43 -0000 1.102
+++ includes/module.inc 5 Jun 2007 03:42:39 -0000
@@ -345,9 +345,11 @@ function module_implements($hook, $sort
if (!isset($implementations[$hook])) {
$implementations[$hook] = array();
$list = module_list(FALSE, TRUE, $sort);
- foreach ($list as $module) {
- if (module_hook($module, $hook)) {
- $implementations[$hook][] = $module;
+ if (!empty($list)) {
+ foreach ($list as $module) {
+ if (module_hook($module, $hook)) {
+ $implementations[$hook][] = $module;
+ }
}
}
}
Index: includes/path.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/path.inc,v
retrieving revision 1.15
diff -u -p -r1.15 path.inc
--- includes/path.inc 26 Mar 2007 01:32:22 -0000 1.15
+++ includes/path.inc 5 Jun 2007 03:42:41 -0000
@@ -15,10 +15,165 @@
*/
function drupal_init_path() {
if (!empty($_GET['q'])) {
- $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
+ $path = drupal_get_normal_path(trim($_GET['q'], '/'));
}
else {
$_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
+ return;
+ }
+
+ // Wipe the cached alias data.
+ drupal_lookup_path('wipe');
+
+ $active_alias = drupal_get_path_alias($path);
+ if ($_GET['q'] != $active_alias) {
+ $query = $_GET;
+ // Unset the drupal path query.
+ unset($query['q']);
+
+ // Redirect to the active alias.
+ drupal_goto($path, ($query ? $query : NULL), NULL, 301);
+ }
+ else {
+ $_GET['q'] = $path;
+ }
+}
+
+/**
+ * @name HTTP handling
+ * @{
+ * Functions to properly handle HTTP responses.
+ */
+
+/**
+ * Parse an array into a valid urlencoded query string.
+ *
+ * @param $query
+ * The array to be processed e.g. $_GET
+ * @param $exclude
+ * The array filled with keys to be excluded. Use parent[child] to exclude nested items.
+ * @param $urlencode
+ * If TRUE, the keys and values are both urlencoded.
+ * @param $parent
+ * Should not be passed, only used in recursive calls
+ * @return
+ * urlencoded string which can be appended to/as the URL query string
+ */
+function drupal_query_string_encode($query, $exclude = array(), $parent = '') {
+ $params = array();
+
+ foreach ($query as $key => $value) {
+ $key = drupal_urlencode($key);
+ if ($parent) {
+ $key = $parent .'['. $key .']';
+ }
+
+ if (in_array($key, $exclude)) {
+ continue;
+ }
+
+ if (is_array($value)) {
+ $params[] = drupal_query_string_encode($value, $exclude, $key);
+ }
+ else {
+ $params[] = $key .'='. drupal_urlencode($value);
+ }
+ }
+
+ return implode('&', $params);
+}
+
+/**
+ * Send the user to a different Drupal page.
+ *
+ * This issues an on-site HTTP redirect. The function makes sure the redirected
+ * URL is formatted correctly.
+ *
+ * Usually the redirected URL is constructed from this function's input
+ * parameters. However you may override that behavior by setting a
+ * destination in either the $_REQUEST-array (i.e. by using
+ * the query string of an URI) or the $_REQUEST['edit']-array (i.e. by
+ * using a hidden form field). This is used to direct the user back to
+ * the proper page after completing a form. For example, after editing
+ * a post on the 'admin/content/node'-page or after having logged on using the
+ * 'user login'-block in a sidebar. The function drupal_get_destination()
+ * can be used to help set the destination URL.
+ *
+ * It is advised to use drupal_goto() instead of PHP's header(), because
+ * drupal_goto() will append the user's session ID to the URI when PHP is
+ * compiled with "--enable-trans-sid".
+ *
+ * This function ends the request; use it rather than a print theme('page')
+ * statement in your menu callback.
+ *
+ * @param $path
+ * A Drupal path or a full URL.
+ * @param $query
+ * The query string component, if any.
+ * @param $fragment
+ * The destination fragment identifier (named anchor).
+ * @param $http_response_code
+ * Valid values for an actual "goto" as per RFC 2616 section 10.3 are:
+ * - 301 Moved Permanently (the recommended value for most redirects)
+ * - 302 Found (default in Drupal and PHP, sometimes used for spamming search
+ * engines)
+ * - 303 See Other
+ * - 304 Not Modified
+ * - 305 Use Proxy
+ * - 307 Temporary Redirect (an alternative to "503 Site Down for Maintenance")
+ * Note: Other values are defined by RFC 2616, but are rarely used and poorly
+ * supported.
+ * @see drupal_get_destination()
+ */
+function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
+ if (isset($_REQUEST['destination'])) {
+ extract(parse_url(urldecode($_REQUEST['destination'])));
+ }
+ else if (isset($_REQUEST['edit']['destination'])) {
+ extract(parse_url(urldecode($_REQUEST['edit']['destination'])));
+ }
+
+ $url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE));
+
+ // Before the redirect, allow modules to react to the end of the page request.
+ module_invoke_all('exit', $url);
+
+ header('Location: '. $url, TRUE, $http_response_code);
+
+ // The "Location" header sends a REDIRECT status code to the http
+ // daemon. In some cases this can go wrong, so we make sure none
+ // of the code below the drupal_goto() call gets executed when we redirect.
+ exit();
+}
+/**
+ * @} End of "HTTP handling".
+ */
+
+/**
+ * Wrapper around urlencode() which avoids Apache quirks.
+ *
+ * Should be used when placing arbitrary data in an URL. Note that Drupal paths
+ * are urlencoded() when passed through url() and do not require urlencoding()
+ * of individual components.
+ *
+ * Notes:
+ * - For esthetic reasons, we do not escape slashes. This also avoids a 'feature'
+ * in Apache where it 404s on any path containing '%2F'.
+ * - mod_rewrite's unescapes %-encoded ampersands and hashes when clean URLs
+ * are used, which are interpreted as delimiters by PHP. These characters are
+ * double escaped so PHP will still see the encoded version.
+ *
+ * @param $text
+ * String to encode
+ */
+function drupal_urlencode($text) {
+ if (variable_get('clean_url', '0')) {
+ return str_replace(array('%2F', '%26', '%23'),
+ array('/', '%2526', '%2523'),
+ urlencode($text));
+ }
+ else {
+ return str_replace('%2F', '/', urlencode($text));
}
}
@@ -65,7 +220,7 @@ function drupal_lookup_path($action, $pa
return $map[$path_language][$path];
}
// Get the most fitting result falling back with alias without language
- $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language));
+ $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND active = 1 AND language IN('%s', '') ORDER BY language DESC", $path, $path_language));
$map[$path_language][$path] = $alias;
return $alias;
}
@@ -140,6 +295,122 @@ function drupal_get_normal_path($path, $
}
/**
+ * Generate a URL from a Drupal menu path. Will also pass-through existing URLs.
+ *
+ * @param $path
+ * The Drupal path being linked to, such as "admin/content/node", or an existing URL
+ * like "http://drupal.org/".
+ * @param $options
+ * An associative array of additional options, with the following keys:
+ * 'query'
+ * A query string to append to the link, or an array of query key/value
+ * properties.
+ * 'fragment'
+ * A fragment identifier (or named anchor) to append to the link.
+ * Do not include the '#' character.
+ * 'absolute' (default FALSE)
+ * Whether to force the output to be an absolute link (beginning with
+ * http:). Useful for links that will be displayed outside the site, such
+ * as in an RSS feed.
+ * 'alias' (default FALSE)
+ * Whether the given path is an alias already.
+ * @return
+ * a string containing a URL to the given path.
+ *
+ * When creating links in modules, consider whether l() could be a better
+ * alternative than url().
+ */
+function url($path = NULL, $options = array()) {
+ // Merge in defaults
+ $options += array(
+ 'fragment' => '',
+ 'query' => '',
+ 'absolute' => FALSE,
+ 'alias' => FALSE,
+ );
+
+ // May need language dependant rewriting if language.inc is present
+ if (function_exists('language_url_rewrite')) {
+ language_url_rewrite($path, $options);
+ }
+ if ($options['fragment']) {
+ $options['fragment'] = '#'. $options['fragment'];
+ }
+ if (is_array($options['query'])) {
+ $options['query'] = drupal_query_string_encode($options['query']);
+ }
+
+ // Return an external link if $path contains an allowed absolute URL.
+ // Only call the slow filter_xss_bad_protocol if $path contains a ':' before any / ? or #.
+ $colonpos = strpos($path, ':');
+ if ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path)) {
+ // Split off the fragment
+ if (strpos($path, '#') !== FALSE) {
+ list($path, $old_fragment) = explode('#', $path, 2);
+ if (isset($old_fragment) && !$options['fragment']) {
+ $options['fragment'] = '#'. $old_fragment;
+ }
+ }
+ // Append the query
+ if ($options['query']) {
+ $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . $options['query'];
+ }
+ // Reassemble
+ return $path . $options['fragment'];
+ }
+
+ global $base_url;
+ static $script;
+ static $clean_url;
+
+ if (!isset($script)) {
+ // On some web servers, such as IIS, we can't omit "index.php". So, we
+ // generate "index.php?q=foo" instead of "?q=foo" on anything that is not
+ // Apache.
+ $script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : '';
+ }
+
+ // Cache the clean_url variable to improve performance.
+ if (!isset($clean_url)) {
+ $clean_url = (bool)variable_get('clean_url', '0');
+ }
+
+ $base = $options['absolute'] ? $base_url .'/' : base_path();
+
+ // The special path '' links to the default front page.
+ if (!empty($path) && $path != '') {
+ if (!$options['alias']) {
+ $path = drupal_get_path_alias($path);
+ }
+ $path = drupal_urlencode($path);
+ if (!$clean_url) {
+ if ($options['query']) {
+ return $base . $script .'?q='. $path .'&'. $options['query'] . $options['fragment'];
+ }
+ else {
+ return $base . $script .'?q='. $path . $options['fragment'];
+ }
+ }
+ else {
+ if ($options['query']) {
+ return $base . $path .'?'. $options['query'] . $options['fragment'];
+ }
+ else {
+ return $base . $path . $options['fragment'];
+ }
+ }
+ }
+ else {
+ if ($options['query']) {
+ return $base . $script .'?'. $options['query'] . $options['fragment'];
+ }
+ else {
+ return $base . $options['fragment'];
+ }
+ }
+}
+
+/**
* Return a component of the current Drupal path.
*
* When viewing a page at the path "admin/content/types", for example, arg(0)
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.177
diff -u -p -r1.177 locale.module
--- modules/locale/locale.module 30 May 2007 08:08:58 -0000 1.177
+++ modules/locale/locale.module 5 Jun 2007 03:42:46 -0000
@@ -223,6 +223,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.121
diff -u -p -r1.121 path.module
--- modules/path/path.module 4 Jun 2007 07:22:20 -0000 1.121
+++ modules/path/path.module 5 Jun 2007 03:42:48 -0000
@@ -34,6 +34,18 @@ 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 +84,190 @@ function path_menu() {
}
/**
- * Menu callback; handles pages for creating and editing URL aliases.
+ * Menu callback; handles forms for creating and editing URL aliases.
+ */
+function path_admin_edit(&$form_state) {
+ $args = func_get_args();
+ $language = (isset($args[1]) && $args[1] != 'all') ? $args[1] : '';
+
+ // Unset the form state and language argument.
+ unset($args[0], $args[1]);
+
+ $src = implode('/', $args);
+ if (!empty($src)) {
+ $aliases = path_load(NULL, $src, $language);
+ }
+ else {
+ $aliases = array();
+ }
+
+ $administer_access = user_access('administer url aliases');
+ $create_access = user_access('create url aliases');
+ $field_prefix = url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=');
+ $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,
+ '#attributes' => ($administer_access || $create_access) ? array() : array('disabled' => 'disabled'),
+ '#description' => t('Specify the existing path you wish to alias. For example: node/28, forum/1, taxonomy/term/12.'),
+ '#field_prefix' => $field_prefix
+ );
+ $options[0] = '';
+
+ if (!empty($aliases)) {
+ $add_form = FALSE;
+ $attributes = array('disabled' => 'disabled');
+
+ // Disable system path field when editing.
+ $form['alias'][0]['#attributes'] = $attributes;
+
+ foreach ($aliases as $alias) {
+ if (!empty($alias['active'])) {
+ $active_alias = $alias['pid'];
+ }
+ $form['alias'][$alias['pid']] = array(
+ '#type' => 'textfield',
+ '#title' => '',
+ '#default_value' => $alias['dst'],
+ '#maxlength' => 64,
+ '#attributes' => $administer_access ? array() : $attributes,
+ '#size' => 45,
+ '#field_prefix' => $field_prefix
+ );
+ $form['operations'][$alias['pid']] = array(
+ '#value' => l(t('delete'), 'admin/build/path/delete/'. $alias['pid'], array('query' => array('destination' => $_GET['q'])))
+ );
+ $options[$alias['pid']] = '';
+ }
+ }
+ else {
+ $attributes = array();
+ $add_form = 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' => $add_form,
+ '#weight' => 1,
+ '#description' => t('Specify a new path by which this data can be accessed. For example: about, faq, etc.'),
+ '#field_prefix' => $field_prefix
+ );
+ $options[-1] = '';
+
+ $form['active'] = array(
+ '#type' => 'radios',
+ '#options' => $options,
+ '#required' => $add_form,
+ '#attributes' => $administer_access ? array() : array('disabled' => 'disabled'),
+ '#default_value' => isset($active_alias) ? $active_alias : 0,
+ );
+
+ // 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'), t('Operations'));
+ $rows = array();
+ foreach (element_children($form['alias']) as $key) {
+ $rows[] = array(
+ drupal_render($form['active'][$key]),
+ drupal_render($form['alias'][$key]),
+ drupal_render($form['operations'][$key]),
+ );
+ }
+ $output = theme('table', $header, $rows);
+ $output .= drupal_render($form);
+ return $output;
+}
+
+/**
+ * Verify that a new URL alias is valid
*/
-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_validate($form, &$form_state) {
+ $form_values = $form_state['values'];
+ $src = !empty($form_values['alias'][0]) ? $form_values['alias'][0] : NULL;
+
+ // Language is only set if locale module is enabled, otherwise save for all languages.
+ $language = isset($form_values['language']) ? $form_values['language'] : '';
+
+ $active = !empty($form_values['active']) ? $form_values['active'] : NULL;
+ if ($active == -1 && empty($form_values['alias'][$active])) {
+ form_set_error('alias][-1', t('You cannot set an empty field as active.'));
}
- else {
- $output = path_form();
+
+ if (!empty($form_values['alias'])) {
+ foreach ($form_values['alias'] as $pid => $alias) {
+ if (empty($alias) && $active == $pid) {
+ form_set_error('alias]['. $pid, t('You cannot set an empty field as active.'));
+ }
+ 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)));
+ }
+ }
}
+}
- return $output;
+/**
+ * Save a new URL alias to the database.
+ */
+function path_admin_edit_submit($form, &$form_state) {
+ $form_values = $form_state['values'];
+ $src = !empty($form_values['alias'][0]) ? $form_values['alias'][0] : NULL;
+ $new = !empty($form_values['alias'][-1]) ? $form_values['alias'][-1] : NULL;
+
+ // 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 {
+ path_delete('', $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/edit/'. (!empty($language) ? $language : 'all') .'/'. $src;
+ return;
}
/**
@@ -107,24 +290,17 @@ function path_admin_delete_confirm($pid)
**/
function path_admin_delete_confirm_submit($form, &$form_state) {
if ($form_state['values']['confirm']) {
- path_admin_delete($form_state['values']['pid']);
+ path_delete($form_state['values']['pid']);
+ drupal_set_message(t('The alias has been deleted.'));
$form_state['redirect'] = 'admin/build/path';
return;
}
}
/**
- * Post-confirmation; delete an URL alias.
- */
-function path_admin_delete($pid = 0) {
- db_query('DELETE FROM {url_alias} WHERE pid = %d', $pid);
- drupal_set_message(t('The alias has been deleted.'));
-}
-
-/**
* 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);
@@ -143,13 +319,16 @@ function path_set_alias($path = NULL, $a
$alias_count = db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND language = '%s'", $alias, $language));
if ($alias_count == 0) {
+ if ($active) {
+ db_query("UPDATE {url_alias} SET active = 0 WHERE src = '%s' AND language = '%s'", $path, $language);
+ }
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);
+ db_query("INSERT INTO {url_alias} (src, dst, active, language) VALUES ('%s', '%s', %d, '%s')", $path, $alias, $active, $language);
}
}
// The alias exists.
@@ -160,10 +339,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 +350,6 @@ function path_set_alias($path = NULL, $a
}
/**
- * Return a form for editing or creating an individual URL alias.
- */
-function path_form(&$form_state, $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
@@ -233,9 +368,10 @@ function path_nodeapi(&$node, $op, $arg)
case 'load':
$path = "node/$node->nid";
+ $language = !empty($node->language) ? $node->language : '';
// We don't use drupal_get_path_alias() to avoid custom rewrite functions.
- // We only care about exact aliases.
- $result = db_query("SELECT dst FROM {url_alias} WHERE src = '%s'", $path);
+ // We only care about exact aliases whichever is the active one.
+ $result = db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND active = 1 AND language = '%s'", $path, $language);
if (db_num_rows($result)) {
$node->path = db_result($result);
}
@@ -243,20 +379,28 @@ function path_nodeapi(&$node, $op, $arg)
case 'insert':
// Don't try to insert if path is NULL. We may have already set
- // the alias ahead of time.
+ // the alias ahead of time. This is always the preferred alais.
if ($node->path) {
- path_set_alias("node/$node->nid", $node->path);
+ path_set_alias("node/$node->nid", $node->path, NULL, TRUE);
}
break;
case 'update':
- path_set_alias("node/$node->nid", isset($node->path) ? $node->path : NULL, isset($node->pid) ? $node->pid : NULL);
+ $pid = isset($node->pid) ? $node->pid : NULL;
+ if (!empty($node->path)) {
+ // Update alias data. This is always the preferred alais.
+ path_set_alias("node/$node->nid", $node->path, $pid, TRUE);
+ }
+ else if (!empty($pid)) {
+ // Delete the alias if path was emptied.
+ path_delete($pid);
+ }
break;
case 'delete':
$path = "node/$node->nid";
if (drupal_get_path_alias($path) != $path) {
- path_set_alias($path);
+ path_delete(NULL, $path);
}
break;
}
@@ -307,7 +451,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 +484,10 @@ 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 is only available in multi-lingual aliases. "all" doesn't
+ // include every language.
+ $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,54 +510,76 @@ 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, &$form_state) {
- $src = $form_state['values']['src'];
- $dst = $form_state['values']['dst'];
- $pid = isset($form_state['values']['pid']) ? $form_state['values']['pid'] : 0;
- // Language is only set if locale module is enabled, otherwise save for all languages.
- $language = isset($form_state['values']['language']) ? $form_state['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 = NULL, $src = '', $language = NULL) {
+ $output = '';
+ if (isset($pid) && is_numeric($pid)) {
+ $output = db_fetch_array(db_query('SELECT * FROM {url_alias} WHERE pid = %d', $pid));
+ }
+ else if (!empty($src)) {
+ // Let the user load aliases based on an empty (not every), or
+ // a particular language.
+ if ($language !== NULL) {
+ // Load for a specified language. e.g. 'en', 'de', or even ''.
+ $result = db_query("SELECT * FROM {url_alias} WHERE src = '%s' AND language = '%s' ORDER BY pid", $src, $language);
+ }
+ else {
+ // Load for every language. e.g. 'en', 'de', AND even ''.
+ $result = db_query("SELECT * FROM {url_alias} WHERE src = '%s' ORDER BY pid", $src);
+ }
+ while ($row = db_fetch_array($result)) {
+ $output[] = $row;
+ }
}
+
+ return $output;
}
/**
- * Save a new URL alias to the database.
+ * Delete a specific URL alias from the database.
*/
-function path_form_submit($form, &$form_state) {
- // Language is only set if locale module is enabled
- path_set_alias($form_state['values']['src'], $form_state['values']['dst'], isset($form_state['values']['pid']) ? $form_state['values']['pid'] : 0, isset($form_state['values']['language']) ? $form_state['values']['language'] : '');
+function path_delete($pid = NULL, $src = '', $language = NULL) {
+ // Delete based on path ID.
+ if (isset($pid) && is_numeric($pid)) {
+ db_query('DELETE FROM {url_alias} WHERE pid = %d', $pid);
+ }
+ // Delete based on source(system) path.
+ else if (!empty($src)) {
+ // Let the user delete aliases based on an empty (not every), or
+ // a particular language.
+ if ($language !== NULL) {
+ // Delete for a specified language. e.g. 'en', 'de', or even ''.
+ db_query("DELETE FROM {url_alias} WHERE src = '%s' AND language = '%s'", $src, $language);
+ }
+ else {
+ // Delete for every language. e.g. 'en', 'de', AND even ''.
+ db_query("DELETE FROM {url_alias} WHERE src = '%s'", $src);
+ }
+ }
- drupal_set_message(t('The alias has been saved.'));
- $form_state['redirect'] = 'admin/build/path';
+ drupal_clear_path_cache();
return;
}
/**
* Return a form to filter URL aliases.
*/
-function path_admin_filter_form(&$form_state, $keys = '') {
+function path_admin_filter_form(&$form_state) {
+ $args = func_get_args();
+ unset($args[0]);
+ $keys = implode('/', $args);
+
+ $form = array();
+
$form['#attributes'] = array('class' => 'search-form');
- $form['basic'] = array('#type' => 'fieldset',
- '#title' => t('Filter aliases')
- );
- $form['basic']['inline'] = array('#prefix' => '', '#suffix' => '
');
- $form['basic']['inline']['filter'] = array(
+ $form['inline'] = array('#prefix' => '', '#suffix' => '
');
+ $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'));
return $form;
}
@@ -419,11 +591,3 @@ function path_admin_filter_form_submit($
return 'admin/build/path/list/'. trim($form_state['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.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.119
diff -u -p -r1.119 system.install
--- modules/system/system.install 30 May 2007 08:08:58 -0000 1.119
+++ modules/system/system.install 5 Jun 2007 03:43:04 -0000
@@ -3339,6 +3339,20 @@ function system_update_6022() {
return $ret;
}
+
+/**
+ * Add 'active' column to url_alias table.
+ */
+function system_update_6023() {
+ $ret = array();
+
+ if (db_table_exists('url_alias')) {
+ db_add_field($ret, 'url_alias', 'active', array('type' => 'int', 'not null' => TRUE, 'default' => 0));
+ }
+
+ return $ret;
+}
+
/**
* @} End of "defgroup updates-5.x-to-6.x"
* The next series of updates should start at 7000.
Index: modules/system/system.schema
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.schema,v
retrieving revision 1.4
diff -u -p -r1.4 system.schema
--- modules/system/system.schema 30 May 2007 08:08:59 -0000 1.4
+++ modules/system/system.schema 5 Jun 2007 03:43:06 -0000
@@ -176,6 +176,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')),