Commit 8f8766ab authored by myk%mozilla.org's avatar myk%mozilla.org

Fix for bug 172518: makes the request tracker use the generic user matching code

r=not_erik,joel a=justdave
parent 34c5c3b6
...@@ -368,10 +368,6 @@ sub clear { ...@@ -368,10 +368,6 @@ sub clear {
sub FormToNewFlags { sub FormToNewFlags {
my ($target, $data) = @_; my ($target, $data) = @_;
# Flag for whether or not we must get verification of the requestees
# (if the user did not uniquely identify them).
my $verify_requestees = 0;
# Get information about the setter to add to each flag. # Get information about the setter to add to each flag.
# Uses a conditional to suppress Perl's "used only once" warnings. # Uses a conditional to suppress Perl's "used only once" warnings.
my $setter = new Bugzilla::User($::userid); my $setter = new Bugzilla::User($::userid);
...@@ -396,67 +392,20 @@ sub FormToNewFlags { ...@@ -396,67 +392,20 @@ sub FormToNewFlags {
my $requestee_str = $data->{"requestee-$type_id"} || $data->{'requestee'}; my $requestee_str = $data->{"requestee-$type_id"} || $data->{'requestee'};
if ($requestee_str) { if ($requestee_str) {
$flag->{'requestee_str'} = $requestee_str; my $requestee_id = &::DBname_to_id($requestee_str);
MatchRequestees($flag); $requestee_id
$verify_requestees = 1 if scalar(@{$flag->{'requestees'}}) != 1; || &::ThrowUserError("invalid_username", {name => $requestee_str});
$flag->{'requestee'} = new Bugzilla::User($requestee_id);
} }
# Add the flag to the array of flags. # Add the flag to the array of flags.
push(@flags, $flag); push(@flags, $flag);
} }
if ($verify_requestees) {
$::vars->{'target'} = $target;
$::vars->{'flags'} = \@flags;
$::vars->{'form'} = $data;
$::vars->{'mform'} = \%::MFORM || \%::MFORM;
print "Content-Type: text/html\n\n" unless $::vars->{'header_done'};
$::template->process("request/verify.html.tmpl", $::vars)
|| &::ThrowTemplateError($::template->error());
exit;
}
# Return the list of flags. # Return the list of flags.
return \@flags; return \@flags;
} }
sub MatchRequestees {
my ($flag) = @_;
my $requestee_str = $flag->{'requestee_str'};
# To reduce the size of queries, require the user to enter at least
# three characters of each requestee's name unless this installation
# automatically appends an email suffix to each user's login name,
# in which case we can't guarantee their names are at least three
# characters long.
if (!Param('emailsuffix') && length($requestee_str) < 3) {
&::ThrowUserError("requestee_too_short");
}
# Get a list of potential requestees whose email address or real name
# matches the substring entered by the user. Try an exact match first,
# then fall back to a substring search. Limit search to 100 matches,
# since at that point there are too many to make the user wade through,
# and we need to get the user to enter a more constrictive match string.
my $user_id = &::DBname_to_id($requestee_str);
if ($user_id) { $flag->{'requestees'} = [ new Bugzilla::User($user_id) ] }
else { $flag->{'requestees'} = Bugzilla::User::match($requestee_str, 101, 1) }
# If there is only one requestee match, make them the requestee.
if (scalar(@{$flag->{'requestees'}}) == 1) {
$flag->{'requestee'} = $flag->{'requestees'}[0];
}
# If there are too many requestee matches, throw an error.
elsif (scalar(@{$flag->{'requestees'}}) == 101) {
&::ThrowUserError("requestee_too_many_matches",
{ requestee => $requestee_str });
}
}
# Ideally, we'd use Bug.pm, but it's way too heavyweight, and it can't be # Ideally, we'd use Bug.pm, but it's way too heavyweight, and it can't be
# made lighter without totally rewriting it, so we'll use this function # made lighter without totally rewriting it, so we'll use this function
# until that one gets rewritten. # until that one gets rewritten.
......
...@@ -217,6 +217,35 @@ sub match_field { ...@@ -217,6 +217,35 @@ sub match_field {
# What does a "--do_not_change--" field look like (if any)? # What does a "--do_not_change--" field look like (if any)?
my $dontchange = $vars->{'form'}->{'dontchange'}; my $dontchange = $vars->{'form'}->{'dontchange'};
# Fields can be regular expressions matching multiple form fields
# (f.e. "requestee-(\d+)"), so expand each non-literal field
# into the list of form fields it matches.
my $expanded_fields = {};
foreach my $field_pattern (keys %{$fields}) {
# Check if the field has any non-word characters. Only those fields
# can be regular expressions, so don't expand the field if it doesn't
# have any of those characters.
if ($field_pattern =~ /^\w+$/) {
$expanded_fields->{$field_pattern} = $fields->{$field_pattern};
}
else {
my @field_names = grep(/$field_pattern/, keys %{$vars->{'form'}});
foreach my $field_name (@field_names) {
$expanded_fields->{$field_name} =
{ type => $fields->{$field_pattern}->{'type'} };
# The field is a requestee field; in order for its name to show
# up correctly on the confirmation page, we need to find out
# the name of its flag type.
if ($field_name =~ /^requestee-(\d+)$/) {
$expanded_fields->{$field_name}->{'flag_type'} =
Bugzilla::FlagType::get($1);
}
}
}
}
$fields = $expanded_fields;
# Skip all of this if the option has been turned off # Skip all of this if the option has been turned off
return 1 if (&::Param('usermatchmode') eq 'off'); return 1 if (&::Param('usermatchmode') eq 'off');
...@@ -285,10 +314,8 @@ sub match_field { ...@@ -285,10 +314,8 @@ sub match_field {
next; next;
} }
$matches->{$field}->{$query}->{'users'} = $users; $matches->{$field}->{$query}->{'users'} = $users;
$matches->{$field}->{$query}->{'status'} = 'success'; $matches->{$field}->{$query}->{'status'} = 'success';
$matches->{$field}->{$query}->{'selecttype'} =
$fields->{$field}->{'type'};
# here is where it checks for multiple matches # here is where it checks for multiple matches
...@@ -323,6 +350,7 @@ sub match_field { ...@@ -323,6 +350,7 @@ sub match_field {
return 1 unless $need_confirm; # skip confirmation if not needed. return 1 unless $need_confirm; # skip confirmation if not needed.
$vars->{'script'} = $ENV{'SCRIPT_NAME'}; # for self-referencing URLs $vars->{'script'} = $ENV{'SCRIPT_NAME'}; # for self-referencing URLs
$vars->{'fields'} = $fields; # fields being matched
$vars->{'matches'} = $matches; # matches that were made $vars->{'matches'} = $matches; # matches that were made
$vars->{'matchsuccess'} = $matchsuccess; # continue or fail $vars->{'matchsuccess'} = $matchsuccess; # continue or fail
......
...@@ -44,6 +44,7 @@ require "CGI.pl"; ...@@ -44,6 +44,7 @@ require "CGI.pl";
# Use these modules to handle flags. # Use these modules to handle flags.
use Bugzilla::Flag; use Bugzilla::Flag;
use Bugzilla::FlagType; use Bugzilla::FlagType;
use Bugzilla::User;
# Establish a connection to the database backend. # Establish a connection to the database backend.
ConnectToDatabase(); ConnectToDatabase();
...@@ -109,6 +110,7 @@ elsif ($action eq "update") ...@@ -109,6 +110,7 @@ elsif ($action eq "update")
validateContentType() unless $::FORM{'ispatch'}; validateContentType() unless $::FORM{'ispatch'};
validateIsObsolete(); validateIsObsolete();
validatePrivate(); validatePrivate();
Bugzilla::User::match_field({ '^requestee-(\d+)$' => { 'type' => 'single' } });
Bugzilla::Flag::validate(\%::FORM); Bugzilla::Flag::validate(\%::FORM);
Bugzilla::FlagType::validate(\%::FORM); Bugzilla::FlagType::validate(\%::FORM);
update(); update();
......
...@@ -91,9 +91,10 @@ scalar(@idlist) || ThrowUserError("no_bugs_chosen"); ...@@ -91,9 +91,10 @@ scalar(@idlist) || ThrowUserError("no_bugs_chosen");
# do a match on the fields if applicable # do a match on the fields if applicable
&Bugzilla::User::match_field({ &Bugzilla::User::match_field({
'qa_contact' => { 'type' => 'single' }, 'qa_contact' => { 'type' => 'single' },
'newcc' => { 'type' => 'multi' }, 'newcc' => { 'type' => 'multi' },
'assigned_to' => { 'type' => 'single' }, 'assigned_to' => { 'type' => 'single' },
'^requestee-(\d+)$' => { 'type' => 'single' },
}); });
# If we are duping bugs, let's also make sure that we can change # If we are duping bugs, let's also make sure that we can change
......
...@@ -23,13 +23,15 @@ ...@@ -23,13 +23,15 @@
[%# INTERFACE: [%# INTERFACE:
# form: hash; the form values submitted to the script # form: hash; the form values submitted to the script
# mform: hash; the form multi-values submitted to the script # mform: hash; the form multi-values submitted to the script
# fields: hash/record; the fields being matched, each of which has:
# type: single|multi: whether or not the user can select multiple matches
# flag_type: for flag requestee fields, the type of flag being requested
# matches: hash; Hierarchical. The levels go like this: # matches: hash; Hierarchical. The levels go like this:
# field_name { # field_name {
# pattern_text { # pattern_text {
# 'users' = @user_list (user objects) # 'users' = @user_list (user objects)
# 'selecttype' = single|multi (selectbox type) # 'status' = success|fail|trunc (result of search.
# 'status' = success|fail|trunc (result of search. # 'trunc' (truncated) means max was reached)
# 'trunc' (truncated) means max was reached)
# } # }
# } # }
# script: string; The name of the calling script, used to create a # script: string; The name of the calling script, used to create a
...@@ -90,7 +92,7 @@ ...@@ -90,7 +92,7 @@
</font> </font>
Please go back and try again with a more specific Please go back and try again with a more specific
name/address. name/address.
[% ELSIF query.value.selecttype == 'single' %] [% ELSIF fields.${field.key}.type == 'single' %]
matched:<br> matched:<br>
<select name="[% field.key FILTER html %]" <select name="[% field.key FILTER html %]"
id="[% field.key FILTER html %]"> id="[% field.key FILTER html %]">
...@@ -173,6 +175,9 @@ ...@@ -173,6 +175,9 @@
[%- # ELSIF for things that don't belong in the field_descs hash here -%] [%- # ELSIF for things that don't belong in the field_descs hash here -%]
[% ELSIF field_name.match("^requestee") %]
[% fields.${field_name}.flag_type.name %] requestee
[% ELSE %] [% ELSE %]
[% field_name FILTER html %] [% field_name FILTER html %]
[% END %] [% END %]
......
<!-- 1.0@bugzilla.org -->
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Myk Melez <myk@mozilla.org>
#%]
[%# INTERFACE:
# form, mform: hashes; the form values submitted to the script, used by
# hidden-fields to generate hidden form fields replicating
# the original form
# flags: array; the flags the user made, including information about
# potential requestees for those flags (based on
# the string the user typed into the requestee fields)
# target: record; the bug/attachment for which the flags are being made
#%]
[% UNLESS header_done %]
[% title = BLOCK %]
Verify Requests for Bug #[% target.bug.id %]
[% IF target.attachment %], Attachment #[% target.attachment.id %][% END %]
[% END %]
[% h1 = BLOCK %]
Verify Requests for <a href="show_bug.cgi?id=[% target.bug.id %]">Bug #[% target.bug.id %]</a>
[% IF target.attachment.exists %],
<a href="attachment.cgi?id=[% target.attachment.id %]&action=edit">Attachment #[% target.attachment.id %]</a>
[% END %]
[% END %]
[% h2 = BLOCK %]
[% target.bug.summary FILTER html %]
[% IF target.attachment.exists %]
: [% target.attachment.summary FILTER html %]
[% END %]
[% END %]
[% PROCESS global/header.html.tmpl %]
[% END %]
<form method="post">
[% PROCESS "global/hidden-fields.html.tmpl"
exclude=("^(flag_type|requestee)-") %]
[% FOREACH flag = flags %]
[% IF flag.requestees.size == 0 %]
<p>
Sorry, I can't find a user whose name or email address contains
the string <em>[% flag.requestee_str FILTER html %]</em>.
Double-check that the user's name or email address contains that
string, or try entering a shorter string.
</p>
<p>
Ask <input type="text" size="20" maxlength="255"
name="requestee-[% flag.type.id %]"
value="[% flag.requestee_str FILTER html %]">
for [% flag.type.name FILTER html %]
<input type="hidden" name="flag_type-[% flag.type.id %]" value="?">
</p>
[% ELSIF flag.requestees.size == 1 %]
<input type="hidden"
name="requestee-[% flag.type.id %]"
value="[% flag.requestee.email FILTER html %]">
<input type="hidden" name="flag_type-[% flag.type.id %]" value="?">
[% ELSE %]
<p>
More than one user's name or email address contains the string
<em>[% flag.requestee_str FILTER html %]</em>. Choose the user
you meant from the following menu or click the back button and try
again with a more specific string.
</p>
<p>
Ask <select name="requestee-[% flag.type.id %]">
[% FOREACH requestee = flag.requestees %]
<option value="[% requestee.email FILTER html %]">
[% requestee.identity FILTER html%]</option>
[% END %]
</select>
for [% flag.type.name %]
<input type="hidden" name="flag_type-[% flag.type.id %]" value="?">
</p>
[% END %]
[% END %]
<input type="submit" value="Commit">
</form>
[% PROCESS global/footer.html.tmpl %]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment