From 84358420bfa8e8b8902ad3bb70bbca0f262c715c Mon Sep 17 00:00:00 2001 From: Bouzid Fergani Date: Wed, 6 Nov 2013 10:49:09 -0500 Subject: [PATCH] Bug 11299: Add a button to the biblio edition page to automatically add authority links in the current biblio record via AJAX. Also adds a button to easily create missing authority records. add authority type in the form to create the missing authority. when authority was found, the 600$9 field have the authid. Testing scenario (Creating an authority record for a failed automatic link) : 1 - In your system preferences set: AutoCreateAuthorities: don't generate BiblioAddsAuthorities: don't allow 2 - Go to the Cataloging -> New record (koha/cataloguing/addbiblio.pl) Ensure you are using the basic editor 3 - Click the "Link authorities automatically" button. A message should appear, telling the user "No authority link was changed." 4 - Add random informations in field 600$a of the biblio record. 5 - Click the "Link authorities automatically" button. the message box should now show "600 - No matching authority found.". the 9 subfield is red Above the 9 subfield is a red X with a blue plus next to it Hover on the plus, see it is titled 'Create authority' 6 - Click the 'Create authority' link 7 - A new authroity form pops up, the info from the cataloging editor is prefilled Click the 100 field heading to expand and confirm info is transferred 8 - Fill in necessary fields and save the new authority 9 - The cataloging screen now has the 9 subfield populated and is green 10 - Click "Link authorities automatically" again Dialog says "No authority link was changed" 11 - In another tab go to System preferences and set AutoCreateAuthorities to 'Allow' 12 - Add random information to the 650 field 13 - Click 'Link authorities' button 14 - Dialog says:650 - No matching authority found. A new authority was created automatically. 15 - The subfield 9 is green and has the id of the new authority record 16 - In another tab search authorities and find an existing subject heading 17 - Add a new 650 with the info from the existing record 18 - Click 'Link authorities' 19 - The new field is correctly linked to existing authority Signed-off-by: Katrin Fischer https://bugs.koha-community.org/show_bug.cgi?id=12299 Signed-off-by: Michal Denar Signed-off-by: Nick Clemens --- C4/Biblio.pm | 25 ++- authorities/authorities.pl | 5 +- cataloguing/z3950_auth_search.pl | 3 + koha-tmpl/intranet-tmpl/prog/css/addbiblio.css | 16 ++ .../prog/en/modules/authorities/authorities.tt | 7 +- .../authorities/blinddetail-biblio-search.tt | 21 +- .../prog/en/modules/cataloguing/addbiblio.tt | 241 ++++++++++++++++++++- .../en/modules/cataloguing/z3950_auth_search.tt | 3 +- koha-tmpl/intranet-tmpl/prog/js/cataloging.js | 6 + koha-tmpl/intranet-tmpl/prog/js/z3950_search.js | 7 +- svc/cataloguing/automatic_linker.pl | 61 ++++++ t/Biblio.t | 2 +- t/db_dependent/Biblio.t | 27 ++- 13 files changed, 404 insertions(+), 20 deletions(-) create mode 100755 svc/cataloguing/automatic_linker.pl diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 97fa95aeb1..b69cba9918 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -435,6 +435,7 @@ Returns the number of headings changed sub BiblioAutoLink { my $record = shift; my $frameworkcode = shift; + my $verbose = shift; if (!$record) { carp('Undefined record passed to BiblioAutoLink'); return 0; @@ -452,15 +453,15 @@ sub BiblioAutoLink { my $linker = $linker_module->new( { 'options' => C4::Context->preference("LinkerOptions") } ); - my ( $headings_changed, undef ) = - LinkBibHeadingsToAuthorities( $linker, $record, $frameworkcode, C4::Context->preference("CatalogModuleRelink") || '' ); + my ( $headings_changed, $results ) = + LinkBibHeadingsToAuthorities( $linker, $record, $frameworkcode, C4::Context->preference("CatalogModuleRelink") || '', $verbose ); # By default we probably don't want to relink things when cataloging - return $headings_changed; + return $headings_changed, $results; } =head2 LinkBibHeadingsToAuthorities - my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc, $frameworkcode, [$allowrelink]); + my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc, $frameworkcode, [$allowrelink, $verbose]); Links bib headings to authority records by checking each authority-controlled field in the C @@ -482,6 +483,7 @@ sub LinkBibHeadingsToAuthorities { my $bib = shift; my $frameworkcode = shift; my $allowrelink = shift; + my $verbose = shift; my %results; if (!$bib) { carp 'LinkBibHeadingsToAuthorities called on undefined bib record'; @@ -489,7 +491,6 @@ sub LinkBibHeadingsToAuthorities { } require C4::Heading; require C4::AuthoritiesMarc; - $allowrelink = 1 unless defined $allowrelink; my $num_headings_changed = 0; foreach my $field ( $bib->fields() ) { @@ -502,6 +503,7 @@ sub LinkBibHeadingsToAuthorities { if ( defined $current_link && (!$allowrelink || !C4::Context->preference('LinkerRelink')) ) { $results{'linked'}->{ $heading->display_form() }++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose; next; } @@ -509,17 +511,23 @@ sub LinkBibHeadingsToAuthorities { if ($authid) { $results{ $fuzzy ? 'fuzzy' : 'linked' } ->{ $heading->display_form() }++; - next if defined $current_link and $current_link == $authid; + if(defined $current_link and $current_link == $authid) { + push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose; + next; + } $field->delete_subfield( code => '9' ) if defined $current_link; $field->add_subfields( '9', $authid ); $num_headings_changed++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => $authid, status => 'LOCAL_FOUND'}) if $verbose; } else { + my $authority_type = Koha::Authority::Types->find( $heading->auth_type() ); if ( defined $current_link && (!$allowrelink || C4::Context->preference('LinkerKeepStale')) ) { $results{'fuzzy'}->{ $heading->display_form() }++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => $current_link, status => 'UNCHANGED'}) if $verbose; } elsif ( C4::Context->preference('AutoCreateAuthorities') ) { if ( _check_valid_auth_link( $current_link, $field ) ) { @@ -595,24 +603,29 @@ sub LinkBibHeadingsToAuthorities { $num_headings_changed++; $linker->update_cache($heading, $authid); $results{'added'}->{ $heading->display_form() }++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => $authid, status => 'CREATED'}) if $verbose; } } elsif ( defined $current_link ) { if ( _check_valid_auth_link( $current_link, $field ) ) { $results{'linked'}->{ $heading->display_form() }++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => $authid, status => 'UNCHANGED'}) if $verbose; } else { $field->delete_subfield( code => '9' ); $num_headings_changed++; $results{'unlinked'}->{ $heading->display_form() }++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => undef, status => 'NONE_FOUND', auth_type => $heading->auth_type(), tag_to_report => $authority_type->auth_tag_to_report}) if $verbose; } } else { $results{'unlinked'}->{ $heading->display_form() }++; + push(@{$results{'details'}}, { tag => $field->tag(), authid => undef, status => 'NONE_FOUND', auth_type => $heading->auth_type(), tag_to_report => $authority_type->auth_tag_to_report}) if $verbose; } } } + push(@{$results{'details'}}, { tag => '', authid => undef, status => 'UNCHANGED'}) unless %results; return $num_headings_changed, \%results; } diff --git a/authorities/authorities.pl b/authorities/authorities.pl index 6a856c19dd..42b37596b1 100755 --- a/authorities/authorities.pl +++ b/authorities/authorities.pl @@ -289,6 +289,9 @@ sub create_input { } } + if ($cgi->param('tagreport') && $subfield_data{tag} == $cgi->param('tagreport')) { + $subfield_data{marc_value}{value} = $cgi->param('tag'. $cgi->param('tagbiblio') . 'subfield' . $subfield_data{subfield}); + } $subfield_data{'index_subfield'} = $index_subfield; return \%subfield_data; } @@ -576,7 +579,7 @@ my ($template, $loggedinuser, $cookie) flagsrequired => {editauthorities => 1}, debug => 1, }); -$template->param(nonav => $nonav,index=>$myindex,authtypecode=>$authtypecode,breedingid=>$breedingid,); +$template->param(nonav => $nonav,index=>$myindex,authtypecode=>$authtypecode,breedingid=>$breedingid); $tagslib = GetTagsLabels(1,$authtypecode); $mandatory_z3950 = GetMandatoryFieldZ3950($authtypecode); diff --git a/cataloguing/z3950_auth_search.pl b/cataloguing/z3950_auth_search.pl index 1e25468785..ec8266d037 100755 --- a/cataloguing/z3950_auth_search.pl +++ b/cataloguing/z3950_auth_search.pl @@ -42,6 +42,7 @@ my $subjectsubdiv = $input->param('subjectsubdiv'); my $srchany = $input->param('srchany'); my $op = $input->param('op')||''; my $page = $input->param('current_page') || 1; +my $index =$input->param('index'); $page = $input->param('goto_page') if $input->param('changepage_goto'); my $controlnumber = $input->param('controlnumber'); @@ -65,6 +66,7 @@ $template->param( srchany => $srchany, authid => $authid, controlnumber => $controlnumber, + index => $index, ); if ( $op ne "do_search" ) { @@ -74,6 +76,7 @@ if ( $op ne "do_search" ) { $template->param( serverloop => $serverloop, opsearch => "search", + index => $index, ); output_html_with_http_headers $input, $cookie, $template->output; exit; diff --git a/koha-tmpl/intranet-tmpl/prog/css/addbiblio.css b/koha-tmpl/intranet-tmpl/prog/css/addbiblio.css index baf3f2138d..b7facc0d2d 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/addbiblio.css +++ b/koha-tmpl/intranet-tmpl/prog/css/addbiblio.css @@ -322,6 +322,22 @@ tbody tr.active td { display: inline-block; } +.matching_authority{ + color: #99FF99; +} + +.no_matching_authority{ + color: #FFAAAA; +} + +.matching_authority_field{ + background-color: #99FF99 !important; + } + + .no_matching_authority_field{ + background-color: #FFAAAA !important; + } + @media (min-width: 768px) { li.subfield_line label { width: 20em; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt index 601726a25f..ed34c91b91 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/authorities.tt @@ -32,8 +32,9 @@ }); $("#z3950submit").click(function(){ var strQuery = GetZ3950Terms(); + var index = "&index=[% index | html %]"; if(strQuery){ - window.open("/cgi-bin/koha/cataloguing/z3950_auth_search.pl?authid=[% authid | html %]"+strQuery,"z3950search",'width=740,height=450,location=yes,toolbar=no,scrollbars=yes,resize=yes'); + window.open("/cgi-bin/koha/cataloguing/z3950_auth_search.pl?authid=[% authid | html %]"+strQuery+index,"z3950search",'width=740,height=450,location=yes,toolbar=no,scrollbars=yes,resize=yes'); } return false; }); @@ -211,9 +212,9 @@ function confirmnotdup(redirect){ - + - +
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/blinddetail-biblio-search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/blinddetail-biblio-search.tt index 083eda7c18..ef3cd93917 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/blinddetail-biblio-search.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/authorities/blinddetail-biblio-search.tt @@ -44,11 +44,12 @@ var whichfield; try { whichfield = opener.opener.document.getElementById(index_start); + autolinker_dialog = opener.opener.document.getElementById("autolinker_dialog"); } catch(e) { - return; + whichfield = opener.document.getElementById(index_start); + autolinker_dialog = opener.document.getElementById("autolinker_dialog"); } var field_start = whichfield.parentNode.parentNode.parentNode; - // Sets the good number of form fields for the specified subfield // Returns false if the cloning failed function SetSubfieldNumber(subfield_name, nb) { @@ -138,6 +139,8 @@ [% ELSE %] if(code.value=='9'){ subfield.value = "[% To.json(authid) | $raw %]"; + subfield.className = subfield.className.replace("no_matching_authority_field", "matching_authority_field"); + break; } [% END %] @@ -145,6 +148,20 @@ } [% END %] + //Delete create authority button and status + var linkinfos = field_start.getElementsByTagName('i'); + for (index = linkinfos.length - 1; index >= 0; index--) { + linkinfos[index].parentNode.removeChild(linkinfos[index]); + } + //Change message autolinker_dialog + var subfield_dialog = $(autolinker_dialog).children('ul').children('li'); + for (index = subfield_dialog.length - 1; index >= 0; index--){ + var tag_field = field_start.id.split("_")[1]; + if (subfield_dialog[index].innerHTML.indexOf(tag_field) !== -1 ){ + subfield_dialog[index].innerHTML = subfield_dialog[index].innerHTML.replace(_("No matching authority found."), _("No matching authority found. A new authority was created or imported")); + break; + } + } opener.close(); window.close(); return false; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt index 70dbd7e5a9..7e175eb450 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt @@ -91,6 +91,10 @@ PopupZ3950(); }); + $("#linkerbutton").click(function(){ + AutomaticLinker(); + }); + $("#saverecord").click(function(){ $(".btn-group").removeClass("open"); onOption(); @@ -177,8 +181,240 @@ var onOption = function () { return Check(); } - [% END %] +[% END %] + +function confirmnotdup(redirect){ + $("#confirm_not_duplicate").attr("value","1"); + $("#redirect").attr("value",redirect); + Check(); +} + +function Dopop(link,i) { + defaultvalue = document.getElementById(i).value; + window.open(link+"&result="+defaultvalue,"valuebuilder",'width=700,height=550,toolbar=false,scrollbars=yes'); +} + +/** + * this function open a popup to search on z3950 server. + */ +function PopupZ3950() { + var strQuery = GetZ3950Terms(); + if(strQuery){ + window.open("/cgi-bin/koha/cataloguing/z3950_search.pl?biblionumber=[% biblionumber | html %]"+strQuery,"z3950search",'width=740,height=450,location=yes,toolbar=no,scrollbars=yes,resize=yes'); + } +} + +/** +* this function append button for create new authority if not found +*/ + +function addCreateAuthorityButton(tag_subfield_line, heading, tag_index) { + var title = _("Create authority"); + var elem = $(''); + tag_subfield_line.append(elem); + var tag_subfield_line_a = $('.subfield_line[id^=subfield' + heading.tag + 'a]').eq(tag_index); + var subfield_a = tag_subfield_line_a.children('.input_marceditor').eq(0); + var index = subfield_a.attr('id'); + elem.click(function() { + var popup = window.open("", "new_auth_popup",'fullscreen,toolbar=false,scrollbars=yes'); + if(popup !== null) { + // Create a new form that will be POSTed in the new window + var form = $('
').attr({ + method: 'post', + action: "../authorities/authorities.pl", + target: "new_auth_popup" + }); + //add the authtypecode + form.append($('').attr({ + type: 'hidden', + name: 'authtypecode', + value: heading.auth_type + })); + form.append($('').attr({ + type: 'hidden', + name: 'tagreport', + value: heading.tag_to_report + })); + form.append($('').attr({ + type: 'hidden', + name: 'tagbiblio', + value: heading.tag + })); + form.append($('').attr({ + type: 'hidden', + name: 'index', + value: index + })); + $('.tag[id^=tag_' + heading.tag + '_]').eq(tag_index).find(':input').each(function(){ + form.append($('').attr({ + type: 'hidden', + name: this.name.split('_',4).join(''), + value: $(this).val() + })); + }); + + $('body').append(form); + form.submit(); + form.remove(); + } + return false; + }); + +} + +/** + * Updates the authid for every heading field + * Adds visual feedback for the changes made on the form. + */ +function updateHeadingLinks(links) { + var current_tag = ''; + var tag_index = 0; + + // Delete the old message dialog and create a new one + $('#autolinker_dialog').remove(); + var message_dialog = $('
' + _("Automatic authority link results:") + '
    '); + var message_dialog_ul = message_dialog.find('ul'); + + $.each(links, function(index, heading) { + if(current_tag == heading.tag) { + tag_index++; + } + else { + current_tag = heading.tag; + tag_index = 0; + } + + // Find the $9 field to update + var tag_subfield_line = $('.subfield_line[id^=subfield' + heading.tag + '9]').eq(tag_index); + var subfield = tag_subfield_line.children('.input_marceditor').eq(0); + + // Delete the old status if one exists + tag_subfield_line.children('.subfield_status').remove(); + + // If the field wasn't modified. Skip it. + if(heading.status == 'UNCHANGED') { + return; + } + + + // Make the subfield line visible and update its value + tag_subfield_line.show(); + subfield.val(heading.authid); + + // Add the new status + var image = ' '; + var message = ''; + var field_class = 'no_matching_authority_field'; + switch(heading.status) { + case 'LOCAL_FOUND': + image = ' '; + message = _("A matching authority was found in the local database."); + field_class = 'matching_authority_field'; + break; + case 'CREATED': + image = ' '; + message = _("No matching authority found. A new authority was created automatically."); + field_class = 'matching_authority_field'; + break; + case 'MULTIPLE_MATCH': + message = _("More than one local match found. Possibly a duplicate authority!"); + break; + case 'NONE_FOUND': + message = _("No matching authority found."); + break; + default: + message = heading.status; + break; + } + subfield[0].classList.add(field_class); + tag_subfield_line.find('i').each(function() { + this.remove(); + }); + tag_subfield_line.append(image); + + // Add the message to the dialog + message_dialog_ul.append('
  • ' + heading.tag + ' - ' + message + '
  • '); + + // Add a link to create a new authority if none was found + if(heading.status == 'NONE_FOUND' && tag_subfield_line.find('i').length == 1) { + addCreateAuthorityButton(tag_subfield_line, heading , tag_index); + } + }); + + if(message_dialog.find('li').length == 0) { + message_dialog_ul.append("
  • " + _("No authority link was changed.") + "
  • "); + } + $('#addbibliotabs').before(message_dialog); +} + +/** + * Use an ajax request to automatically find authority links for the current record + */ +function AutomaticLinker() { + // Show the Loading overlay + $("#loading").show(); + + // Remove fields that are completely empty + $('#f').find('.tag').each(function() { + var empty = true; + $(this).find('.input_marceditor').each(function() { + if($(this).val() != '') { + empty = false; + return false; + } + }); + if(empty) { + UnCloneField($(this).attr('id')); + } + }); + + // Get all the form values to post via AJAX + var form_data = {}; + $('#f').find(':input').each(function(){ + form_data[this.name] = $(this).val(); + }); + delete form_data['']; + + // Send the data to automatic_linker.pl + $.ajax({ + url:'/cgi-bin/koha/svc/cataloguing/automatic_linker.pl', + type:'post', + data: form_data, + dataType: 'json', + error: function(xhr) { + alert("Error : \n" + xhr.responseText); + }, + success: function(json) { + switch(json.status) { + case 'UNAUTHORIZED': + alert(_("Error : You do not have the permissions necessary to use this functionality.")); + break; + case 'OK': + updateHeadingLinks(json.links); + break; + } + }, + complete: function() { + $("#loading").hide(); + } + }); +} + + +function PopupMARCFieldDoc(field) { + [% IF Koha.Preference('marcfielddocurl') %] + var docurl = "[% Koha.Preference('marcfielddocurl').replace('"','"') | html %]"; + docurl = docurl.replace("{MARC}", "[% marcflavour | html %]"); + docurl = docurl.replace("{FIELD}", ""+field); + docurl = docurl.replace("{LANG}", "[% lang | html %]"); + window.open(docurl); + [% ELSIF ( marcflavour == 'MARC21' ) %] + _MARC21FieldDoc(field); + [% ELSIF ( marcflavour == 'UNIMARC' ) %] + _UNIMARCFieldDoc(field); + [% END %] +} function confirmnotdup(redirect){ $("#confirm_not_duplicate").attr("value","1"); $("#redirect").attr("value",redirect); @@ -588,6 +824,9 @@ [% ELSE %] [% END %] + [% IF ( CAN_user_editauthorities ) %] + + [% END %] [% END %]
    diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_auth_search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_auth_search.tt index 7335ac67ea..439a9f6be3 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_auth_search.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/z3950_auth_search.tt @@ -20,6 +20,7 @@ +
    @@ -94,7 +95,7 @@
    diff --git a/koha-tmpl/intranet-tmpl/prog/js/cataloging.js b/koha-tmpl/intranet-tmpl/prog/js/cataloging.js index 417a78ec6d..614f064cff 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/cataloging.js +++ b/koha-tmpl/intranet-tmpl/prog/js/cataloging.js @@ -187,6 +187,9 @@ function CloneField(index, hideMarc, advancedMARCEditor) { for( j = 0 ; j < inputs.length ; j++ ) { if(inputs[j].getAttribute("id") && inputs[j].getAttribute("id").match(/^tag_/) ){ inputs[j].value = ""; + + //Remove the color added by the automatic linker + $(inputs[j]).css({backgroundColor:""}); } } var textareas = divs[i].getElementsByTagName('textarea'); @@ -196,6 +199,9 @@ function CloneField(index, hideMarc, advancedMARCEditor) { } } + // Remove the status icons added by the automatic linker + $(divs[i]).find('.subfield_status').remove(); + inputs[0].setAttribute('id',inputs[0].getAttribute('id')+new_key); inputs[0].setAttribute('name',inputs[0].getAttribute('name')+new_key); diff --git a/koha-tmpl/intranet-tmpl/prog/js/z3950_search.js b/koha-tmpl/intranet-tmpl/prog/js/z3950_search.js index 368aacb22d..44b00197c8 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/z3950_search.js +++ b/koha-tmpl/intranet-tmpl/prog/js/z3950_search.js @@ -1,10 +1,10 @@ //z3950_search.js for Authorities, Bib records and Acquisitions module -function Import(Breeding, recordid, AuthType, FrameworkCode) { +function Import(Breeding, recordid, AuthType, FrameworkCode, index) { if ( AuthType == false ) { opener.document.location="../cataloguing/addbiblio.pl?biblionumber="+recordid+"&z3950=1&frameworkcode="+FrameworkCode+"&breedingid="+Breeding; } else { - opener.document.location="../authorities/authorities.pl?breedingid="+Breeding+"&authtypecode="+AuthType+"&authid="+recordid; + opener.document.location="../authorities/authorities.pl?breedingid="+Breeding+"&authtypecode="+AuthType+"&authid="+recordid+"&index="+index; } window.close(); return false; @@ -127,10 +127,11 @@ $( document ).ready( function() { var data_authid = $( this ).data( "authid" ); var data_biblionumber = $( this ).data( "biblionumber" ); var data_frameworkcode = $( this ).data( "frameworkcode" ); + var data_index = $( this ).data( "index" ); if ( data_headingcode == undefined ) { Import( data_breedingid, data_biblionumber, false , data_frameworkcode ); } else { - Import( data_breedingid, data_authid, data_headingcode ); + Import( data_breedingid, data_authid, data_headingcode, "", data_index ); } return false; }); diff --git a/svc/cataloguing/automatic_linker.pl b/svc/cataloguing/automatic_linker.pl new file mode 100755 index 0000000000..711debf92d --- /dev/null +++ b/svc/cataloguing/automatic_linker.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl + +# Bouzid Fergani, 2020 - inLibro +# +# 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 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; +use CGI; +use CGI::Cookie; +use JSON; +use C4::Auth; +use C4::Biblio; +use C4::Context; + +my $input = new CGI; +print $input->header('application/json'); + +# Check the user's permissions +my %cookies = CGI::Cookie->fetch; +my $sessid = $cookies{'CGISESSID'}->value || $input->param('CGISESSID'); +my ( $auth_status, $auth_sessid ) = + C4::Auth::check_cookie_auth( $sessid, { editauthorities => 1, editcatalogue => 1 } ); +if ( $auth_status ne "ok" ) { + print to_json( { status => 'UNAUTHORIZED' } ); + exit 0; +} + +# Link the biblio headings to authorities and return a json containing the status of all the links. +# Example : {"status":"OK","links":[{"authid":"123","status":"LINK_CHANGED","tag":"650"}]} +# +# tag = the tag number of the field +# authid = the value of the $9 subfield for this tag +# status = The status of the link (LOCAL_FOUND, NONE_FOUND, MULTIPLE_MATCH, UNCHANGED, CREATED) + +my $json; + +my $record = TransformHtmlToMarc($input,1); + +my ( $headings_changed, $results ) = BiblioAutoLink ( + $record, + $input->param('frameworkcode'), + 1 +); + +$json->{status} = 'OK'; +$json->{links} = $results->{details} || ''; + +print to_json($json); diff --git a/t/Biblio.t b/t/Biblio.t index 5596b4bf19..a847edaa97 100755 --- a/t/Biblio.t +++ b/t/Biblio.t @@ -157,4 +157,4 @@ warnings_like { $ret = UpdateTotalIssues() } "UpdateTotalIssues returns carped warnings if biblio record does not exist"; ok( !defined $ret, 'UpdateTotalIssues returns carped warning if biblio record does not exist'); - +1; diff --git a/t/db_dependent/Biblio.t b/t/db_dependent/Biblio.t index 4d3db2491e..f0c12c9770 100755 --- a/t/db_dependent/Biblio.t +++ b/t/db_dependent/Biblio.t @@ -705,7 +705,7 @@ subtest 'ModBiblio called from linker test' => sub { }; subtest "LinkBibHeadingsToAuthorities record generation tests" => sub { - plan tests => 6; + plan tests => 12; # Set up mocks to ensure authorities are generated my $biblio_mod = Test::MockModule->new( 'C4::Linker::Default' ); @@ -739,6 +739,20 @@ subtest "LinkBibHeadingsToAuthorities record generation tests" => sub { "The generated record contains the correct subfields" ); + #Add test for this case using verbose + my ( $num_headings_changed, $results ) = LinkBibHeadingsToAuthorities($linker, $record, "",undef, 1); + my $details = $results->{details}; + is( $num_headings_changed, 1, 'We changed the one we passed' ); + is( $results->{details}->[0]->{status}, 'CREATED', "We added an authority record for the heading using verbose"); + + # Now we check the authority record itself + my $authority = GetAuthority($results->{details}->[0]->{authid}); + + is( $authority->field('150')->as_string(), + "Beach city Weirdness Fiction Books 21st Century Fish Stew Pizza", + "The generated record contains the correct subfields when using verbose" + ); + # Example series link with volume and punctuation $record = MARC::Record->new(); $field = MARC::Field->new('800','','','a' => 'Tolkien, J. R. R.', 'q' => '(John Ronald Reuel),', 'd' => '1892-1973.', 't' => 'Lord of the rings ;', 'v' => '1'); @@ -759,8 +773,17 @@ subtest "LinkBibHeadingsToAuthorities record generation tests" => sub { "The generated record contains the correct subfields" ); + # The same exemple With verbose + ( $num_headings_changed, $results ) = LinkBibHeadingsToAuthorities($linker, $record, "",undef, 1); + is( $num_headings_changed, 1, 'We changed the one we passed' ); + is( $results->{details}->[0]->{status}, 'CREATED', "We added an authority record for the heading using verbose"); - + # Now we check the authority record itself + my $authority = GetAuthority($results->{details}->[0]->{authid}); + is( $authority->field('100')->as_string(), + "Tolkien, J. R. R. (John Ronald Reuel), 1892-1973. Lord of the rings", + "The generated record contains the correct subfields" + ); }; # Cleanup -- 2.11.0