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

(-)a/C4/Biblio.pm (-3 / +15 lines)
Lines 477-483 sub BiblioAutoLink { Link Here
477
477
478
=head2 LinkBibHeadingsToAuthorities
478
=head2 LinkBibHeadingsToAuthorities
479
479
480
  my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc, $frameworkcode, [$allowrelink, $verbose]);
480
  my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc, $frameworkcode, [$allowrelink, $verbose, $dont_auto_create]);
481
481
482
Links bib headings to authority records by checking
482
Links bib headings to authority records by checking
483
each authority-controlled field in the C<MARC::Record>
483
each authority-controlled field in the C<MARC::Record>
Lines 500-506 sub LinkBibHeadingsToAuthorities { Link Here
500
    my $frameworkcode = shift;
500
    my $frameworkcode = shift;
501
    my $allowrelink = shift;
501
    my $allowrelink = shift;
502
    my $verbose = shift;
502
    my $verbose = shift;
503
    my $dont_auto_create = shift;
503
    my %results;
504
    my %results;
505
    my $linker_default='C4::Linker::Default';
504
    if (!$bib) {
506
    if (!$bib) {
505
        carp 'LinkBibHeadingsToAuthorities called on undefined bib record';
507
        carp 'LinkBibHeadingsToAuthorities called on undefined bib record';
506
        return ( 0, {});
508
        return ( 0, {});
Lines 522-529 sub LinkBibHeadingsToAuthorities { Link Here
522
            push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose;
524
            push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose;
523
            next;
525
            next;
524
        }
526
        }
525
526
        my ( $authid, $fuzzy, $status ) = $linker->get_link($heading);
527
        my ( $authid, $fuzzy, $status ) = $linker->get_link($heading);
528
        if(defined $status){
529
            if ($status eq 'NO_CONNECTION' or $status eq 'SERVER_NOT_FOUND') {
530
                return 0, { error => $status };
531
            }
532
            elsif($status eq 'Z3950_SEARCH_EMPTY'){
533
                ( $authid, $fuzzy, $status ) = $linker_default->get_link($heading);
534
            }
535
        }
527
        if ($authid) {
536
        if ($authid) {
528
            $results{ $fuzzy ? 'fuzzy' : 'linked' }
537
            $results{ $fuzzy ? 'fuzzy' : 'linked' }
529
              ->{ $heading->display_form() }++;
538
              ->{ $heading->display_form() }++;
Lines 545-553 sub LinkBibHeadingsToAuthorities { Link Here
545
                $results{'fuzzy'}->{ $heading->display_form() }++;
554
                $results{'fuzzy'}->{ $heading->display_form() }++;
546
                push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose;
555
                push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose;
547
            }
556
            }
548
            elsif ( C4::Context->preference('AutoCreateAuthorities') ) {
557
            elsif ( !$dont_auto_create && C4::Context->preference('AutoCreateAuthorities') ) {
549
                if ( _check_valid_auth_link( $current_link, $field ) ) {
558
                if ( _check_valid_auth_link( $current_link, $field ) ) {
550
                    $results{'linked'}->{ $heading->display_form() }++;
559
                    $results{'linked'}->{ $heading->display_form() }++;
560
                    push(@{$results{'details'}}, { tag => $field->tag(), authid => $authid, status => 'UNCHANGED'}) if $verbose;
551
                }
561
                }
552
                else {
562
                else {
553
                    my $marcrecordauth = MARC::Record->new();
563
                    my $marcrecordauth = MARC::Record->new();
Lines 671-676 sub AddAuthorityFromHeading { Link Here
671
    my $heading = shift;
681
    my $heading = shift;
672
    my $field = shift;
682
    my $field = shift;
673
    my $bib = shift;
683
    my $bib = shift;
684
    my $current_link = $field->subfield('9');
674
685
675
    if(!defined $heading || !defined $field || !defined $bib){
686
    if(!defined $heading || !defined $field || !defined $bib){
676
       return 0;
687
       return 0;
Lines 682-687 sub AddAuthorityFromHeading { Link Here
682
        $marcrecordauth->leader('     nz  a22     o  4500');
693
        $marcrecordauth->leader('     nz  a22     o  4500');
683
        SetMarcUnicodeFlag( $marcrecordauth, 'MARC21' );
694
        SetMarcUnicodeFlag( $marcrecordauth, 'MARC21' );
684
    }
695
    }
696
    $field->delete_subfield( code => '9' ) if defined $current_link;
685
    my $authfield =
697
    my $authfield =
686
      MARC::Field->new( $authtypedata->auth_tag_to_report,
698
      MARC::Field->new( $authtypedata->auth_tag_to_report,
687
        '', '', "a" => "" . $field->subfield('a') );
699
        '', '', "a" => "" . $field->subfield('a') );
(-)a/C4/Linker/Z3950Server.pm (+384 lines)
Line 0 Link Here
1
package C4::Linker::Z3950Server;
2
3
# Copyright 2012 Frédérick Capovilla - Libéo
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use strict;
19
use warnings;
20
use Carp;
21
use MARC::Field;
22
use MARC::Record;
23
use C4::Context;
24
use C4::Heading;
25
use ZOOM; # For Z39.50 Searches
26
use C4::AuthoritiesMarc; # For Authority addition
27
use C4::Log; # logaction
28
29
use base qw(C4::Linker);
30
31
32
sub get_link {
33
    my $self        = shift;
34
    my $heading     = shift;
35
    my $behavior    = shift || 'default';
36
    my $search_form = $heading->search_form();
37
    my $authid;
38
    my $fuzzy = 0;
39
    my $status = '';
40
41
if ( $self->{'cache'}->{$search_form}->{'cached'} ) {
42
    $authid = $self->{'cache'}->{$search_form}->{'authid'};
43
        $fuzzy  = $self->{'cache'}->{$search_form}->{'fuzzy'};
44
    }
45
    else {
46
        # Look for matching authorities on the Z39.50 server
47
        unless($self->{'local_first'}) {
48
            ($authid, undef, $status) = $self->getZ3950Authority($heading);
49
            if($status eq 'Z3950_SEARCH_ERROR' or
50
               $status eq 'Z3950_QUERY_ERROR' or
51
               $status eq 'NO_CONNECTION' or
52
               $status eq 'SERVER_NOT_FOUND') {
53
                return $authid, $fuzzy, $status;
54
            }
55
        }
56
        if(!$authid) {
57
            # look for matching authorities
58
            my $authorities = $heading->authorities(1);    # $skipmetadata = true
59
60
            if ( $behavior eq 'default' && $#{$authorities} == 0 ) {
61
                $authid = $authorities->[0]->{'authid'};
62
            } elsif ( $behavior eq 'default' && $#{$authorities} >= 0 ) {
63
                #authority informations
64
                my $authType = GetAuthType($heading->{'auth_type'});
65
                my $authFieldTag = $authType->{'auth_tag_to_report'};
66
                my ($authId,$authRecord,$auth,$authField,$authSubfieldValue);
67
                my $acceptAuthority = 0;
68
                my @authSubfieldFilled;
69
70
                #record informations
71
                my $recordSubfields = $heading->{'subfields'};
72
                my @recordSubfields = split(//,$recordSubfields);
73
                my @recordSubfieldsFilled = @{$heading->{'field'}->{'_subfields'}};
74
                my %subfieldsFilledHash = @recordSubfieldsFilled;
75
                my @subfieldsFilledKey = keys %subfieldsFilledHash;
76
                @subfieldsFilledKey = sort @subfieldsFilledKey;
77
                foreach (@$authorities){
78
                    $authId = $_->{'authid'};
79
                    $auth = Koha::Authority->get_from_authid($authId);
80
                    $authRecord = $auth->record;
81
                    $authField = $authRecord->field($authFieldTag);
82
83
                    #the record's set of subfields not empty must be the same as the authority
84
                    #get authority filled subfields tag
85
                    @authSubfieldFilled = ();          #clear array
86
                    foreach (@recordSubfields){
87
                        if ($authField){
88
                            if ($authRecord->field($authFieldTag)->subfield($_)){
89
                                push (@authSubfieldFilled, $_);
90
                            }
91
                        }
92
                    }
93
                    @authSubfieldFilled = sort @authSubfieldFilled;
94
95
                    #if subfields are the same, check theirs values
96
                    if (@authSubfieldFilled == @subfieldsFilledKey) {
97
                        while ( my ($key, $value) = each(%subfieldsFilledHash) ) {
98
                             if ($authField){
99
                                $authSubfieldValue = $authRecord->field($authFieldTag)->subfield($key);
100
101
                                if ($authSubfieldValue && $authSubfieldValue eq $value){
102
                                   $acceptAuthority = 1;
103
                                } else {
104
                                   $acceptAuthority = 0;
105
                                   last;
106
                                }
107
                            }
108
                        }
109
                        if ($acceptAuthority){
110
                            $authid = $authorities->[0]->{'authid'};
111
                        }
112
                    }
113
                }
114
            }
115
            elsif ( $behavior eq 'first' && $#{$authorities} >= 0 ) {
116
                $authid = $authorities->[0]->{'authid'};
117
                $fuzzy  = $#{$authorities} > 0;
118
            }
119
            elsif ( $behavior eq 'last' && $#{$authorities} >= 0 ) {
120
                $authid = $authorities->[ $#{$authorities} ]->{'authid'};
121
                $fuzzy  = $#{$authorities} > 0;
122
            }
123
124
            if ( !defined $authid && $self->{'broader_headings'} ) {
125
                my $field     = $heading->field();
126
                my @subfields = $field->subfields();
127
                if ( scalar @subfields > 1 ) {
128
                    pop @subfields;
129
                    $field->replace_with(
130
                        MARC::Field->new(
131
                            $field->tag,
132
                            $field->indicator(1),
133
                            $field->indicator(2),
134
                            map { $_[0] => $_[1] } @subfields
135
                        )
136
                    );
137
                    ( $authid, $fuzzy ) =
138
                      $self->get_link( C4::Heading->new_from_bib_field($field),
139
                        $behavior );
140
                }
141
            }
142
        }
143
        if($self->{'local_first'} && !$authid) {
144
            ($authid, undef, $status) = $self->getZ3950Authority($heading);
145
        }
146
147
        $self->{'cache'}->{$search_form}->{'cached'} = 1;
148
        $self->{'cache'}->{$search_form}->{'authid'} = $authid;
149
        $self->{'cache'}->{$search_form}->{'fuzzy'}  = $fuzzy;
150
    }
151
    return $self->SUPER::_handle_auth_limit($authid), $fuzzy, $status;
152
}
153
154
sub update_cache {
155
    my $self        = shift;
156
    my $heading     = shift;
157
    my $authid      = shift;
158
    my $search_form = $heading->search_form();
159
    my $fuzzy = 0;
160
161
    $self->{'cache'}->{$search_form}->{'cached'} = 1;
162
    $self->{'cache'}->{$search_form}->{'authid'} = $authid;
163
    $self->{'cache'}->{$search_form}->{'fuzzy'}  = $fuzzy;
164
}
165
sub flip_heading {
166
    my $self    = shift;
167
    my $heading = shift;
168
169
    # TODO: implement
170
}
171
172
173
=head1 getZ3950Authority
174
175
  ($authid, $record, $status) = $self->getZ3950Authority($heading);
176
177
  Do a Z39.50 search for the heading using the $conn ZOOM::Connection object and the $heading Heading.
178
  The column origincode is used to check for duplicates.
179
  FIXME: Use thesaurus in search? As of Koha 3.8, the community stopped using them.
180
181
  RETURNS :
182
  $authid = the ID of the local copy of the authority record that was found. undef if nothing was found.
183
  $record = the MARC record of the found authority.
184
  $status = A string with additional informations on the search status (Z3950_CREATED, Z3950_UPDATED, Z3950_QUERY_ERROR, Z3950_SEARCH_ERROR)
185
186
=cut
187
188
sub getZ3950Authority {
189
    my $self = shift;
190
    my $heading = shift;
191
192
    # Try to find a match on the Z39.50 server if LinkerZ3950Server is set
193
    if(C4::Context->preference('LinkerZ3950Server')) {
194
        unless($self->{'conn'}) {
195
            my $sth = C4::Context->dbh->prepare("select * from z3950servers where servername=?");
196
            $sth->execute(C4::Context->preference('LinkerZ3950Server'));
197
            my $server = $sth->fetchrow_hashref or undef;
198
            $sth->finish;
199
200
            if($server) {
201
                my $options = new ZOOM::Options();
202
                $options->option('cclfile' => C4::Context->ModZebrations('authorityserver')->{"ccl2rpn"});
203
                $options->option('elementSetName', 'F');
204
                $options->option('async', 0);
205
                $options->option('databaseName', $server->{db});
206
                $options->option('user',         $server->{userid}  ) if $server->{userid};
207
                $options->option('password',     $server->{password}) if $server->{password};
208
                $options->option('preferredRecordSyntax', $server->{syntax});
209
                $self->{'conn'} = create ZOOM::Connection($options);
210
                eval{ $self->{'conn'}->connect( $server->{host}, $server->{port} ) };
211
                if($@) {
212
                    return (undef, undef, 'NO_CONNECTION');
213
                }}
214
            else {
215
                return (undef, undef, 'SERVER_NOT_FOUND');
216
            }
217
        }
218
    }
219
    else {
220
        return;
221
    }
222
    my $query;
223
    if ($heading->{'auth_type'} eq 'PERSO_NAME' ){
224
            $query =qq(Personal-name,do-not-truncate,ext="$heading->{'search_form'}");
225
    }elsif ($heading->{'auth_type'}  eq 'UNIF_TITLE' ) {
226
            $query =qq(Title-uniform,do-not-truncate,ext="$heading->{'search_form'}");
227
    }elsif ($heading->{'auth_type'} eq 'MEETI_NAME' ){
228
            $query =qq(Meeting-name-heading,do-not-truncate,ext="$heading->{'search_form'}");
229
    }elsif ($heading->{'auth_type'} eq 'GEOGR_NAME' ){
230
            $query =qq(Name-geographic,do-not-truncate,ext="$heading->{'search_form'}");
231
    }elsif ($heading->{'auth_type'} eq 'GENRE/FORM' ){
232
            $query =qq(Term-genre-form,do-not-truncate,ext="$heading->{'search_form'}");
233
    }elsif ($heading->{'auth_type'} eq 'CORPO_NAME' ) {
234
            $query =qq(Corporate-name,do-not-truncate,ext="$heading->{'search_form'}");
235
    }elsif ( $heading->{'auth_type'} eq 'CHRON_TERM' ) {
236
            $query =qq(Chronological-term,do-not-truncate,ext="$heading->{'search_form'}");
237
    }elsif ($heading->{'auth_type'} eq 'TOPIC_TERM' ){
238
            $query =qq(Subject-topical,do-not-truncate,ext="$heading->{'search_form'}");
239
    }
240
241
    my $zquery = eval{ new ZOOM::Query::CCL2RPN($query, $self->{'conn'}) };
242
    if($@) {
243
        warn $query . "\n" . $@;
244
        return (undef, undef, 'Z3950_QUERY_ERROR');
245
    }
246
247
    # Try to send the search query to the server.
248
    my $rs = eval{ $self->{'conn'}->search($zquery) };
249
    if($@){
250
        warn $query . "\n" . $@;
251
        return (undef, undef, 'Z3950_SEARCH_EMPTY');
252
    }
253
254
    # If authorities are found, select the first valid one for addition in the local authority table.
255
    my $record;
256
    if($rs->size() != 0) {
257
        $record = MARC::Record::new_from_usmarc($rs->record(0)->raw());
258
    }else{
259
        return (undef, undef, 'Z3950_SEARCH_ERROR');
260
    }
261
    $rs->destroy();
262
    $zquery->destroy();
263
264
    # If a valid authority was found, add it in the local authority database.
265
    if($record) {
266
        my $dbh=C4::Context->dbh;
267
268
        my $authtypecode = C4::AuthoritiesMarc::GuessAuthTypeCode($record);
269
        my $authId;
270
271
        # Use the control number to prevent the creation of duplicate authorities.
272
        my $controlNumber = $record->field('970')->subfield('0');
273
        my $sthExist=$dbh->prepare("SELECT authid FROM auth_header WHERE origincode =?");
274
        $sthExist->execute($controlNumber) or die $sthExist->errstr;
275
        ($authId) = $sthExist->fetchrow;
276
        $sthExist->finish;
277
278
        #------------------------------------------------------------------------------------------
279
        # Corrections and verifications before insertion
280
        my $format;
281
        my $leader='     nz  a22     o  4500';# Leader for incomplete MARC21 record
282
283
        if (uc(C4::Context->preference('marcflavour')) eq 'UNIMARC') {
284
            $format= 'UNIMARCAUTH';
285
        }
286
        else {
287
            $format= 'MARC21';
288
        }
289
290
        if ($format eq "MARC21") {
291
            if (!$record->leader) {
292
                $record->leader($leader);
293
            }
294
            if (!$record->field('003')) {
295
                $record->insert_fields_ordered(
296
                        MARC::Field->new('003',C4::Context->preference('MARCOrgCode'))
297
                        );
298
            }
299
            my $time=POSIX::strftime("%Y%m%d%H%M%S",localtime);
300
            if (!$record->field('005')) {
301
                $record->insert_fields_ordered(
302
                        MARC::Field->new('005',$time.".0")
303
                        );
304
            }
305
            my $date=POSIX::strftime("%y%m%d",localtime);
306
            if (!$record->field('008')) {
307
                # Get a valid default value for field 008
308
                my $default_008 = C4::Context->preference('MARCAuthorityControlField008');
309
                if(!$default_008 or length($default_008)<34) {
310
                    $default_008 = '|| aca||aabn           | a|a     d';
311
            }
312
            else {
313
                    $default_008 = substr($default_008,0,34);
314
                }
315
                $record->insert_fields_ordered( MARC::Field->new('008',$date.$default_008) );
316
            }
317
            if (!$record->field('040')) {
318
                $record->insert_fields_ordered(
319
                    MARC::Field->new('040','','',
320
                        'a' => C4::Context->preference('MARCOrgCode'),
321
                        'c' => C4::Context->preference('MARCOrgCode')
322
                    )
323
                );
324
            }
325
        }
326
        if ($format eq "UNIMARCAUTH") {
327
            $record->leader("     nx  j22             ") unless ($record->leader());
328
            my $date=POSIX::strftime("%Y%m%d",localtime);
329
            if (my $string=$record->subfield('100',"a")){
330
                $string=~s/fre50/frey50/;
331
                $record->field('100')->update('a'=>$string);
332
            }
333
            elsif ($record->field('100')){
334
                $record->field('100')->update('a'=>$date."afrey50      ba0");
335
            } else {
336
                $record->append_fields(
337
                    MARC::Field->new('100',' ',' '
338
                        ,'a'=>$date."afrey50      ba0")
339
                );
340
            }
341
        }
342
        my ($auth_type_tag, $auth_type_subfield) = C4::AuthoritiesMarc::get_auth_type_location($authtypecode);
343
        if (!$authId and $format eq "MARC21") {
344
        # only need to do this fix when modifying an existing authority
345
            C4::AuthoritiesMarc::MARC21::fix_marc21_auth_type_location($record, $auth_type_tag, $auth_type_subfield);
346
        }
347
        if (my $field=$record->field($auth_type_tag)){
348
            $field->update($auth_type_subfield=>$authtypecode);
349
        }
350
        else {
351
            $record->add_fields($auth_type_tag,'','', $auth_type_subfield=>$authtypecode);
352
        }
353
        #------------------------------------------------------------------------------------------
354
        if ($authId) {
355
            my $oldRecord=C4::AuthoritiesMarc::GetAuthority($authId);
356
357
            my $sth=$dbh->prepare("UPDATE auth_header SET authtypecode=?,marc=?,marcxml=? WHERE origincode =?");
358
            eval { $sth->execute($authtypecode,$record->as_usmarc,$record->as_xml_record($format),$controlNumber) or die $sth->errstr; };
359
            $sth->finish;
360
            warn "Problem with authority $controlNumber : Cannot update" if $@;
361
            $dbh->commit unless $dbh->{AutoCommit};
362
            return if $@;
363
364
            C4::Biblio::ModZebra($authId,'linkerUpdate',"authorityserver",$oldRecord,$record);
365
            return ($authId, $record, 'Z3950_UPDATED');
366
        }
367
        else {
368
            my $sth=$dbh->prepare("INSERT INTO auth_header (datecreated,authtypecode,marc,marcxml,origincode) VALUES (NOW(),?,?,?,?)");
369
            eval { $sth->execute($authtypecode,$record->as_usmarc,$record->as_xml_record($format),$controlNumber) or die $sth->errstr; };
370
            $sth->finish;
371
            warn "Problem with authority $controlNumber : Cannot insert" if $@;
372
            my $id = $dbh->{'mysql_insertid'};
373
            $dbh->commit unless $dbh->{AutoCommit};
374
            return if $@;
375
376
            logaction( "AUTHORITIES", "ADD", $id, "authority" ) if C4::Context->preference("AuthoritiesLog");
377
            C4::Biblio::ModZebra($id,'linkerUpdate',"authorityserver",undef,$record);
378
            return ($id, $record, 'Z3950_CREATED');
379
        }
380
    }
381
    return ;
382
}
383
384
1;
(-)a/cataloguing/automatic_linker.pl (-12 / +17 lines)
Lines 33-57 my %cookies = CGI::Cookie->fetch; Link Here
33
my $sessid = $cookies{'CGISESSID'}->value || $input->param('CGISESSID');
33
my $sessid = $cookies{'CGISESSID'}->value || $input->param('CGISESSID');
34
my ( $auth_status, $auth_sessid ) =
34
my ( $auth_status, $auth_sessid ) =
35
  C4::Auth::check_cookie_auth( $sessid, { editauthorities => 1 } );
35
  C4::Auth::check_cookie_auth( $sessid, { editauthorities => 1 } );
36
if ( $auth_status ne "ok" ) {
36
#if ( $auth_status ne "ok" ) {
37
    print to_json( { status => 'UNAUTHORIZED' } );
37
#    print to_json( { status => 'UNAUTHORIZED' } );
38
    exit 0;
38
#    exit 0;
39
}
39
#}
40
40
41
# Link the biblio headings to authorities and return a json containing the status of all the links.
41
# Link the biblio headings to authorities and return a json containing the status of all the links.
42
# Example : {"status":"OK","links":[{"authid":"123","status":"LINK_CHANGED","tag":"650"}]}
42
# Example : {"status":"OK","links":[{"authid":"123","status":"LINK_CHANGED","tag":"650"}]}
43
#
43
#
44
# tag = the tag number of the field
44
# tag = the tag number of the field
45
# authid = the value of the $9 subfield for this tag
45
# authid = the value of the $9 subfield for this tag
46
# status = The status of the link (LOCAL_FOUND, NONE_FOUND, MULTIPLE_MATCH, UNCHANGED, CREATED)
46
# status = The status of the link (LOCAL_FOUND, NONE_FOUND, MULTIPLE_MATCH, UNCHANGED, CREATED,3950_CREATED, Z3950_UPDATED)
47
47
48
my $json;
48
my $json;
49
49
50
my $record = TransformHtmlToMarc($input,1);
50
my $record = TransformHtmlToMarc($input,1);
51
51
52
my $linker_module =
52
my $linker_module = "C4::Linker::" . ( C4::Context->preference("LinkerModule") || 'Default' );
53
  "C4::Linker::" . ( C4::Context->preference("LinkerModule") || 'Default' );
53
my $linker_default='C4::Linker::Default';
54
eval { eval "require $linker_module"; };
54
  eval { eval "require $linker_module"; };
55
if ($@) {
55
if ($@) {
56
    $linker_module = 'C4::Linker::Default';
56
    $linker_module = 'C4::Linker::Default';
57
    eval "require $linker_module";
57
    eval "require $linker_module";
Lines 65-74 my $linker = $linker_module->new( Link Here
65
my ( $headings_changed, $results ) = LinkBibHeadingsToAuthorities(
65
my ( $headings_changed, $results ) = LinkBibHeadingsToAuthorities(
66
    $linker, $record,
66
    $linker, $record,
67
    $input->param('frameworkcode'),
67
    $input->param('frameworkcode'),
68
    C4::Context->preference("CatalogModuleRelink") || '', 1
68
    C4::Context->preference("CatalogModuleRelink") || '', 1, 1
69
);
69
);
70
70
if(defined $results->{error}) {
71
$json->{status} = 'OK';
71
    $json->{links} = $results->{details} || '';
72
$json->{links} = $results->{details} || '';
72
    $json->{links} = $results->{details} || '';
73
}
74
else{
75
    $json->{status} = 'OK';
76
    $json->{links} = $results->{details} || '';
77
}
73
78
74
print to_json($json);
79
print to_json($json);
(-)a/installer/data/mysql/atomicupdate/Bug11300_LinkerZ3950Server_syspef.sql (+2 lines)
Line 0 Link Here
1
INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES
2
('LinkerZ3950Server','',NULL,'Import authorities from this Z39.50 server when searching for authority links with the Z39.50 Server linker module','free');
(-)a/installer/data/mysql/sysprefs.sql (+2 lines)
Lines 7-12 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
7
('AcqViewBaskets','user','user|branch|all','Define which baskets a user is allowed to view: his own only, any within his branch or all','Choice'),
7
('AcqViewBaskets','user','user|branch|all','Define which baskets a user is allowed to view: his own only, any within his branch or all','Choice'),
8
('AcqWarnOnDuplicateInvoice','0','','Warn librarians when they try to create a duplicate invoice','YesNo'),
8
('AcqWarnOnDuplicateInvoice','0','','Warn librarians when they try to create a duplicate invoice','YesNo'),
9
('AddressFormat','us','us|de|fr','Choose format to display postal addresses', 'Choice'),
9
('AddressFormat','us','us|de|fr','Choose format to display postal addresses', 'Choice'),
10
('AddPatronLists','categorycode','categorycode|category_type','Allow user to choose what list to pick up from when adding patrons','Choice'),
10
('advancedMARCeditor','0','','If ON, the MARC editor won\'t display field/subfield descriptions','YesNo'),
11
('advancedMARCeditor','0','','If ON, the MARC editor won\'t display field/subfield descriptions','YesNo'),
11
('AdvancedSearchLanguages','','','ISO 639-2 codes of languages you wish to see appear as an Advanced search option.  Example: eng|fre|ita','Textarea'),
12
('AdvancedSearchLanguages','','','ISO 639-2 codes of languages you wish to see appear as an Advanced search option.  Example: eng|fre|ita','Textarea'),
12
('AdvancedSearchTypes','itemtypes','itemtypes|ccode','Select which set of fields comprise the Type limit in the advanced search','Choice'),
13
('AdvancedSearchTypes','itemtypes','itemtypes|ccode','Select which set of fields comprise the Type limit in the advanced search','Choice'),
Lines 245-250 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
245
('LinkerModule','Default','Default|FirstMatch|LastMatch','Chooses which linker module to use (see documentation).','Choice'),
246
('LinkerModule','Default','Default|FirstMatch|LastMatch','Chooses which linker module to use (see documentation).','Choice'),
246
('LinkerOptions','','','A pipe-separated list of options for the linker.','free'),
247
('LinkerOptions','','','A pipe-separated list of options for the linker.','free'),
247
('LinkerRelink','1',NULL,'If ON the authority linker will relink headings that have previously been linked every time it runs.','YesNo'),
248
('LinkerRelink','1',NULL,'If ON the authority linker will relink headings that have previously been linked every time it runs.','YesNo'),
249
('LinkerZ3950Server','',NULL,'Import authorities from this Z39.50 server when searching for authority links with the Z39.50 Server linker module',''),
248
('LoadSearchHistoryToTheFirstLoggedUser', '1', NULL, 'If ON, the next user will automatically get the last searches in his history', 'YesNo'),
250
('LoadSearchHistoryToTheFirstLoggedUser', '1', NULL, 'If ON, the next user will automatically get the last searches in his history', 'YesNo'),
249
('LocalCoverImages','0','1','Display local cover images on intranet details pages.','YesNo'),
251
('LocalCoverImages','0','1','Display local cover images on intranet details pages.','YesNo'),
250
('LocalHoldsPriority',  '0', NULL,  'Enables the LocalHoldsPriority feature',  'YesNo'),
252
('LocalHoldsPriority',  '0', NULL,  'Enables the LocalHoldsPriority feature',  'YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref (+5 lines)
Lines 65-70 Authorities: Link Here
65
                  Default: Default
65
                  Default: Default
66
                  FirstMatch: "First Match"
66
                  FirstMatch: "First Match"
67
                  LastMatch: "Last Match"
67
                  LastMatch: "Last Match"
68
                  Z3950Server: "Z39.50 Server"
68
            - linker module for matching headings to authority records.
69
            - linker module for matching headings to authority records.
69
        -
70
        -
70
            - Set the following options for the authority linker
71
            - Set the following options for the authority linker
Lines 92-94 Authorities: Link Here
92
                  yes: Do
93
                  yes: Do
93
                  no: "Do not"
94
                  no: "Do not"
94
            - automatically relink headings that have previously been linked when saving records in the cataloging module.
95
            - automatically relink headings that have previously been linked when saving records in the cataloging module.
96
        -
97
            - pref: LinkerZ3950Server
98
            - class: multi
99
            - Import authorities from this Z39.50 server when searching for authority links with the Z39.50 Server linker module :
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt (-3 / +19 lines)
Lines 271-276 function updateHeadingLinks(links) { Link Here
271
        var message = '';
271
        var message = '';
272
        var field_color = '#FFAAAA';
272
        var field_color = '#FFAAAA';
273
        switch(heading.status) {
273
        switch(heading.status) {
274
            case 'Z3950_CREATED':
275
                image = 'approve.gif';
276
                message = _("A matching authority record was found on the Z39.50 server and was imported locally.");
277
                field_color = '#99FF99';
278
                break;
279
            case 'Z3950_UPDATED':
280
                image = 'approve.gif';
281
                message = _("A matching authority record was found on the Z39.50 server and a local authority was updated.");
282
                field_color = '#99FF99';
283
                break;
274
            case 'LOCAL_FOUND':
284
            case 'LOCAL_FOUND':
275
                image = 'approve.gif';
285
                image = 'approve.gif';
276
                message = _("A matching authority was found in the local database.");
286
                message = _("A matching authority was found in the local database.");
Lines 321-327 function AutomaticLinker() { Link Here
321
    $('#f').find('.tag').each(function() {
331
    $('#f').find('.tag').each(function() {
322
        var empty = true;
332
        var empty = true;
323
        $(this).find('.input_marceditor').each(function() {
333
        $(this).find('.input_marceditor').each(function() {
324
            if($(this).val() != '') {
334
            if(this.value != '') {
325
                empty = false;
335
                empty = false;
326
                return false;
336
                return false;
327
            }
337
            }
Lines 333-340 function AutomaticLinker() { Link Here
333
343
334
    // Get all the form values to post via AJAX
344
    // Get all the form values to post via AJAX
335
    var form_data = {};
345
    var form_data = {};
346
    var i=0;
336
    $('#f').find(':input').each(function(){
347
    $('#f').find(':input').each(function(){
337
        form_data[this.name] = $(this).val();
348
       form_data[this.name] = this.value;
338
    });
349
    });
339
    delete form_data[''];
350
    delete form_data[''];
340
351
Lines 352-357 function AutomaticLinker() { Link Here
352
                case 'UNAUTHORIZED':
363
                case 'UNAUTHORIZED':
353
                    alert(_("Error : You do not have the permissions necessary to use this functionality."));
364
                    alert(_("Error : You do not have the permissions necessary to use this functionality."));
354
                    break;
365
                    break;
366
                case 'SERVER_NOT_FOUND':
367
                    alert(_("Error : The Z39.50 server configured in the 'LinkerZ3950Server' preference was not found in the Z39.50 servers list."));
368
                    break;
369
                case 'NO_CONNECTION':
370
                    alert(_("Error : Could not connect to the Z39.50 server."));
371
                    break;
355
                case 'OK':
372
                case 'OK':
356
                    updateHeadingLinks(json.links);
373
                    updateHeadingLinks(json.links);
357
                    break;
374
                    break;
358
- 

Return to bug 11300