@@ -, +, @@
display in OPAC.
---
.../data/mysql/en/mandatory/userpermissions.sql | 1 +
installer/data/mysql/kohastructure.sql | 13 +
installer/data/mysql/sysprefs.sql | 2 +-
installer/data/mysql/updatedatabase.pl | 16 +
.../intranet-tmpl/prog/en/includes/tools-menu.inc | 3 +
.../admin/preferences/enhanced_content.pref | 7 +
.../prog/en/modules/tools/tools-home.tt | 5 +
.../prog/en/modules/tools/upload-cover-image.tt | 126 +++++++
koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt | 1 +
.../opac-tmpl/prog/en/modules/opac-results.tt | 1 +
opac/opac-coverimage.pl | 105 ++++++
opac/opac-detail.pl | 5 +
opac/opac-search.pl | 4 +
tools/upload-cover-image.pl | 341 ++++++++++++++++++++
14 files changed, 629 insertions(+), 1 deletions(-)
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-cover-image.tt
create mode 100755 opac/opac-coverimage.pl
create mode 100755 tools/upload-cover-image.pl
--- a/installer/data/mysql/en/mandatory/userpermissions.sql
+++ a/installer/data/mysql/en/mandatory/userpermissions.sql
@@ -36,6 +36,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES
(13, 'manage_csv_profiles', 'Manage CSV export profiles'),
(13, 'moderate_tags', 'Moderate patron tags'),
(13, 'rotating_collections', 'Manage rotating collections'),
+ (13, 'upload_local_cover_images', 'Upload local cover images'),
(15, 'check_expiration', 'Check the expiration of a serial'),
(15, 'claim_serials', 'Claim missing serials'),
(15, 'create_subscription', 'Create a new subscription'),
--- a/installer/data/mysql/kohastructure.sql
+++ a/installer/data/mysql/kohastructure.sql
@@ -2665,6 +2665,19 @@ CREATE TABLE `fieldmapping` ( -- koha to keyword mapping
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+--
+-- Table structure for table `bibliocoverimage`
+--
+
+DROP TABLE IF EXISTS `bibliocoverimage`;
+
+CREATE TABLE `bibliocoverimage` (
+ `biblionumber` int(11) NOT NULL,
+ `mimetype` varchar(15) NOT NULL,
+ `imagefile` mediumblob NOT NULL,
+ PRIMARY KEY (`biblionumber`),
+ CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
--- a/installer/data/mysql/sysprefs.sql
+++ a/installer/data/mysql/sysprefs.sql
@@ -328,4 +328,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OpacKohaUrl','1',"Show 'Powered by Koha' text on OPAC footer.",NULL,NULL);
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('EasyAnalyticalRecords','0','If on, display in the catalogue screens tools to easily setup analytical record relationships','','YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo');
-
+INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover images on OPAC search and details pages.','1','YesNo');
--- a/installer/data/mysql/updatedatabase.pl
+++ a/installer/data/mysql/updatedatabase.pl
@@ -4550,6 +4550,22 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
SetVersion ($DBversion);
}
+$DBversion = '3.06.00.XXX';
+if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+ $dbh->do( q|CREATE TABLE `bibliocoverimage` (
+ `biblionumber` int(11) NOT NULL,
+ `mimetype` varchar(15) NOT NULL,
+ `imagefile` mediumblob NOT NULL,
+ PRIMARY KEY (`biblionumber`),
+ CONSTRAINT `bibliocoverimage_fk1` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8|);
+ $dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('OPACLocalCoverImages','0','Display local cover mages on OPAC search and details pages.','1','YesNo')|);
+ $dbh->do( q|INSERT INTO permissions (module_bit, code, description) VALUES (13, 'upload_local_cover_images', 'Upload local cover images')|);
+ print "Upgrade to $DBversion done (Added bibliocoverimage table to stover local cover images)\n";
+ SetVersion ($DBversion);
+}
+
+
=head1 FUNCTIONS
=head2 DropAllForeignKeys($table)
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc
@@ -70,6 +70,9 @@
[% IF ( CAN_user_tools_manage_staged_marc ) %]
Staged MARC management
[% END %]
+ [% IF ( CAN_user_tools_upload_local_cover_images ) %]
+ Upload Local Cover Image
+ [% END %]
Additional Tools
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref
@@ -311,3 +311,10 @@ Enhanced Content:
- pref: TagsExternalDictionary
class: file
- on the server to be approved without moderation.
+ Local Cover Images:
+ -
+ - pref: OPACLocalCoverImages
+ choices:
+ yes: Display
+ no: "Don't display"
+ - local cover images on OPAC search and details pages.
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
@@ -140,6 +140,11 @@
- Managed staged MARC records, including completing and reversing imports
[% END %]
+ [% IF ( CAN_user_tools_upload_local_cover_images ) %]
+ - Upload Local Cover Image
+ - Utility to upload scanned cover images for display in OPAC
+ [% END %]
+
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-cover-image.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-cover-image.tt
@@ -0,0 +1,126 @@
+[% INCLUDE 'doc-head-open.inc' %]
+Koha › Tools › Upload Cover Images
+[% INCLUDE 'doc-head-close.inc' %]
+
+
+
+
+[% INCLUDE 'header.inc' %]
+[%# [% INCLUDE 'cover-search.inc' %] %]
+
+
+
+
+
+
+[% IF ( TOTAL ) %]
+
+
+
+ [% IF ( ERRORS ) %]
+ [% IF ( TCOUNTS ) %]
+
+
Cover Image(s) Uploaded With Some Errors
+ [% ELSE %]
+
+
Cover Image Failed to Upload
+ [% END %]
+ [% ELSE %]
+
+
Cover Image(s) Successfully Uploaded
+ [% END %]
+
+ - Unpacking completed
+ - [% TOTAL %] directorie(s) scanned.
+ - [% HANDLED %] directorie(s) processed.
+
+ [% FOREACH COUNT IN COUNTS %]
+
+ [% IF ( COUNT.TCOUNTS ) %]- [% COUNT.TCOUNTS %] image(s) moved into the database:
[% END %]
+ [% FOREACH filename IN COUNT.filenames %]
+ - [% filename.source %] - Biblionumber: [% filename.biblionumber %]
+ [% IF ( filename.filerrors ) %]
WARNING: This image not imported because
+ [% FOREACH filerror IN filename.filerrors %]
+ [% IF ( filerror.DBERR ) %]the database returned an error. Please refer to the error log for more details.
+ [% ELSIF ( filerror.IMGEXISTS ) %]this cover does not exist in the database.
+ [% ELSIF ( filerror.MIMERR ) %]the image format is unrecognized.
+ [% ELSIF ( filerror.CORERR ) %]the image file is corrupted.
+ [% ELSIF ( filerror.OPNERR ) %]Koha was unable to open the image for reading.
+ [% ELSIF ( filerror.OVRSIZ ) %]the image file is too big.
+ [% ELSIF ( filerror.CRDFIL ) %]the [% filerror.CRDFIL %] is missing.
+ [% ELSE %]of an unknown error. Please refer to the error log for more details.[% END %]
+ [% END %]
+ [% ELSE %] imported successfully.
+ [% END %]
+ [% END %]
+
+ [% END %]
+
+
+
+
Upload More Images
+
Return to Tools
+
+[% ELSE %]
+
+
+
+
Upload Cover Images
+ [% IF ( ERRORS ) %]
+
+ [% FOREACH ERROR IN ERRORS %]
+ [% IF ( ERROR.NOTZIP ) %]
- The upload file does not appear to be a zip file. The extension is not '.zip'.
+ [% ELSIF ( ERROR.NOWRITETEMP ) %]- This script is not able to create/write to the necessary temporary directory.
+ [% ELSIF ( ERROR.EMPTYUPLOAD ) %]- The upload file appears to be empty.
+ [% ELSIF ( ERROR.OPNLINK ) %]- Cannot open [% ERROR.OPNLINK %] to read.
Please verify that it exists.
+ [% ELSIF ( ERROR.OPNIMG ) %]- Cannot open [% ERROR.OPNIMG %] to read.
Please verify that it exists.
+ [% ELSIF ( ERROR.DELERR ) %]- Unrecognized or missing field delimiter.
Please verify that you are using either a single quote or a tab.
+ [% ELSIF ( ERROR.UZIPFAIL ) %]- [% ERROR.UZIPFAIL %] failed to unpack.
Please verify the integrity of the zip file and retry.
+ [% ELSE %]- [% ERROR.CORERR %] An unknown error has occurred.
Please review the error log for more details. [% END %]
+ [% END %]
+
+ [% END %]
+
+
+
+[% END %]
+
+
+
+
+ [% INCLUDE 'tools-menu.inc' %]
+
+
+[% INCLUDE 'intranet-bottom.inc' %]
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt
+++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt
@@ -224,6 +224,7 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
+ [% IF ( OPACLocalCoverImages ) %]
[% ELSE %]
No Local cover image available[% END %]
[% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( OPACurlOpenInNewWindow ) %]
[% ELSE %]
[% END %][% END %][% END %]
[% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( content_identifier_exists ) %][% IF ( using_https ) %]
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt
+++ a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt
@@ -528,6 +528,7 @@ $(document).ready(function(){
+ [% IF ( OPACLocalCoverImages ) %] [% ELSE %]No Local cover image available[% END %]
[% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %][% ELSE %]No cover image available[% END %][% END %][% END %]
[% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( using_https ) %]
--- a/opac/opac-coverimage.pl
+++ a/opac/opac-coverimage.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl
+#
+# based on patronimage.pl
+#
+# 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 2 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#
+#
+
+use strict;
+use warnings;
+
+use CGI; #qw(:standard escapeHTML);
+use C4::Context;
+
+$|=1;
+
+my $DEBUG = 0;
+my $data = new CGI;
+my $biblionumber;
+
+=head1 NAME
+
+opac-coverimage.pl - Script for retrieving and formatting local cover images for display
+
+=head1 SYNOPSIS
+
+{'patronimage'} via a warn to a log or nasty
+# things will result... you have been warned!
+
+if ($imagedata) {
+ print $data->header (-type => $imagedata->{'mimetype'}, -'Cache-Control' => 'no-store', -Content_Length => length ($imagedata->{'imagefile'})), $imagedata->{'imagefile'};
+ exit;
+} else {
+ warn "No image exists for $biblionumber";
+ exit;
+}
+
+=head2 GetCoverImage
+
+ my ($imagedata, $dberror) = GetCoverImage($biblionumber);
+
+Returns the mimetype and binary image data of the local cover image for the biblio with the supplied biblionumber.
+
+=cut
+
+sub GetCoverImage {
+ my ($biblionumber) = @_;
+ warn "Biblionumber passed to GetCoverImage is $biblionumber" if $DEBUG;
+ my $dbh = C4::Context->dbh;
+ my $query = 'SELECT mimetype, imagefile FROM bibliocoverimage WHERE biblionumber = ?';
+ my $sth = $dbh->prepare($query);
+ $sth->execute($biblionumber);
+ my $imagedata = $sth->fetchrow_hashref;
+ warn "Database error!" if $sth->errstr;
+ return $imagedata, $sth->errstr;
+}
+
+
+exit;
+
+=head1 AUTHOR
+
+Chris Nighswonger cnighswonger foundations edu
+
+modified for local cover images by Koustubha Kale kmkale anantcorp com
+
+=cut
--- a/opac/opac-detail.pl
+++ a/opac/opac-detail.pl
@@ -681,6 +681,11 @@ if (scalar(@serialcollections) > 0) {
serialcollections => \@serialcollections);
}
+# Local cover Images stuff
+if (C4::Context->preference("OPACLocalCoverImages")){
+ $template->param(OPACLocalCoverImages => 1);
+}
+
# Amazon.com Stuff
if ( C4::Context->preference("OPACAmazonEnabled") ) {
$template->param( AmazonTld => get_amazon_tld() );
--- a/opac/opac-search.pl
+++ a/opac/opac-search.pl
@@ -611,6 +611,10 @@ for (my $i=0;$i<@servers;$i++) {
$template->param(SEARCH_RESULTS => \@newresults,
OPACItemsResultsDisplay => (C4::Context->preference("OPACItemsResultsDisplay") eq "itemdetails"?1:0),
);
+ if (C4::Context->preference("OPACLocalCoverImages")){
+ $template->param(OPACLocalCoverImages => 1);
+ $template->param(OPACLocalCoverImagesPriority => C4::Context->preference("OPACLocalCoverImagesPriority"));
+ }
## Build the page numbers on the bottom of the page
my @page_numbers;
# total number of pages there will be
--- a/tools/upload-cover-image.pl
+++ a/tools/upload-cover-image.pl
@@ -0,0 +1,341 @@
+#!/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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA 02111-1307 USA
+#
+#
+#
+
+#use strict;
+#use warnings; FIXME - Bug 2505
+
+use File::Temp;
+use File::Copy;
+use CGI;
+use GD;
+use C4::Context;
+use C4::Auth;
+use C4::Output;
+use C4::Debug;
+
+my $input = new CGI;
+
+my ($template, $loggedinuser, $cookie)
+ = get_template_and_user({template_name => "tools/upload-cover-image.tmpl",
+ query => $input,
+ type => "intranet",
+ authnotrequired => 0,
+ flagsrequired => { tools => '*'},
+ debug => 0,
+ });
+
+my $filetype = $input->param('filetype');
+my $biblionumber = $input->param('biblionumber');
+my $uploadfilename = $input->param('uploadfile');
+my $uploadfile = $input->upload('uploadfile');
+my $op = $input->param('op');
+
+#FIXME: This code is really in the rough. The variables need to be re-scoped as the two subs depend on global vars to operate.
+# Other parts of this code could be optimized as well, I think. Perhaps the file upload could be done with YUI's upload
+# coded. -fbcit
+
+$debug and warn "Params are: filetype=$filetype, biblionumber=$biblionumber, uploadfile=$uploadfilename";
+
+=head1 NAME
+
+upload-cover-image.pl - Script for handling uploading of both single and bulk coverimages and importing them into the database.
+
+=head1 SYNOPSIS
+
+Copied from picture-upload.pl
+
+=head1 DESCRIPTION
+
+This script is called and presents the user with an interface allowing him/her to upload a single cover image or bulk cover images via a zip file.
+Files greater than 100K will be refused. Images should be 140x200 pixels. If they are larger they will be auto-resized to comply.
+
+=cut
+
+$debug and warn "Operation requested: $op";
+
+my ( $total, $handled, @counts, $tempfile, $tfh );
+
+if ( ($op eq 'Upload') && $uploadfile ) { # Case is important in these operational values as the template must use case to be visually pleasing!
+ my $dirname = File::Temp::tempdir( CLEANUP => 1);
+ $debug and warn "dirname = $dirname";
+ my $filesuffix = $1 if $uploadfilename =~ m/(\..+)$/i;
+ ( $tfh, $tempfile ) = File::Temp::tempfile( SUFFIX => $filesuffix, UNLINK => 1 );
+ $debug and warn "tempfile = $tempfile";
+ my ( @directories, $errors );
+
+ $errors{'NOTZIP'} = 1 if ( $uploadfilename !~ /\.zip$/i && $filetype =~ m/zip/i );
+ $errors{'NOWRITETEMP'} = 1 unless ( -w $dirname );
+ $errors{'EMPTYUPLOAD'} = 1 unless ( length( $uploadfile ) > 0 );
+
+ if ( %errors ) {
+ $template->param( ERRORS => [ \%errors ] );
+ } else {
+ while ( <$uploadfile> ) {
+ print $tfh $_;
+ }
+ close $tfh;
+ if ( $filetype eq 'zip' ) {
+ unless (system("unzip", $tempfile, '-d', $dirname) == 0) {
+ $errors{'UZIPFAIL'} = $uploadfilename;
+ $template->param( ERRORS => [ \%errors ] );
+ output_html_with_http_headers $input, $cookie, $template->output; # This error is fatal to the import, so bail out here
+ exit;
+ }
+ push @directories, "$dirname";
+ foreach $recursive_dir ( @directories ) {
+ opendir $dir, $recursive_dir;
+ while ( my $entry = readdir $dir ) {
+ push @directories, "$recursive_dir/$entry" if ( -d "$recursive_dir/$entry" and $entry !~ /^\./ );
+ $debug and warn "$recursive_dir/$entry";
+ }
+ closedir $dir;
+ }
+ my $results;
+ foreach my $dir ( @directories ) {
+ $results = handle_dir( $dir, $filesuffix );
+ $handled++ if $results == 1;
+ }
+ $total = scalar @directories;
+ } else { #if ($filetype eq 'zip' )
+ $results = handle_dir( $dirname, $filesuffix );
+ $handled = 1;
+ $total = 1;
+ }
+
+ if ( %$results || %errors ) {
+ $template->param( ERRORS => [ \%$results ] );
+ } else {
+ my $filecount;
+ map {$filecount += $_->{count}} @counts;
+ $debug and warn "Total directories processed: $total";
+ $debug and warn "Total files processed: $filecount";
+ $template->param(
+ TOTAL => $total,
+ HANDLED => $handled,
+ COUNTS => \@counts,
+ TCOUNTS => ($filecount > 0 ? $filecount : undef),
+ );
+ $template->param( biblionumber => $biblionumber ) if $biblionumber;
+ }
+ }
+} elsif ( ($op eq 'Upload') && !$uploadfile ) {
+ warn "Problem uploading file or no file uploaded.";
+ $template->param(biblionumber => $biblionumber);
+ $template->param(filetype => $filetype);
+} elsif ( $op eq 'Delete' ) {
+ my $dberror = RmBiblioImage($biblionumber);
+ $debug and warn "Cover image deleted for $biblionumber";
+ warn "Database returned $dberror" if $dberror;
+}
+
+output_html_with_http_headers $input, $cookie, $template->output;
+
+
+sub handle_dir {
+ my ( $dir, $suffix ) = @_;
+ my $source;
+ $debug and warn "Entering sub handle_dir; passed \$dir=$dir, \$suffix=$suffix";
+ if ($suffix =~ m/zip/i) { # If we were sent a zip file, process any included data/idlink.txt files
+ my ( $file, $filename, $biblionumber );
+ $debug and warn "Passed a zip file.";
+ opendir my $dirhandle, $dir;
+ while ( my $filename = readdir $dirhandle ) {
+ $file = "$dir/$filename" if ($filename =~ m/datalink\.txt/i || $filename =~ m/idlink\.txt/i);
+ }
+ unless (open (FILE, $file)) {
+ warn "Opening $dir/$file failed!";
+ $errors{'OPNLINK'} = $file;
+ return $errors; # This error is fatal to the import of this directory contents, so bail and return the error to the caller
+ };
+
+ while (my $line = ) {
+ $debug and warn "Reading contents of $file";
+ chomp $line;
+ $debug and warn "Examining line: $line";
+ my $delim = ($line =~ /\t/) ? "\t" : ($line =~ /,/) ? "," : "";
+ $debug and warn "Delimeter is \'$delim\'";
+ unless ( $delim eq "," || $delim eq "\t" ) {
+ warn "Unrecognized or missing field delimeter. Please verify that you are using either a ',' or a 'tab'";
+ $errors{'DELERR'} = 1; # This error is fatal to the import of this directory contents, so bail and return the error to the caller
+ return $errors;
+ }
+ ($biblionumber, $filename) = split $delim, $line;
+ $biblionumber =~ s/[\"\r\n]//g; # remove offensive characters
+ $filename =~ s/[\"\r\n\s]//g;
+ $debug and warn "Biblionumber: $biblionumber Filename: $filename";
+ $source = "$dir/$filename";
+ %counts = handle_file($biblionumber, $source, %counts);
+ }
+ close FILE;
+ closedir ($dirhandle);
+ } else {
+ $source = $tempfile;
+ %counts = handle_file($biblionumber, $source, %counts);
+ }
+push @counts, \%counts;
+return 1;
+}
+
+sub handle_file {
+ my ($biblionumber, $source, %count) = @_;
+ $debug and warn "Entering sub handle_file; passed \$biblionumber=$biblionumber, \$source=$source";
+ $count{filenames} = () if !$count{filenames};
+ $count{source} = $source if !$count{source};
+ if ($biblionumber && $source) { # Now process any imagefiles
+ my %filerrors;
+ my $filename;
+ if ($filetype eq 'image') {
+ $filename = $uploadfilename;
+ } else {
+ $filename = $1 if ($source =~ /\/([^\/]+)$/);
+ }
+ $debug and warn "Source: $source";
+ my $size = (stat($source))[7];
+ if ($size > 550000) { # This check is necessary even with image resizing to avoid possible security/performance issues...
+ $filerrors{'OVRSIZ'} = 1;
+ push my @filerrors, \%filerrors;
+ push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
+ $template->param( ERRORS => 1 );
+ return %count; # this one is fatal so bail here...
+ }
+ my ($srcimage, $image);
+ if (open (IMG, "$source")) {
+ $srcimage = GD::Image->new(*IMG);
+ close (IMG);
+ if (defined $srcimage) {
+ 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 ($width, $height) = $srcimage->getBounds();
+ $debug and warn "$filename is $width pix X $height pix.";
+ if ($width > 200 || $height > 300) { # MAX pixel dims are 200 X 300...
+ $debug and warn "$filename exceeds the maximum pixel dimensions of 200 X 300. Resizing...";
+ my $percent_reduce; # Percent we will reduce the image dimensions by...
+ if ($width > 200) {
+ $percent_reduce = sprintf("%.5f",(140/$width)); # If the width is oversize, scale based on width overage...
+ } else {
+ $percent_reduce = sprintf("%.5f",(200/$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 $filename by " . ($percent_reduce * 100) . "\% or to $width_reduce pix X $height_reduce pix";
+ $image = GD::Image->new($width_reduce, $height_reduce, 1); #'1' creates true color image...
+ $image->copyResampled($srcimage,0,0,0,0,$width_reduce,$height_reduce,$width,$height);
+ $imgfile = $image->png();
+ $debug and warn "$filename is " . length($imgfile) . " bytes after resizing.";
+ undef $image;
+ undef $srcimage; # This object can get big...
+ } else {
+ $image = $srcimage;
+ $imgfile = $image->png();
+ $debug and warn "$filename is " . length($imgfile) . " bytes.";
+ undef $image;
+ undef $srcimage; # This object can get big...
+ }
+ $debug and warn "Image is of mimetype $mimetype";
+ my $dberror = PutCoverImage($biblionumber,$mimetype, $imgfile) if $mimetype;
+ if ( !$dberror && $mimetype ) { # Errors from here on are fatal only to the import of a particular image, so don't bail, just note the error and keep going
+ $count{count}++;
+ push @{ $count{filenames} }, { source => $filename, biblionumber => $biblionumber };
+ } elsif ( $dberror ) {
+ warn "Database returned error: $dberror";
+ ($dberror =~ /coverimage_fk1/) ? $filerrors{'IMGEXISTS'} = 1 : $filerrors{'DBERR'} = 1;
+ push my @filerrors, \%filerrors;
+ push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
+ $template->param( ERRORS => 1 );
+ } elsif ( !$mimetype ) {
+ warn "Unable to determine mime type of $filename. Please verify mimetype.";
+ $filerrors{'MIMERR'} = 1;
+ push my @filerrors, \%filerrors;
+ push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
+ $template->param( ERRORS => 1 );
+ }
+ } else {
+ warn "Contents of $filename corrupted!";
+ # $count{count}--;
+ $filerrors{'CORERR'} = 1;
+ push my @filerrors, \%filerrors;
+ push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
+ $template->param( ERRORS => 1 );
+ }
+ } else {
+ warn "Opening $dir/$filename failed!";
+ $filerrors{'OPNERR'} = 1;
+ push my @filerrors, \%filerrors;
+ push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
+ $template->param( ERRORS => 1 );
+ }
+ } else { # The need for this seems a bit unlikely, however, to maximize error trapping it is included
+ warn "Missing " . ($biblionumber ? "filename" : ($filename ? "biblionumber" : "biblionumber and filename"));
+ $filerrors{'CRDFIL'} = ($biblionumber ? "filename" : ($filename ? "biblionumber" : "biblionumber and filename"));
+ push my @filerrors, \%filerrors;
+ push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, biblionumber => $biblionumber };
+ $template->param( ERRORS => 1 );
+ }
+ return (%count);
+}
+=head2 PutCoverImage
+
+ PutCoverImage($biblionumber, $mimetype, $imgfile);
+
+Stores cover binary image data and mimetype in database.
+NOTE: This function is good for updating images as well as inserting new images in the database.
+
+=cut
+
+sub PutCoverImage {
+ my ($biblionumber, $mimetype, $imgfile) = @_;
+ warn "Parameters passed in: Biblionumber=$biblionumber, Mimetype=$mimetype, " . ($imgfile ? "Imagefile" : "No Imagefile") if $debug;
+ my $dbh = C4::Context->dbh;
+ my $query = "INSERT INTO bibliocoverimage (biblionumber, mimetype, imagefile) VALUES (?,?,?) ON DUPLICATE KEY UPDATE imagefile = ?;";
+ my $sth = $dbh->prepare($query);
+ $sth->execute($biblionumber,$mimetype,$imgfile,$imgfile);
+ warn "Error returned inserting $biblionumber.$mimetype." if $sth->errstr;
+ return $sth->errstr;
+}
+
+=head2 RmCoverImage
+
+ my ($dberror) = RmCoverImage($biblionumber);
+
+Removes the image for the cover with the supplied biblionumber.
+
+=cut
+
+sub RmCoverImage {
+ my ($biblionumber) = @_;
+ warn "Biblionumber passed to RmBiblioImage is $biblionumber" if $debug;
+ my $dbh = C4::Context->dbh;
+ my $query = "DELETE FROM bibliocoverimage WHERE biblionumber = ?;";
+ my $sth = $dbh->prepare($query);
+ $sth->execute($biblionumber);
+ my $dberror = $sth->errstr;
+ warn "Database error!" if $sth->errstr;
+ return $dberror;
+}
+
+=head1 AUTHORS
+
+Copied from picture-upload.pl
+
+Database storage, single coverimage upload option, and extensive error trapping contributed by Chris Nighswonger cnighswonger foundations edu
+Image scaling/resizing contributed by the same.
+
+=cut
--
|