Bug 26145: Refactoring - Move C4::Images to Koha::CoverImages
authorJonathan Druart <jonathan.druart@bugs.koha-community.org>
Wed, 5 Aug 2020 14:27:14 +0000 (16:27 +0200)
committerJonathan Druart <jonathan.druart@bugs.koha-community.org>
Mon, 12 Oct 2020 09:28:41 +0000 (11:28 +0200)
Sponsored-by: Gerhard Sondermann Dialog e.K. (presseplus.de, presseshop.at, presseshop.ch)
Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
20 files changed:
C4/Images.pm [deleted file]
Koha/Biblio.pm
Koha/CoverImage.pm [new file with mode: 0644]
Koha/CoverImages.pm [new file with mode: 0644]
Koha/Item.pm
catalogue/detail.pl
catalogue/image.pl
catalogue/imageviewer.pl
installer/data/mysql/kohastructure.sql
koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt
koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-detail.tt
koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-imageviewer.tt
opac/opac-detail.pl
opac/opac-image.pl
opac/opac-imageviewer.pl
svc/cover_images
t/Images.t [deleted file]
t/db_dependent/Koha/CoverImages.t
tools/upload-cover-image.pl

diff --git a/C4/Images.pm b/C4/Images.pm
deleted file mode 100644 (file)
index a5c6258..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-package C4::Images;
-
-# Copyright (C) 2011 C & P Bibliography Services
-# Jared Camins-Esakov <jcamins@cpbibliograpy.com>
-#
-# This file is part of Koha.
-#
-# Koha is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# Koha is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Koha; if not, see <http://www.gnu.org/licenses>.
-
-use Modern::Perl;
-
-use C4::Context;
-use GD;
-use Koha::Exceptions;
-
-use vars qw($debug $noimage @ISA @EXPORT);
-
-BEGIN {
-
-    require Exporter;
-    @ISA    = qw(Exporter);
-    @EXPORT = qw(
-      &PutImage
-      &RetrieveImage
-      &ListImagesForBiblio
-      &DelImage
-    );
-    $debug = $ENV{KOHA_DEBUG} || $ENV{DEBUG} || 0;
-
-    $noimage = pack( "H*",
-            '47494638396101000100800000FFFFFF'
-          . '00000021F90401000000002C00000000'
-          . '010001000002024401003B' );
-}
-
-=head2 PutImage
-
-    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 or item.
-
-=cut
-
-sub PutImage {
-    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 ($biblionumber && $replace) {
-        foreach ( ListImagesForBiblio($biblionumber) ) {
-            DelImage($_);
-        }
-    }
-
-    my $dbh = C4::Context->dbh;
-    my $query =
-"INSERT INTO biblioimages (biblionumber, itemnumber, mimetype, imagefile, thumbnail) VALUES (?,?,?,?,?);";
-    my $sth = $dbh->prepare($query);
-
-    my $mimetype = 'image/png'
-      ; # GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to PNG which is lossless...
-
-    # Check the pixel size of the image we are about to import...
-    my $thumbnail = _scale_image( $srcimage, 140, 200 )
-      ;    # MAX pixel dims are 140 X 200 for thumbnail...
-    my $fullsize = _scale_image( $srcimage, 600, 800 )
-      ;    # MAX pixel dims are 600 X 800 for full-size image...
-    $debug and warn "thumbnail is " . length($thumbnail) . " bytes.";
-
-    $sth->execute( $biblionumber, $itemnumber, $mimetype, $fullsize->png(),
-        $thumbnail->png() );
-    my $dberror = $sth->errstr;
-    warn sprintf("Error returned inserting %s.%s.", ($biblionumber || $itemnumber, $mimetype)) if $sth->errstr;
-    undef $thumbnail;
-    undef $fullsize;
-    return $dberror;
-}
-
-=head2 RetrieveImage
-    my ($imagedata, $error) = RetrieveImage($imagenumber);
-
-Retrieves the specified image.
-
-=cut
-
-sub RetrieveImage {
-    my ($imagenumber) = @_;
-
-    my $dbh = C4::Context->dbh;
-    my $query =
-'SELECT biblionumber, itemnumber, imagenumber, mimetype, imagefile, thumbnail FROM biblioimages WHERE imagenumber = ?';
-    my $sth = $dbh->prepare($query);
-    $sth->execute($imagenumber);
-    my $imagedata = $sth->fetchrow_hashref;
-    if ( !$imagedata ) {
-        $imagedata->{'thumbnail'} = $noimage;
-        $imagedata->{'imagefile'} = $noimage;
-    }
-    if ( $sth->err ) {
-        warn "Database error!" if $debug;
-    }
-    return $imagedata;
-}
-
-=head2 ListImagesForBiblio
-    my (@images) = ListImagesForBiblio($biblionumber);
-
-Gets a list of all images associated with a particular biblio.
-
-=cut
-
-sub ListImagesForBiblio {
-    my ($biblionumber) = @_;
-
-    my @imagenumbers;
-    my $dbh   = C4::Context->dbh;
-    my $query = 'SELECT imagenumber FROM biblioimages WHERE biblionumber = ?';
-    my $sth   = $dbh->prepare($query);
-    $sth->execute($biblionumber);
-    while ( my $row = $sth->fetchrow_hashref ) {
-        push @imagenumbers, $row->{'imagenumber'};
-    }
-    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);
-
-Removes the image with the supplied imagenumber.
-
-=cut
-
-sub DelImage {
-    my ($imagenumber) = @_;
-    warn "Imagenumber passed to DelImage is $imagenumber" if $debug;
-    my $dbh   = C4::Context->dbh;
-    my $query = "DELETE FROM biblioimages WHERE imagenumber = ?;";
-    my $sth   = $dbh->prepare($query);
-    $sth->execute($imagenumber);
-    my $dberror = $sth->errstr;
-    warn "Database error!" if $sth->errstr;
-    return $dberror;
-}
-
-sub _scale_image {
-    my ( $image, $maxwidth, $maxheight ) = @_;
-    my ( $width, $height ) = $image->getBounds();
-    $debug and warn "image is $width pix X $height pix.";
-    if ( $width > $maxwidth || $height > $maxheight ) {
-
-#        $debug and warn "$filename exceeds the maximum pixel dimensions of $maxwidth X $maxheight. Resizing...";
-        my $percent_reduce;  # Percent we will reduce the image dimensions by...
-        if ( $width > $maxwidth ) {
-            $percent_reduce =
-              sprintf( "%.5f", ( $maxwidth / $width ) )
-              ;    # If the width is oversize, scale based on width overage...
-        }
-        else {
-            $percent_reduce =
-              sprintf( "%.5f", ( $maxheight / $height ) )
-              ;    # otherwise scale based on height overage.
-        }
-        my $width_reduce  = sprintf( "%.0f", ( $width * $percent_reduce ) );
-        my $height_reduce = sprintf( "%.0f", ( $height * $percent_reduce ) );
-        $debug
-          and warn "Reducing image by "
-          . ( $percent_reduce * 100 )
-          . "\% or to $width_reduce pix X $height_reduce pix";
-        my $newimage = GD::Image->new( $width_reduce, $height_reduce, 1 )
-          ;        #'1' creates true color image...
-        $newimage->copyResampled( $image, 0, 0, 0, 0, $width_reduce,
-            $height_reduce, $width, $height );
-        return $newimage;
-    }
-    else {
-        return $image;
-    }
-}
-
-=head2 NoImage
-
-    C4::Images->NoImage;
-
-Returns the gif to be used when there is no image matching the request, and
-its mimetype (image/gif).
-
-=cut
-
-sub NoImage {
-    return $noimage, 'image/gif';
-}
-
-1;
index f430f41..29c7d1e 100644 (file)
@@ -780,6 +780,21 @@ sub custom_cover_image_url {
     return $url;
 }
 
