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

(-)a/C4/AuthoritiesMarc.pm (-57 / +64 lines)
Lines 1-6 Link Here
1
package C4::AuthoritiesMarc;
1
package C4::AuthoritiesMarc;
2
2
3
# Copyright 2000-2002 Katipo Communications
3
# Copyright 2000-2002 Katipo Communications
4
# Copyright 2018 The National Library of Finland, University of Helsinki
4
#
5
#
5
# This file is part of Koha.
6
# This file is part of Koha.
6
#
7
#
Lines 359-368 sub GuessAuthTypeCode { Link Here
359
        '110'=>{authtypecode=>'CORPO_NAME'},
360
        '110'=>{authtypecode=>'CORPO_NAME'},
360
        '111'=>{authtypecode=>'MEETI_NAME'},
361
        '111'=>{authtypecode=>'MEETI_NAME'},
361
        '130'=>{authtypecode=>'UNIF_TITLE'},
362
        '130'=>{authtypecode=>'UNIF_TITLE'},
363
        '147'=>{authtypecode=>'NAME_EVENT'},
362
        '148'=>{authtypecode=>'CHRON_TERM'},
364
        '148'=>{authtypecode=>'CHRON_TERM'},
363
        '150'=>{authtypecode=>'TOPIC_TERM'},
365
        '150'=>{authtypecode=>'TOPIC_TERM'},
364
        '151'=>{authtypecode=>'GEOGR_NAME'},
366
        '151'=>{authtypecode=>'GEOGR_NAME'},
365
        '155'=>{authtypecode=>'GENRE/FORM'},
367
        '155'=>{authtypecode=>'GENRE/FORM'},
368
        '162'=>{authtypecode=>'MED_PERFRM'},
366
        '180'=>{authtypecode=>'GEN_SUBDIV'},
369
        '180'=>{authtypecode=>'GEN_SUBDIV'},
367
        '181'=>{authtypecode=>'GEO_SUBDIV'},
370
        '181'=>{authtypecode=>'GEO_SUBDIV'},
368
        '182'=>{authtypecode=>'CHRON_SUBD'},
371
        '182'=>{authtypecode=>'CHRON_SUBD'},
Lines 938-943 sub BuildSummary { Link Here
938
# construct MARC21 summary
941
# construct MARC21 summary
939
# FIXME - looping over 1XX is questionable
942
# FIXME - looping over 1XX is questionable
940
# since MARC21 authority should have only one 1XX
943
# since MARC21 authority should have only one 1XX
944
        use C4::Heading::MARC21;
945
        my $handler = C4::Heading::MARC21->new();
941
        my $subfields_to_report;
946
        my $subfields_to_report;
942
        foreach my $field ($record->field('1..')) {
947
        foreach my $field ($record->field('1..')) {
943
            my $tag = $field->tag();
948
            my $tag = $field->tag();
Lines 945-975 sub BuildSummary { Link Here
945
# FIXME - 152 is not a good tag to use
950
# FIXME - 152 is not a good tag to use
946
# in MARC21 -- purely local tags really ought to be
951
# in MARC21 -- purely local tags really ought to be
947
# 9XX
952
# 9XX
948
            if ($tag eq '100') {
953
949
                $subfields_to_report = 'abcdefghjklmnopqrstvxyz';
954
            $subfields_to_report = $handler->get_auth_heading_subfields_to_report($tag);
950
            } elsif ($tag eq '110') {
955
951
                $subfields_to_report = 'abcdefghklmnoprstvxyz';
952
            } elsif ($tag eq '111') {
953
                $subfields_to_report = 'acdefghklnpqstvxyz';
954
            } elsif ($tag eq '130') {
955
                $subfields_to_report = 'adfghklmnoprstvxyz';
956
            } elsif ($tag eq '148') {
957
                $subfields_to_report = 'abvxyz';
958
            } elsif ($tag eq '150') {
959
                $subfields_to_report = 'abvxyz';
960
            } elsif ($tag eq '151') {
961
                $subfields_to_report = 'avxyz';
962
            } elsif ($tag eq '155') {
963
                $subfields_to_report = 'abvxyz';
964
            } elsif ($tag eq '180') {
965
                $subfields_to_report = 'vxyz';
966
            } elsif ($tag eq '181') {
967
                $subfields_to_report = 'vxyz';
968
            } elsif ($tag eq '182') {
969
                $subfields_to_report = 'vxyz';
970
            } elsif ($tag eq '185') {
971
                $subfields_to_report = 'vxyz';
972
            }
973
            if ($subfields_to_report) {
956
            if ($subfields_to_report) {
974
                push @authorized, {
957
                push @authorized, {
975
                    heading => $field->as_string($subfields_to_report),
958
                    heading => $field->as_string($subfields_to_report),
Lines 1093-1136 sub GetAuthorizedHeading { Link Here
1093
            return $field->as_string('abcdefghijlmnopqrstuvwxyz');
1076
            return $field->as_string('abcdefghijlmnopqrstuvwxyz');
1094
        }
1077
        }
1095
    } else {
1078
    } else {
1079
        use C4::Heading::MARC21;
1080
        my $handler = C4::Heading::MARC21->new();
1081
1096
        foreach my $field ($record->field('1..')) {
1082
        foreach my $field ($record->field('1..')) {
1097
            my $tag = $field->tag();
1083
            my $subfields = $handler->get_valid_bib_heading_subfields($field->tag());
1098
            next if "152" eq $tag;
1084
            return $field->as_string($subfields) if ($subfields);
1099
# FIXME - 152 is not a good tag to use
1100
# in MARC21 -- purely local tags really ought to be
1101
# 9XX
1102
            if ($tag eq '100') {
1103
                return $field->as_string('abcdefghjklmnopqrstvxyz68');
1104
            } elsif ($tag eq '110') {
1105
                return $field->as_string('abcdefghklmnoprstvxyz68');
1106
            } elsif ($tag eq '111') {
1107
                return $field->as_string('acdefghklnpqstvxyz68');
1108
            } elsif ($tag eq '130') {
1109
                return $field->as_string('adfghklmnoprstvxyz68');
1110
            } elsif ($tag eq '148') {
1111
                return $field->as_string('abvxyz68');
1112
            } elsif ($tag eq '150') {
1113
                return $field->as_string('abvxyz68');
1114
            } elsif ($tag eq '151') {
1115
                return $field->as_string('avxyz68');
1116
            } elsif ($tag eq '155') {
1117
                return $field->as_string('abvxyz68');
1118
            } elsif ($tag eq '180') {
1119
                return $field->as_string('vxyz68');
1120
            } elsif ($tag eq '181') {
1121
                return $field->as_string('vxyz68');
1122
            } elsif ($tag eq '182') {
1123
                return $field->as_string('vxyz68');
1124
            } elsif ($tag eq '185') {
1125
                return $field->as_string('vxyz68');
1126
            } else {
1127
                return $field->as_string();
1128
            }
1129
        }
1085
        }
1130
    }
1086
    }
1131
    return;
1087
    return;
1132
}
1088
}
1133
1089
1090
=head2 CompareFieldWithAuthority
1091
1092
  $match = &CompareFieldWithAuthority({ field => $field, authid => $authid })
1093
1094
Takes a MARC::Field from a bibliographic record and an authid, and returns true if they match.
1095
1096
=cut
1097
1098
sub CompareFieldWithAuthority {
1099
    my $args = shift;
1100
1101
    my $record = GetAuthority($args->{authid});
1102
    return unless (ref $record eq 'MARC::Record');
1103
    if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
1104
        # UNIMARC has same subfields for bibs and authorities
1105
        foreach my $field ($record->field('2..')) {
1106
            return compare_fields($field, $args->{field}, 'abcdefghijlmnopqrstuvwxyz');
1107
        }
1108
    } else {
1109
        use C4::Heading::MARC21;
1110
        my $handler = C4::Heading::MARC21->new();
1111
1112
        foreach my $field ($record->field('1..')) {
1113
            my $subfields = $handler->get_valid_bib_heading_subfields($field->tag());
1114
            return compare_fields($field, $args->{field}, $subfields) if ($subfields);
1115
        }
1116
    }
1117
    return 0;
1118
}
1119
1134
=head2 BuildAuthHierarchies
1120
=head2 BuildAuthHierarchies
1135
1121
1136
  $text= &BuildAuthHierarchies( $authid, $force)
1122
  $text= &BuildAuthHierarchies( $authid, $force)
Lines 1592-1597 sub get_auth_type_location { Link Here
1592
    }
1578
    }
1593
}
1579
}
1594
1580
1581
=head2 compare_fields
1582
1583
  my match = compare_fields($field1, $field2, 'abcde');
