added editor for MARC matching rules

Signed-off-by: Chris Cormack <crc@liblime.com>
Signed-off-by: Joshua Ferraro <jmf@liblime.com>
This commit is contained in:
Galen Charlton 2007-11-16 18:49:30 -06:00 committed by Joshua Ferraro
parent e88ea6cbdd
commit 44f4e9baf3
5 changed files with 1062 additions and 3 deletions

View File

@ -62,6 +62,8 @@ foreach $match (@matches) {
}
my $matcher_description = $matcher->dump();
=back
=head1 FUNCTIONS
@ -365,6 +367,29 @@ sub _store_matchpoint {
return $matchpoint_id;
}
=head2 delete
=over 4
C4::Matcher->delete($id);
=back
Deletes the matcher of the specified ID
from the database.
=cut
sub delete {
my $class = shift;
my $matcher_id = shift;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("DELETE FROM marc_matchers WHERE matcher_id = ?");
$sth->execute($matcher_id); # relying on cascading deletes to clean up everything
}
=head2 threshold
=over 4
@ -383,6 +408,26 @@ sub threshold {
@_ ? $self->{'threshold'} = shift : $self->{'threshold'};
}
=head2 _id
=over 4
$matcher->_id(123);
my $id = $matcher->_id();
=back
Accessor method. Note that using this method
to set the DB ID of the matcher should not be
done outside of the editing CGI.
=cut
sub _id {
my $self = shift;
@_ ? $self->{'id'} = shift : $self->{'id'};
}
=head2 code
=over 4
@ -483,7 +528,7 @@ sub add_simple_matchpoint {
$self->add_matchpoint($index, $score, [
{ tag => $source_tag, subfields => $source_subfields,
offset => $source_offset, length => $source_length,
offset => $source_offset, 'length' => $source_length,
norms => [ $source_normalizer ]
}
]);
@ -565,9 +610,9 @@ sub add_simple_required_check {
$target_tag, $target_subfields, $target_offset, $target_length, $target_normalizer) = @_;
$self->add_required_check(
[ { tag => $source_tag, subfields => $source_subfields, offset => $source_offset, length => $source_length,
[ { tag => $source_tag, subfields => $source_subfields, offset => $source_offset, 'length' => $source_length,
norms => [ $source_normalizer ] } ],
[ { tag => $target_tag, subfields => $target_subfields, offset => $target_offset, length => $target_length,
[ { tag => $target_tag, subfields => $target_subfields, offset => $target_offset, 'length' => $target_length,
norms => [ $target_normalizer ] } ]
);
}
@ -646,6 +691,41 @@ sub get_matches {
}
=head2 dump
=over 4
$description = $matcher->dump();
=back
Returns a reference to a structure containing all of the information
in the matcher object. This is mainly a convenience method to
aid setting up a HTML editing form.
=cut
sub dump {
my $self = shift;
my $result = {};
$result->{'matcher_id'} = $self->{'id'};
$result->{'code'} = $self->{'code'};
$result->{'description'} = $self->{'description'};
$result->{'matchpoints'} = [];
foreach my $matchpoint (@{ $self->{'matchpoints'} }) {
push @{ $result->{'matchpoints'} }, $matchpoint;
}
$result->{'matchchecks'} = [];
foreach my $matchcheck (@{ $self->{'required_checks'} }) {
push @{ $result->{'matchchecks'} }, $matchcheck;
}
return $result;
}
sub _passes_required_checks {
my ($source_record, $target_blob, $matchchecks) = @_;
my $target_record = MARC::Record->new_from_usmarc($target_blob); # FIXME -- need to avoid parsing record twice

280
admin/matching-rules.pl Executable file
View File

@ -0,0 +1,280 @@
#! /usr/bin/perl
#
# Copyright 2007 LibLime
#
# 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., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
#
use strict;
use CGI;
use C4::Auth;
use C4::Context;
use C4::Output;
use C4::Koha;
use C4::Matcher;
my $script_name = "/cgi-bin/koha/admin/matching-rules.pl";
my $input = new CGI;
my $op = $input->param('op');
my ($template, $loggedinuser, $cookie)
= get_template_and_user({template_name => "admin/matching-rules.tmpl",
query => $input,
type => "intranet",
authnotrequired => 0,
flagsrequired => {parameters => 1},
debug => 1,
});
$template->param(script_name => $script_name);
my $matcher_id = $input->param("matcher_id");
$template->param(max_matchpoint => 0);
$template->param(max_matchcheck => 0);
my $display_list = 0;
if ($op eq "edit_matching_rule") {
edit_matching_rule_form($template, $matcher_id);
} elsif ($op eq "edit_matching_rule_confirmed") {
add_update_matching_rule($template, $matcher_id);
$display_list = 1;
} elsif ($op eq "add_matching_rule") {
add_matching_rule_form($template);
} elsif ($op eq "add_matching_rule_confirmed") {
add_update_matching_rule($template, $matcher_id);
$display_list = 1;
} elsif ($op eq "delete_matching_rule") {
delete_matching_rule_form($template, $matcher_id);
} elsif ($op eq "delete_matching_rule_confirmed") {
delete_matching_rule($template, $matcher_id);
$display_list = 1;
} else {
$display_list = 1;
}
if ($display_list) {
matching_rule_list($template);
}
output_html_with_http_headers $input, $cookie, $template->output;
exit 0;
sub add_matching_rule_form {
my $template = shift;
$template->param(
matching_rule_form => 1,
confirm_op => 'add_matching_rule_confirmed',
max_matchpoint => 1,
max_matchcheck => 1
);
}
sub add_update_matching_rule {
my $template = shift;
my $matcher_id = shift;
# do parsing
my $matcher = C4::Matcher->new('biblio', 1000); # FIXME biblio only for now
$matcher->code($input->param('code'));
$matcher->description($input->param('description'));
$matcher->threshold($input->param('threshold'));
# matchpoints
my @mp_nums = sort map { /^mp_(\d+)_search_index/ ? int($1): () } $input->param;
foreach my $mp_num (@mp_nums) {
my $index = $input->param("mp_${mp_num}_search_index");
my $score = $input->param("mp_${mp_num}_score");
# components
my $components = [];
my @comp_nums = sort map { /^mp_${mp_num}_c_(\d+)_tag/ ? int($1): () } $input->param;
foreach my $comp_num (@comp_nums) {
my $component = {};
$component->{'tag'} = $input->param("mp_${mp_num}_c_${comp_num}_tag");
$component->{'subfields'} = $input->param("mp_${mp_num}_c_${comp_num}_subfields");
$component->{'offset'} = $input->param("mp_${mp_num}_c_${comp_num}_offset");
$component->{'length'} = $input->param("mp_${mp_num}_c_${comp_num}_length");
# norms
$component->{'norms'} = [];
my @norm_nums = sort map { /^mp_${mp_num}_c_${comp_num}_n_(\d+)_norm/ ? int($1): () } $input->param;
foreach my $norm_num (@norm_nums) {
push @{ $component->{'norms'} }, $input->param("mp_${mp_num}_c_${comp_num}_n_${norm_num}_norm");
}
push @$components, $component;
}
$matcher->add_matchpoint($index, $score, $components);
}
# match checks
my @mc_nums = sort map { /^mc_(\d+)_id/ ? int($1): () } $input->param;
foreach my $mc_num (@mp_nums) {
# source components
my $src_components = [];
my @src_comp_nums = sort map { /^mc_${mc_num}_src_c_(\d+)_tag/ ? int($1): () } $input->param;
foreach my $comp_num (@src_comp_nums) {
my $component = {};
$component->{'tag'} = $input->param("mc_${mc_num}_src_c_${comp_num}_tag");
$component->{'subfields'} = $input->param("mc_${mc_num}_src_c_${comp_num}_subfields");
$component->{'offset'} = $input->param("mc_${mc_num}_src_c_${comp_num}_offset");
$component->{'length'} = $input->param("mc_${mc_num}_src_c_${comp_num}_length");
# norms
$component->{'norms'} = [];
my @norm_nums = sort map { /^mc_${mc_num}_src_c_${comp_num}_n_(\d+)_norm/ ? int($1): () } $input->param;
foreach my $norm_num (@norm_nums) {
push @{ $component->{'norms'} }, $input->param("mc_${mc_num}_src_c_${comp_num}_n_${norm_num}_norm");
}
push @$src_components, $component;
}
# target components
my $tgt_components = [];
my @tgt_comp_nums = sort map { /^mc_${mc_num}_tgt_c_(\d+)_tag/ ? int($1): () } $input->param;
foreach my $comp_num (@tgt_comp_nums) {
my $component = {};
$component->{'tag'} = $input->param("mc_${mc_num}_tgt_c_${comp_num}_tag");
$component->{'subfields'} = $input->param("mc_${mc_num}_tgt_c_${comp_num}_subfields");
$component->{'offset'} = $input->param("mc_${mc_num}_tgt_c_${comp_num}_offset");
$component->{'length'} = $input->param("mc_${mc_num}_tgt_c_${comp_num}_length");
# norms
$component->{'norms'} = [];
my @norm_nums = sort map { /^mc_${mc_num}_tgt_c_${comp_num}_n_(\d+)_norm/ ? int($1): () } $input->param;
foreach my $norm_num (@norm_nums) {
push @{ $component->{'norms'} }, $input->param("mc_${mc_num}_tgt_c_${comp_num}_n_${norm_num}_norm");
}
push @$tgt_components, $component;
}
$matcher->add_required_check($src_components, $tgt_components);
}
if (defined $matcher_id and $matcher_id =~ /^\d+/) {
$matcher->_id($matcher_id);
$template->param(edited_matching_rule => $matcher->code());
} else {
$template->param(added_matching_rule => $matcher->code());
}
$matcher_id = $matcher->store();
}
sub delete_matching_rule_form {
my $template = shift;
my $matcher_id = shift;
my $matcher = C4::Matcher->fetch($matcher_id);
$template->param(
delete_matching_rule_form => 1,
confirm_op => "delete_matching_rule_confirmed",
matcher_id => $matcher_id,
code => $matcher->code(),
description => $matcher->description(),
);
}
sub delete_matching_rule {
my $template = shift;
my $matcher_id = shift;
my $matcher = C4::Matcher->fetch($matcher_id);
$template->param(deleted_matching_rule => $matcher->code(),
);
C4::Matcher->delete($matcher_id);
}
sub edit_matching_rule_form {
my $template = shift;
my $matcher_id = shift;
my $matcher = C4::Matcher->fetch($matcher_id);
$template->param(matcher_id => $matcher_id);
$template->param(code => $matcher->code());
$template->param(description => $matcher->description());
$template->param(threshold => $matcher->threshold());
my $matcher_info = $matcher->dump();
my @matchpoints = ();
my $mp_num = 0;
foreach my $matchpoint (@{ $matcher_info->{'matchpoints'} }) {
$mp_num++;
my @components = _parse_components($matchpoint->{'components'});
push @matchpoints, {
mp_num => $mp_num,
index => $matchpoint->{'index'},
score => $matchpoint->{'score'},
components => \@components
};
}
$template->param(matchpoints => \@matchpoints);
my $mc_num = 0;
my @matchchecks = ();
foreach my $matchcheck (@{ $matcher_info->{'matchchecks'} }) {
$mc_num++;
my @src_components = _parse_components($matchcheck->{'source_matchpoint'}->{'components'});
my @tgt_components = _parse_components($matchcheck->{'target_matchpoint'}->{'components'});
push @matchchecks, {
mc_num => $mc_num,
src_components => \@src_components,
tgt_components => \@tgt_components
};
}
$template->param(matchchecks => \@matchchecks);
$template->param(
matching_rule_form => 1,
edit_matching_rule => 1,
confirm_op => 'edit_matching_rule_confirmed',
max_matchpoint => $mp_num,
max_matchcheck => $mc_num
);
}
sub _parse_components {
my $components_ref = shift;
my @components = ();
my $comp_num = 0;
foreach my $component (@{ $components_ref }) {
$comp_num++;
my $norm_num = 0;
my @norms;
foreach my $norm (@{ $component->{'norms'} }) {
$norm_num++;
push @norms, { norm_num => $norm_num, norm => $norm };
}
push @components, {
comp_num => $comp_num,
tag => $component->{'tag'},
subfields => join("", sort keys %{ $component->{'subfields'} }),
offset => $component->{'offset'},
'length' => $component->{'length'},
norms => \@norms
};
}
return @components;
}
sub matching_rule_list {
my $template = shift;
my @matching_rules = C4::Matcher::GetMatcherList();
$template->param(available_matching_rules => \@matching_rules);
$template->param(display_list => 1);
}

View File

@ -28,6 +28,7 @@
<li><a href="/cgi-bin/koha/admin/checkmarc.pl">MARC Bibliographic framework test</a></li>
<li><a href="/cgi-bin/koha/admin/authtypes.pl">MARC Authorities framework</a></li>
<li><a href="/cgi-bin/koha/admin/classsources.pl">Classification sources</a></li>
<li><a href="/cgi-bin/koha/admin/matching-rules.pl">Record matching rules</a></li>
</ul>
<h5>Additional parameters</h5>

View File

@ -65,6 +65,8 @@
<dd>Create and manage Authorities frameworks that define the characteristics of your MARC Records (field and subfield definitions).</dd>
<dt><a href="/cgi-bin/koha/admin/classsources.pl">Classification sources</a></dt>
<dd>Define classification sources (i.e., call number schemes) used by your collection. Also define filing rules used for sorting call numbers.</dd>
<dt><a href="/cgi-bin/koha/admin/matching-rules.pl">Record matching rules</a></dt>
<dd>Manage rules for automatically matching MARC records during record imports.</dd>
</dl>
<h3>Additional parameters</h3>

View File

@ -0,0 +1,696 @@
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
<title>Koha &rsaquo; Administration &rsaquo; Record Matching Rules
<!-- TMPL_IF name="matching_rule_form" -->
<!-- TMPL_IF name="edit_matching_rule" -->
&rsaquo; Modify record matching rule
<!-- TMPL_ELSE -->
&rsaquo; Add record matching rule
<!-- /TMPL_IF -->
<!-- /TMPL_IF -->
<!-- TMPL_IF name="delete_matching_rule_form" -->
&rsaquo; Confirm deletion of record matching rule &quot;<!-- TMPL_VAR name="code" -->&quot;
<!-- /TMPL_IF -->
</title>
<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
<script type="text/javascript">
//<![CDATA[
var maxMatchPoint = <!-- TMPL_VAR name="max_matchpoint" -->;
var maxMatchCheck = <!-- TMPL_VAR name="max_matchcheck" -->;
function InsertMatchpoint(loc, index) {
var original= document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
// update IDs and form names
maxMatchPoint++;
clone.setAttribute('id', 'mp_' + maxMatchPoint);
var divs = clone.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var s = divs[i].getAttribute('id');
if (s.match(/mp_num/)) {
divs[i].setAttribute('id', s.replace(/mp_num/, 'mp_' + maxMatchPoint));
}
}
var inputs = clone.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var s = inputs[i].getAttribute('id');
if (s.match(/mp_num/)) {
inputs[i].setAttribute('id', s);
inputs[i].setAttribute('id', s.replace(/mp_num/, 'mp_' + maxMatchPoint));
}
var s = inputs[i].getAttribute('name');
if (s.match(/mp_num/)) {
inputs[i].setAttribute('name', s.replace(/mp_num/, 'mp_' + maxMatchPoint));
}
}
loc.parentNode.parentNode.insertBefore(clone, loc.nextSibling);
}
function InsertMatchcheck(loc, index) {
var original= document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
// update IDs and form names
maxMatchCheck++;
clone.setAttribute('id', 'mc_' + maxMatchCheck);
var divs = clone.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var s = divs[i].getAttribute('id');
if (s.match(/mc_num/)) {
divs[i].setAttribute('id', s.replace(/mc_num/, 'mc_' + maxMatchCheck));
}
}
var inputs = clone.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var s = inputs[i].getAttribute('id');
if (s.match(/mc_num/)) {
inputs[i].setAttribute('id', s);
inputs[i].setAttribute('id', s.replace(/mc_num/, 'mc_' + maxMatchCheck));
}
var s = inputs[i].getAttribute('name');
if (s.match(/mc_num/)) {
inputs[i].setAttribute('name', s.replace(/mc_num/, 'mc_' + maxMatchCheck));
}
}
loc.parentNode.parentNode.insertBefore(clone, loc.nextSibling);
}
function DeleteMatchpoint(loc) {
var parentdiv = loc.parentNode.parentNode.parentNode;
parentdiv.parentNode.removeChild(parentdiv);
}
function DeleteMatchcheck(loc) {
var parentdiv = loc.parentNode.parentNode.parentNode;
parentdiv.parentNode.removeChild(parentdiv);
}
function DoCancel(f) {
f.op.value='';
document.Aform.submit();
}
function CheckMatchingRuleForm(f) {
var ok=1;
var _alertString="";
var alertString2;
if (f.code.value.length==0) {
_alertString += "\n- " + _("Matching rule code missing");
}
if (f.description.value.length==0) {
_alertString += "\n- " + _("Description missing");
}
if (f.threshold.value.length==0) {
_alertString += "\n- " + _("Threshold missing");
}
if (_alertString.length==0) {
document.Aform.submit();
} else {
alertString2 = _("Form not submitted because of the following problem(s)");
alertString2 += "\n------------------------------------------------------------------------------------\n";
alertString2 += _alertString;
alert(alertString2);
}
}
function CheckRuleForm(f) {
var ok=1;
var _alertString="";
var alertString2;
if (f.sort_rule.value.length==0) {
_alertString += "\n- " + _("Filing rule code missing");
}
if (f.description.value.length==0) {
_alertString += "\n- " + _("Description missing");
}
if (f.sort_routine.value.length==0) {
_alertString += "\n- " + _("Sort routine missing");
}
if (_alertString.length==0) {
document.Aform.submit();
} else {
alertString2 = _("Form not submitted because of the following problem(s)");
alertString2 += "\n------------------------------------------------------------------------------------\n";
alertString2 += _alertString;
alert(alertString2);
}
}
//]]>
</script>
</head>
<body>
<!-- TMPL_INCLUDE NAME="header.inc" -->
<!-- TMPL_INCLUDE NAME="cat-search.inc" -->
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> &rsaquo; <!-- TMPL_IF name="display_list" -->Record Matching Rules<!-- TMPL_ELSE --><a href="/cgi-bin/koha/admin/matching-rules.pl">Record Matching Rules</a><!-- /TMPL_IF -->
<!-- TMPL_IF name="matching_rule_form" -->
<!-- TMPL_IF name="edit_matching_rule" -->
&rsaquo; Modify record matching rule
<!-- TMPL_ELSE -->
&rsaquo; Add record matching rule
<!-- /TMPL_IF -->
<!-- /TMPL_IF -->
<!-- TMPL_IF name="delete_matching_rule_form" -->
&rsaquo; Confirm deletion of record matching rule &quot;<!-- TMPL_VAR name="code" -->&quot;
<!-- /TMPL_IF -->
</div>
<div id="doc3" class="yui-t2">
<div id="bd">
<div id="yui-main">
<div class="yui-b">
<!-- TMPL_IF name="matching_rule_form" -->
<!-- TMPL_IF name="edit_matching_rule" -->
<h2>Modify record matching rule</h2>
<!-- TMPL_ELSE -->
<h2>Add record matching rule</h2>
<!-- /TMPL_IF -->
<form action="<!-- TMPL_VAR name="script_name" -->" name="Aform" method="post">
<input type="hidden" name="op" value="<!-- TMPL_VAR name="confirm_op"-->" />
<fieldset class="rows">
<ol>
<li>
<!-- TMPL_IF name="edit_matching_rule" -->
<span class="label">Matching rule code: </span>
<input type="hidden" name="matcher_id" value="<!-- TMPL_VAR name="matcher_id" -->" />
<input type="hidden" name="code" value="<!-- TMPL_VAR name="code" -->" />
<!-- TMPL_VAR name="code" -->
<!-- TMPL_ELSE -->
<label for="code">Matching rule code: </label>
<input type="text" id="code" name="code" size="10" maxlength="10" />
<!-- /TMPL_IF -->
</li>
<li><label for="description">Description: </label>
<input type="text" id="description" name="description" size="50" maxlength="250"
value="<!-- TMPL_VAR name="description" escape="HTML" -->" />
</li>
<li><label for="description">Match threshold: </label>
<input type="text" id="threshold" name="threshold" size="5" maxlength="5"
value="<!-- TMPL_VAR name="threshold" escape="HTML" -->" />
</li>
</ol>
</fieldset>
<fieldset class="rows">
<legend >Match points <a class="button" onclick="InsertMatchpoint(this, 'mp_template')">Add matchpoint</a></legend>
<!-- TMPL_IF name="edit_matching_rule" -->
<!-- TMPL_LOOP name="matchpoints" -->
<div id="mp_<!-- TMPL_VAR name="mp_num" -->">
<fieldset class="rows">
<legend><a class="button" onclick="DeleteMatchpoint(this)">Remove this matchpoint</a></legend>
<ol>
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_search_index">Search index: </label>
<input type ="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_search_index"
name="mp_<!-- TMPL_VAR name="mp_num" -->_search_index" size="20"
value="<!-- TMPL_VAR name="index" -->"
maxlegnth="30" escape="HTML" />
</li>
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_score">Score: </label>
<input type ="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_score"
name="mp_<!-- TMPL_VAR name="mp_num" -->_score" size="5"
value="<!-- TMPL_VAR name="score" -->"
maxlegnth="5" escape="HTML" />
</li>
<!-- TMPL_LOOP name="components" -->
<div id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->">
<fieldset class="rows">
<ol>
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_tag">Tag: </label>
<input type="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_tag"
name="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_tag"
value="<!-- TMPL_VAR name="tag" -->"
size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_subfields">Subfields: </label>
<input type="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_subfields"
name="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_subfields"
value="<!-- TMPL_VAR name="subfields" -->"
size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_offset">Offset: </label>
<input type="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_offset"
name="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_offset"
value="<!-- TMPL_VAR name="offset" -->"
size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_length">Length: </label>
<input type="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_length"
name="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_length"
value="<!-- TMPL_VAR name="length" -->"
size="5" maxlength="5" escape="HTML" />
</li>
<!-- TMPL_LOOP name="norms" -->
<div id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num"-->">
<li>
<label for="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_n__<!-- TMPL_VAR name="norm_num"-->">Normalization rule: </label>
<input type="text" id="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_n__<!-- TMPL_VAR name="norm_num"-->_norm"
name="mp_<!-- TMPL_VAR name="mp_num" -->_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num"-->_norm"
value="<!-- TMPL_VAR name="norm" -->"
size="20" maxnorms="50" escape="HTML" />
</li>
</div>
<!-- /TMPL_LOOP -->
</ol>
</fieldset>
</div>
<!-- /TMPL_LOOP -->
</ol>
</fieldset>
</div>
<!-- /TMPL_LOOP -->
<!-- TMPL_ELSE -->
<div id="mp_1">
<fieldset class="rows">
<legend><a class="button" onclick="DeleteMatchpoint(this)">Remove this matchpoint</a></legend>
<ol>
<li>
<label for="mp_1_search_index">Search index: </label>
<input type ="text" id="mp_1_search_index" name="mp_1_search_index" size="20"
maxlegnth="30" escape="HTML" />
</li>
<li>
<label for="mp_1_score">Score: </label>
<input type ="text" id="mp_1_score" name="mp_1_score" size="5" maxlegnth="5" escape="HTML" />
</li>
<div id="mp_1_c_1">
<fieldset class="rows">
<ol>
<li>
<label for="mp_1_c_1_tag">Tag: </label>
<input type="text" id="mp_1_c_1_tag" name="mp_1_c_1_tag" size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mp_1_c_1_subfields">Subfields: </label>
<input type="text" id="mp_1_c_1_subfields" name="mp_1_c_1_subfields" size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mp_1_c_1_offset">Offset: </label>
<input type="text" id="mp_1_c_1_offset" name="mp_1_c_1_offset" size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mp_1_c_1_length">Length: </label>
<input type="text" id="mp_1_c_1_length" name="mp_1_c_1_length" size="5" maxlength="5" escape="HTML" />
</li>
<div id="mp_1_c_1_n_1">
<li>
<label for="mp_1_c_1_n_1_norm">Normalization rule: </label>
<input type="text" id="mp_1_c_1_n_1_norm" name="mp_1_c_1_n_1_norm" size="20" maxnorms="50" escape="HTML" />
</li>
</div>
</ol>
</fieldset>
</div>
</ol>
</fieldset>
</div>
<!-- /TMPL_IF -->
</fieldset>
<fieldset class="rows">
<legend >Required match checks <a class="button" onclick="InsertMatchcheck(this, 'mc_template')">Add match check</a></legend>
<!-- TMPL_IF name="edit_matching_rule" -->
<!-- TMPL_LOOP name="matchchecks" -->
<div id="mc_<!-- TMPL_VAR name="mc_num" -->">
<fieldset class="rows">
<legend><a class="button" onclick="DeleteMatchcheck(this)">Remove this match check</a></legend>
<input type="hidden" id="mc_<!-- TMPL_VAR name="mc_num" -->_id" name="mc_<!-- TMPL_VAR name="mc_num" -->_id" value="1" />
<ol>
<!-- TMPL_LOOP name="src_components" -->
<div id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->">
<fieldset class="rows">
<legend>Source (incoming) record check field</legend>
<ol>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_tag">Tag: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_tag"
name="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_tag"
value="<!-- TMPL_VAR name="tag" -->"
size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_subfields">Subfields: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_subfields"
name="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_subfields"
value="<!-- TMPL_VAR name="subfields" -->"
size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_offset">Offset: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_offset"
name="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_offset"
value="<!-- TMPL_VAR name="offset" -->"
size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_length">Length: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_length"
name="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_length"
value="<!-- TMPL_VAR name="length" -->"
size="5" maxlength="5" escape="HTML" />
</li>
<!-- TMPL_LOOP name="norms" -->
<div id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->">
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->_norm">Normalization rule: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->_norm"
name="mc_<!-- TMPL_VAR name="mc_num" -->_src_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->_norm"
value="<!-- TMPL_VAR name="norm" -->"
size="20" maxnorms="50" escape="HTML" />
</li>
</div>
<!-- /TMPL_LOOP -->
</ol>
</fieldset>
</div>
<!-- /TMPL_LOOP -->
<!-- TMPL_LOOP name="tgt_components" -->
<div id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->">
<fieldset class="rows">
<legend>Target (database) record check field</legend>
<ol>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_tag">Tag: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_tag"
name="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_tag"
value="<!-- TMPL_VAR name="tag" -->"
size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_subfields">Subfields: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_subfields"
name="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_subfields"
value="<!-- TMPL_VAR name="subfields" -->"
size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_offset">Offset: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_offset"
name="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_offset"
value="<!-- TMPL_VAR name="offset" -->"
size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_length">Length: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_length"
name="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_length"
value="<!-- TMPL_VAR name="length" -->"
size="5" maxlength="5" escape="HTML" />
</li>
<!-- TMPL_LOOP name="norms" -->
<div id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->">
<li>
<label for="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->_norm">Normalization rule: </label>
<input type="text" id="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->_norm"
name="mc_<!-- TMPL_VAR name="mc_num" -->_tgt_c_<!-- TMPL_VAR name="comp_num" -->_n_<!-- TMPL_VAR name="norm_num" -->_norm"
value="<!-- TMPL_VAR name="norm" -->"
size="20" maxnorms="50" escape="HTML" />
</li>
</div>
<!-- /TMPL_LOOP -->
</ol>
</fieldset>
</div>
<!-- /TMPL_LOOP -->
</ol>
</fieldset>
</div>
<!-- /TMPL_LOOP -->
<!-- TMPL_ELSE -->
<div id="mc_1">
<fieldset class="rows">
<legend><a class="button" onclick="DeleteMatchcheck(this)">Remove this match check</a></legend>
<input type="hidden" id="mc_1_id" name="mc_1_id" value="1" />
<ol>
<div id="mc_1_src_c_1">
<fieldset class="rows">
<legend>Source (incoming) record check field</legend>
<ol>
<li>
<label for="mc_1_src_c_1_tag">Tag: </label>
<input type="text" id="mc_1_src_c_1_tag" name="mc_1_src_c_1_tag" size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mc_1_src_c_1_subfields">Subfields: </label>
<input type="text" id="mc_1_src_c_1_subfields" name="mc_1_src_c_1_subfields" size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mc_1_src_c_1_offset">Offset: </label>
<input type="text" id="mc_1_src_c_1_offset" name="mc_1_src_c_1_offset" size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mc_1_src_c_1_length">Length: </label>
<input type="text" id="mc_1_src_c_1_length" name="mc_1_src_c_1_length" size="5" maxlength="5" escape="HTML" />
</li>
<div id="mc_1_src_c_1_n_1">
<li>
<label for="mc_1_src_c_1_n_1_norm">Normalization rule: </label>
<input type="text" id="mc_1_src_c_1_n_1_norm" name="mc_1_src_c_1_n_1_norm" size="20" maxnorms="50" escape="HTML" />
</li>
</div>
</ol>
</fieldset>
</div>
<div id="mc_1_tgt_c_1">
<fieldset class="rows">
<legend>Target (database) record check field</legend>
<ol>
<li>
<label for="mc_1_tgt_c_1_tag">Tag: </label>
<input type="text" id="mc_1_tgt_c_1_tag" name="mc_1_tgt_c_1_tag" size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mc_1_tgt_c_1_subfields">Subfields: </label>
<input type="text" id="mc_1_tgt_c_1_subfields" name="mc_1_tgt_c_1_subfields" size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mc_1_tgt_c_1_offset">Offset: </label>
<input type="text" id="mc_1_tgt_c_1_offset" name="mc_1_tgt_c_1_offset" size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mc_1_tgt_c_1_length">Length: </label>
<input type="text" id="mc_1_tgt_c_1_length" name="mc_1_tgt_c_1_length" size="5" maxlength="5" escape="HTML" />
</li>
<div id="mc_1_tgt_c_1_n_1">
<li>
<label for="mc_1_tgt_c_1_n_1_norm">Normalization rule: </label>
<input type="text" id="mc_1_tgt_c_1_n_1_norm" name="mc_1_tgt_c_1_n_1_norm" size="20" maxnorms="50" escape="HTML" />
</li>
</div>
</ol>
</fieldset>
</div>
</ol>
</fieldset>
</div>
<!-- /TMPL_IF -->
</fieldset>
<fieldset class="action">
<!-- TMPL_IF name="edit_matching_rule" -->
<input type="button" value="Save"
onclick="CheckMatchingRuleForm(this.form)" />
<!-- TMPL_ELSE -->
<input type="button" value="Save"
onclick="CheckMatchingRuleForm(this.form)" />
<!-- /TMPL_IF-->
<a class="cancel" href="/cgi-bin/koha/admin/matching-rules.pl">Cancel</a>
</fieldset>
</form>
<!-- /TMPL_IF -->
<!-- TMPL_IF name="delete_matching_rule_form" -->
<h2>Confirm deletion of record matching rule &quot;<!-- TMPL_VAR name="code" -->&quot; (<!-- TMPL_VAR name="description" -->)?</h2>
<form action="<!-- TMPL_VAR name="script_name" -->" name="Aform" method="post">
<input type="hidden" name="op" value="<!-- TMPL_VAR name="confirm_op"-->" />
<input type="hidden" name="matcher_id" value="<!-- TMPL_VAR name="matcher_id" -->" />
<p id="action">
<input type="submit" value="Delete record matching rule" />
<input type="button" value="Cancel" onclick="DoCancel(this.form)" />
</p>
</form>
<!-- /TMPL_IF -->
<!-- TMPL_IF name="display_list" -->
<div id="toolbar">
<script type="text/javascript">
//<![CDATA[
// prepare DOM for YUI Toolbar
$(document).ready(function() {
yuiToolbar();
});
// YUI Toolbar Functions
function yuiToolbar() {
new YAHOO.widget.Button("newrule");
} //]]>
</script>
<ul class="toolbar">
<li><a id="newrule" href="<!-- TMPL_VAR name="script_name" -->?op=add_matching_rule">New Record Matching Rule</a></li>
</ul></div>
<h2>Record Matching Rules</h2>
<!-- TMPL_IF name="added_matching_rule" -->
<span class="problem">Added record matching rule &quot;<!-- TMPL_VAR name="added_matching_rule" -->&quot;</span>
<!-- /TMPL_IF -->
<!-- TMPL_IF name="edited_matching_rule" -->
<span class="problem">Modified record matching rule &quot;<!-- TMPL_VAR name="edited_matching_rule" -->&quot;</span>
<!-- /TMPL_IF -->
<!-- TMPL_IF name="deleted_matching_rule" -->
<span class="problem">Deleted record matching rule &quot;<!-- TMPL_VAR name="deleted_matching_rule" -->&quot;</span>
<!-- /TMPL_IF -->
<table>
<tr>
<th>#</th>
<th>Code</th>
<th>Description</th>
<th>Actions</th>
</tr>
<!-- TMPL_LOOP name="available_matching_rules" -->
<tr>
<td><!-- TMPL_VAR name="matcher_id" --></td>
<td><!-- TMPL_VAR name="code" --></td>
<td><!-- TMPL_VAR name="description" --></td>
<td>
<a href="<!-- TMPL_VAR name="script_name" -->?op=edit_matching_rule&amp;matcher_id=<!-- TMPL_VAR name="matcher_id" escape="HTML" -->">Edit</a>
<a href="<!-- TMPL_VAR name="script_name" -->?op=delete_matching_rule&amp;matcher_id=<!-- TMPL_VAR name="matcher_id" escape="HTML" -->">Delete</a>
</td>
</tr>
<!-- /TMPL_LOOP -->
</table>
<div class="paginationBar"><!-- TMPL_VAR NAME="pagination_bar" --></div>
<!-- /TMPL_IF -->
<div id="mp_template" style="display:none">
<fieldset class="rows">
<legend><a class="button" onclick="DeleteMatchpoint(this)">Remove this matchpoint</a></legend>
<ol>
<li>
<label for="mp_num_search_index">Search index: </label>
<input type ="text" id="mp_num_search_index" name="mp_num_search_index" size="20"
maxlegnth="30" escape="HTML" />
</li>
<li>
<label for="mp_num_score">Score: </label>
<input type ="text" id="mp_num_score" name="mp_num_score" size="5" maxlegnth="5" escape="HTML" />
</li>
<div id="mp_num_c_1">
<fieldset class="rows">
<ol>
<li>
<label for="mp_num_c_1_tag">Tag: </label>
<input type="text" id="mp_num_c_1_tag" name="mp_num_c_1_tag" size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mp_num_c_1_subfields">Subfields: </label>
<input type="text" id="mp_num_c_1_subfields" name="mp_num_c_1_subfields" size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mp_num_c_1_offset">Offset: </label>
<input type="text" id="mp_num_c_1_offset" name="mp_num_c_1_offset" size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mp_num_c_1_length">Length: </label>
<input type="text" id="mp_num_c_1_length" name="mp_num_c_1_length" size="5" maxlength="5" escape="HTML" />
</li>
<div id="mp_num_c_1_n_1">
<li>
<label for="mp_num_c_1_n_1_norm">Normalization rule: </label>
<input type="text" id="mp_num_c_1_n_1_norm" name="mp_num_c_1_n_1_norm" size="20" maxnorms="50" escape="HTML" />
</li>
</div>
</ol>
</fieldset>
</div>
</ol>
</fieldset>
</div>
<div id="mc_template" style="display:none">
<fieldset class="rows">
<legend><a class="button" onclick="DeleteMatchcheck(this)">Remove this match check</a></legend>
<input type="hidden" id="mc_num_id" name="mc_num_id" value="1" />
<ol>
<div id="mc_num_src_c_1">
<fieldset class="rows">
<legend>Source (incoming) record check field</legend>
<ol>
<li>
<label for="mc_num_src_c_1_tag">Tag: </label>
<input type="text" id="mc_num_src_c_1_tag" name="mc_num_src_c_1_tag" size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mc_num_src_c_1_subfields">Subfields: </label>
<input type="text" id="mc_num_src_c_1_subfields" name="mc_num_src_c_1_subfields" size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mc_num_src_c_1_offset">Offset: </label>
<input type="text" id="mc_num_src_c_1_offset" name="mc_num_src_c_1_offset" size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mc_num_src_c_1_length">Length: </label>
<input type="text" id="mp_num_c_1_length" name="mp_num_c_1_length" size="5" maxlength="5" escape="HTML" />
</li>
<div id="mc_num_src_c_1_n_1">
<li>
<label for="mc_num_src_c_1_n_1_norm">Normalization rule: </label>
<input type="text" id="mc_num_src_c_1_n_1_norm" name="mc_num_src_c_1_n_1_norm" size="20" maxnorms="50" escape="HTML" />
</li>
</div>
</ol>
</fieldset>
</div>
<div id="mc_num_tgt_c_1">
<fieldset class="rows">
<legend>Target (database) record check field</legend>
<ol>
<li>
<label for="mc_num_tgt_c_1_tag">Tag: </label>
<input type="text" id="mc_num_tgt_c_1_tag" name="mc_num_tgt_c_1_tag" size="3" maxlength="3" escape="HTML" />
</li>
<li>
<label for="mc_num_tgt_c_1_subfields">Subfields: </label>
<input type="text" id="mc_num_tgt_c_1_subfields" name="mc_num_tgt_c_1_subfields" size="10" maxlength="40" escape="HTML" />
</li>
<li>
<label for="mc_num_tgt_c_1_offset">Offset: </label>
<input type="text" id="mc_num_tgt_c_1_offset" name="mc_num_tgt_c_1_offset" size="5" maxoffset="5" escape="HTML" />
</li>
<li>
<label for="mc_num_tgt_c_1_length">Length: </label>
<input type="text" id="mp_num_c_1_length" name="mp_num_c_1_length" size="5" maxlength="5" escape="HTML" />
</li>
<div id="mc_num_tgt_c_1_n_1">
<li>
<label for="mc_num_tgt_c_1_n_1_norm">Normalization rule: </label>
<input type="text" id="mc_num_tgt_c_1_n_1_norm" name="mc_num_tgt_c_1_n_1_norm" size="20" maxnorms="50" escape="HTML" />
</li>
</div>
</ol>
</fieldset>
</div>
</ol>
</fieldset>
</div>
</div>
</div>
<div class="yui-b">
<!-- TMPL_INCLUDE NAME="admin-menu.inc" -->
</div>
</div>
<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->