summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Attachment.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Attachment.pm')
-rw-r--r--Bugzilla/Attachment.pm135
1 files changed, 92 insertions, 43 deletions
diff --git a/Bugzilla/Attachment.pm b/Bugzilla/Attachment.pm
index 69939a657..944337711 100644
--- a/Bugzilla/Attachment.pm
+++ b/Bugzilla/Attachment.pm
@@ -22,10 +22,11 @@
# Marc Schumann <wurblzap@gmail.com>
# Frédéric Buclin <LpSolit@gmail.com>
-use strict;
-
package Bugzilla::Attachment;
+use 5.10.0;
+use strict;
+
=head1 NAME
Bugzilla::Attachment - Bugzilla attachment class.
@@ -142,8 +143,7 @@ the ID of the bug to which the attachment is attached
=cut
sub bug_id {
- my $self = shift;
- return $self->{bug_id};
+ return $_[0]->{bug_id};
}
=over
@@ -157,11 +157,8 @@ the bug object to which the attachment is attached
=cut
sub bug {
- my $self = shift;
-
require Bugzilla::Bug;
- $self->{bug} ||= Bugzilla::Bug->new($self->bug_id);
- return $self->{bug};
+ return $_[0]->{bug} //= Bugzilla::Bug->new({ id => $_[0]->bug_id, cache => 1 });
}
=over
@@ -175,8 +172,7 @@ user-provided text describing the attachment
=cut
sub description {
- my $self = shift;
- return $self->{description};
+ return $_[0]->{description};
}
=over
@@ -190,8 +186,7 @@ the attachment's MIME media type
=cut
sub contenttype {
- my $self = shift;
- return $self->{mimetype};
+ return $_[0]->{mimetype};
}
=over
@@ -205,10 +200,8 @@ the user who attached the attachment
=cut
sub attacher {
- my $self = shift;
- return $self->{attacher} if exists $self->{attacher};
- $self->{attacher} = new Bugzilla::User($self->{submitter_id});
- return $self->{attacher};
+ return $_[0]->{attacher}
+ //= new Bugzilla::User({ id => $_[0]->{submitter_id}, cache => 1 });
}
=over
@@ -222,8 +215,7 @@ the date and time on which the attacher attached the attachment
=cut
sub attached {
- my $self = shift;
- return $self->{creation_ts};
+ return $_[0]->{creation_ts};
}
=over
@@ -237,8 +229,7 @@ the date and time on which the attachment was last modified.
=cut
sub modification_time {
- my $self = shift;
- return $self->{modification_time};
+ return $_[0]->{modification_time};
}
=over
@@ -252,8 +243,7 @@ the name of the file the attacher attached
=cut
sub filename {
- my $self = shift;
- return $self->{filename};
+ return $_[0]->{filename};
}
=over
@@ -267,8 +257,7 @@ whether or not the attachment is a patch
=cut
sub ispatch {
- my $self = shift;
- return $self->{ispatch};
+ return $_[0]->{ispatch};
}
=over
@@ -282,8 +271,7 @@ whether or not the attachment is obsolete
=cut
sub isobsolete {
- my $self = shift;
- return $self->{isobsolete};
+ return $_[0]->{isobsolete};
}
=over
@@ -297,8 +285,7 @@ whether or not the attachment is private
=cut
sub isprivate {
- my $self = shift;
- return $self->{isprivate};
+ return $_[0]->{isprivate};
}
=over
@@ -315,8 +302,7 @@ matches, because this will return a value even if it's matched by the generic
=cut
sub is_viewable {
- my $self = shift;
- my $contenttype = $self->contenttype;
+ my $contenttype = $_[0]->contenttype;
my $cgi = Bugzilla->cgi;
# We assume we can view all text and image types.
@@ -390,7 +376,7 @@ the length (in characters) of the attachment content
sub datasize {
my $self = shift;
- return $self->{datasize} if exists $self->{datasize};
+ return $self->{datasize} if defined $self->{datasize};
# If we have already retrieved the data, return its size.
return length($self->{data}) if exists $self->{data};
@@ -415,6 +401,53 @@ sub datasize {
return $self->{datasize};
}
+=over
+
+=item C<linecount>
+
+the number of lines of the attachment content
+
+=back
+
+=cut
+
+# linecount allows for getting the number of lines of an attachment
+# from the database directly if the data has not yet been loaded for
+# performance reasons.
+
+sub linecount {
+ my ($self) = @_;
+
+ return $self->{linecount} if exists $self->{linecount};
+
+ # Limit this to just text/* attachments as this could
+ # cause strange results for binary attachments.
+ return if $self->contenttype !~ /^text\//;
+
+ # If the data has already been loaded, we can just determine
+ # line count from the data directly.
+ if ($self->{data}) {
+ $self->{linecount} = $self->{data} =~ tr/\n/\n/;
+ }
+ else {
+ $self->{linecount} =
+ int(Bugzilla->dbh->selectrow_array("
+ SELECT LENGTH(attach_data.thedata)-LENGTH(REPLACE(attach_data.thedata,'\n',''))/LENGTH('\n')
+ FROM attach_data WHERE id = ?", undef, $self->id));
+
+ }
+
+ # If we still do not have a linecount either the attachment
+ # is stored in a local file or has been deleted. If the former,
+ # we call self->data to force a load from the filesystem and
+ # then do a split on newlines and count again.
+ unless ($self->{linecount}) {
+ $self->{linecount} = $self->data =~ tr/\n/\n/;
+ }
+
+ return $self->{linecount};
+}
+
sub _get_local_filename {
my $self = shift;
my $hash = ($self->id % 100) + 100;
@@ -433,11 +466,8 @@ flags that have been set on the attachment
=cut
sub flags {
- my $self = shift;
-
# Don't cache it as it must be in sync with ->flag_types.
- $self->{flags} = [map { @{$_->{flags}} } @{$self->flag_types}];
- return $self->{flags};
+ return $_[0]->{flags} = [map { @{$_->{flags}} } @{$_[0]->flag_types}];
}
=over
@@ -458,10 +488,10 @@ sub flag_types {
my $vars = { target_type => 'attachment',
product_id => $self->bug->product_id,
component_id => $self->bug->component_id,
- attach_id => $self->id };
+ attach_id => $self->id,
+ active_or_has_flags => $self->bug_id };
- $self->{flag_types} = Bugzilla::Flag->_flag_types($vars);
- return $self->{flag_types};
+ return $self->{flag_types} = Bugzilla::Flag->_flag_types($vars);
}
###############################
@@ -573,7 +603,7 @@ sub _check_filename {
else {
ThrowUserError('file_not_specified');
}
- }
+ }
# Remove path info (if any) from the file name. The browser should do this
# for us, but some are buggy. This may not work on Mac file names and could
@@ -656,6 +686,24 @@ sub get_attachments_by_bug {
push(@{$att{$_->attach_id}->{flags}}, $_) foreach @$flags;
$attachments = [sort {$a->id <=> $b->id} values %att];
+
+ # Preload attachers.
+ my %user_ids = map { $_->{submitter_id} => 1 } @$attachments;
+ my $users = Bugzilla::User->new_from_list([keys %user_ids]);
+ my %user_map = map { $_->id => $_ } @$users;
+ foreach my $attachment (@$attachments) {
+ $attachment->{attacher} = $user_map{$attachment->{submitter_id}};
+ }
+
+ # Preload datasizes.
+ my $sizes =
+ $dbh->selectall_hashref('SELECT attach_id, LENGTH(thedata) AS datasize
+ FROM attachments LEFT JOIN attach_data ON attach_id = id
+ WHERE bug_id = ?',
+ 'attach_id', undef, $bug_id);
+
+ # Force the size of attachments not in the DB to be recalculated.
+ $_->{datasize} = $sizes->{$_->id}->{datasize} || undef foreach @$attachments;
}
return $attachments;
}
@@ -865,10 +913,11 @@ sub update {
}
if (scalar(keys %$changes)) {
- $dbh->do('UPDATE attachments SET modification_time = ? WHERE attach_id = ?',
- undef, ($timestamp, $self->id));
- $dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
- undef, ($timestamp, $self->bug_id));
+ $dbh->do('UPDATE attachments SET modification_time = ? WHERE attach_id = ?',
+ undef, ($timestamp, $self->id));
+ $dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
+ undef, ($timestamp, $self->bug_id));
+ $self->{modification_time} = $timestamp;
}
return $changes;