1584
1585
Compares the listed subfields of both fields and return true if they all match
1586
1587
=cut
1588
1589
sub compare_fields {
1590
    my ($field1, $field2, $subfields) = @_;
1591
1592
    foreach my $subfield (split(//, $subfields)) {
1593
        my $subfield1 = $field1->subfield($subfield) // '';
1594
        my $subfield2 = $field2->subfield($subfield) // '';
1595
        return 0 unless $subfield1 eq $subfield2;
1596
    }
1597
    return 1;
1598
}
1599
1600
1595
END { }       # module clean-up code here (global destructor)
1601
END { }       # module clean-up code here (global destructor)
1596
1602
1597
1;
1603
1;
Lines 1602-1607 __END__ Link Here
1602
Koha Development Team <http://koha-community.org/>
1608
Koha Development Team <http://koha-community.org/>
1603
1609
1604
Paul POULAIN paul.poulain@free.fr
1610
Paul POULAIN paul.poulain@free.fr
1611
Ere Maijala ere.maijala@helsinki.fi
1605
1612
1606
=cut
1613
=cut
1607
1614
(-)a/C4/Biblio.pm (-3 / +1 lines)
Lines 636-644 sub _check_valid_auth_link { Link Here
636
    my ( $authid, $field ) = @_;
636
    my ( $authid, $field ) = @_;
637
    require C4::AuthoritiesMarc;
637
    require C4::AuthoritiesMarc;
638
638
639
    my $authorized_heading =
639
    return C4::AuthoritiesMarc::CompareFieldWithAuthority( { 'field' => $field, 'authid' => $authid } );
640
      C4::AuthoritiesMarc::GetAuthorizedHeading( { 'authid' => $authid } ) || '';
641
   return ($field->as_string('abcdefghijklmnopqrstuvwxyz') eq $authorized_heading);
642
}
640
}
643
641
644
=head2 GetBiblioData
642
=head2 GetBiblioData
(-)a/C4/Heading.pm (+2 lines)
Lines 174-179 sub preferred_authorities { Link Here
174
174
175
    if (C4::Heading::valid_bib_heading_subfield('100', 'e', '')) ...
175
    if (C4::Heading::valid_bib_heading_subfield('100', 'e', '')) ...
176
176
177
Check if the given subfield is valid for the given field.
178
177
=cut
179
=cut
178
180
179
sub valid_bib_heading_subfield {
181
sub valid_bib_heading_subfield {
(-)a/C4/Heading/MARC21.pm (+120 lines)
Lines 68-73 my $bib_heading_fields = { Link Here
68
        subfields  => 'adfghklmnoprst',
68
        subfields  => 'adfghklmnoprst',
69
        main_entry => 1
69
        main_entry => 1
70
    },
70
    },
71
    '147' => {
72
        auth_type => 'NAME_EVENT',
73
        subfields => 'acdgvxyz68',
74
        main_entry => 1
75
    },
76
    '148' => {
77
        auth_type => 'CHRON_TERM',
78
        subfields => 'abvxyz68',
79
        main_entry => 1
80
    },
81
    '150' => {
82
        auth_type => 'TOPIC_TERM',
83
        subfields => 'abvxyz68',
84
        main_entry => 1
85
    },
86
    '151' => {
87
        auth_type => 'GEOGR_NAME',
88
        subfields => 'avxyz68',
89
        main_entry => 1
90
    },
91
    '155' => {
92
        auth_type => 'GENRE/FORM',
93
        subfields => 'abvxyz68',
94
        main_entry => 1
95
    },
96
    '162' => {
97
        auth_type => 'MED_PERFRM',
98
        subfields => 'a68',
99
        main_entry => 1
100
    },
101
    '180' => {
102
        auth_type => 'TOPIC_TERM',
103
        subfields => 'vxyz68'
104
    },
105
    '181' => {
106
        auth_type => 'GEOGR_NAME',
107
        subfields => 'vxyz68'
108
    },
109
    '182' => {
110
        auth_type => 'CHRON_TERM',
111
        subfields => 'vxyz68'
112
    },
113
    '185' => {
114
        auth_type => 'GENRE/FORM',
115
        subfields => 'vxyz68'
116
    },
71
    '440' => { auth_type => 'UNIF_TITLE', subfields => 'anp', series => 1 },
117
    '440' => { auth_type => 'UNIF_TITLE', subfields => 'anp', series => 1 },
72
    '600' => {
118
    '600' => {
73
        auth_type => 'PERSO_NAME',
119
        auth_type => 'PERSO_NAME',
Lines 119-124 my $bib_heading_fields = { Link Here
119
      { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', series => 1 },
165
      { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', series => 1 },
120
};
166
};
121
167
168
169
=head2 auth_heading_fields
170
171
=cut
172
173
my $auth_heading_fields = {
174
    '100' => {
175
        subfields => 'abcdefghjklmnopqrstvxyz68',
176
    },
177
    '110' => {
178
        subfields => 'abcdefghklmnoprstvxyz68',
179
    },
180
    '111' => {
181
        subfields => 'acdefghklnpqstvxyz68',
182
    },
183
    '130' => {
184
        subfields => 'adfghklmnoprstvxyz68',
185
    },
186
    '147' => {
187
        subfields => 'acdgvxyz68',
188
    },
189
    '148' => {
190
        subfields => 'abvxyz68',
191
    },
192
    '150' => {
193
        subfields => 'abvxyz68',
194
    },
195
    '151' => {
196
        subfields => 'avxyz68',
197
    },
198
    '155' => {
199
        subfields => 'abvxyz68',
200
    },
201
    '162' => {
202
        subfields => 'a68',
203
    },
204
    '180' => {
205
        subfields => 'vxyz68',
206
    },
207
    '181' => {
208
        subfields => 'vxyz68',
209
    },
210
    '182' => {
211
        subfields => 'vxyz68',
212
    },
213
    '185' => {
214
        subfields => 'vxyz68',
215
    },
216
};
217
122
=head2 subdivisions
218
=head2 subdivisions
123
219
124
=cut
220
=cut
Lines 176-181 sub valid_bib_heading_subfield { Link Here
176
    return 0;
272
    return 0;
177
}
273
}
178
274
275
=head2 get_valid_bib_heading_subfields
276
277
=cut
278
279
sub get_valid_bib_heading_subfields {
280
    my $self          = shift;
281
    my $tag           = shift;
282
283
    return $bib_heading_fields->{$tag}->{subfields} // undef;
284
}
285
286
=head2 get_auth_heading_subfields_to_report
287
288
=cut
289
290
sub get_auth_heading_subfields_to_report {
291
    my $self          = shift;
292
    my $tag           = shift;
293
294
    my $subfields = $auth_heading_fields->{$tag}->{subfields} // '';
295
    $subfields =~ s/[68]//;
296
    return $subfields;
297
}
298
179
=head2 parse_heading
299
=head2 parse_heading
180
300
181
=cut
301
=cut
(-)a/installer/data/mysql/en/marcflavour/marc21/mandatory/authorities_normal_marc21.sql (-2 / +3 lines)
Lines 28-38 INSERT INTO auth_types (authtypecode, authtypetext, auth_tag_to_report, summary) Link Here
28
		('CORPO_NAME', 'Corporate Name', '110', 'Corporate Names'),
28
		('CORPO_NAME', 'Corporate Name', '110', 'Corporate Names'),
29
		('MEETI_NAME', 'Meeting Name', '111', 'Meeting Name'),
29
		('MEETI_NAME', 'Meeting Name', '111', 'Meeting Name'),
30
		('UNIF_TITLE', 'Uniform Title', '130', 'Uniform Title'),
30
		('UNIF_TITLE', 'Uniform Title', '130', 'Uniform Title'),
31
		('NAME_EVENT', 'Named Event', '147', 'Named Event'),
31
		('CHRON_TERM', 'Chronological Term', '148', 'Chronological Term'),
32
		('CHRON_TERM', 'Chronological Term', '148', 'Chronological Term'),
32
		('TOPIC_TERM', 'Topical Term', '150', 'Topical Term'),
33
		('TOPIC_TERM', 'Topical Term', '150', 'Topical Term'),
33
		('GEOGR_NAME', 'Geographic Name', '151', 'Geographic Name'),
34
		('GEOGR_NAME', 'Geographic Name', '151', 'Geographic Name'),
34
		('GENRE/FORM', 'Genre/Form Term', '155', 'Genre/Form Term');
35
		('GENRE/FORM', 'Genre/Form Term', '155', 'Genre/Form Term'),
35
36
	    ('MED_PERFRM', 'Medium of Performance', '162', 'Medium of Performance');
36
37
37
-- ******************************************************
38
-- ******************************************************
38
-- KOHA UNSUPPORTED STANDARD MARC 21 AUTHORITY TYPES.
39
-- KOHA UNSUPPORTED STANDARD MARC 21 AUTHORITY TYPES.
(-)a/t/db_dependent/AuthoritiesMarc.t (-1 / +27 lines)
Lines 5-13 Link Here
5
5
6
use Modern::Perl;
6
use Modern::Perl;
7
7
8
use Test::More tests => 9;
8
use Test::More tests => 10;
9
use Test::MockModule;
9
use Test::MockModule;
10
use Test::Warn;
10
use Test::Warn;
11
use MARC::Field;
11
use MARC::Record;
12
use MARC::Record;
12
13
13
use t::lib::Mocks;
14
use t::lib::Mocks;
Lines 54-59 $module->mock('GetAuthority', sub { Link Here
54
            [ '151', ' ', ' ', a => 'New York (City)' ],
55
            [ '151', ' ', ' ', a => 'New York (City)' ],
55
            [ '551', ' ', ' ', a => 'New York (State)', w => 'g' ]
56
            [ '551', ' ', ' ', a => 'New York (State)', w => 'g' ]
56
            );
57
            );
58
    } elsif ($authid eq '5') {
59
        $record->add_fields(
60
            [ '001', '5' ],
61
            [ '100', ' ', ' ', a => 'Lastname, Firstname', b => 'b', c => 'c', i => 'i' ]
62
            );
57
    } else {
63
    } else {
58
        undef $record;
64
        undef $record;
59
    }
65
    }
Lines 214-217 subtest 'AddAuthority should respect AUTO_INCREMENT (BZ 18104)' => sub { Link Here
214
    is( $record->field('001')->data, $id3, 'Check updated 001' );
220
    is( $record->field('001')->data, $id3, 'Check updated 001' );
215
};
221
};
216
222
223
subtest 'CompareFieldWithAuthority tests' => sub {
224
    plan tests => 3;
225
226
    t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
227
228
    $builder->build({ source => 'AuthType', value => { authtypecode => 'PERSO_NAME' }});
229
230
    my $field = MARC::Field->new('100', 0, 0, a => 'Lastname, Firstname', b => 'b', c => 'c');
231
232
    ok(C4::AuthoritiesMarc::CompareFieldWithAuthority({'field' => $field, 'authid' => 5}), 'Authority matches');
233
234
    $field->add_subfields(i => 'X');
235
236
    ok(C4::AuthoritiesMarc::CompareFieldWithAuthority({'field' => $field, 'authid' => 5}), 'Compare ignores unlisted subfields');
237
238
    $field->add_subfields(d => 'd');
239
240
    ok(!C4::AuthoritiesMarc::CompareFieldWithAuthority({'field' => $field, 'authid' => 5}), 'Authority does not match');
241
};
242
217
$schema->storage->txn_rollback;
243
$schema->storage->txn_rollback;
(-)a/t/db_dependent/AuthoritiesMarc/MARC21.t (-1 / +91 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
#
3
4
use strict;
5
use warnings;
6
7
use Test::MockModule;
8
use Test::More tests => 2;
9
use MARC::Field;
10
use MARC::Record;
11
12
use t::lib::Mocks;
13
use t::lib::TestBuilder;
14
15
BEGIN {
16
    use_ok('C4::AuthoritiesMarc::MARC21');
17
}
18
19
my $schema  = Koha::Database->new->schema;
20
$schema->storage->txn_begin;
21
my $dbh = C4::Context->dbh;
22
my $builder = t::lib::TestBuilder->new;
23
24
t::lib::Mocks::mock_preference('marcflavour', 'MARC21');
25
26
subtest 'CompareFieldWithAuthority tests' => sub {
27
    plan tests => 3;
28
29
    # We are now going to be testing the authorities hierarchy code, and
30
    # therefore need to pretend that we have consistent data in our database
31
    my $module = new Test::MockModule('C4::AuthoritiesMarc');
32
    $module->mock('GetHeaderAuthority', sub {
33
        return {'authtrees' => ''};
34
    });
35
    $module->mock('AddAuthorityTrees', sub {
36
        return;
37
    });
38
    $module->mock('GetAuthority', sub {
39
        my ($authid) = @_;
40
        my $record = MARC::Record->new();
41
        if ($authid eq '1') {
42
            $record->add_fields(
43
                [ '001', '1' ],
44
                [ '151', ' ', ' ', a => 'United States' ]
45
            );
46
        } elsif ($authid eq '2') {
47
            $record->add_fields(
48
                [ '001', '2' ],
49
                [ '151', ' ', ' ', a => 'New York (State)' ],
50
                [ '551', ' ', ' ', a => 'United States', w => 'g', 9 => '1' ]
51
            );
52
        } elsif ($authid eq '3') {
53
            $record->add_fields(
54
                [ '001', '3' ],
55
                [ '151', ' ', ' ', a => 'New York (City)' ],
56
                [ '551', ' ', ' ', a => 'New York (State)', w => 'g', 9 => '2' ]
57
            );
58
        } elsif ($authid eq '4') {
59
            $record->add_fields(
60
                [ '001', '4' ],
61
                [ '151', ' ', ' ', a => 'New York (City)' ],
62
                [ '551', ' ', ' ', a => 'New York (State)', w => 'g' ]
63
            );
64
        } elsif ($authid eq '5') {
65
            $record->add_fields(
66
                [ '001', '5' ],
67
                [ '100', ' ', ' ', a => 'Lastname, Firstname', b => 'b', c => 'c', i => 'i' ]
68
            );
69
        } else {
70
            undef $record;
71
        }
72
        return $record;
73
    });
74
75
    $dbh->do('DELETE FROM auth_types');
76
    $builder->build({ source => 'AuthType', value => { authtypecode => 'PERSO_NAME' }});
77
78
    my $field = MARC::Field->new('100', 0, 0, a => 'Lastname, Firstname', b => 'b', c => 'c');
79
80
    ok(C4::AuthoritiesMarc::CompareFieldWithAuthority({'field' => $field, 'authid' => 5}), 'Authority matches');
81
82
    $field->add_subfields(i => 'X');
83
84
    ok(C4::AuthoritiesMarc::CompareFieldWithAuthority({'field' => $field, 'authid' => 5}), 'Compare ignores unlisted subfields');
85
86
    $field->add_subfields(d => 'd');
87
88
    ok(!C4::AuthoritiesMarc::CompareFieldWithAuthority({'field' => $field, 'authid' => 5}), 'Authority does not match');
89
};
90
91
$schema->storage->txn_rollback;

Return to bug 21958