From 53d3d353d29c8bd47d90cca6c3f55cf36a1f24ff Mon Sep 17 00:00:00 2001 From: "zach%zachlipton.com" <> Date: Sat, 11 Aug 2001 08:18:16 +0000 Subject: fix for bug 66235: process_bug.cgi: multiple product change misses the groupset bit. Patch by Myk r=Jake, oh, and it's my first checkin, yahoo! --- globals.pl | 24 ++++++ process_bug.cgi | 226 +++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 217 insertions(+), 33 deletions(-) diff --git a/globals.pl b/globals.pl index 51fe1ddee..29024e26d 100644 --- a/globals.pl +++ b/globals.pl @@ -1108,6 +1108,16 @@ sub UserInGroup { return 0; } +sub BugInGroup { + my ($bugid, $groupname) = (@_); + my $groupbit = GroupNameToBit($groupname); + PushGlobalSQLState(); + SendSQL("SELECT (bugs.groupset & $groupbit) != 0 FROM bugs WHERE bugs.bug_id = $bugid"); + my $bugingroup = FetchOneColumn(); + PopGlobalSQLState(); + return $bugingroup; +} + sub GroupExists { my ($groupname) = (@_); ConnectToDatabase(); @@ -1116,11 +1126,25 @@ sub GroupExists { return $count; } +# Given the name of an existing group, returns the bit associated with it. +# If the group does not exist, returns 0. +# !!! Remove this function when the new group system is implemented! +sub GroupNameToBit { + my ($groupname) = (@_); + ConnectToDatabase(); + PushGlobalSQLState(); + SendSQL("SELECT bit FROM groups WHERE name = " . SqlQuote($groupname)); + my $bit = FetchOneColumn() || 0; + PopGlobalSQLState(); + return $bit; +} + # Determines whether or not a group is active by checking # the "isactive" column for the group in the "groups" table. # Note: This function selects groups by bit rather than by name. sub GroupIsActive { my ($groupbit) = (@_); + $groupbit ||= 0; ConnectToDatabase(); SendSQL("select isactive from groups where bit=$groupbit"); my $isactive = FetchOneColumn(); diff --git a/process_bug.cgi b/process_bug.cgi index d42f6b84e..511150911 100755 --- a/process_bug.cgi +++ b/process_bug.cgi @@ -108,7 +108,19 @@ if ( Param("strictvaluechecks") ) { } } -if ($::FORM{'product'} ne $::dontchange) { +ConnectToDatabase(); + +# Figure out whether or not the user is trying to change the product +# (either the "product" variable is not set to "don't change" or the +# user is changing a single bug and has changed the bug's product), +# and make the user verify the version, component, target milestone, +# and bug groups if so. +if ( $::FORM{'id'} ) { + SendSQL("SELECT product FROM bugs WHERE bug_id = $::FORM{'id'}"); + $::oldproduct = FetchSQLData(); +} +if ( ($::FORM{'id'} && $::FORM{'product'} ne $::oldproduct) + || (!$::FORM{'id'} && $::FORM{'product'} ne $::dontchange) ) { if ( Param("strictvaluechecks") ) { CheckFormField(\%::FORM, 'product', \@::legal_product); } @@ -130,42 +142,105 @@ if ($::FORM{'product'} ne $::dontchange) { $mok = lsearch($::target_milestone{$prod}, $::FORM{'target_milestone'}) >= 0; } - if (!$vok || !$cok || !$mok) { - print "

Changing product means changing version, target milestone and component.

\n"; - print "You have chosen a new product, and now the version, target milestone and/or\n"; - print "component fields are not correct. (Or, possibly, the bug did\n"; - print "not have a valid target milestone, component or version field in the first place.)\n"; - print "Anyway, please set the version, target milestone and component now.

\n"; - print "

\n"; - print "\n"; - print "\n"; - print "\n"; - print "\n"; - print "\n"; - print "\n"; - print "\n"; - print "\n"; - - if ( Param("usetargetmilestone") ) { - print "\n"; - print "\n"; - print "\n"; - } + # If anything needs to be verified, generate a form for verifying it. + if (!$vok || !$cok || !$mok || (Param('usebuggroups') && !defined($::FORM{'addtonewgroup'}))) { + + # Start the form. + print qq|\n|; - print "\n"; - print "\n"; - print "\n"; - print "
Product:$prod
Version:" . Version_element($::FORM{'version'}, $prod) . "
Target Milestone:" . Milestone_element($::FORM{'target_milestone'}, $prod) . "
Component:" . Component_element($::FORM{'component'}, $prod) . "
\n"; + # Add all form fields to the form as hidden fields (except those + # being verified), so the user's changes are preserved. foreach my $i (keys %::FORM) { if ($i ne 'version' && $i ne 'component' && $i ne 'target_milestone') { - print "\n"; + print qq|\n|; + } + } + + # Display UI for verifying the version, component, and target milestone fields. + if (!$vok || !$cok || !$mok) { + my ($sectiontitle, $sectiondescription); + if ( Param('usetargetmilestone') ) { + $sectiontitle = "Verify Version, Component, Target Milestone"; + $sectiondescription = qq| + You are moving the bug(s) to the product $prod, and now the + version, component, and/or target milestone fields are not correct + (or perhaps they were not correct in the first place). In any case, + please set the correct version, component, and target milestone now: + |; + } else { + $sectiontitle = "Verify Version, Component"; + $sectiondescription = qq| + You are moving the bug(s) to the product $prod, and now the + version, and component fields are not correct (or perhaps they were + not correct in the first place). In any case, please set the correct + version and component now: + |; + } + + my $versionmenu = Version_element($::FORM{'version'}, $prod); + my $componentmenu = Component_element($::FORM{'component'}, $prod); + + print qq| +

