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

(-)a/C4/Matcher.pm (-21 / +39 lines)
Lines 199-204 sub fetch { Link Here
199
        my $matchcheck = {};
199
        my $matchcheck = {};
200
        $matchcheck->{'source_matchpoint'} = $source_matchpoint;
200
        $matchcheck->{'source_matchpoint'} = $source_matchpoint;
201
        $matchcheck->{'target_matchpoint'} = $target_matchpoint;
201
        $matchcheck->{'target_matchpoint'} = $target_matchpoint;
202
        $matchcheck->{'operator'}          = $row->{'operator'};
202
        push @{ $self->{'required_checks'} }, $matchcheck;
203
        push @{ $self->{'required_checks'} }, $matchcheck;
203
    }
204
    }
204
205
Lines 208-214 sub fetch { Link Here
208
sub _fetch_matchpoint {
209
sub _fetch_matchpoint {
209
    my $self = shift;
210
    my $self = shift;
210
    my $matchpoint_id = shift;
211
    my $matchpoint_id = shift;
211
    
212
212
    my $dbh = C4::Context->dbh;
213
    my $dbh = C4::Context->dbh;
213
    my $sth = $dbh->prepare_cached("SELECT * FROM matchpoints WHERE matchpoint_id = ?");
214
    my $sth = $dbh->prepare_cached("SELECT * FROM matchpoints WHERE matchpoint_id = ?");
214
    $sth->execute($matchpoint_id);
215
    $sth->execute($matchpoint_id);
Lines 223-235 sub _fetch_matchpoint { Link Here
223
    $sth->execute($matchpoint_id);
224
    $sth->execute($matchpoint_id);
224
    while ($row = $sth->fetchrow_hashref) {
225
    while ($row = $sth->fetchrow_hashref) {
225
        my $component = {};
226
        my $component = {};
226
        $component->{'tag'} = $row->{'tag'};
227
        $component->{'tag'}       = $row->{'tag'};
227
        $component->{'subfields'} = { map { $_ => 1 } split(//,  $row->{'subfields'}) };
228
        $component->{'subfields'} = { map { $_ => 1 } split(//,  $row->{'subfields'}) };
228
        $component->{'offset'} = int($row->{'offset'});
229
        $component->{'offset'}    = int($row->{'offset'});
229
        $component->{'length'} = int($row->{'length'});
230
        $component->{'length'}    = int($row->{'length'});
230
        $component->{'norms'} = [];
231
        $component->{'norms'}     = [];
231
        my $sth2 = $dbh->prepare_cached("SELECT * 
232
        $component->{'constant'}  = $row->{'constant'};
232
                                         FROM matchpoint_component_norms 
233
        $component->{'type'}      = defined $row->{'constant'} ? 'constant' : 'field';
234
        my $sth2 = $dbh->prepare_cached("SELECT *
235
                                         FROM matchpoint_component_norms
233
                                         WHERE matchpoint_component_id = ? ORDER BY sequence");
236
                                         WHERE matchpoint_component_id = ? ORDER BY sequence");
234
        $sth2->execute($row->{'matchpoint_component_id'});
237
        $sth2->execute($row->{'matchpoint_component_id'});
235
        while (my $row2 = $sth2->fetchrow_hashref) {
238
        while (my $row2 = $sth2->fetchrow_hashref) {
Lines 319-328 sub _store_matcher_components { Link Here
319
    foreach my $matchcheck (@{ $self->{'required_checks'} }) {
322
    foreach my $matchcheck (@{ $self->{'required_checks'} }) {
320
        my $source_matchpoint_id = $self->_store_matchpoint($matchcheck->{'source_matchpoint'});
323
        my $source_matchpoint_id = $self->_store_matchpoint($matchcheck->{'source_matchpoint'});
321
        my $target_matchpoint_id = $self->_store_matchpoint($matchcheck->{'target_matchpoint'});
324
        my $target_matchpoint_id = $self->_store_matchpoint($matchcheck->{'target_matchpoint'});
322
        $sth = $dbh->prepare_cached("INSERT INTO matchchecks
325
        $sth = $dbh->prepare_cached(
323
                                     (matcher_id, source_matchpoint_id, target_matchpoint_id)
326
            "INSERT INTO matchchecks
324
                                     VALUES (?, ?, ?)");
327
                                     (matcher_id, source_matchpoint_id, target_matchpoint_id, operator)
325
        $sth->execute($matcher_id, $source_matchpoint_id,  $target_matchpoint_id);
328
                                     VALUES (?, ?, ?, ?)"
329
        );
330
        $sth->execute( $matcher_id, $source_matchpoint_id,  $target_matchpoint_id, $matchcheck->{'operator'} );
326
    }
331
    }
327
332
328
}
333
}
Lines 341-355 sub _store_matchpoint { Link Here
341
    my $seqnum = 0;
346
    my $seqnum = 0;
342
    foreach my $component (@{ $matchpoint->{'components'} }) {
347
    foreach my $component (@{ $matchpoint->{'components'} }) {
343
        $seqnum++;
348
        $seqnum++;
344
        $sth = $dbh->prepare_cached("INSERT INTO matchpoint_components 
349
        $sth = $dbh->prepare_cached(
345
                                     (matchpoint_id, sequence, tag, subfields, `offset`, length)
350
            "INSERT INTO matchpoint_components
346
                                     VALUES (?, ?, ?, ?, ?, ?)");
351
                                     (matchpoint_id, sequence, tag, subfields, `offset`, length, `constant`)
352
                                     VALUES (?, ?, ?, ?, ?, ?, ?)"
353
        );
347
        $sth->bind_param(1, $matchpoint_id);
354
        $sth->bind_param(1, $matchpoint_id);
348
        $sth->bind_param(2, $seqnum);
355
        $sth->bind_param(2, $seqnum);
349
        $sth->bind_param(3, $component->{'tag'});
356
        $sth->bind_param(3, $component->{'tag'});
350
        $sth->bind_param(4, join "", sort keys %{ $component->{'subfields'} });
357
        $sth->bind_param(4, join "", sort keys %{ $component->{'subfields'} });
351
        $sth->bind_param(5, $component->{'offset'}||0);
358
        $sth->bind_param(5, $component->{'offset'}||0);
352
        $sth->bind_param(6, $component->{'length'});
359
        $sth->bind_param(6, $component->{'length'});
360
        $sth->bind_param( 7, $component->{'constant'} );
353
        $sth->execute();
361
        $sth->execute();
354
        my $matchpoint_component_id = $dbh->{'mysql_insertid'};
362
        my $matchpoint_component_id = $dbh->{'mysql_insertid'};
355
        my $normseq = 0;
363
        my $normseq = 0;
Lines 552-560 to the source string. Link Here
552
560
553
sub add_required_check {
561
sub add_required_check {
554
    my $self = shift;
562
    my $self = shift;
555
    my ($source_matchpoint, $target_matchpoint) = @_;
563
    my ( $source_matchpoint, $target_matchpoint, $operator ) = @_;
556
564
557
    my $matchcheck = {};
565
    my $matchcheck = { 'operator' => $operator };
558
    $matchcheck->{'source_matchpoint'}->{'index'} = '';
566
    $matchcheck->{'source_matchpoint'}->{'index'} = '';
559
    $matchcheck->{'source_matchpoint'}->{'score'} = 0;
567
    $matchcheck->{'source_matchpoint'}->{'score'} = 0;
560
    $matchcheck->{'source_matchpoint'}->{'components'} = [];
568
    $matchcheck->{'source_matchpoint'}->{'components'} = [];
Lines 903-913 sub _parse_match_component { Link Here
903
    my $input_component = shift;
911
    my $input_component = shift;
904
912
905
    my $component = {};
913
    my $component = {};
906
    $component->{'tag'} = $input_component->{'tag'};
914
    if ( $input_component->{'type'} eq 'constant' ) {
907
    $component->{'subfields'} = { map { $_ => 1 } split(//, $input_component->{'subfields'}) };
915
        $component->{'tag'}       = '';
908
    $component->{'offset'} = exists($input_component->{'offset'}) ? $input_component->{'offset'} : -1;
916
        $component->{'subfields'} = {};
909
    $component->{'length'} = $input_component->{'length'} ? $input_component->{'length'} : 0;
917
        $component->{'offset'}    = 0;
910
    $component->{'norms'} =  $input_component->{'norms'} ? $input_component->{'norms'} : [];
918
        $component->{'length'}    = 0;
919
        $component->{'norms'}     = [];
920
        $component->{'constant'}  = $input_component->{'constant'};
921
    } else {
922
        $component->{'tag'}       = $input_component->{'tag'};
923
        $component->{'subfields'} = { map { $_ => 1 } split( //, $input_component->{'subfields'} ) };
924
        $component->{'offset'}    = exists( $input_component->{'offset'} ) ? $input_component->{'offset'} : -1;
925
        $component->{'length'}    = $input_component->{'length'}           ? $input_component->{'length'} : 0;
926
        $component->{'norms'}     = $input_component->{'norms'}            ? $input_component->{'norms'}  : [];
927
        $component->{'constant'}  = undef;
928
    }
911
929
912
    return $component;
930
    return $component;
913
}
931
}
(-)a/admin/matching-rules.pl (-6 / +10 lines)
Lines 136-142 sub add_update_matching_rule { Link Here
136
            foreach my $comp_num (@comp_nums) {
136
            foreach my $comp_num (@comp_nums) {
137
                my $component = {};
137
                my $component = {};
138
                my $p = "mc_${mc_num}_${which}_c_${comp_num}_";
138
                my $p = "mc_${mc_num}_${which}_c_${comp_num}_";
139
                map { $component->{$_} = $input->param("${p}$_") } qw(tag subfields offset length);
139
                map { $component->{$_} = $input->param("${p}$_") } qw(tag subfields offset length constant type);
140
                # norms
140
                # norms
141
                $component->{'norms'} = [];
141
                $component->{'norms'} = [];
142
                my @norm_nums = sort map { /^${p}n_(\d+)_norm/ ? int($1): () } $input->multi_param;
142
                my @norm_nums = sort map { /^${p}n_(\d+)_norm/ ? int($1): () } $input->multi_param;
Lines 146-152 sub add_update_matching_rule { Link Here
146
                push @$components, $component;
146
                push @$components, $component;
147
            }
147
            }
148
        }
148
        }
149
        $matcher->add_required_check($src_components, $tgt_components);
149
150
        $matcher->add_required_check($src_components, $tgt_components, $input->param("mc_${mc_num}_operator"));
150
    }
151
    }
151
152
152
    if (defined $matcher_id and $matcher_id =~ /^\d+/) {
153
    if (defined $matcher_id and $matcher_id =~ /^\d+/) {
Lines 200-211 sub edit_matching_rule_form { Link Here
200
    foreach my $matchpoint (@{ $matcher_info->{'matchpoints'} }) {
201
    foreach my $matchpoint (@{ $matcher_info->{'matchpoints'} }) {
201
        $mp_num++;
202
        $mp_num++;
202
        my @components = _parse_components($matchpoint->{'components'});
203
        my @components = _parse_components($matchpoint->{'components'});
203
        push @matchpoints, { 
204
        push @matchpoints, {
204
            mp_num => $mp_num, 
205
            mp_num => $mp_num,
205
            index => $matchpoint->{'index'}, 
206
            index => $matchpoint->{'index'},
206
            score => $matchpoint->{'score'},
207
            score => $matchpoint->{'score'},
207
            components => \@components
208
            components => \@components
208
        };        
209
        };
209
    }
210
    }
210
    $template->param(matchpoints => \@matchpoints);
211
    $template->param(matchpoints => \@matchpoints);
211
212
Lines 217-222 sub edit_matching_rule_form { Link Here
217
        my @tgt_components = _parse_components($matchcheck->{'target_matchpoint'}->{'components'});
218
        my @tgt_components = _parse_components($matchcheck->{'target_matchpoint'}->{'components'});
218
        push @matchchecks, {
219
        push @matchchecks, {
219
            mc_num => $mc_num,
220
            mc_num => $mc_num,
221
            operator => $matchcheck->{'operator'},
220
            src_components => \@src_components,
222
            src_components => \@src_components,
221
            tgt_components => \@tgt_components
223
            tgt_components => \@tgt_components
222
        };
224
        };
Lines 252-257 sub _parse_components { Link Here
252
            subfields => join("", sort keys %{ $component->{'subfields'} }),
254
            subfields => join("", sort keys %{ $component->{'subfields'} }),
253
            offset => $component->{'offset'},
255
            offset => $component->{'offset'},
254
            'length' => $component->{'length'},
256
            'length' => $component->{'length'},
257
            constant => $component->{'constant'},
258
            type => $component->{'type'},
255
            norms => \@norms
259
            norms => \@norms
256
        };
260
        };
257
    }
261
    }
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/matching-rules.tt (-19 / +32 lines)
Lines 54-85 Link Here
54
    </select>
54
    </select>
55
[% END %]
55
[% END %]
56
56
57
[% BLOCK operator_select %]
58
[%# PARAMS: operator, id, name  %]
59
    <label for="[% id | html %]">Operator: </label>
60
    <select id="[% id | html %]" name="[% name | html %]">
61
        <option value="eq" [% IF operator == 'eq' %] selected="selected" [% END %]>source = target (case sensitive string equality)</option>
62
        <option value="ne" [% IF operator == 'ne' %] selected="selected" [% END %]>source ≠ target (case sensitive string inequality)</option>
63
    </select>
64
[% END %]
65
57
[% BLOCK match_check_component %]
66
[% BLOCK match_check_component %]
58
    [%# PARAMS mc_num, which, components %]
67
    [%# PARAMS mc_num, which, components %]
59
    [% IF (!components) %]
68
    [% IF (!components) %]
60
        [% SET components = [
69
        [% SET components = [ { comp_num => 1, norms => [ { norm_num => 1, norm = "none" } ], tag => '', subfields => '', offset => '', length => '', type => 'field', constant => '' } ] %]
61
            {
62
                comp_num => 1, norms => [
63
                    {
64
                        norm_num => 1,
65
                        norm = "none"
66
                    }
67
                ],
68
                tag => '',
69
                subfields => '',
70
                offset => '',
71
                length => ''
72
            }
73
         ] %]
74
    [% END %]
70
    [% END %]
75
    [% FOREACH component IN components %]
71
    [% FOREACH component IN components %]
76
        [% SET pc = "mc_${mc_num}_${which}_c_${component.comp_num}" %]
72
        [% SET pc = "mc_${mc_num}_${which}_c_${component.comp_num}" %]
77
        <fieldset class="rows" id="[% pc | html %]">
73
        <fieldset class="rows" id="[% pc | html %]">
74
            <legend><input type="radio" name="[% pc | html %]_type" id="[% pc | html %]_type_field" value="field" [% IF component.type != 'constant' %]checked="checked"[% END %] />
78
            [% IF (which == 'src') %]
75
            [% IF (which == 'src') %]
79
            <legend>Source (incoming) record check field</legend>
76
            Source (incoming) record check field
80
            [% ELSE %]
77
            [% ELSE %]
81
            <legend>Target (database) record check field</legend>
78
            Target (database) record check field
82
            [% END %]
79
            [% END %]
80
            </legend>
83
            <ol>
81
            <ol>
84
                <li>
82
                <li>
85
                    <label for="[% pc | html %]_tag">Tag: </label>
83
                    <label for="[% pc | html %]_tag">Tag: </label>
Lines 104-110 Link Here
104
                    </li>
102
                    </li>
105
                [% END %]
103
                [% END %]
106
            </ol>
104
            </ol>
107
        </fieldset> <!-- /#[% pc %] -->
105
            <legend><input type="radio" name="[% pc | html %]_type" id="[% pc | html %]_type_field" value="constant" [% IF component.type == 'constant' %]checked="checked"[% END %] />
106
            [% IF (which == 'src') %]
107
            Compare to constant value instead of source field
108
            [% ELSE %]
109
            Compare to constant value instead of target field
110
            [% END %]
111
            </legend>
112
            <ol>
113
                <li>
114
                    <label for="[% pc | html %]_constant">Constant value: </label>
115
                    <input type="text" id="[% pc | html %]_constant" name="[% pc | html %]_constant" value="[% component.constant | html %]" size="50" />
116
                </li>
117
            </ol>
118
        </fieldset> <!-- /#[% pc | html %] -->
108
    [% END #/FOREACH component %]
119
    [% END #/FOREACH component %]
109
[% END %]
120
[% END %]
110
121
Lines 340-345 Link Here
340
                                        <fieldset class="rows">
351
                                        <fieldset class="rows">
341
                                            <legend>Match check [% matchcheck.mc_num | html %]</legend>
352
                                            <legend>Match check [% matchcheck.mc_num | html %]</legend>
342
                                            <p><a href="#" class="btn btn-link" onclick="InsertMatchcheck('mc_[% matchcheck.mc_num | html %]', 'mc_template'); return false;"><i class="fa fa-plus" aria-hidden="true"></i> New match check</a> | <a href="#" class="btn btn-link" onclick="DeleteMatchcheck(this); return false;"><i class="fa fa-trash-can" aria-hidden="true"></i> Remove this match check</a></p>
353
                                            <p><a href="#" class="btn btn-link" onclick="InsertMatchcheck('mc_[% matchcheck.mc_num | html %]', 'mc_template'); return false;"><i class="fa fa-plus" aria-hidden="true"></i> New match check</a> | <a href="#" class="btn btn-link" onclick="DeleteMatchcheck(this); return false;"><i class="fa fa-trash-can" aria-hidden="true"></i> Remove this match check</a></p>
354
                                            [% PROCESS operator_select id="mc_${matchcheck.mc_num}_operator" name="mc_${matchcheck.mc_num}_operator" operator=matchcheck.operator %]
343
                                            <input type="hidden" id="mc_[% matchcheck.mc_num | html %]_id" name="mc_[% matchcheck.mc_num | html %]_id" value="1" />
355
                                            <input type="hidden" id="mc_[% matchcheck.mc_num | html %]_id" name="mc_[% matchcheck.mc_num | html %]_id" value="1" />
344
                                            [% PROCESS match_check_component mc_num=matchcheck.mc_num which="src" components=matchcheck.src_components %]
356
                                            [% PROCESS match_check_component mc_num=matchcheck.mc_num which="src" components=matchcheck.src_components %]
345
                                            [% PROCESS match_check_component mc_num=matchcheck.mc_num which="tgt" components=matchcheck.tgt_components %]
357
                                            [% PROCESS match_check_component mc_num=matchcheck.mc_num which="tgt" components=matchcheck.tgt_components %]
Lines 352-357 Link Here
352
                                    <fieldset class="rows">
364
                                    <fieldset class="rows">
353
                                        <legend>Match check 1</legend>
365
                                        <legend>Match check 1</legend>
354
                                        <p><a href="#" class="btn btn-link" onclick="InsertMatchcheck('mc_1', 'mc_template'); return false;"><i class="fa fa-plus" aria-hidden="true"></i> New match check</a> | <a href="#" class="btn btn-link" onclick="DeleteMatchcheck(this); return false;"><i class="fa fa-trash-can" aria-hidden="true"></i> Remove this match check</a></p>
366
                                        <p><a href="#" class="btn btn-link" onclick="InsertMatchcheck('mc_1', 'mc_template'); return false;"><i class="fa fa-plus" aria-hidden="true"></i> New match check</a> | <a href="#" class="btn btn-link" onclick="DeleteMatchcheck(this); return false;"><i class="fa fa-trash-can" aria-hidden="true"></i> Remove this match check</a></p>
367
                                        [% PROCESS operator_select id="mc_1_operator" name="mc_1_operator" %]
355
                                        <input type="hidden" id="mc_1_id" name="mc_1_id" value="1" />
368
                                        <input type="hidden" id="mc_1_id" name="mc_1_id" value="1" />
356
                                        [% PROCESS match_check_component mc_num=1 which="src" components=0 %]
369
                                        [% PROCESS match_check_component mc_num=1 which="src" components=0 %]
357
                                        [% PROCESS match_check_component mc_num=1 which="tgt" components=0 %]
370
                                        [% PROCESS match_check_component mc_num=1 which="tgt" components=0 %]
Lines 480-485 Link Here
480
                        <fieldset class="rows">
493
                        <fieldset class="rows">
481
                            <legend>Match check <span class="counter"></span></legend>
494
                            <legend>Match check <span class="counter"></span></legend>
482
                            <p><a href="#" class="button" onclick="DeleteMatchcheck(this); return false;"><i class="fa fa-trash-can" aria-hidden="true"></i>  Remove this match check</a></p>
495
                            <p><a href="#" class="button" onclick="DeleteMatchcheck(this); return false;"><i class="fa fa-trash-can" aria-hidden="true"></i>  Remove this match check</a></p>
496
                            [% PROCESS operator_select id="mc_num_operator" name="mc_num_operator" %]
483
                            <input type="hidden" id="mc_num_id" name="mc_num_id" value="1" />
497
                            <input type="hidden" id="mc_num_id" name="mc_num_id" value="1" />
484
                            [% PROCESS match_check_component mc_num="num" which="src" components=0 %]
498
                            [% PROCESS match_check_component mc_num="num" which="src" components=0 %]
485
                            [% PROCESS match_check_component mc_num="num" which="tgt" components=0 %]
499
                            [% PROCESS match_check_component mc_num="num" which="tgt" components=0 %]
Lines 562-568 Link Here
562
                    $(this).attr("id",s.replace(/mc_num/, 'mc_' + maxMatchCheck));
576
                    $(this).attr("id",s.replace(/mc_num/, 'mc_' + maxMatchCheck));
563
                }
577
                }
564
            });
578
            });
565
            $("input",clone).each(function(){
579
            $("input, select",clone).each(function(){
566
                var s = $(this).attr("id");
580
                var s = $(this).attr("id");
567
                if(s.match(/mc_num/)){
581
                if(s.match(/mc_num/)){
568
                  $(this).attr("id",s.replace(/mc_num/, 'mc_' + maxMatchCheck));
582
                  $(this).attr("id",s.replace(/mc_num/, 'mc_' + maxMatchCheck));
569
- 

Return to bug 15536