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

(-)a/Koha/Carousel.pm (+278 lines)
Line 0 Link Here
1
package Koha::Carousel;
2
3
# Copyright 2016 Mason James
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
use C4::Koha;
23
use C4::Biblio;
24
use C4::Debug;
25
26
use LWP::Simple;
27
use List::Util qw(shuffle );
28
use Business::ISBN;
29
30
if ( $ENV{DEBUG} ) {
31
    use Time::HiRes qw/gettimeofday tv_interval/;
32
    use Carp;
33
}
34
35
use vars qw($VERSION @ISA @EXPORT);
36
37
BEGIN {
38
    $VERSION = 1.00;
39
40
    require Exporter;
41
    @ISA = qw( Exporter );
42
43
    push @EXPORT, qw(
44
      &GetRecentBibs
45
    );
46
}
47
48
=head1 NAME
49
50
Koha::Carousel - A module to handle subroutines for the 'new items' carousel
51
52
=head1 DESCRIPTION
53
54
This module has 1 subroutine,
55
56
    GetRecentBibs() returns a hashref of bibs with a matching amazon bookcover url
57
58
=head1 SYNOPSIS
59
60
    use Koha::Carousel
61
62
    # give me a hashref of 10 random new bibs
63
    my $new_bibs_href =  GetRecentBibs();
64
65
    # give me a hashref of 20 random new bibs
66
    my $new_bibs_href =  GetRecentBibs('20');
