| File: | C4/XISBN.pm |
| Coverage: | 23.4% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package C4::XISBN; | |||||
| 2 | # Copyright (C) 2007 LibLime | |||||
| 3 | # Joshua Ferraro <jmf@liblime.com> | |||||
| 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 2 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 | 1 1 1 | 268 9 22 | use XML::Simple; | |||
| 21 | #use LWP::Simple; | |||||
| 22 | 1 1 1 | 73 9 745 | use C4::Biblio; | |||
| 23 | 1 1 1 | 10 6 358 | use C4::Koha; | |||
| 24 | 1 1 1 | 2484 2 67 | use C4::External::Syndetics qw(get_syndetics_editions); | |||
| 25 | 1 1 1 | 4 2 16 | use LWP::UserAgent; | |||
| 26 | 1 1 1 | 4 1 60 | use HTTP::Request::Common; | |||
| 27 | ||||||
| 28 | 1 1 1 | 4 2 23 | use strict; | |||
| 29 | #use warnings; FIXME - Bug 2505 | |||||
| 30 | 1 1 1 | 4 1 90 | use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); | |||
| 31 | ||||||
| 32 | BEGIN { | |||||
| 33 | 1 | 5 | require Exporter; | |||
| 34 | 1 | 1 | $VERSION = 3.01; | |||
| 35 | 1 | 9 | @ISA = qw(Exporter); | |||
| 36 | 1 | 467 | @EXPORT_OK = qw( | |||
| 37 | &get_xisbns | |||||
| 38 | &get_biblionumber_from_isbn | |||||
| 39 | ); | |||||
| 40 | } | |||||
| 41 | ||||||
| 42 | sub get_biblionumber_from_isbn { | |||||
| 43 | 0 | my $isbn = shift; | ||||
| 44 | 0 | $isbn.='%'; | ||||
| 45 | 0 | my @biblionumbers; | ||||
| 46 | 0 | my $dbh=C4::Context->dbh; | ||||
| 47 | 0 | my $query = "SELECT biblionumber FROM biblioitems WHERE isbn LIKE ? LIMIT 10"; | ||||
| 48 | 0 | my $sth = $dbh->prepare($query); | ||||
| 49 | 0 | $sth->execute($isbn); | ||||
| 50 | 0 | return $sth->fetchall_arrayref({}); | ||||
| 51 | } | |||||
| 52 - 60 | =head1 NAME C4::XISBN - Functions for retrieving XISBN content in Koha =head1 FUNCTIONS This module provides facilities for retrieving ThingISBN and XISBN content in Koha =cut | |||||
| 61 | ||||||
| 62 | sub _get_biblio_from_xisbn { | |||||
| 63 | 0 | my $xisbn = shift; | ||||
| 64 | 0 | $xisbn.='%'; | ||||
| 65 | 0 | my $dbh = C4::Context->dbh; | ||||
| 66 | 0 | my $query = "SELECT biblionumber FROM biblioitems WHERE isbn LIKE ?"; | ||||
| 67 | 0 | my $sth = $dbh->prepare($query); | ||||
| 68 | 0 | $sth->execute($xisbn); | ||||
| 69 | 0 | my $xbib_data = $sth->fetchrow_hashref(); | ||||
| 70 | 0 | my $xbiblio; | ||||
| 71 | 0 | if ($xbib_data->{biblionumber}) { | ||||
| 72 | 0 | $xbiblio = GetBiblioData($xbib_data->{biblionumber}); | ||||
| 73 | 0 | $xbiblio->{normalized_isbn} = GetNormalizedISBN($xbiblio->{isbn}); | ||||
| 74 | } | |||||
| 75 | 0 | return ($xbiblio); | ||||
| 76 | } | |||||
| 77 | ||||||
| 78 - 82 | =head1 get_xisbns($isbn); =head2 $isbn is an ISBN string =cut | |||||
| 83 | ||||||
| 84 | sub get_xisbns { | |||||
| 85 | 0 | my ( $isbn ) = @_; | ||||
| 86 | 0 | my ($response,$thing_response,$xisbn_response,$syndetics_response); | ||||
| 87 | # THINGISBN | |||||
| 88 | 0 | if ( C4::Context->preference('ThingISBN') ) { | ||||
| 89 | 0 | my $url = "http://www.librarything.com/api/thingISBN/".$isbn; | ||||
| 90 | 0 | $thing_response = _get_url($url,'thingisbn'); | ||||
| 91 | } | |||||
| 92 | ||||||
| 93 | 0 | if ( C4::Context->preference("SyndeticsEnabled") && C4::Context->preference("SyndeticsEditions") ) { | ||||
| 94 | 0 | my $syndetics_preresponse = &get_syndetics_editions($isbn); | ||||
| 95 | 0 | my @syndetics_response; | ||||
| 96 | 0 | for my $response (@$syndetics_preresponse) { | ||||
| 97 | 0 | push @syndetics_response, {content => $response->{a}}; | ||||
| 98 | } | |||||
| 99 | 0 | $syndetics_response = {isbn => \@syndetics_response}; | ||||
| 100 | } | |||||
| 101 | ||||||
| 102 | # XISBN | |||||
| 103 | 0 | if ( C4::Context->preference('XISBN') ) { | ||||
| 104 | 0 | my $affiliate_id=C4::Context->preference('OCLCAffiliateID'); | ||||
| 105 | 0 | my $limit = C4::Context->preference('XISBNDailyLimit') || 999; | ||||
| 106 | 0 | my $reached_limit = _service_throttle('xisbn',$limit); | ||||
| 107 | 0 | my $url = "http://xisbn.worldcat.org/webservices/xid/isbn/".$isbn."?method=getEditions&format=xml&fl=form,year,lang,ed"; | ||||
| 108 | 0 | $url.="&ai=".$affiliate_id if $affiliate_id; | ||||
| 109 | 0 | unless ($reached_limit) { | ||||
| 110 | 0 | $xisbn_response = _get_url($url,'xisbn'); | ||||
| 111 | } | |||||
| 112 | } | |||||
| 113 | ||||||
| 114 | 0 0 0 0 | $response->{isbn} = [ @{ $xisbn_response->{isbn} or [] }, @{ $syndetics_response->{isbn} or [] }, @{ $thing_response->{isbn} or [] } ]; | ||||
| 115 | 0 | my @xisbns; | ||||
| 116 | 0 | my $unique_xisbns; # a hashref | ||||
| 117 | ||||||
| 118 | # loop through each ISBN and scope to the local collection | |||||
| 119 | 0 0 | for my $response_data( @{ $response->{ isbn } } ) { | ||||
| 120 | 0 | next if $response_data->{'content'} eq $isbn; | ||||
| 121 | 0 | next if $isbn eq $response_data; | ||||
| 122 | 0 | next if $unique_xisbns->{ $response_data->{content} }; | ||||
| 123 | 0 | $unique_xisbns->{ $response_data->{content} }++; | ||||
| 124 | 0 | my $xbiblio= _get_biblio_from_xisbn($response_data->{content}); | ||||
| 125 | 0 | push @xisbns, $xbiblio if $xbiblio; | ||||
| 126 | } | |||||
| 127 | 0 | return \@xisbns; | ||||
| 128 | } | |||||
| 129 | ||||||
| 130 | sub _get_url { | |||||
| 131 | 0 | my ($url,$service_type) = @_; | ||||
| 132 | 0 | my $ua = LWP::UserAgent->new( | ||||
| 133 | timeout => 2 | |||||
| 134 | ); | |||||
| 135 | ||||||
| 136 | 0 | my $response = $ua->get($url); | ||||
| 137 | 0 | if ($response->is_success) { | ||||
| 138 | 0 | warn "WARNING could not retrieve $service_type $url" unless $response; | ||||
| 139 | 0 | if ($response) { | ||||
| 140 | 0 | my $xmlsimple = XML::Simple->new(); | ||||
| 141 | 0 | my $content = $xmlsimple->XMLin( | ||||
| 142 | $response->content, | |||||
| 143 | ForceArray => [ qw(isbn) ], | |||||
| 144 | ForceContent => 1, | |||||
| 145 | ); | |||||
| 146 | 0 | return $content; | ||||
| 147 | } | |||||
| 148 | } else { | |||||
| 149 | 0 | warn "WARNING: URL Request Failed " . $response->status_line . "\n"; | ||||
| 150 | } | |||||
| 151 | ||||||
| 152 | } | |||||
| 153 | ||||||
| 154 | ||||||
| 155 | # Throttle services to the specified amount | |||||
| 156 | sub _service_throttle { | |||||
| 157 | 0 | my ($service_type,$daily_limit) = @_; | ||||
| 158 | 0 | my $dbh = C4::Context->dbh; | ||||
| 159 | 0 | my $sth = $dbh->prepare("SELECT service_count FROM services_throttle WHERE service_type=?"); | ||||
| 160 | 0 | $sth->execute($service_type); | ||||
| 161 | 0 | my $count = 1; | ||||
| 162 | ||||||
| 163 | 0 | while (my $counter = $sth->fetchrow_hashref()) { | ||||
| 164 | 0 | $count = $counter->{service_count} if $counter->{service_count}; | ||||
| 165 | } | |||||
| 166 | ||||||
| 167 | # we're over the limit | |||||
| 168 | 0 | return 1 if $count >= $daily_limit; | ||||
| 169 | ||||||
| 170 | # not over the limit | |||||
| 171 | 0 | $count++; | ||||
| 172 | 0 | $sth = $dbh->do("UPDATE services_throttle SET service_count=$count WHERE service_type='xisbn'"); | ||||
| 173 | 0 | return undef; | ||||
| 174 | } | |||||
| 175 | ||||||
| 176 | 1; | |||||