my ( $dbh, $userid, $password, $query ) = @_;
if ($ldap) {
- $debug and print "## checkpw - checking LDAP\n";
+ $debug and print STDERR "## checkpw - checking LDAP\n";
my ($retval,$retcard,$retuserid) = checkpw_ldap(@_); # EXTERNAL AUTH
($retval) and return ($retval,$retcard,$retuserid);
}
my $dbh = C4::Context->dbh;
- my $batch_id = 0;
- if ($batch_type eq 'z3950') {
- $batch_id = GetZ3950BatchId($filename);
- } else {
- # create a new one
- $batch_id = AddImportBatch('create_new', 'staging', 'batch', $filename, '');
- }
+ my $batch_id = GetZ3950BatchId($filename);
my $searchisbn = $dbh->prepare("select biblioitemnumber from biblioitems where isbn=?");
my $searchissn = $dbh->prepare("select biblioitemnumber from biblioitems where issn=?");
# FIXME -- not sure that this kind of checking is actually needed
use C4::Debug;
use C4::Branch; # GetBranches
use C4::Log; # logaction
-
+use C4::Koha qw(GetAuthorisedValueByCode);
use Data::Dumper;
use Koha::DateUtils;
use Koha::Calendar;
{
$issuingimpossible{RESTRICTED} = 1;
}
+ if ( $item->{'itemlost'} ) {
+ $needsconfirmation{ITEM_LOST} = GetAuthorisedValueByCode( 'LOST', $item->{'itemlost'} );
+ }
if ( C4::Context->preference("IndependantBranches") ) {
my $userenv = C4::Context->userenv;
if ( ($userenv) && ( $userenv->{flags} % 2 != 1 ) ) {
my $bib_heading_fields;
-BEGIN {
+=head1 METHODS
+
+=head2 new
+
+ my $marc_handler = C4::Heading::UNIMARC->new();
+
+=cut
+
+sub new {
+ my $class = shift;
+
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare(
"SELECT tagfield, authtypecode
subfields => 'abcdefghjklmnopqrstvxyz',
};
}
-}
-
-=head1 METHODS
-=head2 new
-
- my $marc_handler = C4::Heading::UNIMARC->new();
-
-=cut
-
-sub new {
- my $class = shift;
return bless {}, $class;
}
@ISA = qw(Exporter);
@EXPORT = qw(
GetZ3950BatchId
+ GetWebserviceBatchId
GetImportRecordMarc
+ GetImportRecordMarcXML
AddImportBatch
GetImportBatch
AddBiblioToBatch
+ AddItemsToImportBiblio
ModBiblioInBatch
BatchStageMarcRecords
CleanBatch
GetAllImportBatches
+ GetStagedWebserviceBatches
GetImportBatchRangeDesc
GetNumberOfNonZ3950ImportBatches
GetImportBibliosRange
if (defined $rowref) {
return $rowref->[0];
} else {
- my $batch_id = AddImportBatch('create_new', 'staged', 'z3950', $z3950server, '');
+ my $batch_id = AddImportBatch( {
+ overlay_action => 'create_new',
+ import_status => 'staged',
+ batch_type => 'z3950',
+ file_name => $z3950server,
+ } );
return $batch_id;
}
}
+=head2 GetWebserviceBatchId
+
+ my $batchid = GetWebserviceBatchId();
+
+Retrieves the ID of the import batch for webservice.
+If necessary, creates the import batch.
+
+=cut
+
+my $WEBSERVICE_BASE_QRY = <<EOQ;
+SELECT import_batch_id FROM import_batches
+WHERE batch_type = 'webservice'
+AND import_status = 'staged'
+EOQ
+sub GetWebserviceBatchId {
+ my ($params) = @_;
+
+ my $dbh = C4::Context->dbh;
+ my $sql = $WEBSERVICE_BASE_QRY;
+ my @args;
+ foreach my $field (qw(matcher_id overlay_action nomatch_action item_action)) {
+ if (my $val = $params->{$field}) {
+ $sql .= " AND $field = ?";
+ push @args, $val;
+ }
+ }
+ my $id = $dbh->selectrow_array($sql, undef, @args);
+ return $id if $id;
+
+ $params->{batch_type} = 'webservice';
+ $params->{import_status} = 'staged';
+ return AddImportBatch($params);
+}
+
=head2 GetImportRecordMarc
my ($marcblob, $encoding) = GetImportRecordMarc($import_record_id);
}
-=head2 AddImportBatch
+=head2 GetImportRecordMarcXML
- my $batch_id = AddImportBatch($overlay_action, $import_status, $type,
- $file_name, $comments);
+ my $marcxml = GetImportRecordMarcXML($import_record_id);
=cut
-sub AddImportBatch {
- my ($overlay_action, $import_status, $type, $file_name, $comments) = @_;
+sub GetImportRecordMarcXML {
+ my ($import_record_id) = @_;
my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare("INSERT INTO import_batches (overlay_action, import_status, batch_type,
- file_name, comments)
- VALUES (?, ?, ?, ?, ?)");
- $sth->execute($overlay_action, $import_status, $type, $file_name, $comments);
- my $batch_id = $dbh->{'mysql_insertid'};
+ my $sth = $dbh->prepare("SELECT marcxml FROM import_records WHERE import_record_id = ?");
+ $sth->execute($import_record_id);
+ my ($marcxml) = $sth->fetchrow();
$sth->finish();
+ return $marcxml;
- return $batch_id;
+}
+
+=head2 AddImportBatch
+ my $batch_id = AddImportBatch($params_hash);
+
+=cut
+
+sub AddImportBatch {
+ my ($params) = @_;
+
+ my (@fields, @vals);
+ foreach (qw( matcher_id template_id branchcode
+ overlay_action nomatch_action item_action
+ import_status batch_type file_name comments )) {
+ if (exists $params->{$_}) {
+ push @fields, $_;
+ push @vals, $params->{$_};
+ }
+ }
+ my $dbh = C4::Context->dbh;
+ $dbh->do("INSERT INTO import_batches (".join( ',', @fields).")
+ VALUES (".join( ',', map '?', @fields).")",
+ undef,
+ @vals);
+ return $dbh->{'mysql_insertid'};
}
=head2 GetImportBatch
$progress_interval = 0 unless 'CODE' eq ref $progress_callback;
}
- my $batch_id = AddImportBatch('create_new', 'staging', 'batch', $file_name, $comments);
+ my $batch_id = AddImportBatch( {
+ overlay_action => 'create_new',
+ import_status => 'staging',
+ batch_type => 'batch',
+ file_name => $file_name,
+ comments => $comments,
+ } );
if ($parse_items) {
SetImportBatchItemAction($batch_id, 'always_add');
} else {
sub GetAllImportBatches {
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare_cached("SELECT * FROM import_batches
- WHERE batch_type = 'batch'
+ WHERE batch_type IN ('batch', 'webservice')
ORDER BY import_batch_id ASC");
my $results = [];
return $results;
}
+=head2 GetStagedWebserviceBatches
+
+ my $batch_ids = GetStagedWebserviceBatches();
+
+Returns a references to an array of batch id's
+of batch_type 'webservice' that are not imported
+
+=cut
+
+my $PENDING_WEBSERVICE_BATCHES_QRY = <<EOQ;
+SELECT import_batch_id FROM import_batches
+WHERE batch_type = 'webservice'
+AND import_status = 'staged'
+EOQ
+sub GetStagedWebserviceBatches {
+ my $dbh = C4::Context->dbh;
+ return $dbh->selectcol_arrayref($PENDING_WEBSERVICE_BATCHES_QRY);
+}
+
=head2 GetImportBatchRangeDesc
my $results = GetImportBatchRangeDesc($offset, $results_per_group);
my $dbh = C4::Context->dbh;
my $query = "SELECT * FROM import_batches
- WHERE batch_type = 'batch'
+ WHERE batch_type IN ('batch', 'webservice')
ORDER BY import_batch_id DESC";
my @params;
if ($results_per_group){
sub GetNumberOfNonZ3950ImportBatches {
my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare("SELECT COUNT(*) FROM import_batches WHERE batch_type='batch'");
+ my $sth = $dbh->prepare("SELECT COUNT(*) FROM import_batches WHERE batch_type != 'z3950'");
$sth->execute();
my ($count) = $sth->fetchrow_array();
$sth->finish();
my ($batch_id) = @_;
my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare_cached("UPDATE import_batches SET num_biblios = (
- SELECT COUNT(*)
- FROM import_records
- WHERE import_batch_id = import_batches.import_batch_id
- AND record_type = 'biblio')
- WHERE import_batch_id = ?");
- $sth->bind_param(1, $batch_id);
- $sth->execute();
- $sth->finish();
- $sth = $dbh->prepare_cached("UPDATE import_batches SET num_items = (
- SELECT COUNT(*)
- FROM import_records
- JOIN import_items USING (import_record_id)
- WHERE import_batch_id = import_batches.import_batch_id
- AND record_type = 'biblio')
+ my $sth = $dbh->prepare_cached("UPDATE import_batches SET
+ num_biblios = (
+ SELECT COUNT(*)
+ FROM import_records
+ WHERE import_batch_id = import_batches.import_batch_id
+ AND record_type = 'biblio'),
+ num_items = (
+ SELECT COUNT(*)
+ FROM import_records
+ JOIN import_items USING (import_record_id)
+ WHERE import_batch_id = import_batches.import_batch_id
+ AND record_type = 'biblio')
WHERE import_batch_id = ?");
$sth->bind_param(1, $batch_id);
$sth->execute();
$sth->finish();
-
}
sub _get_commit_action {
use C4::Koha;
use C4::Biblio;
use C4::Dates qw/format_date format_date_in_iso/;
-use C4::Search qw/SimpleSearch/;
use MARC::Record;
use C4::ClassSource;
use C4::Log;
return @results;
}
+=head2 GetMatcherId
+
+ my $matcher_id = C4::Matcher::GetMatcherId($code);
+
+Returns the matcher_id of a code.
+
+=cut
+
+sub GetMatcherId {
+ my ($code) = @_;
+ my $dbh = C4::Context->dbh;
+
+ my $matcher_id = $dbh->selectrow_array("SELECT matcher_id FROM marc_matchers WHERE code = ?", undef, $code);
+ return $matcher_id;
+}
+
=head1 METHODS
=head2 new
return ($overdue_count, $issue_count, $total_fines);
}
-sub columns(;$) {
- return @{C4::Context->dbh->selectcol_arrayref("SHOW columns from borrowers")};
-}
-
=head2 ModMember
my $success = ModMember(borrowernumber => $borrowernumber,
# FIXME: the locale should be set based on the user's language and/or search choice
#warn "$lang";
+ # Make sure we only use the first two letters from the language code
+ $lang = lc(substr($lang, 0, 2));
+ # The language codes for the two variants of Norwegian will now be "nb" and "nn",
+ # none of which Lingua::Stem::Snowball can use, so we need to "translate" them
+ if ($lang eq 'nb' || $lang eq 'nn') {
+ $lang = 'no';
+ }
my $stemmer = Lingua::Stem::Snowball->new( lang => $lang,
encoding => "UTF-8" );
use warnings;
use Carp;
use CGI;
-use List::Util qw/first/;
+use List::MoreUtils qw/any/;
# Copyright 2009 Chris Cormack and The Koha Dev Team
#
my ($query, $interface) = @_;
# Select a language based on cookie, syspref available languages & browser
- my $is_intranet = $interface eq 'intranet';
- my @languages = split(",", C4::Context->preference(
- $is_intranet ? 'language' : 'opaclanguages'));
+ my $preference_to_check =
+ $interface eq 'intranet' ? 'language' : 'opaclanguages';
+ my @languages = split /,/, C4::Context->preference($preference_to_check);
my $lang;
}
#Â HTTP_ACCEPT_LANGUAGE
- unless ($lang) {
- my $http_accept_language = $ENV{ HTTP_ACCEPT_LANGUAGE };
- $lang = accept_language( $http_accept_language,
- getTranslatedLanguages($interface,'prog') );
+ if ( !$lang && $ENV{HTTP_ACCEPT_LANGUAGE} ) {
+ $lang = accept_language( $ENV{HTTP_ACCEPT_LANGUAGE},
+ getTranslatedLanguages( $interface, 'prog' ) );
}
# Ignore a lang not selected in sysprefs
- $lang = undef unless first { $_ eq $lang } @languages;
+ if ( $lang && any { $_ eq $lang } @languages ) {
+ return $lang;
+ }
# Fall back to English if necessary
- $lang = 'en' unless $lang;
-
- return $lang;
+ return 'en';
}
1;
-
-# -*- tab-width: 8 -*-
-# Please use 8-character tabs for this file (indents are every 4 characters)
-
package C4::VirtualShelves;
-
# Copyright 2000-2002 Katipo Communications
#
# This file is part of Koha.
$qry1.= "ORDER BY vs.lastmodified DESC LIMIT $limit";
unless($adding_allowed && (!defined($owner) || $owner<=0)) {
- #if adding items, user should be known
- $pub= $dbh->selectall_arrayref($qry1,{Slice=>{}},@params);
+ #if adding items, user should be known
+ $pub= $dbh->selectall_arrayref($qry1,{Slice=>{}},@params);
}
if($owner) {
- my $qry2= $bquery. qq{
- LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber AND sh.borrowernumber=?
- WHERE vs.category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
- @params=($owner,$owner,$owner);
- $qry2.= "AND (allow_add=1 OR owner=?) " if $adding_allowed;
- push @params, $owner if $adding_allowed;
- $qry2.= "ORDER BY vs.lastmodified DESC ";
- $qry2.= "LIMIT $limit";
- $bar= $dbh->selectall_arrayref($qry2,{Slice=>{}},@params);
+ my $qry2= $bquery. qq{
+ LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber AND sh.borrowernumber=?
+ WHERE vs.category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
+ @params=($owner,$owner,$owner);
+ $qry2.= "AND (allow_add=1 OR owner=?) " if $adding_allowed;
+ push @params, $owner if $adding_allowed;
+ $qry2.= "ORDER BY vs.lastmodified DESC ";
+ $qry2.= "LIMIT $limit";
+ $bar= $dbh->selectall_arrayref($qry2,{Slice=>{}},@params);
}
return ( { bartotal => $bar? scalar @$bar: 0, pubtotal => $pub? scalar @$pub: 0}, $pub, $bar);
my $sth = $dbh->prepare($query);
$sth->execute(
- $hashref->{shelfname},
- $owner,
- $hashref->{category},
- $hashref->{sortfield},
- $hashref->{allow_add}||0,
- $hashref->{allow_delete_own}||1,
- $hashref->{allow_delete_other}||0 );
+ $hashref->{shelfname},
+ $owner,
+ $hashref->{category},
+ $hashref->{sortfield},
+ $hashref->{allow_add}||0,
+ $hashref->{allow_delete_own}||1,
+ $hashref->{allow_delete_other}||0 );
my $shelfnumber = $dbh->{'mysql_insertid'};
return $shelfnumber;
}
my $sth = $dbh->prepare($query);
$sth->execute( $shelfnumber, $biblionumber );
- ($sth->rows) and return undef; # already on shelf
+ ($sth->rows) and return undef; # already on shelf
$query = qq(
INSERT INTO virtualshelfcontents
(shelfnumber, biblionumber, flags, borrowernumber)
$query= "UPDATE virtualshelves SET shelfname=?, category=?, sortfield=?, allow_add=?, allow_delete_own=?, allow_delete_other=? WHERE shelfnumber=?";
$sth = $dbh->prepare($query);
$sth->execute(
- $hashref->{shelfname}||$oldrecord->{shelfname},
- $hashref->{category}||$oldrecord->{category},
- $hashref->{sortfield}||$oldrecord->{sortfield},
- $hashref->{allow_add}||$oldrecord->{allow_add},
- $hashref->{allow_delete_own}||$oldrecord->{allow_delete_own},
- $hashref->{allow_delete_other}||$oldrecord->{allow_delete_other},
- $shelfnumber );
+ $hashref->{shelfname}||$oldrecord->{shelfname},
+ $hashref->{category}||$oldrecord->{category},
+ $hashref->{sortfield}||$oldrecord->{sortfield},
+ $hashref->{allow_add}||$oldrecord->{allow_add},
+ $hashref->{allow_delete_own}||$oldrecord->{allow_delete_own},
+ $hashref->{allow_delete_other}||$oldrecord->{allow_delete_other},
+ $shelfnumber );
return $@? 0: 1;
}
return 0 unless $shelf && ($shelf->{category}==2 || $shelf->{owner}==$user || $shelf->{borrowernumber}==$user);
if($action eq 'view') {
- #already handled in the above condition
- return 1;
+ #already handled in the above condition
+ return 1;
}
elsif($action eq 'add') {
- return 0 if $user<=0; #should be logged in
- return 1 if $shelf->{allow_add}==1 || $shelf->{owner}==$user;
- #owner may always add
+ return 0 if $user<=0; #should be logged in
+ return 1 if $shelf->{allow_add}==1 || $shelf->{owner}==$user;
+ #owner may always add
}
elsif($action eq 'delete') {
#this answer is just diplomatic: it says that you may be able to delete
#some items from that shelf
#it does not answer the question about a specific biblio
#DelFromShelf checks the situation per biblio
- return 1 if $user>0 && ($shelf->{allow_delete_own}==1 || $shelf->{allow_delete_other}==1);
+ return 1 if $user>0 && ($shelf->{allow_delete_own}==1 || $shelf->{allow_delete_other}==1);
}
elsif($action eq 'manage') {
- return 1 if $user && $shelf->{owner}==$user;
+ return 1 if $user && $shelf->{owner}==$user;
}
return 0;
}
$query = qq(DELETE FROM virtualshelfcontents
WHERE shelfnumber=? AND biblionumber=? AND borrowernumber=?);
$sth= $dbh->prepare($query);
- foreach my $biblionumber (@$bibref) {
+ foreach my $biblionumber (@$bibref) {
$sth->execute($shelfnumber, $biblionumber, $user);
- $r= $sth->rows; #Expect -1, 0 or 1 (-1 means Don't know; count as 1)
- $t+= ($r==-1)? 1: $r;
- }
+ $r= $sth->rows; #Expect -1, 0 or 1 (-1 means Don't know; count as 1)
+ $t+= ($r==-1)? 1: $r;
+ }
}
if($del_oth) {
#includes a check if borrowernumber is null (deleted patron)
WHERE shelfnumber=? AND biblionumber=? AND
(borrowernumber IS NULL OR borrowernumber<>?)/;
$sth= $dbh->prepare($query);
- foreach my $biblionumber (@$bibref) {
+ foreach my $biblionumber (@$bibref) {
$sth->execute($shelfnumber, $biblionumber, $user);
- $r= $sth->rows;
- $t+= ($r==-1)? 1: $r;
- }
+ $r= $sth->rows;
+ $t+= ($r==-1)? 1: $r;
+ }
}
return $t;
}
=cut
sub ShelvesMax {
- my $which= shift;
- return SHELVES_POPUP_MAX if $which eq 'POPUP';
- return SHELVES_MGRPAGE_MAX if $which eq 'MGRPAGE';
- return SHELVES_COMBO_MAX if $which eq 'COMBO';
- return SHELVES_MASTHEAD_MAX if $which eq 'MASTHEAD';
- return SHELVES_MASTHEAD_MAX;
+ my $which= shift;
+ return SHELVES_POPUP_MAX if $which eq 'POPUP';
+ return SHELVES_MGRPAGE_MAX if $which eq 'MGRPAGE';
+ return SHELVES_COMBO_MAX if $which eq 'COMBO';
+ return SHELVES_MASTHEAD_MAX if $which eq 'MASTHEAD';
+ return SHELVES_MASTHEAD_MAX;
}
sub HandleDelBorrower {
@params= ($owner, $owner, $owner);
}
else {
- $query.='WHERE category=2';
+ $query.='WHERE category=2';
@params= ();
}
my $sth = $dbh->prepare($query);
my $query = 'select biblionumber from virtualshelfcontents where shelfnumber = ?';
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare($query)
- or die $dbh->errstr;
+ or die $dbh->errstr;
$sth->execute( $shelf )
- or die $sth->errstr;
+ or die $sth->errstr;
$sth;
}
my ($code,$shelf) = @_;
my $ref = _biblionumber_sth($shelf)->fetchall_arrayref;
map {
- $_=$$_[0];
- $code->();
- } @$ref;
+ $_=$$_[0];
+ $code->();
+ } @$ref;
}
sub _CheckShelfName {
my $query = qq(
SELECT DISTINCT shelfnumber
FROM virtualshelves
- LEFT JOIN virtualshelfshares sh USING (shelfnumber)
+ LEFT JOIN virtualshelfshares sh USING (shelfnumber)
WHERE shelfname=? AND shelfnumber<>?);
if($cat==1) {
$query.= ' AND (sh.borrowernumber=? OR owner=?) AND category=1';
$getreserv{biblionumber} = $getiteminfo->{'biblionumber'};
$getreserv{waitingat} = GetBranchName( $num_res->{'branchcode'} );
$getreserv{suspend} = $num_res->{'suspend'};
- $getreserv{suspend_until} = C4::Dates->new( $num_res->{'suspend_until'}, "iso")->output("syspref");
+ $getreserv{suspend_until} = $num_res->{'suspend_until'};
# check if we have a waiting status for reservations
if ( $num_res->{'found'} eq 'W' ) {
$getreserv{color} = 'reserved';
`nomatch_action` enum('create_new', 'ignore') NOT NULL default 'create_new',
`item_action` enum('always_add', 'add_only_for_matches', 'add_only_for_new', 'ignore') NOT NULL default 'always_add',
`import_status` enum('staging', 'staged', 'importing', 'imported', 'reverting', 'reverted', 'cleaned') NOT NULL default 'staging',
- `batch_type` enum('batch', 'z3950') NOT NULL default 'batch',
+ `batch_type` enum('batch', 'z3950', 'webservice') NOT NULL default 'batch',
`file_name` varchar(100),
`comments` mediumtext,
PRIMARY KEY (`import_batch_id`),
`chargename` varchar(100) default NULL,
`maxissueqty` int(4) default NULL,
`issuelength` int(4) default NULL,
+ `lengthunit` varchar(10) default 'days',
`hardduedate` date default NULL,
`hardduedatecompare` tinyint NOT NULL default "0",
`renewalsallowed` smallint(6) NOT NULL default "0",
$dbh->do("ALTER TABLE old_issues CHANGE returndate returndate datetime");
$dbh->do("ALTER TABLE old_issues CHANGE lastreneweddate lastreneweddate datetime");
$dbh->do("ALTER TABLE old_issues CHANGE issuedate issuedate datetime");
- $dbh->do("alter table issuingrules add column lengthunit varchar(10) default 'days' after issuelength");
print "Upgrade to $DBversion done (Setting up issues tables for hourly loans)\n";
SetVersion($DBversion);
}
SetVersion($DBversion);
}
+$DBversion = "3.07.00.045";
+if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+ $dbh->do("ALTER TABLE import_batches MODIFY COLUMN batch_type ENUM('batch','z3950','webservice') NOT NULL default 'batch'");
+ print "Upgrade to $DBversion done (Add 'webservice' to batch_type enum)\n";
+ SetVersion ($DBversion);
+}
+
+$DBversion = "3.07.00.046";
+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+ $dbh->do("ALTER TABLE issuingrules ADD COLUMN lengthunit varchar(10) DEFAULT 'days' AFTER issuelength");
+ print "Upgrade to $DBversion done (Setting up issues tables for hourly loans (lengthunit fix))\n";
+ SetVersion($DBversion);
+}
+
=head1 FUNCTIONS
=head2 DropAllForeignKeys($table)
}
/* borrower autocomplete */
-#borrowerautocomplete { width: 450px; text-align:left;} /* z-index needed on top instances for ie & sf absolute inside relative issue */
+#borrowerautocomplete { width: 500px; text-align:left;} /* z-index needed on top instances for ie & sf absolute inside relative issue */
.autocomplete .yui-ac-highlight ,
.autocomplete .yui-ac-highlight .sample-result,
.autocomplete .yui-ac-highlight .sample-query { color:#FFF; }
function yuiToolbar() {
var printmenu = [
[% IF ( CAN_user_borrowers ) %]
- { text: _("Print page"), onclick: {fn: function(){printx_window("page")}} },
+ { text: _("Print summary"), onclick: {fn: function(){printx_window("page")}} },
[% END %]
{ text: _("Print slip"), onclick: {fn: function(){printx_window("slip")}} },
- { text: _("Quick slip"), onclick: {fn: function(){printx_window("qslip")}} }
+ { text: _("Print quick slip"), onclick: {fn: function(){printx_window("qslip")}} }
];
var moremenu = [
[% IF ( CAN_user_borrowers ) %] <li><a id="changepassword" href="/cgi-bin/koha/members/member-password.pl?member=[% borrowernumber %]">Change password</a></li>[% END %]
[% END %]
<li><a id="duplicate" href="/cgi-bin/koha/members/memberentry.pl?op=duplicate&borrowernumber=[% borrowernumber %]&category_type=[% category_type %]">Duplicate</a></li>
- <li id="printmenuc"><a id="printpage" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=page">Print page</a></li>
+ <li id="printmenuc"><a id="printpage" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=page">Print summary</a></li>
<li><a id="printslip" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=slip">Print slip</a></li>
<li id="searchtoholdc"><a id="searchtohold" href="#">Search to hold</a></li>
<li id="moremenuc"><a id="renewpatron" href="/cgi-bin/koha/members/moremember.pl?reregistration=y&borrowernumber=[% borrowernumber %]">Renew account</a></li>
--- /dev/null
+
+<h1 id="logo"><a href="/cgi-bin/koha/mainpage.pl">[% LibraryName %]</a></h1><!-- Begin Main page Resident Search Box -->
+
+<div id="header_search">
+ [% INCLUDE 'patron-search-box.inc' %]
+[% IF ( CAN_user_circulate ) %]
+<div id="checkin_search" class="residentsearch" style="display:none;">
+ <p class="tip">Scan a barcode to check in:</p>
+ <form method="post" action="/cgi-bin/koha/circ/returns.pl" autocomplete="off">
+ <input name="barcode" id="ret_barcode" size="40" accesskey="r" />
+ <input value="Submit" class="submit" type="submit" />
+ </form>
+</div>[% END %]
+[% IF ( CAN_user_borrowers ) %]
+<div id="patron_search" class="residentsearch">
+ <p class="tip">Enter patron card number or partial name:</p>
+ <form action="/cgi-bin/koha/members/member.pl" method="post">
+ <input name="member" id="searchmember" size="40" type="text""/>
+ <input value="Submit" class="submit" type="submit" />
+ </form>
+</div>[% END %]
+[% IF ( CAN_user_catalogue ) %]
+<div id="catalog_search" class="residentsearch" style="display:none;">
+ <p class="tip">Enter search keywords:</p>
+ <form action="/cgi-bin/koha/catalogue/search.pl" method="get" id="cat-search-block">
+ <input type="text" name="q" id="search-form" size="40" accesskey="q" />
+ <input type="submit" class="submit" value="Submit"/>
+ </form>
+</div>[% END %]
+
+<ul>
+ [% IF ( CAN_user_circulate ) %]<li><a href="/cgi-bin/koha/circ/circulation.pl#circ_search">Check out</a></li>[% END %]
+ [% IF ( CAN_user_circulate ) %]<li><a href="/cgi-bin/koha/circ/returns.pl#checkin_search">Check in</a></li>[% END %]
+ [% IF ( CAN_user_borrowers ) %]<li><a href="/cgi-bin/koha/members/members-home.pl#patron_search">Search patrons</a></li>[% END %]
+ [% IF ( CAN_user_catalogue ) %]<li><a href="/cgi-bin/koha/catalogue/search.pl#catalog_search">Search the catalog</a></li>[% END %]
+</ul>
+
+</div>
+
+<!-- End Main page Resident Search Box -->
}
function yuiToolbar() {
var printmenu = [
- { text: _("Print page"), onclick: {fn: function(){printx_window("page")}} },
+ { text: _("Print summary"), onclick: {fn: function(){printx_window("page")}} },
{ text: _("Print slip"), onclick: {fn: function(){printx_window("slip")}} },
- { text: _("Quick slip"), onclick: {fn: function(){printx_window("qslip")}} }
+ { text: _("Print quick slip"), onclick: {fn: function(){printx_window("qslip")}} }
];
var moremenu = [
[% IF ( adultborrower AND activeBorrowerRelationship ) %]<li><a id="addchild" href="/cgi-bin/koha/members/memberentry.pl?op=add&guarantorid=[% borrowernumber %]&category_type=C">Add child</a></li>[% END %]
[% IF CAN_user_staffaccess %]<li><a id="changepassword" href="/cgi-bin/koha/members/member-password.pl?member=[% borrowernumber %]">Change password</a></li> [% END %]
<li><a id="duplicate" href="/cgi-bin/koha/members/memberentry.pl?op=duplicate&borrowernumber=[% borrowernumber %]&category_type=[% category_type %]">Duplicate</a></li>
- <li id="printmenuc"><a id="printpage" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=page">Print page</a></li>
+ <li id="printmenuc"><a id="printpage" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=page">Print summary</a></li>
<li><a id="printslip" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]&print=slip">Print slip</a></li>
<li id="searchtoholdc"><a id="searchtohold" href="#">Search to hold</a></li>
<li id="moremenuc"><a id="renewpatron" href="/cgi-bin/koha/members/moremember.pl?reregistration=y&borrowernumber=[% borrowernumber %]">Renew account</a></li>[% IF ( CAN_user_permissions ) %]<li><a id="patronflags" href="/cgi-bin/koha/members/member-flags.pl?member=[% borrowernumber %]">Set permissions</a></li>[% END %]<li><a id="deletepatron" href="javascript:confirm_deletion();">Delete</a></li>
<li>Norsk Nynorsk (Norwegian) Unni Knutsen and Marit Kristine Ã…dland</li>
<li>ArmenianTigran Zargaryan</li>
<li>(Indonesian)</li>
-<li>Italiano (Italian) Zeno Tajoli, Pietro Gozzetti and Paolo Pozzan</li>
+<li>Italiano (Italian) for 3.2: Zeno Tajoli, Pietro Gozzetti and Paolo Pozzan; for 3.4 and more: Zeno Tajoli, Stefano Bargioni, Paolo Bizzarri</li>
<li>日本語 (Japanese)</li>
<li>한국어 (Korean)</li>
<li>ಕನ್ನಡ (kannaḍa)</li>
- Automatically log out users after
- pref: timeout
class: integer
- - milliseconds of inactivity.
+ - seconds of inactivity. Adding d will specify it in days, e.g. 1d is timeout of one day.
-
- pref: AutoLocation
default: 0
- pref: numSearchRSSResults
class: long
- search results in the RSS feed.
+ -
+ - pref: SocialNetworks
+ default: 0
+ choices:
+ yes: Enable
+ no: Disable
+ - social network links in opac detail pages
Policy:
-
- pref: singleBranchMode
yes: Using
no: "Not using"
- 'ICU Zebra indexing. Please note: This setting will not affect Zebra indexing, it should only be used to tell Koha that you have activated ICU indexing if you have actually done so, since there is no way for Koha to figure this out on its own.'
- -
- - pref: SocialNetworks
- default: 0
- choices:
- yes: Enable
- no: Disable
- - Enable/Disable social network links in opac detail pages
Search Form:
-
- Show tabs in OPAC and staff-side advanced search for limiting searches on the
[% IF ( NOT_FOR_LOAN_FORCING ) %]
<li>Item is normally not for loan. Check out anyway?</li>
[% END %]
+
[% IF ( USERBLOCKEDOVERDUE ) %]
<li>Patron has [% USERBLOCKEDOVERDUE %] overdue item(s). Check out anyway?</li>
[% END %]
+
+[% IF ( ITEM_LOST ) %]
+ <li>This item has been lost with a status of "[% ITEM_LOST %]". Check out anyway?</li>
+[% END %]
</ul>
<form method="post" action="/cgi-bin/koha/circ/circulation.pl" autocomplete="off">
<input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
<input type="hidden" name="reservenumber" value="[% reservloo.reservenumber %]" />
</td>
- <td>[% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until %][% END %][% END %]</td>
+ <td>[% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until | $KohaDates %][% END %][% END %]</td>
</tr>
[% END %]</tbody>
</table>
- <fieldset class="action"><input type="submit" class="cancel" name="submit" value="Cancel Marked Requests" /></fieldset>
+ <fieldset class="action"><input type="submit" class="cancel" name="submit" value="Cancel marked holds" /></fieldset>
</form>
<fieldset class="action">
<form action="/cgi-bin/koha/reserve/modrequest_suspendall.pl" method="post">
<input type="hidden" name="from" value="circ" />
<input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
- <input type="submit" value="Suspend All Requests" />
+ <input type="submit" value="Suspend all holds" />
[% IF AutoResumeSuspendedHolds %]
<label for="suspend_until">until</label>
<input type="hidden" name="from" value="circ" />
<input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
<input type="hidden" name="suspend" value="0" />
- <input type="submit" value="Resume All Suspended All Requests" />
+ <input type="submit" value="Resume all suspended holds" />
</form>
</fieldset>
</head>
<body id="main_intranet-main" class="main">
[% INCLUDE 'header.inc' %]
-[% IF ( koha_news_count ) %]<div id="doc3" class="yui-t3">[% ELSE %]<div id="doc3" class="yui-t7">[% END %]
+[% INCLUDE 'home-search.inc' %]
+
+<div id="breadcrumbs">Home</div>
+
+<div id="doc3" class="yui-t3">
<div id="bd">
-[% IF ( koha_news_count ) %]<div id="yui-main"><div class="yui-b"><div class="yui-g">
-[% ELSE %] <div class="yui-g">[% END %]
+<div id="yui-main"><div class="yui-b"><div class="yui-g">
- <div class="yui-u first">
- [% IF ( CAN_user_circulate ) %]
- <h3><a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a></h3>
- <ul><li style="padding-bottom:.3em;">
- <form method="post" action="/cgi-bin/koha/circ/circulation.pl">
- <label for="navfindborrower">Check out to:</label>
- <input accesskey="u" id="navfindborrower" name="findborrower" type="text" size="10" />
- <input type="hidden" name="branch" value="[% branch %]" />
- <input type="hidden" name="printer" value="[% printer %]" />
- <input type="submit" class="submit" value="OK" />
- </form>
- </li>
- <li style="padding-bottom:.3em;">
- <form method="post" action="/cgi-bin/koha/circ/returns.pl">
- <label for="barcode">Check in:</label>
- <input accesskey="r" id="barcode" name="barcode" type="text" size="10" />
- <input type="submit" class="submit" value="OK" />
- </form></li>
+<h1>Welcome to Koha</h1>
- <li><a href="/cgi-bin/koha/circ/branchtransfers.pl">Transfers</a></li></ul>
- [% END %]
- [% IF ( CAN_user_borrowers ) %]
- <h3><a href="/cgi-bin/koha/members/members-home.pl">Patrons</a></h3>
- <ul>
- <li><form action="/cgi-bin/koha/members/member.pl" method="post">
- <label for="navmember">Search: </label>
- <input id="navmember" type="text" size="10" name="member" />
- <input type="submit" value="OK" class="submit" />
- </form>
- </li>
- </ul>
- [% END %]
- [% IF ( CAN_user_catalogue ) %]
- <h3><a href="/cgi-bin/koha/catalogue/search.pl">Search</a></h3>
- <ul>
- <li>
- <form name="searchform" method="get" action="/cgi-bin/koha/catalogue/search.pl" id="searchform">
- <input type="hidden" name="idx" value="" />
- <label for="navkeyword">
- Search catalog:
- </label><input type="text" id="navkeyword" name="q" size="10" accesskey="q" />
- <input type="submit" value="OK" class="submit" />
- </form>
- </li>
- </ul>
- [% END %]
- <h3><a href="/cgi-bin/koha/virtualshelves/shelves.pl">Lists</a></h3>
- </div>
-
- <div class="yui-u">
- [% IF ( CAN_user_editcatalogue_edit_catalogue ) %]
- <h3><a href="/cgi-bin/koha/cataloguing/addbooks.pl">Cataloging</a></h3>
- <ul>
- <li><a href="/cgi-bin/koha/cataloguing/addbiblio.pl">Add MARC Record</a></li>
- [% ELSE %]
- [% IF ( CAN_user_editauthorities ) %]
- <h3>Cataloging</h3>
+ <div class="yui-u first">
+ <!-- START - CIRCULATION -->
+ [% IF ( CAN_user_circulate ) %]
+ <h3><a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a></h3>
<ul>
+ <li><a href="/cgi-bin/koha/circ/branchtransfers.pl">Transfers</a></li>
+ </ul>
[% END %]
+ <!-- END - CIRCULATION -->
+
+ <!-- START - PATRONS -->
+ [% IF ( CAN_user_borrowers ) %]
+ <h3><a href="/cgi-bin/koha/members/members-home.pl">Patrons</a></h3>
[% END %]
-
- [% IF ( CAN_user_editauthorities ) %]
- <li><a href="/cgi-bin/koha/authorities/authorities-home.pl">Authorities</a></li>
+ <!-- END - PATRONS -->
+
+ <!-- START - ADVANCED SEARCH -->
+ [% IF ( CAN_user_catalogue ) %]
+ <h3><a href="/cgi-bin/koha/catalogue/search.pl">Advanced search</a></h3>
[% END %]
- </ul>
-
+ <!-- END - ADVANCED SEARCH -->
+ <!-- START - LISTS -->
+ <h3><a href="/cgi-bin/koha/virtualshelves/shelves.pl">Lists</a></h3>
+ <!-- END - LISTS -->
+
+ <!-- START - CATALOGING -->
+ [% IF ( CAN_user_catalogue || CAN_user_editcatalogue || CAN_user_editauthorities ) %]
+ <h3><a href="/cgi-bin/koha/cataloguing/addbooks.pl">Cataloging</a></h3>
+ <ul>
+ [% IF ( CAN_user_catalogue || CAN_user_editcatalogue ) %]
+ <li><a href="/cgi-bin/koha/cataloguing/addbiblio.pl">Add MARC Record</a></li>
+ [% END %]
+ [% IF ( CAN_user_editauthorities ) %]
+ <li><a href="/cgi-bin/koha/authorities/authorities-home.pl">Authorities</a></li>
+ [% END %]
+ </ul>
+ [% END %]
+ <!-- END - CATALOGING -->
+ </div>
+
+ <div class="yui-u">
+ <!-- START - SERIALS -->
[% IF ( CAN_user_serials ) %]
- <h3><a href="/cgi-bin/koha/serials/serials-home.pl">Serials</a></h3>
+ <h3><a href="/cgi-bin/koha/serials/serials-home.pl">Serials</a></h3>
[% END %]
- [% IF ( CAN_user_acquisition ) %]
- <h3><a href="/cgi-bin/koha/acqui/acqui-home.pl">Acquisitions</a></h3>
- [% IF ( pendingsuggestions ) %]<ul><li><a href="/cgi-bin/koha/suggestion/suggestion.pl">Suggestions pending approval</a>: <span class="holdcount"><a href="/cgi-bin/koha/suggestion/suggestion.pl">[% pendingsuggestions %]</a></span></li></ul>[% END %]
- [% END %]
+ [% IF ( CAN_user_acquisition ) %]
+ <h3><a href="/cgi-bin/koha/acqui/acqui-home.pl">Acquisitions</a></h3>
+ [% IF ( pendingsuggestions ) %]
+ <ul>
+ <li><a href="/cgi-bin/koha/suggestion/suggestion.pl">Suggestions pending approval</a>: <span class="holdcount"><a href="/cgi-bin/koha/suggestion/suggestion.pl">[% pendingsuggestions %]</a></span></li>
+ </ul>
+ [% END %]
+ [% END %]
+ <!-- END - SERIALS -->
+
+ <!-- START - REPORTS -->
[% IF ( CAN_user_reports ) %]
- <h3><a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a></h3>
+ <h3><a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a></h3>
[% END %]
+ <!-- END - REPORTS -->
+
+ <!-- START - ADMINISTRATION -->
[% IF ( CAN_user_parameters ) %]
- <h3><a href="/cgi-bin/koha/admin/admin-home.pl">Koha administration</a></h3>
- <ul>
- <li><a href="/cgi-bin/koha/admin/preferences.pl">System preferences</a></li>
- </ul>
- [% END %]
+ <h3><a href="/cgi-bin/koha/admin/admin-home.pl">Koha administration</a></h3>
+ <ul>
+ <li><a href="/cgi-bin/koha/admin/preferences.pl">System preferences</a></li>
+ </ul>
+ [% END %]
[% IF ( CAN_user_tools ) %]
- <h3><a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a></h3>
+ <h3><a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a></h3>
[% IF ( CAN_user_tools_moderate_comments && pendingcomments ) || ( CAN_user_tools_moderate_tags && pendingtags ) %]
<ul>
- [% IF ( CAN_user_tools_moderate_comments && pendingcomments ) %]<li><a href="/cgi-bin/koha/reviews/reviewswaiting.pl">Comments pending approval</a>: <span class="holdcount"><a href="/cgi-bin/koha/reviews/reviewswaiting.pl">[% pendingcomments %]</a></span></li>[% END %]
- [% IF ( CAN_user_tools_moderate_tags && pendingtags ) %]<li><a href="/cgi-bin/koha/tags/review.pl">Tags pending approval</a>: <span class="holdcount"><a href="/cgi-bin/koha/tags/review.pl">[% pendingtags %]</a></span></li>[% END %]
+ [% IF ( CAN_user_tools_moderate_comments && pendingcomments ) %]
+ <li><a href="/cgi-bin/koha/reviews/reviewswaiting.pl">Comments pending approval</a>: <span class="holdcount"><a href="/cgi-bin/koha/reviews/reviewswaiting.pl">[% pendingcomments %]</a></span></li>
+ [% END %]
+ [% IF ( CAN_user_tools_moderate_tags && pendingtags ) %]
+ <li><a href="/cgi-bin/koha/tags/review.pl">Tags pending approval</a>: <span class="holdcount"><a href="/cgi-bin/koha/tags/review.pl">[% pendingtags %]</a></span></li>
+ [% END %]
</ul>
[% END %]
[% END %]
+ <!-- END - ADMINISTRATION -->
+
+ <!-- START - ABOUT -->
<h3><a href="/cgi-bin/koha/about.pl">About Koha</a></h3>
- </div>
- </div>
- [% IF ( IntranetmainUserblock ) %]<div id="mainuserblock" class="yui-g">
- [% IntranetmainUserblock %]
- </div>[% ELSE %]
- [% END %]
-[% IF ( koha_news_count ) %]
- </div><!-- /yui-bd -->
- </div><!-- /yui-main -->
- <div class="yui-b">
- <div id="koha-news">
- <h3>News</h3>
- [% FOREACH koha_new IN koha_news %]
+ <!-- END - ABOUT -->
+ </div>
+ </div>
+ [% IF ( IntranetmainUserblock ) %]
+ <div id="mainuserblock" class="yui-g">
+ [% IntranetmainUserblock %]
+ </div>[% ELSE %]
+ [% END %]
+ </div><!-- /yui-bd -->
+ </div><!-- /yui-main -->
+ [% IF ( koha_news_count ) %]
+ <div class="yui-b">
+ <div id="koha-news">
+ <h3>News</h3>
+ [% FOREACH koha_new IN koha_news %]
<div class="newsitem" id="news[% koha_new.idnew %]"><h4>[% koha_new.title %]</h4>
- <p>[% koha_new.new %]</p>
- <p class="newsfooter"> Posted on [% koha_new.newdate %] [% IF ( CAN_user_tools ) %]
- <a href="/cgi-bin/koha/tools/koha-news.pl?op=add_form&id=[% koha_new.idnew %]">Edit</a> | <a href="/cgi-bin/koha/tools/koha-news.pl?op=del&ids=[% koha_new.idnew %]">Delete</a> | <a href="/cgi-bin/koha/tools/koha-news.pl?op=add_form">New</a>[% END %]</p></div>
- [% END %]
- </div><!-- /koha-news -->
- </div>
-[% END %]
+ <p>[% koha_new.new %]</p>
+ <p class="newsfooter"> Posted on [% koha_new.newdate %]
+ [% IF ( CAN_user_tools ) %]
+ <a href="/cgi-bin/koha/tools/koha-news.pl?op=add_form&id=[% koha_new.idnew %]">Edit</a> | <a href="/cgi-bin/koha/tools/koha-news.pl?op=del&ids=[% koha_new.idnew %]">Delete</a> | <a href="/cgi-bin/koha/tools/koha-news.pl?op=add_form">New</a>
+ [% END %]
+ </p>
+ </div>
+ [% END %]
+ </div><!-- /koha-news -->
+ </div>
+ [% END %]
+
</div>
<input type="hidden" name="biblionumber" value="[% reservloo.biblionumber %]" />
<input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
</td>
- <td>[% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until %][% END %][% END %]</td>
+ <td>[% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until | $KohaDates %][% END %][% END %]</td>
</tr>
[% END %]</tbody>
</table>
- <fieldset class="action"><input type="submit" class="cancel" name="submit" value="Cancel Marked Requests" /></fieldset>
+ <fieldset class="action"><input type="submit" class="cancel" name="submit" value="Cancel marked holds" /></fieldset>
</form>
<fieldset class="action">
<form action="/cgi-bin/koha/reserve/modrequest_suspendall.pl" method="post">
<input type="hidden" name="from" value="borrower" />
<input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
- <input type="submit" value="Suspend All Requests" />
+ <input type="submit" value="Suspend all holds" />
[% IF AutoResumeSuspendedHolds %]
<label for="suspend_until">until</label>
<input type="hidden" name="from" value="borrower" />
<input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
<input type="hidden" name="suspend" value="0" />
- <input type="submit" value="Resume All Suspended All Requests" />
+ <input type="submit" value="Resume all suspended holds" />
</form>
</fieldset>
use strict;
sub kohaversion {
- our $VERSION = '3.07.00.044';
+ our $VERSION = '3.07.00.046';
# version needs to be set this way
# so that it can be picked up by Makefile.PL
# during install
}
$getreserv{waitingposition} = $num_res->{'priority'};
$getreserv{suspend} = $num_res->{'suspend'};
- $getreserv{suspend_until} = C4::Dates->new( $num_res->{'suspend_until'}, "iso")->output("syspref");;
+ $getreserv{suspend_until} = $num_res->{'suspend_until'};
push( @reservloop, \%getreserv );
}
--- /dev/null
+#!/usr/bin/perl -w
+
+# Copyright 2012 CatalystIT
+#
+# 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 Getopt::Long;
+
+my ($help, $config, $daemon);
+
+GetOptions(
+ 'config|c=s' => \$config,
+ 'daemon|d' => \$daemon,
+ 'help|?' => \$help,
+);
+
+if($help || !$config){
+ print <<EOF
+$0 --config=my.conf
+Parameters :
+ --daemon | -d - go to background; prints pid to stdout
+ --config | -c - config file
+ --help | -? - this message
+
+Config file format:
+ Lines of the form:
+ name: value
+
+ # comments are supported
+ No quotes
+
+ Parameter Names:
+ host - ip address or hostname to bind to, defaults all available
+ port - port to bind to, mandatory
+ log - log file path, stderr if omitted
+ debug - dumps requests to the log file, passwords inclusive
+ koha - koha intranet base url, eg http://librarian.koha
+ user - koha user, authentication
+ password - koha user password, authentication
+ match - marc_matchers.code: ISBN or ISSN
+ overlay_action - import_batches.overlay_action: replace, create_new or ignore
+ nomatch_action - import_batches.nomatch_action: create_new or ignore
+ item_action - import_batches.item_action: always_add,
+ add_only_for_matches, add_only_for_new or ignore
+ import_mode - stage or direct
+ framework - to be used if import_mode is direct
+
+ All process related parameters (all but ip and port) have default values as
+ per Koha import process.
+EOF
+;
+ exit;
+}
+
+my $server = ImportProxyServer->new($config);
+
+if ($daemon) {
+ print $server->background;
+} else {
+ $server->run;
+}
+
+exit;
+
+{
+package ImportProxyServer;
+
+use Carp;
+use IO::Socket::INET;
+# use IO::Socket::IP;
+use IO::Select;
+use POSIX;
+use HTTP::Status qw(:constants);
+
+use LWP::UserAgent;
+use XML::Simple;
+
+use constant CLIENT_READ_TIMEOUT => 5;
+use constant CLIENT_READ_BUFFER_SIZE => 4 * 1024;
+use constant AUTH_URI => "/cgi-bin/koha/mainpage.pl";
+use constant IMPORT_SVC_URI => "/cgi-bin/koha/svc/import_bib";
+
+sub new {
+ my $class = shift;
+ my $config_file = shift or croak "No config file";
+
+ my $self = {time_to_die => 0, config_file => $config_file };
+ bless $self, $class;
+
+ $self->parse_config;
+ return $self;
+}
+
+sub parse_config {
+ my $self = shift;
+
+ my $config_file = $self->{config_file};
+
+ open (my $conf_fh, '<', $config_file) or die "Cannot open config file $config: $!";
+
+ my %param;
+ my $line = 0;
+ while (<$conf_fh>) {
+ $line++;
+ chomp;
+ s/\s*#.*//o; # remove comments
+ s/^\s+//o; # trim leading spaces
+ s/\s+$//o; # trim trailing spaces
+ next unless $_;
+
+ my ($p, $v) = m/(\S+?):\s*(.*)/o;
+ die "Invalid config line $line: $_" unless defined $v;
+ $param{$p} = $v;
+ }
+
+ $self->{koha} = delete( $param{koha} )
+ or die "No koha base url in config file";
+ $self->{user} = delete( $param{user} )
+ or die "No koha user in config file";
+ $self->{password} = delete( $param{password} )
+ or die "No koha user password in config file";
+
+ $self->{host} = delete( $param{host} );
+ $self->{port} = delete( $param{port} )
+ or die "Port not specified";
+
+ $self->{debug} = delete( $param{debug} );
+
+ my $log_fh;
+ close $self->{log_fh} if $self->{log_fh};
+ if (my $logfile = delete $param{log}) {
+ open ($log_fh, '>>', $logfile) or die "Cannot open $logfile for write: $!";
+ } else {
+ $log_fh = \*STDERR;
+ }
+ $self->{log_fh} = $log_fh;
+
+ $self->{params} = \%param;
+}
+
+sub log {
+ my $self = shift;
+ my $log_fh = $self->{log_fh}
+ or warn "No log fh",
+ return;
+ my $t = localtime;
+ print $log_fh map "$t: $_\n", @_;
+}
+
+sub background {
+ my $self = shift;
+
+ my $pid = fork;
+ return ($pid) if $pid; # parent
+
+ die "Couldn't fork: $!" unless defined($pid);
+
+ POSIX::setsid() or die "Can't start a new session: $!";
+
+ $SIG{INT} = $SIG{TERM} = $SIG{HUP} = sub { $self->{time_to_die} = 1 };
+ # trap or ignore $SIG{PIPE}
+ $SIG{USR1} = sub { $self->parse_config };
+
+ $self->run;
+}
+
+sub run {
+ my $self = shift;
+
+ my $server_port = $self->{port};
+ my $server_host = $self->{host};
+
+ my $server = IO::Socket::INET->new(
+ LocalHost => $server_host,
+ LocalPort => $server_port,
+ Type => SOCK_STREAM,
+ Proto => "tcp",
+ Listen => 12,
+ Blocking => 1,
+ ReuseAddr => 1,
+ ) or die "Couldn't be a tcp server on port $server_port: $! $@";
+
+ $self->log("Started tcp listener on $server_host:$server_port");
+
+ $self->{ua} = _ua();
+
+ while ("FOREVER") {
+ my $client = $server->accept()
+ or die "Cannot accept: $!";
+ my $oldfh = select($client);
+ $self->handle_request($client);
+ select($oldfh);
+ last if $self->{time_to_die};
+ }
+
+ close($server);
+}
+
+sub _ua {
+ my $ua = LWP::UserAgent->new;
+ $ua->timeout(10);
+ $ua->cookie_jar({});
+ return $ua;
+}
+
+sub read_request {
+ my ( $self, $io ) = @_;
+
+ my ($in, @in, $timeout);
+ my $select = IO::Select->new($io) ;
+ while ( "FOREVER" ) {
+ if ( $select->can_read(CLIENT_READ_TIMEOUT) ){
+ $io->recv($in, CLIENT_READ_BUFFER_SIZE);
+ last unless $in;
+
+ # XXX ignore after NULL
+ if ( $in =~ m/^(.*)\000/so ) { # null received, EOT
+ push @in, $1;
+ last;
+ }
+ push @in, $in;
+ }
+ else {
+ $timeout = 1;
+ last;
+ }
+ }
+
+ $in = join '', @in;
+
+ my ($xml, $user, $password, $local_user);
+ my $data = $in; # copy for diagmostic purposes
+ while ( my $first = substr( $data, 0, 1 ) ) {
+ $first eq 'U' && do {
+ ($user, $data) = _trim_identifier($data);
+ next;
+ };
+ $first eq 'A' && do {
+ ($local_user, $data) = _trim_identifier($data);
+ next;
+ };
+ $first eq 'P' && do {
+ ($password,, $data) = _trim_identifier($data);
+ next;
+ };
+ $first eq ' ' && do {
+ $data = substr( $data, 1 ); # trim
+ next;
+ };
+ $first eq '<' && do {
+ $xml = $data;
+ last;
+ };
+
+ last; # unexpected input
+ }
+
+ my @details;
+ push @details, "Timeout" if $timeout;
+ push @details, "User: $user" if $user;
+ push @details, "Password: " . ( $self->{debug} ? $password : ("x" x length($password)) ) if $password;
+ push @details, "Local user: $local_user" if $local_user;
+ unless ($xml) {
+ $self->log("Invalid request", $in, @details);
+ return;
+ }
+
+ $self->log("Request", @details);
+ $self->log($in) if $self->{debug};
+ return ($xml, $user, $password);
+}
+
+sub _trim_identifier {
+ my ($a, $len) = unpack "cc", substr( $_[0], 0, 2 );
+
+ return ( substr( $_[0], 2, $len ), substr( $_[0], 2 + $len ) );
+}
+
+sub handle_request {
+ my ( $self, $io ) = @_;
+
+ my ($data, $user, $password) = $self->read_request($io)
+ or return $self->error_response("Bad request");
+
+ my $ua;
+ if ($self->{user}) {
+ $user = $self->{user};
+ $password = $self->{password};
+ $ua = $self->{ua};
+ }
+ else {
+ $ua = _ua(); # fresh one, needs to authenticate
+ }
+
+ my $base_url = $self->{koha};
+ my $resp = $ua->post( $base_url.IMPORT_SVC_URI, $self->{params}, 'Content-Type' => 'text/plain', Content => $data );
+ my $status = $resp->code;
+ if ($status == HTTP_UNAUTHORIZED || $status == HTTP_FORBIDDEN) {
+ my $user = $self->{user};
+ my $password = $self->{password};
+ $resp = $ua->post( $base_url.AUTH_URI, { userid => $user, password => $password } );
+ $resp = $ua->post( $base_url.IMPORT_SVC_URI, $self->{params}, 'Content-Type' => 'text/plain', Content => $data )
+ if $resp->is_success;
+ }
+ unless ($resp->is_success) {
+ $self->log("Unsuccessful request", $resp->request->as_string, $resp->as_string);
+ return $self->error_response("Unsuccessful request");
+ }
+
+ my ($koha_status, $bib, $batch_id, $error);
+ if ( my $r = eval { XMLin($resp->content) } ) {
+ $koha_status = $r->{status};
+ $batch_id = $r->{import_batch_id};
+ $error = $r->{error};
+ }
+ else {
+ $koha_status = "error";
+ $self->log("Response format error:\n$resp->content");
+ return $self->error_response("Invalid response");
+ }
+
+ if ($koha_status eq "ok") {
+ return $self->response( sprintf( "Success. Import batch id: %s", $batch_id ) );
+ }
+
+ return $self->error_response( sprintf( "%s. Please contact administrator.", $error ) );
+}
+
+sub error_response {
+ my $self = shift;
+ $self->response(@_);
+}
+
+sub response {
+ my $self = shift;
+ $self->log("Response: $_[0]");
+ printf $_[0] . "\0";
+}
+
+
+} # package
--- /dev/null
+#!/usr/bin/perl -w
+
+# Copyright 2012 CatalystIT
+#
+# 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 utf8;
+
+BEGIN {
+
+ # find Koha's Perl modules
+ # test carefully before changing this
+ use FindBin;
+ eval { require "$FindBin::Bin/../kohalib.pl" };
+}
+
+use Getopt::Long;
+use Pod::Usage;
+use C4::ImportBatch;
+
+my ($help, $framework);
+
+GetOptions(
+ 'help|?' => \$help,
+ 'framework=s' => \$framework,
+);
+
+if($help){
+ print <<EOF
+$0 --framework=myframework
+Parameters :
+--help|? This message
+--framework default ""
+EOF
+;
+ exit;
+}
+
+my $batch_ids = GetStagedWebserviceBatches() or exit;
+
+$framework ||= '';
+BatchCommitBibRecords($_, $framework) foreach @$batch_ids;
for (my $i=0;$i<@servers;$i++) {
my $server = $servers[$i];
$hits = $results_hashref->{$server}->{"hits"};
- @newresults = searchResults('opac', '', $hits, $results_per_page, $offset, $arrParamsBusc->{'scan'}, @{$results_hashref->{$server}->{"RECORDS"}},, C4::Context->preference('hidelostitems'));
+ my @records = $results_hashref->{$server}->{"RECORDS"};
+ @newresults = searchResults('opac', '', $hits, $results_per_page, $offset, $arrParamsBusc->{'scan'}, \@records,, C4::Context->preference('hidelostitems'));
}
return \@newresults;
}#searchAgain
--- /dev/null
+#!/usr/bin/perl
+
+# Copyright 2012 CatalystIT Ltd
+#
+# 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 qw/check_api_auth/;
+use C4::Context;
+use C4::ImportBatch;
+use C4::Matcher;
+use XML::Simple;
+# use Carp::Always;
+
+my $query = new CGI;
+binmode STDOUT, ':encoding(UTF-8)';
+
+my ($status, $cookie, $sessionID) = check_api_auth($query, { editcatalogue => 'edit_catalogue'} );
+unless ($status eq "ok") {
+ print $query->header(-type => 'text/xml', -status => '403 Forbidden');
+ print XMLout({ auth_status => $status }, NoAttr => 1, RootName => 'response', XMLDecl => 1);
+ exit 0;
+}
+
+my $xml;
+if ($query->request_method eq "POST") {
+ $xml = $query->param('POSTDATA');
+}
+if ($xml) {
+ my %params = map { $_ => $query->url_param($_) } $query->url_param;
+ my $result = import_bib($xml, \%params );
+ print $query->header(-type => 'text/xml');
+ print XMLout($result, NoAttr => 1, RootName => 'response', XMLDecl => 1);
+} else {
+ print $query->header(-type => 'text/xml', -status => '400 Bad Request');
+}
+
+exit 0;
+
+sub import_bib {
+ my ($inxml, $params) = @_;
+
+ my $result = {};
+
+ my $import_mode = delete $params->{import_mode} || '';
+ my $framework = delete $params->{framework} || '';
+
+ if (my $matcher_code = delete $params->{matcher}) {
+ $params->{matcher_id} = C4::Matcher::GetMatcherId($matcher_code);
+ }
+
+ my $batch_id = GetWebserviceBatchId($params);
+ unless ($batch_id) {
+ $result->{'status'} = "failed";
+ $result->{'error'} = "Batch create error";
+ return $result;
+ }
+
+ my $marcflavour = C4::Context->preference('marcflavour') || 'MARC21';
+ my $marc_record = eval {MARC::Record::new_from_xml( $inxml, "utf8", $marcflavour)};
+ if ($@) {
+ $result->{'status'} = "failed";
+ $result->{'error'} = $@;
+ return $result;
+ }
+
+ my $import_record_id = AddBiblioToBatch($batch_id, 0, $marc_record, "utf8", int(rand(99999)));
+ my @import_items_ids = AddItemsToImportBiblio($batch_id, $import_record_id, $marc_record, 'UPDATE COUNTS');
+ my $marcxml = GetImportRecordMarcXML($import_record_id);
+ unless ($marcxml) {
+ $result->{'status'} = "failed";
+ $result->{'error'} = "database write error";
+ return $result;
+ }
+ $marcxml =~ s/<\?xml.*?\?>//i;
+
+ # XXX we are ignoring the result of this;
+ BatchCommitBibRecords($batch_id, $framework) if lc($import_mode) eq 'direct';
+
+ $result->{'status'} = "ok";
+ $result->{'import_batch_id'} = $batch_id;
+ $result->{'marcxml'} = $marcxml;
+ return $result;
+}
+++ /dev/null
-#!/usr/bin/perl
-#
-# This Koha test module is a stub!
-# Add more tests here!!!
-
-use strict;
-use warnings;
-
-use Test::More tests => 3;
-use C4::Context;
-
-BEGIN {
- use_ok('C4::Heading');
-}
-
-SKIP: {
- skip "MARC21 heading tests not applicable to UNIMARC", 2 if C4::Context->preference('marcflavour') eq 'UNIMARC';
- my $field = MARC::Field->new( '650', ' ', '0', a => 'Uncles', x => 'Fiction' );
- my $heading = C4::Heading->new_from_bib_field($field);
- is($heading->display_form(), 'Uncles--Fiction', 'Display form generation');
- is($heading->search_form(), 'Uncles generalsubdiv Fiction', 'Search form generation');
-}
--- /dev/null
+#!/usr/bin/perl
+#
+# This Koha test module is a stub!
+# Add more tests here!!!
+
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+use C4::Context;
+
+BEGIN {
+ use_ok('C4::Heading');
+}
+
+SKIP: {
+ skip "MARC21 heading tests not applicable to UNIMARC", 2 if C4::Context->preference('marcflavour') eq 'UNIMARC';
+ my $field = MARC::Field->new( '650', ' ', '0', a => 'Uncles', x => 'Fiction' );
+ my $heading = C4::Heading->new_from_bib_field($field);
+ is($heading->display_form(), 'Uncles--Fiction', 'Display form generation');
+ is($heading->search_form(), 'Uncles generalsubdiv Fiction', 'Search form generation');
+}
file_name => 'foo',
comments => 'inserted during automated testing',
};
- my $batch_id = AddImportBatch( $test_batch->{'overlay_action'},
- $test_batch->{'import_status'},
- $test_batch->{'batch_type'},
- $test_batch->{'file_name'},
- $test_batch->{'comments'}, );
+ my $batch_id = AddImportBatch( $test_batch );
return $batch_id;
}
+++ /dev/null
-package KohaTest::ImportBatch::AddImportBatch;
-use base qw( KohaTest::ImportBatch );
-
-use strict;
-use warnings;
-
-use Test::More;
-
-use C4::ImportBatch;
-use C4::Matcher;
-use C4::Biblio;
-
-
-=head3 add_one
-
-=cut
-
-sub add_one : Test( 1 ) {
- my $self = shift;
-
- my $batch_id = AddImportBatch(
- 'create_new', #overlay_action
- 'staging', # import_status
- 'batch', # batc_type
- 'foo', # file_name
- 'inserted during automated testing', # comments
- );
- ok( $batch_id, "successfully inserted batch: $batch_id" );
-}
-
-1;
file_name => 'foo',
comments => 'inserted during automated testing',
};
- my $batch_id = AddImportBatch(
- $batch->{'overlay_action'},
- $batch->{'import_status'},
- $batch->{'batch_type'},
- $batch->{'file_name'},
- $batch->{'comments'},
- );
+ my $batch_id = AddImportBatch($batch);
ok( $batch_id, "successfully inserted batch: $batch_id" );
my $retrieved = GetImportBatch( $batch_id );
num_items => $batch->{'num_items'},
upload_timestamp => $batch->{'upload_timestamp'},
import_status => $batch->{'import_status'},
- file_name => $batch->{'file_name'},
+ file_name => $batch->{'file_name'} || "($batch->{'batch_type'})",
comments => $batch->{'comments'},
can_clean => ($batch->{'import_status'} ne 'cleaned') ? 1 : 0,
};