View | Details | Raw Unified | Return to bug 17650
Collapse All | Expand All

(-)a/C4/Images.pm (-14 / +69 lines)
Lines 24-29 use 5.010; Link Here
24
24
25
use C4::Context;
25
use C4::Context;
26
use GD;
26
use GD;
27
use Koha::Upload;
28
29
use File::Path qw(make_path);
27
30
28
use vars qw($debug $noimage @ISA @EXPORT);
31
use vars qw($debug $noimage @ISA @EXPORT);
29
32
Lines 54-60 Stores binary image data and thumbnail in database, optionally replacing existin Link Here
54
=cut
57
=cut
55
58
56
sub PutImage {
59
sub PutImage {
57
    my ( $biblionumber, $srcimage, $replace ) = @_;
60
    my ( $biblionumber, $srcimage, $replace, $uploadedfileid ) = @_;
58
61
59
    return -1 unless defined($srcimage);
62
    return -1 unless defined($srcimage);
60
63
Lines 66-90 sub PutImage { Link Here
66
69
67
    my $dbh = C4::Context->dbh;
70
    my $dbh = C4::Context->dbh;
68
    my $query =
71
    my $query =
69
"INSERT INTO biblioimages (biblionumber, mimetype, imagefile, thumbnail) VALUES (?,?,?,?);";
72
"INSERT INTO biblioimages (biblionumber, mimetype, imagefile, thumbnail, uploadedfileid) VALUES (?,?,?,?,?);";
70
    my $sth = $dbh->prepare($query);
73
    my $sth = $dbh->prepare($query);
71
74
72
    my $mimetype = 'image/png'
75
    my $mimetype = 'image/png'
73
      ; # GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to PNG which is lossless...
76
      ; # GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to PNG which is lossless...
77
    if( defined $uploadedfileid){
78
        $sth->execute( $biblionumber, $mimetype, undef, undef, $uploadedfileid );
79
    }else{
80
        # Check the pixel size of the image we are about to import...
81
        my $thumbnail = _scale_image( $srcimage, 140, 200 )
82
          ;    # MAX pixel dims are 140 X 200 for thumbnail...
83
        my $fullsize = _scale_image( $srcimage, 600, 800 )
84
          ;    # MAX pixel dims are 600 X 800 for full-size image...
85
        $debug and warn "thumbnail is " . length($thumbnail) . " bytes.";
86
87
        $sth->execute( $biblionumber, $mimetype, $fullsize->png(),
88
            $thumbnail->png(), $uploadedfileid );
89
        undef $thumbnail;
90
        undef $fullsize;
91
    }
74
92
75
    # Check the pixel size of the image we are about to import...
76
    my $thumbnail = _scale_image( $srcimage, 140, 200 )
77
      ;    # MAX pixel dims are 140 X 200 for thumbnail...
78
    my $fullsize = _scale_image( $srcimage, 600, 800 )
79
      ;    # MAX pixel dims are 600 X 800 for full-size image...
80
    $debug and warn "thumbnail is " . length($thumbnail) . " bytes.";
81
82
    $sth->execute( $biblionumber, $mimetype, $fullsize->png(),
83
        $thumbnail->png() );
84
    my $dberror = $sth->errstr;
93
    my $dberror = $sth->errstr;
85
    warn "Error returned inserting $biblionumber.$mimetype." if $sth->errstr;
94
    warn "Error returned inserting $biblionumber.$mimetype." if $sth->errstr;
86
    undef $thumbnail;
87
    undef $fullsize;
88
    return $dberror;
95
    return $dberror;
89
}
96
}
90
97
Lines 100-119 sub RetrieveImage { Link Here
100
107
101
    my $dbh = C4::Context->dbh;
108
    my $dbh = C4::Context->dbh;
102
    my $query =
109
    my $query =
103
'SELECT imagenumber, mimetype, imagefile, thumbnail FROM biblioimages WHERE imagenumber = ?';
110
'SELECT imagenumber, mimetype, imagefile, thumbnail, uploadedfileid FROM biblioimages WHERE imagenumber = ?';
104
    my $sth = $dbh->prepare($query);
111
    my $sth = $dbh->prepare($query);
105
    $sth->execute($imagenumber);
112
    $sth->execute($imagenumber);
106
    my $imagedata = $sth->fetchrow_hashref;
113
    my $imagedata = $sth->fetchrow_hashref;
107
    if ( !$imagedata ) {
114
    if ( !$imagedata ) {
108
        $imagedata->{'thumbnail'} = $noimage;
115
        $imagedata->{'thumbnail'} = $noimage;
109
        $imagedata->{'imagefile'} = $noimage;
116
        $imagedata->{'imagefile'} = $noimage;
117
    }else{
118
        if (defined $imagedata->{'uploadedfileid'}){
119
            my ($thumbnail, $imagefile) = _retrieve_thumbs_images($imagedata->{'uploadedfileid'});
120
            $imagedata->{'thumbnail'} = $thumbnail;    # MAX pixel dims are 140 X 200 for thumbnail...
121
            $imagedata->{'imagefile'} = $imagefile;
122
123
        }
110
    }
124
    }
125
111
    if ( $sth->err ) {
126
    if ( $sth->err ) {
112
        warn "Database error!" if $debug;
127
        warn "Database error!" if $debug;
113
    }
128
    }
114
    return $imagedata;
129
    return $imagedata;
115
}
130
}
116
131
132
sub _retrieve_thumbs_images {
133
    my ($uploadedfileid) = @_;
134
    my $thumbnail_name = '140_200.png';
135
    my $imagefile_name = '600_800.png';
136
    my $temp_directory = "/tmp/koha_thumbs_$uploadedfileid";
137
    my $files_exists = 0;
138
    #Check if the uploaded file id exists on the temp directory.
139
    #Check if a temp dir exists.
140
    if ( -d $temp_directory){
141
        if ( -e "$temp_directory/$thumbnail_name" && -e "$temp_directory/$imagefile_name"){
142
            $files_exists = 1;
143
        }
144
    }else{
145
        make_path("/tmp/koha_thumbs_$uploadedfileid");
146
    }
147
    my $thumbnail;
148
    my $imagefile;
149
    if($files_exists){
150
        $thumbnail = GD::Image->new("$temp_directory/$thumbnail_name")->png();
151
        $imagefile = GD::Image->new("$temp_directory/$imagefile_name")->png();
152
    }else{
153
        # There is none temp files, create them.
154
        my $upload = Koha::Upload->new->get({ id => $uploadedfileid, filehandle => 1 });
155
        my $srcimage = GD::Image->new($upload->{fh});
156
        $thumbnail = _scale_image( $srcimage, 140, 200 )->png();
157
        $imagefile = _scale_image( $srcimage, 600, 800 )->png();
158
        warn "$temp_directory/$thumbnail_name";
159
        open( IMAGE, ">$temp_directory/$thumbnail_name");
160
        binmode( IMAGE );
161
        print IMAGE $thumbnail;
162
        close IMAGE;
163
        warn "$temp_directory/$imagefile_name";
164
        open( IMAGE2, ">$temp_directory/$imagefile_name");
165
        binmode( IMAGE2 );
166
        print IMAGE2 $imagefile;
167
        close IMAGE2;
168
    }
169
    return ($thumbnail, $imagefile);
170
}
171
117
=head2 ListImagesForBiblio
172
=head2 ListImagesForBiblio
118
    my (@images) = ListImagesForBiblio($biblionumber);
