diff options
Diffstat (limited to 'Bugzilla/Attachment.pm')
-rw-r--r-- | Bugzilla/Attachment.pm | 135 |
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; |