Index: includes/bootstrap.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v retrieving revision 1.60 diff -u -F^f -r1.60 bootstrap.inc --- includes/bootstrap.inc 5 Aug 2005 00:49:02 -0000 1.60 +++ includes/bootstrap.inc 18 Aug 2005 17:13:00 -0000 @@ -879,4 +892,11 @@ function drupal_maintenance_theme() { $theme = ''; } +/** + * Encode special characters in a plain-text string for display as HTML. + */ +function check_plain($text) { + return htmlspecialchars($text); +} + ?> \ No newline at end of file Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.469 diff -u -F^f -r1.469 common.inc --- includes/common.inc 17 Aug 2005 19:14:08 -0000 1.469 +++ includes/common.inc 18 Aug 2005 17:43:07 -0000 @@ -649,13 +652,6 @@ function t($string, $args = 0) { } /** - * Encode special characters in a plain-text string for display as HTML. - */ -function check_plain($text) { - return htmlspecialchars($text, ENT_QUOTES); -} - -/** * @defgroup validation Input validation * @{ * Functions to validate user input. @@ -1302,24 +1298,32 @@ function form_textfield($title, $name, $ * A measure of the visible size of the field (passed directly to HTML). * @param $maxlength * The maximum number of characters that may be entered in the field. - * @param $callback_path - * A drupal path for the Ajax autocomplete callback. + * @param $module + * A drupal module that has the Ajax autocomplete callback. + * module_invoke($module, 'autocomplete') is called. * @param $description * Explanatory text to display after the form item. * @param $attributes * An associative array of HTML attributes to add to the form item. * @param $required * Whether the user must enter some text in the field. + * @param $op + * Optional parameter passed to $module_autocomplete. * @return * A themed HTML string representing the field. */ -function form_autocomplete($title, $name, $value, $size, $maxlength, $callback_path, $description = NULL, $attributes = NULL, $required = FALSE) { +function form_autocomplete($title, $name, $value, $size, $maxlength, $module, $description = NULL, $attributes = NULL, $required = FALSE, $op = '') { + global $base_url; drupal_add_js('misc/autocomplete.js'); $size = $size ? ' size="'. $size .'"' : ''; + $url = $base_url .'/autocomplete.php?m='. $module; + if ($function != 'autocomplete') { + $url .= '&f='. $function; + } $output = theme('form_element', $title, '', $description, 'edit-'. $name, $required, _form_get_error($name)); - $output .= ''; + $output .= ''; return $output; } @@ -1809,24 +1813,6 @@ function drupal_add_js($file) { } /** - * Implode a PHP array into a string that can be decoded by the autocomplete JS routines. - * - * Items are separated by double pipes. Each item consists of a key-value pair - * separated by single pipes. Entities are used to ensure pipes in the strings - * pass unharmed. - * - * The key is what is filled in in the text-box (plain-text), the value is what - * is displayed in the suggestion list (HTML). - */ -function drupal_implode_autocomplete($array) { - $output = array(); - foreach ($array as $k => $v) { - $output[] = str_replace('|', '|', $k) .'|'. str_replace('|', '|', $v); - } - return implode('||', $output); -} - -/** * Performs one or more XML-RPC request(s). * * @param $url Index: modules/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment.module,v retrieving revision 1.365 diff -u -F^f -r1.365 comment.module --- modules/comment.module 17 Aug 2005 20:07:35 -0000 1.365 +++ modules/comment.module 18 Aug 2005 17:13:02 -0000 @@ -1390,7 +1390,7 @@ function theme_comment_form($edit, $titl else { $author = $edit['registered_name']; } - $output = form_autocomplete(t('Authored by'), 'author', $author, 30, 60, 'user/autocomplete'); + $output = form_autocomplete(t('Authored by'), 'author', $author, 30, 60, 'user'); $output .= form_textfield(t('Authored on'), 'date', $edit['date'] ? $edit['date'] : format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O'), 20, 25, NULL, NULL, TRUE); $output .= form_radios(t('Status'), 'status', $edit['status'], array(t('Published'), t('Not published'))); Index: modules/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node.module,v retrieving revision 1.519 diff -u -F^f -r1.519 node.module --- modules/node.module 11 Aug 2005 12:53:39 -0000 1.519 +++ modules/node.module 18 Aug 2005 17:13:03 -0000 @@ -1297,7 +1296,7 @@ function node_form($edit) { if (user_access('administer nodes')) { $output .= '
'; - $author = form_autocomplete(t('Authored by'), 'name', $edit->name, 30, 60, 'user/autocomplete'); + $author = form_autocomplete(t('Authored by'), 'name', $edit->name, 30, 60, 'user'); $author .= form_textfield(t('Authored on'), 'date', $edit->date, 30, 25, NULL, NULL, TRUE); $output .= '
'; Index: modules/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user.module,v retrieving revision 1.501 diff -u -F^f -r1.501 user.module --- modules/user.module 11 Aug 2005 13:52:44 -0000 1.501 +++ modules/user.module 18 Aug 2005 17:13:04 -0000 @@ -661,9 +661,6 @@ function user_menu($may_cache) { $items[] = array('path' => 'user', 'title' => t('user account'), 'callback' => 'user_page', 'access' => TRUE, 'type' => MENU_CALLBACK); - $items[] = array('path' => 'user/autocomplete', 'title' => t('user autocomplete'), - 'callback' => 'user_autocomplete', 'access' => $admin_access, 'type' => MENU_CALLBACK); - //registration and login pages. $items[] = array('path' => 'user/login', 'title' => t('log in'), 'type' => MENU_DEFAULT_LOCAL_TASK); @@ -1902,12 +1909,14 @@ function _user_forms(&$edit, $account, $ * Retrieve a pipe delimited string of autocomplete suggestions for existing users */ function user_autocomplete($string) { - $matches = array(); - $result = db_query_range('SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER("%%%s%%")', $string, 0, 10); - while ($user = db_fetch_object($result)) { - $matches[$user->name] = check_plain($user->name); + if (user_access('administer users')) { + $matches = array(); + $result = db_query_range('SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER("%%%s%%")', $string, 0, 10); + while ($user = db_fetch_object($result)) { + $matches[$user->name] = check_plain($user->name); + } + print drupal_implode_autocomplete($matches); } - print drupal_implode_autocomplete($matches); exit(); } Index: modules/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy.module,v retrieving revision 1.217 diff -u -F^f -r1.217 taxonomy.module --- modules/taxonomy.module 25 Jul 2005 04:55:37 -0000 1.217 +++ modules/taxonomy.module 18 Aug 2005 17:13:05 -0000 @@ -81,10 +81,6 @@ function taxonomy_menu($may_cache) { 'access' => user_access('access content'), 'type' => MENU_CALLBACK); - $items[] = array('path' => 'taxonomy/autocomplete', 'title' => t('autocomplete taxonomy'), - 'callback' => 'taxonomy_autocomplete', - 'access' => user_access('access content'), - 'type' => MENU_CALLBACK); } else { if (is_numeric(arg(2))) { @@ -1266,32 +1261,34 @@ function _taxonomy_get_tid_from_term($te * Helper function for autocompletion */ function taxonomy_autocomplete($vid, $string = '') { - // The user enters a comma-separated list of tags. We only autocomplete the last tag. - // This regexp allows the following types of user input: - // this, "somecmpany, llc", "and ""this"" w,o.rks", foo bar - $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x'; - preg_match_all($regexp, $string, $matches); - $array = $matches[1]; - - // Fetch last tag - $last_string = trim(array_pop($array)); - if ($last_string != '') { - $result = db_query_range("SELECT name FROM {term_data} WHERE vid = %d AND LOWER(name) LIKE LOWER('%%%s%%')", $vid, $last_string, 0, 10); - - $prefix = count($array) ? implode(', ', $array) .', ' : ''; - - $matches = array(); - while ($tag = db_fetch_object($result)) { - $n = $tag->name; - // Commas and quotes in terms are special cases, so encode 'em. - if (preg_match('/,/', $tag->name) || preg_match('/"/', $tag->name)) { - $n = '"'. preg_replace('/"/', '""', $tag->name) .'"'; + if (user_access('access content')) { + // The user enters a comma-separated list of tags. We only autocomplete the last tag. + // This regexp allows the following types of user input: + // this, "somecmpany, llc", "and ""this"" w,o.rks", foo bar + $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x'; + preg_match_all($regexp, $string, $matches); + $array = $matches[1]; + + // Fetch last tag + $last_string = trim(array_pop($array)); + if ($last_string != '') { + $result = db_query_range("SELECT name FROM {term_data} WHERE vid = %d AND LOWER(name) LIKE LOWER('%%%s%%')", $vid, $last_string, 0, 10); + + $prefix = count($array) ? implode(', ', $array) .', ' : ''; + + $matches = array(); + while ($tag = db_fetch_object($result)) { + $n = $tag->name; + // Commas and quotes in terms are special cases, so encode 'em. + if (preg_match('/,/', $tag->name) || preg_match('/"/', $tag->name)) { + $n = '"'. preg_replace('/"/', '""', $tag->name) .'"'; + } + $matches[$prefix . $n] = check_plain($tag->name); } - $matches[$prefix . $n] = check_plain($tag->name); + print drupal_implode_autocomplete($matches); } - print drupal_implode_autocomplete($matches); - exit(); } + exit(); } ?> Index: misc/autocomplete.js =================================================================== RCS file: /cvs/drupal/drupal/misc/autocomplete.js,v retrieving revision 1.4 diff -u -F^f -r1.4 autocomplete.js --- misc/autocomplete.js 11 Aug 2005 13:00:17 -0000 1.4 +++ misc/autocomplete.js 18 Aug 2005 17:13:05 -0000 @@ -242,7 +242,7 @@ function ACDB(uri) { var db = this; this.timer = setTimeout(function() { addClass(db.owner.input, 'throbbing'); - HTTPGet(db.uri +'/'+ searchString +'/'+ db.max, db.receive, db); + HTTPGet(db.uri +'&i='+ searchString +'&d='+ db.max, db.receive, db); }, this.delay); }