173
    my (@images) = ListImagesForBiblio($biblionumber);
119
174
(-)a/installer/data/mysql/atomicupdate/bug_17650_save_cover_to_hd.sql (+16 lines)
Line 0 Link Here
1
ALTER TABLE `biblioimages`
2
DROP FOREIGN KEY `bibliocoverimage_fk1`;
3
ALTER TABLE `biblioimages`
4
CHANGE COLUMN `imagefile` `imagefile` MEDIUMBLOB NULL DEFAULT NULL ,
5
CHANGE COLUMN `thumbnail` `thumbnail` MEDIUMBLOB NULL DEFAULT NULL ,
6
ADD COLUMN `uploadedfileid` INT(11) NULL DEFAULT NULL AFTER `thumbnail`,
7
ADD INDEX `bibliocoverimage_fk2_idx` (`uploadedfileid` ASC);
8
ALTER TABLE `biblioimages`
9
ADD CONSTRAINT `bibliocoverimage_fk2`
10
  FOREIGN KEY (`uploadedfileid`)
11
  REFERENCES `uploaded_files` (`id`)
12
  ON DELETE CASCADE
13
  ON UPDATE CASCADE;
14
15
16
INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES ('SaveCoverOnDisk','0','','Save the covers on the the hard disk instead of the database.','YesNo');
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref (+6 lines)
Lines 316-321 Enhanced Content: Link Here
316
                  yes: Allow
