1 package C4::AuthoritiesMarc;
2 # Copyright 2000-2002 Katipo Communications
4 # This file is part of Koha.
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
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.
15 # You should have received a copy of the GNU General Public License along with
16 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
17 # Suite 330, Boston, MA 02111-1307 USA
25 use vars qw($VERSION @ISA @EXPORT);
27 # set the version for version checking
34 &MARCfind_frameworkcode
45 &MARCaddword &MARCdelword
51 my ($dbh,$forlibrarian,$authtypecode)= @_;
52 warn "AUTH : $authtypecode";
53 $authtypecode="" unless $authtypecode;
54 warn "AUTH : $authtypecode";
56 my $libfield = ($forlibrarian eq 1)? 'liblibrarian' : 'libopac';
57 # check that framework exists
58 $sth=$dbh->prepare("select count(*) from auth_tag_structure where authtypecode=?");
59 $sth->execute($authtypecode);
60 my ($total) = $sth->fetchrow;
61 $authtypecode="" unless ($total >0);
62 $sth=$dbh->prepare("select tagfield,$libfield as lib,mandatory,repeatable from auth_tag_structure where authtypecode=? order by tagfield");
63 $sth->execute($authtypecode);
64 my ($lib,$tag,$res,$tab,$mandatory,$repeatable);
65 while ( ($tag,$lib,$mandatory,$repeatable) = $sth->fetchrow) {
66 $res->{$tag}->{lib}=$lib;
67 $res->{$tab}->{tab}=""; # XXX
68 $res->{$tag}->{mandatory}=$mandatory;
69 $res->{$tag}->{repeatable}=$repeatable;
72 $sth=$dbh->prepare("select tagfield,tagsubfield,$libfield as lib,tab, mandatory, repeatable,authorised_value,value_builder,seealso from auth_subfield_structure where authtypecode=? order by tagfield,tagsubfield");
73 $sth->execute($authtypecode);
77 my $thesaurus_category;
83 while ( ($tag, $subfield, $lib, $tab, $mandatory, $repeatable,$authorised_value,$value_builder,$seealso) = $sth->fetchrow) {
84 $res->{$tag}->{$subfield}->{lib}=$lib;
85 $res->{$tag}->{$subfield}->{tab}=$tab;
86 $res->{$tag}->{$subfield}->{mandatory}=$mandatory;
87 $res->{$tag}->{$subfield}->{repeatable}=$repeatable;
88 $res->{$tag}->{$subfield}->{authorised_value}=$authorised_value;
89 $res->{$tag}->{$subfield}->{thesaurus_category}=$thesaurus_category;
90 $res->{$tag}->{$subfield}->{value_builder}=$value_builder;
91 $res->{$tag}->{$subfield}->{seealso}=$seealso;
92 $res->{$tag}->{$subfield}->{hidden}=$hidden;
93 $res->{$tag}->{$subfield}->{isurl}=$isurl;
98 sub AUTHaddauthority {
99 # pass the MARC::Record to this function, and it will create the records in the marc tables
100 my ($dbh,$record,$authid,$authtypecode) = @_;
101 my @fields=$record->fields();
102 # warn "IN AUTHaddauthority $authid => ".$record->as_formatted;
103 # adding main table, and retrieving authid
104 # if authid is sent, then it's not a true add, it's only a re-add, after a delete (ie, a mod)
105 # if authid empty => true add, find a new authid number
107 $dbh->do("lock tables auth_header WRITE,auth_subfield_table WRITE, auth_word WRITE, stopwords READ");
108 my $sth=$dbh->prepare("insert into auth_header (datecreated,authtypecode) values (now(),?)");
109 $sth->execute($authtypecode);
110 $sth=$dbh->prepare("select max(authid) from auth_header");
112 ($authid)=$sth->fetchrow;
116 # now, add subfields...
117 foreach my $field (@fields) {
119 if ($field->tag() <10) {
120 &AUTHaddsubfield($dbh,$authid,
129 my @subfields=$field->subfields();
130 foreach my $subfieldcount (0..$#subfields) {
131 &AUTHaddsubfield($dbh,$authid,
133 $field->indicator(1).$field->indicator(2),
135 $subfields[$subfieldcount][0],
137 $subfields[$subfieldcount][1]
142 $dbh->do("unlock tables");
147 sub AUTHaddsubfield {
148 # Add a new subfield to a tag into the DB.
149 my ($dbh,$authid,$tagid,$tag_indicator,$tagorder,$subfieldcode,$subfieldorder,$subfieldvalues) = @_;
150 # if not value, end of job, we do nothing
151 if (length($subfieldvalues) ==0) {
154 if (not($subfieldcode)) {
157 my @subfieldvalues = split /\|/,$subfieldvalues;
158 foreach my $subfieldvalue (@subfieldvalues) {
159 my $sth=$dbh->prepare("insert into auth_subfield_table (authid,tag,tagorder,tag_indicator,subfieldcode,subfieldorder,subfieldvalue) values (?,?,?,?,?,?,?)");
160 $sth->execute($authid,(sprintf "%03s",$tagid),$tagorder,$tag_indicator,$subfieldcode,$subfieldorder,$subfieldvalue);
162 warn "ERROR ==> insert into auth_subfield_table (authid,tag,tagorder,tag_indicator,subfieldcode,subfieldorder,subfieldvalue) values ($authid,$tagid,$tagorder,$tag_indicator,$subfieldcode,$subfieldorder,$subfieldvalue)\n";
164 &AUTHaddword($dbh,$authid,$tagid,$tagorder,$subfieldcode,$subfieldorder,$subfieldvalue);
168 sub AUTHgetauthority {
169 # Returns MARC::Record of the biblio passed in parameter.
170 my ($dbh,$authid)=@_;
171 my $record = MARC::Record->new();
172 #---- TODO : the leader is missing
173 $record->leader(' ');
174 my $sth=$dbh->prepare("select authid,subfieldid,tag,tagorder,tag_indicator,subfieldcode,subfieldorder,subfieldvalue,valuebloblink
175 from auth_subfield_table
176 where authid=? order by tag,tagorder,subfieldcode
178 $sth->execute($authid);
182 my $field; # for >=10 tags
183 my $prevvalue; # for <10 tags
184 while (my $row=$sth->fetchrow_hashref) {
185 if ($row->{tagorder} ne $prevtagorder || $row->{tag} ne $prevtag) {
188 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue) unless $prevtag eq "XXX"; # ignore the 1st loop
190 $record->add_fields($field) unless $prevtag eq "XXX";
193 $prevtagorder=$row->{tagorder};
194 $prevtag = $row->{tag};
195 $previndicator=$row->{tag_indicator};
196 if ($row->{tag}<10) {
197 $prevvalue = $row->{subfieldvalue};
199 $field = MARC::Field->new((sprintf "%03s",$prevtag), substr($row->{tag_indicator}.' ',0,1), substr($row->{tag_indicator}.' ',1,1), $row->{'subfieldcode'}, $row->{'subfieldvalue'} );
202 if ($row->{tag} <10) {
203 $record->add_fields((sprintf "%03s",$row->{tag}), $row->{'subfieldvalue'});
205 $field->add_subfields($row->{'subfieldcode'}, $row->{'subfieldvalue'} );
207 $prevtag= $row->{tag};
208 $previndicator=$row->{tag_indicator};
211 # the last has not been included inside the loop... do it now !
212 if ($prevtag ne "XXX") { # check that we have found something. Otherwise, prevtag is still XXX and we
213 # must return an empty record, not make MARC::Record fail because we try to
214 # create a record with XXX as field :-(
216 $record->add_fields($prevtag,$prevvalue);
218 # my $field = MARC::Field->new( $prevtag, "", "", %subfieldlist);
219 $record->add_fields($field);
225 sub AUTHmodauthority {
226 my ($dbh,$authid,$record,$delete)=@_;
227 my $oldrecord=&AUTHgetauthority($dbh,$authid);
228 if ($oldrecord eq $record) {
231 # 1st delete the authority,
233 &AUTHdelauthority($dbh,$authid,1);
234 &AUTHaddauthority($dbh,$record,$authid);
235 # FIXME : modify the authority in biblio too.
238 sub AUTHdelauthority {
239 my ($dbh,$authid,$keep_biblio) = @_;
240 # if the keep_biblio is set to 1, then authority entries in biblio are preserved.
241 # This flag is set when the delauthority is called by modauthority
242 # due to a too complex structure of MARC (repeatable fields and subfields),
243 # the best solution for a modif is to delete / recreate the record.
245 my $record = AUTHgetauthority($dbh,$authid);
246 $dbh->do("delete from auth_biblio where authid=$authid");
247 $dbh->do("delete from auth_subfield_table where authid=$authid");
248 $dbh->do("delete from auth_word where authid=$authid");
249 # FIXME : delete or not in biblio tables (depending on $keep_biblio flag)
252 sub AUTHmodsubfield {
253 # Subroutine changes a subfield value given a subfieldid.
254 my ($dbh, $subfieldid, $subfieldvalue )=@_;
255 $dbh->do("lock tables auth_subfield_table WRITE");
256 my $sth=$dbh->prepare("update auth_subfield_table set subfieldvalue=? where subfieldid=?");
257 $sth->execute($subfieldvalue, $subfieldid);
258 $dbh->do("unlock tables");
260 $sth=$dbh->prepare("select authid,tag,tagorder,subfieldcode,subfieldid,subfieldorder from auth_subfield_table where subfieldid=?");
261 $sth->execute($subfieldid);
262 my ($authid,$tagid,$tagorder,$subfieldcode,$x,$subfieldorder) = $sth->fetchrow;
264 &AUTHdelword($dbh,$authid,$tagid,$tagorder,$subfieldcode,$subfieldorder);
265 &AUTHaddword($dbh,$authid,$tagid,$tagorder,$subfieldcode,$subfieldorder,$subfieldvalue);
266 return($subfieldid, $subfieldvalue);
269 sub AUTHfindsubfield {
270 my ($dbh,$authid,$tag,$subfieldcode,$subfieldorder,$subfieldvalue) = @_;
274 my $query="select subfieldid from auth_subfield_table where authid=? and tag=? and subfieldcode=?";
275 my @bind_values = ($authid,$tag, $subfieldcode);
276 if ($subfieldvalue) {
277 $query .= " and subfieldvalue=?";
278 push(@bind_values,$subfieldvalue);
280 if ($subfieldorder<1) {
283 $query .= " and subfieldorder=?";
284 push(@bind_values,$subfieldorder);
286 my $sti=$dbh->prepare($query);
287 $sti->execute(@bind_values);
288 while (($subfieldid) = $sti->fetchrow) {
290 $lastsubfieldid=$subfieldid;
292 if ($resultcounter>1) {
293 # Error condition. Values given did not resolve into a unique record. Don't know what to edit
294 # should rarely occur (only if we use subfieldvalue with a value that exists twice, which is strange)
297 return $lastsubfieldid;
301 sub AUTHfindsubfieldid {
302 my ($dbh,$authid,$tag,$tagorder,$subfield,$subfieldorder) = @_;
303 my $sth=$dbh->prepare("select subfieldid from auth_subfield_table
304 where authid=? and tag=? and tagorder=?
305 and subfieldcode=? and subfieldorder=?");
306 $sth->execute($authid,$tag,$tagorder,$subfield,$subfieldorder);
307 my ($res) = $sth->fetchrow;
309 $sth=$dbh->prepare("select subfieldid from auth_subfield_table
310 where authid=? and tag=? and tagorder=?
311 and subfieldcode=?");
312 $sth->execute($authid,$tag,$tagorder,$subfield);
313 ($res) = $sth->fetchrow;
318 sub AUTHfind_authtypecode {
319 my ($dbh,$authid) = @_;
320 my $sth = $dbh->prepare("select authtypecode from auth_header where authid=?");
321 $sth->execute($authid);
322 my ($authtypecode) = $sth->fetchrow;
323 return $authtypecode;
326 sub AUTHdelsubfield {
327 # delete a subfield for $authid / tag / tagorder / subfield / subfieldorder
328 my ($dbh,$authid,$tag,$tagorder,$subfield,$subfieldorder) = @_;
329 $dbh->do("delete from auth_subfield_table where authid='$authid' and
330 tag='$tag' and tagorder='$tagorder'
331 and subfieldcode='$subfield' and subfieldorder='$subfieldorder'
336 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
338 my $record = MARC::Record->new();
339 # my %subfieldlist=();
340 my $prevvalue; # if tag <10
341 my $field; # if tag >=10
342 for (my $i=0; $i< @$rtags; $i++) {
343 # rebuild MARC::Record
344 if (@$rtags[$i] ne $prevtag) {
347 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
351 $record->add_fields($field);
354 $indicators{@$rtags[$i]}.=' ';
355 if (@$rtags[$i] <10) {
356 $prevvalue= @$rvalues[$i];
358 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
360 $prevtag = @$rtags[$i];
362 if (@$rtags[$i] <10) {
363 $prevvalue=@$rvalues[$i];
366 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
369 $prevtag= @$rtags[$i];
372 # the last has not been included inside the loop... do it now !
373 $record->add_fields($field);
374 # warn $record->as_formatted;
379 # split a subfield string and adds it into the word table.
381 my ($dbh,$authid,$tag,$tagorder,$subfieldid,$subfieldorder,$sentence) =@_;
382 $sentence =~ s/(\.|\?|\:|\!|\'|,|\-|\"|\(|\)|\[|\]|\{|\})/ /g;
383 my @words = split / /,$sentence;
384 my $stopwords= C4::Context->stopwords;
385 my $sth=$dbh->prepare("insert into auth_word (authid, tag, tagorder, subfieldid, subfieldorder, word, sndx_word)
386 values (?,?,?,?,?,?,soundex(?))");
387 foreach my $word (@words) {
388 # we record only words longer than 2 car and not in stopwords hash
389 if (length($word)>2 and !($stopwords->{uc($word)})) {
390 $sth->execute($authid,$tag,$tagorder,$subfieldid,$subfieldorder,$word,$word);
392 warn "ERROR ==> insert into auth_word (authid, tag, tagorder, subfieldid, subfieldorder, word, sndx_word) values ($authid,$tag,$tagorder,$subfieldid,$subfieldorder,$word,soundex($word))\n";
399 # delete words. this sub deletes all the words from a sentence. a subfield modif is done by a delete then a add
400 my ($dbh,$authid,$tag,$tagorder,$subfield,$subfieldorder) = @_;
401 my $sth=$dbh->prepare("delete from auth_word where authid=? and tag=? and tagorder=? and subfieldid=? and subfieldorder=?");
402 $sth->execute($authid,$tag,$tagorder,$subfield,$subfieldorder);
406 # converts ISO 5426 coded string to ISO 8859-1
407 # sloppy code : should be improved in next issue
408 my ($string,$encoding) = @_ ;
410 # $encoding = C4::Context->preference("marcflavour") unless $encoding;
411 if ($encoding eq "UNIMARC") {
473 # this handles non-sorting blocks (if implementation requires this)
474 $string = nsb_clean($_) ;
475 } elsif ($encoding eq "USMARC" || $encoding eq "MARC21") {
528 # this handles non-sorting blocks (if implementation requires this)
529 $string = nsb_clean($_) ;
536 my $NSB = '\x88' ; # NSB : begin Non Sorting Block
537 my $NSE = '\x89' ; # NSE : Non Sorting Block end
538 # handles non sorting blocks
542 s/[ ]{0,1}$NSE/) /gm ;
547 END { } # module clean-up code here (global destructor)
553 Koha Developement team <info@koha.org>
555 Paul POULAIN paul.poulain@free.fr
561 # Revision 1.1 2004/06/07 07:35:01 tipaul
562 # MARC authority management package