]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 453743: Decrease the number of calls to the DB about flags when viewing a bug...
authorlpsolit%gmail.com <>
Mon, 8 Sep 2008 21:21:24 +0000 (21:21 +0000)
committerlpsolit%gmail.com <>
Mon, 8 Sep 2008 21:21:24 +0000 (21:21 +0000)
Bugzilla/Attachment.pm
Bugzilla/Bug.pm
Bugzilla/Flag.pm
attachment.cgi
template/en/default/attachment/edit.html.tmpl

index 314227c873302950359f99a8adfacc567fd20828..fcaf38c9fead3d62dcb7a9c16dd5e1d01615df5e 100644 (file)
@@ -139,8 +139,6 @@ the ID of the bug to which the attachment is attached
 
 =cut
 
-# XXX Once Bug.pm slims down sufficiently this should become a reference
-# to a bug object.
 sub bug_id {
     my $self = shift;
     return $self->{bug_id};
@@ -148,6 +146,24 @@ sub bug_id {
 
 =over
 
+=item C<bug>
+
+the bug object to which the attachment is attached
+
+=back
+
+=cut
+
+sub bug {
+    my $self = shift;
+
+    require Bugzilla::Bug;
+    $self->{bug} = Bugzilla::Bug->new($self->bug_id);
+    return $self->{bug};
+}
+
+=over
+
 =item C<description>
 
 user-provided text describing the attachment
@@ -430,6 +446,30 @@ sub flags {
     return $self->{flags};
 }
 
+=over
+
+=item C<flag_types>
+
+Return all flag types available for this attachment as well as flags
+already set, grouped by flag type.
+
+=back
+
+=cut
+
+sub flag_types {
+    my $self = shift;
+    return $self->{flag_types} if exists $self->{flag_types};
+
+    my $vars = { target_type  => 'attachment',
+                 product_id   => $self->bug->product_id,
+                 component_id => $self->bug->component_id,
+                 attach_id    => $self->id };
+
+    $self->{flag_types} = Bugzilla::Flag::_flag_types($vars);
+    return $self->{flag_types};
+}
+
 # Instance methods; no POD documentation here yet because the only ones so far
 # are private.
 
@@ -538,7 +578,7 @@ Returns:    a reference to an array of attachment objects.
 =cut
 
 sub get_attachments_by_bug {
-    my ($class, $bug_id) = @_;
+    my ($class, $bug_id, $vars) = @_;
     my $user = Bugzilla->user;
     my $dbh = Bugzilla->dbh;
 
@@ -556,6 +596,20 @@ sub get_attachments_by_bug {
                                                WHERE bug_id = ? $and_restriction",
                                                undef, @values);
     my $attachments = Bugzilla::Attachment->get_list($attach_ids);
+
+    # To avoid $attachment->flags to run SQL queries itself for each
+    # attachment listed here, we collect all the data at once and
+    # populate $attachment->{flags} ourselves.
+    if ($vars->{preload}) {
+        $_->{flags} = [] foreach @$attachments;
+        my %att = map { $_->id => $_ } @$attachments;
+
+        my $flags = Bugzilla::Flag->match({ bug_id      => $bug_id,
+                                            target_type => 'attachment' });
+
+        push(@{$att{$_->attach_id}->{flags}}, $_) foreach @$flags;
+        $attachments = [sort {$a->id <=> $b->id} values %att];
+    }
     return $attachments;
 }
 
index d625953a9ad3342ae895f441fdd627fed29b98f1..14f781c42f3c4db528e8dcbf18e1151cc4f4c7f4 100644 (file)
@@ -2314,7 +2314,7 @@ sub attachments {
     return [] if $self->{'error'};
 
     $self->{'attachments'} =
-        Bugzilla::Attachment->get_attachments_by_bug($self->bug_id);
+        Bugzilla::Attachment->get_attachments_by_bug($self->bug_id, {preload => 1});
     return $self->{'attachments'};
 }
 
@@ -2421,22 +2421,12 @@ sub flag_types {
     return $self->{'flag_types'} if exists $self->{'flag_types'};
     return [] if $self->{'error'};
 
-    # The types of flags that can be set on this bug.
-    # If none, no UI for setting flags will be displayed.
-    my $flag_types = Bugzilla::FlagType::match(
-        {'target_type'  => 'bug',
-         'product_id'   => $self->{'product_id'}, 
-         'component_id' => $self->{'component_id'} });
-
-    foreach my $flag_type (@$flag_types) {
-        $flag_type->{'flags'} = Bugzilla::Flag->match(
-            { 'bug_id'      => $self->bug_id,
-              'type_id'     => $flag_type->{'id'},
-              'target_type' => 'bug' });
-    }
-
-    $self->{'flag_types'} = $flag_types;
+    my $vars = { target_type  => 'bug',
+                 product_id   => $self->{product_id},
+                 component_id => $self->{component_id},
+                 bug_id       => $self->bug_id };
 
+    $self->{'flag_types'} = Bugzilla::Flag::_flag_types($vars);
     return $self->{'flag_types'};
 }
 
index 8201a907da660f7478a14381b71056f2762bcc41..ea3e940d868431fc2cb6ff58072b8ce2e9b2dd58 100644 (file)
@@ -1158,6 +1158,44 @@ sub CancelRequests {
                     \@old_summaries, \@new_summaries);
 }
 
+# This is an internal function used by $bug->flag_types
+# and $attachment->flag_types to collect data about available
+# flag types and existing flags set on them. You should never
+# call this function directly.
+sub _flag_types {
+    my $vars = shift;
+
+    my $target_type = $vars->{target_type};
+    my $flags;
+
+    # Retrieve all existing flags for this bug/attachment.
+    if ($target_type eq 'bug') {
+        my $bug_id = delete $vars->{bug_id};
+        $flags = Bugzilla::Flag->match({target_type => 'bug', bug_id => $bug_id});
+    }
+    elsif ($target_type eq 'attachment') {
+        my $attach_id = delete $vars->{attach_id};
+        $flags = Bugzilla::Flag->match({attach_id => $attach_id});
+    }
+    else {
+        ThrowCodeError('bad_arg', {argument => 'target_type',
+                                   function => 'Bugzilla::Flag::_flag_types'});
+    }
+
+    # Get all available flag types for the given product and component.
+    my $flag_types = Bugzilla::FlagType::match($vars);
+
+    $_->{flags} = [] foreach @$flag_types;
+    my %flagtypes = map { $_->id => $_ } @$flag_types;
+
+    # Group existing flags per type.
+    # Call the internal 'type_id' variable instead of the method
+    # to not create a flagtype object.
+    push(@{$flagtypes{$_->{type_id}}->{flags}}, $_) foreach @$flags;
+
+    return [sort {$a->sortkey <=> $b->sortkey || $a->name cmp $b->name} values %flagtypes];
+}
+
 =head1 SEE ALSO
 
 =over
index c28a300a09ff7f23bc07b024da14a8511b708a7c..4f3dabd55f761c255e9e9f38ebc9b2e4d72bc170 100755 (executable)
@@ -435,32 +435,14 @@ sub insert {
 # Validations are done later when the user submits changes.
 sub edit {
   my $attachment = validateID();
-  my $dbh = Bugzilla->dbh;
 
-  # Retrieve a list of attachments for this bug as well as a summary of the bug
-  # to use in a navigation bar across the top of the screen.
   my $bugattachments =
       Bugzilla::Attachment->get_attachments_by_bug($attachment->bug_id);
   # We only want attachment IDs.
   @$bugattachments = map { $_->id } @$bugattachments;
 
-  my ($bugsummary, $product_id, $component_id) =
-      $dbh->selectrow_array('SELECT short_desc, product_id, component_id
-                               FROM bugs
-                              WHERE bug_id = ?', undef, $attachment->bug_id);
-
-  # Get a list of flag types that can be set for this attachment.
-  my $flag_types = Bugzilla::FlagType::match({ 'target_type'  => 'attachment' ,
-                                               'product_id'   => $product_id ,
-                                               'component_id' => $component_id });
-  foreach my $flag_type (@$flag_types) {
-    $flag_type->{'flags'} = Bugzilla::Flag->match({ 'type_id'   => $flag_type->id,
-                                                    'attach_id' => $attachment->id });
-  }
-  $vars->{'flag_types'} = $flag_types;
-  $vars->{'any_flags_requesteeble'} = grep($_->is_requesteeble, @$flag_types);
+  $vars->{'any_flags_requesteeble'} = grep($_->is_requesteeble, @{$attachment->flag_types});
   $vars->{'attachment'} = $attachment;
-  $vars->{'bugsummary'} = $bugsummary; 
   $vars->{'attachments'} = $bugattachments;
 
   print $cgi->header();
index 49c28aa6499e8fb68a736358df33c46de773f599..8d0422065ae4b79cbac205c36e75a042decf9ae9 100644 (file)
@@ -29,7 +29,7 @@
   Attachment [% attachment.id %] Details for
   [%+ "$terms.Bug ${attachment.bug_id}" FILTER bug_link(attachment.bug_id) FILTER none %]
 [% END %]
-[% subheader = BLOCK %][% bugsummary FILTER html %][% END %]
+[% subheader = BLOCK %][% attachment.bug.short_desc FILTER html %][% END %]
 
 [% PROCESS global/header.html.tmpl
   title = title
           <br>
         </small>
 
-        [% IF flag_types.size > 0 %]
+        [% IF attachment.flag_types.size > 0 %]
           [% PROCESS "flag/list.html.tmpl" bug_id = attachment.bug_id
-                                           attach_id = attachment.id %]<br>
+                                           attach_id = attachment.id
+                                           flag_types = attachment.flag_types
+          %]<br>
         [% END %]
 
         <div id="smallCommentFrame">