diff options
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 59 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Photo.pm | 70 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/New.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Model/PhotoSet.pm | 29 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Comment.pm | 38 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Problem.pm | 47 |
7 files changed, 136 insertions, 111 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 0fc87c2f6..686d23aa1 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -683,7 +683,7 @@ sub report_edit : Path('report_edit') : Args(1) { } if (my $rotate_photo_param = $self->_get_rotate_photo_param($c)) { - $self->rotate_photo($c, @$rotate_photo_param); + $self->rotate_photo($c, $problem, @$rotate_photo_param); if ( $c->cobrand->moniker eq 'zurich' ) { # Clicking the photo rotation buttons should do nothing # except for rotating the photo, so return the user @@ -790,11 +790,12 @@ sub report_edit : Path('report_edit') : Args(1) { } # Deal with photos - if ( $c->get_param('remove_photo') ) { - $problem->photo(undef); + my $remove_photo_param = $self->_get_remove_photo_param($c); + if ($remove_photo_param) { + $self->remove_photo($c, $problem, $remove_photo_param); } - if ( $c->get_param('remove_photo') || $new_state eq 'hidden' ) { + if ( $remove_photo_param || $new_state eq 'hidden' ) { unlink glob FixMyStreet->path_to( 'web', 'photo', $problem->id . '.*' ); } @@ -974,6 +975,11 @@ sub update_edit : Path('update_edit') : Args(1) { $c->stash->{update} = $update; + if (my $rotate_photo_param = $self->_get_rotate_photo_param($c)) { + $self->rotate_photo($c, $update, @$rotate_photo_param); + return 1; + } + $c->forward('check_email_for_abuse', [ $update->user->email ] ); if ( $c->get_param('banuser') ) { @@ -1003,13 +1009,14 @@ sub update_edit : Path('update_edit') : Args(1) { || $c->get_param('anonymous') ne $update->anonymous || $c->get_param('text') ne $update->text ) { $edited = 1; - } + } - if ( $c->get_param('remove_photo') ) { - $update->photo(undef); + my $remove_photo_param = $self->_get_remove_photo_param($c); + if ($remove_photo_param) { + $self->remove_photo($c, $update, $remove_photo_param); } - if ( $c->get_param('remove_photo') || $new_state eq 'hidden' ) { + if ( $remove_photo_param || $new_state eq 'hidden' ) { unlink glob FixMyStreet->path_to( 'web', 'photo', 'c', $update->id . '.*' ); } @@ -1488,22 +1495,48 @@ sub _get_rotate_photo_param { my $key = first { /^rotate_photo/ } keys %{ $c->req->params } or return; my ($index) = $key =~ /(\d+)$/; my $direction = $c->get_param($key); - return [ $index || 0, $key, $direction ]; + return [ $index || 0, $direction ]; } sub rotate_photo : Private { - my ( $self, $c, $index, $key, $direction ) = @_; + my ( $self, $c, $object, $index, $direction ) = @_; return unless $direction eq _('Rotate Left') or $direction eq _('Rotate Right'); - my $problem = $c->stash->{problem}; - my $fileid = $problem->get_photoset($c)->rotate_image( + my $fileid = $object->get_photoset->rotate_image( $index, $direction eq _('Rotate Left') ? -90 : 90 ) or return; - $problem->update({ photo => $fileid }); + $object->update({ photo => $fileid }); + + return 1; +} + +=head2 remove_photo + +Remove a photo from a report +=cut + +# Returns index of photo(s) to remove, if any +sub _get_remove_photo_param { + my ($self, $c) = @_; + + return 'ALL' if $c->get_param('remove_photo'); + + my @keys = map { /(\d+)$/ } grep { /^remove_photo_/ } keys %{ $c->req->params } or return; + return \@keys; +} + +sub remove_photo : Private { + my ($self, $c, $object, $keys) = @_; + if ($keys eq 'ALL') { + $object->photo(undef); + } else { + my $fileids = $object->get_photoset->remove_images($keys); + $object->photo($fileids); + } return 1; } diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm index f4866cc26..df4cab2d8 100644 --- a/perllib/FixMyStreet/App/Controller/Photo.pm +++ b/perllib/FixMyStreet/App/Controller/Photo.pm @@ -4,11 +4,9 @@ use namespace::autoclean; BEGIN {extends 'Catalyst::Controller'; } -use DateTime::Format::HTTP; -use Digest::SHA qw(sha1_hex); +use JSON; use File::Path; use File::Slurp; -use Path::Class; use FixMyStreet::App::Model::PhotoSet; use if !$ENV{TRAVIS}, 'Image::Magick'; @@ -35,16 +33,12 @@ sub during :LocalRegex('^([0-9a-f]{40})\.(temp|fulltemp)\.jpeg$') { my ( $self, $c ) = @_; my ( $hash, $size ) = @{ $c->req->captures }; - my $file = file( $c->config->{UPLOAD_DIR}, "$hash.jpeg" ); - my $photo = $file->slurp; + my $photoset = FixMyStreet::App::Model::PhotoSet->new({ + data_items => [ $hash ] + }); - if ( $size eq 'temp' ) { - if ( $c->cobrand->default_photo_resize ) { - $photo = _shrink( $photo, $c->cobrand->default_photo_resize ); - } else { - $photo = _shrink( $photo, '250x250' ); - } - } + $size = $size eq 'temp' ? 'default' : 'full'; + my $photo = $photoset->get_image_data(size => $size, default => $c->cobrand->default_photo_resize); $c->forward( 'output', [ $photo ] ); } @@ -73,29 +67,9 @@ sub index :LocalRegex('^(c/)?(\d+)(?:\.(\d+))?(?:\.(full|tn|fp))?\.jpeg$') { $c->detach( 'no_photo' ) unless $c->cobrand->allow_photo_display($item); # Should only be for reports, not updates my $photo; - if ($item->can('get_photoset')) { - $photo = $item->get_photoset( $c ) - ->get_image_data( num => $photo_number, size => $size ) + $photo = $item->get_photoset + ->get_image_data( num => $photo_number, size => $size, default => $c->cobrand->default_photo_resize ) or $c->detach( 'no_photo' ); - } else { - $photo = $item->photo; - # If photo field contains a hash - if (length($photo) == 40) { - my $file = file( $c->config->{UPLOAD_DIR}, "$photo.jpeg" ); - $photo = $file->slurp; - } - - if ( $size eq 'tn' ) { - $photo = _shrink( $photo, 'x100' ); - } elsif ( $size eq 'fp' ) { - $photo = _crop( $photo ); - } elsif ( $size eq 'full' ) { - } elsif ( $c->cobrand->default_photo_resize ) { - $photo = _shrink( $photo, $c->cobrand->default_photo_resize ); - } else { - $photo = _shrink( $photo, '250x250' ); - } - } $c->forward( 'output', [ $photo ] ); } @@ -116,34 +90,6 @@ sub no_photo : Private { $c->detach( '/page_error_404_not_found', [ 'No photo' ] ); } -# Shrinks a picture to the specified size, but keeping in proportion. -sub _shrink { - my ($photo, $size) = @_; - my $image = Image::Magick->new; - $image->BlobToImage($photo); - my $err = $image->Scale(geometry => "$size>"); - throw Error::Simple("resize failed: $err") if "$err"; - $image->Strip(); - my @blobs = $image->ImageToBlob(); - undef $image; - return $blobs[0]; -} - -# Shrinks a picture to 90x60, cropping so that it is exactly that. -sub _crop { - my ($photo) = @_; - my $image = Image::Magick->new; - $image->BlobToImage($photo); - my $err = $image->Resize( geometry => "90x60^" ); - throw Error::Simple("resize failed: $err") if "$err"; - $err = $image->Extent( geometry => '90x60', gravity => 'Center' ); - throw Error::Simple("resize failed: $err") if "$err"; - $image->Strip(); - my @blobs = $image->ImageToBlob(); - undef $image; - return $blobs[0]; -} - sub upload : Local { my ( $self, $c ) = @_; my @items = ( diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index 4632f450d..db524ada4 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -449,7 +449,7 @@ sub initialize_report : Private { $c->stash->{partial_token} = $token if $report; # Stash the photo IDs for "already got" display - $c->stash->{upload_fileid} = $report->get_photoset($c)->data; + $c->stash->{upload_fileid} = $report->get_photoset->data; } else { # no point keeping it if it is done. diff --git a/perllib/FixMyStreet/App/Model/PhotoSet.pm b/perllib/FixMyStreet/App/Model/PhotoSet.pm index e8396b5aa..35a7e8a53 100644 --- a/perllib/FixMyStreet/App/Model/PhotoSet.pm +++ b/perllib/FixMyStreet/App/Model/PhotoSet.pm @@ -222,7 +222,7 @@ sub get_image_data { } elsif ( $size eq 'full' ) { # do nothing } else { - $photo = _shrink( $photo, $self->c->cobrand->default_photo_resize || '250x250' ); + $photo = _shrink( $photo, $args{default} || '250x250' ); } return $photo; @@ -239,6 +239,27 @@ sub delete_cached { ); } +sub remove_images { + my ($self, $ids) = @_; + + my @images = $self->all_images; + my $dec = 0; + for (sort { $a <=> $b } @$ids) { + splice(@images, $_ + $dec, 1); + --$dec; + } + my @items = map $_->[0], @images; + + my $new_set = (ref $self)->new({ + data_items => \@items, + object => $self->object, + }); + + $self->delete_cached(); + + return $new_set->data; # e.g. new comma-separated fileid +} + sub rotate_image { my ($self, $index, $direction) = @_; @@ -250,7 +271,6 @@ sub rotate_image { my $new_set = (ref $self)->new({ data_items => \@items, - c => $self->c, object => $self->object, }); @@ -272,11 +292,6 @@ sub _rotate_image { } - - - -# NB: These 2 subs stolen from A::C::Photo, should be purged from there! -# # Shrinks a picture to the specified size, but keeping in proportion. sub _shrink { my ($photo, $size) = @_; diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index b7c9e9f45..ea4eda8c4 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -1172,7 +1172,7 @@ sub admin_stats { $public_response =~ s{\r?\n}{ <br/> }g if $public_response; # Assemble photo URL, if report has a photo - my $media_url = $report->get_photo_params->{url} ? ($c->cobrand->base_url . $report->get_photo_params->{url}) : ''; + my $media_url = @{$report->photos} ? ($c->cobrand->base_url . $report->photos->[0]->{url}) : ''; my @columns = ( $report->id, diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm index 41e8cf315..3ae56591f 100644 --- a/perllib/FixMyStreet/DB/Result/Comment.pm +++ b/perllib/FixMyStreet/DB/Result/Comment.pm @@ -97,7 +97,6 @@ __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); use Moo; -use Utils::Photo; use namespace::clean -except => [ 'meta' ]; with 'FixMyStreet::Roles::Abuser'; @@ -148,15 +147,44 @@ sub confirm { $self->confirmed( \'current_timestamp' ); } -=head2 get_photo_params +=head2 get_photoset -Returns a hashref of details of any attached photo for use in templates. +Return a PhotoSet object for all photos attached to this field + + my $photoset = $obj->get_photoset; + print $photoset->num_images; + return $photoset->get_image_data(num => 0, size => 'full'); =cut -sub get_photo_params { +sub get_photoset { + my ($self) = @_; + my $class = 'FixMyStreet::App::Model::PhotoSet'; + eval "use $class"; + return $class->new({ + db_data => $self->photo, + object => $self, + }); +} + +sub photos { my $self = shift; - return Utils::Photo::get_photo_params($self, 'c'); + my $photoset = $self->get_photoset; + my $i = 0; + my $id = $self->id; + my @photos = map { + my $format = 'jpeg'; + my $cachebust = substr($_, 0, 8); + { + id => $_, + url_temp => "/photo/$_.temp.$format", + url_temp_full => "/photo/$_.fulltemp.$format", + url => "/photo/c/$id.$i.$format?$cachebust", + url_full => "/photo/c/$id.$i.full.$format?$cachebust", + idx => $i++, + } + } map { $_->[0] } $photoset->all_images; + return \@photos; } =head2 meta_problem_state diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index 237785820..8f9e76ad6 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -160,7 +160,6 @@ __PACKAGE__->rabx_column('geocode'); use Moo; use namespace::clean -except => [ 'meta' ]; use Utils; -use Utils::Photo; with 'FixMyStreet::Roles::Abuser', 'FixMyStreet::Roles::Extra'; @@ -483,23 +482,6 @@ sub admin_url { return $cobrand->admin_base_url . '/report_edit/' . $self->id; } -=head2 get_photo_params - -Returns a hashref of details of the attached photo, if any, for use in templates. - -NB: this method doesn't currently support multiple photos gracefully. - -Use get_photoset($c) instead to do the right thing with reports with 0, 1, or more photos. - -=cut - -sub get_photo_params { - # use Carp 'cluck'; - # cluck "get_photo_params called"; # TEMPORARY die to make sure I've done right thing with Zurich templates - my $self = shift; - return Utils::Photo::get_photo_params($self, 'id'); -} - =head2 is_open Returns 1 if the problem is in a open state otherwise 0. @@ -836,7 +818,7 @@ sub as_hashref { state_t => _( $self->state ), used_map => $self->used_map, is_fixed => $self->fixed_states->{ $self->state } ? 1 : 0, - photo => $self->get_photo_params, + photos => [ map { $_->{url} } @{$self->photos} ], meta => $self->confirmed ? $self->meta_line( $c ) : '', confirmed_pp => $self->confirmed ? $c->cobrand->prettify_dt( $self->confirmed ): '', created_pp => $c->cobrand->prettify_dt( $self->created ), @@ -858,23 +840,44 @@ sub latest_moderation_log_entry { Return a PhotoSet object for all photos attached to this field - my $photoset = $obj->get_photoset( $c ); + my $photoset = $obj->get_photoset; print $photoset->num_images; return $photoset->get_image_data(num => 0, size => 'full'); =cut sub get_photoset { - my ($self, $c) = @_; + my ($self) = @_; my $class = 'FixMyStreet::App::Model::PhotoSet'; eval "use $class"; return $class->new({ - c => $c, db_data => $self->photo, object => $self, }); } +sub photos { + my $self = shift; + my $photoset = $self->get_photoset; + my $i = 0; + my $id = $self->id; + my @photos = map { + my $format = 'jpeg'; + my $cachebust = substr($_, 0, 8); + { + id => $_, + url_temp => "/photo/$_.temp.$format", + url_temp_full => "/photo/$_.fulltemp.$format", + url => "/photo/$id.$i.$format?$cachebust", + url_full => "/photo/$id.$i.full.$format?$cachebust", + url_tn => "/photo/$id.$i.tn.$format?$cachebust", + url_fp => "/photo/$id.$i.fp.$format?$cachebust", + idx => $i++, + } + } map { $_->[0] } $photoset->all_images; + return \@photos; +} + __PACKAGE__->has_many( "admin_log_entries", "FixMyStreet::DB::Result::AdminLog", |