+=head3 cover_images
+
+Return the cover images associated with this biblio.
+
+=cut
+
+sub cover_images {
+    my ( $self ) = @_;
+
+    my $cover_images_rs = $self->_result->cover_images;
+    return unless $cover_images_rs;
+    return Koha::CoverImages->_new_from_dbic($cover_images_rs);
+}
+
+
 =head3 to_api
 
     my $json = $biblio->to_api;
diff --git a/Koha/CoverImage.pm b/Koha/CoverImage.pm
new file mode 100644 (file)
index 0000000..7edb35b
--- /dev/null
@@ -0,0 +1,116 @@
+package Koha::CoverImage;
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Carp;
+use GD;
+
+use Koha::Database;
+
+use base qw(Koha::Object);
+
+=head1 NAME
+
+Koha::CoverImage - Koha CoverImage Object class
+
+=head1 API
+
+=head2 Class methods
+
+=head3 new
+
+my $cover_image = Koha::CoverImage->new(
+    {
+        biblionumber => $biblionumber,
+        itemnumber   => $itemnumber,
+        src_image    => $image,
+        mimetype     => $mimetype,
+    }
+);
+
+biblionumber and/or itemnumber must be passed, otherwise the image will not be
+linked to anything.
+
+src_image must contain the GD image, the fullsize and thumbnail images will be generated
+and stored in the database.
+
+=cut
+
+sub new {
+    my ( $class, $params ) = @_;
+
+    my $src_image = delete $params->{src_image};
+
+    if ( $src_image ) {
+          ; # GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to PNG which is lossless...
+
+        # Check the pixel size of the image we are about to import...
+        my $thumbnail = $class->_scale_image( $src_image, 140, 200 )
+          ;    # MAX pixel dims are 140 X 200 for thumbnail...
+        my $fullsize = $class->_scale_image( $src_image, 600, 800 )
+          ;    # MAX pixel dims are 600 X 800 for full-size image...
+
+        $params->{mimetype} = 'image/png';
+        $params->{imagefile} = $fullsize->png();
+        $params->{thumbnail} = $thumbnail->png();
+    }
+
+    return $class->SUPER::new($params);
+}
+
+sub _scale_image {
+    my ( $self, $image, $maxwidth, $maxheight ) = @_;
+    my ( $width, $height ) = $image->getBounds();
+    if ( $width > $maxwidth || $height > $maxheight ) {
+
+        my $percent_reduce;  # Percent we will reduce the image dimensions by...
+        if ( $width > $maxwidth ) {
+            $percent_reduce =
+              sprintf( "%.5f", ( $maxwidth / $width ) )
+              ;    # If the width is oversize, scale based on width overage...
+        }
+        else {
+            $percent_reduce =
+              sprintf( "%.5f", ( $maxheight / $height ) )
+              ;    # otherwise scale based on height overage.
+        }
+        my $width_reduce  = sprintf( "%.0f", ( $width * $percent_reduce ) );
+        my $height_reduce = sprintf( "%.0f", ( $height * $percent_reduce ) );
+        my $newimage = GD::Image->new( $width_reduce, $height_reduce, 1 )
+          ;        #'1' creates true color image...
+        $newimage->copyResampled( $image, 0, 0, 0, 0, $width_reduce,
+            $height_reduce, $width, $height );
+        return $newimage;
+    }
+    else {
+        return $image;
+    }
+}
+
+
+=head2 Internal methods
+
+=head3 _type
+
+=cut
+
+sub _type {
+    return 'CoverImage';
+}
+
+1;
diff --git a/Koha/CoverImages.pm b/Koha/CoverImages.pm
new file mode 100644 (file)
index 0000000..4dff96d
--- /dev/null
@@ -0,0 +1,71 @@
+package Koha::CoverImages;
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use Carp;
+
+use Koha::Database;
+
+use Koha::CoverImage;
+
+use base qw(Koha::Objects);
+
+=head1 NAME
+
+Koha::Cities - Koha CoverImage Object set class
+
+=head1 API
+
+=head2 Class Methods
+
+=cut
+
+=head3 no_image
+
+Returns the gif to be used when there is no image.
+Its mimetype is image/gif.
+
+=cut
+
+sub no_image {
+    my $no_image = pack( "H*",
+            '47494638396101000100800000FFFFFF'
+          . '00000021F90401000000002C00000000'
+          . '010001000002024401003B' );
+    return Koha::CoverImage->new(
+        {
+            mimetype  => 'image/gif',
+            imagefile => $no_image,
+            thumbnail => $no_image,
+        }
+    );
+}
+
+=head3 _type
+
+=cut
+
+sub _type {
+    return 'CoverImage';
+}
+
+sub object_class {
+    return 'Koha::CoverImage';
+}
+
+1;
index 5b12115..13c4f9f 100644 (file)
@@ -35,6 +35,7 @@ use C4::Log qw( logaction );
 
 use Koha::Checkouts;
 use Koha::CirculationRules;
