Merge remote-tracking branch 'origin/new/bug_6720'
[koha.git] / C4 / AuthoritiesMarc.pm
index fa2ef00..21ebd94 100644 (file)
@@ -17,9 +17,8 @@ package C4::AuthoritiesMarc;
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 use strict;
-#use warnings; FIXME - Bug 2505
+use warnings;
 use C4::Context;
-use C4::Koha;
 use MARC::Record;
 use C4::Biblio;
 use C4::Search;
@@ -32,7 +31,7 @@ use vars qw($VERSION @ISA @EXPORT);
 
 BEGIN {
        # set the version for version checking
-       $VERSION = 3.01;
+    $VERSION = 3.07.00.049;
 
        require Exporter;
        @ISA = qw(Exporter);
@@ -41,19 +40,18 @@ BEGIN {
            &GetAuthType
            &GetAuthTypeCode
        &GetAuthMARCFromKohaField 
-       &AUTHhtml2marc
 
        &AddAuthority
        &ModAuthority
        &DelAuthority
        &GetAuthority
        &GetAuthorityXML
-    
+
        &CountUsage
        &CountUsageChildren
        &SearchAuthorities
     
-       &BuildSummary
+        &BuildSummary
        &BuildUnimarcHierarchies
        &BuildUnimarcHierarchy
     
@@ -98,15 +96,16 @@ sub GetAuthMARCFromKohaField {
 =head2 SearchAuthorities 
 
   (\@finalresult, $nbresults)= &SearchAuthorities($tags, $and_or, 
-     $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby)
+     $excluding, $operator, $value, $offset,$length,$authtypecode,
+     $sortby[, $skipmetadata])
 
 returns ref to array result and count of results returned
 
 =cut
 
 sub SearchAuthorities {
-    my ($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby) = @_;
-#     warn "CALL : $tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby";
+    my ($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby,$skipmetadata) = @_;
+    # warn Dumper($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby);
     my $dbh=C4::Context->dbh;
     if (C4::Context->preference('NoZebra')) {
     
@@ -225,23 +224,45 @@ sub SearchAuthorities {
         for(my $i = 0 ; $i <= $#{$value} ; $i++)
         {
             if (@$value[$i]){
-                if (@$tags[$i] eq "mainmainentry") {
-
-                $attr =" \@attr 1=Heading-Main ";
-
-                }elsif (@$tags[$i] eq "mainentry") {
-                $attr =" \@attr 1=Heading ";
-                }else{
-                $attr =" \@attr 1=Any ";
+                if ( @$tags[$i] eq "mainmainentry" ) {
+                    $attr = " \@attr 1=Heading-Main ";
                 }
-                if (@$operator[$i] eq 'is') {
-                    $attr.=" \@attr 4=1  \@attr 5=100 ";##Phrase, No truncation,all of subfield field must match
-                }elsif (@$operator[$i] eq "="){
-                    $attr.=" \@attr 4=107 ";           #Number Exact match
-                }elsif (@$operator[$i] eq "start"){
-                    $attr.=" \@attr 3=2 \@attr 4=1 \@attr 5=1 ";#Firstinfield Phrase, Right truncated
-                } else {
-                    $attr .=" \@attr 5=1 \@attr 4=6 ";## Word list, right truncated, anywhere
+                elsif ( @$tags[$i] eq "mainentry" ) {
+                    $attr = " \@attr 1=Heading ";
+                }
+                elsif ( @$tags[$i] eq "any" ) {
+                    $attr = " \@attr 1=Any ";
+                }
+                elsif ( @$tags[$i] eq "match" ) {
+                    $attr = " \@attr 1=Match ";
+                }
+                elsif ( @$tags[$i] eq "match-heading" ) {
+                    $attr = " \@attr 1=Match-heading ";
+                }
+                elsif ( @$tags[$i] eq "see-from" ) {
+                    $attr = " \@attr 1=Match-heading-see-from ";
+                }
+                elsif ( @$tags[$i] eq "thesaurus" ) {
+                    $attr = " \@attr 1=Subject-heading-thesaurus ";
+                }
+                if ( @$operator[$i] eq 'is' ) {
+                    $attr .= " \@attr 4=1  \@attr 5=100 "
+                      ; ##Phrase, No truncation,all of subfield field must match
+                }
+                elsif ( @$operator[$i] eq "=" ) {
+                    $attr .= " \@attr 4=107 ";    #Number Exact match
+                }
+                elsif ( @$operator[$i] eq "start" ) {
+                    $attr .= " \@attr 3=2 \@attr 4=1 \@attr 5=1 "
+                      ;    #Firstinfield Phrase, Right truncated
+                }
+                elsif ( @$operator[$i] eq "exact" ) {
+                    $attr .= " \@attr 4=1  \@attr 5=100 \@attr 6=3 "
+                      ; ##Phrase, No truncation,all of subfield field must match
+                }
+                else {
+                    $attr .= " \@attr 5=1 \@attr 4=6 "
+                      ;    ## Word list, right truncated, anywhere
                 }
                 @$value[$i] =~ s/"/\\"/g; # Escape the double-quotes in the search value
                 $attr =$attr."\"".@$value[$i]."\"";
@@ -251,20 +272,23 @@ sub SearchAuthorities {
             }#if value
         }
         ##Add how many queries generated
-        if ($query=~/\S+/){
-          $query= $and x $attr_cnt . $query . $q2;
+        if (defined $query && $query=~/\S+/){
+          $query= $and x $attr_cnt . $query . (defined $q2 ? $q2 : '');
         } else {
           $query= $q2;
         }
         ## Adding order
         #$query=' @or  @attr 7=2 @attr 1=Heading 0 @or  @attr 7=1 @attr 1=Heading 1'.$query if ($sortby eq "HeadingDsc");
-        my $orderstring= ($sortby eq "HeadingAsc"?
-                           '@attr 7=1 @attr 1=Heading 0'
-                         :
-                           $sortby eq "HeadingDsc"?      
-                            '@attr 7=2 @attr 1=Heading 0'
-                           :''
-                        );            
+        my $orderstring;
+        if ($sortby eq 'HeadingAsc') {
+            $orderstring = '@attr 7=1 @attr 1=Heading 0';
+        } elsif ($sortby eq 'HeadingDsc') {
+            $orderstring = '@attr 7=2 @attr 1=Heading 0';
+        } elsif ($sortby eq 'AuthidAsc') {
+            $orderstring = '@attr 7=1 @attr 1=Local-Number 0';
+        } elsif ($sortby eq 'AuthidDsc') {
+            $orderstring = '@attr 7=2 @attr 1=Local-Number 0';
+        }
         $query=($query?$query:"\@attr 1=_ALLRECORDS \@attr 2=103 ''");
         $query="\@or $orderstring $query" if $orderstring;
 
@@ -309,35 +333,46 @@ sub SearchAuthorities {
             my $separator=C4::Context->preference('authoritysep');
             $authrecord = MARC::File::USMARC::decode($marcdata);
             my $authid=$authrecord->field('001')->data(); 
-            my $summary=BuildSummary($authrecord,$authid,$authtypecode);
-            my $query_auth_tag = "SELECT auth_tag_to_report FROM auth_types WHERE authtypecode=?";
-            my $sth = $dbh->prepare($query_auth_tag);
-            $sth->execute($authtypecode);
-            my $auth_tag_to_report = $sth->fetchrow;
-            my $reported_tag;
-            my $mainentry = $authrecord->field($auth_tag_to_report);
-            if ($mainentry) {
-                foreach ($mainentry->subfields()) {
-                    $reported_tag .='$'.$_->[0].$_->[1];
-                }
-            }
             my %newline;
-            $newline{summary} = $summary;
             $newline{authid} = $authid;
-            $newline{even} = $counter % 2;
-            $newline{reported_tag} = $reported_tag;
+            if ( !$skipmetadata ) {
+                my $summary =
+                  BuildSummary( $authrecord, $authid, $authtypecode );
+                my $query_auth_tag =
+"SELECT auth_tag_to_report FROM auth_types WHERE authtypecode=?";
+                my $sth = $dbh->prepare($query_auth_tag);
+                $sth->execute($authtypecode);
+                my $auth_tag_to_report = $sth->fetchrow;
+                my $reported_tag;
+                my $mainentry = $authrecord->field($auth_tag_to_report);
+                if ($mainentry) {
+
+                    foreach ( $mainentry->subfields() ) {
+                        $reported_tag .= '$' . $_->[0] . $_->[1];
+                    }
+                }
+                my $thisauthtype = GetAuthType(GetAuthTypeCode($authid));
+                $newline{authtype}     = defined ($thisauthtype) ?
+                                            $thisauthtype->{'authtypetext'} :
+                                            (GetAuthType($authtypecode) ? $_->{'authtypetext'} : '');
+                $newline{summary}      = $summary;
+                $newline{even}         = $counter % 2;
+                $newline{reported_tag} = $reported_tag;
+            }
             $counter++;
             push @finalresult, \%newline;
             }## while counter
-        ###
-        for (my $z=0; $z<@finalresult; $z++){
-                my  $count=CountUsage($finalresult[$z]{authid});
-                $finalresult[$z]{used}=$count;
-        }# all $z's
-        
+            ###
+            if (! $skipmetadata) {
+                for (my $z=0; $z<@finalresult; $z++){
+                    my  $count=CountUsage($finalresult[$z]{authid});
+                    $finalresult[$z]{used}=$count;
+                }# all $z's
+            }
+
         }## if nbresult
         NOLUCK:
-        $oAResult->destroy();
+        $oAResult->destroy();
         # $oAuth[0]->destroy();
         
         return (\@finalresult, $nbresults);
@@ -639,9 +674,16 @@ sub AddAuthority {
                }
                my $date=POSIX::strftime("%y%m%d",localtime);
                if (!$record->field('008')) {
-                       $record->insert_fields_ordered(
-                               MARC::Field->new('008',$date."|||a||||||           | |||     d")
-                       );
+            # Get a valid default value for field 008
+            my $default_008 = C4::Context->preference('MARCAuthorityControlField008');
+            if(!$default_008 or length($default_008)<34) {
+                $default_008 = '|| aca||aabn           | a|a     d';
+            }
+            else {
+                $default_008 = substr($default_008,0,34);
+            }
+
+            $record->insert_fields_ordered( MARC::Field->new('008',$date.$default_008) );
                }
                if (!$record->field('040')) {
                 $record->insert_fields_ordered(
@@ -734,30 +776,33 @@ sub DelAuthority {
     $sth->execute($authid);
 }
 
+=head2 ModAuthority
+
+  $authid= &ModAuthority($authid,$record,$authtypecode)
+
+Modifies authority record, optionally updates attached biblios.
+
+=cut
+
 sub ModAuthority {
-  my ($authid,$record,$authtypecode,$merge)=@_;
+  my ($authid,$record,$authtypecode)=@_; # deprecated $merge parameter removed
+
   my $dbh=C4::Context->dbh;
   #Now rewrite the $record to table with an add
   my $oldrecord=GetAuthority($authid);
   $authid=AddAuthority($record,$authid,$authtypecode);
 
-### If a library thinks that updating all biblios is a long process and wishes to leave that to a cron job to use merge_authotities.p
-### they should have a system preference "dontmerge=1" otherwise by default biblios will be updated
-### the $merge flag is now depreceated and will be removed at code cleaning
-  if (C4::Context->preference('MergeAuthoritiesOnUpdate') ){
+  # If a library thinks that updating all biblios is a long process and wishes
+  # to leave that to a cron job, use misc/migration_tools/merge_authority.pl.
+  # In that case set system preference "dontmerge" to 1. Otherwise biblios will
+  # be updated.
+  unless(C4::Context->preference('dontmerge') eq '1'){
       &merge($authid,$oldrecord,$authid,$record);
   } else {
-  # save the file in tmp/modified_authorities
-      my $cgidir = C4::Context->intranetdir ."/cgi-bin";
-      unless (opendir(DIR,"$cgidir")) {
-              $cgidir = C4::Context->intranetdir."/";
-              closedir(DIR);
-      }
-  
-      my $filename = $cgidir."/tmp/modified_authorities/$authid.authid";
-      open AUTH, "> $filename";
-      print AUTH $authid;
-      close AUTH;
+      # save a record in need_merge_authorities table
+      my $sqlinsert="INSERT INTO need_merge_authorities (authid, done) ".
+       "VALUES (?,?)";
+      $dbh->do($sqlinsert,undef,($authid,0));
   }
   logaction( "AUTHORITIES", "MODIFY", $authid, "BEFORE=>" . $oldrecord->as_formatted ) if C4::Context->preference("AuthoritiesLog");
   return $authid;
@@ -844,53 +889,6 @@ sub GetAuthType {
 }
 
 
-sub AUTHhtml2marc {
-    my ($rtags,$rsubfields,$rvalues,%indicators) = @_;
-    my $dbh=C4::Context->dbh;
-    my $prevtag = -1;
-    my $record = MARC::Record->new();
-#---- TODO : the leader is missing
-
-#     my %subfieldlist=();
-    my $prevvalue; # if tag <10
-    my $field; # if tag >=10
-    for (my $i=0; $i< @$rtags; $i++) {
-        # rebuild MARC::Record
-        if (@$rtags[$i] ne $prevtag) {
-            if ($prevtag < 10) {
-                if ($prevvalue) {
-                    $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
-                }
-            } else {
-                if ($field) {
-                    $record->add_fields($field);
-                }
-            }
-            $indicators{@$rtags[$i]}.='  ';
-            if (@$rtags[$i] <10) {
-                $prevvalue= @$rvalues[$i];
-                undef $field;
-            } else {
-                undef $prevvalue;
-                $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
-            }
-            $prevtag = @$rtags[$i];
-        } else {
-            if (@$rtags[$i] <10) {
-                $prevvalue=@$rvalues[$i];
-            } else {
-                if (length(@$rvalues[$i])>0) {
-                    $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
-                }
-            }
-            $prevtag= @$rtags[$i];
-        }
-    }
-    # the last has not been included inside the loop... do it now !
-    $record->add_fields($field) if $field;
-    return $record;
-}
-
 =head2 FindDuplicateAuthority
 
   $record= &FindDuplicateAuthority( $record, $authtypecode)
@@ -932,9 +930,9 @@ sub FindDuplicateAuthority {
 
 =head2 BuildSummary
 
-  $text= &BuildSummary( $record, $authid, $authtypecode)
+  $summary= &BuildSummary( $record, $authid, $authtypecode)
 
-return HTML encoded Summary
+Returns a hashref with a summary of the specified record.
 
 Comment : authtypecode can be infered from both record and authid.
 Moreover, authid can also be inferred from $record.
@@ -942,171 +940,206 @@ Would it be interesting to delete those things.
 
 =cut
 
-sub BuildSummary{
-## give this a Marc record to return summary
-  my ($record,$authid,$authtypecode)=@_;
-  my $dbh=C4::Context->dbh;
-  my $summary;
-  # handle $authtypecode is NULL or eq ""
-  if ($authtypecode) {
-       my $authref = GetAuthType($authtypecode);
-       $summary = $authref->{summary};
-  }
-  # FIXME: should use I18N.pm
-  my %language;
-  $language{'fre'}="Français";
-  $language{'eng'}="Anglais";
-  $language{'ger'}="Allemand";
-  $language{'ita'}="Italien";
-  $language{'spa'}="Espagnol";
-  my %thesaurus;
-  $thesaurus{'1'}="Peuples";
-  $thesaurus{'2'}="Anthroponymes";
-  $thesaurus{'3'}="Oeuvres";
-  $thesaurus{'4'}="Chronologie";
-  $thesaurus{'5'}="Lieux";
-  $thesaurus{'6'}="Sujets";
-  #thesaurus a remplir
-  my @fields = $record->fields();
-  my $reported_tag;
-  # if the library has a summary defined, use it. Otherwise, build a standard one
-  # FIXME - it appears that the summary field in the authority frameworks
-  #         can work as a display template.  However, this doesn't
-  #         suit the MARC21 version, so for now the "templating"
-  #         feature will be enabled only for UNIMARC for backwards
-  #         compatibility.
-  if ($summary and C4::Context->preference('marcflavour') eq 'UNIMARC') {
-    my @fields = $record->fields();
-    #             $reported_tag = '$9'.$result[$counter];
-       my @stringssummary;
-    foreach my $field (@fields) {
-      my $tag = $field->tag();
-      my $tagvalue = $field->as_string();
-      my $localsummary= $summary;
-         $localsummary =~ s/\[(.?.?.?.?)$tag\*(.*?)\]/$1$tagvalue$2\[$1$tag$2\]/g;
-      if ($tag<10) {
-        if ($tag eq '001') {
-          $reported_tag.='$3'.$field->data();
-        }
-      } else {
-        my @subf = $field->subfields;
-        for my $i (0..$#subf) {
-          my $subfieldcode = $subf[$i][0];
-          my $subfieldvalue = $subf[$i][1];
-          my $tagsubf = $tag.$subfieldcode;
-          $localsummary =~ s/\[(.?.?.?.?)$tagsubf(.*?)\]/$1$subfieldvalue$2\[$1$tagsubf$2\]/g;
+sub BuildSummary {
+    ## give this a Marc record to return summary
+    my ($record,$authid,$authtypecode)=@_;
+    my $dbh=C4::Context->dbh;
+    my %summary;
+    # handle $authtypecode is NULL or eq ""
+    if ($authtypecode) {
+        my $authref = GetAuthType($authtypecode);
+        $summary{authtypecode} = $authref->{authtypecode};
+        $summary{type} = $authref->{authtypetext};
+        $summary{summary} = $authref->{summary};
+    }
+    my $marc21subfields = 'abcdfghjklmnopqrstuvxyz';
+    my %marc21controlrefs = ( 'a' => 'earlier',
+        'b' => 'later',
+        'd' => 'acronym',
+        'f' => 'musical',
+        'g' => 'broader',
+        'h' => 'narrower',
+        'n' => 'notapplicable',
+        'i' => 'subfi',
+        't' => 'parent'
+    );
+    my %thesaurus;
+    $thesaurus{'1'}="Peuples";
+    $thesaurus{'2'}="Anthroponymes";
+    $thesaurus{'3'}="Oeuvres";
+    $thesaurus{'4'}="Chronologie";
+    $thesaurus{'5'}="Lieux";
+    $thesaurus{'6'}="Sujets";
+    #thesaurus a remplir
+    my $reported_tag;
+# if the library has a summary defined, use it. Otherwise, build a standard one
+# FIXME - it appears that the summary field in the authority frameworks
+#         can work as a display template.  However, this doesn't
+#         suit the MARC21 version, so for now the "templating"
+#         feature will be enabled only for UNIMARC for backwards
+#         compatibility.
+    if ($summary{summary} and C4::Context->preference('marcflavour') eq 'UNIMARC') {
+        my @fields = $record->fields();
+#             $reported_tag = '$9'.$result[$counter];
+        my @stringssummary;
+        foreach my $field (@fields) {
+            my $tag = $field->tag();
+            my $tagvalue = $field->as_string();
+            my $localsummary= $summary{summary};
+            $localsummary =~ s/\[(.?.?.?.?)$tag\*(.*?)\]/$1$tagvalue$2\[$1$tag$2\]/g;
+            if ($tag<10) {
+                if ($tag eq '001') {
+                    $reported_tag.='$3'.$field->data();
+                }
+            } else {
+                my @subf = $field->subfields;
+                for my $i (0..$#subf) {
+                    my $subfieldcode = $subf[$i][0];
+                    my $subfieldvalue = $subf[$i][1];
+                    my $tagsubf = $tag.$subfieldcode;
+                    $localsummary =~ s/\[(.?.?.?.?)$tagsubf(.*?)\]/$1$subfieldvalue$2\[$1$tagsubf$2\]/g;
+                }
+            }
+            push @stringssummary, $localsummary if ($localsummary ne $summary{summary});
         }
-      }
-         push @stringssummary, $localsummary if ($localsummary ne $summary);
+        my $resultstring;
+        $resultstring = join(" -- ",@stringssummary);
+        $resultstring =~ s/\[(.*?)\]//g;
+        $resultstring =~ s/\n/<br>/g;
+        $summary{summary}      =  $resultstring;
     }
-       my $resultstring;
-       $resultstring = join(" -- ",@stringssummary);
-    $resultstring =~ s/\[(.*?)\]//g;
-    $resultstring =~ s/\n/<br>/g;
-       $summary      =  $resultstring;
-  } else {
-    my $heading; 
-    my $altheading;
-    my $seealso;
-    my $broaderterms;
-    my $narrowerterms;
-    my $see;
-    my $seeheading;
-        my $notes;
-    my @fields = $record->fields();
+    my @authorized;
+    my @notes;
+    my @seefrom;
+    my @seealso;
+    my @otherscript;
     if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
-    # construct UNIMARC summary, that is quite different from MARC21 one
-      # accepted form
-      foreach my $field ($record->field('2..')) {
-        $heading.= $field->as_string('abcdefghijlmnopqrstuvwxyz');
-      }
-      # rejected form(s)
-      foreach my $field ($record->field('3..')) {
-        $notes.= '<span class="note">'.$field->subfield('a')."</span>\n";
-      }
-      foreach my $field ($record->field('4..')) {
-        if ($field->subfield('2')) {
-            my $thesaurus = "thes. : ".$thesaurus{"$field->subfield('2')"}." : ";
-            $see.= '<span class="UF">'.$thesaurus.$field->as_string('abcdefghijlmnopqrstuvwxyz')."</span> -- \n";
+# construct UNIMARC summary, that is quite different from MARC21 one
+# accepted form
+        foreach my $field ($record->field('2..')) {
+            push @authorized, { heading => $field->as_string('abcdefghijlmnopqrstuvwxyz'), field => $field->tag() };
         }
-      }
-      # see :
-      foreach my $field ($record->field('5..')) {
-            
-        if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) {
-          $broaderterms.= '<span class="BT"> '.$field->as_string('abcdefgjxyz')."</span> -- \n";
-        } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){
-          $narrowerterms.= '<span class="NT">'.$field->as_string('abcdefgjxyz')."</span> -- \n";
-        } elsif ($field->subfield('a')) {
-          $seealso.= '<span class="RT">'.$field->as_string('abcdefgxyz')."</a></span> -- \n";
+# rejected form(s)
+        foreach my $field ($record->field('3..')) {
+            push @notes, { note => $field->subfield('a'), field => $field->tag() };
         }
-      }
-      # // form
-      foreach my $field ($record->field('7..')) {
-        my $lang = substr($field->subfield('8'),3,3);
-        $seeheading.= '<span class="langue"> En '.$language{$lang}.' : </span><span class="OT"> '.$field->subfield('a')."</span><br />\n";  
-      }
-            $broaderterms =~s/-- \n$//;
-            $narrowerterms =~s/-- \n$//;
-            $seealso =~s/-- \n$//;
-            $see =~s/-- \n$//;
-      $summary = $heading."<br />".($notes?"$notes <br />":"");
-      $summary.= '<p><div class="label">TG : '.$broaderterms.'</div></p>' if ($broaderterms);
-      $summary.= '<p><div class="label">TS : '.$narrowerterms.'</div></p>' if ($narrowerterms);
-      $summary.= '<p><div class="label">TA : '.$seealso.'</div></p>' if ($seealso);
-      $summary.= '<p><div class="label">EP : '.$see.'</div></p>' if ($see);
-      $summary.= '<p><div class="label">'.$seeheading.'</div></p>' if ($seeheading);
-      } else {
-      # construct MARC21 summary
-          # FIXME - looping over 1XX is questionable
-          # since MARC21 authority should have only one 1XX
-          foreach my $field ($record->field('1..')) {
-              next if "152" eq $field->tag(); # FIXME - 152 is not a good tag to use
-                                              # in MARC21 -- purely local tags really ought to be
-                                              # 9XX
-              if ($record->field('100')) {
-                  $heading.= $field->as_string('abcdefghjklmnopqrstvxyz68');
-              } elsif ($record->field('110')) {
-                                      $heading.= $field->as_string('abcdefghklmnoprstvxyz68');
-              } elsif ($record->field('111')) {
-                                      $heading.= $field->as_string('acdefghklnpqstvxyz68');
-              } elsif ($record->field('130')) {
-                                      $heading.= $field->as_string('adfghklmnoprstvxyz68');
-              } elsif ($record->field('148')) {
-                                      $heading.= $field->as_string('abvxyz68');
-              } elsif ($record->field('150')) {
-          #    $heading.= $field->as_string('abvxyz68');
-          $heading.= $field->as_formatted();
-              my $tag=$field->tag();
-              $heading=~s /^$tag//g;
-              $heading =~s /\_/\$/g;
-              } elsif ($record->field('151')) {
-                                      $heading.= $field->as_string('avxyz68');
-              } elsif ($record->field('155')) {
-                                      $heading.= $field->as_string('abvxyz68');
-              } elsif ($record->field('180')) {
-                                      $heading.= $field->as_string('vxyz68');
-              } elsif ($record->field('181')) {
-                                      $heading.= $field->as_string('vxyz68');
-              } elsif ($record->field('182')) {
-                                      $heading.= $field->as_string('vxyz68');
-              } elsif ($record->field('185')) {
-                                      $heading.= $field->as_string('vxyz68');
-              } else {
-                  $heading.= $field->as_string();
-              }
-          } #See From
-          foreach my $field ($record->field('4..')) {
-              $seeheading.= "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>used for/see from:</i> ".$field->as_string();
-          } #See Also
-          foreach my $field ($record->field('5..')) {
-              $altheading.= "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>see also:</i> ".$field->as_string();
-          }
-          $summary .= ": " if $summary;
-          $summary.=$heading.$seeheading.$altheading;
-      }
-  }
-  return $summary;
+        foreach my $field ($record->field('4..')) {
+            my $thesaurus = $field->subfield('2') ? "thes. : ".$thesaurus{"$field->subfield('2')"}." : " : '';
+            push @seefrom, { heading => $thesaurus . $field->as_string('abcdefghijlmnopqrstuvwxyz'), type => 'seefrom', field => $field->tag() };
+        }
+# see :
+        foreach my $field ($record->field('5..')) {
+            if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) {
+                push @seealso, { $field->as_string('abcdefgjxyz'), type => 'broader', field => $field->tag() };
+            } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){
+                push @seealso, { heading => $field->as_string('abcdefgjxyz'), type => 'narrower', field => $field->tag() };
+            } elsif ($field->subfield('a')) {
+                push @seealso, { heading => $field->as_string('abcdefgxyz'), type => 'seealso', field => $field->tag() };
+            }
+        }
+# // form
+        foreach my $field ($record->field('7..')) {
+            my $lang = substr($field->subfield('8'),3,3);
+            push @otherscript, { lang => $lang, term => $field->subfield('a'), direction => 'ltr', field => $field->tag() };
+        }
+    } else {
+# construct MARC21 summary
+# FIXME - looping over 1XX is questionable
+# since MARC21 authority should have only one 1XX
+        my $subfields_to_report;
+        foreach my $field ($record->field('1..')) {
+            my $tag = $field->tag();
+            next if "152" eq $tag;
+# FIXME - 152 is not a good tag to use
+# in MARC21 -- purely local tags really ought to be
+# 9XX
+            if ($tag eq '100') {
+                $subfields_to_report = 'abcdefghjklmnopqrstvxyz';
+            } elsif ($tag eq '110') {
+                $subfields_to_report = 'abcdefghklmnoprstvxyz';
+            } elsif ($tag eq '111') {
+                $subfields_to_report = 'acdefghklnpqstvxyz';
+            } elsif ($tag eq '130') {
+                $subfields_to_report = 'adfghklmnoprstvxyz';
+            } elsif ($tag eq '148') {
+                $subfields_to_report = 'abvxyz';
+            } elsif ($tag eq '150') {
+                $subfields_to_report = 'abvxyz';
+            } elsif ($tag eq '151') {
+                $subfields_to_report = 'avxyz';
+            } elsif ($tag eq '155') {
+                $subfields_to_report = 'abvxyz';
+            } elsif ($tag eq '180') {
+                $subfields_to_report = 'vxyz';
+            } elsif ($tag eq '181') {
+                $subfields_to_report = 'vxyz';
+            } elsif ($tag eq '182') {
+                $subfields_to_report = 'vxyz';
+            } elsif ($tag eq '185') {
+                $subfields_to_report = 'vxyz';
+            }
+            if ($subfields_to_report) {
+                push @authorized, { heading => $field->as_string($subfields_to_report), field => $tag };
+            } else {
+                push @authorized, { heading => $field->as_string(), field => $tag };
+            }
+        }
+        foreach my $field ($record->field('4..')) { #See From
+            my $type = 'seefrom';
+            $type = $marc21controlrefs{substr $field->subfield('w'), 0, 1} if ($field->subfield('w'));
+            if ($type eq 'notapplicable') {
+                $type = substr $field->subfield('w'), 2, 1;
+                $type = 'earlier' if $type && $type ne 'n';
+            }
+            if ($type eq 'subfi') {
+                push @seefrom, { heading => $field->as_string($marc21subfields), type => $field->subfield('i'), field => $field->tag() };
+            } else {
+                push @seefrom, { heading => $field->as_string($marc21subfields), type => $type, field => $field->tag() };
+            }
+        }
+        foreach my $field ($record->field('5..')) { #See Also
+            my $type = 'seealso';
+            $type = $marc21controlrefs{substr $field->subfield('w'), 0, 1} if ($field->subfield('w'));
+            if ($type eq 'notapplicable') {
+                $type = substr $field->subfield('w'), 2, 1;
+                $type = 'earlier' if $type && $type ne 'n';
+            }
+            if ($type eq 'subfi') {
+                push @seealso, { heading => $field->as_string($marc21subfields), type => $field->subfield('i'), field => $field->tag() };
+            } else {
+                push @seealso, { heading => $field->as_string($marc21subfields), type => $type, field => $field->tag() };
+            }
+        }
+        foreach my $field ($record->field('6..')) {
+            push @notes, { note => $field->as_string(), field => $field->tag() };
+        }
+        foreach my $field ($record->field('880')) {
+            my $linkage = $field->subfield('6');
+            my $category = substr $linkage, 0, 1;
+            if ($category eq '1') {
+                $category = 'preferred';
+            } elsif ($category eq '4') {
+                $category = 'seefrom';
+            } elsif ($category eq '5') {
+                $category = 'seealso';
+            }
+            my $type;
+            if ($field->subfield('w')) {
+                $type = $marc21controlrefs{substr $field->subfield('w'), '0'};
+            } else {
+                $type = $category;
+            }
+            my $direction = $linkage =~ m#/r$# ? 'rtl' : 'ltr';
+            push @otherscript, { term => $field->as_string($subfields_to_report), category => $category, type => $type, direction => $direction, linkage => $linkage };
+        }
+    }
+    $summary{mainentry} = $authorized[0]->{heading};
+    $summary{authorized} = \@authorized;
+    $summary{notes} = \@notes;
+    $summary{seefrom} = \@seefrom;
+    $summary{seealso} = \@seealso;
+    $summary{otherscript} = \@otherscript;
+    return \%summary;
 }
 
 =head2 BuildUnimarcHierarchies
@@ -1307,6 +1340,7 @@ sub merge {
     } else {
         #zebra connection  
         my $oConnection=C4::Context->Zconn("biblioserver",0);
+        my $oldSyntax = $oConnection->option("preferredRecordSyntax");
         $oConnection->option("preferredRecordSyntax"=>"XML");
         my $query;
         $query= "an=".$mergefrom;
@@ -1320,10 +1354,15 @@ sub merge {
             my $rec;
             $rec=$oResult->record($z);
             my $marcdata = $rec->raw();
-            push @reccache, $marcdata;
+            my $marcrecordzebra= MARC::Record->new_from_xml($marcdata,"utf8",C4::Context->preference("marcflavour"));
+            my ( $biblionumbertagfield, $biblionumbertagsubfield ) = &GetMarcFromKohaField( "biblio.biblionumber", '' );
+            my $i = $marcrecordzebra->subfield($biblionumbertagfield, $biblionumbertagsubfield);
+            my $marcrecorddb=GetMarcBiblio($i);
+            push @reccache, $marcrecorddb;
             $z++;
         }
-        $oConnection->destroy();    
+        $oResult->destroy();
+        $oConnection->option("preferredRecordSyntax"=>$oldSyntax);
     }
     #warn scalar(@reccache)." biblios to update";
     # Get All candidate Tags for the change 
@@ -1345,7 +1384,6 @@ sub merge {
     # May be used as a template for a bulkedit field  
     foreach my $marcrecord(@reccache){
         my $update;           
-        $marcrecord= MARC::Record->new_from_xml($marcrecord,"utf8",C4::Context->preference("marcflavour")) unless(C4::Context->preference('NoZebra'));
         foreach my $tagfield (@tags_using_authtype){
 #             warn "tagfield : $tagfield ";
             foreach my $field ($marcrecord->field($tagfield)){
@@ -1459,7 +1497,7 @@ sub get_auth_type_location {
     my $auth_type_code = @_ ? shift : '';
 
     my ($tag, $subfield) = GetAuthMARCFromKohaField('auth_header.authtypecode', $auth_type_code);
-    if (defined $tag and defined $subfield and $tag != 0 and $subfield != 0) {
+    if (defined $tag and defined $subfield and $tag != 0 and $subfield ne '' and $subfield ne ' ') {
         return ($tag, $subfield);
     } else {
         if (C4::Context->preference('marcflavour') eq "MARC21")  {