diff options
-rw-r--r-- | globals.pl | 24 | ||||
-rwxr-xr-x | 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 "<H1>Changing product means changing version, target milestone and component.</H1>\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.<p>\n"; - print "<form>\n"; - print "<table>\n"; - print "<tr>\n"; - print "<td align=right><b>Product:</b></td>\n"; - print "<td>$prod</td>\n"; - print "</tr><tr>\n"; - print "<td align=right><b>Version:</b></td>\n"; - print "<td>" . Version_element($::FORM{'version'}, $prod) . "</td>\n"; - print "</tr><tr>\n"; - - if ( Param("usetargetmilestone") ) { - print "<td align=right><b>Target Milestone:</b></td>\n"; - print "<td>" . Milestone_element($::FORM{'target_milestone'}, $prod) . "</td>\n"; - print "</tr><tr>\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|<form action="process_bug.cgi" method="post">\n|; - print "<td align=right><b>Component:</b></td>\n"; - print "<td>" . Component_element($::FORM{'component'}, $prod) . "</td>\n"; - print "</tr>\n"; - print "</table>\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 "<input type=hidden name=$i value=\"" . - value_quote($::FORM{$i}) . "\">\n"; + print qq|<input type="hidden" name="$i" value="| . value_quote($::FORM{$i}) . 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 <b>$prod</b>, 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 <b>$prod</b>, 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| + <h3>$sectiontitle</h3> + + <p> + $sectiondescription + <p> + + <table><tr> + <td> + <b>Version:</b><br> + $versionmenu + </td> + <td> + <b>Component:</b><br> + $componentmenu + </td> + |; + + if ( Param("usetargetmilestone") ) { + my $milestonemenu = Milestone_element($::FORM{'target_milestone'}, $prod); + print qq| + <td> + <b>Target Milestone:</b><br> + $milestonemenu + </td> + |; } + + print qq| + </tr></table> + |; + } + + # 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| + <h3>Verify Bug Group</h3> + + <p> + Do you want to add the bug to its new product's group (if any)? + </p> + + <p> + <input type="radio" name="addtonewgroup" value="no"><b>no</b><br> + <input type="radio" name="addtonewgroup" value="yes"><b>yes</b><br> + <input type="radio" name="addtonewgroup" value="yesifinold" checked> + <b>yes, but only if the bug was in its old product's group</b><br> + </p> + |; } - print "<input type=submit value=Commit>\n"; - print "</form>\n"; - print "</hr>\n"; - print "<a href=query.cgi>Cancel all this and go to the query page.</a>\n"; + + # End the form. + print qq| + <input type="submit" value="Commit"> + </form> + <hr> + <a href="query.cgi">Cancel and Return to the Query Page</a> + |; + + # 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|<p>\n|; + print qq|<em>usebuggroups</em> is enabled and this bug has changed from the + <em>$oldhash{'product'}</em> to the <em>$::FORM{'product'}</em> 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.<br>\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 <em>addtonewgroup</em>, there is a group + associated with the new product, the user is a member of that + group (or <em>usebuggroupsentry</em> is off), and the group + is active, so we have to add the product to the group:<br> + <code>UPDATE bugs SET groupset = groupset + $groupbit WHERE bug_id = $id</code><br> + |; + # 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:<br> + UPDATE bugs SET groupset = groupset - $groupbit WHERE bug_id = $id<br> + |; + # 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|</p>|; + } + # 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. |