]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 223878: Flag system dies when changing a deleted flag.
authorjouni%heikniemi.net <>
Tue, 6 Jul 2004 14:08:02 +0000 (14:08 +0000)
committerjouni%heikniemi.net <>
Tue, 6 Jul 2004 14:08:02 +0000 (14:08 +0000)
r=joel, justdave
a=justdave

Bugzilla/Attachment.pm
Bugzilla/Bug.pm
Bugzilla/Flag.pm
Bugzilla/FlagType.pm
Bugzilla/Search.pm
attachment.cgi
checksetup.pl
editflagtypes.cgi
request.cgi

index 9f0467bb7193e35c379ca5f3d7fccc528e41009b..e7b3ffe86e52885f84d758aaf28f00944e133c14 100644 (file)
@@ -90,7 +90,8 @@ sub query
      $a{'datasize'}) = &::FetchSQLData();
 
     # Retrieve a list of flags for this attachment.
-    $a{'flags'} = Bugzilla::Flag::match({ 'attach_id' => $a{'attachid'} });
+    $a{'flags'} = Bugzilla::Flag::match({ 'attach_id' => $a{'attachid'},
+                                          'is_active' => 1 });
     
     # We will display the edit link if the user can edit the attachment;
     # ie the are the submitter, or they have canedit.
index 91cd0d8c8292654bd6cb9507a8883cacfe0a5228..f1a1cf34175bb150ce0784cda1ec05a13c91476b 100755 (executable)
@@ -226,7 +226,8 @@ sub initBug  {
       $flag_type->{'flags'} = 
         Bugzilla::Flag::match({ 'bug_id'      => $self->{bug_id},
                                 'type_id'     => $flag_type->{'id'},
-                                'target_type' => 'bug' });
+                                'target_type' => 'bug',
+                                'is_active'   => 1 });
   }
   $self->{'flag_types'} = $flag_types;
   $self->{'any_flags_requesteeble'} = grep($_->{'is_requesteeble'}, @$flag_types);
@@ -238,11 +239,11 @@ sub initBug  {
   my $num_attachment_flag_types =
     Bugzilla::FlagType::count({ 'target_type'  => 'attachment',
                                 'product_id'   => $self->{'product_id'},
-                                'component_id' => $self->{'component_id'},
-                                'is_active'    => 1 });
+                                'component_id' => $self->{'component_id'} });
   my $num_attachment_flags =
     Bugzilla::Flag::count({ 'target_type'  => 'attachment',
-                            'bug_id'       => $self->{bug_id} });
+                            'bug_id'       => $self->{bug_id},
+                            'is_active'    => 1 });
 
   $self->{'show_attachment_flags'}
     = $num_attachment_flag_types || $num_attachment_flags;
index 3272b840917934e289d418bcc48795219c40c350..707316ce1339e75bc543700fb3a2651a9b171bde 100644 (file)
@@ -18,6 +18,7 @@
 # Rights Reserved.
 #
 # Contributor(s): Myk Melez <myk@mozilla.org>
+#                 Jouni Heikniemi <jouni@heikniemi.net>
 
 ################################################################################
 # Module Initialization
@@ -52,8 +53,8 @@ use vars qw($template $vars);
 # basic sets of columns and tables for getting flags from the database
 
 my @base_columns = 
-  ("1", "id", "type_id", "bug_id", "attach_id", "requestee_id", "setter_id",
-   "status");
+  ("is_active", "id", "type_id", "bug_id", "attach_id", "requestee_id", 
+   "setter_id", "status");
 
 # Note: when adding tables to @base_tables, make sure to include the separator 
 # (i.e. a comma or words like "LEFT OUTER JOIN") before the table name, 