+use Koha::CoverImages;
 use Koha::SearchEngine::Indexer;
 use Koha::Item::Transfer::Limits;
 use Koha::Item::Transfers;
@@ -781,6 +782,21 @@ sub renewal_branchcode {
     return $branchcode;
 }
 
+=head3 cover_image
+
+Return the cover image associated with this item.
+
+=cut
+
+sub cover_image {
+    my ( $self ) = @_;
+
+    my $cover_image_rs = $self->_result->cover_images;
+    return unless $cover_image_rs;
+    # So far we allow only 1 cover image per item
+    return Koha::CoverImages->_new_from_dbic($cover_image_rs)->next;
+}
+
 =head3 _set_found_trigger
 
     $self->_set_found_trigger
index 3246468..4e64043 100755 (executable)
@@ -36,13 +36,13 @@ use C4::External::Amazon;
 use C4::Search;        # enabled_staff_search_views
 use C4::Tags qw(get_tags);
 use C4::XSLT;
-use C4::Images;
 use Koha::DateUtils;
 use C4::HTML5Media;
 use C4::CourseReserves qw(GetItemCourseReservesInfo);
 use C4::Acquisition qw(GetOrdersByBiblionumber);
 use Koha::AuthorisedValues;
 use Koha::Biblios;
+use Koha::CoverImages;
 use Koha::Illrequests;
 use Koha::Items;
 use Koha::ItemTypes;
