@@ -, +, @@ - FindDuplicateOptions, - FindDuplicateMaxResults, --- C4/AuthoritiesMarc.pm | 113 +++++++++++++++++--- installer/data/mysql/sysprefs.sql | 2 + installer/data/mysql/updatedatabase.pl | 14 +++ .../en/modules/admin/preferences/authorities.pref | 16 +++ 4 files changed, 128 insertions(+), 17 deletions(-) --- a/C4/AuthoritiesMarc.pm +++ a/C4/AuthoritiesMarc.pm @@ -896,31 +896,110 @@ Comments : an improvement would be to return All the records that match. =cut +sub _find_duplicate_authority_try { + my ($try, $authorityfield, $authtypecode) = @_; + + my $filtervalues = + qr([\001-\040\!\'\"\`\#\$\%\&\*\+,\-\./:;<=>\?\@\(\)\{\[\]\}_\|\~]); + + # build a request for SearchAuthorities + my $query = "at=$authtypecode"; + + foreach my $s ($authorityfield->subfields()) { + next unless ($s->[0] =~ /[A-z]/); + $s->[1] =~ s/$filtervalues/ /g; + $query .= qq{ and $try->{index}="$s->[1]"}; + } + + my $duplicaterecord; + if ($try->{field} and $try->{subfields}) { + my $maxresults = C4::Context->preference('FindDuplicateMaxResults') || 10; + my ($error, $results, $total_hits) = + C4::Search::SimpleSearch($query, 0, $maxresults, ["authorityserver"]); + return unless (!defined $error and @{$results}); + + foreach my $result (@$results) { + my $marcrecord = MARC::File::USMARC::decode($result); + my @marcfields = $marcrecord->field($try->{field}); + next if (scalar @marcfields == 0); + my $stillmatch = 1; + foreach my $marcfield (@marcfields) { + foreach my $subfield (@{ $try->{subfields} }) { + my $authoritysubfield = $authorityfield->subfield($subfield); + my $marcsubfield = $marcfield->subfield($subfield); + if ( (defined $authoritysubfield xor defined $marcsubfield) + or (defined $authoritysubfield + and $authoritysubfield ne $marcsubfield) + ) { + $stillmatch = 0; + last; + } + } + last unless $stillmatch; + } + if ($stillmatch) { + $duplicaterecord = $marcrecord; + last; + } + } + } else { + my ($error, $results, $total_hits) = + C4::Search::SimpleSearch( $query, 0, 1, ["authorityserver"] ); + if (!defined $error and @{$results}) { + $duplicaterecord = MARC::File::USMARC::decode($results->[0]); + } + } + + return $duplicaterecord; +} + sub FindDuplicateAuthority { + my ($record, $authtypecode) = @_; + + return unless $record; + + my $opts = C4::Context->preference('FindDuplicateOptions'); + return unless $opts; - my ($record,$authtypecode)=@_; -# warn "IN for ".$record->as_formatted; my $dbh = C4::Context->dbh; -# warn "".$record->as_formatted; - my $sth = $dbh->prepare("select auth_tag_to_report from auth_types where authtypecode=?"); + my $sth = $dbh->prepare(" + SELECT auth_tag_to_report FROM auth_types WHERE authtypecode = ? + "); $sth->execute($authtypecode); my ($auth_tag_to_report) = $sth->fetchrow; $sth->finish; -# warn "record :".$record->as_formatted." auth_tag_to_report :$auth_tag_to_report"; - # build a request for SearchAuthorities - my $query='at='.$authtypecode.' '; - my $filtervalues=qr([\001-\040\!\'\"\`\#\$\%\&\*\+,\-\./:;<=>\?\@\(\)\{\[\]\}_\|\~]); - if ($record->field($auth_tag_to_report)) { - foreach ($record->field($auth_tag_to_report)->subfields()) { - $_->[1]=~s/$filtervalues/ /g; $query.= " and he,wrdl=\"".$_->[1]."\"" if ($_->[0]=~/[A-z]/); - } + + my $authorityfield = $record->field($auth_tag_to_report); + return unless $authorityfield; + + my @tries; + $opts =~ s/ //g; + foreach my $try (split /\|/, $opts) { + my ($index, $matchcheck) = split m#/#, $try; + my ($field, @subfields); + if ($matchcheck and length($matchcheck) > 3) { + $field = substr $matchcheck, 0, 3; + @subfields = split(//, substr($matchcheck, 3)); + } + push @tries, { + index => $index, + field => $field, + subfields => \@subfields, + }; } - my ($error, $results, $total_hits) = C4::Search::SimpleSearch( $query, 0, 1, [ "authorityserver" ] ); - # there is at least 1 result => return the 1st one - if (!defined $error && @{$results} ) { - my $marcrecord = MARC::File::USMARC::decode($results->[0]); - return $marcrecord->field('001')->data,BuildSummary($marcrecord,$marcrecord->field('001')->data,$authtypecode); + + my $duplicaterecord; + foreach my $try (@tries) { + $duplicaterecord = _find_duplicate_authority_try($try, $authorityfield, + $authtypecode); + last if $duplicaterecord; } + + if ($duplicaterecord) { + my $authid = $duplicaterecord->field('001')->data; + return $authid, BuildSummary($duplicaterecord, $authid, $authtypecode); + } + # no result, returns nothing return; } --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -386,3 +386,5 @@ INSERT INTO systempreferences (variable,value,explanation,type) VALUES('OPACdidy INSERT INTO systempreferences (variable,value,explanation,type) VALUES('INTRAdidyoumean',NULL,'Did you mean? configuration for the Intranet. Do not change, as this is controlled by /cgi-bin/koha/admin/didyoumean.pl.','Free'); INSERT INTO systempreferences (variable, value, options, explanation, type) VALUES ('BlockReturnOfWithdrawnItems', '1', '0', 'If enabled, items that are marked as withdrawn cannot be returned.', 'YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HoldsToPullStartDate','2','Set the default start date for the Holds to pull list to this many days ago',NULL,'Integer'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('FindDuplicateOptions','he,wrdl','Options to determine how to search for duplicate authorities. General form: "index1/XXXcc|index2" where indexX is the index where we want to search, and XXXcc the field(s) and subfield(s) we want to check for each search results (if omitted, the first result is returned as duplicate)',NULL,'Free'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('FindDuplicateMaxResults','10','Maximum number of results fetched when searching a duplicate',NULL,'Free'); --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -6020,6 +6020,20 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { SetVersion ($DBversion); } +$DBversion = "XXX"; +if (C4::Context->preference("Version") < TransformToNum($DBversion)) { + $dbh->do(qq{ + INSERT INTO systempreferences (variable, value, explanation, options, type) + VALUES ('FindDuplicateOptions', 'he,wrdl', 'Options to determine how to search for duplicate authorities. General form: "index1/XXXcc#index2" where indexX is the index where we want to search, and XXXcc the field(s) and subfield(s) we want to check for each search results (if omitted, the first result is returned as duplicate)', NULL, 'Free'); + }); + $dbh->do(qq{ + INSERT INTO systempreferences (variable, value, explanation, options, type) + VALUES ('FindDuplicateMaxResults', '10', 'Maximum number of results fetched when searching a duplicate', NULL, 'Integer'); + }); + print "Upgrade to $DBversion done (Added system preference FindDuplicateOptions)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref @@ -43,6 +43,22 @@ Authorities: yes: Use no: "Don't use" - authority record numbers instead of text strings for searches from subject tracings. + - + - pref: FindDuplicateOptions + class: long + - '
Options to determine how to search for duplicate authorities when creating new authorities. General form: "index1/XXXcc | index2" where indexX is the index where we want to search, and XXXcc the field(s) and subfield(s) we want to check for each search results (if omitted, the first result is returned as duplicate)' + - '
Examples:' + - '
- he,wrdl: Search in "he" index, do not check subfields data in search results, the first result is returned as a duplicate (default).' + - '
- he,wrdl/2..ab: Search in "he" index, and compare 2XX$a and 2XX$b of search results with XXX$a and XXX$b of created authority (XXX is the "Authority field to copy"). The first matching authority is returned as duplicate.' + - '
- he,wrdl | See,wrdl/4..ab: Search in "he" index and do not check subfields. If there is no results, search in "See" index and compare 4XX$a and 4XX$b of search results with XXX$a and XXX$b of created authority.' + - '
Notes:' + - '
- only authorities of the same type are returned by the search' + - '
- if compared subfields are repeatable, only the first of each field is checked' + - + - 'Maximum number of results fetched when searching a duplicate:' + - pref: FindDuplicateMaxResults + class: integer + - "It's only used when FindDuplicateOptions contains fields and subfields to check against (default: 10)" Linker: - - Use the --