316
                  yes: Allow
317
                  no: "Don't allow"
317
                  no: "Don't allow"
318
            - multiple images to be attached to each bibliographic record.
318
            - multiple images to be attached to each bibliographic record.
319
        -
320
            - pref: SaveCoverOnDisk
321
              choices:
322
                  yes: "Yes"
323
                  no: "No"
324
            - Save the covers on the the hard disk instead of the database.
319
    HTML5 Media:
325
    HTML5 Media:
320
        -
326
        -
321
            - Show a tab with a HTML5 media player for files catalogued in field 856
327
            - Show a tab with a HTML5 media player for files catalogued in field 856
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/file-search.tt (+29 lines)
Line 0 Link Here
1
[% USE Koha %]
2
<table>
3
	<thead>
4
		<tr>
5
		    <th>Filename</th>
6
		    <th>Size</th>
7
		    <th>Hashvalue</th>
8
		    <th>Category</th>
9
		    <th>Public</th>
10
		    <th>Temporary</th>
11
		    <th>Actions</th>
12
		</tr>
13
	</thead>
14
	<tbody>
15
		[% FOREACH record IN uploads %]
16
		<tr>
17
		    <td>[% record.name %]</td>
18
		    <td>[% record.filesize %]</td>
19
		    <td>[% record.hashvalue %]</td>
20
		    <td>[% record.uploadcategorycode %]</td>
21
	        <td>[% IF record.public %]Yes[% ELSE %]No[% END %]</td>
22
	        <td>[% IF record.permanent %]No[% ELSE %]Yes[% END %]</td>
23
		    <td class="actions">
24
		        <button class="btn btn-mini choose_entry" data-record-id="[% record.id %]" onclick="selectFileToAssociate([% record.id %])"><i class="fa fa-view"></i>Choose</button>
25
		    </td>
26
		</tr>
27
		[% END %]
28
	</tbody>
29
</table>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/upload-images.tt (-1 / +55 lines)
Lines 68-74 Link Here
68
        <div id="fileuploadfailed"></div>
68
        <div id="fileuploadfailed"></div>
69
    </div>
69
    </div>
70
</form>
70
</form>
71
[% IF SaveCoverOnDisk %]
72
<form method="post" id="searchfile" action="/cgi-bin/koha/tools/file-search.pl">
73
    <input type="hidden" name="op" value="search"/>
74
    <input type="hidden" name="category" value="covers"/>
75
    <fieldset class="rows">
76
        <legend>Search uploads by name or hashvalue</legend>
77
        <ol>
78
        <li>
79
            <label for="term">Search term: </label>
80
            <input type="text" id="term" name="term" value=""/>
81
        </li>
82
        </ol>
83
        <fieldset class="action">
84
            <button id="searchbutton" class="submit">Search</button>