67
68
=cut
69
70
sub GetRecentBibs {
71
72
    my $caro_num = shift;
73
74
    # speed stats for debugging.
75
    my $tt0;
76
    my $tt1;
77
    if ( $ENV{DEBUG} ) {
78
        $tt0 = [gettimeofday];
79
    }
80
81
    # set vars = 0, to shush warnings
82
    my ( $amz_hit_cnt, $amz_miss_cnt, $dupes, $cache_hits, $fetches, $hits,
83
        $cache_misses )
84
      = (0) x 7;
85
    my ( @bibs_stage1, @bibs_stage2, @bibs_stage3 );
86
87
    my $ua = new LWP::UserAgent( 'max_redirect' => 0 );
88
89
    # 3 different limits, for narrowing the list of bib results
90
    my $stage1_limit = 300;
91
    my $stage2_limit = 150;
92
    my $stage3_limit = $caro_num ? $caro_num : 10;
93
94
# Initial SQL query to get recently added bibs
95
# we choose a 'reasonable' limit here, to ensure we don't make our dataset too small
96
97
    my $bib_rs = Koha::Database->new()->schema->resultset('Biblio')->search(
98
        { 'biblioitems.isbn' => { '!=', undef }, },
99
        {
100
            join      => 'biblioitems',
101
            '+select' => ['biblioitems.isbn'],
102
            '+as'     => ['isbn'],
103
104
            rows => $stage1_limit,
105
            desc => 'datecreated',
106
        }
107
    );
108
109
    # run a loop to get $stage1_limit bibs with checksum verified ISBNs.
110
    my $i;
111
    while ( my $r1 = $bib_rs->next ) {
112
113
        # test checksum of ISBN10
114
        my $isbn_tmp = $r1->get_column('isbn');
115
        my $isbn;
116
117
        my @ibs = split( /\|/, $isbn_tmp );
118
        foreach my $ii (@ibs) {
119
120
            # strip trailing (comments) from isbn
121
            $ii =~ s/\(.*$//g;
122
123
            my $isbn_obj = Business::ISBN->new($ii);
124
            next unless $isbn_obj;
125
126
            my $isbn10;
127
            $isbn10 = $isbn_obj->as_isbn10;
128
            if ( $isbn10->is_valid() ) {
129
                $isbn = $isbn10->as_string( [] );
130
                last;
131
            }
132
        }
133
134
        next unless $isbn;
135
136
        my $bib = {
137
            biblionumber => $r1->biblionumber,
138
            title        => $r1->title,
139
            author       => $r1->author,
140
            isbn         => $isbn,
141
        };
142
143
        push @bibs_stage1, $bib;
144
145
    }    # end while
146
147
    # run a loop to remove any dupes
148
    $i = 0;
149
    foreach my $bib (@bibs_stage1) {
150
151
        # check for dups before adding
152
        my $dupe = 0;
153
        foreach my $b (@bibs_stage2) {
154
            if ( $bib->{isbn} eq $b->{isbn} ) {
155
                $dupe = 1;
156
                $dupes++;
157
                last;
158
            }
159
        }
160
        next if $dupe == 1;
161
        push @bibs_stage2, $bib;
162
        last if ++$i == $stage2_limit;
163
    }    # end while
164
165
    #randomise our bibs
166
    @bibs_stage2 = shuffle @bibs_stage2;
167
168
   # loop, until we get enough cover images
169
   # add each amazon lookup attempt to the carousel db table, for future caching
170
171
    for my $bib (@bibs_stage2) {
172
173
        # check for an existing ISBN row, in caro table
174
        my $caro_rs =
175
          Koha::Database->new()->schema->resultset('Carousel')
176
          ->search( { 'isbn' => { '=', $bib->{'isbn'} }, }, { rows => '1' } );
177
178
        my $cnt = $caro_rs->count;
179
180
        my $rs = $caro_rs->next;
181
        my $amz_miss;
182
        my $image_url;
183
184
        # if not db match, do amazon lookup....
185
        if ( $cnt == 0 ) {
186
187
            # no row in table, so fetch from amazon
188
            $image_url =
189
                'http://images.amazon.com/images/P/'
190
              . $bib->{isbn}
191
              . '.01._THUMBZZZ.jpg';
192
193
            my $req      = HTTP::Request->new( 'GET', $image_url );
194
            my $res      = $ua->request($req);
195
            my $res_size = $res->headers->{'content-length'};
196
197
            $fetches++;
198
199
            #     warn $res_size;
200
            # 43 bytes returned, means lookup was a miss :'(
201
            $amz_miss = 1 if ( $res_size == 43 );
202
203
            # insert lookup result into table
204
            $caro_rs->create(
205
                {
206
                    isbn      => $bib->{'isbn'},
207
                    image_url => ( $amz_miss ? undef : $image_url )
208
                }
209
            );
210
211
            if ($amz_miss) {
212
                $amz_miss_cnt++;
213
                next;
214
            }
215
            else {
216
                # else, got a match from amazon
217
                $amz_hit_cnt++;
218
            }
219
220
        }    # end
221
             # else, got result from db..
222
        else {
223
224
            # but no image, so skip :/
225
            unless ( $rs->get_column('image_url') ) {
226
                $cache_misses++;
227
                next;
228
            }
229
            else {
230
                # db result has image, so use ;)
231
                $image_url = $rs->get_column('image_url');
232
                $cache_hits++;
233
            }
234
        }    # end for
235
236
        # remove glitchy trailing chars from title/author for display /:,
237
        foreach ( $bib->{title}, $bib->{author} ) {
238
            next unless $_;    # shush warns
239
            s|/$||;
240
            s|:$||;
241
            s|,$||;
242
            s/[ \t]+$//g;
243
        }
244
245
        $bib->{image_url} = $image_url;
246
        $bib->{id}        = $hits;
247
248
        push @bibs_stage3, $bib;
249
250
        $hits++;
251
        last if $hits == $stage3_limit;
252
    }
253
254
    # if debug, print some extra stats
255
    if ( $ENV{DEBUG} ) {
256
        $tt1 = [gettimeofday];
257
        carp 'carousel: load time ' . tv_interval( $tt0, $tt1 );
258
        carp "carousel: db_hits: $cache_hits, amz_fetches:$fetches";
259
        carp
260
"amz_hit:$amz_hit_cnt, amz_miss:$amz_miss_cnt, dupes:$dupes, hits: $hits, misses: $cache_misses, needs: $stage3_limit";
261
    }
262
263
    return \@bibs_stage3;
264
}
265
266
=head1 EXPORT
267
268
None by default.
269
270
=head1 AUTHOR
271
272
Mason James, E<lt>mason@calyx.net.auE<gt>
273
274
=cut
275
276
1;
277
278
__END__
(-)a/Koha/Schema/Result/Carousel.pm (+79 lines)
Line 0 Link Here
1
use utf8;
2
package Koha::Schema::Result::Carousel;
3
4
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
7
=head1 NAME
8
9
Koha::Schema::Result::Carousel
10
11
=cut
12
13
use strict;
14
use warnings;
15
16
use base 'DBIx::Class::Core';
17
18
=head1 TABLE: C<carousel>
19
20
=cut
21
22
__PACKAGE__->table("carousel");
23
24
=head1 ACCESSORS
25
26
=head2 isbn
27
28
  data_type: 'varchar'
29
  is_nullable: 0
30
  size: 30
31
32
=head2 image_url
33
34
  data_type: 'varchar'
35
  is_nullable: 1
36
  size: 255
37
38
=head2 timestamp
39
40
  data_type: 'timestamp'
41
  datetime_undef_if_invalid: 1
42
  default_value: current_timestamp
43
  is_nullable: 0
44
45
=cut
46
47
__PACKAGE__->add_columns(
48
  "isbn",
49
  { data_type => "varchar", is_nullable => 0, size => 255 },
50
  "image_url",
51
  { data_type => "varchar", is_nullable => 0, size => 255 },
52
  "timestamp",
53
  {
54
    data_type => "timestamp",
55
    datetime_undef_if_invalid => 1,
56
    default_value => \"current_timestamp",
57
    is_nullable => 0,
58
  },
59
);
60
61
=head1 PRIMARY KEY
62
63
=over 4
64
65
=item * L</isbn>
66
67
=back
68
69
=cut
70
71
__PACKAGE__->set_primary_key("isbn");
72
73
74
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2014-11-15 02:47:15
75
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WlpGsPHQes9PIDaN4/6zaA
76
77
78
# You can replace this text with custom code or comments, and it will be preserved on regeneration
79
1;
(-)a/debian/koha-common.cron.daily (-1 / +1 lines)
Lines 21-27 koha-foreach --enabled --email /usr/share/koha/bin/cronjobs/advance_notices.pl - Link Here
21
koha-foreach --enabled /usr/share/koha/bin/cronjobs/membership_expiry.pl -c
21
koha-foreach --enabled /usr/share/koha/bin/cronjobs/membership_expiry.pl -c
22
koha-foreach --enabled /usr/share/koha/bin/cronjobs/holds/cancel_expired_holds.pl >/dev/null 2>&1
22
koha-foreach --enabled /usr/share/koha/bin/cronjobs/holds/cancel_expired_holds.pl >/dev/null 2>&1
23
koha-foreach --enabled /usr/share/koha/bin/cronjobs/services_throttle.pl > /dev/null 2>&1
23
koha-foreach --enabled /usr/share/koha/bin/cronjobs/services_throttle.pl > /dev/null 2>&1
24
koha-foreach --enabled /usr/share/koha/bin/cronjobs/cleanup_database.pl --sessions --zebraqueue 10 --list-invites
24
koha-foreach --enabled /usr/share/koha/bin/cronjobs/cleanup_database.pl --sessions --zebraqueue 10 --list-invites --carousel
25
koha-foreach --enabled --noemail /usr/share/koha/bin/cronjobs/cleanup_database.pl --mail
25
koha-foreach --enabled --noemail /usr/share/koha/bin/cronjobs/cleanup_database.pl --mail
26
koha-foreach --enabled /usr/share/koha/bin/cronjobs/holds/auto_unsuspend_holds.pl > /dev/null 2>&1
26
koha-foreach --enabled /usr/share/koha/bin/cronjobs/holds/auto_unsuspend_holds.pl > /dev/null 2>&1
27
koha-foreach --enabled /usr/share/koha/bin/cronjobs/automatic_renewals.pl
27
koha-foreach --enabled /usr/share/koha/bin/cronjobs/automatic_renewals.pl
(-)a/installer/data/mysql/atomicupdate/Bug-10756-carousel.pl (+20 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
use strict;
4
use warnings;
5
use C4::Context;
6
my $dbh = C4::Context->dbh;
7
8
$dbh->do(
9
q|
10
CREATE TABLE `carousel` (
11
  `isbn` varchar(255) NOT NULL,
12
  `image_url` varchar(255) NULL,
13
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
14
  PRIMARY KEY (`isbn`)
15
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
16
);
17
18
  $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacCarousel','0','Display the new-items carousel on OPAC home page.','','YesNo')");
19
20
print "Upgrade done (Bug 10756 - Carousel Display of New Titles on OPAC)\n";
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+7 lines)
Lines 484-489 OPAC: Link Here
484
                  no: Don't display
484
                  no: Don't display
485
            - the acquisition details on OPAC detail pages.
485
            - the acquisition details on OPAC detail pages.
486
        -
486
        -
487
            - pref: OPACCarousel
488
              default: 0
489
              choices:
490
                  yes: Display
491
                  no: Don't display
492
            - the 'new items' carousel on OPAC home page.
493
        -
487
            - "Use the following as the OPAC ISBD template:"
494
            - "Use the following as the OPAC ISBD template:"
488
            - pref: OPACISBD
495
            - pref: OPACISBD
489
              type: textarea
496
              type: textarea
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-bottom.inc (+16 lines)
Lines 188-193 $.widget.bridge('uitooltip', $.ui.tooltip); Link Here
188
    </script>
188
    </script>
189
[% END %]
189
[% END %]
190
190
191
[% IF OpacCarousel %]
192
    <script type="text/javascript" src="[% interface %]/[% theme %]/lib/contentflow/contentflow.js"></script>
193
    <script type="text/javascript">
194
    //<![CDATA[
195
    $(document).ready(function() {
196
      var cflow2 = new ContentFlow('cflow2', {
197
        reflectionHeight : 0.2 ,
198
        reflectionGap : 0.0,
199
        scaleFactor : 2.0,
200
      });
201
      cflow2.init()
202
    });
203
    //]]>
204
    </script>
205
[% END %]
206
191
[% IF OPACLocalCoverImages %]
207
[% IF OPACLocalCoverImages %]
192
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/localcovers.js"></script>
208
    <script type="text/javascript" src="[% interface %]/[% theme %]/js/localcovers.js"></script>
193
    <script type="text/javascript">
209
    <script type="text/javascript">
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt (+18 lines)
Lines 66-71 Link Here
66
        [% END %]
66
        [% END %]
67
67
68
        [% IF ( OpacMainUserBlock ) %]<div id="opacmainuserblock">[% OpacMainUserBlock %]</div>[% END %]
68
        [% IF ( OpacMainUserBlock ) %]<div id="opacmainuserblock">[% OpacMainUserBlock %]</div>[% END %]
69
70
        [% IF ( caro_bibs  ) %]
71
        <div id="cflow1" class="span6 offset3">
72
        <center><h3>Recently added items</h3></center>
73
          <div id="cflow2" class="ContentFlow" style="background: hidden;">
74
            <div class="flow">
75
            [% FOREACH caro_bibs IN caro_bibs %]
76
                <div class="item" href="/cgi-bin/koha/opac-detail.pl?bib=[% caro_bibs.biblionumber %]" >
77
                  <img class="content" src="[% caro_bibs.image_url %]" />
78
                  <div class="caption">[% caro_bibs.title %][% IF ( caro_bibs.author  ) %] by [% caro_bibs.author %][% END %]</div>
79
                </div>
80
            [% END %]
81
            </div>
82
            <div class="globalCaption"></div>
83
          </div>
84
        </div>
85
        [% END %]
86
69
        </div> <!-- / .span 7/9 -->
87
        </div> <!-- / .span 7/9 -->
70
88
71
        [% IF ( ( Koha.Preference( 'opacuserlogin' ) == 1 ) || OpacNavRight ) %]
89
        [% IF ( ( Koha.Preference( 'opacuserlogin' ) == 1 ) || OpacNavRight ) %]
(-)a/misc/cronjobs/cleanup_database.pl (-2 / +25 lines)
Lines 23-28 use constant DEFAULT_ZEBRAQ_PURGEDAYS => 30; Link Here
23
use constant DEFAULT_MAIL_PURGEDAYS               => 30;
23
use constant DEFAULT_MAIL_PURGEDAYS               => 30;
24
use constant DEFAULT_IMPORT_PURGEDAYS             => 60;
24
use constant DEFAULT_IMPORT_PURGEDAYS             => 60;
25
use constant DEFAULT_LOGS_PURGEDAYS               => 180;
25
use constant DEFAULT_LOGS_PURGEDAYS               => 180;
26
use constant DEFAULT_CAROUSEL_PURGEDAYS           => 90;
26
use constant DEFAULT_SEARCHHISTORY_PURGEDAYS      => 30;
27
use constant DEFAULT_SEARCHHISTORY_PURGEDAYS      => 30;
27
use constant DEFAULT_SHARE_INVITATION_EXPIRY_DAYS => 14;
28
use constant DEFAULT_SHARE_INVITATION_EXPIRY_DAYS => 14;
28
use constant DEFAULT_DEBARMENTS_PURGEDAYS         => 30;
29
use constant DEFAULT_DEBARMENTS_PURGEDAYS         => 30;
Lines 43-49 use C4::Accounts; Link Here
43
44
44
sub usage {
45
sub usage {
45
    print STDERR <<USAGE;
46
    print STDERR <<USAGE;
46
Usage: $0 [-h|--help] [--sessions] [--sessdays DAYS] [-v|--verbose] [--zebraqueue DAYS] [-m|--mail] [--merged] [--import DAYS] [--logs DAYS] [--searchhistory DAYS] [--restrictions DAYS] [--all-restrictions] [--fees DAYS]
47
Usage: $0 [-h|--help] [--sessions] [--sessdays DAYS] [-v|--verbose] [--zebraqueue DAYS] [-m|--mail] [--merged] [--import DAYS] [--logs DAYS] [--searchhistory DAYS] [--restrictions DAYS] [--all-restrictions] [--fees DAYS] [--carousel DAYS]
47
48
48
   -h --help          prints this help message, and exits, ignoring all
49
   -h --help          prints this help message, and exits, ignoring all
49
                      other options
50
                      other options
Lines 76-84 Usage: $0 [-h|--help] [--sessions] [--sessdays DAYS] [-v|--verbose] [--zebraqueu Link Here
76
                         days.  Defaults to 14 days if no days specified.
77
                         days.  Defaults to 14 days if no days specified.
77
   --restrictions DAYS   purge patrons restrictions expired since more than DAYS days.
78
   --restrictions DAYS   purge patrons restrictions expired since more than DAYS days.
78
                         Defaults to 30 days if no days specified.
79
                         Defaults to 30 days if no days specified.
79
    --all-restrictions   purge all expired patrons restrictions.
80
   --all-restrictions   purge all expired patrons restrictions.
80
   --del-exp-selfreg  Delete expired self registration accounts
81
   --del-exp-selfreg  Delete expired self registration accounts
81
   --del-unv-selfreg DAYS  Delete unverified self registrations older than DAYS
82
   --del-unv-selfreg DAYS  Delete unverified self registrations older than DAYS
83
   --carousel DAYS    purge entries from carousel older than DAYS days.
84
                      Defaults to 90 days if no days specified.
82
USAGE
85
USAGE
83
    exit $_[0];
86
    exit $_[0];
84
}
87
}
Lines 92-97 my $mail; Link Here
92
my $purge_merged;
95
my $purge_merged;
93
my $pImport;
96
my $pImport;
94
my $pLogs;
97
my $pLogs;
98
my $pCarousel;
95
my $pSearchhistory;
99
my $pSearchhistory;
96
my $pZ3950;
100
my $pZ3950;
97
my $pListShareInvites;
101
my $pListShareInvites;
Lines 113-118 GetOptions( Link Here
113
    'z3950'           => \$pZ3950,
117
    'z3950'           => \$pZ3950,
114
    'logs:i'          => \$pLogs,
118
    'logs:i'          => \$pLogs,
115
    'fees:i'          => \$fees_days,
119
    'fees:i'          => \$fees_days,
120
    'carousel:i'      => \$pCarousel,
116
    'searchhistory:i' => \$pSearchhistory,
121
    'searchhistory:i' => \$pSearchhistory,
117
    'list-invites:i'  => \$pListShareInvites,
122
    'list-invites:i'  => \$pListShareInvites,
118
    'restrictions:i'  => \$pDebarments,
123
    'restrictions:i'  => \$pDebarments,
Lines 125-130 GetOptions( Link Here
125
$sessions          = 1                                    if $sess_days                  && $sess_days > 0;
130
$sessions          = 1                                    if $sess_days                  && $sess_days > 0;
126
$pImport           = DEFAULT_IMPORT_PURGEDAYS             if defined($pImport)           && $pImport == 0;
131
$pImport           = DEFAULT_IMPORT_PURGEDAYS             if defined($pImport)           && $pImport == 0;
127
$pLogs             = DEFAULT_LOGS_PURGEDAYS               if defined($pLogs)             && $pLogs == 0;
132
$pLogs             = DEFAULT_LOGS_PURGEDAYS               if defined($pLogs)             && $pLogs == 0;
133
$pCarousel         = DEFAULT_CAROUSEL_PURGEDAYS           if defined($pCarousel)         && $pCarousel == 0;
128
$zebraqueue_days   = DEFAULT_ZEBRAQ_PURGEDAYS             if defined($zebraqueue_days)   && $zebraqueue_days == 0;
134
$zebraqueue_days   = DEFAULT_ZEBRAQ_PURGEDAYS             if defined($zebraqueue_days)   && $zebraqueue_days == 0;
129
$mail              = DEFAULT_MAIL_PURGEDAYS               if defined($mail)              && $mail == 0;
135
$mail              = DEFAULT_MAIL_PURGEDAYS               if defined($mail)              && $mail == 0;
130
$pSearchhistory    = DEFAULT_SEARCHHISTORY_PURGEDAYS      if defined($pSearchhistory)    && $pSearchhistory == 0;
136
$pSearchhistory    = DEFAULT_SEARCHHISTORY_PURGEDAYS      if defined($pSearchhistory)    && $pSearchhistory == 0;
Lines 142-147 unless ( $sessions Link Here
142
    || $pImport
148
    || $pImport
143
    || $pLogs
149
    || $pLogs
144
    || $fees_days
150
    || $fees_days
151
    || $pCarousel
145
    || $pSearchhistory
152
    || $pSearchhistory
146
    || $pZ3950
153
    || $pZ3950
147
    || $pListShareInvites
154
    || $pListShareInvites
Lines 238-243 if ($pZ3950) { Link Here
238
    print "Done with purging Z39.50 records from import tables.\n" if $verbose;
245
    print "Done with purging Z39.50 records from import tables.\n" if $verbose;
239
}
246
}
240
247
248
if ($pCarousel) {
249
    print "Purging records from carousel tables.\n" if $verbose;
250
    PurgeCarousel();
251
    print "Done with purging records from carousel tables.\n" if $verbose;
252
}
253
241
if ($pLogs) {
254
if ($pLogs) {
242
    print "Purging records from action_logs.\n" if $verbose;
255
    print "Purging records from action_logs.\n" if $verbose;
243
    $sth = $dbh->prepare(
256
    $sth = $dbh->prepare(
Lines 363-368 sub PurgeZ3950 { Link Here
363
    $sth->execute() or die $dbh->errstr;
376
    $sth->execute() or die $dbh->errstr;
364
}
377
}
365
378
379
sub PurgeCarousel {
380
    $sth = $dbh->prepare(
381
        q{
382
            DELETE FROM carousel
383
            WHERE timestamp <  date_sub(curdate(), INTERVAL ? DAY)
384
        }
385
    );
386
    $sth->execute($pCarousel) or die $dbh->errstr;
387
}
388
366
sub PurgeDebarments {
389
sub PurgeDebarments {
367
    require Koha::Patron::Debarments;
390
    require Koha::Patron::Debarments;
368
    my $days = shift;
391
    my $days = shift;
(-)a/opac/opac-main.pl (+9 lines)
Lines 25-30 use C4::Output; Link Here
25
use C4::NewsChannels;    # GetNewsToDisplay
25
use C4::NewsChannels;    # GetNewsToDisplay
26
use C4::Languages qw(getTranslatedLanguages accept_language);
26
use C4::Languages qw(getTranslatedLanguages accept_language);
27
use C4::Koha qw( GetDailyQuote );
27
use C4::Koha qw( GetDailyQuote );
28
use Koha::Carousel;
28
29
29
my $input = new CGI;
30
my $input = new CGI;
30
my $dbh   = C4::Context->dbh;
31
my $dbh   = C4::Context->dbh;
Lines 76-79 if (C4::Context->preference('OPACNumbersPreferPhrase')) { Link Here
76
        $template->param('numbersphr' => 1);
77
        $template->param('numbersphr' => 1);
77
}
78
}
78
79
80
if ( C4::Context->preference('OpacCarousel') ) {
81
    our $caro_bibs = GetRecentBibs(10);
82
    $template->param(
83
        caro_bibs    => $caro_bibs,
84
        OpacCarousel => 1
85
    );
86
}
87
79
output_html_with_http_headers $input, $cookie, $template->output;
88
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/t/db_dependent/Carousel.t (-1 / +243 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Copyright 2016 CALYX Group
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 5;
23
use Test::MockModule;
24
25
use MARC::Record;
26
use t::lib::Mocks qw( mock_preference );
27
28
BEGIN {
29
    use_ok('C4::Biblio');
30
    use_ok('Koha::Carousel');
31
}
32
33
my $dbh = C4::Context->dbh;
34
35
$dbh->{AutoCommit} = 0;
36
$dbh->{RaiseError} = 1;
37
38
# Mock a context
39
my $context = new Test::MockModule('C4::Context');
40
mock_marcfromkohafield();
41
42
# create 3 sets of ISBN run to tests on...
43
# 1 set of invalid isbns
44
my @isbns_bad = qw |
45
  1111
46
  2222
47
  333
48
  444
49
  5555
50
  666
51
  777
52
  88
53
  99
54
  1100000
55
56
  |;
57
58
# 1 set of mixed valid and invalid isbns
59
my @isbns_mixed = qw |
60
  2846542082
61
  2848301384
62
  2848672870
63
  2953079971
64
  2953636501
65
  11111
66
  2222
67
  33333
68
  4444444
69
  55555
70
71
  |;
72
73
# 1 set of valid isbns
74
my @isbns_good = qw |
75
  2846542082
76
  2848301384
77
  2848672870
78
  2953079971
79
  2953636501
80
  3110251345
81
  3406606067
82
  3531167707
83
  3531174142
84
  3531174827
85
86
  |;
87
88
my $marcflavour;
89
90
# run some tests for MARC21, UNIMARC and NORMARC bibsets
91
sub run_tests {
92
93
    $marcflavour = shift;
94
95
    # clean the bib tables for the before starting the tests, with auto-commit off
96
    my $sth;
97
    $sth = $dbh->do("delete from items");
98
    $sth = $dbh->do("delete from biblioitems");
99
100
    $sth = $dbh->do("delete from biblio");
101
    $sth = $dbh->do("delete from caro_isbn_url");
102
103
    # Undef C4::Biblio::inverted_field_map to avoid problems introduced
104
    # by caching in TransformMarcToKoha
105
    undef $C4::Biblio::inverted_field_map;
106
    t::lib::Mocks::mock_preference( 'marcflavour', $marcflavour );
107
108
    # add some bibs with bad isbns
109
    our $caro_bibs_bad = GetRecentBibs(10);
110
111
    # test for 10 invalid ISBNs, expects 0 successful results
112
    is(
113
        scalar @$caro_bibs_bad,
114
        0,
115
        'Number of invalid bibs returned is '
116
          . scalar @$caro_bibs_bad
117
          . ', expected 0'
118
    );
119
120
121
    foreach my $i (@isbns_mixed) { create_bib($i); }
122
    our $caro_bibs_mixed = GetRecentBibs(10);
123
124
    # test for 10 mixed ISBNs, expects 5 successful results
125
    is(
126
        scalar @$caro_bibs_mixed,
127
        5,
128
        'Number of mixed bibs returned is '
129
          . scalar @$caro_bibs_mixed
130
          . ', expected 5'
131
    );
132
133
    # test for 10 valid ISBNs, expects 10 successful results
134
    foreach my $i (@isbns_good) { create_bib($i); }
135
    our $caro_bibs_good = GetRecentBibs(10);
136
137
    # then... add some more bibs with good isbns
138
    is(
139
        scalar @$caro_bibs_good,
140
        10,
141
        'Number of valid bibs returned is '
142
          . scalar @$caro_bibs_good
143
          . ', expected 10'
144
    );
145
}
146
147
# mock a needed MARC subfield, for testing
148
sub mock_marcfromkohafield {
149
150
    $context->mock(
151
        'marcfromkohafield',
152
        sub {
153
            my ($self) = shift;
154
155
            # if we are testing MARC21 or NORMARC, use these subfields...
156
            if (   C4::Context->preference('marcflavour') eq 'MARC21'
157
                || C4::Context->preference('marcflavour') eq 'NORMARC' )
158
            {
159
                return {
160
                    '' => {
161
                        'biblio.title'                 => [ '245', 'a' ],
162
                        'biblio.biblionumber'          => [ '999', 'c' ],
163
                        'biblioitems.isbn'             => [ '020', 'a' ],
164
                        'biblioitems.issn'             => [ '022', 'a' ],
165
                        'biblioitems.biblioitemnumber' => [ '999', 'd' ]
166
                    }
167
                };
168
            }
169
170
            # or, if we are testing UNIMARC, use these subfields...
171
            elsif ( C4::Context->preference('marcflavour') eq 'UNIMARC' ) {
172
173
                return {
174
                    '' => {
175
                        'biblio.title'                 => [ '200', 'a' ],
176
                        'biblio.biblionumber'          => [ '999', 'c' ],
177
                        'biblioitems.isbn'             => [ '010', 'a' ],
178
                        'biblioitems.issn'             => [ '011', 'a' ],
179
                        'biblioitems.biblioitemnumber' => [ '090', 'a' ]
180
                    }
181
                };
182
            }
183
        }
184
    );
185
}
186
187
# create a simple mocked bib
188
sub create_bib {
189
190
    my $isbn  = shift;
191
    my $title = 'some title';
192
193
    # Generate a record with just the ISBN
194
    my $marc_record = MARC::Record->new;
195
    my $isbn_field = create_isbn_field( $isbn, $marcflavour );
196
    $marc_record->append_fields($isbn_field);
197
198
    # Add title
199
    my $fld = ( $marcflavour eq 'UNIMARC' ) ? '200' : '245';
200
    my $title_field = MARC::Field->new( $fld, '', '', 'a' => $title );
201
    $marc_record->append_fields($title_field);
202
203
    # Add the record to the DB
204
    my ( $biblionumber, $biblioitemnumber ) = AddBiblio( $marc_record, '' );
205
    my $data = GetBiblioData($biblionumber);
206
207
}
208
209
# Add an isbn subfield to an item
210
sub create_isbn_field {
211
    my ( $isbn, $marcflavour ) = @_;
212
213
    my $isbn_field = ( $marcflavour eq 'UNIMARC' ) ? '010' : '020';
214
    my $field = MARC::Field->new( $isbn_field, '', '', 'a' => $isbn );
215
216
    return $field;
217
}
218
219
# do tests on 3 different MARC formats
220
subtest 'MARC21' => sub {
221
    plan tests => 3;
222
    run_tests('MARC21');
223
224
    $dbh->rollback;
225
};
226
227
subtest 'UNIMARC' => sub {
228
    plan tests => 3;
229
    run_tests('UNIMARC');
230
231
    $dbh->rollback;
232
};
233
234
subtest 'NORMARC' => sub {
235
    plan tests => 3;
236
    run_tests('NORMARC');
237
238
    $dbh->rollback;
239
};
240
241
done_testing();
242
243
1;

Return to bug 10756