Bug 8015: Add MARC Modifications Templates

The MARC Modification Templates system gives Koha users
the power to make alterations to MARC records automatically
while staging MARC records for import.

This tool is useful for altering MARC records from
various venders work with your MARC framework.

The system essentially allows one to create a basic script
using actions to Copy, Move, Add, Update and Delete fields.

Each action can also have an optional condition to check
the value or existance of another field.

The Copy & Move actions also support Regular Expressions,
which can be used to automatically modify field values during the
copy/move. An example would be to strip out the '$' character
in field 020$c.

Furthermore, the value for an update can include variables
that change each time the template is used. Currently,
the system supports two variables, __BRANCHCODE__ which
is replaced with the branchcode of the library currently
using the template, and __CURRENTDATE__ which is replaced
with the current date in ISO format ( YYYY-MM-DD ).

At its simplist, it can perform functions such as:
Copy field 092$a to 952$c
At its most complex it can run actions like:
Copy field 020$c to 020$c using RegEx s/\$// if 020$c equals RegEx m/^\$/

Signed-off-by: Leila <koha.aixmarseille@gmail.com>
Signed-off-by: Galen Charlton <gmc@esilibrary.com>
This commit is contained in:
Kyle M Hall 2012-04-26 16:08:57 -04:00 committed by Galen Charlton
parent 7c521a8cf2
commit 622430cfb5
14 changed files with 1688 additions and 5 deletions

View File

