Bugzilla – Attachment 6699 Details for
Bug 1633
Add ability to take book cover images from local img db
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 1633: Add support for uploading images to Koha
Bug-1633-Add-support-for-uploading-images-to-Koha.patch (text/plain), 62.75 KB, created by
Jared Camins-Esakov
on 2011-12-10 19:27:24 UTC
(
hide
)
Description:
Bug 1633: Add support for uploading images to Koha
Filename:
MIME Type:
Creator:
Jared Camins-Esakov
Created:
2011-12-10 19:27:24 UTC
Size:
62.75 KB
patch
obsolete
>From 5a8e5b54faec0ab39883fa8ab06519fed1a93a09 Mon Sep 17 00:00:00 2001 >From: Jared Camins-Esakov <jcamins@cpbibliography.com> >Date: Sun, 6 Nov 2011 11:13:23 +0530 >Subject: [PATCH] Bug 1633: Add support for uploading images to Koha >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit >Content-Type: text/plain; charset="UTF-8" > >A frequently-requested feature for Koha, especially by special libraries, is the >ability to upload local cover images into Koha. This patch adds that ability. > >This counter-patch builds on the work by Koustubha Kale at Anant Corporation, >but adds the following additional features: >1. Moves the code for handling image retrieval/saving into the Koha namespace >2. The ability to have multiple cover images for a biblio >3. Handling for "full size" (800x600) and thumbnail-size (200x140) images >4. A separate image viewer page >5. Javascript-based handling of cover image placement for the cover images in > the OPAC (as opposed to static <img /> tags embedded into pages) >6. Local cover display in the staff client >7. Uploading images directly from the record view > >How to use/test : >Assign user permission to the user Tools > (upload_local_cover_images Upload >local cover images). In order to upload local images, login to the staff >client. Go to Home ⺠Tools ⺠Upload Cover Images. Here you can upload cover >images either singly or in bulk in the form of a zip file. If uploading singly, >click on image file, browse the image from your local disk, type in the biblio >number of the catalogue entry and press upload. If uploading in bulk as a zip >file, the zip file must contain (in addition to cover images) one text file named >either datalink.txt OR idlink.txt. This file should have mapping of biblionumber >to image file name in the zip one per line with comma or tab as delimiters. For >example: > >1, scanned_cover_image_of_bib_no_1.jpg >2, scanned_cover_image_of_bib_no_1.jpg > >Cover images will be resized to a large image of 800x600 and a thumbnail of >200x140. Depending on the setting of AllowMultipleCovers, it is possible to >upload multiple images for a single bibliographic record. However, even if >multiple covers are permitted, you have the option of replacing the existing >covers by checking the "Replace existing covers" option on the upload screen. > >1. The patch adds a menu link in Tools from where you can upload local cover > images >2. It adds a user permission to enable access control to this menu item under > Tools >3. It adds a system preference OPACLocalCoverImages under Enhanced Content. > This needs to be turned on to show local cover images in OPAC. > >Once you have uploaded local images, if you search for the biblio, the local >cover should show up in search as well as search detail pages in the OPAC, and >the details view in the Intranet. > >Koustubha Kale is working on another patch which will allow us to set a cover >image source priority in system preferences, and which will then gracefully >fail over to the next source if image is not available from the first choice >source. > >Detailed test plan: >1. Install update (database updates are in > installer/data/mysql/atomicupdate/local_cover_images.pl) >2. Enable LocalCoverImages and OPACLocalCoverImages in the Enhanced content > preferences screen >3. Upload an image of type GIF, JPEG, PNG, or XPM either from the "Local Cover > Image" tool and choosing "Image file" as its type and entering a valid > biblionumber, or by viewing a record and clicking the "Upload Image" option > under the Edit button in the toolbar >4. View the record in the Intranet and OPAC. The image should show up directly > in OPAC search results and details, and there should be an "Images" tab on > both the Intranet and the OPAC detail view >5. Upload another image and attach it to the same bibliographic record. >6. Confirm that the new image (only) shows up in the OPAC and Intranet >7. Change the AllowMultipleCovers to "Allow" in the Enhanced content preferences > screen >8. Add several images to a bibliographic record >9. Confirm that they all show up in the "Images" tab on the Intranet and OPAC > and only one shows up in the main display in the OPAC details and search > results pages >10. Create a zip file containing at least one image and a text file "idlink.txt" > with one or more lines that looks like this: > 1, filename.jpg > Replace the '1' with a valid biblionumber, and 'filename.jpg' with the name > of the image file you are adding to the zip file >11. Upload the zip file from the "Local Cover Image" tool (being sure to choose > "zip file" as the filetype) >12. Check that the image(s) have been attached to the appropriate bibliographic > record(s) > >Special thanks to Koustubha Kale and Anant Corporation for the initial >implementation of local cover images, and to Chris Nighswonger of Foundation >Bible College for his prior work on patron images. >--- > C4/Auth.pm | 5 +- > C4/UploadedFile.pm | 18 ++ > Koha/Images.pm | 149 +++++++++++++++++ > catalogue/detail.pl | 6 + > catalogue/image.pl | 111 +++++++++++++ > catalogue/imageviewer.pl | 51 ++++++ > .../data/mysql/atomicupdate/local_cover_images.pl | 20 +++ > .../data/mysql/en/mandatory/userpermissions.sql | 1 + > installer/data/mysql/kohastructure.sql | 15 ++ > installer/data/mysql/sysprefs.sql | 4 +- > .../intranet-tmpl/prog/en/css/staff-global.css | 3 + > .../intranet-tmpl/prog/en/includes/cat-toolbar.inc | 3 +- > .../prog/en/includes/doc-head-close.inc | 8 + > .../intranet-tmpl/prog/en/includes/tools-menu.inc | 3 + > koha-tmpl/intranet-tmpl/prog/en/js/localcovers.js | 44 +++++ > .../admin/preferences/enhanced_content.pref | 19 +++ > .../prog/en/modules/catalogue/detail.tt | 12 ++ > .../prog/en/modules/catalogue/imageviewer.tt | 43 +++++ > .../prog/en/modules/tools/tools-home.tt | 5 + > .../prog/en/modules/tools/upload-images.tt | 130 +++++++++++++++ > .../opac-tmpl/prog/en/includes/doc-head-close.inc | 9 + > koha-tmpl/opac-tmpl/prog/en/js/localcovers.js | 44 +++++ > koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt | 18 ++ > .../opac-tmpl/prog/en/modules/opac-imageviewer.tt | 43 +++++ > .../opac-tmpl/prog/en/modules/opac-results.tt | 2 + > opac/opac-detail.pl | 11 ++ > opac/opac-image.pl | 111 +++++++++++++ > opac/opac-imageviewer.pl | 51 ++++++ > opac/opac-search.pl | 4 + > tools/upload-cover-image.pl | 167 ++++++++++++++++++++ > 30 files changed, 1107 insertions(+), 3 deletions(-) > create mode 100644 Koha/Images.pm > create mode 100755 catalogue/image.pl > create mode 100755 catalogue/imageviewer.pl > create mode 100644 installer/data/mysql/atomicupdate/local_cover_images.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/js/localcovers.js > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt > create mode 100644 koha-tmpl/opac-tmpl/prog/en/js/localcovers.js > create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-imageviewer.tt > create mode 100755 opac/opac-image.pl > create mode 100755 opac/opac-imageviewer.pl > create mode 100755 tools/upload-cover-image.pl > >diff --git a/C4/Auth.pm b/C4/Auth.pm >index e360e10..2b997dd 100755 >--- a/C4/Auth.pm >+++ b/C4/Auth.pm >@@ -389,7 +389,9 @@ sub get_template_and_user { > virtualshelves => C4::Context->preference("virtualshelves"), > StaffSerialIssueDisplayCount => C4::Context->preference("StaffSerialIssueDisplayCount"), > NoZebra => C4::Context->preference('NoZebra'), >- EasyAnalyticalRecords => C4::Context->preference('EasyAnalyticalRecords'), >+ EasyAnalyticalRecords => C4::Context->preference('EasyAnalyticalRecords'), >+ LocalCoverImages => C4::Context->preference('LocalCoverImages'), >+ AllowMultipleCovers => C4::Context->preference('AllowMultipleCovers'), > ); > } > else { >@@ -494,6 +496,7 @@ sub get_template_and_user { > SyndeticsAwards => C4::Context->preference("SyndeticsAwards"), > SyndeticsSeries => C4::Context->preference("SyndeticsSeries"), > SyndeticsCoverImageSize => C4::Context->preference("SyndeticsCoverImageSize"), >+ OPACLocalCoverImages => C4::Context->preference("OPACLocalCoverImages"), > ); > > $template->param(OpacPublic => '1') if ($user || C4::Context->preference("OpacPublic")); >diff --git a/C4/UploadedFile.pm b/C4/UploadedFile.pm >index da29c1f..e8c9080 100644 >--- a/C4/UploadedFile.pm >+++ b/C4/UploadedFile.pm >@@ -159,6 +159,24 @@ sub name { > } > } > >+=head2 filename >+ >+ my $filename = $uploaded_file->filename(); >+ >+Accessor method for the name by which the file is to be known. >+ >+=cut >+ >+sub filename { >+ my $self = shift; >+ if (@_) { >+ $self->{'tmp_file_name'} = shift; >+ $self->_serialize(); >+ } else { >+ return $self->{'tmp_file_name'}; >+ } >+} >+ > =head2 max_size > > my $max_size = $uploaded_file->max_size(); >diff --git a/Koha/Images.pm b/Koha/Images.pm >new file mode 100644 >index 0000000..80ef437 >--- /dev/null >+++ b/Koha/Images.pm >@@ -0,0 +1,149 @@ >+package Koha::Images; >+use strict; >+use warnings; >+use 5.010; >+ >+use C4::Context; >+use GD; >+ >+use vars qw($debug $VERSION @ISA @EXPORT); >+ >+BEGIN { >+ # set the version for version checking >+ $VERSION = 3.03; >+ require Exporter; >+ @ISA = qw(Exporter); >+ @EXPORT = qw( >+ &PutImage >+ &RetrieveImage >+ &ListImagesForBiblio >+ &DelImage >+ ); >+ $debug = $ENV{KOHA_DEBUG} || $ENV{DEBUG} || 0; >+} >+ >+=head2 PutImage >+ >+ PutImage($biblionumber, $srcimage, $replace); >+ >+Stores binary image data and thumbnail in database, optionally replacing existing images for the given biblio. >+ >+=cut >+ >+sub PutImage { >+ my ($biblionumber, $srcimage, $replace) = @_; >+ >+ return -1 unless defined($srcimage); >+ >+ if ($replace) { >+ foreach (ListImagesForBiblio($biblionumber)) { >+ DelImage($_); >+ } >+ } >+ >+ my $dbh = C4::Context->dbh; >+ my $query = "INSERT INTO biblioimages (biblionumber, 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,$mimetype,$fullsize->png(),$thumbnail->png()); >+ my $dberror = $sth->errstr; >+ warn "Error returned inserting $biblionumber.$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 mimetype, imagefile, thumbnail FROM biblioimages WHERE imagenumber = ?'; >+ my $sth = $dbh->prepare($query); >+ $sth->execute($imagenumber); >+ my $imagedata = $sth->fetchrow_hashref; >+ warn "Database error!" if $sth->errstr; >+ return $imagedata, $sth->errstr; >+} >+ >+=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); >+ if (!$sth->errstr) { >+ while (my $row = $sth->fetchrow_hashref) { >+ push @imagenumbers, $row->{'imagenumber'}; >+ } >+ } >+ warn "Database error!" if $sth->errstr; >+ return @imagenumbers, $sth->errstr; >+} >+ >+=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; >+ } >+} >+ >+1; >diff --git a/catalogue/detail.pl b/catalogue/detail.pl >index 580949d..7719c77 100755 >--- a/catalogue/detail.pl >+++ b/catalogue/detail.pl >@@ -37,6 +37,7 @@ use C4::External::Amazon; > use C4::Search; # enabled_staff_search_views > use C4::VirtualShelves; > use C4::XSLT; >+use Koha::Images; > > # use Smart::Comments; > >@@ -379,6 +380,11 @@ if ( C4::Context->preference("AmazonEnabled") == 1 ) { > } > } > >+if ( C4::Context->preference("LocalCoverImages") == 1 ) { >+ my @images = ListImagesForBiblio($biblionumber); >+ $template->{VARS}->{localimages} = \@images; >+} >+ > # Get OPAC URL > if (C4::Context->preference('OPACBaseURL')){ > $template->param( OpacUrl => C4::Context->preference('OPACBaseURL') ); >diff --git a/catalogue/image.pl b/catalogue/image.pl >new file mode 100755 >index 0000000..8721299 >--- /dev/null >+++ b/catalogue/image.pl >@@ -0,0 +1,111 @@ >+#!/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; >+use Koha::Images; >+ >+$|=1; >+ >+my $DEBUG = 1; >+my $data = new CGI; >+my $imagenumber; >+ >+=head1 NAME >+ >+image.pl - Script for retrieving and formatting local cover images for display >+ >+=head1 SYNOPSIS >+ >+<img src="image.pl?imagenumber=X" /> >+<img src="image.pl?biblionumber=X" /> >+<img src="image.pl?imagenumber=X&thumbnail=1" /> >+<img src="image.pl?biblionumber=X&thumbnail=1" /> >+ >+=head1 DESCRIPTION >+ >+This script, when called from within HTML and passed a valid imagenumber or >+biblionumber, will retrieve the image data associated with that biblionumber >+if one exists, format it in proper HTML format and pass it back to be displayed. >+If the parameter thumbnail has been provided, a thumbnail will be returned >+rather than the full-size image. When a biblionumber is provided rather than an >+imagenumber, a random image is selected. >+ >+=cut >+ >+if (defined $data->param('imagenumber')) { >+ $imagenumber = $data->param('imagenumber'); >+} elsif (defined $data->param('biblionumber')) { >+ my @imagenumbers = ListImagesForBiblio($data->param('biblionumber')); >+ if (@imagenumbers) { >+ $imagenumber = $imagenumbers[0]; >+ } else { >+ warn "No images for this biblio" if $DEBUG; >+ error(); >+ } >+} else { >+ $imagenumber = shift; >+} >+ >+if ($imagenumber) { >+ warn "imagenumber passed in: $imagenumber" if $DEBUG; >+ my ($imagedata, $dberror) = RetrieveImage($imagenumber); >+ >+ if ($dberror) { >+ warn "Database Error!" if $DEBUG; >+ error(); >+ } >+ >+ if ($imagedata) { >+ my $image; >+ if ($data->param('thumbnail')) { >+ $image = $imagedata->{'thumbnail'}; >+ } else { >+ $image = $imagedata->{'imagefile'}; >+ } >+ print $data->header (-type => $imagedata->{'mimetype'}, -'Cache-Control' => 'no-store', -expires => 'now', -Content_Length => length ($image)), $image; >+ exit; >+ } else { >+ warn "No image exists for $imagenumber" if $DEBUG; >+ error(); >+ } >+} else { >+ error(); >+} >+ >+error(); >+ >+sub error { >+ print $data->header ( -status=> '404', -expires => 'now' ); >+ exit; >+} >+ >+=head1 AUTHOR >+ >+Chris Nighswonger cnighswonger <at> foundations <dot> edu >+ >+modified for local cover images by Koustubha Kale kmkale <at> anantcorp <dot> com >+ >+=cut >diff --git a/catalogue/imageviewer.pl b/catalogue/imageviewer.pl >new file mode 100755 >index 0000000..fae6243 >--- /dev/null >+++ b/catalogue/imageviewer.pl >@@ -0,0 +1,51 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 C & P Bibliography Services >+# >+# 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; >+use C4::Auth; >+use C4::Biblio; >+use C4::Output; >+use Koha::Images; >+ >+my $query = new CGI; >+my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { >+ template_name => "catalogue/imageviewer.tmpl", >+ query => $query, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { catalogue => 1 }, >+ } >+); >+ >+my $biblionumber = $query->param('biblionumber') || $query->param('bib'); >+my ($count, $biblio) = GetBiblio($biblionumber); >+ >+if (C4::Context->preference("LocalCoverImages")) { >+ my @images = ListImagesForBiblio($biblionumber); >+ $template->{VARS}->{'LocalCoverImages'} = 1; >+ $template->{VARS}->{'images'} = \@images; >+} >+ >+$template->{VARS}->{'biblio'} = $biblio; >+ >+output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/installer/data/mysql/atomicupdate/local_cover_images.pl b/installer/data/mysql/atomicupdate/local_cover_images.pl >new file mode 100644 >index 0000000..a698e7f >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/local_cover_images.pl >@@ -0,0 +1,20 @@ >+#! /usr/bin/perl >+use strict; >+use warnings; >+use C4::Context; >+my $dbh=C4::Context->dbh; >+ >+$dbh->do( q|CREATE TABLE `biblioimages` ( >+ `imagenumber` int(11) NOT NULL AUTO_INCREMENT, >+ `biblionumber` int(11) NOT NULL, >+ `mimetype` varchar(15) NOT NULL, >+ `imagefile` mediumblob NOT NULL, >+ `thumbnail` mediumblob NOT NULL, >+ PRIMARY KEY (`imagenumber`), >+ 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 images on OPAC search and details pages.','1','YesNo')|); >+$dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('LocalCoverImages','0','Display local cover images on intranet search and details pages.','1','YesNo')|); >+$dbh->do( q|INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('AllowMultipleCovers','0','Allow multiple cover images to be attached to each bibliographic record.','1','YesNo')|); >+$dbh->do( q|INSERT INTO permissions (module_bit, code, description) VALUES (13, 'upload_local_cover_images', 'Upload local cover images')|); >+print "Upgrade done (Added support for local cover images)\n"; >diff --git a/installer/data/mysql/en/mandatory/userpermissions.sql b/installer/data/mysql/en/mandatory/userpermissions.sql >index ec61ea0..873089a 100644 >--- a/installer/data/mysql/en/mandatory/userpermissions.sql >+++ b/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'), >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 452173d..7340eee 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -2667,6 +2667,21 @@ 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` ( >+ `imagenumber` int(11) NOT NULL AUTO_INCREMENT, >+ `biblionumber` int(11) NOT NULL, >+ `mimetype` varchar(15) NOT NULL, >+ `imagefile` mediumblob NOT NULL, >+ `thumbnail` mediumblob NOT NULL, >+ PRIMARY KEY (`imagenumber`), >+ 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 */; >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index ae2c1cb..99e88c1 100755 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -328,4 +328,6 @@ 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'); >+INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('LocalCoverImages','0','Display local cover images on intranet details pages.','1','YesNo'); >+INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('AllowMultipleCovers','0','Allow multiple cover images to be attached to each bibliographic record.','1','YesNo'); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css >index 7710eda..c1d4b43 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css >+++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css >@@ -2093,3 +2093,6 @@ div.pager input.pagedisplay { > font-weight: bold; > text-align : center; > } >+.localimage { >+ padding: .3em; >+} >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc >index 4b54c40..64f5c4c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc >@@ -101,7 +101,8 @@ function confirm_items_deletion() { > [% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Edit Record"), url: "/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[% biblionumber %]&frameworkcode=&op=" },[% END %] > [% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Edit Items"), url: "/cgi-bin/koha/cataloguing/additem.pl?biblionumber=[% biblionumber %]" },[% END %] > [% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Attach Item"), url: "/cgi-bin/koha/cataloguing/moveitem.pl?biblionumber=[% biblionumber %]" },[% END %] >- [% IF ( EasyAnalyticalRecords ) %][% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Link to Host Item"), url: "/cgi-bin/koha/cataloguing/linkitem.pl?biblionumber=[% biblionumber %]" },[% END %][% END %] >+ [% IF ( EasyAnalyticalRecords ) %][% IF ( CAN_user_editcatalogue_edit_items ) %]{ text: _("Link to Host Item"), url: "/cgi-bin/koha/cataloguing/linkitem.pl?biblionumber=[% biblionumber %]" },[% END %][% END %] >+ [% IF ( LocalCoverImages ) %][% IF ( CAN_user_tools_upload_local_cover_images ) %]{ text: _("Upload Image"), url: "/cgi-bin/koha/tools/upload-cover-image.pl?biblionumber=[% biblionumber %]&filetype=image" },[% END %][% END %] > [% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Edit as New (Duplicate)"), url: "/cgi-bin/koha/cataloguing/addbiblio.pl?biblionumber=[% biblionumber %]&frameworkcode=&op=duplicate" },[% END %] > [% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Replace Record via Z39.50"), onclick: {fn: PopupZ3950 } },[% END %] > [% IF ( CAN_user_editcatalogue_edit_catalogue ) %]{ text: _("Delete Record"), onclick: {fn: confirm_deletion }[% IF ( count ) %],id:'disabled'[% END %] },[% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc >index 6a2dae0..53f6843 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc >@@ -99,3 +99,11 @@ > [% IF ( virtualshelves || intranetbookbag ) %] > <script type="text/javascript" language="javascript" src="[% themelang %]/js/basket.js"></script> > [% END %] >+[% IF LocalCoverImages %] >+<script type="text/javascript" language="javascript" src="[% themelang %]/js/localcovers.js"></script> >+<script type="text/javascript" language="javascript"> >+//<![CDATA[ >+var NO_LOCAL_JACKET = _("No cover image available"); >+//]]> >+</script> >+[% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >index e3896cc..8a739d5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/tools-menu.inc >@@ -70,6 +70,9 @@ > [% IF ( CAN_user_tools_manage_staged_marc ) %] > <li><a href="/cgi-bin/koha/tools/manage-marc-import.pl">Staged MARC management</a></li> > [% END %] >+ [% IF ( CAN_user_tools_upload_local_cover_images ) %] >+ <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a></li> >+ [% END %] > </ul> > <h5>Additional Tools</h5> > <ul> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/localcovers.js b/koha-tmpl/intranet-tmpl/prog/en/js/localcovers.js >new file mode 100644 >index 0000000..981af75 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/js/localcovers.js >@@ -0,0 +1,44 @@ >+if (typeof KOHA == "undefined" || !KOHA) { >+ var KOHA = {}; >+} >+ >+/** >+ * A namespace for local cover related functions. >+ */ >+KOHA.LocalCover = { >+ >+ >+ /** >+ * Search all: >+ * <div title="biblionumber" id="isbn" class="openlibrary-thumbnail"></div> >+ * or >+ * <div title="biblionumber" id="isbn" class="openlibrary-thumbnail-preview"></div> >+ * and run a search with all collected isbns to Open Library Book Search. >+ * The result is asynchronously returned by OpenLibrary and catched by >+ * olCallBack(). >+ */ >+ GetCoverFromBibnumber: function(uselink) { >+ $("div [id^=local-thumbnail]").each(function(i) { >+ var mydiv = this; >+ var message = document.createElement("span"); >+ $(message).attr("class","no-image"); >+ $(message).html(NO_LOCAL_JACKET); >+ $(mydiv).append(message); >+ var img = $("<img />").attr('src', >+ '/cgi-bin/koha/catalogue/image.pl?thumbnail=1&biblionumber=' + $(mydiv).attr("class")) >+ .load(function () { >+ if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) { >+ } else { >+ if (uselink) { >+ var a = $("<a />").attr('href', '/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=' + $(mydiv).attr("class")); >+ $(a).append(img); >+ $(mydiv).append(a); >+ } else { >+ $(mydiv).append(img); >+ } >+ $(mydiv).children('.no-image').remove(); >+ } >+ }) >+ }); >+ } >+}; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref >index 171b5f4..f5828ae 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref >@@ -311,3 +311,22 @@ Enhanced Content: > - pref: TagsExternalDictionary > class: file > - on the server to be approved without moderation. >+ Local Cover Images: >+ - >+ - pref: LocalCoverImages >+ choices: >+ yes: Display >+ no: "Don't display" >+ - local cover images on intranet search and details pages. >+ - >+ - pref: OPACLocalCoverImages >+ choices: >+ yes: Display >+ no: "Don't display" >+ - local cover images on OPAC search and details pages. >+ - >+ - pref: AllowMultipleCovers >+ choices: >+ yes: Allow >+ no: "Don't allow" >+ - multiple images to be attached to each bibliographic record. >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >index 019fa10..9174d94 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >@@ -228,6 +228,7 @@ function verify_images() { > [% IF ( subscriptionsnumber ) %]<li><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber %]#subscriptions">Subscriptions</a></li>[% END %] > [% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber %]#editions">Editions</a></li>[% END %][% END %] > [% IF ( AmazonSimilarItems ) %]<li><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber %]#related">Related Titles</a></li>[% END %] >+[% IF ( LocalCoverImages ) %]<li><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber %]#images">Images</a></li>[% END %] > </ul> > > <div id="holdings"> >@@ -516,6 +517,17 @@ function verify_images() { > </div> > [% END %][% END %] > >+[% IF ( LocalCoverImages ) %] >+<div id="images"> >+<div>Click on an image to view it in the image viewer</div> >+[% FOREACH image IN localimages %] >+[% IF image %] >+<span class="localimage"><a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber %]&imagenumber=[% image %]"><img alt="img" src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&imagenumber=[% image %]" /></a></span> >+[% END %] >+[% END %] >+</div> >+[% END %] >+ > </div><!-- /bibliodetails --> > > <div class="yui-g" id="export" style="margin-top: 1em;"> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt >new file mode 100644 >index 0000000..c5ab657 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/imageviewer.tt >@@ -0,0 +1,43 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] Catalog › Images for: [% biblio.title |html %] >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/JavaScript" language="JavaScript"> >+//<![CDATA[ >+ >+$(document).ready(function(){ >+ showCover($('.thumbnail').attr('id')); >+}); >+ >+function showCover(img) { >+ $('.thumbnail').attr('class', 'thumbnail'); >+ $('#largeCoverImg').attr('src', '/cgi-bin/koha/catalogue/image.pl?imagenumber=' + img); >+ $('#' + img + '.thumbnail').attr('class', 'thumbnail selected'); >+} >+//]]> >+</script> >+<style type="text/css"> >+img.thumbnail { >+ border-style: solid; >+ border-width: 3px; >+ border-color: white; >+} >+ >+img.selected { >+ border-color: black; >+} >+</style> >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.tablesorter.min.js"></script> >+<body id="imageviewer"> >+<div id="largeCover"><img id="largeCoverImg" alt="Large view" /></div> >+[% IF LocalCoverImages == 1 %] >+[% FOREACH img IN images %] >+[% IF img %] >+<a href='#' onclick='showCover([% img %])'><img class='thumbnail' id='[% img %]' src='/cgi-bin/koha/catalogue/image.pl?imagenumber=[% img %]&thumbnail=1' alt='Image'/></a> >+[% END %] >+[% END %] >+[% biblio.title %] [% biblio.author %] >+[% ELSE %] >+Unfortunately, images are not enabled for this catalog at this time. >+[% END %] >+</body> >+</html> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt >index 05bdb47..b71a1ee 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt >@@ -140,6 +140,11 @@ > <dd>Managed staged MARC records, including completing and reversing imports</dd> > [% END %] > >+ [% IF ( CAN_user_tools_upload_local_cover_images ) %] >+ <dt><a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a></dt> >+ <dd>Utility to upload scanned cover images for display in OPAC</dd> >+ [% END %] >+ > </dl> > </div> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt >new file mode 100644 >index 0000000..1f1b964 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt >@@ -0,0 +1,130 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Tools › Upload Images</title> >+[% INCLUDE 'doc-head-close.inc' %] >+[% INCLUDE 'file-upload.inc' %] >+[% INCLUDE 'background-job.inc' %] >+<style type="text/css"> >+ #uploadpanel,#fileuploadstatus,#fileuploadfailed,#jobpanel,#jobstatus,#jobfailed { display : none; } >+ #fileuploadstatus,#jobstatus { margin:.4em; } >+ #fileuploadprogress,#jobprogress{ width:150px;height:10px;border:1px solid #666;background:url('/intranet-tmpl/prog/img/progress.png') -300px 0px no-repeat; }</style> >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function(){ >+ $("#processfile").hide(); >+ $("#zipfile").click(function(){ >+ $("#bibnum").hide(); >+ }); >+ $("#image").click(function(){ >+ $("#bibnum").show(); >+ }); >+}); >+function CheckForm(f) { >+ if ($("#fileToUpload").value == '') { >+ alert(_('Please upload a file first.')); >+ } else { >+ return submitBackgroundJob(f); >+ } >+ return false; >+} >+ >+//]]> >+</script> >+</head> >+<body> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'cat-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> › [% IF ( uploadimage ) %]<a href="/cgi-bin/koha/tools/upload-cover-image.pl">Upload Local Cover Image</a> › Upload Results[% ELSE %]Upload Local Cover Image[% END %]</div> >+ >+<div id="doc3" class="yui-t2"> >+ >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ >+<h1>Upload Local Cover Image</h1> >+[% IF ( uploadimage ) %] >+<p>Image upload results :</p> >+<ul> >+ <li>[% total %] images found</li> >+ [% IF ( error ) %] >+ <div class="dialog alert"> >+ [% IF ( error == 'UZIPFAIL' ) %]<p><b>Failed to unzip archive.<br />Please ensure you are uploading a valid zip file and try again.</b></p> >+ [% ELSIF ( error == 'OPNLINK' ) %]<p><b>Cannot open folder index (idlink.txt or datalink.txt) to read.<br />Please verify that it exists.</b></p> >+ [% ELSIF ( error == 'OPNIMG' ) %]<p><b>Cannot process file as an image.<br />Please ensure you only upload GIF, JPEG, PNG, or XPM images.</b></p> >+ [% ELSIF ( error == 'DELERR' ) %]<p><b>Unrecognized or missing field delimiter.<br />Please verify that you are using either a single quote or a tab.</b></p> >+ [% ELSIF ( error == 'DBERR' ) %]<p><b>Unable to save image to database.</b></p> >+ [% ELSE %]<p><b>An unknown error has occurred.<br />Please review the error log for more details.</b></p>[% END %] >+ </div> >+ </li> >+ [% END %] >+ <li><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber %]">View final record</a></li> >+ <li><a href="/cgi-bin/koha/tools/tools-home.pl">Back</a></li> >+</ul> >+<hr /> >+[% END %] >+<ul> >+ <li>Select an image file or ZIP file to upload. The tool will accept images in GIF, JPEG, PNG, and XPM formats.</li> >+</ul> >+<form method="post" action="[% SCRIPT_NAME %]" id="uploadfile" enctype="multipart/form-data"> >+<fieldset class="rows" id="uploadform"> >+<legend>Upload images</legend> >+<ol> >+ <li> >+ <div id="fileuploadform"> >+ <label for="fileToUpload">Select the file to upload: </label> >+ <input type="file" id="fileToUpload" name="fileToUpload" /> >+ </div> </li> >+</ol> >+ <fieldset class="action"><button class="submit" onclick="return ajaxFileUpload();">Upload file</button></fieldset> >+</fieldset> >+ >+ <div id="uploadpanel"><div id="fileuploadstatus">Upload progress: <div id="fileuploadprogress"></div> <span id="fileuploadpercent">0</span>%</div> >+ <div id="fileuploadfailed"></div></div> >+</form> >+ >+ <form method="post" id="processfile" action="[% SCRIPT_NAME %]" enctype="multipart/form-data"> >+<fieldset class="rows"> >+ <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" /> >+ <input type="hidden" name="runinbackground" id="runinbackground" value="" /> >+ <input type="hidden" name="completedJobID" id="completedJobID" value="" /> >+ </fieldset> >+ <fieldset class="rows"> >+ <legend>File type</legend> >+ <ol> >+ <li class="radio"> >+ <input type="radio" id="zipfile" name="filetype" value="zip" [% IF (filetype != 'image' ) %]checked="checked"[% END %] /> >+ <label for="zipfile">ZIP file</label> >+ </li> >+ <li class="radio"> >+ <input type="radio" id="image" name="filetype" value="image" [% IF (filetype == 'image' ) %]checked="checked"[% END %] /> >+ <label for="imagefile">Image file</label> >+ </li> >+ <li class="radio"> >+ [% IF ( filetype == 'image' ) %]<span id="bibnum">[% ELSE %]<span id="bibnum" style="display: none">[% END %]<label for="biblionumber">Enter cover biblionumber: </label><input type="text" id="biblionumber" name="biblionumber" value="[% biblionumber %]" size="15" /></span> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="rows"> >+ <legend>Options</legend> >+ <ol> >+ <li class="checkbox"> >+ <input type="checkbox" id="replace" name="replace" [% IF AllowMultipleCovers == 0 %]checked="checked" disabled="disabled"[% END %] /> >+ <label for="replace">Replace existing covers</label> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"><input type="submit" value="Process images" /></fieldset> >+ >+ <div id="jobpanel"><div id="jobstatus">Job progress: <div id="jobprogress"></div> <span id="jobprogresspercent">0</span>%</div> >+ <div id="jobfailed"></div></div> >+ >+</form> >+ >+</div> >+</div> >+<div class="yui-b"> >+[% INCLUDE 'tools-menu.inc' %] >+</div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc b/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc >index 15bea79..18e5917 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc >+++ b/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc >@@ -98,6 +98,15 @@ var NO_OL_JACKET = _("No cover image available"); > </script> > [% END %] > >+[% IF OPACLocalCoverImages %] >+<script type="text/javascript" language="javascript" src="[% themelang %]/js/localcovers.js"></script> >+<script type="text/javascript" language="javascript"> >+//<![CDATA[ >+var NO_LOCAL_JACKET = _("No cover image available"); >+//]]> >+</script> >+[% END %] >+ > [% IF ( BakerTaylorEnabled ) %]<script type="text/javascript" language="javascript" src="[% themelang %]/js/bakertaylorimages.js"></script> > <script type="text/javascript" language="javascript"> > //<![CDATA[ >diff --git a/koha-tmpl/opac-tmpl/prog/en/js/localcovers.js b/koha-tmpl/opac-tmpl/prog/en/js/localcovers.js >new file mode 100644 >index 0000000..298a20e >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/prog/en/js/localcovers.js >@@ -0,0 +1,44 @@ >+if (typeof KOHA == "undefined" || !KOHA) { >+ var KOHA = {}; >+} >+ >+/** >+ * A namespace for local cover related functions. >+ */ >+KOHA.LocalCover = { >+ >+ >+ /** >+ * Search all: >+ * <div title="biblionumber" id="isbn" class="openlibrary-thumbnail"></div> >+ * or >+ * <div title="biblionumber" id="isbn" class="openlibrary-thumbnail-preview"></div> >+ * and run a search with all collected isbns to Open Library Book Search. >+ * The result is asynchronously returned by OpenLibrary and catched by >+ * olCallBack(). >+ */ >+ GetCoverFromBibnumber: function(uselink) { >+ $("div [id^=local-thumbnail]").each(function(i) { >+ var mydiv = this; >+ var message = document.createElement("span"); >+ $(message).attr("class","no-image"); >+ $(message).html(NO_LOCAL_JACKET); >+ $(mydiv).append(message); >+ var img = $("<img />").attr('src', >+ '/cgi-bin/koha/opac-image.pl?thumbnail=1&biblionumber=' + $(mydiv).attr("class")) >+ .load(function () { >+ if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) { >+ } else { >+ if (uselink) { >+ var a = $("<a />").attr('href', '/cgi-bin/koha/opac-imageviewer.pl?biblionumber=' + $(mydiv).attr("class")); >+ $(a).append(img); >+ $(mydiv).append(a); >+ } else { >+ $(mydiv).append(img); >+ } >+ $(mydiv).children('.no-image').remove(); >+ } >+ }) >+ }); >+ } >+}; >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt >index 3175d47..fc2da3f 100755 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt >@@ -39,6 +39,9 @@ > [% IF OpenLibraryCovers %] > KOHA.OpenLibrary.GetCoverFromIsbn(); > [% END %] >+ [% IF OPACLocalCoverImages %] >+ KOHA.LocalCover.GetCoverFromBibnumber(true); >+ [% END %] > [% IF ( NovelistSelectProfile ) %] > novSelect.loadContentForISBN('[% normalized_isbn %]','[% NovelistSelectProfile %]', '[% NovelistSelectPassword %]', function(d){}); > [% END %] >@@ -224,6 +227,7 @@ YAHOO.util.Event.onContentReady("furtherm", function () { > <div id="catalogue_detail_biblio"> > > <div id="bookcover"> >+ [% IF ( OPACLocalCoverImages ) %]<div style="block" title="[% biblionumber |url %]" class="[% biblionumber %]" id="local-thumbnail-preview"></div>[% END %] > [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( OPACurlOpenInNewWindow ) %]<a href="http://www.amazon[% AmazonTld %]/gp/reader/[% normalized_isbn %]/ref=sib_dp_pt/002-7879865-0184864#reader-link" target="_blank"><img border="0" src="http://images.amazon.com/images/P/[% normalized_isbn %].01.MZZZZZZZ.jpg" alt="Cover Image" /></a>[% ELSE %]<a href="http://www.amazon[% AmazonTld %]/gp/reader/[% normalized_isbn %]/ref=sib_dp_pt/002-7879865-0184864#reader-link"><img border="0" src="http://images.amazon.com/images/P/[% normalized_isbn %].01.MZZZZZZZ.jpg" alt="Cover Image" /></a>[% END %][% END %][% END %] > > [% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( content_identifier_exists ) %][% IF ( using_https ) %] >@@ -543,6 +547,8 @@ YAHOO.util.Event.onContentReady("furtherm", function () { > [% ELSE %]<li>[% END %] > <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% biblionumber %]#serialcollection">Serial Collection</a></li> > [% END %] >+ >+ [% IF ( OPACLocalCoverImages ) %]<li><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% biblionumber %]#images">Images</a></li>[% END %] > </ul> > > [% IF ( serialcollection ) %] >@@ -979,6 +985,18 @@ YAHOO.util.Event.onContentReady("furtherm", function () { > [% END %] > > >+[% IF ( OPACLocalCoverImages ) %] >+<div id="images"> >+<div>Click on an image to view it in the image viewer</div> >+[% FOREACH image IN localimages %] >+[% IF image %] >+<span class="localimage"><a href="/cgi-bin/koha/opac-imageviewer.pl?biblionumber=[% biblionumber %]&imagenumber=[% image %]"><img alt="img" src="/cgi-bin/koha/opac-image.pl?thumbnail=1&imagenumber=[% image %]" /></a></span> >+[% END %] >+[% END %] >+</div> >+[% END %] >+ >+ > </div> > [% IF ( NovelistSelectProfile ) %][% IF ( NovelistSelectView == 'below' ) %] > <div id="NovelistSelect"> >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-imageviewer.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-imageviewer.tt >new file mode 100644 >index 0000000..d6633e1 >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-imageviewer.tt >@@ -0,0 +1,43 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha Online[% END %] Catalog › Images for: [% biblio.title |html %] >+[% INCLUDE 'doc-head-close.inc' %] >+<script type="text/JavaScript" language="JavaScript"> >+//<![CDATA[ >+ >+$(document).ready(function(){ >+ showCover($('.thumbnail').attr('id')); >+}); >+ >+function showCover(img) { >+ $('.thumbnail').attr('class', 'thumbnail'); >+ $('#largeCoverImg').attr('src', '/cgi-bin/koha/opac-image.pl?imagenumber=' + img); >+ $('#' + img + '.thumbnail').attr('class', 'thumbnail selected'); >+} >+//]]> >+</script> >+<style type="text/css"> >+img.thumbnail { >+ border-style: solid; >+ border-width: 3px; >+ border-color: white; >+} >+ >+img.selected { >+ border-color: black; >+} >+</style> >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.tablesorter.min.js"></script> >+<body id="opac-imageviewer"> >+<div id="largeCover"><img id="largeCoverImg" alt="Large view" /></div> >+[% IF OPACLocalCoverImages == 1 %] >+[% FOREACH img IN images %] >+[% IF img %] >+<a href='#' onclick='showCover([% img %])'><img class='thumbnail' id='[% img %]' src='/cgi-bin/koha/opac-image.pl?imagenumber=[% img %]&thumbnail=1' alt='Image'/></a> >+[% END %] >+[% END %] >+[% biblio.title %] [% biblio.author %] >+[% ELSE %] >+Unfortunately, images are not enabled for this catalog at this time. >+[% END %] >+</body> >+</html> >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt >index 7201a82..2565c8f 100755 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tt >@@ -229,6 +229,7 @@ $(document).ready(function(){ > [% END %] > [% END %][% END %] > [% IF OpenLibraryCovers %]KOHA.OpenLibrary.GetCoverFromIsbn();[% END %] >+ [% IF OPACLocalCoverImages %]KOHA.LocalCover.GetCoverFromBibnumber(false);[% END %] > [% IF ( GoogleJackets ) %]KOHA.Google.GetCoverFromIsbn();[% END %] > }); > //]]> >@@ -528,6 +529,7 @@ $(document).ready(function(){ > </span> > </td><td> > <a class="p1" href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% SEARCH_RESULT.biblionumber %]"> >+ [% IF ( OPACLocalCoverImages ) %]<div style="block" title="[% SEARCH_RESULT.biblionumber |url %]" class="[% SEARCH_RESULT.biblionumber %]" id="local-thumbnail[% loop.count %]"></div>[% END %] > [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonCoverImages ) %][% IF ( SEARCH_RESULT.normalized_isbn ) %]<img src="http://images.amazon.com/images/P/[% SEARCH_RESULT.normalized_isbn %].01.TZZZZZZZ.jpg" alt="" class="thumbnail" />[% ELSE %]<span class="no-image">No cover image available</span>[% END %][% END %][% END %] > > [% IF ( SyndeticsEnabled ) %][% IF ( SyndeticsCoverImages ) %][% IF ( using_https ) %] >diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl >index f82dde2..714ea24 100755 >--- a/opac/opac-detail.pl >+++ b/opac/opac-detail.pl >@@ -45,6 +45,7 @@ use C4::Charset; > use MARC::Record; > use MARC::Field; > use List::MoreUtils qw/any none/; >+use Koha::Images; > > BEGIN { > if (C4::Context->preference('BakerTaylorEnabled')) { >@@ -686,6 +687,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() ); >@@ -911,4 +917,9 @@ my $defaulttab = > ? 'serialcollection' : 'subscription'; > $template->param('defaulttab' => $defaulttab); > >+if (C4::Context->preference('OPACLocalCoverImages') == 1) { >+ my @images = ListImagesForBiblio($biblionumber); >+ $template->{VARS}->{localimages} = \@images; >+} >+ > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/opac/opac-image.pl b/opac/opac-image.pl >new file mode 100755 >index 0000000..de44152 >--- /dev/null >+++ b/opac/opac-image.pl >@@ -0,0 +1,111 @@ >+#!/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; >+use Koha::Images; >+ >+$|=1; >+ >+my $DEBUG = 1; >+my $data = new CGI; >+my $imagenumber; >+ >+=head1 NAME >+ >+opac-image.pl - Script for retrieving and formatting local cover images for display >+ >+=head1 SYNOPSIS >+ >+<img src="opac-image.pl?imagenumber=X" /> >+<img src="opac-image.pl?biblionumber=X" /> >+<img src="opac-image.pl?imagenumber=X&thumbnail=1" /> >+<img src="opac-image.pl?biblionumber=X&thumbnail=1" /> >+ >+=head1 DESCRIPTION >+ >+This script, when called from within HTML and passed a valid imagenumber or >+biblionumber, will retrieve the image data associated with that biblionumber >+if one exists, format it in proper HTML format and pass it back to be displayed. >+If the parameter thumbnail has been provided, a thumbnail will be returned >+rather than the full-size image. When a biblionumber is provided rather than an >+imagenumber, a random image is selected. >+ >+=cut >+ >+if (defined $data->param('imagenumber')) { >+ $imagenumber = $data->param('imagenumber'); >+} elsif (defined $data->param('biblionumber')) { >+ my @imagenumbers = ListImagesForBiblio($data->param('biblionumber')); >+ if (@imagenumbers) { >+ $imagenumber = $imagenumbers[0]; >+ } else { >+ warn "No images for this biblio" if $DEBUG; >+ error(); >+ } >+} else { >+ $imagenumber = shift; >+} >+ >+if ($imagenumber) { >+ warn "imagenumber passed in: $imagenumber" if $DEBUG; >+ my ($imagedata, $dberror) = RetrieveImage($imagenumber); >+ >+ if ($dberror) { >+ warn "Database Error!" if $DEBUG; >+ error(); >+ } >+ >+ if ($imagedata) { >+ my $image; >+ if ($data->param('thumbnail')) { >+ $image = $imagedata->{'thumbnail'}; >+ } else { >+ $image = $imagedata->{'imagefile'}; >+ } >+ print $data->header (-type => $imagedata->{'mimetype'}, -'Cache-Control' => 'no-store', -expires => 'now', -Content_Length => length ($image)), $image; >+ exit; >+ } else { >+ warn "No image exists for $imagenumber" if $DEBUG; >+ error(); >+ } >+} else { >+ error(); >+} >+ >+error(); >+ >+sub error { >+ print $data->header ( -status=> '404', -expires => 'now' ); >+ exit; >+} >+ >+=head1 AUTHOR >+ >+Chris Nighswonger cnighswonger <at> foundations <dot> edu >+ >+modified for local cover images by Koustubha Kale kmkale <at> anantcorp <dot> com >+ >+=cut >diff --git a/opac/opac-imageviewer.pl b/opac/opac-imageviewer.pl >new file mode 100755 >index 0000000..6d2f326 >--- /dev/null >+++ b/opac/opac-imageviewer.pl >@@ -0,0 +1,51 @@ >+#!/usr/bin/perl >+ >+# Copyright 2011 C & P Bibliography Services >+# >+# 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; >+use C4::Auth; >+use C4::Biblio; >+use C4::Output; >+use Koha::Images; >+ >+my $query = new CGI; >+my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { >+ template_name => "opac-imageviewer.tmpl", >+ query => $query, >+ type => "opac", >+ authnotrequired => ( C4::Context->preference("OpacPublic") ? 1 : 0 ), >+ flagsrequired => { borrow => 1 }, >+ } >+); >+ >+my $biblionumber = $query->param('biblionumber') || $query->param('bib'); >+my ($count, $biblio) = GetBiblio($biblionumber); >+ >+if (C4::Context->preference("OPACLocalCoverImages")) { >+ my @images = ListImagesForBiblio($biblionumber); >+ $template->{VARS}->{'OPACLocalCoverImages'} = 1; >+ $template->{VARS}->{'images'} = \@images; >+} >+ >+$template->{VARS}->{'biblio'} = $biblio; >+ >+output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/opac/opac-search.pl b/opac/opac-search.pl >index 42eb0ec..365bd72 100755 >--- a/opac/opac-search.pl >+++ b/opac/opac-search.pl >@@ -612,6 +612,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 >diff --git a/tools/upload-cover-image.pl b/tools/upload-cover-image.pl >new file mode 100755 >index 0000000..af45cbc >--- /dev/null >+++ b/tools/upload-cover-image.pl >@@ -0,0 +1,167 @@ >+#!/usr/bin/perl >+# >+# Copyright 2011 C & P Bibliography Services >+# >+# 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 >+# >+# >+# >+=head1 NAME >+ >+upload-cover-image.pl - Script for handling uploading of both single and bulk coverimages and importing them into the database. >+ >+=head1 SYNOPSIS >+ >+upload-cover-image.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 >+ >+ >+use strict; >+use warnings; >+ >+use File::Temp; >+use CGI; >+use GD; >+use C4::Context; >+use C4::Auth; >+use C4::Output; >+use Koha::Images; >+use C4::UploadedFile; >+ >+my $debug = 1; >+ >+my $input = new CGI; >+ >+my $fileID=$input->param('uploadedfileid'); >+my ($template, $loggedinuser, $cookie) >+ = get_template_and_user({template_name => "tools/upload-images.tmpl", >+ query => $input, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { tools => 'upload_cover_images'}, >+ debug => 0, >+ }); >+ >+my $filetype = $input->param('filetype'); >+my $biblionumber = $input->param('biblionumber'); >+my $uploadfilename = $input->param('uploadfile'); >+my $replace = $input->param('replace'); >+my $op = $input->param('op'); >+my %cookies = parse CGI::Cookie($cookie); >+my $sessionID = $cookies{'CGISESSID'}->value; >+ >+my $error; >+ >+$template->{VARS}->{'filetype'} = $filetype; >+$template->{VARS}->{'biblionumber'} = $biblionumber; >+ >+my $total = 0; >+ >+if ($fileID) { >+ my $uploaded_file = C4::UploadedFile->fetch($sessionID, $fileID); >+ if ($filetype eq 'image') { >+ my $fh = $uploaded_file->fh(); >+ my $srcimage = GD::Image->new($fh); >+ if (defined $srcimage) { >+ my $dberror = PutImage($biblionumber, $srcimage, $replace); >+ if ($dberror) { >+ $error = 'DBERR'; >+ } else { >+ $total = 1; >+ } >+ } else { >+ $error = 'OPNIMG'; >+ } >+ undef $srcimage; >+ } else { >+ my $filename = $uploaded_file->filename(); >+ my $dirname = File::Temp::tempdir( CLEANUP => 1); >+ unless (system("unzip", $filename, '-d', $dirname) == 0) { >+ $error = 'UZIPFAIL'; >+ } else { >+ my @directories; >+ push @directories, "$dirname"; >+ foreach my $recursive_dir ( @directories ) { >+ my $dir; >+ opendir $dir, $recursive_dir; >+ while ( my $entry = readdir $dir ) { >+ push @directories, "$recursive_dir/$entry" if ( -d "$recursive_dir/$entry" and $entry !~ /^[._]/ ); >+ } >+ closedir $dir; >+ } >+ foreach my $dir ( @directories ) { >+ my $file; >+ if ( -e "$dir/idlink.txt" ) { >+ $file = "$dir/idlink.txt"; >+ } elsif ( -e "$dir/datalink.txt" ) { >+ $file = "$dir/datalink.txt"; >+ } else { >+ next; >+ } >+ if (open (FILE, $file)) { >+ while (my $line = <FILE>) { >+ 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'"; >+ $error = 'DELERR'; >+ } else { >+ ($biblionumber, $filename) = split $delim, $line; >+ $biblionumber =~ s/[\"\r\n]//g; # remove offensive characters >+ $filename =~ s/[\"\r\n\s]//g; >+ my $srcimage = GD::Image->new("$dir/$filename"); >+ if (defined $srcimage) { >+ $total++; >+ my $dberror = PutImage($biblionumber, $srcimage, $replace); >+ if ($dberror) { >+ $error = 'DBERR'; >+ } >+ } else { >+ $error = 'OPNIMG'; >+ } >+ undef $srcimage; >+ } >+ } >+ close(FILE); >+ } else { >+ $error = 'OPNLINK'; >+ } >+ } >+ } >+ } >+ $template->{VARS}->{'total'} = $total; >+ $template->{VARS}->{'uploadimage'} = 1; >+ $template->{VARS}->{'error'} = $error; >+ $template->{VARS}->{'biblionumber'} = $biblionumber; >+} >+ >+output_html_with_http_headers $input, $cookie, $template->output; >+ >+exit 0; >+ >+=head1 AUTHORS >+ >+Written by Jared Camins-Esakov of C & P Bibliography Services, in part based on >+code by Koustubha Kale of Anant Corporation and Chris Nighswonger of Foundation >+Bible College. >+ >+=cut >-- >1.7.2.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 1633
:
6242
|
6699
|
6706
|
6712
|
6745
|
6746
|
6747
|
6748
|
6749
|
6750
|
6755
|
6756
|
6758
|
6759
|
6764
|
6765
|
6766
|
6785
|
6786
|
6787
|
6788
|
6791
|
6823
|
6973
|
6974
|
6975
|
6976
|
6977
|
6978
|
6979
|
6980
|
6981
|
6982
|
6983
|
7146
|
7147
|
7148
|
7149
|
7150
|
7151
|
7152
|
7153
|
7156
|
7219
|
7267
|
7268
|
7270
|
7271
|
7272
|
7273
|
7274
|
7275
|
7312
|
7315
|
7320
|
7324
|
7325
|
7334