85
        </fieldset>
86
    </fieldset>
87
</form>
71
88
89
<div id="searchfilepanel"></div>
90
[% END %]
72
    <form method="post" id="processfile" action="/cgi-bin/koha/tools/upload-cover-image.pl" enctype="multipart/form-data">
91
    <form method="post" id="processfile" action="/cgi-bin/koha/tools/upload-cover-image.pl" enctype="multipart/form-data">
73
<fieldset class="rows">
92
<fieldset class="rows">
74
        <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
93
        <input type="hidden" name="uploadedfileid" id="uploadedfileid" value="" />
Lines 120-126 Link Here
120
            $('#uploadform button.submit').prop('disabled',true);
139
            $('#uploadform button.submit').prop('disabled',true);
121
            $("#fileuploadstatus").show();
140
            $("#fileuploadstatus").show();
122
            $("#uploadedfileid").val('');
141
            $("#uploadedfileid").val('');
123
            xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), 'temp=1', cbUpload );
142
            xhr= AjaxUpload( $('#fileToUpload'), $('#fileuploadprogress'), 'temp=[% IF SaveCoverOnDisk %]0&category=covers[% ELSE %]1[% END %]', cbUpload );
124
        }
143
        }
125
        function cbUpload( status, fileid, errors ) {
144
        function cbUpload( status, fileid, errors ) {
126
            if( status=='done' ) {
145
            if( status=='done' ) {
Lines 139-146 Link Here
139
                $("#processfile").hide();
158
                $("#processfile").hide();
140
            }
159
            }
141
        }
160
        }
161
        [% IF SaveCoverOnDisk %]
162
        function searchFile(form){
163
            $.ajax({
164
                url: $(form).attr('action'),
165
                data: $(form).serialize(),
166
                type: 'post',
167
                success: function(html){
168
                    $("#searchfilepanel").html(html);
169
                }
170
                ,
171
                complete: function()
172
                {
173
                }
174
            });
175
            return false;
176
        }
177
178
        function selectFileToAssociate(fileid){
179
            $("#uploadedfileid").val( fileid );
180
            $('#fileToUpload').prop('disabled',true);
181
            $("#processfile").show();
182
        }
183
        [% END %]
184
142
        $(document).ready(function(){
185
        $(document).ready(function(){
143
            $("#processfile").hide();
186
            $("#processfile").hide();
187
144
            $("#zipfile").click(function(){
188
            $("#zipfile").click(function(){
145
                $("#bibnum").hide();
189
                $("#bibnum").hide();
146
            });
190
            });
Lines 153-158 Link Here
153
                    return false;
197
                    return false;
154
                }
198
                }
155
            });
199
            });
200
            [% IF SaveCoverOnDisk %]
201
            $("#searchbutton").on("click",function(e){
202
                e.preventDefault();
203
                searchFile($('#searchfile'));
204
            });
205
            $(".choose_entry").on("click",function(e){
206
                e.preventDefault();
207
                selectFileToAssociate($(this).data("record-id"));
208
            });
209
            [% END %]
156
        });
210
        });
157
    </script>
211
    </script>
