export auth_count_usage (bugfix)
[koha.git] / C4 / AuthoritiesMarc.pm
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 with
16 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
17 # Suite 330, Boston, MA  02111-1307 USA
18
19 use strict;
20 require Exporter;
21 use C4::Context;
22 use C4::Database;
23 use C4::Koha;
24 use MARC::Record;
25 use C4::Biblio;
26
27 use vars qw($VERSION @ISA @EXPORT);
28
29 # set the version for version checking
30 $VERSION = 0.01;
31
32 @ISA = qw(Exporter);
33 @EXPORT = qw(
34         &AUTHgettagslib
35         &AUTHfindsubfield
36         &AUTHfind_authtypecode
37
38         &AUTHaddauthority
39         &AUTHmodauthority
40         &AUTHdelauthority
41         &AUTHaddsubfield
42         &AUTHgetauthority
43         
44         &AUTHgetauth_type
45         &AUTHcount_usage
46         
47         &authoritysearch
48         
49         &MARCmodsubfield
50         &AUTHhtml2marc
51         &AUTHaddword
52         &MARCaddword &MARCdelword
53         &char_decode
54  );
55
56 sub authoritysearch {
57         my ($dbh, $tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode) = @_;
58         # build the sql request. She will look like :
59         # select m1.bibid
60         #               from auth_subfield_table as m1, auth_subfield_table as m2
61         #               where m1.authid=m2.authid and
62         #               (m1.subfieldvalue like "Des%" and m2.subfieldvalue like "27%")
63
64         # "Normal" statements
65         my @normal_tags = ();
66         my @normal_and_or = ();
67         my @normal_operator = ();
68         my @normal_value = ();
69         # Extracts the NOT statements from the list of statements
70         for(my $i = 0 ; $i <= $#{$value} ; $i++)
71         {
72                 if(@$operator[$i] eq "contains") # if operator is contains, splits the words in separate requests
73                 {
74                         foreach my $word (split(/ /, @$value[$i]))
75                         {
76                                 unless (C4::Context->stopwords->{uc($word)}) {  #it's NOT a stopword => use it. Otherwise, ignore
77                                         my $tag = substr(@$tags[$i],0,3);
78                                         my $subf = substr(@$tags[$i],3,1);
79                                         push @normal_tags, @$tags[$i];
80                                         push @normal_and_or, "and";     # assumes "foo" and "bar" if "foo bar" is entered
81                                         push @normal_operator, @$operator[$i];
82                                         push @normal_value, $word;
83                                 }
84                         }
85                 }
86                 else
87                 {
88                         push @normal_tags, @$tags[$i];
89                         push @normal_and_or, @$and_or[$i];
90                         push @normal_operator, @$operator[$i];
91                         push @normal_value, @$value[$i];
92                 }
93         }
94
95         # Finds the basic results without the NOT requests
96         my ($sql_tables, $sql_where1, $sql_where2) = create_request($dbh,\@normal_tags, \@normal_and_or, \@normal_operator, \@normal_value);
97
98         my $sth;
99
100         if ($sql_where2) {
101                 $sth = $dbh->prepare("select distinct m1.authid from auth_header,$sql_tables where  m1.authid=auth_header.authid and auth_header.authtypecode=? and $sql_where2 and ($sql_where1)");
102                 warn "Q2 : select distinct m1.authid from auth_header,$sql_tables where  m1.authid=auth_header.authid and auth_header.authtypecode=? and $sql_where2 and ($sql_where1)";
103         } else {
104                 $sth = $dbh->prepare("select distinct m1.authid from auth_header,$sql_tables where  m1.authid=auth_header.authid and auth_header.authtypecode=? and $sql_where1");
105                 warn "Q : select distinct m1.authid from auth_header,$sql_tables where  m1.authid=auth_header.authid and auth_header.authtypecode=? and $sql_where1";
106         }
107         $sth->execute($authtypecode);
108         my @result = ();
109         while (my ($authid) = $sth->fetchrow) {
110                         push @result,$authid;
111                 }
112
113         # we have authid list. Now, loads summary from [offset] to [offset]+[length]
114         my $counter = $offset;
115         my @finalresult = ();
116         my $oldline;
117         while (($counter <= $#result) && ($counter <= ($offset + $length))) {
118 #               warn " HERE : $counter, $#result, $offset, $length";
119                 # get MARC::Record of the authority
120                 my $record = AUTHgetauthority($dbh,$result[$counter]);
121                 # then build the summary
122                 my $authtypecode = AUTHfind_authtypecode($dbh,$result[$counter]);
123                 my $authref = getauthtype($authtypecode);
124                 my $summary = $authref->{summary};
125                 my @fields = $record->fields();
126                 foreach my $field (@fields) {
127                         my $tag = $field->tag();
128                         if ($tag<10) {
129                         } else {
130                                 my @subf = $field->subfields;
131                                 for my $i (0..$#subf) {
132                                         my $subfieldcode = $subf[$i][0];
133                                         my $subfieldvalue = $subf[$i][1];
134                                         my $tagsubf = $tag.$subfieldcode;
135                                         $summary =~ s/\[(.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue\[$1$tagsubf$2]$2$3/g;
136                                 }
137                         }
138                 }
139                 $summary =~ s/\[(.*?)]//g;
140                 $summary =~ s/\n/<br>/g;
141
142                 # find biblio MARC field using this authtypecode (to jump to biblio)
143                 my $authtypecode = AUTHfind_authtypecode($dbh,$result[$counter]);
144                 my $sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?");
145                 $sth->execute($authtypecode);
146                 my $tags_using_authtype;
147                 while (my ($tagfield) = $sth->fetchrow) {
148 #                       warn "TAG : $tagfield";
149                         $tags_using_authtype.= $tagfield."9,";
150                 }
151                 chop $tags_using_authtype;
152                 
153                 # then add a line for the template loop
154                 my %newline;
155                 $newline{summary} = $summary;
156                 $newline{authid} = $result[$counter];
157                 $newline{used} = &AUTHcount_usage($result[$counter]);
158                 $newline{biblio_fields} = $tags_using_authtype;
159                 $counter++;
160                 push @finalresult, \%newline;
161         }
162         my $nbresults = $#result + 1;
163         return (\@finalresult, $nbresults);
164 }
165
166 # Creates the SQL Request
167
168 sub create_request {
169         my ($dbh,$tags, $and_or, $operator, $value) = @_;
170
171         my $sql_tables; # will contain marc_subfield_table as m1,...
172         my $sql_where1; # will contain the "true" where
173         my $sql_where2 = "("; # will contain m1.authid=m2.authid
174         my $nb_active=0; # will contain the number of "active" entries. and entry is active is a value is provided.
175         my $nb_table=1; # will contain the number of table. ++ on each entry EXCEPT when an OR  is provided.
176
177
178         for(my $i=0; $i<=@$value;$i++) {
179                 if (@$value[$i]) {
180                         $nb_active++;
181                         if ($nb_active==1) {
182                                 if (@$operator[$i] eq "start") {
183                                         $sql_tables .= "auth_subfield_table as m$nb_table,";
184                                         $sql_where1 .= "(m1.subfieldvalue like ".$dbh->quote("@$value[$i]%");
185                                         if (@$tags[$i]) {
186                                                 $sql_where1 .=" and m1.tag+m1.subfieldcode in (@$tags[$i])";
187                                         }
188                                         $sql_where1.=")";
189                                 } elsif (@$operator[$i] eq "contains") {        
190                                 $sql_tables .= "auth_word as m$nb_table,";
191                                         $sql_where1 .= "(m1.word  like ".$dbh->quote("@$value[$i]%");
192                                         if (@$tags[$i]) {
193                                                  $sql_where1 .=" and m1.tagsubfield in (@$tags[$i])";
194                                         }
195                                         $sql_where1.=")";
196                                 } else {
197
198                                         $sql_tables .= "auth_subfield_table as m$nb_table,";
199                                         $sql_where1 .= "(m1.subfieldvalue @$operator[$i] ".$dbh->quote("@$value[$i]");
200                                         if (@$tags[$i]) {
201                                                  $sql_where1 .=" and m1.tag+m1.subfieldcode in (@$tags[$i])";
202                                         }
203                                         $sql_where1.=")";
204                                 }
205                         } else {
206                                 if (@$operator[$i] eq "start") {
207                                         $nb_table++;
208                                         $sql_tables .= "auth_subfield_table as m$nb_table,";
209                                         $sql_where1 .= "@$and_or[$i] (m$nb_table.subfieldvalue like ".$dbh->quote("@$value[$i]%");
210                                         if (@$tags[$i]) {
211                                                 $sql_where1 .=" and m$nb_table.tag+m$nb_table.subfieldcode in (@$tags[$i])";
212                                         }
213                                         $sql_where1.=")";
214                                         $sql_where2 .= "m1.authid=m$nb_table.authid and ";
215                                 } elsif (@$operator[$i] eq "contains") {
216                                         if (@$and_or[$i] eq 'and') {
217                                                 $nb_table++;
218                                                 $sql_tables .= "auth_word as m$nb_table,";
219                                                 $sql_where1 .= "@$and_or[$i] (m$nb_table.word like ".$dbh->quote("@$value[$i]%");
220                                                 if (@$tags[$i]) {
221                                                         $sql_where1 .=" and m$nb_table.tagsubfield in(@$tags[$i])";
222                                                 }
223                                                 $sql_where1.=")";
224                                                 $sql_where2 .= "m1.authid=m$nb_table.authid and ";
225                                         } else {
226                                                 $sql_where1 .= "@$and_or[$i] (m$nb_table.word like ".$dbh->quote("@$value[$i]%");
227                                                 if (@$tags[$i]) {
228                                                         $sql_where1 .="  and m$nb_table.tag+m$nb_table.subfieldid in (@$tags[$i])";
229                                                 }
230                                                 $sql_where1.=")";
231                                                 $sql_where2 .= "m1.authid=m$nb_table.authid and ";
232                                         }
233                                 } else {
234                                         $nb_table++;
235                                         $sql_tables .= "auth_subfield_table as m$nb_table,";
236                                         $sql_where1 .= "@$and_or[$i] (m$nb_table.subfieldvalue @$operator[$i] ".$dbh->quote(@$value[$i]);
237                                         if (@$tags[$i]) {
238                                                 $sql_where1 .="  and m$nb_table.tag+m$nb_table.subfieldcode in (@$tags[$i])";
239                                         }
240                                         $sql_where2 .= "m1.authid=m$nb_table.authid and ";
241                                         $sql_where1.=")";
242                                 }
243                         }
244                 }
245         }
246
247         if($sql_where2 ne "(")  # some datas added to sql_where2, processing
248         {
249                 $sql_where2 = substr($sql_where2, 0, (length($sql_where2)-5)); # deletes the trailing ' and '
250                 $sql_where2 .= ")";
251         }
252         else    # no sql_where2 statement, deleting '('
253         {
254                 $sql_where2 = "";
255         }
256         chop $sql_tables;       # deletes the trailing ','
257         
258         return ($sql_tables, $sql_where1, $sql_where2);
259 }
260
261
262 sub AUTHcount_usage {
263         my ($authid) = @_;
264         my $dbh = C4::Context->dbh;
265         # find MARC fields using this authtype
266         my $authtypecode = AUTHfind_authtypecode($dbh,$authid);
267         my $sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?");
268         $sth->execute($authtypecode);
269         my $tags_using_authtype;
270         while (my ($tagfield) = $sth->fetchrow) {
271 #               warn "TAG : $tagfield";
272                 $tags_using_authtype.= "'".$tagfield."9',";
273         }
274         chop $tags_using_authtype;
275         if ($tags_using_authtype) {
276                 $sth = $dbh->prepare("select count(*) from marc_subfield_table where concat(tag,subfieldcode) in ($tags_using_authtype) and subfieldvalue=?");
277         } else {
278                 $sth = $dbh->prepare("select count(*) from marc_subfield_table where subfieldvalue=?");
279         }
280 #       warn "Q : select count(*) from marc_subfield_table where concat(tag,subfieldcode) in ($tags_using_authtype) and subfieldvalue=$authid";
281         $sth->execute($authid);
282         my ($result) = $sth->fetchrow;
283 #       warn "Authority $authid TOTAL USED : $result";
284         return $result;
285 }
286
287 # merging 2 authority entries. After a merge, the "from" can be deleted.
288 # sub AUTHmerge {
289 #       my ($auth_merge_from,$auth_merge_to) = @_;
290 #       my $dbh = C4::Context->dbh;
291 #       # find MARC fields using this authtype
292 #       my $authtypecode = AUTHfind_authtypecode($dbh,$authid);
293 #       # retrieve records
294 #       my $record_from = AUTHgetauthority($dbh,$auth_merge_from);
295 #       my $record_to = AUTHgetauthority($dbh,$auth_merge_to);
296 #       my $sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?");
297 #       $sth->execute($authtypecode);
298 #       my $tags_using_authtype;
299 #       while (my ($tagfield) = $sth->fetchrow) {
300 #               warn "TAG : $tagfield";
301 #               $tags_using_authtype.= "'".$tagfield."9',";
302 #       }
303 #       chop $tags_using_authtype;
304 #       # now, find every biblio using this authority
305 #       $sth = $dbh->prepare("select bibid,tag,tag_indicator,tagorder from marc_subfield_table where tag+subfieldid in ($tags_using_authtype) and subfieldvalue=?");
306 #       $sth->execute($authid);
307 #       # and delete entries before recreating them
308 #       while (my ($bibid,$tag,$tag_indicator,$tagorder) = $sth->fetchrow) {
309 #               &MARCdelsubfield($dbh,$bibid,$tag);
310 #               
311 #       }
312
313 # }
314
315 sub AUTHfind_authtypecode {
316         my ($dbh,$authid) = @_;
317         my $sth = $dbh->prepare("select authtypecode from auth_header where authid=?");
318         $sth->execute($authid);
319         my ($authtypecode) = $sth->fetchrow;
320         return $authtypecode;
321 }
322  
323
324 sub AUTHgettagslib {
325         my ($dbh,$forlibrarian,$authtypecode)= @_;
326         $authtypecode="" unless $authtypecode;
327         my $sth;
328         my $libfield = ($forlibrarian eq 1)? 'liblibrarian' : 'libopac';
329         # check that framework exists
330         $sth=$dbh->prepare("select count(*) from auth_tag_structure where authtypecode=?");
331         $sth->execute($authtypecode);
332         my ($total) = $sth->fetchrow;
333         $authtypecode="" unless ($total >0);
334         $sth=$dbh->prepare("select tagfield,$libfield as lib,mandatory,repeatable from auth_tag_structure where authtypecode=? order by tagfield");
335         $sth->execute($authtypecode);
336         my ($lib,$tag,$res,$tab,$mandatory,$repeatable);
337         while ( ($tag,$lib,$mandatory,$repeatable) = $sth->fetchrow) {
338                 $res->{$tag}->{lib}=$lib;
339                 $res->{$tab}->{tab}=""; # XXX
340                 $res->{$tag}->{mandatory}=$mandatory;
341                 $res->{$tag}->{repeatable}=$repeatable;
342         }
343
344         $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");
345         $sth->execute($authtypecode);
346
347         my $subfield;
348         my $authorised_value;
349         my $thesaurus_category;
350         my $value_builder;
351         my $kohafield;
352         my $seealso;
353         my $hidden;
354         my $isurl;
355         while ( ($tag, $subfield, $lib, $tab, $mandatory, $repeatable,$authorised_value,$value_builder,$seealso) = $sth->fetchrow) {
356                 $res->{$tag}->{$subfield}->{lib}=$lib;
357                 $res->{$tag}->{$subfield}->{tab}=$tab;
358                 $res->{$tag}->{$subfield}->{mandatory}=$mandatory;
359                 $res->{$tag}->{$subfield}->{repeatable}=$repeatable;
360                 $res->{$tag}->{$subfield}->{authorised_value}=$authorised_value;
361                 $res->{$tag}->{$subfield}->{thesaurus_category}=$thesaurus_category;
362                 $res->{$tag}->{$subfield}->{value_builder}=$value_builder;
363                 $res->{$tag}->{$subfield}->{seealso}=$seealso;
364                 $res->{$tag}->{$subfield}->{hidden}=$hidden;
365                 $res->{$tag}->{$subfield}->{isurl}=$isurl;
366         }
367         return $res;
368 }
369
370 sub AUTHaddauthority {
371 # pass the MARC::Record to this function, and it will create the records in the marc tables
372         my ($dbh,$record,$authid,$authtypecode) = @_;
373         my @fields=$record->fields();
374 #       warn "IN AUTHaddauthority $authid => ".$record->as_formatted;
375 # adding main table, and retrieving authid
376 # if authid is sent, then it's not a true add, it's only a re-add, after a delete (ie, a mod)
377 # if authid empty => true add, find a new authid number
378         unless ($authid) {
379                 $dbh->do("lock tables auth_header WRITE,auth_subfield_table WRITE, auth_word WRITE, stopwords READ");
380                 my $sth=$dbh->prepare("insert into auth_header (datecreated,authtypecode) values (now(),?)");
381                 $sth->execute($authtypecode);
382                 $sth=$dbh->prepare("select max(authid) from auth_header");
383                 $sth->execute;
384                 ($authid)=$sth->fetchrow;
385                 $sth->finish;
386         }
387         my $fieldcount=0;
388         # now, add subfields...
389         foreach my $field (@fields) {
390                 $fieldcount++;
391                 if ($field->tag() <10) {
392                                 &AUTHaddsubfield($dbh,$authid,
393                                                 $field->tag(),
394                                                 '',
395                                                 $fieldcount,
396                                                 '',
397                                                 1,
398                                                 $field->data()
399                                                 );
400                 } else {
401                         my @subfields=$field->subfields();
402                         foreach my $subfieldcount (0..$#subfields) {
403                                 &AUTHaddsubfield($dbh,$authid,
404                                                 $field->tag(),
405                                                 $field->indicator(1).$field->indicator(2),
406                                                 $fieldcount,
407                                                 $subfields[$subfieldcount][0],
408                                                 $subfieldcount+1,
409                                                 $subfields[$subfieldcount][1]
410                                                 );
411                         }
412                 }
413         }
414         $dbh->do("unlock tables");
415         return $authid;
416 }
417
418
419 sub AUTHaddsubfield {
420 # Add a new subfield to a tag into the DB.
421         my ($dbh,$authid,$tagid,$tag_indicator,$tagorder,$subfieldcode,$subfieldorder,$subfieldvalues) = @_;
422         # if not value, end of job, we do nothing
423         if (length($subfieldvalues) ==0) {
424                 return;
425         }
426         if (not($subfieldcode)) {
427                 $subfieldcode=' ';
428         }
429         my @subfieldvalues = split /\|/,$subfieldvalues;
430         foreach my $subfieldvalue (@subfieldvalues) {
431                 my $sth=$dbh->prepare("insert into auth_subfield_table (authid,tag,tagorder,tag_indicator,subfieldcode,subfieldorder,subfieldvalue) values (?,?,?,?,?,?,?)");
432                 $sth->execute($authid,(sprintf "%03s",$tagid),$tagorder,$tag_indicator,$subfieldcode,$subfieldorder,$subfieldvalue);
433                 if ($sth->errstr) {
434                         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";
435                 }
436                 &AUTHaddword($dbh,$authid,$tagid,$tagorder,$subfieldcode,$subfieldorder,$subfieldvalue);
437         }
438 }
439
440 sub AUTHgetauthority {
441 # Returns MARC::Record of the biblio passed in parameter.
442     my ($dbh,$authid)=@_;
443     my $record = MARC::Record->new();
444 #---- TODO : the leader is missing
445         $record->leader('                        ');
446     my $sth=$dbh->prepare("select authid,subfieldid,tag,tagorder,tag_indicator,subfieldcode,subfieldorder,subfieldvalue
447                                  from auth_subfield_table
448                                  where authid=? order by tag,tagorder,subfieldcode
449                          ");
450         $sth->execute($authid);
451         my $prevtagorder=1;
452         my $prevtag='XXX';
453         my $previndicator;
454         my $field; # for >=10 tags
455         my $prevvalue; # for <10 tags
456         while (my $row=$sth->fetchrow_hashref) {
457                 if ($row->{tagorder} ne $prevtagorder || $row->{tag} ne $prevtag) {
458                         $previndicator.="  ";
459                         if ($prevtag <10) {
460                         $record->add_fields((sprintf "%03s",$prevtag),$prevvalue) unless $prevtag eq "XXX"; # ignore the 1st loop
461                         } else {
462                                 $record->add_fields($field) unless $prevtag eq "XXX";
463                         }
464                         undef $field;
465                         $prevtagorder=$row->{tagorder};
466                         $prevtag = $row->{tag};
467                         $previndicator=$row->{tag_indicator};
468                         if ($row->{tag}<10) {
469                                 $prevvalue = $row->{subfieldvalue};
470                         } else {
471                                 $field = MARC::Field->new((sprintf "%03s",$prevtag), substr($row->{tag_indicator}.'  ',0,1), substr($row->{tag_indicator}.'  ',1,1), $row->{'subfieldcode'}, $row->{'subfieldvalue'} );
472                         }
473                 } else {
474                         if ($row->{tag} <10) {
475                                 $record->add_fields((sprintf "%03s",$row->{tag}), $row->{'subfieldvalue'});
476                         } else {
477                                 $field->add_subfields($row->{'subfieldcode'}, $row->{'subfieldvalue'} );
478                         }
479                         $prevtag= $row->{tag};
480                         $previndicator=$row->{tag_indicator};
481                 }
482         }
483         # the last has not been included inside the loop... do it now !
484         if ($prevtag ne "XXX") { # check that we have found something. Otherwise, prevtag is still XXX and we
485                                                 # must return an empty record, not make MARC::Record fail because we try to
486                                                 # create a record with XXX as field :-(
487                 if ($prevtag <10) {
488                         $record->add_fields($prevtag,$prevvalue);
489                 } else {
490         #               my $field = MARC::Field->new( $prevtag, "", "", %subfieldlist);
491                         $record->add_fields($field);
492                 }
493         }
494         return $record;
495 }
496
497 sub AUTHgetauth_type {
498         my ($authtypecode) = @_;
499         my $dbh=C4::Context->dbh;
500         my $sth=$dbh->prepare("select * from auth_types where authtypecode=?");
501         $sth->execute($authtypecode);
502         return $sth->fetchrow_hashref;
503 }
504 sub AUTHmodauthority {
505         my ($dbh,$authid,$record,$delete)=@_;
506         my $oldrecord=&AUTHgetauthority($dbh,$authid);
507         if ($oldrecord eq $record) {
508                 return;
509         }
510 # 1st delete the authority,
511 # 2nd recreate it
512         &AUTHdelauthority($dbh,$authid,1);
513         &AUTHaddauthority($dbh,$record,$authid,AUTHfind_authtypecode($dbh,$authid));
514         # FIXME : modify the authority in biblio too.
515 }
516
517 sub AUTHdelauthority {
518         my ($dbh,$authid,$keep_biblio) = @_;
519 # if the keep_biblio is set to 1, then authority entries in biblio are preserved.
520 # This flag is set when the delauthority is called by modauthority
521 # due to a too complex structure of MARC (repeatable fields and subfields),
522 # the best solution for a modif is to delete / recreate the record.
523
524         my $record = AUTHgetauthority($dbh,$authid);
525         $dbh->do("delete from auth_header where authid=$authid") unless $keep_biblio;
526         $dbh->do("delete from auth_subfield_table where authid=$authid");
527         $dbh->do("delete from auth_word where authid=$authid");
528 # FIXME : delete or not in biblio tables (depending on $keep_biblio flag)
529 }
530
531 sub AUTHmodsubfield {
532 # Subroutine changes a subfield value given a subfieldid.
533         my ($dbh, $subfieldid, $subfieldvalue )=@_;
534         $dbh->do("lock tables auth_subfield_table WRITE");
535         my $sth=$dbh->prepare("update auth_subfield_table set subfieldvalue=? where subfieldid=?");
536         $sth->execute($subfieldvalue, $subfieldid);
537         $dbh->do("unlock tables");
538         $sth->finish;
539         $sth=$dbh->prepare("select authid,tag,tagorder,subfieldcode,subfieldid,subfieldorder from auth_subfield_table where subfieldid=?");
540         $sth->execute($subfieldid);
541         my ($authid,$tagid,$tagorder,$subfieldcode,$x,$subfieldorder) = $sth->fetchrow;
542         $subfieldid=$x;
543         &AUTHdelword($dbh,$authid,$tagid,$tagorder,$subfieldcode,$subfieldorder);
544         &AUTHaddword($dbh,$authid,$tagid,$tagorder,$subfieldcode,$subfieldorder,$subfieldvalue);
545         return($subfieldid, $subfieldvalue);
546 }
547
548 sub AUTHfindsubfield {
549     my ($dbh,$authid,$tag,$subfieldcode,$subfieldorder,$subfieldvalue) = @_;
550     my $resultcounter=0;
551     my $subfieldid;
552     my $lastsubfieldid;
553     my $query="select subfieldid from auth_subfield_table where authid=? and tag=? and subfieldcode=?";
554     my @bind_values = ($authid,$tag, $subfieldcode);
555     if ($subfieldvalue) {
556         $query .= " and subfieldvalue=?";
557         push(@bind_values,$subfieldvalue);
558     } else {
559         if ($subfieldorder<1) {
560             $subfieldorder=1;
561         }
562         $query .= " and subfieldorder=?";
563         push(@bind_values,$subfieldorder);
564     }
565     my $sti=$dbh->prepare($query);
566     $sti->execute(@bind_values);
567     while (($subfieldid) = $sti->fetchrow) {
568         $resultcounter++;
569         $lastsubfieldid=$subfieldid;
570     }
571     if ($resultcounter>1) {
572                 # Error condition.  Values given did not resolve into a unique record.  Don't know what to edit
573                 # should rarely occur (only if we use subfieldvalue with a value that exists twice, which is strange)
574                 return -1;
575     } else {
576                 return $lastsubfieldid;
577     }
578 }
579
580 sub AUTHfindsubfieldid {
581         my ($dbh,$authid,$tag,$tagorder,$subfield,$subfieldorder) = @_;
582         my $sth=$dbh->prepare("select subfieldid from auth_subfield_table
583                                 where authid=? and tag=? and tagorder=?
584                                         and subfieldcode=? and subfieldorder=?");
585         $sth->execute($authid,$tag,$tagorder,$subfield,$subfieldorder);
586         my ($res) = $sth->fetchrow;
587         unless ($res) {
588                 $sth=$dbh->prepare("select subfieldid from auth_subfield_table
589                                 where authid=? and tag=? and tagorder=?
590                                         and subfieldcode=?");
591                 $sth->execute($authid,$tag,$tagorder,$subfield);
592                 ($res) = $sth->fetchrow;
593         }
594     return $res;
595 }
596
597 sub AUTHfind_authtypecode {
598         my ($dbh,$authid) = @_;
599         my $sth = $dbh->prepare("select authtypecode from auth_header where authid=?");
600         $sth->execute($authid);
601         my ($authtypecode) = $sth->fetchrow;
602         return $authtypecode;
603 }
604
605 sub AUTHdelsubfield {
606 # delete a subfield for $authid / tag / tagorder / subfield / subfieldorder
607     my ($dbh,$authid,$tag,$tagorder,$subfield,$subfieldorder) = @_;
608     $dbh->do("delete from auth_subfield_table where authid='$authid' and
609                         tag='$tag' and tagorder='$tagorder'
610                         and subfieldcode='$subfield' and subfieldorder='$subfieldorder'
611                         ");
612 }
613
614 sub AUTHhtml2marc {
615         my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
616         my $prevtag = -1;
617         my $record = MARC::Record->new();
618 #       my %subfieldlist=();
619         my $prevvalue; # if tag <10
620         my $field; # if tag >=10
621         for (my $i=0; $i< @$rtags; $i++) {
622                 # rebuild MARC::Record
623                 if (@$rtags[$i] ne $prevtag) {
624                         if ($prevtag < 10) {
625                                 if ($prevvalue) {
626                                         $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
627                                 }
628                         } else {
629                                 if ($field) {
630                                         $record->add_fields($field);
631                                 }
632                         }
633                         $indicators{@$rtags[$i]}.='  ';
634                         if (@$rtags[$i] <10) {
635                                 $prevvalue= @$rvalues[$i];
636                         } else {
637                                 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
638                         }
639                         $prevtag = @$rtags[$i];
640                 } else {
641                         if (@$rtags[$i] <10) {
642                                 $prevvalue=@$rvalues[$i];
643                         } else {
644                                 if (@$rvalues[$i]) {
645                                         $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
646                                 }
647                         }
648                         $prevtag= @$rtags[$i];
649                 }
650         }
651         # the last has not been included inside the loop... do it now !
652         $record->add_fields($field);
653 #       warn $record->as_formatted;
654         return $record;
655 }
656
657 sub AUTHaddword {
658 # split a subfield string and adds it into the word table.
659 # removes stopwords
660     my ($dbh,$authid,$tag,$tagorder,$subfieldid,$subfieldorder,$sentence) =@_;
661     $sentence =~ s/(\.|\?|\:|\!|\'|,|\-|\"|\(|\)|\[|\]|\{|\})/ /g;
662     my @words = split / /,$sentence;
663     my $stopwords= C4::Context->stopwords;
664     my $sth=$dbh->prepare("insert into auth_word (authid, tagsubfield, tagorder, subfieldorder, word, sndx_word)
665                         values (?,concat(?,?),?,?,?,soundex(?))");
666     foreach my $word (@words) {
667 # we record only words longer than 2 car and not in stopwords hash
668         if (length($word)>2 and !($stopwords->{uc($word)})) {
669             $sth->execute($authid,$tag,$subfieldid,$tagorder,$subfieldorder,$word,$word);
670             if ($sth->err()) {
671                 warn "ERROR ==> insert into auth_word (authid, tagsubfield, tagorder, subfieldorder, word, sndx_word) values ($authid,concat($tag,$subfieldid),$tagorder,$subfieldorder,$word,soundex($word))\n";
672             }
673         }
674     }
675 }
676
677 sub AUTHdelword {
678 # delete words. this sub deletes all the words from a sentence. a subfield modif is done by a delete then a add
679     my ($dbh,$authid,$tag,$tagorder,$subfield,$subfieldorder) = @_;
680     my $sth=$dbh->prepare("delete from auth_word where authid=? and tagsubfield=concat(?,?) and tagorder=? and subfieldorder=?");
681     $sth->execute($authid,$tag,$subfield,$tagorder,$subfieldorder);
682 }
683
684 sub char_decode {
685         # converts ISO 5426 coded string to ISO 8859-1
686         # sloppy code : should be improved in next issue
687         my ($string,$encoding) = @_ ;
688         $_ = $string ;
689 #       $encoding = C4::Context->preference("marcflavour") unless $encoding;
690         if ($encoding eq "UNIMARC") {
691                 s/\xe1/Æ/gm ;
692                 s/\xe2/Ð/gm ;
693                 s/\xe9/Ø/gm ;
694                 s/\xec/þ/gm ;
695                 s/\xf1/æ/gm ;
696                 s/\xf3/ð/gm ;
697                 s/\xf9/ø/gm ;
698                 s/\xfb/ß/gm ;
699                 s/\xc1\x61/à/gm ;
700                 s/\xc1\x65/è/gm ;
701                 s/\xc1\x69/ì/gm ;
702                 s/\xc1\x6f/ò/gm ;
703                 s/\xc1\x75/ù/gm ;
704                 s/\xc1\x41/À/gm ;
705                 s/\xc1\x45/È/gm ;
706                 s/\xc1\x49/Ì/gm ;
707                 s/\xc1\x4f/Ò/gm ;
708                 s/\xc1\x55/Ù/gm ;
709                 s/\xc2\x41/Á/gm ;
710                 s/\xc2\x45/É/gm ;
711                 s/\xc2\x49/Í/gm ;
712                 s/\xc2\x4f/Ó/gm ;
713                 s/\xc2\x55/Ú/gm ;
714                 s/\xc2\x59/Ý/gm ;
715                 s/\xc2\x61/á/gm ;
716                 s/\xc2\x65/é/gm ;
717                 s/\xc2\x69/í/gm ;
718                 s/\xc2\x6f/ó/gm ;
719                 s/\xc2\x75/ú/gm ;
720                 s/\xc2\x79/ý/gm ;
721                 s/\xc3\x41/Â/gm ;
722                 s/\xc3\x45/Ê/gm ;
723                 s/\xc3\x49/Î/gm ;
724                 s/\xc3\x4f/Ô/gm ;
725                 s/\xc3\x55/Û/gm ;
726                 s/\xc3\x61/â/gm ;
727                 s/\xc3\x65/ê/gm ;
728                 s/\xc3\x69/î/gm ;
729                 s/\xc3\x6f/ô/gm ;
730                 s/\xc3\x75/û/gm ;
731                 s/\xc4\x41/Ã/gm ;
732                 s/\xc4\x4e/Ñ/gm ;
733                 s/\xc4\x4f/Õ/gm ;
734                 s/\xc4\x61/ã/gm ;
735                 s/\xc4\x6e/ñ/gm ;
736                 s/\xc4\x6f/õ/gm ;
737                 s/\xc8\x45/Ë/gm ;
738                 s/\xc8\x49/Ï/gm ;
739                 s/\xc8\x65/ë/gm ;
740                 s/\xc8\x69/ï/gm ;
741                 s/\xc8\x76/ÿ/gm ;
742                 s/\xc9\x41/Ä/gm ;
743                 s/\xc9\x4f/Ö/gm ;
744                 s/\xc9\x55/Ü/gm ;
745                 s/\xc9\x61/ä/gm ;
746                 s/\xc9\x6f/ö/gm ;
747                 s/\xc9\x75/ü/gm ;
748                 s/\xca\x41/Å/gm ;
749                 s/\xca\x61/å/gm ;
750                 s/\xd0\x43/Ç/gm ;
751                 s/\xd0\x63/ç/gm ;
752                 # this handles non-sorting blocks (if implementation requires this)
753                 $string = nsb_clean($_) ;
754         } elsif ($encoding eq "USMARC" || $encoding eq "MARC21") {
755                 if(/[\xc1-\xff]/) {
756                         s/\xe1\x61/à/gm ;
757                         s/\xe1\x65/è/gm ;
758                         s/\xe1\x69/ì/gm ;
759                         s/\xe1\x6f/ò/gm ;
760                         s/\xe1\x75/ù/gm ;
761                         s/\xe1\x41/À/gm ;
762                         s/\xe1\x45/È/gm ;
763                         s/\xe1\x49/Ì/gm ;
764                         s/\xe1\x4f/Ò/gm ;
765                         s/\xe1\x55/Ù/gm ;
766                         s/\xe2\x41/Á/gm ;
767                         s/\xe2\x45/É/gm ;
768                         s/\xe2\x49/Í/gm ;
769                         s/\xe2\x4f/Ó/gm ;
770                         s/\xe2\x55/Ú/gm ;
771                         s/\xe2\x59/Ý/gm ;
772                         s/\xe2\x61/á/gm ;
773                         s/\xe2\x65/é/gm ;
774                         s/\xe2\x69/í/gm ;
775                         s/\xe2\x6f/ó/gm ;
776                         s/\xe2\x75/ú/gm ;
777                         s/\xe2\x79/ý/gm ;
778                         s/\xe3\x41/Â/gm ;
779                         s/\xe3\x45/Ê/gm ;
780                         s/\xe3\x49/Î/gm ;
781                         s/\xe3\x4f/Ô/gm ;
782                         s/\xe3\x55/Û/gm ;
783                         s/\xe3\x61/â/gm ;
784                         s/\xe3\x65/ê/gm ;
785                         s/\xe3\x69/î/gm ;
786                         s/\xe3\x6f/ô/gm ;
787                         s/\xe3\x75/û/gm ;
788                         s/\xe4\x41/Ã/gm ;
789                         s/\xe4\x4e/Ñ/gm ;
790                         s/\xe4\x4f/Õ/gm ;
791                         s/\xe4\x61/ã/gm ;
792                         s/\xe4\x6e/ñ/gm ;
793                         s/\xe4\x6f/õ/gm ;
794                         s/\xe8\x45/Ë/gm ;
795                         s/\xe8\x49/Ï/gm ;
796                         s/\xe8\x65/ë/gm ;
797                         s/\xe8\x69/ï/gm ;
798                         s/\xe8\x76/ÿ/gm ;
799                         s/\xe9\x41/Ä/gm ;
800                         s/\xe9\x4f/Ö/gm ;
801                         s/\xe9\x55/Ü/gm ;
802                         s/\xe9\x61/ä/gm ;
803                         s/\xe9\x6f/ö/gm ;
804                         s/\xe9\x75/ü/gm ;
805                         s/\xea\x41/Å/gm ;
806                         s/\xea\x61/å/gm ;
807                         # this handles non-sorting blocks (if implementation requires this)
808                         $string = nsb_clean($_) ;
809                 }
810         }
811         return($string) ;
812 }
813
814 sub nsb_clean {
815         my $NSB = '\x88' ;              # NSB : begin Non Sorting Block
816         my $NSE = '\x89' ;              # NSE : Non Sorting Block end
817         # handles non sorting blocks
818         my ($string) = @_ ;
819         $_ = $string ;
820         s/$NSB/(/gm ;
821         s/[ ]{0,1}$NSE/) /gm ;
822         $string = $_ ;
823         return($string) ;
824 }
825
826 END { }       # module clean-up code here (global destructor)
827
828 =back
829
830 =head1 AUTHOR
831
832 Koha Developement team <info@koha.org>
833
834 Paul POULAIN paul.poulain@free.fr
835
836 =cut
837
838 # $Id$
839 # $Log$
840 # Revision 1.8  2004/11/05 10:11:39  tipaul
841 # export auth_count_usage (bugfix)
842 #
843 # Revision 1.7  2004/09/23 16:13:00  tipaul
844 # Bugfix in modification
845 #
846 # Revision 1.6  2004/08/18 16:00:24  tipaul
847 # fixes for authorities management
848 #
849 # Revision 1.5  2004/07/05 13:37:22  doxulting
850 # First step for working authorities
851 #
852 # Revision 1.4  2004/06/22 11:35:37  tipaul
853 # removing % at the beginning of a string to avoid loooonnnngggg searchs
854 #
855 # Revision 1.3  2004/06/17 08:02:13  tipaul
856 # merging tag & subfield in auth_word for better perfs
857 #
858 # Revision 1.2  2004/06/10 08:29:01  tipaul
859 # MARC authority management (continued)
860 #
861 # Revision 1.1  2004/06/07 07:35:01  tipaul
862 # MARC authority management package
863 #