@ -26,6 +26,7 @@ use C4::Biblio;
use C4::Items;
use C4::Charset;
use C4::AuthoritiesMarc;
use Koha::MarcModificationTemplates;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
@ -316,7 +317,7 @@ sub ModAuthInBatch {
=head2 BatchStageMarcRecords
($batch_id, $num_records, $num_items, @invalid_records) =
BatchStageMarcRecords($record_type, $encoding, $marc_records, $file_name,
BatchStageMarcRecords($encoding, $marc_records, $file_name, $marc_modification_template,
$comments, $branch_code, $parse_items,
$leave_as_staging,
$progress_interval, $progress_callback);
@ -328,6 +329,7 @@ sub BatchStageMarcRecords {
my $encoding = shift;
my $marc_records = shift;
my $file_name = shift;
my $marc_modification_template = shift;
my $comments = shift;
my $branch_code = shift;
my $parse_items = shift;
@ -378,6 +380,8 @@ sub BatchStageMarcRecords {
$encoding = $charset_guessed unless $encoding;
ModifyRecordWithTemplate( $marc_modification_template, $marc_record ) if ( $marc_modification_template );
my $import_record_id;
if (scalar($marc_record->fields()) == 0) {
push @invalid_records, $marc_blob;

View File

@ -1486,6 +1486,23 @@ sub _isbn_cleanup {
return;
}
=head2
Log( $message );
Writes data to /tmp/koha.log.
This is useful for debugging forked processes
that do not write to the apache error log
=cut
sub Log {
my ($data) = @_;
open (MYFILE, '>>/tmp/koha.log');
print MYFILE "$data\n";
close (MYFILE);
}
1;
__END__

View File

@ -0,0 +1,579 @@
package Koha::MarcModificationTemplates;
# Copyright 2010 Kyle M Hall <kyle.m.hall@gmail.com>
#
# 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.
## NOTE:
## Parts of this module are used from cgi scripts that are detached from apache before
## execution. For this reason, the C4::Koha::Log function has been used to capture
## output for debugging purposes.
use strict;
use warnings;
use DateTime;
use C4::Context;
use Koha::SimpleMARC;
use vars qw($VERSION @ISA @EXPORT);
use constant DEBUG => 0;
BEGIN {
$VERSION = 1.00; # set the version for version checking
@ISA = qw(Exporter);
@EXPORT = qw(
&GetModificationTemplates
&AddModificationTemplate
&DelModificationTemplate
&GetModificationTemplateAction
&GetModificationTemplateActions
&AddModificationTemplateAction
&ModModificationTemplateAction
&DelModificationTemplateAction
&MoveModificationTemplateAction
&ModifyRecordsWithTemplate
&ModifyRecordWithTemplate
);
}
=head1 NAME
Koha::MarcModificationTemplates - Module to manage MARC Modification Templates
=head1 DESCRIPTION
MARC Modification Templates are a tool for marc batch imports,
so that librarians can set up templates for various vendors'
files telling Koha what fields to insert data into.
=head1 FUNCTIONS
=cut
=head2 GetModificationTemplates
my @templates = GetModificationTemplates( [ $template_id ] );
Passing a $template_id will mark the given id as the selected template.
=cut
sub GetModificationTemplates {
my ( $template_id ) = @_;
C4::Koha::Log("Koha::MarcModificationTemplates::GetModificationTemplates( $template_id )") if DEBUG;
warn("Koha::MarcModificationTemplates::GetModificationTemplates( $template_id )") if DEBUG;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT * FROM marc_modification_templates");
$sth->execute();
my @templates;
while ( my $template = $sth->fetchrow_hashref() ) {
$template->{'selected'} = 1 if ( $template->{'template_id'} eq $template_id );
push( @templates, $template );
}
return @templates;
}
=head2
AddModificationTemplate
$template_id = AddModificationTemplate( $template_name[, $template_id ] );
If $template_id is supplied, the actions from that template will be copied
into the newly created template.
=cut
sub AddModificationTemplate {
my ( $template_name, $template_id_copy ) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("INSERT INTO marc_modification_templates ( name ) VALUES ( ? )");
$sth->execute( $template_name );
$sth = $dbh->prepare("SELECT * FROM marc_modification_templates WHERE name = ?");
$sth->execute( $template_name );
my $row = $sth->fetchrow_hashref();
my $template_id = $row->{'template_id'};
if ( $template_id_copy ) {
my @actions = GetModificationTemplateActions( $template_id_copy );
foreach my $action ( @actions ) {
AddModificationTemplateAction(
$template_id,
$action->{'action'},
$action->{'field_number'},
$action->{'from_field'},
$action->{'from_subfield'},
$action->{'field_value'},
$action->{'to_field'},
$action->{'to_subfield'},
$action->{'to_regex'},
$action->{'conditional'},
$action->{'conditional_field'},
$action->{'conditional_subfield'},
$action->{'conditional_comparison'},
$action->{'conditional_value'},
$action->{'conditional_regex'},
$action->{'description'},
);
}
}
return $template_id;
}
=head2
DelModificationTemplate
DelModificationTemplate( $template_id );
=cut
sub DelModificationTemplate {
my ( $template_id ) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("DELETE FROM marc_modification_templates WHERE template_id = ?");
$sth->execute( $template_id );
$sth = $dbh->prepare("DELETE FROM marc_modification_template_actions WHERE template_id = ?");
$sth->execute( $template_id );
}
=head2
GetModificationTemplateAction
my $action = GetModificationTemplateAction( $mmta_id );
=cut
sub GetModificationTemplateAction {
my ( $mmta_id ) = @_;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT * FROM marc_modification_template_actions WHERE mmta_id = ?");
$sth->execute( $mmta_id );
my $action = $sth->fetchrow_hashref();
return $action;
}
=head2
GetModificationTemplateActions
my @actions = GetModificationTemplateActions( $template_id );
=cut
sub GetModificationTemplateActions {
my ( $template_id ) = @_;
C4::Koha::Log( "Koha::MarcModificationTemplates::GetModificationTemplateActions( $template_id )" ) if DEBUG;
warn( "Koha::MarcModificationTemplates::GetModificationTemplateActions( $template_id )" ) if DEBUG;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT * FROM marc_modification_template_actions WHERE template_id = ? ORDER BY ordering");
$sth->execute( $template_id );
my @actions;
while ( my $action = $sth->fetchrow_hashref() ) {
push( @actions, $action );
}
C4::Koha::Log( Data::Dumper::Dumper( @actions ) ) if DEBUG > 4;
warn( Data::Dumper::Dumper( @actions ) ) if DEBUG > 4;
return @actions;
}
=head2
AddModificationTemplateAction
AddModificationTemplateAction(
$template_id, $action, $field_number,
$from_field, $from_subfield, $field_value,
$to_field, $to_subfield, $to_regex,
$conditional, $conditional_field, $conditional_subfield,
$conditional_comparison, $conditional_value,
$conditional_regex, $description
);
Adds a new action to the given modification template.
=cut
sub AddModificationTemplateAction {
my (
$template_id,
$action,
$field_number,
$from_field,
$from_subfield,
$field_value,
$to_field,
$to_subfield,
$to_regex,
$conditional,
$conditional_field,
$conditional_subfield,
$conditional_comparison,
$conditional_value,
$conditional_regex,
$description
) = @_;
C4::Koha::Log( "Koha::MarcModificationTemplates::AddModificationTemplateAction( $template_id, $action,
$field_number, $from_field, $from_subfield, $field_value, $to_field, $to_subfield,
$to_regex, $conditional, $conditional_field, $conditional_subfield, $conditional_comparison,
$conditional_value, $conditional_regex, $description )" ) if DEBUG;
warn( "Koha::MarcModificationTemplates::AddModificationTemplateAction( $template_id, $action,
$field_number, $from_field, $from_subfield, $field_value, $to_field, $to_subfield,
$to_regex, $conditional, $conditional_field, $conditional_subfield, $conditional_comparison,
$conditional_value, $conditional_regex, $description )" ) if DEBUG;
$conditional_regex ||= '0';
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare( 'SELECT MAX(ordering) + 1 AS next_ordering FROM marc_modification_template_actions WHERE template_id = ?' );
$sth->execute( $template_id );
my $row = $sth->fetchrow_hashref;
my $ordering = $row->{'next_ordering'} || 1;
my $query = "
INSERT INTO marc_modification_template_actions (
mmta_id,
template_id,
ordering,
action,
field_number,
from_field,
from_subfield,
field_value,
to_field,
to_subfield,
to_regex,
conditional,
conditional_field,
conditional_subfield,
conditional_comparison,
conditional_value,
conditional_regex,
description
)
VALUES ( NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";
$sth = $dbh->prepare( $query );
$sth->execute(
$template_id,
$ordering,
$action,
$field_number,
$from_field,
$from_subfield,
$field_value,
$to_field,
$to_subfield,
$to_regex,
$conditional,
$conditional_field,
$conditional_subfield,
$conditional_comparison,
$conditional_value,
$conditional_regex,
$description
);
}
=head2
ModModificationTemplateAction
ModModificationTemplateAction(
$mmta_id, $action, $field_number, $from_field,
$from_subfield, $field_value, $to_field,
$to_subfield, $to_regex, $conditional,
$conditional_field, $conditional_subfield,
$conditional_comparison, $conditional_value,
$conditional_regex, $description
);
Modifies an existing action.
=cut
sub ModModificationTemplateAction {
my (
$mmta_id,
$action,
$field_number,
$from_field,
$from_subfield,
$field_value,
$to_field,
$to_subfield,
$to_regex,
$conditional,
$conditional_field,
$conditional_subfield,
$conditional_comparison,
$conditional_value,
$conditional_regex,
$description
) = @_;
my $dbh = C4::Context->dbh;
my $query = "
UPDATE marc_modification_template_actions SET
action = ?,
field_number = ?,
from_field = ?,
from_subfield = ?,
field_value = ?,
to_field = ?,
to_subfield = ?,
to_regex = ?,
conditional = ?,
conditional_field = ?,
conditional_subfield = ?,
conditional_comparison = ?,
conditional_value = ?,
conditional_regex = ?,
description = ?
WHERE mmta_id = ?";
my $sth = $dbh->prepare( $query );
$sth->execute(
$action,
$field_number,
$from_field,
$from_subfield,
$field_value,
$to_field,
$to_subfield,
$to_regex,
$conditional,
$conditional_field,
$conditional_subfield,
$conditional_comparison,
$conditional_value,
$conditional_regex,
$description,
$mmta_id
);
}
=head2
DelModificationTemplateAction
DelModificationTemplateAction( $mmta_id );
Deletes the given template action.
=cut
sub DelModificationTemplateAction {
my ( $mmta_id ) = @_;
my $action = GetModificationTemplateAction( $mmta_id );
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("DELETE FROM marc_modification_template_actions WHERE mmta_id = ?");
$sth->execute( $mmta_id );
$sth = $dbh->prepare("UPDATE marc_modification_template_actions SET ordering = ordering - 1 WHERE template_id = ? AND ordering > ?");
$sth->execute( $action->{'template_id'}, $action->{'ordering'} );
}
=head2
MoveModificationTemplateAction
MoveModificationTemplateAction( $mmta_id, $where );
Changes the order for the given action.
Options for $where are 'up', 'down', 'top' and 'bottom'
=cut
sub MoveModificationTemplateAction {
my ( $mmta_id, $where ) = @_;
my $action = GetModificationTemplateAction( $mmta_id );
return if ( $action->{'ordering'} eq '1' && ( $where eq 'up' || $where eq 'top' ) );
return if ( $action->{'ordering'} eq GetModificationTemplateActions( $action->{'template_id'} ) && ( $where eq 'down' || $where eq 'bottom' ) );
my $dbh = C4::Context->dbh;
my ( $sth, $query );
if ( $where eq 'up' || $where eq 'down' ) {
## For up and down, we just swap the ordering number with the one above or below it.
## Change the ordering for the other action
$query = "UPDATE marc_modification_template_actions SET ordering = ? WHERE template_id = ? AND ordering = ?";
my $ordering = $action->{'ordering'};
$ordering-- if ( $where eq 'up' );
$ordering++ if ( $where eq 'down' );
$sth = $dbh->prepare( $query );
$sth->execute( $action->{'ordering'}, $action->{'template_id'}, $ordering );
## Change the ordering for this action
$query = "UPDATE marc_modification_template_actions SET ordering = ? WHERE mmta_id = ?";
$sth = $dbh->prepare( $query );
$sth->execute( $ordering, $action->{'mmta_id'} );
} elsif ( $where eq 'top' ) {
$sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = ordering + 1 WHERE template_id = ? AND ordering < ?');
$sth->execute( $action->{'template_id'}, $action->{'ordering'} );
$sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = 1 WHERE mmta_id = ?');
$sth->execute( $mmta_id );
} elsif ( $where eq 'bottom' ) {
my $ordering = GetModificationTemplateActions( $action->{'template_id'} );
$sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = ordering - 1 WHERE template_id = ? AND ordering > ?');
$sth->execute( $action->{'template_id'}, $action->{'ordering'} );
$sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = ? WHERE mmta_id = ?');
$sth->execute( $ordering, $mmta_id );
}
}
=head2
ModifyRecordsWithTemplate
ModifyRecordsWithTemplate( $template_id, $batch );
Accepts a template id and a MARC::Batch object.
=cut
sub ModifyRecordsWithTemplate {
my ( $template_id, $batch ) = @_;
C4::Koha::Log( "Koha::MarcModificationTemplates::ModifyRecordsWithTemplate( $template_id, $batch )" ) if DEBUG;
warn( "Koha::MarcModificationTemplates::ModifyRecordsWithTemplate( $template_id, $batch )" ) if DEBUG;
while ( my $record = $batch->next() ) {
ModifyRecordWithTemplate( $template_id, $record );
}
}
=head2
ModifyRecordWithTemplate
ModifyRecordWithTemplate( $template_id, $record )
Accepts a MARC::Record object ( $record ) and modifies
it based on the actions for the given $template_id
=cut
sub ModifyRecordWithTemplate {
my ( $template_id, $record ) = @_;
C4::Koha::Log( "Koha::MarcModificationTemplates::ModifyRecordWithTemplate( $template_id, $record )" ) if DEBUG;
warn( "Koha::MarcModificationTemplates::ModifyRecordWithTemplate( $template_id, $record )" ) if DEBUG;
C4::Koha::Log( "Unmodified Record:\n" . $record->as_formatted() ) if DEBUG >= 10;
warn( "Unmodified Record:\n" . $record->as_formatted() ) if DEBUG >= 10;
my $current_date = DateTime->now()->ymd();
my $branchcode = C4::Context->userenv->{branch};
my @actions = GetModificationTemplateActions( $template_id );
foreach my $a ( @actions ) {
my $action = $a->{'action'};
my $field_number = $a->{'field_number'};
my $from_field = $a->{'from_field'};
my $from_subfield = $a->{'from_subfield'};
my $field_value = $a->{'field_value'};
my $to_field = $a->{'to_field'};
my $to_subfield = $a->{'to_subfield'};
my $to_regex = $a->{'to_regex'};
my $conditional = $a->{'conditional'};
my $conditional_field = $a->{'conditional_field'};
my $conditional_subfield = $a->{'conditional_subfield'};
my $conditional_comparison = $a->{'conditional_comparison'};
my $conditional_value = $a->{'conditional_value'};
my $conditional_regex = $a->{'conditional_regex'};
my $eval = "$action( \$record, '$from_field', '$from_subfield', ";
if ( $field_value ) {
C4::Koha::Log( "Field value before replacements: $field_value" ) if ( DEBUG >= 3 );
warn( "Field value before replacements: $field_value" ) if ( DEBUG >= 3 );
$field_value =~ s/__CURRENTDATE__/$current_date/g;
$field_value =~ s/__BRANCHCODE__/$branchcode/g;
$eval .= " '$field_value' ";
C4::Koha::Log( "Field value after replacements: $field_value" ) if ( DEBUG >= 3 );
warn( "Field value after replacements: $field_value" ) if ( DEBUG >= 3 );
} elsif ( $to_field ) {
$eval .= " '$to_field', '$to_subfield', '$to_regex' ";
}
$eval .= ", '$field_number' " if ( $field_number );
$eval .= ') ';
if ( $conditional ) {
$eval .= " $conditional ( ";
if ( $conditional_comparison eq 'exists' ) {
$eval .= "field_exists( \$record, '$conditional_field', '$conditional_subfield' )";
} elsif ( $conditional_comparison eq 'not_exists' ) {
$eval .= "!field_exists( \$record, '$conditional_field', '$conditional_subfield' )";
} elsif ( $conditional_comparison eq 'equals' ) {
$eval .= "field_equals( \$record, '$conditional_value', '$conditional_field', '$conditional_subfield', '$conditional_regex' ) ";
} elsif ( $conditional_comparison eq 'not_equals' ) {
$eval .= "!field_equals( \$record, '$conditional_value', '$conditional_field', '$conditional_subfield', '$conditional_regex' ) ";
}
$eval .= " )";
}
$eval .= ";";
C4::Koha::Log("eval $eval") if DEBUG >= 2;
warn("eval $eval") if DEBUG >= 2;
eval $eval;
C4::Koha::Log( $record->as_formatted() ) if DEBUG >= 10;
warn( $record->as_formatted() ) if DEBUG >= 10;
}
}
1;
__END__
=head1 AUTHOR
Kyle M Hall
=cut

331
Koha/SimpleMARC.pm Normal file
View File

@ -0,0 +1,331 @@
package Koha::SimpleMARC;
# Copyright 2009 Kyle M. Hall <kyle.m.hall@gmail.com>
use strict;
use warnings;
#use MARC::Record;
require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw(
) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
read_field
update_field
copy_field
move_field
delete_field
field_exists
field_equals
);
our $VERSION = '0.01';
our $debug = 0;
=head1 NAME
SimpleMARC - Perl modle for making simple MARC record alterations.
=head1 SYNOPSIS
use SimpleMARC;
=head1 DESCRIPTION
SimpleMARC is designed to make writing scripts
to modify MARC records simple and easy.
Every function in the modules requires a
MARC::Record object as its first parameter.
=head1 AUTHOR
Kyle Hall <lt>kyle.m.hall@gmail.com<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009 by Kyle Hall
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.7 or,
at your option, any later version of Perl 5 you may have available.
=head1 FUNCTIONS
=head2
copy_field( $record, $fromFieldName, $fromSubfieldName, $toFieldName, $toSubfieldName[, $regex[, $n ] ] );
Copies a value from one field to another. If a regular expression ( $regex ) is supplied,
the value will be transformed by the given regex before being copied into the new field.
Example: $regex = 's/Old Text/Replacement Text/'
If $n is passed, copy_field will only copy the Nth field of the list of fields.
E.g. $n = 1 will only use the first field's value, $n = 2 will use only the 2nd field's value.
=cut
sub copy_field {
my ( $record, $fromFieldName, $fromSubfieldName, $toFieldName, $toSubfieldName, $regex, $n ) = @_;
C4::Koha::Log( "C4::SimpleMARC::copy_field( '$record', '$fromFieldName', '$fromSubfieldName', '$toFieldName', '$toSubfieldName', '$regex', '$n' )" ) if $debug;
if ( ! ( $record && $fromFieldName && $toFieldName ) ) { return; }
my @values = read_field( $record, $fromFieldName, $fromSubfieldName );
@values = ( $values[$n-1] ) if ( $n );
C4::Koha::Log( "@values = read_field( $record, $fromFieldName, $fromSubfieldName )" ) if $debug >= 3;
if ( $regex ) {
foreach my $value ( @values ) {
C4::Koha::Log( "\$value =~ s$regex" ) if ( $debug >= 3 );
eval "\$value =~ s$regex";
}
}
update_field( $record, $toFieldName, $toSubfieldName, @values );
}
=head2
update_field( $record, $fieldName, $subfieldName, $value[, $value,[ $value ... ] ] );
Updates a field with the given value, creating it if neccessary.
If multiple values are supplied, they will be used to update a list of repeatable fields
until either the fields or the values are all used.
If a single value is supplied for a repeated field, that value will be used to update
each of the repeated fields.
=cut
sub update_field {
my ( $record, $fieldName, $subfieldName, @values ) = @_;
C4::Koha::Log( "C4::SimpleMARC::update_field( $record, $fieldName, $subfieldName, @values )" ) if $debug;
if ( ! ( $record && $fieldName ) ) { return; }
if ( @values eq 1 ) {
_update_repeatable_field_with_single_value( $record, $fieldName, $subfieldName, @values );
return;
}
my $i = 0;
my $field;
if ( $subfieldName ) {
if ( my @fields = $record->field( $fieldName ) ) {
foreach my $field ( @fields ) {
$field->update( "$subfieldName" => $values[$i++] );
}
} else {
## Field does not exist, create it.
foreach my $value ( @values ) {
$field = MARC::Field->new( $fieldName, '', '', "$subfieldName" => $values[$i++] );
$record->append_fields( $field );
}
}
} else { ## No subfield
if ( my @fields = $record->field( $fieldName ) ) {
foreach my $field ( @fields ) {
$field->update( $values[$i++] );
}
} else {
## Field does not exists, create it
foreach my $value ( @values ) {
$field = MARC::Field->new( $fieldName, $value );
$record->append_fields( $field );
}
}
}
}
=head2
my @values = read_field( $record, $fieldName[, $subfieldName, [, $n ] ] );
Returns an array of field values for the given field and subfield
If $n is given, it will return only the $nth value of the array.
E.g. If $n = 1, it return the 1st value, if $n = 3, it will return the 3rd value.
=cut
sub read_field {
my ( $record, $fieldName, $subfieldName, $n ) = @_;
C4::Koha::Log( "C4::SimpleMARC::read_field( '$record', '$fieldName', '$subfieldName', '$n' )" ) if $debug;
my @fields = $record->field( $fieldName );
return @fields unless $subfieldName;
my @subfields;
foreach my $field ( @fields ) {
my @sf = $field->subfield( $subfieldName );
push( @subfields, @sf );
}
if ( $n ) {
return $subfields[$n-1];
} else {
return @subfields;
}
}
=head2
$bool = field_exists( $record, $fieldName[, $subfieldName ]);
Returns true if the field exits, false otherwise.
=cut
sub field_exists {
my ( $record, $fieldName, $subfieldName ) = @_;
C4::Koha::Log( "C4::SimpleMARC::field_exists( $record, $fieldName, $subfieldName )" ) if $debug;
if ( ! $record ) { return; }
my $return = 0;
if ( $fieldName && $subfieldName ) {
$return = $record->field( $fieldName ) && $record->subfield( $fieldName, $subfieldName );
} elsif ( $fieldName ) {
$return = $record->field( $fieldName ) && 1;
}
C4::Koha::Log( "C4:SimpleMARC::field_exists: Returning '$return'" ) if $debug >= 2;
return $return;
}
=head2
$bool = field_equals( $record, $value, $fieldName[, $subfieldName[, $regex [, $n ] ] ]);
Returns true if the field equals the given value, false otherwise.
If a regular expression ( $regex ) is supplied, the value will be compared using
the given regex. Example: $regex = 'm/sought_text/'
If $n is passed, the Nth field of a repeatable series will be used for comparison.
Set $n to 1 or leave empty for a non-repeatable field.
=cut
sub field_equals {
my ( $record, $value, $fieldName, $subfieldName, $regex, $n ) = @_;
$n = 1 unless ( $n ); ## $n defaults to first field of a repeatable field series
C4::Koha::Log( "C4::SimpleMARC::field_equals( '$record', '$value', '$fieldName', '$subfieldName', '$regex', '$n')" ) if $debug;
if ( ! $record ) { return; }
my @field_values = read_field( $record, $fieldName, $subfieldName, $n );
my $field_value = $field_values[$n-1];
if ( $regex ) {
C4::Koha::Log( "Testing '$field_value' =~ m$value" ) if $debug >= 3;
return eval "\$field_value =~ m$value";
} else {
return $field_value eq $value;
}
}
=head2
move_field( $record, $fromFieldName, $fromSubfieldName, $toFieldName, $toSubfieldName[, $regex [, $n ] ] );
Moves a value from one field to another. If a regular expression ( $regex ) is supplied,
the value will be transformed by the given regex before being moved into the new field.
Example: $regex = 's/Old Text/Replacement Text/'
If $n is passed, only the Nth field will be moved. $n = 1
will move the first repeatable field, $n = 3 will move the third.
=cut
sub move_field {
my ( $record, $fromFieldName, $fromSubfieldName, $toFieldName, $toSubfieldName, $regex, $n ) = @_;
C4::Koha::Log( "C4::SimpleMARC::move_field( '$record', '$fromFieldName', '$fromSubfieldName', '$toFieldName', '$toSubfieldName', '$regex', '$n' )" ) if $debug;
copy_field( $record, $fromFieldName, $fromSubfieldName, $toFieldName, $toSubfieldName, $regex, $n );
delete_field( $record, $fromFieldName, $fromSubfieldName, $n );
}
=head2
delete_field( $record, $fieldName[, $subfieldName [, $n ] ] );
Deletes the given field.
If $n is passed, only the Nth field will be deleted. $n = 1
will delete the first repeatable field, $n = 3 will delete the third.
=cut
sub delete_field {
my ( $record, $fieldName, $subfieldName, $n ) = @_;
C4::Koha::Log( "C4::SimpleMARC::delete_field( '$record', '$fieldName', '$subfieldName', '$n' )" ) if $debug;
my @fields = $record->field( $fieldName );
@fields = ( $fields[$n-1] ) if ( $n );
if ( @fields && !$subfieldName ) {
foreach my $field ( @fields ) {
$record->delete_field( $field );
}
} elsif ( @fields && $subfieldName ) {
foreach my $field ( @fields ) {
$field->delete_subfield( code => $subfieldName );
}
}
}
=head2
_update_repeatable_field_with_single_value( $record, $fieldName, $subfieldName, $value );
Updates a repeatable field, giving all existing copies of that field the given value.
This is an internal function, and thus is not exported.
=cut
sub _update_repeatable_field_with_single_value {
my ( $record, $fieldName, $subfieldName, $value ) = @_;
C4::Koha::Log( "C4::SimpleMARC::_update_repeatable_field_with_single_value( $record, $fieldName, $subfieldName, $value )" ) if $debug;
if ( ! ( $record && $fieldName ) ) { return; }
my $field;
if ( $subfieldName ) {
if ( my @fields = $record->field( $fieldName ) ) {
foreach my $field ( @fields ) {
$field->update( "$subfieldName" => $value );
}
} else {
## Field does not exist, create it.
$field = MARC::Field->new( $fieldName, '', '', "$subfieldName" => $value );
$record->append_fields( $field );
}
} else { ## No subfield
if ( my @fields = $record->field( $fieldName ) ) {
foreach my $field ( @fields ) {
$field->update( $value );
}
} else {
## Field does not exists, create it
$field = MARC::Field->new( $fieldName, $value );
$record->append_fields( $field );
}
}
}
1;
__END__

View File

@ -45,6 +45,7 @@ INSERT INTO permissions (module_bit, code, description) VALUES
(13, 'rotating_collections', 'Manage rotating collections'),
(13, 'upload_local_cover_images', 'Upload local cover images'),
(13, 'manage_patron_lists', 'Add, edit and delete patron lists and their contents'),
(13, 'marc_modification_templates', 'Manage marc modification templates'),
(15, 'check_expiration', 'Check the expiration of a serial'),
(15, 'claim_serials', 'Claim missing serials'),
(15, 'create_subscription', 'Create a new subscription'),

View File

@ -3348,6 +3348,41 @@ ALTER TABLE `patron_list_patrons`
ADD CONSTRAINT patron_list_patrons_ibfk_1 FOREIGN KEY (patron_list_id) REFERENCES patron_lists (patron_list_id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT patron_list_patrons_ibfk_2 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Table structure for table 'marc_modification_templates'
--
CREATE TABLE IF NOT EXISTS marc_modification_templates (
template_id int(11) NOT NULL AUTO_INCREMENT,
name text NOT NULL,
PRIMARY KEY (template_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Table structure for table 'marc_modification_template_actions'
--
CREATE TABLE IF NOT EXISTS marc_modification_template_actions (
mmta_id int(11) NOT NULL AUTO_INCREMENT,
template_id int(11) NOT NULL,
ordering int(3) NOT NULL,
action enum('delete_field','update_field','move_field','copy_field') NOT NULL,
field_number smallint(6) NOT NULL DEFAULT '0',
from_field varchar(3) NOT NULL,
from_subfield varchar(1) DEFAULT NULL,
field_value varchar(100) DEFAULT NULL,
to_field varchar(3) DEFAULT NULL,
to_subfield varchar(1) DEFAULT NULL,
to_regex text,
conditional enum('if','unless') DEFAULT NULL,
conditional_field varchar(3) DEFAULT NULL,
conditional_subfield varchar(1) DEFAULT NULL,
conditional_comparison enum('exists','not_exists','equals','not_equals') DEFAULT NULL,
conditional_value text,
conditional_regex tinyint(1) NOT NULL DEFAULT '0',
description text,
PRIMARY KEY (mmta_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;

View File

@ -7686,6 +7686,45 @@ if ( CheckVersion($DBversion) ) {
SetVersion($DBversion);
}
$DBversion = "3.11.00.XXX";
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
$dbh->do("CREATE TABLE IF NOT EXISTS marc_modification_templates (
template_id int(11) NOT NULL auto_increment,
name text NOT NULL,
PRIMARY KEY (template_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;"
);
$dbh->do("
CREATE TABLE IF NOT EXISTS marc_modification_template_actions (
mmta_id int(11) NOT NULL auto_increment,
template_id int(11) NOT NULL,
ordering int(3) NOT NULL,
action enum('delete_field','update_field','move_field','copy_field') NOT NULL,
field_number smallint(6) NOT NULL default '0',
from_field varchar(3) NOT NULL,
from_subfield varchar(1) NULL,
field_value varchar(100) default NULL,
to_field varchar(3) default NULL,
to_subfield varchar(1) default NULL,
to_regex text,
conditional enum('if','unless') default NULL,
conditional_field varchar(3) default NULL,
conditional_subfield varchar(1) default NULL,
conditional_comparison enum('exists','not_exists','equals','not_equals') default NULL,
conditional_value text,
conditional_regex tinyint(1) NOT NULL default '0',
description text,
PRIMARY KEY (mmta_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
");
$dbh->do("INSERT INTO permissions (module_bit, code, description) VALUES ('13', 'marc_modification_templates', 'Manage marc modification templates')");
print "Upgrade to $DBversion done ( Added tables for MARC Modification Framework )\n";
SetVersion($DBversion);
}
=head1 FUNCTIONS
=head2 TableExists($table)

View File

@ -71,6 +71,9 @@
<li><a href="/cgi-bin/koha/rotating_collections/rotatingCollections.pl">Rotating collections</a></li>
[% END %]
-->
[% IF ( CAN_user_tools_marc_modification_templates ) %]
<li><a href="/cgi-bin/koha/tools/marc_modification_templates.pl">Manage MARC modification templates</a></li>
[% END %]
[% IF ( CAN_user_tools_stage_marc_import ) %]
<li><a href="/cgi-bin/koha/tools/stage-marc-import.pl">Stage MARC for import</a></li>
[% END %]

View File

@ -68,8 +68,8 @@
<dd>Create and manage Bibliographic frameworks that define the characteristics of your MARC Records (field and subfield definitions) as well as templates for the MARC editor.</dd>
<dt><a href="/cgi-bin/koha/admin/koha2marclinks.pl">Koha to MARC mapping</a></dt>
<dd>Define the mapping between the Koha transactional database (SQL) and the MARC Bibliographic records. Note that the mapping can be defined through MARC Bibliographic Framework. This tool is just a shortcut to speed up linkage.</dd>
<dt><a href="/cgi-bin/koha/admin/fieldmapping.pl">Keywords to MARC mapping</a></dt>
<dd>Define the mapping between keywords and MARC fields, those keywords are used to find some datas independently of the framework.</dd>
<dt><a href="/cgi-bin/koha/admin/fieldmapping.pl">Keywords to MARC mapping</a></dt>
<dd>Define the mapping between keywords and MARC fields, those keywords are used to find some datas independently of the framework.</dd>
<dt><a href="/cgi-bin/koha/admin/checkmarc.pl">MARC Bibliographic framework test</a></dt>
<dd>Checks the MARC structure. If you change your MARC Bibliographic framework it's recommended that you run this tool to test for errors in your definition.</dd>
<dt><a href="/cgi-bin/koha/admin/authtypes.pl">Authority types</a></dt>

View File

@ -0,0 +1,492 @@
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Tools &rsaquo; MARC Modification Templates</title>
[% INCLUDE 'doc-head-close.inc' %]
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
$('#select_template').find("input:submit").hide();
$('#select_template').change(function() {
$('#select_template').submit();
});
});
//]]>
</script>
<script>
function onActionChange(selectObj) {
// get the index of the selected option
var idx = selectObj.selectedIndex;
// get the value of the selected option
var action = selectObj.options[idx].value;
switch( action ) {
case 'delete_field':
show('field_number_block');
hide('with_value_block');
hide('to_field_block');
break;
case 'update_field':
hide('field_number_block');
show('with_value_block');
hide('to_field_block');
break;
case 'move_field':
show('field_number_block');
hide('with_value_block');
show('to_field_block');
break;
case 'copy_field':
show('field_number_block');
hide('with_value_block');
show('to_field_block');
break;
}
}
function onConditionalChange(selectObj) {
// get the index of the selected option
var idx = selectObj.selectedIndex;
// get the value of the selected option
var action = selectObj.options[idx].value;
switch( action ) {
case '':
hide('conditional_block');
break;
case 'if':
case 'unless':
show('conditional_block');
break;
}
}
function onConditionalComparisonChange(selectObj) {
// get the index of the selected option
var idx = selectObj.selectedIndex;
// get the value of the selected option
var action = selectObj.options[idx].value;
switch( action ) {
case 'equals':
case 'not_equals':
show('conditional_comparison_block');
break;
default:
hide('conditional_comparison_block');
break;
}
}
function onToFieldRegexChange( checkboxObj ) {
if ( checkboxObj.checked ) {
show('to_field_regex_value_block');
} else {
hide('to_field_regex_value_block');
}
}
function onConditionalRegexChange( checkboxObj ) {
if ( checkboxObj.checked ) {
document.getElementById( 'match_regex_prefix' ).style.visibility='visible';
} else {
document.getElementById( 'match_regex_prefix' ).style.visibility='hidden';
}
}
function show(eltId) {
elt = document.getElementById( eltId );
elt.style.display='inline';
}
function hide(eltId) {
clearFormElements( eltId );
elt = document.getElementById( eltId );
elt.style.display='none';
}
function clearFormElements(divId) {
myBlock = document.getElementById( divId );
var inputElements = myBlock.getElementsByTagName( "input" );
for (var i = 0; i < inputElements.length; i++) {
switch( inputElements[i].type ) {
case "text":
inputElements[i].value = '';
break;
case "checkbox":
inputElements[i].checked = false;
break;
}
}
var selectElements = myBlock.getElementsByTagName( "select" );
for (var i = 0; i < selectElements.length; i++) {
selectElements[i].selectedIndex = 0;
}
}
function confirmDelete() {
var agree = confirm("Are you sure you wish to delete this template?");
return agree;
}
var modaction_legend_innerhtml;
var action_submit_value;
function editAction( mmta_id, ordering, action, field_number, from_field, from_subfield, field_value, to_field,
to_subfield, to_regex, conditional, conditional_field, conditional_subfield,
conditional_comparison, conditional_value, conditional_regex, description
) {
document.getElementById('mmta_id').value = mmta_id;
setSelectByValue( 'action', action );
document.getElementById('action').onchange();
setSelectByValue( 'field_number', field_number );
document.getElementById('from_field').value = from_field;
document.getElementById('from_subfield').value = from_subfield;
document.getElementById('field_value').value = field_value;
document.getElementById('to_field').value = to_field;
document.getElementById('to_subfield').value = to_subfield;
document.getElementById('to_regex').value = to_regex;
document.getElementById('to_field_regex').checked = to_regex.length;
document.getElementById('to_field_regex').onchange();
setSelectByValue( 'conditional', conditional );
document.getElementById('conditional').onchange();
document.getElementById('conditional_field').value = conditional_field;
document.getElementById('conditional_subfield').value = conditional_subfield;
setSelectByValue( 'conditional_comparison', conditional_comparison );
document.getElementById('conditional_comparison').onchange();
document.getElementById('conditional_value').value = conditional_value;
document.getElementById('conditional_regex').checked = parseInt( conditional_regex );
document.getElementById('description').value = description;
window.modaction_legend_innerhtml = document.getElementById('modaction_legend').innerhtml;
document.getElementById('modaction_legend').innerhtml = "Edit Action " + ordering;
window.action_submit_value = document.getElementById('action_submit').value;
document.getElementById('action_submit').value = "Update Action";
show('cancel_edit');
}
function cancelEditAction() {
document.getElementById('mmta_id').value = '';
setSelectByValue( 'action', 'delete_field' );
document.getElementById('action').onchange();
document.getElementById('from_field').value = '';
document.getElementById('from_subfield').value = '';
document.getElementById('field_value').value = '';
document.getElementById('to_field').value = '';
document.getElementById('to_subfield').value = '';
document.getElementById('to_regex').value = '';
document.getElementById('to_field_regex').checked = false;
document.getElementById('to_field_regex').onchange();
setSelectByValue( 'conditional', '' );
document.getElementById('conditional').onchange();
document.getElementById('conditional_field').value = '';
document.getElementById('conditional_subfield').value = '';
setSelectByValue( 'conditional_comparison', '' );
document.getElementById('conditional_comparison').onchange();
document.getElementById('conditional_value').value = '';
document.getElementById('conditional_regex').checked = false;
document.getElementById('modaction_legend').innerhtml = window.modaction_legend_innerhtml;
document.getElementById('action_submit').value = window.action_submit_value;
hide('cancel_edit');
}
function setSelectByValue( selectId, value ) {
s = document.getElementById( selectId );
for ( i = 0; i < s.options.length; i++ ) {
if ( s.options[i].value == value ) {
s.selectedIndex = i;
}
}
}
</script>
</head>
<body>
[% INCLUDE 'header.inc' %]
[% INCLUDE 'cat-search.inc' %]
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; MARC Modification Templates</div>
<div id="doc3" class="yui-t2">
<div id="yui-main">
<div class="yui-b">
<h2>MARC Modification Templates</h2>
[% IF ( TemplatesLoop ) %]
<form method="get" action="/cgi-bin/koha/tools/marc_modification_templates.pl" id="select_template">
<label for="select_template">Template: </label>
<select name="template_id" id="select_template" style="width:20em;">
[% FOREACH TemplatesLoo IN TemplatesLoop %]
<option value="[% TemplatesLoo.template_id %]" [% IF ( TemplatesLoo.selected ) %] selected [% END %] > [% TemplatesLoo.name %]</option>
[% END %]
</select>
<input type="hidden" name="op" value="select_template">
<input type="submit" value="Go" />
</form>
<form method="get" action="/cgi-bin/koha/tools/marc_modification_templates.pl" id="delete_template">
<input type="hidden" name="template_id" value="[% template_id %]" />
<input type="hidden" name="op" value="delete_template">
<input type="submit" value="Delete Template" onClick="return confirmDelete()" />
</form>
[% IF ( ActionsLoop ) %]
<table>
<caption>Actions for this template</caption>
<tr>
<th>Change Order</th>
<th>Order</th>
<th>Action</th>
<th>Description</th>
<th>&nbsp</th>
<th>&nbsp</th>
</tr>
[% FOREACH ActionsLoo IN ActionsLoop %]
<tr>
<td style="white-space:nowrap;">
<a title="Move Action Up" href="marc_modification_templates.pl?op=move_action&amp;where=up&amp;template_id=[% ActionsLoo.template_id %]&amp;mmta_id=[% ActionsLoo.mmta_id %]">
<img src="/intranet-tmpl/[% theme %]/img/go-up.png" border="0" alt="Go up" />
</a>
<a title="Move Action To Top" href="marc_modification_templates.pl?op=move_action&amp;where=top&amp;template_id=[% ActionsLoo.template_id %]&amp;mmta_id=[% ActionsLoo.mmta_id %]">
<img src="/intranet-tmpl/[% theme %]/img/go-top.png" border="0" alt="Go top" />
</a>
<a title="Move Action To Bottom" href="marc_modification_templates.pl?op=move_action&amp;where=bottom&amp;template_id=[% ActionsLoo.template_id %]&amp;mmta_id=[% ActionsLoo.mmta_id %]">
<img src="/intranet-tmpl/[% theme %]/img/go-bottom.png" border="0" alt="Go bottom" />
</a>
<a title="Move Action Down" href="marc_modification_templates.pl?op=move_action&amp;where=down&amp;template_id=[% ActionsLoo.template_id %]&amp;mmta_id=[% ActionsLoo.mmta_id %]">
<img src="/intranet-tmpl/[% theme %]/img/go-down.png" border="0" alt="Go down" />
</a>
</td>
<td>[% ActionsLoo.ordering %]</td>
<td>
[% IF ( ActionsLoo.action_delete_field ) %] Delete [% END %]
[% IF ( ActionsLoo.action_update_field ) %] Update [% END %]
[% IF ( ActionsLoo.action_move_field ) %] Move [% END %]
[% IF ( ActionsLoo.action_copy_field ) %] Copy [% END %]
[% UNLESS ( ActionsLoo.action_update_field ) %]
[% IF ( ActionsLoo.field_number ) %]
1st
[% END %]
[% END %]
field
[% ActionsLoo.from_field %][% IF ( ActionsLoo.from_subfield ) %]$[% ActionsLoo.from_subfield %][% END %]
[% IF ( ActionsLoo.field_value ) %]
with value <i>[% ActionsLoo.field_value %]</i>
[% END %]
[% IF ( ActionsLoo.to_field ) %]
to [% ActionsLoo.to_field %][% IF ( ActionsLoo.to_subfield ) %]$[% ActionsLoo.to_subfield %][% END %]
[% IF ( ActionsLoo.to_regex ) %]
using RegEx s<strong>[% ActionsLoo.to_regex %]</strong>
[% END %]
[% END %]
[% IF ( ActionsLoo.conditional ) %]
[% IF ( ActionsLoo.conditional_if ) %] if [% END %]
[% IF ( ActionsLoo.conditional_unless ) %] unless [% END %]
[% ActionsLoo.conditional_field %][% IF ( ActionsLoo.conditional_subfield ) %]$[% ActionsLoo.conditional_subfield %][% END %]
[% IF ( ActionsLoo.conditional_comparison_exists ) %] exists [% END %]
[% IF ( ActionsLoo.conditional_comparison_not_exists ) %] does not exist [% END %]
[% IF ( ActionsLoo.conditional_comparison_equals ) %] matches [% END %]
[% IF ( ActionsLoo.conditional_comparison_not_equals ) %] does not match [% END %]
[% IF ( ActionsLoo.conditional_regex ) %] RegEx m[% END %]<strong>[% ActionsLoo.conditional_value %]</strong>
[% END %]
</td>
<td>[% ActionsLoo.description %]</td>
<td><a href="#modaction" onclick='editAction(
"[% ActionsLoo.mmta_id |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.ordering |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.action |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.field_number |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.from_field |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.from_subfield |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.field_value |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.to_field |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.to_subfield |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.to_regex |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.conditional |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.conditional_field |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.conditional_subfield |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.conditional_comparison |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.conditional_value |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.conditional_regex |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]",
"[% ActionsLoo.description |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') %]"
)'>Edit</a></td>
<td><a href="marc_modification_templates.pl?template_id=[% ActionsLoo.template_id %]&op=delete_action&mmta_id=[% ActionsLoo.mmta_id %]">Delete</a></td>
</tr>
[% END %]
</table>
[% ELSE %]
<div class="dialog message"><p>There are no defined actions for this template.</p></div>
[% END %]
<form method="post" action="/cgi-bin/koha/tools/marc_modification_templates.pl" id="add_action" >
<a name="modaction"></a>
<fieldset>
<legend id="modaction_legend">Add A New Action</legend>
<select name="action" id="action" onchange="onActionChange(this);">
<option value="delete_field">Delete</option>
<option value="update_field">Add/Update</option>
<option value="move_field">Move</option>
<option value="copy_field">Copy</option>
</select>
<span id="field_number_block">
<select name="field_number" id="field_number">
<option value="0">All</option>
<option value="1">1st</option>
</select>
</span>
field(s) <input type="text" name="from_field" id="from_field" size="3" maxlength="3" /> <input type="text" name="from_subfield" id="from_subfield" size="1" maxlength="1" />
<span name="with_value_block" id="with_value_block" style="display:none;">
with value <input type="text" name="field_value" id="field_value" />
</span>
<span name="to_field_block" id="to_field_block" style="display:none;">
to field <input type="text" name="to_field" id="to_field" size="3" maxlength="3" /> <input type="text" name="to_subfield" id="to_subfield" size="1" maxlength="1" />
<span name="to_field_regex_block" id="to_field_regex_block">
<sup>
<label for="to_field_regex">RegEx</label>
<input type="checkbox" name="to_field_regex" id="to_field_regex" onchange="onToFieldRegexChange(this);" />
<span name="to_field_regex_value_block" id="to_field_regex_value_block" style="display:none;">
s<input type="text" name="to_regex" id="to_regex" />
</span>
</sup>
</span>
</span>
<p/>
<select name="conditional" id="conditional" onchange="onConditionalChange(this);">
<option value="" selected />
<option value="if">if</option>
<option value="unless">unless</option>
</select>
<span name="conditional_block" id="conditional_block" style="display:none;">
field <input type="text" name="conditional_field" id="conditional_field" size="3" maxlength="3" /> <input type="text" name="conditional_subfield" id="conditional_subfield" size="1" maxlength="1" />
<select name="conditional_comparison" id="conditional_comparison" onchange="onConditionalComparisonChange(this);">
<option value="" />
<option value="exists">exists</option>
<option value="not_exists">doesn't exist</option>
<option value="equals">matches</option>
<option value="not_equals">doesn't match</option>
</select>
<span name="conditional_comparison_block" id="conditional_comparison_block" style="display:none;">
<span id="match_regex_prefix" style="visibility:hidden;">m</span><input type="text" id="conditional_value" name="conditional_value" />
<sup>
<label for="conditional_regex">RegEx</label>
<input type="checkbox" name="conditional_regex" id="conditional_regex" onchange="onConditionalRegexChange(this);" />
</sup>
</span>
</span>
<input type="hidden" name="template_id" value="[% template_id %]" />
<input type="hidden" name="mmta_id" id="mmta_id" />
<input type="hidden" name="op" value="add_action" />
<br/><br/>
<label for="description">Description:</label>
<input type="text" name="description" id="description" size="60" />
<br/><br/>
<input id="action_submit" type="submit" value="Add Action" /> <a href="#modaction" id="cancel_edit" onclick="cancelEditAction();" style="display:none;">Cancel</a>
</fieldset>
</form>
[% ELSE %]
<div class="dialog message"><p>There are no defined templates. Please create a template first.</p></div>
[% END %]
<form method="post" action="/cgi-bin/koha/tools/marc_modification_templates.pl" id="add_template" >
<fieldset>
<legend>Create A New Template</legend>
<label for="template_name">Name: </label>
<input name="template_name" id="template_name" type="text" size="30" />
<input type="hidden" name="op" value="create_template" />
<input type="submit" value="Create Template" />
[% IF ( template_id ) %]
<input type="hidden" name="template_id" value="[% template_id %]" />
<input type="checkbox" name="duplicate_current_template" id="duplicate_current_template" />
<label for="duplicate_current_template">Duplicate Current Template</label>
[% END %]
</fieldset>
</form>
</div>
</div>
<div class="yui-b">
[% INCLUDE 'tools-menu.inc' %]
</div>
</div>
[% INCLUDE 'intranet-bottom.inc' %]

View File

@ -117,6 +117,23 @@ function CheckForm(f) {
<select name="encoding" id="encoding"><option value="utf8" selected="selected">UTF-8 (Default)</option><option value="MARC-8">MARC 8</option><option value="ISO_5426">ISO 5426</option><option value="ISO_6937">ISO 6937</option><option value=ISO_8859-1">ISO 8859-1</option><option value="EUC-KR">EUC-KR</option></select>
</li>
</ol></fieldset>
[% IF MarcModificationTemplatesLoop %]
<fieldset class="rows">
<legend>Use MARC Modification Template:</legend>
<ol>
<li>
<label for="comments">Modify record using the following template: </label>
<select name="marc_modification_template_id" id="marc_modification_template_id">
<option value="">Do not use.</option>
[% FOREACH mmt IN MarcModificationTemplatesLoop %]
<option value="[% mmt.template_id %]">[% mmt.name %]</option>
[% END %]
</select>
</li>
</ol>
</fieldset>
[% END %]
<fieldset class="rows">
<legend>Look for existing records in catalog?</legend>
<ol><li><label for="matcher">Record matching rule:</label>

View File

@ -145,10 +145,15 @@
<!--
[% IF ( CAN_user_tools_rotating_collections ) %]
<dt><a href="/cgi-bin/koha/rotating_collections/rotatingCollections.pl">Rotating collections</a></dt>
<dd>Manage Rotating Collections</dd>
<dd>Manage Rotating Collections</dd>
[% END %]
-->
[% IF ( CAN_user_tools_marc_modification_templates ) %]
<dt><a href="/cgi-bin/koha/tools/marc_modification_templates.pl">MARC Modification Templates</a></dt>
<dd>Manage templates for modifying MARC records during import.</dd>
[% END %]
[% IF ( CAN_user_tools_stage_marc_import ) %]
<dt><a href="/cgi-bin/koha/tools/stage-marc-import.pl">Stage MARC records for import</a></dt>
<dd>Stage MARC records into the reservoir.</dd>

View File

@ -0,0 +1,151 @@
#!/usr/bin/perl
# Copyright 2010 Kyle M Hall <kyle.m.hall@gmail.com>
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use strict;
use warnings;
use CGI;
use C4::Auth;
use C4::Koha;
use C4::Output;
use Koha::MarcModificationTemplates;
my $cgi = new CGI;
my $op = $cgi->param('op');
my $template_id = $cgi->param('template_id');
my ($template, $loggedinuser, $cookie)
= get_template_and_user({template_name => "tools/marc_modification_templates.tmpl",
query => $cgi,
type => "intranet",
authnotrequired => 0,
flagsrequired => { tools => 'marc_modfication_templates' },
debug => 1,
});
if ( $op eq "create_template" ) {
$template_id = '' unless $cgi->param('duplicate_current_template');
$template_id = AddModificationTemplate( $cgi->param('template_name'), $template_id );
} elsif ( $op eq "delete_template" ) {
DelModificationTemplate( $template_id );
$template_id = '';
} elsif ( $op eq "add_action" ) {
my $mmta_id = $cgi->param('mmta_id');
my $action = $cgi->param('action');
my $field_number = $cgi->param('field_number');
my $from_field = $cgi->param('from_field');
my $from_subfield = $cgi->param('from_subfield');
my $field_value = $cgi->param('field_value');
my $to_field = $cgi->param('to_field');
my $to_subfield = $cgi->param('to_subfield');
my $to_regex = $cgi->param('to_regex');
my $conditional = $cgi->param('conditional');
my $conditional_field = $cgi->param('conditional_field');
my $conditional_subfield = $cgi->param('conditional_subfield');
my $conditional_comparison = $cgi->param('conditional_comparison');
my $conditional_value = $cgi->param('conditional_value');
my $conditional_regex = $cgi->param('conditional_regex') eq 'on';
my $description = $cgi->param('description');
unless ( $mmta_id ) {
AddModificationTemplateAction(
$template_id,
$action,
$field_number,
$from_field,
$from_subfield,
$field_value,
$to_field,
$to_subfield,
$to_regex,
$conditional,
$conditional_field,
$conditional_subfield,
$conditional_comparison,
$conditional_value,
$conditional_regex,
$description
);
} else {
ModModificationTemplateAction(
$mmta_id,
$action,
$field_number,
$from_field,
$from_subfield,
$field_value,
$to_field,
$to_subfield,
$to_regex,
$conditional,
$conditional_field,
$conditional_subfield,
$conditional_comparison,
$conditional_value,
$conditional_regex,
$description
);
}
} elsif ( $op eq "delete_action" ) {
DelModificationTemplateAction( $cgi->param('mmta_id') );
} elsif ( $op eq "move_action" ) {
MoveModificationTemplateAction( $cgi->param('mmta_id'), $cgi->param('where') );
}
my @templates = GetModificationTemplates( $template_id );
unless ( $template_id ) {
$template_id = $templates[0]->{'template_id'};
@templates = GetModificationTemplates( $template_id );
}
my @actions = GetModificationTemplateActions( $template_id );
foreach my $action ( @actions ) {
$action->{'action_delete_field'} = ( $action->{'action'} eq 'delete_field' );
$action->{'action_update_field'} = ( $action->{'action'} eq 'update_field' );
$action->{'action_move_field'} = ( $action->{'action'} eq 'move_field' );
$action->{'action_copy_field'} = ( $action->{'action'} eq 'copy_field' );
$action->{'conditional_if'} = ( $action->{'conditional'} eq 'if' );
$action->{'conditional_unless'} = ( $action->{'conditional'} eq 'unless' );
$action->{'conditional_comparison_exists'} = ( $action->{'conditional_comparison'} eq 'exists' );
$action->{'conditional_comparison_not_exists'} = ( $action->{'conditional_comparison'} eq 'not_exists' );
$action->{'conditional_comparison_equals'} = ( $action->{'conditional_comparison'} eq 'equals' );
$action->{'conditional_comparison_not_equals'} = ( $action->{'conditional_comparison'} eq 'not_equals' );
}
$template->param(
TemplatesLoop => \@templates,
ActionsLoop => \@actions,
template_id => $template_id,
);
output_html_with_http_headers $cgi, $cookie, $template->output;

View File

@ -41,6 +41,7 @@ use C4::ImportBatch;
use C4::Matcher;
use C4::UploadedFile;
use C4::BackgroundJob;
use Koha::MarcModificationTemplates;
my $input = new CGI;
my $dbh = C4::Context->dbh;
@ -57,6 +58,8 @@ my $item_action = $input->param('item_action');
my $comments = $input->param('comments');
my $record_type = $input->param('record_type');
my $encoding = $input->param('encoding');
my $marc_modification_template = $input->param('marc_modification_template_id');
my ($template, $loggedinuser, $cookie)
= get_template_and_user({template_name => "tools/stage-marc-import.tmpl",
query => $input,
@ -131,7 +134,7 @@ if ($completedJobID) {
}
# FIXME branch code
my ($batch_id, $num_valid, $num_items, @import_errors) = BatchStageMarcRecords($record_type, $encoding, $marcrecord, $filename, $comments, '', $parse_items, 0, 50, staging_progress_callback($job, $dbh));
my ($batch_id, $num_valid, $num_items, @import_errors) = BatchStageMarcRecords($record_type, $encoding, $marcrecord, $filename, $marc_modification_template, $comments, '', $parse_items, 0, 50, staging_progress_callback($job, $dbh));
$dbh->commit();
@ -180,6 +183,8 @@ if ($completedJobID) {
matcher_code => $matcher_code,
import_batch_id => $batch_id
);
}
} else {
@ -189,6 +194,10 @@ if ($completedJobID) {
}
my @matchers = C4::Matcher::GetMatcherList();
$template->param(available_matchers => \@matchers);
my @templates = GetModificationTemplates();
$template->param( MarcModificationTemplatesLoop => \@templates );
}
output_html_with_http_headers $input, $cookie, $template->output;