158
[% END %]
212
[% END %]
(-)a/tools/file-search.pl (+67 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Converted to new plugin style (Bug 13437)
4
5
# Copyright 2000-2002 Katipo Communications
6
#
7
# This file is part of Koha.
8
#
9
# Koha is free software; you can redistribute it and/or modify it
10
# under the terms of the GNU General Public License as published by
11
# the Free Software Foundation; either version 3 of the License, or
12
# (at your option) any later version.
13
#
14
# Koha is distributed in the hope that it will be useful, but
15
# WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License
20
# along with Koha; if not, see <http://www.gnu.org/licenses>.
21
22
use Modern::Perl;
23
use CGI qw ( -utf8 );
24
use JSON;
25
26
use warnings;
27
no warnings 'redefine'; # otherwise loading up multiple plugins fills the log with subroutine redefine warnings
28
29
use C4::Auth;
30
use C4::Context;
31
use C4::Output;
32
33
use Koha::Upload;
34
35
use Data::Dumper;
36
37
use vars qw($debug);
38
39
BEGIN {
40
    $debug = $ENV{DEBUG} || 0;
41
}
42
43
my $dbh = C4::Context->dbh;
44
my $input = CGI->new;
45
$debug or $debug = $input->param('debug') || 0;
46
my $content_type = 'json';
47
48
my $term = $input->param('term');
49
50
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
51
    {   template_name   => "tools/file-search.tt",
52
        query           => $input,
53
        type            => "intranet",
54
        authnotrequired => 0,
55
        flagsrequired   => { editcatalogue => '*' },
56
        debug           => 1,
57
    }
58
);
59
60
my $upar = {};
61
my $h = { term => $term, uploadcategorycode => 'covers' };
62
my @uploads = Koha::Upload->new($upar)->get($h);
63
$template->param(
64
    uploads => \@uploads,
65
);
66
67
output_with_http_headers $input, $cookie, $template->output, 'html';
(-)a/tools/upload-cover-image.pl (-2 / +3 lines)
Lines 48-53 use C4::Output; Link Here
48
use C4::Images;
48
use C4::Images;
49
use Koha::UploadedFiles;
49
use Koha::UploadedFiles;
50
use C4::Log;
50
use C4::Log;
51
use Data::Dumper;
51
52
52
my $debug = 1;
53
my $debug = 1;
53
54
Lines 78-86 my $error; Link Here
78
79
79
$template->{VARS}->{'filetype'}     = $filetype;
80
$template->{VARS}->{'filetype'}     = $filetype;
80
$template->{VARS}->{'biblionumber'} = $biblionumber;
81
$template->{VARS}->{'biblionumber'} = $biblionumber;
82
$template->{VARS}->{'SaveCoverOnDisk'} = C4::Context->preference("SaveCoverOnDisk");
81
83
82
my $total = 0;
84
my $total = 0;
83
84
if ($fileID) {
85
if ($fileID) {
85
    my $upload = Koha::UploadedFiles->find( $fileID );
86
    my $upload = Koha::UploadedFiles->find( $fileID );
86
    if ( $filetype eq 'image' ) {
87
    if ( $filetype eq 'image' ) {
Lines 88-94 if ($fileID) { Link Here
88
        my $srcimage = GD::Image->new($fh);
89
        my $srcimage = GD::Image->new($fh);
89
        $fh->close if $fh;
90
        $fh->close if $fh;
90
        if ( defined $srcimage ) {
91
        if ( defined $srcimage ) {
91
            my $dberror = PutImage( $biblionumber, $srcimage, $replace );
92
            my $dberror = PutImage( $biblionumber, $srcimage, $replace, $fileID );
92
            if ($dberror) {
93
            if ($dberror) {
93
                $error = 'DBERR';
94
                $error = 'DBERR';
94
            }
95
            }
(-)a/tools/upload-file.pl (-1 / +2 lines)
Lines 28-33 use URI::Escape; Link Here
28
use C4::Context;
28
use C4::Context;
29
use C4::Auth qw/check_cookie_auth haspermission/;
29
use C4::Auth qw/check_cookie_auth haspermission/;
30
use Koha::Uploader;
30
use Koha::Uploader;
31
use Data::Dumper;
31
32
32
# upload-file.pl must authenticate the user
33
# upload-file.pl must authenticate the user
33
# before processing the POST request,
34
# before processing the POST request,
Lines 80-84 sub upload_pars { # this sub parses QUERY_STRING in order to build the Link Here
80
            $rv->{$p} = $2;
81
            $rv->{$p} = $2;
81
        }
82
        }
82
    }
83
    }
84
    warn Dumper($rv);
83
    return $rv;
85
    return $rv;
84
}
86
}
85
- 

Return to bug 17650