$sectiontitle

+ +

+ $sectiondescription +

+ + + + + |; + + if ( Param("usetargetmilestone") ) { + my $milestonemenu = Milestone_element($::FORM{'target_milestone'}, $prod); + print qq| + + |; } + + print qq| +
+ Version:
+ $versionmenu +
+ Component:
+ $componentmenu +
+ Target Milestone:
+ $milestonemenu +
+ |; + } + + # Display UI for determining whether or not to remove the bug from + # its old product's group and/or add it to its new product's group. + if (Param('usebuggroups') && !defined($::FORM{'addtonewgroup'})) { + print qq| +

Verify Bug Group

+ +

+ Do you want to add the bug to its new product's group (if any)? +

+ +

+ no
+ yes
+ + yes, but only if the bug was in its old product's group
+

+ |; } - print "\n"; - print "
\n"; - print "\n"; - print "Cancel all this and go to the query page.\n"; + + # End the form. + print qq| + + +
+ Cancel and Return to the Query Page + |; + + # End the page and stop processing. PutFooter(); exit; } @@ -453,7 +528,6 @@ if (defined $::FORM{'qa_contact'}) { } -ConnectToDatabase(); my $removedCcString = ""; my $duplicate = 0; @@ -993,6 +1067,92 @@ The changes made were: } } + # When a bug changes products and the old or new product is associated + # with a bug group, it may be necessary to remove the bug from the old + # group or add it to the new one. There are a very specific series of + # conditions under which these activities take place, more information + # about which can be found in comments within the conditionals below. + if ( + # the "usebuggroups" parameter is on, indicating that products + # are associated with groups of the same name; + Param('usebuggroups') + + # the user has changed the product to which the bug belongs; + && defined $::FORM{'product'} + && $::FORM{'product'} ne $::dontchange + && $::FORM{'product'} ne $oldhash{'product'} + ) { + # DEBUGGING INSTRUCTIONS THAT WILL GO AWAY ONCE THIS PATCH IS READY + print qq|

\n|; + print qq|usebuggroups is enabled and this bug has changed from the + $oldhash{'product'} to the $::FORM{'product'} product, + so it is time to check if we have to remove the bug from its old product + group or add it to its new product group.
\n|; + # END DEBUGGING INSTRUCTIONS THAT WILL GO AWAY ONCE THIS PATCH IS READY + if ( + # the user wants to add the bug to the new product's group; + ($::FORM{'addtonewgroup'} eq 'yes' + || ($::FORM{'addtonewgroup'} eq 'yesifinold' + && GroupNameToBit($oldhash{'product'}) & $oldhash{'groupset'})) + + # the new product is associated with a group; + && GroupExists($::FORM{'product'}) + + # the bug is not already in the group; (This can happen when the user + # goes to the "edit multiple bugs" form with a list of bugs at least + # one of which is in the new group. In this situation, the user can + # simultaneously change the bugs to a new product and move the bugs + # into that product's group, which happens earlier in this script + # and thus is already done. If we didn't check for this, then this + # situation would cause us to add the bug to the group twice, which + # would result in the bug being added to a totally different group.) + && !BugInGroup($id, $::FORM{'product'}) + + # the user is a member of the associated group, indicating they + # are authorized to add bugs to that group, *or* the "usebuggroupsentry" + # parameter is off, indicating that users can add bugs to a product + # regardless of whether or not they belong to its associated group; + && (UserInGroup($::FORM{'product'}) || !Param('usebuggroupsentry')) + + # the associated group is active, indicating it can accept new bugs; + && GroupIsActive(GroupNameToBit($::FORM{'product'})) + ) { + # Add the bug to the group associated with its new product. + my $groupbit = GroupNameToBit($::FORM{'product'}); + # DEBUGGING INSTRUCTIONS THAT WILL GO AWAY ONCE THIS PATCH IS READY + print qq| + The user specified addtonewgroup, there is a group + associated with the new product, the user is a member of that + group (or usebuggroupsentry is off), and the group + is active, so we have to add the product to the group:
+ UPDATE bugs SET groupset = groupset + $groupbit WHERE bug_id = $id
+ |; + # END DEBUGGING INSTRUCTIONS THAT WILL GO AWAY ONCE THIS PATCH IS READY + SendSQL("UPDATE bugs SET groupset = groupset + $groupbit WHERE bug_id = $id"); + } + + if ( + # the old product is associated with a group; + GroupExists($oldhash{'product'}) + + # the bug is a member of that group; + && BugInGroup($id, $oldhash{'product'}) + ) { + # Remove the bug from the group associated with its old product. + # DEBUGGING INSTRUCTIONS THAT WILL GO AWAY ONCE THIS PATCH IS READY + my $groupbit = GroupNameToBit($oldhash{'product'}); + print qq| + There is a group associated with the old product, the bug is a + member of that group, so remove the bug from the group:
+ UPDATE bugs SET groupset = groupset - $groupbit WHERE bug_id = $id
+ |; + # END DEBUGGING INSTRUCTIONS THAT WILL GO AWAY ONCE THIS PATCH IS READY + SendSQL("UPDATE bugs SET groupset = groupset - $groupbit WHERE bug_id = $id"); + } + + print qq|

|; + } + # get a snapshot of the newly set values out of the database, # and then generate any necessary bug activity entries by seeing # what has changed since before we wrote out the new values. -- cgit v1.2.3-24-g4f1b