| File: | C4/AuthoritiesMarc.pm |
| Coverage: | 4.7% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package C4::AuthoritiesMarc; | |||||
| 2 | # Copyright 2000-2002 Katipo Communications | |||||
| 3 | # | |||||
| 4 | # This file is part of Koha. | |||||
| 5 | # | |||||
| 6 | # Koha is free software; you can redistribute it and/or modify it under the | |||||
| 7 | # terms of the GNU General Public License as published by the Free Software | |||||
| 8 | # Foundation; either version 2 of the License, or (at your option) any later | |||||
| 9 | # version. | |||||
| 10 | # | |||||
| 11 | # Koha is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| 14 | # | |||||
| 15 | # You should have received a copy of the GNU General Public License along | |||||
| 16 | # with Koha; if not, write to the Free Software Foundation, Inc., | |||||
| 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||||
| 18 | ||||||
| 19 | 3 3 3 | 639 30 119 | use strict; | |||
| 20 | 3 3 3 | 37 25 185 | use warnings; | |||
| 21 | 3 3 3 | 246 15 59 | use C4::Context; | |||
| 22 | 3 3 3 | 38297 35562 350 | use MARC::Record; | |||
| 23 | 3 3 3 | 178 12 1340 | use C4::Biblio; | |||
| 24 | 3 3 3 | 266 9 462 | use C4::Search; | |||
| 25 | 3 3 3 | 949 23 95 | use C4::AuthoritiesMarc::MARC21; | |||
| 26 | 3 3 3 | 485 33 115 | use C4::AuthoritiesMarc::UNIMARC; | |||
| 27 | 3 3 3 | 33 11 301 | use C4::Charset; | |||
| 28 | 3 3 3 | 22 10 314 | use C4::Log; | |||
| 29 | ||||||
| 30 | 3 3 3 | 20 9 354 | use vars qw($VERSION @ISA @EXPORT); | |||
| 31 | ||||||
| 32 | BEGIN { | |||||
| 33 | # set the version for version checking | |||||
| 34 | 3 | 13 | $VERSION = 3.01; | |||
| 35 | ||||||
| 36 | 3 | 18 | require Exporter; | |||
| 37 | 3 | 38 | @ISA = qw(Exporter); | |||
| 38 | 3 | 27658 | @EXPORT = qw( | |||
| 39 | &GetTagsLabels | |||||
| 40 | &GetAuthType | |||||
| 41 | &GetAuthTypeCode | |||||
| 42 | &GetAuthMARCFromKohaField | |||||
| 43 | ||||||
| 44 | &AddAuthority | |||||
| 45 | &ModAuthority | |||||
| 46 | &DelAuthority | |||||
| 47 | &GetAuthority | |||||
| 48 | &GetAuthorityXML | |||||
| 49 | ||||||
| 50 | &CountUsage | |||||
| 51 | &CountUsageChildren | |||||
| 52 | &SearchAuthorities | |||||
| 53 | ||||||
| 54 | &BuildSummary | |||||
| 55 | &BuildUnimarcHierarchies | |||||
| 56 | &BuildUnimarcHierarchy | |||||
| 57 | ||||||
| 58 | &merge | |||||
| 59 | &FindDuplicateAuthority | |||||
| 60 | ||||||
| 61 | &GuessAuthTypeCode | |||||
| 62 | &GuessAuthId | |||||
| 63 | ); | |||||
| 64 | } | |||||
| 65 | ||||||
| 66 | ||||||
| 67 - 80 | =head1 NAME C4::AuthoritiesMarc =head2 GetAuthMARCFromKohaField ( $tag, $subfield ) = &GetAuthMARCFromKohaField ($kohafield,$authtypecode); returns tag and subfield linked to kohafield Comment : Suppose Kohafield is only linked to ONE subfield =cut | |||||
| 81 | ||||||
| 82 | sub GetAuthMARCFromKohaField { | |||||
| 83 | #AUTHfind_marc_from_kohafield | |||||
| 84 | 0 | my ( $kohafield,$authtypecode ) = @_; | ||||
| 85 | 0 | my $dbh=C4::Context->dbh; | ||||
| 86 | 0 | return 0, 0 unless $kohafield; | ||||
| 87 | 0 | $authtypecode="" unless $authtypecode; | ||||
| 88 | 0 | my $marcfromkohafield; | ||||
| 89 | 0 | my $sth = $dbh->prepare("select tagfield,tagsubfield from auth_subfield_structure where kohafield= ? and authtypecode=? "); | ||||
| 90 | 0 | $sth->execute($kohafield,$authtypecode); | ||||
| 91 | 0 | my ($tagfield,$tagsubfield) = $sth->fetchrow; | ||||
| 92 | ||||||
| 93 | 0 | return ($tagfield,$tagsubfield); | ||||
| 94 | } | |||||
| 95 | ||||||
| 96 - 104 | =head2 SearchAuthorities
(\@finalresult, $nbresults)= &SearchAuthorities($tags, $and_or,
$excluding, $operator, $value, $offset,$length,$authtypecode,
$sortby[, $skipmetadata])
returns ref to array result and count of results returned
=cut | |||||
| 105 | ||||||
| 106 | sub SearchAuthorities { | |||||
| 107 | 0 | my ($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby,$skipmetadata) = @_; | ||||
| 108 | # warn Dumper($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby); | |||||
| 109 | 0 | my $dbh=C4::Context->dbh; | ||||
| 110 | 0 | if (C4::Context->preference('NoZebra')) { | ||||
| 111 | ||||||
| 112 | # | |||||
| 113 | # build the query | |||||
| 114 | # | |||||
| 115 | 0 | my $query; | ||||
| 116 | 0 | my @auths=split / /,$authtypecode ; | ||||
| 117 | 0 | foreach my $auth (@auths){ | ||||
| 118 | 0 | $query .="AND auth_type= $auth "; | ||||
| 119 | } | |||||
| 120 | 0 | $query =~ s/^AND //; | ||||
| 121 | 0 | my $dosearch; | ||||
| 122 | 0 | for(my $i = 0 ; $i <= $#{$value} ; $i++) | ||||
| 123 | { | |||||
| 124 | 0 | if (@$value[$i]){ | ||||
| 125 | 0 | if (@$tags[$i] =~/mainentry|mainmainentry/) { | ||||
| 126 | 0 | $query .= qq( AND @$tags[$i] ); | ||||
| 127 | } else { | |||||
| 128 | 0 | $query .=" AND "; | ||||
| 129 | } | |||||
| 130 | 0 | if (@$operator[$i] eq 'is') { | ||||
| 131 | 0 | $query.=(@$tags[$i]?"=":""). '"'.@$value[$i].'"'; | ||||
| 132 | }elsif (@$operator[$i] eq "="){ | |||||
| 133 | 0 | $query.=(@$tags[$i]?"=":""). '"'.@$value[$i].'"'; | ||||
| 134 | }elsif (@$operator[$i] eq "start"){ | |||||
| 135 | 0 | $query.=(@$tags[$i]?"=":"").'"'.@$value[$i].'%"'; | ||||
| 136 | } else { | |||||
| 137 | 0 | $query.=(@$tags[$i]?"=":"").'"'.@$value[$i].'%"'; | ||||
| 138 | } | |||||
| 139 | 0 | $dosearch=1; | ||||
| 140 | }#if value | |||||
| 141 | 0 | } | ||||
| 142 | # | |||||
| 143 | # do the query (if we had some search term | |||||
| 144 | # | |||||
| 145 | 0 | if ($dosearch) { | ||||
| 146 | # warn "QUERY : $query"; | |||||
| 147 | 0 | my $result = C4::Search::NZanalyse($query,'authorityserver'); | ||||
| 148 | # warn "result : $result"; | |||||
| 149 | 0 | my %result; | ||||
| 150 | 0 | foreach (split /;/,$result) { | ||||
| 151 | 0 | my ($authid,$title) = split /,/,$_; | ||||
| 152 | # hint : the result is sorted by title.biblionumber because we can have X biblios with the same title | |||||
| 153 | # and we don't want to get only 1 result for each of them !!! | |||||
| 154 | # hint & speed improvement : we can order without reading the record | |||||
| 155 | # so order, and read records only for the requested page ! | |||||
| 156 | 0 | $result{$title.$authid}=$authid; | ||||
| 157 | } | |||||
| 158 | # sort the hash and return the same structure as GetRecords (Zebra querying) | |||||
| 159 | 0 | my @listresult = (); | ||||
| 160 | 0 | my $numbers=0; | ||||
| 161 | 0 | if ($sortby eq 'HeadingDsc') { # sort by mainmainentry desc | ||||
| 162 | 0 0 | foreach my $key (sort {$b cmp $a} (keys %result)) { | ||||
| 163 | 0 | push @listresult, $result{$key}; | ||||
| 164 | # warn "push..."$#finalresult; | |||||
| 165 | 0 | $numbers++; | ||||
| 166 | } | |||||
| 167 | } else { # sort by mainmainentry ASC | |||||
| 168 | 0 | foreach my $key (sort (keys %result)) { | ||||
| 169 | 0 | push @listresult, $result{$key}; | ||||
| 170 | # warn "push..."$#finalresult; | |||||
| 171 | 0 | $numbers++; | ||||
| 172 | } | |||||
| 173 | } | |||||
| 174 | # limit the $results_per_page to result size if it's more | |||||
| 175 | 0 | $length = $numbers-$offset if $numbers < ($offset+$length); | ||||
| 176 | # for the requested page, replace authid by the complete record | |||||
| 177 | # speed improvement : avoid reading too much things | |||||
| 178 | 0 | my @finalresult; | ||||
| 179 | for (my $counter=$offset;$counter<=$offset+$length-1;$counter++) { | |||||
| 180 | # $finalresult[$counter] = GetAuthority($finalresult[$counter])->as_usmarc; | |||||
| 181 | 0 | my $separator=C4::Context->preference('authoritysep'); | ||||
| 182 | 0 | my $authrecord =GetAuthority($listresult[$counter]); | ||||
| 183 | 0 | my $authid=$listresult[$counter]; | ||||
| 184 | 0 | my $summary=BuildSummary($authrecord,$authid,$authtypecode); | ||||
| 185 | 0 | my $query_auth_tag = "SELECT auth_tag_to_report FROM auth_types WHERE authtypecode=?"; | ||||
| 186 | 0 | my $sth = $dbh->prepare($query_auth_tag); | ||||
| 187 | 0 | $sth->execute($authtypecode); | ||||
| 188 | 0 | my $auth_tag_to_report = $sth->fetchrow; | ||||
| 189 | 0 | my %newline; | ||||
| 190 | 0 | $newline{used}=CountUsage($authid); | ||||
| 191 | 0 | $newline{summary} = $summary; | ||||
| 192 | 0 | $newline{authid} = $authid; | ||||
| 193 | 0 | $newline{even} = $counter % 2; | ||||
| 194 | 0 | push @finalresult, \%newline; | ||||
| 195 | 0 | } | ||||
| 196 | 0 | return (\@finalresult, $numbers); | ||||
| 197 | } else { | |||||
| 198 | 0 | return; | ||||
| 199 | } | |||||
| 200 | } else { | |||||
| 201 | 0 | my $query; | ||||
| 202 | 0 | my $attr; | ||||
| 203 | # the marclist may contain "mainentry". In this case, search the tag_to_report, that depends on | |||||
| 204 | # the authtypecode. Then, search on $a of this tag_to_report | |||||
| 205 | # also store main entry MARC tag, to extract it at end of search | |||||
| 206 | 0 | my $mainentrytag; | ||||
| 207 | ##first set the authtype search and may be multiple authorities | |||||
| 208 | 0 | my $n=0; | ||||
| 209 | 0 | my @authtypecode; | ||||
| 210 | 0 | my @auths=split / /,$authtypecode ; | ||||
| 211 | 0 | foreach my $auth (@auths){ | ||||
| 212 | 0 | $query .=" \@attr 1=authtype \@attr 5=100 ".$auth; ##No truncation on authtype | ||||
| 213 | 0 | push @authtypecode ,$auth; | ||||
| 214 | 0 | $n++; | ||||
| 215 | } | |||||
| 216 | 0 | if ($n>1){ | ||||
| 217 | 0 0 0 | while ($n>1){$query= "\@or ".$query;$n--;} | ||||
| 218 | } | |||||
| 219 | ||||||
| 220 | 0 | my $dosearch; | ||||
| 221 | 0 | my $and=" \@and " ; | ||||
| 222 | 0 | my $q2; | ||||
| 223 | 0 | my $attr_cnt = 0; | ||||
| 224 | 0 | for(my $i = 0 ; $i <= $#{$value} ; $i++) | ||||
| 225 | { | |||||
| 226 | 0 | if (@$value[$i]){ | ||||
| 227 | 0 | if ( @$tags[$i] eq "mainmainentry" ) { | ||||
| 228 | 0 | $attr = " \@attr 1=Heading-Main "; | ||||
| 229 | } | |||||
| 230 | elsif ( @$tags[$i] eq "mainentry" ) { | |||||
| 231 | 0 | $attr = " \@attr 1=Heading "; | ||||
| 232 | } | |||||
| 233 | elsif ( @$tags[$i] eq "any" ) { | |||||
| 234 | 0 | $attr = " \@attr 1=Any "; | ||||
| 235 | } | |||||
| 236 | elsif ( @$tags[$i] eq "match" ) { | |||||
| 237 | 0 | $attr = " \@attr 1=Match "; | ||||
| 238 | } | |||||
| 239 | elsif ( @$tags[$i] eq "match-heading" ) { | |||||
| 240 | 0 | $attr = " \@attr 1=Match-heading "; | ||||
| 241 | } | |||||
| 242 | elsif ( @$tags[$i] eq "see-from" ) { | |||||
| 243 | 0 | $attr = " \@attr 1=Match-heading-see-from "; | ||||
| 244 | } | |||||
| 245 | elsif ( @$tags[$i] eq "thesaurus" ) { | |||||
| 246 | 0 | $attr = " \@attr 1=Subject-heading-thesaurus "; | ||||
| 247 | } | |||||
| 248 | 0 | if ( @$operator[$i] eq 'is' ) { | ||||
| 249 | 0 | $attr .= " \@attr 4=1 \@attr 5=100 " | ||||
| 250 | ; ##Phrase, No truncation,all of subfield field must match | |||||
| 251 | } | |||||
| 252 | elsif ( @$operator[$i] eq "=" ) { | |||||
| 253 | 0 | $attr .= " \@attr 4=107 "; #Number Exact match | ||||
| 254 | } | |||||
| 255 | elsif ( @$operator[$i] eq "start" ) { | |||||
| 256 | 0 | $attr .= " \@attr 3=2 \@attr 4=1 \@attr 5=1 " | ||||
| 257 | ; #Firstinfield Phrase, Right truncated | |||||
| 258 | } | |||||
| 259 | elsif ( @$operator[$i] eq "exact" ) { | |||||
| 260 | 0 | $attr .= " \@attr 4=1 \@attr 5=100 \@attr 6=3 " | ||||
| 261 | ; ##Phrase, No truncation,all of subfield field must match | |||||
| 262 | } | |||||
| 263 | else { | |||||
| 264 | 0 | $attr .= " \@attr 5=1 \@attr 4=6 " | ||||
| 265 | ; ## Word list, right truncated, anywhere | |||||
| 266 | } | |||||
| 267 | 0 | @$value[$i] =~ s/"/\\"/g; # Escape the double-quotes in the search value | ||||
| 268 | 0 | $attr =$attr."\"".@$value[$i]."\""; | ||||
| 269 | 0 | $q2 .=$attr; | ||||
| 270 | 0 | $dosearch=1; | ||||
| 271 | 0 | ++$attr_cnt; | ||||
| 272 | }#if value | |||||
| 273 | 0 | } | ||||
| 274 | ##Add how many queries generated | |||||
| 275 | 0 | if (defined $query && $query=~/\S+/){ | ||||
| 276 | 0 | $query= $and x $attr_cnt . $query . (defined $q2 ? $q2 : ''); | ||||
| 277 | } else { | |||||
| 278 | 0 | $query= $q2; | ||||
| 279 | } | |||||
| 280 | ## Adding order | |||||
| 281 | #$query=' @or @attr 7=2 @attr 1=Heading 0 @or @attr 7=1 @attr 1=Heading 1'.$query if ($sortby eq "HeadingDsc"); | |||||
| 282 | 0 | my $orderstring= ($sortby eq "HeadingAsc"? | ||||
| 283 | '@attr 7=1 @attr 1=Heading 0' | |||||
| 284 | : | |||||
| 285 | $sortby eq "HeadingDsc"? | |||||
| 286 | '@attr 7=2 @attr 1=Heading 0' | |||||
| 287 | :'' | |||||
| 288 | ); | |||||
| 289 | 0 | $query=($query?$query:"\@attr 1=_ALLRECORDS \@attr 2=103 ''"); | ||||
| 290 | 0 | $query="\@or $orderstring $query" if $orderstring; | ||||
| 291 | ||||||
| 292 | 0 | $offset=0 unless $offset; | ||||
| 293 | 0 | my $counter = $offset; | ||||
| 294 | 0 | $length=10 unless $length; | ||||
| 295 | 0 | my @oAuth; | ||||
| 296 | 0 | my $i; | ||||
| 297 | 0 | $oAuth[0]=C4::Context->Zconn("authorityserver" , 1); | ||||
| 298 | 0 | my $Anewq= new ZOOM::Query::PQF($query,$oAuth[0]); | ||||
| 299 | 0 | my $oAResult; | ||||
| 300 | 0 | $oAResult= $oAuth[0]->search($Anewq) ; | ||||
| 301 | 0 | while (($i = ZOOM::event(\@oAuth)) != 0) { | ||||
| 302 | 0 | my $ev = $oAuth[$i-1]->last_event(); | ||||
| 303 | 0 | last if $ev == ZOOM::Event::ZEND; | ||||
| 304 | } | |||||
| 305 | 0 | my($error, $errmsg, $addinfo, $diagset) = $oAuth[0]->error_x(); | ||||
| 306 | 0 | if ($error) { | ||||
| 307 | 0 | warn "oAuth error: $errmsg ($error) $addinfo $diagset\n"; | ||||
| 308 | 0 | goto NOLUCK; | ||||
| 309 | } | |||||
| 310 | ||||||
| 311 | 0 | my $nbresults; | ||||
| 312 | 0 | $nbresults=$oAResult->size(); | ||||
| 313 | 0 | my $nremains=$nbresults; | ||||
| 314 | 0 | my @result = (); | ||||
| 315 | 0 | my @finalresult = (); | ||||
| 316 | ||||||
| 317 | 0 | if ($nbresults>0){ | ||||
| 318 | ||||||
| 319 | ##Find authid and linkid fields | |||||
| 320 | ##we may be searching multiple authoritytypes. | |||||
| 321 | ## FIXME this assumes that all authid and linkid fields are the same for all authority types | |||||
| 322 | # my ($authidfield,$authidsubfield)=GetAuthMARCFromKohaField($dbh,"auth_header.authid",$authtypecode[0]); | |||||
| 323 | # my ($linkidfield,$linkidsubfield)=GetAuthMARCFromKohaField($dbh,"auth_header.linkid",$authtypecode[0]); | |||||
| 324 | 0 | while (($counter < $nbresults) && ($counter < ($offset + $length))) { | ||||
| 325 | ||||||
| 326 | ##Here we have to extract MARC record and $authid from ZEBRA AUTHORITIES | |||||
| 327 | 0 | my $rec=$oAResult->record($counter); | ||||
| 328 | 0 | my $marcdata=$rec->raw(); | ||||
| 329 | 0 | my $authrecord; | ||||
| 330 | 0 | my $separator=C4::Context->preference('authoritysep'); | ||||
| 331 | 0 | $authrecord = MARC::File::USMARC::decode($marcdata); | ||||
| 332 | 0 | my $authid=$authrecord->field('001')->data(); | ||||
| 333 | 0 | my %newline; | ||||
| 334 | 0 | $newline{authid} = $authid; | ||||
| 335 | 0 | if ( !$skipmetadata ) { | ||||
| 336 | 0 | my $summary = | ||||
| 337 | BuildSummary( $authrecord, $authid, $authtypecode ); | |||||
| 338 | 0 | my $query_auth_tag = | ||||
| 339 | "SELECT auth_tag_to_report FROM auth_types WHERE authtypecode=?"; | |||||
| 340 | 0 | my $sth = $dbh->prepare($query_auth_tag); | ||||
| 341 | 0 | $sth->execute($authtypecode); | ||||
| 342 | 0 | my $auth_tag_to_report = $sth->fetchrow; | ||||
| 343 | 0 | my $reported_tag; | ||||
| 344 | 0 | my $mainentry = $authrecord->field($auth_tag_to_report); | ||||
| 345 | 0 | if ($mainentry) { | ||||
| 346 | ||||||
| 347 | 0 | foreach ( $mainentry->subfields() ) { | ||||
| 348 | 0 | $reported_tag .= '$' . $_->[0] . $_->[1]; | ||||
| 349 | } | |||||
| 350 | } | |||||
| 351 | 0 | $newline{summary} = $summary; | ||||
| 352 | 0 | $newline{even} = $counter % 2; | ||||
| 353 | 0 | $newline{reported_tag} = $reported_tag; | ||||
| 354 | } | |||||
| 355 | 0 | $counter++; | ||||
| 356 | 0 | push @finalresult, \%newline; | ||||
| 357 | }## while counter | |||||
| 358 | ### | |||||
| 359 | 0 | if (! $skipmetadata) { | ||||
| 360 | for (my $z=0; $z<@finalresult; $z++){ | |||||
| 361 | 0 | my $count=CountUsage($finalresult[$z]{authid}); | ||||
| 362 | 0 | $finalresult[$z]{used}=$count; | ||||
| 363 | 0 | }# all $z's | ||||
| 364 | } | |||||
| 365 | ||||||
| 366 | }## if nbresult | |||||
| 367 | NOLUCK: | |||||
| 368 | 0 | $oAResult->destroy(); | ||||
| 369 | # $oAuth[0]->destroy(); | |||||
| 370 | ||||||
| 371 | 0 | return (\@finalresult, $nbresults); | ||||
| 372 | } | |||||
| 373 | } | |||||
| 374 | ||||||
| 375 - 381 | =head2 CountUsage $count= &CountUsage($authid) counts Usage of Authid in bibliorecords. =cut | |||||
| 382 | ||||||
| 383 | sub CountUsage { | |||||
| 384 | 0 | my ($authid) = @_; | ||||
| 385 | 0 | if (C4::Context->preference('NoZebra')) { | ||||
| 386 | # Read the index Koha-Auth-Number for this authid and count the lines | |||||
| 387 | 0 | my $result = C4::Search::NZanalyse("an=$authid"); | ||||
| 388 | 0 | my @tab = split /;/,$result; | ||||
| 389 | 0 | return scalar @tab; | ||||
| 390 | } else { | |||||
| 391 | ### ZOOM search here | |||||
| 392 | 0 | my $query; | ||||
| 393 | 0 | $query= "an=".$authid; | ||||
| 394 | 0 | my ($err,$res,$result) = C4::Search::SimpleSearch($query,0,10); | ||||
| 395 | 0 | if ($err) { | ||||
| 396 | 0 | warn "Error: $err from search $query"; | ||||
| 397 | 0 | $result = 0; | ||||
| 398 | } | |||||
| 399 | ||||||
| 400 | 0 | return $result; | ||||
| 401 | } | |||||
| 402 | } | |||||
| 403 | ||||||
| 404 - 410 | =head2 CountUsageChildren $count= &CountUsageChildren($authid) counts Usage of narrower terms of Authid in bibliorecords. =cut | |||||
| 411 | ||||||
| 412 | sub CountUsageChildren { | |||||
| 413 | 0 | my ($authid) = @_; | ||||
| 414 | } | |||||
| 415 | ||||||
| 416 - 422 | =head2 GetAuthTypeCode $authtypecode= &GetAuthTypeCode($authid) returns authtypecode of an authid =cut | |||||
| 423 | ||||||
| 424 | sub GetAuthTypeCode { | |||||
| 425 | #AUTHfind_authtypecode | |||||
| 426 | 0 | my ($authid) = @_; | ||||
| 427 | 0 | my $dbh=C4::Context->dbh; | ||||
| 428 | 0 | my $sth = $dbh->prepare("select authtypecode from auth_header where authid=?"); | ||||
| 429 | 0 | $sth->execute($authid); | ||||
| 430 | 0 | my $authtypecode = $sth->fetchrow; | ||||
| 431 | 0 | return $authtypecode; | ||||
| 432 | } | |||||
| 433 | ||||||
| 434 - 440 | =head2 GuessAuthTypeCode my $authtypecode = GuessAuthTypeCode($record); Get the record and tries to guess the adequate authtypecode from its content. =cut | |||||
| 441 | ||||||
| 442 | sub GuessAuthTypeCode { | |||||
| 443 | 0 | my ($record) = @_; | ||||
| 444 | 0 | return unless defined $record; | ||||
| 445 | 0 | my $heading_fields = { | ||||
| 446 | "MARC21"=>{ | |||||
| 447 | '100'=>{authtypecode=>'PERSO_NAME'}, | |||||
| 448 | '110'=>{authtypecode=>'CORPO_NAME'}, | |||||
| 449 | '111'=>{authtypecode=>'MEETI_NAME'}, | |||||
| 450 | '130'=>{authtypecode=>'UNIF_TITLE'}, | |||||
| 451 | '148'=>{authtypecode=>'CHRON_TERM'}, | |||||
| 452 | '150'=>{authtypecode=>'TOPIC_TERM'}, | |||||
| 453 | '151'=>{authtypecode=>'GEOGR_NAME'}, | |||||
| 454 | '155'=>{authtypecode=>'GENRE/FORM'}, | |||||
| 455 | '180'=>{authtypecode=>'GEN_SUBDIV'}, | |||||
| 456 | '181'=>{authtypecode=>'GEO_SUBDIV'}, | |||||
| 457 | '182'=>{authtypecode=>'CHRON_SUBD'}, | |||||
| 458 | '185'=>{authtypecode=>'FORM_SUBD'}, | |||||
| 459 | }, | |||||
| 460 | #200 Personal name 700, 701, 702 4-- with embedded 700, 701, 702 600 | |||||
| 461 | # 604 with embedded 700, 701, 702 | |||||
| 462 | #210 Corporate or meeting name 710, 711, 712 4-- with embedded 710, 711, 712 601 604 with embedded 710, 711, 712 | |||||
| 463 | #215 Territorial or geographic name 710, 711, 712 4-- with embedded 710, 711, 712 601, 607 604 with embedded 710, 711, 712 | |||||
| 464 | #216 Trademark 716 [Reserved for future use] | |||||
| 465 | #220 Family name 720, 721, 722 4-- with embedded 720, 721, 722 602 604 with embedded 720, 721, 722 | |||||
| 466 | #230 Title 500 4-- with embedded 500 605 | |||||
| 467 | #240 Name and title (embedded 200, 210, 215, or 220 and 230) 4-- with embedded 7-- and 500 7-- 604 with embedded 7-- and 500 500 | |||||
| 468 | #245 Name and collective title (embedded 200, 210, 215, or 220 and 235) 4-- with embedded 7-- and 501 604 with embedded 7-- and 501 7-- 501 | |||||
| 469 | #250 Topical subject 606 | |||||
| 470 | #260 Place access 620 | |||||
| 471 | #280 Form, genre or physical characteristics 608 | |||||
| 472 | # | |||||
| 473 | # | |||||
| 474 | # Could also be represented with : | |||||
| 475 | #leader position 9 | |||||
| 476 | #a = personal name entry | |||||
| 477 | #b = corporate name entry | |||||
| 478 | #c = territorial or geographical name | |||||
| 479 | #d = trademark | |||||
| 480 | #e = family name | |||||
| 481 | #f = uniform title | |||||
| 482 | #g = collective uniform title | |||||
| 483 | #h = name/title | |||||
| 484 | #i = name/collective uniform title | |||||
| 485 | #j = topical subject | |||||
| 486 | #k = place access | |||||
| 487 | #l = form, genre or physical characteristics | |||||
| 488 | "UNIMARC"=>{ | |||||
| 489 | '200'=>{authtypecode=>'NP'}, | |||||
| 490 | '210'=>{authtypecode=>'CO'}, | |||||
| 491 | '215'=>{authtypecode=>'SNG'}, | |||||
| 492 | '216'=>{authtypecode=>'TM'}, | |||||
| 493 | '220'=>{authtypecode=>'FAM'}, | |||||
| 494 | '230'=>{authtypecode=>'TU'}, | |||||
| 495 | '235'=>{authtypecode=>'CO_UNI_TI'}, | |||||
| 496 | '240'=>{authtypecode=>'SAUTTIT'}, | |||||
| 497 | '245'=>{authtypecode=>'NAME_COL'}, | |||||
| 498 | '250'=>{authtypecode=>'SNC'}, | |||||
| 499 | '260'=>{authtypecode=>'PA'}, | |||||
| 500 | '280'=>{authtypecode=>'GENRE/FORM'}, | |||||
| 501 | } | |||||
| 502 | }; | |||||
| 503 | 0 0 | foreach my $field (keys %{$heading_fields->{uc(C4::Context->preference('marcflavour'))} }) { | ||||
| 504 | 0 | return $heading_fields->{uc(C4::Context->preference('marcflavour'))}->{$field}->{'authtypecode'} if (defined $record->field($field)); | ||||
| 505 | } | |||||
| 506 | 0 | return; | ||||
| 507 | } | |||||
| 508 | ||||||
| 509 - 515 | =head2 GuessAuthId my $authtid = GuessAuthId($record); Get the record and tries to guess the adequate authtypecode from its content. =cut | |||||
| 516 | ||||||
| 517 | sub GuessAuthId { | |||||
| 518 | 0 | my ($record) = @_; | ||||
| 519 | 0 | return unless ($record && $record->field('001')); | ||||
| 520 | # my $authtypecode=GuessAuthTypeCode($record); | |||||
| 521 | # my ($tag,$subfield)=GetAuthMARCFromKohaField("auth_header.authid",$authtypecode); | |||||
| 522 | # if ($tag > 010) {return $record->subfield($tag,$subfield)} | |||||
| 523 | # else {return $record->field($tag)->data} | |||||
| 524 | 0 | return $record->field('001')->data; | ||||
| 525 | } | |||||
| 526 | ||||||
| 527 - 552 | =head2 GetTagsLabels
$tagslabel= &GetTagsLabels($forlibrarian,$authtypecode)
returns a ref to hashref of authorities tag and subfield structure.
tagslabel usage :
$tagslabel->{$tag}->{$subfield}->{'attribute'}
where attribute takes values in :
lib
tab
mandatory
repeatable
authorised_value
authtypecode
value_builder
kohafield
seealso
hidden
isurl
link
=cut | |||||
| 553 | ||||||
| 554 | sub GetTagsLabels { | |||||
| 555 | 0 | my ($forlibrarian,$authtypecode)= @_; | ||||
| 556 | 0 | my $dbh=C4::Context->dbh; | ||||
| 557 | 0 | $authtypecode="" unless $authtypecode; | ||||
| 558 | 0 | my $sth; | ||||
| 559 | 0 | my $libfield = ($forlibrarian == 1)? 'liblibrarian' : 'libopac'; | ||||
| 560 | ||||||
| 561 | ||||||
| 562 | # check that authority exists | |||||
| 563 | 0 | $sth=$dbh->prepare("SELECT count(*) FROM auth_tag_structure WHERE authtypecode=?"); | ||||
| 564 | 0 | $sth->execute($authtypecode); | ||||
| 565 | 0 | my ($total) = $sth->fetchrow; | ||||
| 566 | 0 | $authtypecode="" unless ($total >0); | ||||
| 567 | 0 | $sth= $dbh->prepare( | ||||
| 568 | "SELECT auth_tag_structure.tagfield,auth_tag_structure.liblibrarian,auth_tag_structure.libopac,auth_tag_structure.mandatory,auth_tag_structure.repeatable | |||||
| 569 | FROM auth_tag_structure | |||||
| 570 | WHERE authtypecode=? | |||||
| 571 | ORDER BY tagfield" | |||||
| 572 | ); | |||||
| 573 | ||||||
| 574 | 0 | $sth->execute($authtypecode); | ||||
| 575 | 0 | my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable ); | ||||
| 576 | ||||||
| 577 | 0 | while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) { | ||||
| 578 | 0 | $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac; | ||||
| 579 | 0 | $res->{$tag}->{tab} = " "; # XXX | ||||
| 580 | 0 | $res->{$tag}->{mandatory} = $mandatory; | ||||
| 581 | 0 | $res->{$tag}->{repeatable} = $repeatable; | ||||
| 582 | } | |||||
| 583 | 0 | $sth= $dbh->prepare( | ||||
| 584 | "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,frameworkcode as authtypecode,value_builder,kohafield,seealso,hidden,isurl | |||||
| 585 | FROM auth_subfield_structure | |||||
| 586 | WHERE authtypecode=? | |||||
| 587 | ORDER BY tagfield,tagsubfield" | |||||
| 588 | ); | |||||
| 589 | 0 | $sth->execute($authtypecode); | ||||
| 590 | ||||||
| 591 | 0 | my $subfield; | ||||
| 592 | 0 | my $authorised_value; | ||||
| 593 | 0 | my $value_builder; | ||||
| 594 | 0 | my $kohafield; | ||||
| 595 | 0 | my $seealso; | ||||
| 596 | 0 | my $hidden; | ||||
| 597 | 0 | my $isurl; | ||||
| 598 | 0 | my $link; | ||||
| 599 | ||||||
| 600 | 0 | while ( | ||||
| 601 | ( $tag, $subfield, $liblibrarian, , $libopac, $tab, | |||||
| 602 | $mandatory, $repeatable, $authorised_value, $authtypecode, | |||||
| 603 | $value_builder, $kohafield, $seealso, $hidden, | |||||
| 604 | $isurl, $link ) | |||||
| 605 | = $sth->fetchrow | |||||
| 606 | ) | |||||
| 607 | { | |||||
| 608 | 0 | $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac; | ||||
| 609 | 0 | $res->{$tag}->{$subfield}->{tab} = $tab; | ||||
| 610 | 0 | $res->{$tag}->{$subfield}->{mandatory} = $mandatory; | ||||
| 611 | 0 | $res->{$tag}->{$subfield}->{repeatable} = $repeatable; | ||||
| 612 | 0 | $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value; | ||||
| 613 | 0 | $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode; | ||||
| 614 | 0 | $res->{$tag}->{$subfield}->{value_builder} = $value_builder; | ||||
| 615 | 0 | $res->{$tag}->{$subfield}->{kohafield} = $kohafield; | ||||
| 616 | 0 | $res->{$tag}->{$subfield}->{seealso} = $seealso; | ||||
| 617 | 0 | $res->{$tag}->{$subfield}->{hidden} = $hidden; | ||||
| 618 | 0 | $res->{$tag}->{$subfield}->{isurl} = $isurl; | ||||
| 619 | 0 | $res->{$tag}->{$subfield}->{link} = $link; | ||||
| 620 | } | |||||
| 621 | 0 | return $res; | ||||
| 622 | } | |||||
| 623 | ||||||
| 624 - 631 | =head2 AddAuthority $authid= &AddAuthority($record, $authid,$authtypecode) Either Create Or Modify existing authority. returns authid of the newly created authority =cut | |||||
| 632 | ||||||
| 633 | sub AddAuthority { | |||||
| 634 | # pass the MARC::Record to this function, and it will create the records in the authority table | |||||
| 635 | 0 | my ($record,$authid,$authtypecode) = @_; | ||||
| 636 | 0 | my $dbh=C4::Context->dbh; | ||||
| 637 | 0 | my $leader=' nz a22 o 4500';#Leader for incomplete MARC21 record | ||||
| 638 | ||||||
| 639 | # if authid empty => true add, find a new authid number | |||||
| 640 | 0 | my $format; | ||||
| 641 | 0 | if (uc(C4::Context->preference('marcflavour')) eq 'UNIMARC') { | ||||
| 642 | 0 | $format= 'UNIMARCAUTH'; | ||||
| 643 | } | |||||
| 644 | else { | |||||
| 645 | 0 | $format= 'MARC21'; | ||||
| 646 | } | |||||
| 647 | ||||||
| 648 | #update date/time to 005 for marc and unimarc | |||||
| 649 | 0 | my $time=POSIX::strftime("%Y%m%d%H%M%S",localtime); | ||||
| 650 | 0 | my $f5=$record->field('005'); | ||||
| 651 | 0 | if (!$f5) { | ||||
| 652 | 0 | $record->insert_fields_ordered( MARC::Field->new('005',$time.".0") ); | ||||
| 653 | } | |||||
| 654 | else { | |||||
| 655 | 0 | $f5->update($time.".0"); | ||||
| 656 | } | |||||
| 657 | ||||||
| 658 | 0 | SetUTF8Flag($record); | ||||
| 659 | 0 | if ($format eq "MARC21") { | ||||
| 660 | 0 | if (!$record->leader) { | ||||
| 661 | 0 | $record->leader($leader); | ||||
| 662 | } | |||||
| 663 | 0 | if (!$record->field('003')) { | ||||
| 664 | 0 | $record->insert_fields_ordered( | ||||
| 665 | MARC::Field->new('003',C4::Context->preference('MARCOrgCode')) | |||||
| 666 | ); | |||||
| 667 | } | |||||
| 668 | 0 | my $date=POSIX::strftime("%y%m%d",localtime); | ||||
| 669 | 0 | if (!$record->field('008')) { | ||||
| 670 | # Get a valid default value for field 008 | |||||
| 671 | 0 | my $default_008 = C4::Context->preference('MARCAuthorityControlField008'); | ||||
| 672 | 0 | if(!$default_008 or length($default_008)<34) { | ||||
| 673 | 0 | $default_008 = '|| aca||aabn | a|a d'; | ||||
| 674 | } | |||||
| 675 | else { | |||||
| 676 | 0 | $default_008 = substr($default_008,0,34); | ||||
| 677 | } | |||||
| 678 | ||||||
| 679 | 0 | $record->insert_fields_ordered( MARC::Field->new('008',$date.$default_008) ); | ||||
| 680 | } | |||||
| 681 | 0 | if (!$record->field('040')) { | ||||
| 682 | 0 | $record->insert_fields_ordered( | ||||
| 683 | MARC::Field->new('040','','', | |||||
| 684 | 'a' => C4::Context->preference('MARCOrgCode'), | |||||
| 685 | 'c' => C4::Context->preference('MARCOrgCode') | |||||
| 686 | ) | |||||
| 687 | ); | |||||
| 688 | } | |||||
| 689 | } | |||||
| 690 | ||||||
| 691 | 0 | if ($format eq "UNIMARCAUTH") { | ||||
| 692 | 0 | $record->leader(" nx j22 ") unless ($record->leader()); | ||||
| 693 | 0 | my $date=POSIX::strftime("%Y%m%d",localtime); | ||||
| 694 | 0 | if (my $string=$record->subfield('100',"a")){ | ||||
| 695 | 0 | $string=~s/fre50/frey50/; | ||||
| 696 | 0 | $record->field('100')->update('a'=>$string); | ||||
| 697 | } | |||||
| 698 | elsif ($record->field('100')){ | |||||
| 699 | 0 | $record->field('100')->update('a'=>$date."afrey50 ba0"); | ||||
| 700 | } else { | |||||
| 701 | 0 | $record->append_fields( | ||||
| 702 | MARC::Field->new('100',' ',' ' | |||||
| 703 | ,'a'=>$date."afrey50 ba0") | |||||
| 704 | ); | |||||
| 705 | } | |||||
| 706 | } | |||||
| 707 | 0 | my ($auth_type_tag, $auth_type_subfield) = get_auth_type_location($authtypecode); | ||||
| 708 | 0 | if (!$authid and $format eq "MARC21") { | ||||
| 709 | # only need to do this fix when modifying an existing authority | |||||
| 710 | 0 | C4::AuthoritiesMarc::MARC21::fix_marc21_auth_type_location($record, $auth_type_tag, $auth_type_subfield); | ||||
| 711 | } | |||||
| 712 | 0 | if (my $field=$record->field($auth_type_tag)){ | ||||
| 713 | 0 | $field->update($auth_type_subfield=>$authtypecode); | ||||
| 714 | } | |||||
| 715 | else { | |||||
| 716 | 0 | $record->add_fields($auth_type_tag,'','', $auth_type_subfield=>$authtypecode); | ||||
| 717 | } | |||||
| 718 | ||||||
| 719 | 0 | my $auth_exists=0; | ||||
| 720 | 0 | my $oldRecord; | ||||
| 721 | 0 | if (!$authid) { | ||||
| 722 | 0 | my $sth=$dbh->prepare("select max(authid) from auth_header"); | ||||
| 723 | 0 | $sth->execute; | ||||
| 724 | 0 | ($authid)=$sth->fetchrow; | ||||
| 725 | 0 | $authid=$authid+1; | ||||
| 726 | ##Insert the recordID in MARC record | |||||
| 727 | 0 | unless ($record->field('001') && $record->field('001')->data() eq $authid){ | ||||
| 728 | 0 | $record->delete_field($record->field('001')); | ||||
| 729 | 0 | $record->insert_fields_ordered(MARC::Field->new('001',$authid)); | ||||
| 730 | } | |||||
| 731 | } else { | |||||
| 732 | 0 | $auth_exists=$dbh->do(qq(select authid from auth_header where authid=?),undef,$authid); | ||||
| 733 | # warn "auth_exists = $auth_exists"; | |||||
| 734 | } | |||||
| 735 | 0 | if ($auth_exists>0){ | ||||
| 736 | 0 | $oldRecord=GetAuthority($authid); | ||||
| 737 | 0 | $record->add_fields('001',$authid) unless ($record->field('001')); | ||||
| 738 | # warn "\n\n\n enregistrement".$record->as_formatted; | |||||
| 739 | 0 | my $sth=$dbh->prepare("update auth_header set authtypecode=?,marc=?,marcxml=? where authid=?"); | ||||
| 740 | 0 | $sth->execute($authtypecode,$record->as_usmarc,$record->as_xml_record($format),$authid) or die $sth->errstr; | ||||
| 741 | 0 | $sth->finish; | ||||
| 742 | } | |||||
| 743 | else { | |||||
| 744 | 0 | my $sth=$dbh->prepare("insert into auth_header (authid,datecreated,authtypecode,marc,marcxml) values (?,now(),?,?,?)"); | ||||
| 745 | 0 | $sth->execute($authid,$authtypecode,$record->as_usmarc,$record->as_xml_record($format)); | ||||
| 746 | 0 | $sth->finish; | ||||
| 747 | 0 | logaction( "AUTHORITIES", "ADD", $authid, "authority" ) if C4::Context->preference("AuthoritiesLog"); | ||||
| 748 | } | |||||
| 749 | 0 | ModZebra($authid,'specialUpdate',"authorityserver",$oldRecord,$record); | ||||
| 750 | 0 | return ($authid); | ||||
| 751 | } | |||||
| 752 | ||||||
| 753 | ||||||
| 754 - 760 | =head2 DelAuthority $authid= &DelAuthority($authid) Deletes $authid =cut | |||||
| 761 | ||||||
| 762 | sub DelAuthority { | |||||
| 763 | 0 | my ($authid) = @_; | ||||
| 764 | 0 | my $dbh=C4::Context->dbh; | ||||
| 765 | ||||||
| 766 | 0 | logaction( "AUTHORITIES", "DELETE", $authid, "authority" ) if C4::Context->preference("AuthoritiesLog"); | ||||
| 767 | 0 | ModZebra($authid,"recordDelete","authorityserver",GetAuthority($authid),undef); | ||||
| 768 | 0 | my $sth = $dbh->prepare("DELETE FROM auth_header WHERE authid=?"); | ||||
| 769 | 0 | $sth->execute($authid); | ||||
| 770 | } | |||||
| 771 | ||||||
| 772 - 778 | =head2 ModAuthority $authid= &ModAuthority($authid,$record,$authtypecode) Modifies authority record, optionally updates attached biblios. =cut | |||||
| 779 | ||||||
| 780 | sub ModAuthority { | |||||
| 781 | 0 | my ($authid,$record,$authtypecode)=@_; # deprecated $merge parameter removed | ||||
| 782 | ||||||
| 783 | 0 | my $dbh=C4::Context->dbh; | ||||
| 784 | #Now rewrite the $record to table with an add | |||||
| 785 | 0 | my $oldrecord=GetAuthority($authid); | ||||
| 786 | 0 | $authid=AddAuthority($record,$authid,$authtypecode); | ||||
| 787 | ||||||
| 788 | # If a library thinks that updating all biblios is a long process and wishes | |||||
| 789 | # to leave that to a cron job, use misc/migration_tools/merge_authority.pl. | |||||
| 790 | # In that case set system preference "dontmerge" to 1. Otherwise biblios will | |||||
| 791 | # be updated. | |||||
| 792 | 0 | unless(C4::Context->preference('dontmerge') eq '1'){ | ||||
| 793 | 0 | &merge($authid,$oldrecord,$authid,$record); | ||||
| 794 | } else { | |||||
| 795 | # save a record in need_merge_authorities table | |||||
| 796 | 0 | my $sqlinsert="INSERT INTO need_merge_authorities (authid, done) ". | ||||
| 797 | "VALUES (?,?)"; | |||||
| 798 | 0 | $dbh->do($sqlinsert,undef,($authid,0)); | ||||
| 799 | } | |||||
| 800 | 0 | logaction( "AUTHORITIES", "MODIFY", $authid, "BEFORE=>" . $oldrecord->as_formatted ) if C4::Context->preference("AuthoritiesLog"); | ||||
| 801 | 0 | return $authid; | ||||
| 802 | } | |||||
| 803 | ||||||
| 804 - 810 | =head2 GetAuthorityXML $marcxml= &GetAuthorityXML( $authid) returns xml form of record $authid =cut | |||||
| 811 | ||||||
| 812 | sub GetAuthorityXML { | |||||
| 813 | # Returns MARC::XML of the authority passed in parameter. | |||||
| 814 | 0 | my ( $authid ) = @_; | ||||
| 815 | 0 | if (uc(C4::Context->preference('marcflavour')) eq 'UNIMARC') { | ||||
| 816 | 0 | my $dbh=C4::Context->dbh; | ||||
| 817 | 0 | my $sth = $dbh->prepare("select marcxml from auth_header where authid=? " ); | ||||
| 818 | 0 | $sth->execute($authid); | ||||
| 819 | 0 | my ($marcxml)=$sth->fetchrow; | ||||
| 820 | 0 | return $marcxml; | ||||
| 821 | } | |||||
| 822 | else { | |||||
| 823 | # for MARC21, call GetAuthority instead of | |||||
| 824 | # getting the XML directly since we may | |||||
| 825 | # need to fix up the location of the authority | |||||
| 826 | # code -- note that this is reasonably safe | |||||
| 827 | # because GetAuthorityXML is used only by the | |||||
| 828 | # indexing processes like zebraqueue_start.pl | |||||
| 829 | 0 | my $record = GetAuthority($authid); | ||||
| 830 | 0 | return $record->as_xml_record('MARC21'); | ||||
| 831 | } | |||||
| 832 | } | |||||
| 833 | ||||||
| 834 - 840 | =head2 GetAuthority $record= &GetAuthority( $authid) Returns MARC::Record of the authority passed in parameter. =cut | |||||
| 841 | ||||||
| 842 | sub GetAuthority { | |||||
| 843 | 0 | my ($authid)=@_; | ||||
| 844 | 0 | my $dbh=C4::Context->dbh; | ||||
| 845 | 0 | my $sth=$dbh->prepare("select authtypecode, marcxml from auth_header where authid=?"); | ||||
| 846 | 0 | $sth->execute($authid); | ||||
| 847 | 0 | my ($authtypecode, $marcxml) = $sth->fetchrow; | ||||
| 848 | 0 0 | my $record=eval {MARC::Record->new_from_xml(StripNonXmlChars($marcxml),'UTF-8', | ||||
| 849 | (C4::Context->preference("marcflavour") eq "UNIMARC"?"UNIMARCAUTH":C4::Context->preference("marcflavour")))}; | |||||
| 850 | 0 | return undef if ($@); | ||||
| 851 | 0 | $record->encoding('UTF-8'); | ||||
| 852 | 0 | if (C4::Context->preference("marcflavour") eq "MARC21") { | ||||
| 853 | 0 | my ($auth_type_tag, $auth_type_subfield) = get_auth_type_location($authtypecode); | ||||
| 854 | 0 | C4::AuthoritiesMarc::MARC21::fix_marc21_auth_type_location($record, $auth_type_tag, $auth_type_subfield); | ||||
| 855 | } | |||||
| 856 | 0 | return ($record); | ||||
| 857 | } | |||||
| 858 | ||||||
| 859 - 867 | =head2 GetAuthType $result = &GetAuthType($authtypecode) If the authority type specified by C<$authtypecode> exists, returns a hashref of the type's fields. If the type does not exist, returns undef. =cut | |||||
| 868 | ||||||
| 869 | sub GetAuthType { | |||||
| 870 | 0 | my ($authtypecode) = @_; | ||||
| 871 | 0 | my $dbh=C4::Context->dbh; | ||||
| 872 | 0 | my $sth; | ||||
| 873 | 0 | if (defined $authtypecode){ # NOTE - in MARC21 framework, '' is a valid authority | ||||
| 874 | # type (FIXME but why?) | |||||
| 875 | 0 | $sth=$dbh->prepare("select * from auth_types where authtypecode=?"); | ||||
| 876 | 0 | $sth->execute($authtypecode); | ||||
| 877 | 0 | if (my $res = $sth->fetchrow_hashref) { | ||||
| 878 | 0 | return $res; | ||||
| 879 | } | |||||
| 880 | } | |||||
| 881 | 0 | return; | ||||
| 882 | } | |||||
| 883 | ||||||
| 884 | ||||||
| 885 - 893 | =head2 FindDuplicateAuthority $record= &FindDuplicateAuthority( $record, $authtypecode) return $authid,Summary if duplicate is found. Comments : an improvement would be to return All the records that match. =cut | |||||
| 894 | ||||||
| 895 | sub FindDuplicateAuthority { | |||||
| 896 | ||||||
| 897 | 0 | my ($record,$authtypecode)=@_; | ||||
| 898 | # warn "IN for ".$record->as_formatted; | |||||
| 899 | 0 | my $dbh = C4::Context->dbh; | ||||
| 900 | # warn "".$record->as_formatted; | |||||
| 901 | 0 | my $sth = $dbh->prepare("select auth_tag_to_report from auth_types where authtypecode=?"); | ||||
| 902 | 0 | $sth->execute($authtypecode); | ||||
| 903 | 0 | my ($auth_tag_to_report) = $sth->fetchrow; | ||||
| 904 | 0 | $sth->finish; | ||||
| 905 | # warn "record :".$record->as_formatted." auth_tag_to_report :$auth_tag_to_report"; | |||||
| 906 | # build a request for SearchAuthorities | |||||
| 907 | 0 | my $query='at='.$authtypecode.' '; | ||||
| 908 | 0 | my $filtervalues=qr([\001-\040\!\'\"\`\#\$\%\&\*\+,\-\./:;<=>\?\@\(\)\{\[\]\}_\|\~]); | ||||
| 909 | 0 | if ($record->field($auth_tag_to_report)) { | ||||
| 910 | 0 | foreach ($record->field($auth_tag_to_report)->subfields()) { | ||||
| 911 | 0 0 | $_->[1]=~s/$filtervalues/ /g; $query.= " and he,wrdl=\"".$_->[1]."\"" if ($_->[0]=~/[A-z]/); | ||||
| 912 | } | |||||
| 913 | } | |||||
| 914 | 0 | my ($error, $results, $total_hits) = C4::Search::SimpleSearch( $query, 0, 1, [ "authorityserver" ] ); | ||||
| 915 | # there is at least 1 result => return the 1st one | |||||
| 916 | 0 0 | if (!defined $error && @{$results} ) { | ||||
| 917 | 0 | my $marcrecord = MARC::File::USMARC::decode($results->[0]); | ||||
| 918 | 0 | return $marcrecord->field('001')->data,BuildSummary($marcrecord,$marcrecord->field('001')->data,$authtypecode); | ||||
| 919 | } | |||||
| 920 | # no result, returns nothing | |||||
| 921 | 0 | return; | ||||
| 922 | } | |||||
| 923 | ||||||
| 924 - 934 | =head2 BuildSummary $text= &BuildSummary( $record, $authid, $authtypecode) return HTML encoded Summary Comment : authtypecode can be infered from both record and authid. Moreover, authid can also be inferred from $record. Would it be interesting to delete those things. =cut | |||||
| 935 | ||||||
| 936 | sub BuildSummary{ | |||||
| 937 | ## give this a Marc record to return summary | |||||
| 938 | 0 | my ($record,$authid,$authtypecode)=@_; | ||||
| 939 | 0 | my $dbh=C4::Context->dbh; | ||||
| 940 | 0 | my $summary; | ||||
| 941 | # handle $authtypecode is NULL or eq "" | |||||
| 942 | 0 | if ($authtypecode) { | ||||
| 943 | 0 | my $authref = GetAuthType($authtypecode); | ||||
| 944 | 0 | $summary = $authref->{summary}; | ||||
| 945 | } | |||||
| 946 | # FIXME: should use I18N.pm | |||||
| 947 | 0 | my %language; | ||||
| 948 | 0 | $language{'fre'}="Français"; | ||||
| 949 | 0 | $language{'eng'}="Anglais"; | ||||
| 950 | 0 | $language{'ger'}="Allemand"; | ||||
| 951 | 0 | $language{'ita'}="Italien"; | ||||
| 952 | 0 | $language{'spa'}="Espagnol"; | ||||
| 953 | 0 | my %thesaurus; | ||||
| 954 | 0 | $thesaurus{'1'}="Peuples"; | ||||
| 955 | 0 | $thesaurus{'2'}="Anthroponymes"; | ||||
| 956 | 0 | $thesaurus{'3'}="Oeuvres"; | ||||
| 957 | 0 | $thesaurus{'4'}="Chronologie"; | ||||
| 958 | 0 | $thesaurus{'5'}="Lieux"; | ||||
| 959 | 0 | $thesaurus{'6'}="Sujets"; | ||||
| 960 | #thesaurus a remplir | |||||
| 961 | 0 | my @fields = $record->fields(); | ||||
| 962 | 0 | my $reported_tag; | ||||
| 963 | # if the library has a summary defined, use it. Otherwise, build a standard one | |||||
| 964 | # FIXME - it appears that the summary field in the authority frameworks | |||||
| 965 | # can work as a display template. However, this doesn't | |||||
| 966 | # suit the MARC21 version, so for now the "templating" | |||||
| 967 | # feature will be enabled only for UNIMARC for backwards | |||||
| 968 | # compatibility. | |||||
| 969 | 0 | if ($summary and C4::Context->preference('marcflavour') eq 'UNIMARC') { | ||||
| 970 | 0 | my @fields = $record->fields(); | ||||
| 971 | # $reported_tag = '$9'.$result[$counter]; | |||||
| 972 | 0 | my @stringssummary; | ||||
| 973 | 0 | foreach my $field (@fields) { | ||||
| 974 | 0 | my $tag = $field->tag(); | ||||
| 975 | 0 | my $tagvalue = $field->as_string(); | ||||
| 976 | 0 | my $localsummary= $summary; | ||||
| 977 | 0 | $localsummary =~ s/\[(.?.?.?.?)$tag\*(.*?)\]/$1$tagvalue$2\[$1$tag$2\]/g; | ||||
| 978 | 0 | if ($tag<10) { | ||||
| 979 | 0 | if ($tag eq '001') { | ||||
| 980 | 0 | $reported_tag.='$3'.$field->data(); | ||||
| 981 | } | |||||
| 982 | } else { | |||||
| 983 | 0 | my @subf = $field->subfields; | ||||
| 984 | 0 | for my $i (0..$#subf) { | ||||
| 985 | 0 | my $subfieldcode = $subf[$i][0]; | ||||
| 986 | 0 | my $subfieldvalue = $subf[$i][1]; | ||||
| 987 | 0 | my $tagsubf = $tag.$subfieldcode; | ||||
| 988 | 0 | $localsummary =~ s/\[(.?.?.?.?)$tagsubf(.*?)\]/$1$subfieldvalue$2\[$1$tagsubf$2\]/g; | ||||
| 989 | } | |||||
| 990 | } | |||||
| 991 | 0 | push @stringssummary, $localsummary if ($localsummary ne $summary); | ||||
| 992 | } | |||||
| 993 | 0 | my $resultstring; | ||||
| 994 | 0 | $resultstring = join(" -- ",@stringssummary); | ||||
| 995 | 0 | $resultstring =~ s/\[(.*?)\]//g; | ||||
| 996 | 0 | $resultstring =~ s/\n/<br>/g; | ||||
| 997 | 0 | $summary = $resultstring; | ||||
| 998 | } else { | |||||
| 999 | 0 | my $heading = ''; | ||||
| 1000 | 0 | my $altheading = ''; | ||||
| 1001 | 0 | my $seealso = ''; | ||||
| 1002 | 0 | my $broaderterms = ''; | ||||
| 1003 | 0 | my $narrowerterms = ''; | ||||
| 1004 | 0 | my $see = ''; | ||||
| 1005 | 0 | my $seeheading = ''; | ||||
| 1006 | 0 | my $notes = ''; | ||||
| 1007 | 0 | my @fields = $record->fields(); | ||||
| 1008 | 0 | if (C4::Context->preference('marcflavour') eq 'UNIMARC') { | ||||
| 1009 | # construct UNIMARC summary, that is quite different from MARC21 one | |||||
| 1010 | # accepted form | |||||
| 1011 | 0 | foreach my $field ($record->field('2..')) { | ||||
| 1012 | 0 | $heading.= $field->as_string('abcdefghijlmnopqrstuvwxyz'); | ||||
| 1013 | } | |||||
| 1014 | # rejected form(s) | |||||
| 1015 | 0 | foreach my $field ($record->field('3..')) { | ||||
| 1016 | 0 | $notes.= '<span class="note">'.$field->subfield('a')."</span>\n"; | ||||
| 1017 | } | |||||
| 1018 | 0 | foreach my $field ($record->field('4..')) { | ||||
| 1019 | 0 | if ($field->subfield('2')) { | ||||
| 1020 | 0 | my $thesaurus = "thes. : ".$thesaurus{"$field->subfield('2')"}." : "; | ||||
| 1021 | 0 | $see.= '<span class="UF">'.$thesaurus.$field->as_string('abcdefghijlmnopqrstuvwxyz')."</span> -- \n"; | ||||
| 1022 | } | |||||
| 1023 | } | |||||
| 1024 | # see : | |||||
| 1025 | 0 | foreach my $field ($record->field('5..')) { | ||||
| 1026 | ||||||
| 1027 | 0 | if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) { | ||||
| 1028 | 0 | $broaderterms.= '<span class="BT"> '.$field->as_string('abcdefgjxyz')."</span> -- \n"; | ||||
| 1029 | } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){ | |||||
| 1030 | 0 | $narrowerterms.= '<span class="NT">'.$field->as_string('abcdefgjxyz')."</span> -- \n"; | ||||
| 1031 | } elsif ($field->subfield('a')) { | |||||
| 1032 | 0 | $seealso.= '<span class="RT">'.$field->as_string('abcdefgxyz')."</a></span> -- \n"; | ||||
| 1033 | } | |||||
| 1034 | } | |||||
| 1035 | # // form | |||||
| 1036 | 0 | foreach my $field ($record->field('7..')) { | ||||
| 1037 | 0 | my $lang = substr($field->subfield('8'),3,3); | ||||
| 1038 | 0 | $seeheading.= '<span class="langue"> En '.$language{$lang}.' : </span><span class="OT"> '.$field->subfield('a')."</span><br />\n"; | ||||
| 1039 | } | |||||
| 1040 | 0 | $broaderterms =~s/-- \n$//; | ||||
| 1041 | 0 | $narrowerterms =~s/-- \n$//; | ||||
| 1042 | 0 | $seealso =~s/-- \n$//; | ||||
| 1043 | 0 | $see =~s/-- \n$//; | ||||
| 1044 | 0 | $summary = $heading."<br />".($notes?"$notes <br />":""); | ||||
| 1045 | 0 | $summary.= '<p><div class="label">TG : '.$broaderterms.'</div></p>' if ($broaderterms); | ||||
| 1046 | 0 | $summary.= '<p><div class="label">TS : '.$narrowerterms.'</div></p>' if ($narrowerterms); | ||||
| 1047 | 0 | $summary.= '<p><div class="label">TA : '.$seealso.'</div></p>' if ($seealso); | ||||
| 1048 | 0 | $summary.= '<p><div class="label">EP : '.$see.'</div></p>' if ($see); | ||||
| 1049 | 0 | $summary.= '<p><div class="label">'.$seeheading.'</div></p>' if ($seeheading); | ||||
| 1050 | } else { | |||||
| 1051 | # construct MARC21 summary | |||||
| 1052 | # FIXME - looping over 1XX is questionable | |||||
| 1053 | # since MARC21 authority should have only one 1XX | |||||
| 1054 | 0 | foreach my $field ($record->field('1..')) { | ||||
| 1055 | 0 | next if "152" eq $field->tag(); # FIXME - 152 is not a good tag to use | ||||
| 1056 | # in MARC21 -- purely local tags really ought to be | |||||
| 1057 | # 9XX | |||||
| 1058 | 0 | if ($record->field('100')) { | ||||
| 1059 | 0 | $heading.= $field->as_string('abcdefghjklmnopqrstvxyz68'); | ||||
| 1060 | } elsif ($record->field('110')) { | |||||
| 1061 | 0 | $heading.= $field->as_string('abcdefghklmnoprstvxyz68'); | ||||
| 1062 | } elsif ($record->field('111')) { | |||||
| 1063 | 0 | $heading.= $field->as_string('acdefghklnpqstvxyz68'); | ||||
| 1064 | } elsif ($record->field('130')) { | |||||
| 1065 | 0 | $heading.= $field->as_string('adfghklmnoprstvxyz68'); | ||||
| 1066 | } elsif ($record->field('148')) { | |||||
| 1067 | 0 | $heading.= $field->as_string('abvxyz68'); | ||||
| 1068 | } elsif ($record->field('150')) { | |||||
| 1069 | 0 | $heading.= $field->as_string('abvxyz68'); | ||||
| 1070 | #$heading.= $field->as_formatted(); | |||||
| 1071 | 0 | my $tag=$field->tag(); | ||||
| 1072 | 0 | $heading=~s /^$tag//g; | ||||
| 1073 | 0 | $heading =~s /\_/\$/g; | ||||
| 1074 | } elsif ($record->field('151')) { | |||||
| 1075 | 0 | $heading.= $field->as_string('avxyz68'); | ||||
| 1076 | } elsif ($record->field('155')) { | |||||
| 1077 | 0 | $heading.= $field->as_string('abvxyz68'); | ||||
| 1078 | } elsif ($record->field('180')) { | |||||
| 1079 | 0 | $heading.= $field->as_string('vxyz68'); | ||||
| 1080 | } elsif ($record->field('181')) { | |||||
| 1081 | 0 | $heading.= $field->as_string('vxyz68'); | ||||
| 1082 | } elsif ($record->field('182')) { | |||||
| 1083 | 0 | $heading.= $field->as_string('vxyz68'); | ||||
| 1084 | } elsif ($record->field('185')) { | |||||
| 1085 | 0 | $heading.= $field->as_string('vxyz68'); | ||||
| 1086 | } else { | |||||
| 1087 | 0 | $heading.= $field->as_string(); | ||||
| 1088 | } | |||||
| 1089 | } #See From | |||||
| 1090 | 0 | foreach my $field ($record->field('4..')) { | ||||
| 1091 | 0 | $seeheading.= "<br /> <i>used for/see from:</i> ".$field->as_string(); | ||||
| 1092 | } #See Also | |||||
| 1093 | 0 | foreach my $field ($record->field('5..')) { | ||||
| 1094 | 0 | $altheading.= "<br /> <i>see also:</i> ".$field->as_string(); | ||||
| 1095 | } | |||||
| 1096 | 0 | $summary .= ": " if $summary; | ||||
| 1097 | 0 | $summary.=$heading.$seeheading.$altheading; | ||||
| 1098 | } | |||||
| 1099 | } | |||||
| 1100 | 0 | return $summary; | ||||
| 1101 | } | |||||
| 1102 | ||||||
| 1103 - 1113 | =head2 BuildUnimarcHierarchies $text= &BuildUnimarcHierarchies( $authid, $force) return text containing trees for hierarchies for them to be stored in auth_header Example of text: 122,1314,2452;1324,2342,3,2452 =cut | |||||
| 1114 | ||||||
| 1115 | sub BuildUnimarcHierarchies{ | |||||
| 1116 | 0 | my $authid = shift @_; | ||||
| 1117 | # warn "authid : $authid"; | |||||
| 1118 | 0 | my $force = shift @_; | ||||
| 1119 | 0 | my @globalresult; | ||||
| 1120 | 0 | my $dbh=C4::Context->dbh; | ||||
| 1121 | 0 | my $hierarchies; | ||||
| 1122 | 0 | my $data = GetHeaderAuthority($authid); | ||||
| 1123 | 0 | if ($data->{'authtrees'} and not $force){ | ||||
| 1124 | 0 | return $data->{'authtrees'}; | ||||
| 1125 | # } elsif ($data->{'authtrees'}){ | |||||
| 1126 | # $hierarchies=$data->{'authtrees'}; | |||||
| 1127 | } else { | |||||
| 1128 | 0 | my $record = GetAuthority($authid); | ||||
| 1129 | 0 | my $found; | ||||
| 1130 | 0 | return unless $record; | ||||
| 1131 | 0 | foreach my $field ($record->field('5..')){ | ||||
| 1132 | 0 | if ($field->subfield('5') && $field->subfield('5') eq 'g'){ | ||||
| 1133 | 0 | my $subfauthid=_get_authid_subfield($field); | ||||
| 1134 | 0 | next if ($subfauthid eq $authid); | ||||
| 1135 | 0 | my $parentrecord = GetAuthority($subfauthid); | ||||
| 1136 | 0 | my $localresult=$hierarchies; | ||||
| 1137 | 0 | my $trees; | ||||
| 1138 | 0 | $trees = BuildUnimarcHierarchies($subfauthid); | ||||
| 1139 | 0 | my @trees; | ||||
| 1140 | 0 | if ($trees=~/;/){ | ||||
| 1141 | 0 | @trees = split(/;/,$trees); | ||||
| 1142 | } else { | |||||
| 1143 | 0 | push @trees, $trees; | ||||
| 1144 | } | |||||
| 1145 | 0 | foreach (@trees){ | ||||
| 1146 | 0 | $_.= ",$authid"; | ||||
| 1147 | } | |||||
| 1148 | 0 | @globalresult = (@globalresult,@trees); | ||||
| 1149 | 0 | $found=1; | ||||
| 1150 | } | |||||
| 1151 | 0 | $hierarchies=join(";",@globalresult); | ||||
| 1152 | } | |||||
| 1153 | #Unless there is no ancestor, I am alone. | |||||
| 1154 | 0 | $hierarchies="$authid" unless ($hierarchies); | ||||
| 1155 | } | |||||
| 1156 | 0 | AddAuthorityTrees($authid,$hierarchies); | ||||
| 1157 | 0 | return $hierarchies; | ||||
| 1158 | } | |||||
| 1159 | ||||||
| 1160 - 1177 | =head2 BuildUnimarcHierarchy $ref= &BuildUnimarcHierarchy( $record, $class,$authid) return a hashref in order to display hierarchy for record and final Authid $authid "loopparents" "loopchildren" "class" "loopauthid" "current_value" "value" "ifparents" "ifchildren" Those two latest ones should disappear soon. =cut | |||||
| 1178 | ||||||
| 1179 | sub BuildUnimarcHierarchy{ | |||||
| 1180 | 0 | my $record = shift @_; | ||||
| 1181 | 0 | my $class = shift @_; | ||||
| 1182 | 0 | my $authid_constructed = shift @_; | ||||
| 1183 | 0 | return undef unless ($record); | ||||
| 1184 | 0 | my $authid=$record->field('001')->data(); | ||||
| 1185 | 0 | my %cell; | ||||
| 1186 | 0 0 | my $parents=""; my $children=""; | ||||
| 1187 | 0 | my (@loopparents,@loopchildren); | ||||
| 1188 | 0 | foreach my $field ($record->field('5..')){ | ||||
| 1189 | 0 | my $subfauthid=_get_authid_subfield($field); | ||||
| 1190 | 0 | if ($subfauthid && $field->subfield('5') && $field->subfield('a')){ | ||||
| 1191 | 0 | if ($field->subfield('5') eq 'h'){ | ||||
| 1192 | 0 | push @loopchildren, { "childauthid"=>$field->subfield('3'),"childvalue"=>$field->subfield('a')}; | ||||
| 1193 | } | |||||
| 1194 | elsif ($field->subfield('5') eq 'g'){ | |||||
| 1195 | 0 | push @loopparents, { "parentauthid"=>$field->subfield('3'),"parentvalue"=>$field->subfield('a')}; | ||||
| 1196 | } | |||||
| 1197 | # brothers could get in there with an else | |||||
| 1198 | } | |||||
| 1199 | } | |||||
| 1200 | 0 | $cell{"ifparents"}=1 if (scalar(@loopparents)>0); | ||||
| 1201 | 0 | $cell{"ifchildren"}=1 if (scalar(@loopchildren)>0); | ||||
| 1202 | 0 | $cell{"loopparents"}=\@loopparents if (scalar(@loopparents)>0); | ||||
| 1203 | 0 | $cell{"loopchildren"}=\@loopchildren if (scalar(@loopchildren)>0); | ||||
| 1204 | 0 | $cell{"class"}=$class; | ||||
| 1205 | 0 | $cell{"loopauthid"}=$authid; | ||||
| 1206 | 0 | $cell{"current_value"} =1 if $authid eq $authid_constructed; | ||||
| 1207 | 0 | $cell{"value"}=$record->subfield('2..',"a"); | ||||
| 1208 | 0 | return \%cell; | ||||
| 1209 | } | |||||
| 1210 | ||||||
| 1211 | sub _get_authid_subfield{ | |||||
| 1212 | 0 | my ($field)=@_; | ||||
| 1213 | 0 | return $field->subfield('9')||$field->subfield('3'); | ||||
| 1214 | } | |||||
| 1215 - 1221 | =head2 GetHeaderAuthority $ref= &GetHeaderAuthority( $authid) return a hashref in order auth_header table data =cut | |||||
| 1222 | ||||||
| 1223 | sub GetHeaderAuthority{ | |||||
| 1224 | 0 | my $authid = shift @_; | ||||
| 1225 | 0 | my $sql= "SELECT * from auth_header WHERE authid = ?"; | ||||
| 1226 | 0 | my $dbh=C4::Context->dbh; | ||||
| 1227 | 0 | my $rq= $dbh->prepare($sql); | ||||
| 1228 | 0 | $rq->execute($authid); | ||||
| 1229 | 0 | my $data= $rq->fetchrow_hashref; | ||||
| 1230 | 0 | return $data; | ||||
| 1231 | } | |||||
| 1232 | ||||||
| 1233 - 1239 | =head2 AddAuthorityTrees $ref= &AddAuthorityTrees( $authid, $trees) return success or failure =cut | |||||
| 1240 | ||||||
| 1241 | sub AddAuthorityTrees{ | |||||
| 1242 | 0 | my $authid = shift @_; | ||||
| 1243 | 0 | my $trees = shift @_; | ||||
| 1244 | 0 | my $sql= "UPDATE IGNORE auth_header set authtrees=? WHERE authid = ?"; | ||||
| 1245 | 0 | my $dbh=C4::Context->dbh; | ||||
| 1246 | 0 | my $rq= $dbh->prepare($sql); | ||||
| 1247 | 0 | return $rq->execute($trees,$authid); | ||||
| 1248 | } | |||||
| 1249 | ||||||
| 1250 - 1257 | =head2 merge $ref= &merge(mergefrom,$MARCfrom,$mergeto,$MARCto) Could add some feature : Migrating from a typecode to an other for instance. Then we should add some new parameter : bibliotargettag, authtargettag =cut | |||||
| 1258 | ||||||
| 1259 | sub merge { | |||||
| 1260 | 0 | my ($mergefrom,$MARCfrom,$mergeto,$MARCto) = @_; | ||||
| 1261 | 0 | my ($counteditedbiblio,$countunmodifiedbiblio,$counterrors)=(0,0,0); | ||||
| 1262 | 0 | my $dbh=C4::Context->dbh; | ||||
| 1263 | 0 | my $authtypecodefrom = GetAuthTypeCode($mergefrom); | ||||
| 1264 | 0 | my $authtypecodeto = GetAuthTypeCode($mergeto); | ||||
| 1265 | # warn "mergefrom : $authtypecodefrom $mergefrom mergeto : $authtypecodeto $mergeto "; | |||||
| 1266 | # return if authority does not exist | |||||
| 1267 | 0 | return "error MARCFROM not a marcrecord ".Data::Dumper::Dumper($MARCfrom) if scalar($MARCfrom->fields()) == 0; | ||||
| 1268 | 0 | return "error MARCTO not a marcrecord".Data::Dumper::Dumper($MARCto) if scalar($MARCto->fields()) == 0; | ||||
| 1269 | # search the tag to report | |||||
| 1270 | 0 | my $sth = $dbh->prepare("select auth_tag_to_report from auth_types where authtypecode=?"); | ||||
| 1271 | 0 | $sth->execute($authtypecodefrom); | ||||
| 1272 | 0 | my ($auth_tag_to_report_from) = $sth->fetchrow; | ||||
| 1273 | 0 | $sth->execute($authtypecodeto); | ||||
| 1274 | 0 | my ($auth_tag_to_report_to) = $sth->fetchrow; | ||||
| 1275 | ||||||
| 1276 | 0 | my @record_to; | ||||
| 1277 | 0 | @record_to = $MARCto->field($auth_tag_to_report_to)->subfields() if $MARCto->field($auth_tag_to_report_to); | ||||
| 1278 | 0 | my @record_from; | ||||
| 1279 | 0 | @record_from = $MARCfrom->field($auth_tag_to_report_from)->subfields() if $MARCfrom->field($auth_tag_to_report_from); | ||||
| 1280 | ||||||
| 1281 | 0 | my @reccache; | ||||
| 1282 | # search all biblio tags using this authority. | |||||
| 1283 | #Getting marcbiblios impacted by the change. | |||||
| 1284 | 0 | if (C4::Context->preference('NoZebra')) { | ||||
| 1285 | #nozebra way | |||||
| 1286 | 0 | my $dbh=C4::Context->dbh; | ||||
| 1287 | 0 | my $rq=$dbh->prepare(qq(SELECT biblionumbers from nozebra where indexname="an" and server="biblioserver" and value="$mergefrom" )); | ||||
| 1288 | 0 | $rq->execute; | ||||
| 1289 | 0 | while (my $biblionumbers=$rq->fetchrow){ | ||||
| 1290 | 0 | my @biblionumbers=split /;/,$biblionumbers; | ||||
| 1291 | 0 | foreach (@biblionumbers) { | ||||
| 1292 | 0 | if ($_=~/(\d+),.*/) { | ||||
| 1293 | 0 | my $marc=GetMarcBiblio($1); | ||||
| 1294 | 0 | push @reccache,$marc; | ||||
| 1295 | } | |||||
| 1296 | } | |||||
| 1297 | } | |||||
| 1298 | } else { | |||||
| 1299 | #zebra connection | |||||
| 1300 | 0 | my $oConnection=C4::Context->Zconn("biblioserver",0); | ||||
| 1301 | 0 | my $oldSyntax = $oConnection->option("preferredRecordSyntax"); | ||||
| 1302 | 0 | $oConnection->option("preferredRecordSyntax"=>"XML"); | ||||
| 1303 | 0 | my $query; | ||||
| 1304 | 0 | $query= "an=".$mergefrom; | ||||
| 1305 | 0 | my $oResult = $oConnection->search(new ZOOM::Query::CCL2RPN( $query, $oConnection )); | ||||
| 1306 | 0 | my $count = 0; | ||||
| 1307 | 0 | if ($oResult) { | ||||
| 1308 | 0 | $count=$oResult->size(); | ||||
| 1309 | } | |||||
| 1310 | 0 | my $z=0; | ||||
| 1311 | 0 | while ( $z<$count ) { | ||||
| 1312 | 0 | my $rec; | ||||
| 1313 | 0 | $rec=$oResult->record($z); | ||||
| 1314 | 0 | my $marcdata = $rec->raw(); | ||||
| 1315 | 0 | my $marcrecordzebra= MARC::Record->new_from_xml($marcdata,"utf8",C4::Context->preference("marcflavour")); | ||||
| 1316 | 0 | my ( $biblionumbertagfield, $biblionumbertagsubfield ) = &GetMarcFromKohaField( "biblio.biblionumber", '' ); | ||||
| 1317 | 0 | my $i = $marcrecordzebra->subfield($biblionumbertagfield, $biblionumbertagsubfield); | ||||
| 1318 | 0 | my $marcrecorddb=GetMarcBiblio($i); | ||||
| 1319 | 0 | push @reccache, $marcrecorddb; | ||||
| 1320 | 0 | $z++; | ||||
| 1321 | } | |||||
| 1322 | 0 | $oResult->destroy(); | ||||
| 1323 | 0 | $oConnection->option("preferredRecordSyntax"=>$oldSyntax); | ||||
| 1324 | } | |||||
| 1325 | #warn scalar(@reccache)." biblios to update"; | |||||
| 1326 | # Get All candidate Tags for the change | |||||
| 1327 | # (This will reduce the search scope in marc records). | |||||
| 1328 | 0 | $sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?"); | ||||
| 1329 | 0 | $sth->execute($authtypecodefrom); | ||||
| 1330 | 0 | my @tags_using_authtype; | ||||
| 1331 | 0 | while (my ($tagfield) = $sth->fetchrow) { | ||||
| 1332 | 0 | push @tags_using_authtype,$tagfield ; | ||||
| 1333 | } | |||||
| 1334 | 0 | my $tag_to=0; | ||||
| 1335 | 0 | if ($authtypecodeto ne $authtypecodefrom){ | ||||
| 1336 | # If many tags, take the first | |||||
| 1337 | 0 | $sth->execute($authtypecodeto); | ||||
| 1338 | 0 | $tag_to=$sth->fetchrow; | ||||
| 1339 | #warn $tag_to; | |||||
| 1340 | } | |||||
| 1341 | # BulkEdit marc records | |||||
| 1342 | # May be used as a template for a bulkedit field | |||||
| 1343 | 0 | foreach my $marcrecord(@reccache){ | ||||
| 1344 | 0 | my $update; | ||||
| 1345 | 0 | foreach my $tagfield (@tags_using_authtype){ | ||||
| 1346 | # warn "tagfield : $tagfield "; | |||||
| 1347 | 0 | foreach my $field ($marcrecord->field($tagfield)){ | ||||
| 1348 | 0 | my $auth_number=$field->subfield("9"); | ||||
| 1349 | 0 | my $tag=$field->tag(); | ||||
| 1350 | 0 | if ($auth_number==$mergefrom) { | ||||
| 1351 | 0 | my $field_to=MARC::Field->new(($tag_to?$tag_to:$tag),$field->indicator(1),$field->indicator(2),"9"=>$mergeto); | ||||
| 1352 | 0 | my $exclude='9'; | ||||
| 1353 | 0 | foreach my $subfield (@record_to) { | ||||
| 1354 | 0 | $field_to->add_subfields($subfield->[0] =>$subfield->[1]); | ||||
| 1355 | 0 | $exclude.= $subfield->[0]; | ||||
| 1356 | } | |||||
| 1357 | 0 | $exclude='['.$exclude.']'; | ||||
| 1358 | # add subfields in $field not included in @record_to | |||||
| 1359 | 0 0 | my @restore= grep {$_->[0]!~/$exclude/} $field->subfields(); | ||||
| 1360 | 0 | foreach my $subfield (@restore) { | ||||
| 1361 | 0 | $field_to->add_subfields($subfield->[0] =>$subfield->[1]); | ||||
| 1362 | } | |||||
| 1363 | 0 | $marcrecord->delete_field($field); | ||||
| 1364 | 0 | $marcrecord->insert_grouped_field($field_to); | ||||
| 1365 | 0 | $update=1; | ||||
| 1366 | } | |||||
| 1367 | }#for each tag | |||||
| 1368 | }#foreach tagfield | |||||
| 1369 | 0 | my ($bibliotag,$bibliosubf) = GetMarcFromKohaField("biblio.biblionumber","") ; | ||||
| 1370 | 0 | my $biblionumber; | ||||
| 1371 | 0 | if ($bibliotag<10){ | ||||
| 1372 | 0 | $biblionumber=$marcrecord->field($bibliotag)->data; | ||||
| 1373 | } | |||||
| 1374 | else { | |||||
| 1375 | 0 | $biblionumber=$marcrecord->subfield($bibliotag,$bibliosubf); | ||||
| 1376 | } | |||||
| 1377 | 0 | unless ($biblionumber){ | ||||
| 1378 | 0 | warn "pas de numéro de notice bibliographique dans : ".$marcrecord->as_formatted; | ||||
| 1379 | 0 | next; | ||||
| 1380 | } | |||||
| 1381 | 0 | if ($update==1){ | ||||
| 1382 | 0 | &ModBiblio($marcrecord,$biblionumber,GetFrameworkCode($biblionumber)) ; | ||||
| 1383 | 0 | $counteditedbiblio++; | ||||
| 1384 | 0 | warn $counteditedbiblio if (($counteditedbiblio % 10) and $ENV{DEBUG}); | ||||
| 1385 | } | |||||
| 1386 | }#foreach $marc | |||||
| 1387 | 0 | return $counteditedbiblio; | ||||
| 1388 | # now, find every other authority linked with this authority | |||||
| 1389 | # now, find every other authority linked with this authority | |||||
| 1390 | # my $oConnection=C4::Context->Zconn("authorityserver"); | |||||
| 1391 | # my $query; | |||||
| 1392 | # # att 9210 Auth-Internal-authtype | |||||
| 1393 | # # att 9220 Auth-Internal-LN | |||||
| 1394 | # # ccl.properties to add for authorities | |||||
| 1395 | # $query= "= ".$mergefrom; | |||||
| 1396 | # my $oResult = $oConnection->search(new ZOOM::Query::CCL2RPN( $query, $oConnection )); | |||||
| 1397 | # my $count=$oResult->size() if ($oResult); | |||||
| 1398 | # my @reccache; | |||||
| 1399 | # my $z=0; | |||||
| 1400 | # while ( $z<$count ) { | |||||
| 1401 | # my $rec; | |||||
| 1402 | # $rec=$oResult->record($z); | |||||
| 1403 | # my $marcdata = $rec->raw(); | |||||
| 1404 | # push @reccache, $marcdata; | |||||
| 1405 | # $z++; | |||||
| 1406 | # } | |||||
| 1407 | # $oResult->destroy(); | |||||
| 1408 | # foreach my $marc(@reccache){ | |||||
| 1409 | # my $update; | |||||
| 1410 | # my $marcrecord; | |||||
| 1411 | # $marcrecord = MARC::File::USMARC::decode($marc); | |||||
| 1412 | # foreach my $tagfield (@tags_using_authtype){ | |||||
| 1413 | # $tagfield=substr($tagfield,0,3); | |||||
| 1414 | # my @tags = $marcrecord->field($tagfield); | |||||
| 1415 | # foreach my $tag (@tags){ | |||||
| 1416 | # my $tagsubs=$tag->subfield("9"); | |||||
| 1417 | # #warn "$tagfield:$tagsubs:$mergefrom"; | |||||
| 1418 | # if ($tagsubs== $mergefrom) { | |||||
| 1419 | # $tag->update("9" =>$mergeto); | |||||
| 1420 | # foreach my $subfield (@record_to) { | |||||
| 1421 | # # warn "$subfield,$subfield->[0],$subfield->[1]"; | |||||
| 1422 | # $tag->update($subfield->[0] =>$subfield->[1]); | |||||
| 1423 | # }#for $subfield | |||||
| 1424 | # } | |||||
| 1425 | # $marcrecord->delete_field($tag); | |||||
| 1426 | # $marcrecord->add_fields($tag); | |||||
| 1427 | # $update=1; | |||||
| 1428 | # }#for each tag | |||||
| 1429 | # }#foreach tagfield | |||||
| 1430 | # my $authoritynumber = TransformMarcToKoha($dbh,$marcrecord,"") ; | |||||
| 1431 | # if ($update==1){ | |||||
| 1432 | # &ModAuthority($marcrecord,$authoritynumber,GetAuthTypeCode($authoritynumber)) ; | |||||
| 1433 | # } | |||||
| 1434 | # | |||||
| 1435 | # }#foreach $marc | |||||
| 1436 | }#sub | |||||
| 1437 | ||||||
| 1438 - 1452 | =head2 get_auth_type_location my ($tag, $subfield) = get_auth_type_location($auth_type_code); Get the tag and subfield used to store the heading type for indexing purposes. The C<$auth_type> parameter is optional; if it is not supplied, assume ''. This routine searches the MARC authority framework for the tag and subfield whose kohafield is C<auth_header.authtypecode>; if no such field is defined in the framework, default to the hardcoded value specific to the MARC format. =cut | |||||
| 1453 | ||||||
| 1454 | sub get_auth_type_location { | |||||
| 1455 | 0 | my $auth_type_code = @_ ? shift : ''; | ||||
| 1456 | ||||||
| 1457 | 0 | my ($tag, $subfield) = GetAuthMARCFromKohaField('auth_header.authtypecode', $auth_type_code); | ||||
| 1458 | 0 | if (defined $tag and defined $subfield and $tag != 0 and $subfield ne '' and $subfield ne ' ') { | ||||
| 1459 | 0 | return ($tag, $subfield); | ||||
| 1460 | } else { | |||||
| 1461 | 0 | if (C4::Context->preference('marcflavour') eq "MARC21") { | ||||
| 1462 | 0 | return C4::AuthoritiesMarc::MARC21::default_auth_type_location(); | ||||
| 1463 | } else { | |||||
| 1464 | 0 | return C4::AuthoritiesMarc::UNIMARC::default_auth_type_location(); | ||||
| 1465 | } | |||||
| 1466 | } | |||||
| 1467 | } | |||||
| 1468 | ||||||
| 1469 | 3 | 2479882 | END { } # module clean-up code here (global destructor) | |||
| 1470 | ||||||
| 1471 | 1; | |||||