@@ -154,6 +155,11 @@ sub validate {
         my $flag = get($id);
         $flag || ThrowCodeError("flag_nonexistent", { id => $id });
 
+        # Note that the deletedness of the flag (is_active or not) is not 
+        # checked here; we do want to allow changes to deleted flags in
+        # certain cases. Flag::modify() will revive the modified flags.
+        # See bug 223878 for details.
+
         # Make sure the user chose a valid status.
         grep($status eq $_, qw(X + - ?))
           || ThrowCodeError("flag_status_invalid", 
@@ -226,7 +232,8 @@ sub process {
     
     # Take a snapshot of flags before any changes.
     my $flags = match({ 'bug_id'    => $target->{'bug'}->{'id'} , 
-                        'attach_id' => $target->{'attachment'}->{'id'} });
+                        'attach_id' => $target->{'attachment'}->{'id'} ,
+                        'is_active' => 1 });
     my @old_summaries;
     foreach my $flag (@$flags) {
         my $summary = $flag->{'type'}->{'name'} . $flag->{'status'};
@@ -249,6 +256,7 @@ sub process {
             AND (bugs.product_id = i.product_id OR i.product_id IS NULL)
             AND (bugs.component_id = i.component_id OR i.component_id IS NULL))
         WHERE bugs.bug_id = $target->{'bug'}->{'id'} 
+        AND flags.is_active = 1
         AND i.type_id IS NULL
     ");
     clear(&::FetchOneColumn()) while &::MoreSQLData();
@@ -257,7 +265,8 @@ sub process {
         FROM flags, bugs, flagexclusions e
         WHERE bugs.bug_id = $target->{'bug'}->{'id'}
         AND flags.bug_id = bugs.bug_id
-        AND flags.type_id = e.type_id 
+        AND flags.type_id = e.type_id
+        AND flags.is_active = 1 
         AND (bugs.product_id = e.product_id OR e.product_id IS NULL)
         AND (bugs.component_id = e.component_id OR e.component_id IS NULL)
     ");
@@ -265,7 +274,8 @@ sub process {
     
     # Take a snapshot of flags after changes.
     $flags = match({ 'bug_id'    => $target->{'bug'}->{'id'} , 
-                     'attach_id' => $target->{'attachment'}->{'id'} });
+                     'attach_id' => $target->{'attachment'}->{'id'} ,
+                     'is_active' => 1 });
     my @new_summaries;
     foreach my $flag (@$flags) {
         my $summary = $flag->{'type'}->{'name'} . $flag->{'status'};
@@ -340,6 +350,9 @@ sub migrate {
 
 sub modify {
     # Modifies flags in the database when a user changes them.
+    # Note that modified flags are always set active (is_active = 1) -
+    # this will revive deleted flags that get changed through 
+    # attachment.cgi midairs. See bug 223878 for details.
 
     my ($data, $timestamp) = @_;
 
@@ -385,7 +398,8 @@ sub modify {
                         SET    setter_id = $::userid , 
                                requestee_id = NULL , 
                                status = '$status' , 
-                               modification_date = $timestamp
+                               modification_date = $timestamp ,
+                               is_active = 1
                         WHERE  id = $flag->{'id'}");
             
             # Send an email notifying the relevant parties about the fulfillment.
@@ -409,7 +423,8 @@ sub modify {
                         SET    setter_id = $::userid , 
                                requestee_id = $requestee_id , 
                                status = '$status' , 
-                               modification_date = $timestamp
+                               modification_date = $timestamp ,
+                               is_active = 1
                         WHERE  id = $flag->{'id'}");
             
             # Send an email notifying the relevant parties about the request.
@@ -420,7 +435,7 @@ sub modify {
                 notify($flag, "request/email.txt.tmpl");
             }
         }
-        # The user unset the flag, so delete it from the database.
+        # The user unset the flag; set is_active = 0
         elsif ($status eq 'X') {
             clear($flag->{'id'});
         }
@@ -437,9 +452,10 @@ sub clear {
     my $flag = get($id);
     
     &::PushGlobalSQLState();
-    &::SendSQL("DELETE FROM flags WHERE id = $id");
+    &::SendSQL("UPDATE flags SET is_active = 0 WHERE id = $id");
     &::PopGlobalSQLState();
-    
+
+    $flag->{'exists'} = 0;    
     # Set the flag's status to "cleared" so the email template
     # knows why email is being sent about the request.
     $flag->{'status'} = "X";
@@ -625,6 +641,7 @@ sub sqlify_criteria {
         elsif ($field eq 'requestee_id') { push(@criteria, "requestee_id = $value") }
         elsif ($field eq 'setter_id')    { push(@criteria, "setter_id    = $value") }
         elsif ($field eq 'status')       { push(@criteria, "status       = '$value'") }
+        elsif ($field eq 'is_active')    { push(@criteria, "is_active    = $value") }
     }
     
     return @criteria;
@@ -635,6 +652,8 @@ sub perlify_record {
     my ($exists, $id, $type_id, $bug_id, $attach_id, 
         $requestee_id, $setter_id, $status) = @_;
     
+    return undef unless defined($exists);
+    
     my $flag =
       {
         exists    => $exists , 
index e6bfaf7ef02a33b5e71917ee1a24129b8f213930..a428d5389acc45c284603355cc8d23079fffc76e 100644 (file)
@@ -270,6 +270,7 @@ sub normalize {
             AND (bugs.product_id = i.product_id OR i.product_id IS NULL)
             AND (bugs.component_id = i.component_id OR i.component_id IS NULL))
         WHERE flags.type_id IN ($ids)
+        AND flags.is_active = 1
         AND i.type_id IS NULL
     ");
     Bugzilla::Flag::clear(&::FetchOneColumn()) while &::MoreSQLData();
@@ -280,6 +281,7 @@ sub normalize {
         WHERE flags.type_id IN ($ids)
         AND flags.bug_id = bugs.bug_id
         AND flags.type_id = e.type_id 
+        AND flags.is_active = 1
         AND (bugs.product_id = e.product_id OR e.product_id IS NULL)
         AND (bugs.component_id = e.component_id OR e.component_id IS NULL)
     ");
index 2f92131fc8d610370731d8f8e1a89f1f6b847706..0ebf1e070105557b6221754c9f9001fcfcbd1ae7 100644 (file)
@@ -586,7 +586,8 @@ sub init {
              # negative conditions (f.e. "flag isn't review+").
              my $flags = "flags_$chartid";
              push(@supptables, "LEFT JOIN flags $flags " . 
-                               "ON bugs.bug_id = $flags.bug_id");
+                               "ON bugs.bug_id = $flags.bug_id " .
+                               "AND $flags.is_active = 1");
              my $flagtypes = "flagtypes_$chartid";
              push(@supptables, "LEFT JOIN flagtypes $flagtypes " . 
                                "ON $flags.type_id = $flagtypes.id");
index c1e8f9dd0fc83bf8966192e8bf3504348b102f92..06a04291e70de66e674e8be5c5472190bd09e578 100755 (executable)
@@ -768,7 +768,8 @@ sub viewall
      $a{'description'}, $a{'ispatch'}, $a{'isobsolete'}, $a{'isprivate'},
      $a{'datasize'}) = FetchSQLData();
     $a{'isviewable'} = isViewable($a{'contenttype'});
-    $a{'flags'} = Bugzilla::Flag::match({ 'attach_id' => $a{'attachid'} });
+    $a{'flags'} = Bugzilla::Flag::match({ 'attach_id' => $a{'attachid'},
+                                          'is_active' => 1 });
 
     # Add the hash representing the attachment to the array of attachments.
     push @attachments, \%a;
@@ -880,7 +881,9 @@ sub insert
       SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added) 
                VALUES ($::FORM{'bugid'}, $obsolete_id, $::userid, NOW(), $fieldid, '0', '1')");
       # If the obsolete attachment has pending flags, migrate them to the new attachment.
-      if (Bugzilla::Flag::count({ 'attach_id' => $obsolete_id , 'status' => 'pending' })) {
+      if (Bugzilla::Flag::count({ 'attach_id' => $obsolete_id , 
+                                  'status' => 'pending',
+                                  'is_active' => 1 })) {
         Bugzilla::Flag::migrate($obsolete_id, $attachid);
       }
   }
@@ -984,7 +987,8 @@ sub edit
                                                'component_id' => $component_id });
   foreach my $flag_type (@$flag_types) {
     $flag_type->{'flags'} = Bugzilla::Flag::match({ 'type_id'   => $flag_type->{'id'}, 
-                                                    'attach_id' => $::FORM{'id'} });
+                                                    'attach_id' => $::FORM{'id'},
+                                                    'is_active' => 1 });
   }
   $vars->{'flag_types'} = $flag_types;
   $vars->{'any_flags_requesteeble'} = grep($_->{'is_requesteeble'}, @$flag_types);
index 684a8ca7edb2086f1e267d50b72c87ea708fab3b..3c4793407daf6e8b229e3d355f0ed27f95f000cf 100755 (executable)
@@ -1609,6 +1609,8 @@ $table{flags} =
      
      setter_id          MEDIUMINT     NULL , 
      requestee_id       MEDIUMINT     NULL , 
+     
+     is_active          TINYINT       NOT NULL  DEFAULT 1, 
    
      INDEX(bug_id, attach_id) , 
      INDEX(setter_id) , 
@@ -3935,6 +3937,11 @@ if (GetFieldDef("user_group_map", "isderived")) {
     }
 }
 
+# 2004-07-03 - Make it possible to disable flags without deleting them
+# from the database. Bug 223878, jouni@heikniemi.net
+
+AddField('flags', 'is_active', 'tinyint not null default 1');
+
     
 
 # If you had to change the --TABLE-- definition in any way, then add your
index 5fcabd73fd560c5bdce0938e496a690eb9bfada6..bb1b86ec0d6ac83558cd67f4bc842780fbede48e 100755 (executable)
@@ -308,6 +308,7 @@ sub update {
             AND (bugs.component_id = i.component_id OR i.component_id IS NULL))
         WHERE flags.type_id = $::FORM{'id'} 
         AND flags.bug_id = bugs.bug_id
+        AND flags.is_active = 1
         AND i.type_id IS NULL
     ");
     Bugzilla::Flag::clear(FetchOneColumn()) while MoreSQLData();
@@ -318,6 +319,7 @@ sub update {
         WHERE flags.type_id = $::FORM{'id'}
         AND flags.bug_id = bugs.bug_id
         AND flags.type_id = e.type_id 
+        AND flags.is_active = 1
         AND (bugs.product_id = e.product_id OR e.product_id IS NULL)
         AND (bugs.component_id = e.component_id OR e.component_id IS NULL)
     ");
@@ -340,7 +342,8 @@ sub confirmDelete
   validateID();
   # check if we need confirmation to delete:
   
-  my $count = Bugzilla::Flag::count({ 'type_id' => $::FORM{'id'} });
+  my $count = Bugzilla::Flag::count({ 'type_id' => $::FORM{'id'},
+                                      'is_active' => 1 });
   
   if ($count > 0) {
     $vars->{'flag_type'} = Bugzilla::FlagType::get($::FORM{'id'});
index e330c2c832ee70419e7b3461f98cd0fb578155b3..047c4fa1437d35b5dffa3efa28ff811f3289b9a4 100755 (executable)
@@ -116,6 +116,9 @@ sub queue {
       AND       flags.bug_id        = bugs.bug_id
     ";
     
+    # Non-deleted flags only
+    $query .= " AND flags.is_active = 1 ";
+    
     # Limit query to pending requests.
     $query .= " AND flags.status = '?' " unless $cgi->param('status');