@@ -408,8 +408,8 @@ foreach my $item (@items) {
     }
 
     if ( C4::Context->preference("LocalCoverImages") == 1 ) {
-        $item->{imagenumber} =
-          C4::Images::GetImageForItem( $item->{itemnumber} );
+        my $cover_image = $item_object->cover_image;
+        $item->{imagenumber} = $cover_image ? $cover_image->imagenumber : undef;
     }
 
     if ($currentbranch and C4::Context->preference('SeparateHoldings')) {
@@ -531,8 +531,8 @@ if (C4::Context->preference("FRBRizeEditions")==1) {
 }
 
 if ( C4::Context->preference("LocalCoverImages") == 1 ) {
-    my @images = ListImagesForBiblio($biblionumber);
-    $template->{VARS}->{localimages} = \@images;
+    my $images = $biblio->cover_images;
+    $template->param( localimages => $biblio->cover_images );
 }
 
 # HTML5 Media
index d1fcba7..a314652 100755 (executable)
@@ -27,7 +27,9 @@ use Modern::Perl;
 
 use CGI qw ( -utf8 );    #qw(:standard escapeHTML);
 use C4::Context;
-use C4::Images;
+use Koha::CoverImages;
+use Koha::Biblios;
+use Koha::Exceptions;
 
 $| = 1;
 
@@ -57,43 +59,38 @@ imagenumber, a random image is selected.
 
 =cut
 
-my ( $image, $mimetype ) = C4::Images->NoImage;
+my ( $image );
 if ( C4::Context->preference("LocalCoverImages") ) {
-    if ( defined $data->param('imagenumber') ) {
+    my $imagenumber = $data->param('imagenumber');
+    my $biblionumber = $data->param('biblionumber');
+    if ( defined $imagenumber ) {
         $imagenumber = $data->param('imagenumber');
+        $image = Koha::CoverImages->find($imagenumber);
     }
-    elsif ( defined $data->param('biblionumber') ) {
-        my @imagenumbers = ListImagesForBiblio( $data->multi_param('biblionumber') );
-        if (@imagenumbers) {
-            $imagenumber = $imagenumbers[0];
-        }
-        else {
+    elsif ( defined $biblionumber ) {
+        my $biblio = Koha::Biblios->find($biblionumber);
+        Koha::Exceptions::ObjectNotFound->throw( 'No bibliographic record for biblionumber ' . $biblionumber ) unless $biblio;
+        my $cover_images = $biblio->cover_images;
+        if ( $cover_images->count ) {
+            $image = $cover_images->next;
+        } else {
             warn "No images for this biblio" if $DEBUG;
         }
     }
-    else {
-        $imagenumber = shift;
-    }
-
-    if ($imagenumber) {
-        warn "imagenumber passed in: $imagenumber" if $DEBUG;
-        my $imagedata = RetrieveImage($imagenumber);
-        if ($imagedata) {
-            if ( $data->param('thumbnail') ) {
-                $image = $imagedata->{'thumbnail'};
-            }
-            else {
-                $image = $imagedata->{'imagefile'};
-            }
-            $mimetype = $imagedata->{'mimetype'};
-        }
-    }
 }
+
+$image ||= Koha::CoverImages->no_image;
+
+my $image_data =
+    $data->param('thumbnail')
+  ? $image->thumbnail
+  : $image->imagefile;
+
 print $data->header(
-    -type            => $mimetype,
+    -type            => $image->mimetype,
     -expires         => '+30m',
-    -Content_Length  => length($image)
-), $image;
+    -Content_Length  => length($image_data)
+), $image_data;
 
 =head1 AUTHOR
 
index d20fae1..3ed64fe 100755 (executable)
@@ -24,7 +24,6 @@ use C4::Auth;
 use C4::Biblio;
 use C4::Items;
 use C4::Output;
-use C4::Images;
 use C4::Search;
 
 use Koha::Biblios;
@@ -68,19 +67,21 @@ if( $query->cookie("searchToOrder") ){
 
 if ( C4::Context->preference("LocalCoverImages") ) {
     if ( $itemnumber ) {
-        my $image = C4::Images::GetImageForItem($itemnumber);
+        my $item = Koha::Items->find($itemnumber);
+        my $image = $item->cover_image;
         $template->param(
             LocalCoverImages => 1,
             images           => [$image],
-            imagenumber      => $imagenumber,
+            imagenumber      => ($image ? $image->imagenumber : undef),
         );
 
     } else {
-        my @images = ListImagesForBiblio($biblionumber);
+        my $images = $biblio->cover_images->as_list;
+
         $template->param(
             LocalCoverImages => 1,
-            images           => \@images,
-            imagenumber      => $imagenumber || $images[0] || '',
+            images           => $images,
+            imagenumber      => (@$images ? $images->[0]->imagenumber : undef),
         );
     }
 }
index 37a51a0..fc9953b 100644 (file)
@@ -3382,7 +3382,7 @@ CREATE TABLE `cover_images` ( -- local cover images
  `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- image creation/update time
  PRIMARY KEY (`imagenumber`),
  CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT `bibliocoverimage_fk2` FOREIGN KEY (`itemnumber`) REFERENCES `item` (`itemnumber`) ON DELETE CASCADE ON UPDATE CASCADE
+ CONSTRAINT `bibliocoverimage_fk2` FOREIGN KEY (`itemnumber`) REFERENCES `items` (`itemnumber`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 --
index da5b91f..3fed84d 100644 (file)
             <div class="col-xs-3" id="bookcoverimg">
                 <div id="cover-slides">
                     [% IF ( LocalCoverImages ) %]
-                        [% IF ( localimages.0 ) %]
+                        [% IF localimages.count %]
                             [% FOREACH image IN localimages %]
-                                [% IF image %]
-                                    <div class="cover-image local-coverimg">
-                                        <a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&amp;imagenumber=[% image | uri %]">
-                                            <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image | uri %]" alt="Local cover image" />
-                                        </a>
-                                        <div class="hint">Local cover image</div>
-                                    </div>
-                                [% END %]
+                                <div class="cover-image local-coverimg">
+                                    <a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&amp;imagenumber=[% image.imagenumber | uri %]">
+                                        <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image.imagenumber | uri %]" alt="Local cover image" />
+                                    </a>
+                                    <div class="hint">Local cover image</div>
+                                </div>
                             [% END %]
                         [% END %]
                     [% END %]
 [% IF suggestions.count %]<li><a href="#suggestion_details">Suggestion details</a></li>[% END %]
 [% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li><a href="#editions">Editions</a></li>[% END %][% END %]
 [% IF ( LocalCoverImages ) %]
-    [% IF ( localimages || CAN_user_tools_upload_local_cover_images ) %]
+    [% IF ( localimages.count || CAN_user_tools_upload_local_cover_images ) %]
         <li>
-            <a href="#images">Images ([% localimages.size() || 0 | html %])</a>
+            <a href="#images">Images ([% localimages.count || 0 | html %])</a>
         </li>
     [% END %]
 [% END %]
@@ -871,14 +869,14 @@ Note that permanent location is a code, and location may be an authval.
 
 [% IF ( LocalCoverImages ) %]
     <div id="images">
-        [% IF ( localimages.0 ) %]
+        [% IF localimages.count %]
             <p>Click on an image to view it in the image viewer</p>
             <ul class="thumbnails">
                 [% FOREACH image IN localimages %]
                     [% IF image %]
-                        <li id="imagenumber-[% image | html %]" class="thumbnail">
-                            <a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&amp;imagenumber=[% image | uri %]">
-                                <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image | uri %]" />
+                        <li id="imagenumber-[% image.imagenumber | html %]" class="thumbnail">
+                            <a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&amp;imagenumber=[% image.imagenumber | uri %]">
+                                <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image.imagenumber | uri %]" />
                             </a>
                             [% IF CAN_user_tools_upload_local_cover_images %]
                                 <a href="#" class="remove"><i class="fa fa-trash"></i> Delete image</a>
index f1fb75e..d77e6bc 100644 (file)
@@ -40,7 +40,7 @@
 <h4>[% biblio.author | html %]</h4>
 
 [% IF ( LocalCoverImages == 1 ) %]
-    [% IF ( images.size > 0 ) %]
+    [% IF images.size %]
         <div class="row">
             <div class="col-md-8">
                 <div id="largeCover">
 
             <div class="col-md-4">
                 <ul class="thumbnails">
-                    [% FOREACH img IN images %]
-                        [% IF img %]
-                            <li id="imagenumber-[% img | html %]" class="thumbnail">
-                                <a class="show_cover" data-coverimg="[% img | html %]" href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | html %]&amp;imagenumber=[% img | html %]">
-                                    [% IF ( imagenumber == img ) %]
-                                        <img class="selected" id="thumbnail_[% img | html %]" src="/cgi-bin/koha/catalogue/image.pl?imagenumber=[% img | html %]&amp;thumbnail=1" alt="Thumbnail" />
-                                    [% ELSE %]
-                                        <img id="thumbnail_[% img | html %]" src="/cgi-bin/koha/catalogue/image.pl?imagenumber=[% img | html %]&amp;thumbnail=1" alt="Thumbnail" />
-                                    [% END %]
-                                </a>
-                                [% IF CAN_user_tools_upload_local_cover_images %]
-                                    <a href="#" class="remove" data-coverimg="[% img | html %]"><i class="fa fa-trash"></i> Delete image</a>
+                    [% FOREACH image IN images %]
+                            <li id="imagenumber-[% image.imagenumber | html %]" class="thumbnail">
+                            <a class="show_cover" data-coverimg="[% image.imagenumber | html %]" href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | html %]&amp;imagenumber=[% image.imagenumber | html %]">
+                                [% IF loop.first %]
+                                    <img class="selected" id="thumbnail_[% image.imagenumber | html %]" src="/cgi-bin/koha/catalogue/image.pl?imagenumber=[% image.imagenumber | html %]&amp;thumbnail=1" alt="Thumbnail" />
+                                [% ELSE %]
+                                    <img id="thumbnail_[% image.imagenumber | html %]" src="/cgi-bin/koha/catalogue/image.pl?imagenumber=[% image.imagenumber | html %]&amp;thumbnail=1" alt="Thumbnail" />
                                 [% END %]
-                            </li>
-                        [% END # /IF img %]
+                            </a>
+                            [% IF CAN_user_tools_upload_local_cover_images %]
+                                <a href="#" class="remove" data-coverimg="[% image.imagenumber | html %]"><i class="fa fa-trash"></i> Delete image</a>
+                            [% END %]
+                        </li>
                     [% END # /FOREACH img %]
                 </ul> <!-- /ul.thumbnails -->
             </div> <!-- /.col-md-4 -->
index 03d07e2..c650fcc 100644 (file)
                             </li>
                         [% END %]
 
-                        [% IF ( OPACLocalCoverImages && localimages.size ) %]
+                        [% IF ( OPACLocalCoverImages && localimages.count ) %]
                             <li id="tab_images"><a href="#images">Images</a></li>
                         [% END %]
 
                             </div>
                         [% END # / IF HTML5MediaEnabled %]
 
-                        [% IF ( OPACLocalCoverImages && localimages.size ) %]
+                        [% IF ( OPACLocalCoverImages && localimages.count ) %]
                             <div id="images">
                                 <p>Click on an image to view it in the image viewer</p>
                                 [% FOREACH image IN localimages %]
-                                    [% IF image %]
-                                        <a class="localimage" href="/cgi-bin/koha/opac-imageviewer.pl?biblionumber=[% biblio.biblionumber | html %]&amp;imagenumber=[% image | html %]"><img alt="" src="/cgi-bin/koha/opac-image.pl?thumbnail=1&amp;imagenumber=[% image | html %]" /></a>
-                                    [% END %]
+                                    <a class="localimage" href="/cgi-bin/koha/opac-imageviewer.pl?biblionumber=[% biblio.biblionumber | html %]&amp;imagenumber=[% image.imagenumber | html %]"><img alt="" src="/cgi-bin/koha/opac-image.pl?thumbnail=1&amp;imagenumber=[% image.imagenumber | html %]" /></a>
                                 [% END %]
                             </div><!-- / #images -->
                         [% END # / IF OPACLocalCoverImages && localimages.size %]
index fbe8673..9096df5 100644 (file)
                         </div> <!-- / .span12 -->
 
                         [% IF OPACLocalCoverImages == 1 %]
-                            <div class="col-lg-3">
-                                <div id="thumbnails">
-                                    [% FOREACH img IN images %]
-                                        [% IF img %]
-                                            <a href="/cgi-bin/koha/opac-imageviewer.pl?biblionumber=[% biblionumber | url %]&amp;imagenumber=[% img | uri %]" onclick="showCover([% img | html %]); return false;">
-                                            [% IF ( imagenumber == img ) %]
-                                                <img class="thumbnail selected" id="[% img | html %]" src="/cgi-bin/koha/opac-image.pl?imagenumber=[% img | html %]&amp;thumbnail=1" alt="Thumbnail"/>
+                            [% IF images.count %]
+                                <div class="col-lg-3">
+                                    <div id="thumbnails">
+                                        [% FOREACH image IN images %]
+                                            <a href="/cgi-bin/koha/opac-imageviewer.pl?biblionumber=[% biblionumber | url %]&amp;imagenumber=[% image.imagenumber| uri %]" onclick="showCover([% image.imagenumber| html %]); return false;">
+                                            [% IF loop.first %]
+                                                <img class="thumbnail selected" id="[% image.imagenumber| html %]" src="/cgi-bin/koha/opac-image.pl?imagenumber=[% image.imagenumber | html %]&amp;thumbnail=1" alt="Thumbnail"/>
                                             [% ELSE %]
-                                                <img class="thumbnail" id="[% img | html %]" src="/cgi-bin/koha/opac-image.pl?imagenumber=[% img | html %]&amp;thumbnail=1" alt="Thumbnail"/>
+                                                <img class="thumbnail" id="[% image.imagenumber | html %]" src="/cgi-bin/koha/opac-image.pl?imagenumber=[% image.imagenumber | html %]&amp;thumbnail=1" alt="Thumbnail"/>
                                             [% END %]
                                             </a>
                                         [% END %]
-                                    [% END %]
-                                </div> <!-- /#thumbnails -->
-                            </div> <!-- /.col-lg-3 -->
+                                    </div> <!-- /#thumbnails -->
+                                </div> <!-- /.col-lg-3 -->
+                            [% END %]
                         [% ELSE %]
                             Unfortunately, images are not enabled for this catalog at this time.
                         [% END %]
index 326c7f5..67c074c 100755 (executable)
@@ -45,7 +45,6 @@ use C4::Letters;
 use MARC::Record;
 use MARC::Field;
 use List::MoreUtils qw/any none/;
-use C4::Images;
 use Koha::DateUtils;
 use C4::HTML5Media;
 use C4::CourseReserves qw(GetItemCourseReservesInfo);
@@ -764,8 +763,8 @@ if ( not $viewallitems and @items > $max_items_to_display ) {
     }
 
     if ( C4::Context->preference("OPACLocalCoverImages") == 1 ) {
-        $itm->{imagenumber} =
-          C4::Images::GetImageForItem( $itm->{itemnumber} );
+        my $cover_image = $item->cover_image;
+        $itm->{imagenumber} = $cover_image ? $cover_image->imagenumber : undef;
     }
 
     my $itembranch = $itm->{$separatebranch};
@@ -1248,8 +1247,7 @@ my $defaulttab =
 $template->param('defaulttab' => $defaulttab);
 
 if (C4::Context->preference('OPACLocalCoverImages') == 1) {
-    my @images = ListImagesForBiblio($biblionumber);
-    $template->{VARS}->{localimages} = \@images;
+    $template->param( localimages => $biblio->cover_images );
 }
 
 $template->{VARS}->{OPACPopupAuthorsSearch} = C4::Context->preference('OPACPopupAuthorsSearch');
index 7a94e81..30efbb2 100755 (executable)
@@ -27,7 +27,8 @@ use Modern::Perl;
 
 use CGI qw ( -utf8 );
 use C4::Context;
-use C4::Images;
+use Koha::Biblios;
+use Koha::CoverImages;
 
 $| = 1;
 
@@ -57,43 +58,38 @@ imagenumber, a random image is selected.
 
 =cut
 
-my ( $image, $mimetype ) = C4::Images->NoImage;
+my ( $image );
 if ( C4::Context->preference("OPACLocalCoverImages") ) {
-    if ( defined $data->param('imagenumber') ) {
+    my $imagenumber = $data->param('imagenumber');
+    my $biblionumber = $data->param('biblionumber');
+    if ( defined $imagenumber ) {
         $imagenumber = $data->param('imagenumber');
+        $image = Koha::CoverImages->find($imagenumber);
     }
-    elsif ( defined $data->param('biblionumber') ) {
-        my @imagenumbers = ListImagesForBiblio( scalar $data->param('biblionumber') );
-        if (@imagenumbers) {
-            $imagenumber = $imagenumbers[0];
-        }
-        else {
+    elsif ( defined $biblionumber ) {
+        my $biblio = Koha::Biblios->find($biblionumber);
+        Koha::Exceptions::ObjectNotFound->throw( 'No bibliographic record for biblionumber ' . $biblionumber ) unless $biblio;
+        my $cover_images = $biblio->cover_images;
+        if ( $cover_images->count ) {
+            $image = $cover_images->next;
+        } else {
             warn "No images for this biblio" if $DEBUG;
         }
     }
-    else {
-        $imagenumber = shift;
-    }
-
-    if ($imagenumber) {
-        warn "imagenumber passed in: $imagenumber" if $DEBUG;
-        my $imagedata = RetrieveImage($imagenumber);
-        if ($imagedata) {
-            if ( $data->param('thumbnail') ) {
-                $image = $imagedata->{'thumbnail'};
-            }
-            else {
-                $image = $imagedata->{'imagefile'};
-            }
-            $mimetype = $imagedata->{'mimetype'};
-        }
-    }
 }
+
+$image ||= Koha::CoverImages->no_image;
+
+my $image_data =
+    $data->param('thumbnail')
+  ? $image->thumbnail
+  : $image->imagefile;
+
 print $data->header(
-    -type            => $mimetype,
+    -type            => $image->mimetype,
     -expires         => '+30m',
-    -Content_Length  => length($image)
-), $image;
+    -Content_Length  => length($image_data)
+), $image_data;
 
 =head1 AUTHOR
 
index 2e4dc39..4e717c2 100755 (executable)
@@ -23,9 +23,9 @@ use CGI qw ( -utf8 );
 use C4::Auth;
 use C4::Biblio;
 use C4::Output;
-use C4::Images;
 
 use Koha::Biblios;
+use Koha::CoverImages;
 use Koha::Items;
 
 my $query = new CGI;
@@ -42,19 +42,19 @@ my $biblionumber = $query->param('biblionumber') || $query->param('bib');
 my $imagenumber = $query->param('imagenumber');
 unless ( $biblionumber ) {
     # Retrieving the biblio from the imagenumber
-    my $image = C4::Images::RetrieveImage($imagenumber);
+    my $image = Koha::CoverImages->find($imagenumber);
     my $item  = Koha::Items->find($image->{itemnumber});
     $biblionumber = $item->biblionumber;
 }
 my $biblio = Koha::Biblios->find( $biblionumber );
 
 if ( C4::Context->preference("OPACLocalCoverImages") ) {
-    my @images = !$imagenumber ? ListImagesForBiblio($biblionumber) : ();
+    my $images = !$imagenumber ? Koha::Biblios->find($biblionumber)->cover_images->as_list : [];
     $template->param(
         OPACLocalCoverImages => 1,
-        images               => \@images,
+        images               => $images,
         biblionumber         => $biblionumber,
-        imagenumber          => $imagenumber || $images[0] || '',
+        imagenumber          => (@$images ? $images->[0]->imagenumber : $imagenumber),
     );
 }
 
index 5894410..688067f 100755 (executable)
@@ -22,7 +22,7 @@ use Modern::Perl;
 
 use CGI qw ( -utf8 );
 use C4::Auth qw/check_cookie_auth/;
-use C4::Images;
+use Koha::CoverImages;
 use JSON qw/to_json/;
 
 my $input = new CGI;
@@ -46,7 +46,7 @@ if ( $action eq "delete" ) {
 
     foreach my $imagenumber ( @imagenumbers ) {
         eval {
-            DelImage($imagenumber);
+            Koha::CoverImages->find($imagenumber)->delete;
         };
         if ( $@ ) {
             push @$response, {
diff --git a/t/Images.t b/t/Images.t
deleted file mode 100755 (executable)
index 338a903..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/perl
-
-# This file is part of Koha.
-#
-# Koha is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# Koha is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Koha; if not, see <http://www.gnu.org/licenses>.
-
-use Modern::Perl;
-
-use Test::More;
-use Test::MockModule;
-
-use Module::Load::Conditional qw/check_install/;
-
-BEGIN {
-    if ( check_install( module => 'Test::DBIx::Class' ) ) {
-        plan tests => 8;
-    } else {
-        plan skip_all => "Need Test::DBIx::Class"
-    }
-}
-
-use_ok('C4::Images');
-
-use Test::DBIx::Class;
-
-# Make the code in the module use our mocked Koha::Schema/Koha::Database
-my $db = Test::MockModule->new('Koha::Database');
-$db->mock(
-    # Schema() gives us the DB connection set up by Test::DBIx::Class
-    _new_schema => sub { return Schema(); }
-);
-
-my $biblionumber = 2;
-my $images = [
-    [ 1, $biblionumber, 'gif',  'imagefile1', 'thumbnail1' ],
-    [ 3, $biblionumber, 'jpeg', 'imagefile3', 'thumbnail3' ],
-];
-fixtures_ok [
-    Biblioimage => [
-        [ 'imagenumber', 'biblionumber', 'mimetype', 'imagefile', 'thumbnail' ],
-        @$images,
-    ],
-], 'add fixtures';
-
-my $image = C4::Images::RetrieveImage(1);
-
-is( $image->{'imagenumber'}, 1, 'First imagenumber is 1' );
-
-is( $image->{'mimetype'}, 'gif', 'First mimetype is gif' );
-
-is( $image->{'thumbnail'}, 'thumbnail1', 'First thumbnail is correct' );
-
-my @imagenumbers = C4::Images::ListImagesForBiblio($biblionumber);
-
-is( $imagenumbers[0], 1, 'imagenumber is 1' );
-
-is( $imagenumbers[1], 3, 'imagenumber is 3' );
-
-is( $imagenumbers[4], undef, 'imagenumber undef' );
-
index 69cfdf4..66067df 100644 (file)
@@ -81,16 +81,13 @@ is( ref( $item->cover_image ),
     'Koha::CoverImage',
     'Koha::Item->cover_image returns a Koha::CoverImage object' );
 
-throws_ok {
-    Koha::CoverImage->new(
-        {
-            biblionumber => $biblio->biblionumber,
-            itemnumber   => $item->itemnumber,
-            src_image    => GD::Image->new($logo_filepath)
-        }
-      )->store
-}
-'Koha::Exceptions::WrongParameter',
-  'Exception is thrown if both biblionumber and itemnumber are passed';
+Koha::CoverImage->new(
+    {
+        biblionumber => $biblio->biblionumber,
+        itemnumber   => $item->itemnumber,
+        src_image    => GD::Image->new($logo_filepath)
+    }
+)->store;
+is( $biblio->cover_images->count, 3, );
 
 $schema->storage->txn_rollback;
index 735987c..85cbedc 100755 (executable)
@@ -45,7 +45,8 @@ use GD;
 use C4::Context;
 use C4::Auth;
 use C4::Output;
-use C4::Images;
+use Koha::Biblios;
+use Koha::CoverImages;
 use Koha::Items;
 use Koha::UploadedFiles;
 use C4::Log;
@@ -92,8 +93,25 @@ if ($fileID) {
         my $srcimage = GD::Image->new($fh);
         $fh->close if $fh;
         if ( defined $srcimage ) {
-            my $dberror = PutImage( { biblionumber => $biblionumber, itemnumber => $itemnumber, src_image => $srcimage, replace => $replace } );
-            if ($dberror) {
+            eval {
+                if ( $replace && $biblionumber ) {
+                    Koha::Biblios->find($biblionumber)->cover_images->delete;
+                } elsif ( $itemnumber ) {
+                    my $cover_image = Koha::Items->find($itemnumber)->cover_image;
+                    $cover_image->delete if $cover_image;
+                }
+
+                Koha::CoverImage->new(
+                    {
+                        biblionumber => $biblionumber,
+                        itemnumber   => $itemnumber,
+                        src_image    => $srcimage
+                    }
+                )->store;
+            };
+
+            if ($@) {
+                warn $@;
                 $error = 'DBERR';
             }
             else {
@@ -162,14 +180,23 @@ if ($fileID) {
                             my $srcimage = GD::Image->new("$dir/$filename");
                             if ( defined $srcimage ) {
                                 $total++;
-                                my $dberror = PutImage(
-                                    {
-                                        biblionumber => $biblionumber,
-                                        src_image    => $srcimage,
-                                        replace      => $replace
+                                eval {
+                                    if ( $replace && $biblionumber ) {
+                                        Koha::Biblios->find($biblionumber)->cover_images->delete;
+                                    } elsif ( $itemnumber ) {
+                                        Koha::Items->find($itemnumber)->cover_image->delete;
                                     }
-                                );
-                                if ($dberror) {
+
+                                    Koha::CoverImage->new(
+                                        {
+                                            biblionumber => $biblionumber,
+                                            itemnumber   => $itemnumber,
+                                            src_image    => $srcimage
+                                        }
+                                    )->store;
+                                };
+
+                                if ($@) {
                                     $error = 'DBERR';
                                 }
                             }