@@ -, +, @@ --- C4/Images.pm | 49 +++++++++++++++---- catalogue/detail.pl | 14 ++++++ catalogue/imageviewer.pl | 24 +++++++-- .../prog/en/modules/catalogue/detail.tt | 23 ++++++++- .../prog/en/modules/catalogue/imageviewer.tt | 2 +- .../prog/en/modules/tools/upload-images.tt | 34 ++++++++----- svc/cover_images | 13 +++-- tools/upload-cover-image.pl | 33 +++++++++---- 8 files changed, 145 insertions(+), 47 deletions(-) --- a/C4/Images.pm +++ a/C4/Images.pm @@ -18,12 +18,11 @@ package C4::Images; # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -use warnings; -use 5.010; +use Modern::Perl; use C4::Context; use GD; +use Koha::Exceptions; use vars qw($debug $noimage @ISA @EXPORT); @@ -47,18 +46,32 @@ BEGIN { =head2 PutImage - PutImage($biblionumber, $srcimage, $replace); + PutImage({ biblionumber => $biblionumber, itemnumber => $itemnumber, src_image => $srcimage, replace => $replace }); -Stores binary image data and thumbnail in database, optionally replacing existing images for the given biblio. +Stores binary image data and thumbnail in database, optionally replacing existing images for the given biblio or item. =cut sub PutImage { - my ( $biblionumber, $srcimage, $replace ) = @_; + my ( $params ) = @_; + + my $biblionumber = $params->{biblionumber}; + my $itemnumber = $params->{itemnumber}; + my $srcimage = $params->{src_image}; + my $replace = $params->{replace}; + + Koha::Exceptions::WrongParameter->throw( + 'PutImage cannot be called with both biblionumber and itemnumber') + if $biblionumber and $itemnumber; + + Koha::Exceptions::WrongParameter->throw( + 'PutImage must be called with "replace" if itemnumber is passed. Only 1 cover per item is allowed.') + if $itemnumber and not $replace; + return -1 unless defined($srcimage); - if ($replace) { + if ($biblionumber && $replace) { foreach ( ListImagesForBiblio($biblionumber) ) { DelImage($_); } @@ -66,7 +79,7 @@ sub PutImage { my $dbh = C4::Context->dbh; my $query = -"INSERT INTO biblioimages (biblionumber, mimetype, imagefile, thumbnail) VALUES (?,?,?,?);"; +"INSERT INTO biblioimages (biblionumber, itemnumber, mimetype, imagefile, thumbnail) VALUES (?,?,?,?,?);"; my $sth = $dbh->prepare($query); my $mimetype = 'image/png' @@ -79,10 +92,10 @@ sub PutImage { ; # MAX pixel dims are 600 X 800 for full-size image... $debug and warn "thumbnail is " . length($thumbnail) . " bytes."; - $sth->execute( $biblionumber, $mimetype, $fullsize->png(), + $sth->execute( $biblionumber, $itemnumber, $mimetype, $fullsize->png(), $thumbnail->png() ); my $dberror = $sth->errstr; - warn "Error returned inserting $biblionumber.$mimetype." if $sth->errstr; + warn sprintf("Error returned inserting %s.%s.", ($biblionumber || $itemnumber, $mimetype)) if $sth->errstr; undef $thumbnail; undef $fullsize; return $dberror; @@ -135,6 +148,22 @@ sub ListImagesForBiblio { return @imagenumbers; } +=head2 GetImageForItem + my $image = GetImageForItem($itemnumber); + +Gets the image associated with a particular item. + +=cut + +sub GetImageForItem { + my ($itemnumber) = @_; + + my $dbh = C4::Context->dbh; + return $dbh->selectrow_array( + 'SELECT imagenumber FROM biblioimages WHERE itemnumber = ?', + undef, $itemnumber ); +} + =head2 DelImage my ($dberror) = DelImage($imagenumber); --- a/catalogue/detail.pl +++ a/catalogue/detail.pl @@ -322,6 +322,7 @@ if ($currentbranch and C4::Context->preference('SeparateHoldings')) { $template->param(SeparateHoldings => 1); } my $separatebranch = C4::Context->preference('SeparateHoldingsBranch') || 'homebranch'; +my ( $itemloop_has_images, $otheritemloop_has_images ); foreach my $item (@items) { my $itembranchcode = $item->{$separatebranch}; @@ -406,17 +407,30 @@ foreach my $item (@items) { } } + if ( C4::Context->preference("LocalCoverImages") == 1 ) { + $item->{imagenumber} = + C4::Images::GetImageForItem( $item->{itemnumber} ); + } + if ($currentbranch and C4::Context->preference('SeparateHoldings')) { if ($itembranchcode and $itembranchcode eq $currentbranch) { push @itemloop, $item; + $itemloop_has_images++ if $item->{imagenumber}; } else { push @otheritemloop, $item; + $otheritemloop_has_images++ if $item->{imagenumber}; } } else { push @itemloop, $item; + $itemloop_has_images++ if $item->{imagenumber}; } } +$template->param( + itemloop_has_images => $itemloop_has_images, + otheritemloop_has_images => $otheritemloop_has_images, +); + # Display only one tab if one items list is empty if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) { $template->param(SeparateHoldings => 0); --- a/catalogue/imageviewer.pl +++ a/catalogue/imageviewer.pl @@ -28,6 +28,7 @@ use C4::Images; use C4::Search; use Koha::Biblios; +use Koha::Items; use Koha::Patrons; my $query = new CGI; @@ -40,7 +41,8 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( } ); -my $biblionumber = $query->param('biblionumber') || $query->param('bib'); +my $itemnumber = $query->param('itemnumber'); +my $biblionumber = $query->param('biblionumber') || $query->param('bib') || Koha::Items->find($itemnumber)->biblionumber; my $imagenumber = $query->param('imagenumber'); my $biblio = Koha::Biblios->find( $biblionumber ); my $itemcount = $biblio ? $biblio->items->count : 0; @@ -65,10 +67,22 @@ if( $query->cookie("searchToOrder") ){ } if ( C4::Context->preference("LocalCoverImages") ) { - my @images = ListImagesForBiblio($biblionumber); - $template->{VARS}->{'LocalCoverImages'} = 1; - $template->{VARS}->{'images'} = \@images; - $template->{VARS}->{'imagenumber'} = $imagenumber || $images[0] || ''; + if ( $itemnumber ) { + my $image = C4::Images::GetImageForItem($itemnumber); + $template->param( + LocalCoverImages => 1, + images => [$image], + imagenumber => $imagenumber, + ); + + } else { + my @images = ListImagesForBiblio($biblionumber); + $template->param( + LocalCoverImages => 1, + images => \@images, + imagenumber => $imagenumber || $images[0] || '', + ); + } } $template->{VARS}->{'count'} = $itemcount; $template->{VARS}->{'biblionumber'} = $biblionumber; --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -285,6 +285,9 @@ [% IF (StaffDetailItemSelection) %][% END %] + [% IF ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %] + Cover image + [% END %] [% IF ( item_level_itypes ) %]Item type[% END %] Current library Home library @@ -323,6 +326,16 @@ [% END %] + [% IF ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %] + + [% IF item.imagenumber %] + + + + [% END %] + + [% END %] + [% IF ( item_level_itypes ) %] [% IF !noItemTypeImages && item.imageurl %] @@ -533,7 +546,12 @@ Note that permanent location is a code, and location may be an authval. [% IF CAN_user_editcatalogue_edit_items %] [% UNLESS item.cannot_be_edited %] - Edit +
+ Edit + +
[% END %] [% END %] @@ -541,6 +559,7 @@ Note that permanent location is a code, and location may be an authval. [% END %] + [% END %][%# end of block items_table %]
@@ -1054,7 +1073,7 @@ Note that permanent location is a code, and location may be an authval. thumbnail.find("img").css("opacity", ".2"); thumbnail.find("a.remove").html(""); $.ajax({ - url: "/cgi-bin/koha/svc/cover_images?action=delete&biblionumber=" + biblionumber + "&imagenumber=" + imagenumber, + url: "/cgi-bin/koha/svc/cover_images?action=delete&imagenumber=" + imagenumber, success: function(data) { $(data).each( function(i) { if ( this.deleted == 1 ) { --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt @@ -133,7 +133,7 @@ thumbnail.find("a.remove").html(""); $.ajax({ - url: "/cgi-bin/koha/svc/cover_images?action=delete&biblionumber=" + biblionumber + "&imagenumber=" + imagenumber, + url: "/cgi-bin/koha/svc/cover_images?action=delete&imagenumber=" + imagenumber, success: function(data) { $(data).each( function() { if ( this.deleted == 1 ) { --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt @@ -77,24 +77,34 @@
File type
    -
  1. - [% IF (filetype != 'image' ) %][% ELSE %][% END %] - -
  2. -
  3. - [% IF (filetype == 'image' ) %][% ELSE %][% END %] - -
  4. -
  5. - [% IF ( filetype == 'image' ) %][% ELSE %] -
  6. + [% UNLESS itemnumber %] +
  7. + [% IF (filetype != 'image' ) %][% ELSE %][% END %] + +
  8. +
  9. + [% IF (filetype == 'image' ) %][% ELSE %][% END %] + +
  10. +
  11. + [% IF ( filetype == 'image' ) %][% ELSE %] +
  12. + [% ELSE %] + + + + [% END %]
Options
  1. - [% IF AllowMultipleCovers == 0 %][% ELSE %][% END %] + [% IF AllowMultipleCovers == 0 OR itemnumber%] + + [% ELSE %] + + [% END %]
--- a/svc/cover_images +++ a/svc/cover_images @@ -37,28 +37,27 @@ if ( $auth_status ne "ok" ) { } my $action = $input->param('action'); -my $biblionumber = $input->param('biblionumber'); my @imagenumbers = $input->param('imagenumber'); # Array to store the reponse JSON my $response = []; if ( $action eq "delete" ) { - # Build a hash of valid imagenumbers fr the given biblionumber - my %valid_imagenumbers = map {$_ => 1} ListImagesForBiblio($biblionumber); foreach my $imagenumber ( @imagenumbers ) { - if ( exists( $valid_imagenumbers{ $imagenumber } ) ) { + eval { DelImage($imagenumber); + }; + if ( $@ ) { push @$response, { imagenumber => $imagenumber, - deleted => 1 + deleted => 0, + error => "MSG_INVALID_IMAGENUMBER" }; } else { push @$response, { imagenumber => $imagenumber, - deleted => 0, - error => "MSG_INVALID_IMAGENUMBER" + deleted => 1 }; } } --- a/tools/upload-cover-image.pl +++ a/tools/upload-cover-image.pl @@ -46,6 +46,7 @@ use C4::Context; use C4::Auth; use C4::Output; use C4::Images; +use Koha::Items; use Koha::UploadedFiles; use C4::Log; @@ -66,6 +67,7 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( my $filetype = $input->param('filetype'); my $biblionumber = $input->param('biblionumber'); +my $itemnumber = $input->param('itemnumber'); #my $uploadfilename = $input->param('uploadfile'); # obsolete? my $replace = !C4::Context->preference("AllowMultipleCovers") || $input->param('replace'); @@ -75,8 +77,11 @@ my $sessionID = $cookies{'CGISESSID'}->value; my $error; -$template->{VARS}->{'filetype'} = $filetype; -$template->{VARS}->{'biblionumber'} = $biblionumber; +$template->param( + filetype => $filetype, + biblionumber => $biblionumber, + itemnumber => $itemnumber, +); my $total = 0; @@ -87,7 +92,7 @@ if ($fileID) { my $srcimage = GD::Image->new($fh); $fh->close if $fh; if ( defined $srcimage ) { - my $dberror = PutImage( $biblionumber, $srcimage, $replace ); + my $dberror = PutImage( { biblionumber => $biblionumber, itemnumber => $itemnumber, src_image => $srcimage, replace => $replace } ); if ($dberror) { $error = 'DBERR'; } @@ -157,9 +162,13 @@ if ($fileID) { my $srcimage = GD::Image->new("$dir/$filename"); if ( defined $srcimage ) { $total++; - my $dberror = - PutImage( $biblionumber, $srcimage, - $replace ); + my $dberror = PutImage( + { + biblionumber => $biblionumber, + src_image => $srcimage, + replace => $replace + } + ); if ($dberror) { $error = 'DBERR'; } @@ -178,10 +187,14 @@ if ($fileID) { } } } - $template->{VARS}->{'total'} = $total; - $template->{VARS}->{'uploadimage'} = 1; - $template->{VARS}->{'error'} = $error; - $template->{VARS}->{'biblionumber'} = $biblionumber; + + $template->param( + total => $total, + uploadimage => 1, + error => $error, + biblionumber => $biblionumber || Koha::Items->find($itemnumber)->biblionumber, + itemnumber => $itemnumber, + ); } output_html_with_http_headers $input, $cookie, $template->output; --