Bug 7576: Add ISSN to SearchForTitleIn preference
[koha.git] / C4 / Biblio.pm
index 8d2dd9d..50830ec 100644 (file)
@@ -27,7 +27,6 @@ use Carp;
 use MARC::Record;
 use MARC::File::USMARC;
 use MARC::File::XML;
-use ZOOM;
 use POSIX qw(strftime);
 
 use C4::Koha;
@@ -35,9 +34,6 @@ use C4::Dates qw/format_date/;
 use C4::Log;    # logaction
 use C4::ClassSource;
 use C4::Charset;
-require C4::Heading;
-require C4::Serials;
-require C4::Items;
 
 use vars qw($VERSION @ISA @EXPORT);
 
@@ -74,6 +70,7 @@ BEGIN {
       &GetMarcControlnumber
       &GetMarcNotes
       &GetMarcISBN
+      &GetMarcISSN
       &GetMarcSubjects
       &GetMarcBiblio
       &GetMarcAuthors
@@ -131,23 +128,17 @@ BEGIN {
       &TransformHtmlToMarc2
       &TransformHtmlToMarc
       &TransformHtmlToXml
-      &PrepareItemrecordDisplay
       &GetNoZebraIndexes
     );
 }
 
 eval {
-    my $servers = C4::Context->config('memcached_servers');
-    if ($servers) {
+    if (C4::Context->ismemcached) {
         require Memoize::Memcached;
         import Memoize::Memcached qw(memoize_memcached);
 
-        my $memcached = {
-            servers     => [$servers],
-            key_prefix  => C4::Context->config('memcached_namespace') || 'koha',
-            expire_time => 600
-        }; # cache for 10 mins, if you want to cache for different make a different memcached hash
-        memoize_memcached( 'GetMarcStructure', memcached => $memcached );
+        memoize_memcached( 'GetMarcStructure',
+                            memcached => C4::Context->memcached);
     }
 };
 
@@ -418,9 +409,10 @@ sub DelBiblio {
     return $error if $error;
 
     # We delete attached subscriptions
-    my $subscriptions = &C4::Serials::GetFullSubscriptionsFromBiblionumber($biblionumber);
+    require C4::Serials;
+    my $subscriptions = C4::Serials::GetFullSubscriptionsFromBiblionumber($biblionumber);
     foreach my $subscription (@$subscriptions) {
-        &C4::Serials::DelSubscription( $subscription->{subscriptionid} );
+        C4::Serials::DelSubscription( $subscription->{subscriptionid} );
     }
 
     # Delete in Zebra. Be careful NOT to move this line after _koha_delete_biblio
@@ -478,6 +470,7 @@ MARC record.
 =cut
 
 sub LinkBibHeadingsToAuthorities {
+    require C4::Heading;
     my $bib = shift;
 
     my $num_headings_changed = 0;
@@ -1382,9 +1375,9 @@ Get the control number / record Identifier from the MARC record and return it.
 sub GetMarcControlnumber {
     my ( $record, $marcflavour ) = @_;
     my $controlnumber = "";
-    # Control number or Record identifier are the same field in MARC21 and UNIMARC
+    # Control number or Record identifier are the same field in MARC21, UNIMARC and NORMARC
     # Keep $marcflavour for possible later use
-    if ($marcflavour eq "MARC21" || $marcflavour eq "UNIMARC") {
+    if ($marcflavour eq "MARC21" || $marcflavour eq "UNIMARC" || $marcflavour eq "NORMARC") {
         my $controlnumberField = $record->field('001');
         if ($controlnumberField) {
             $controlnumber = $controlnumberField->data();
@@ -1398,7 +1391,7 @@ sub GetMarcControlnumber {
   $marcisbnsarray = GetMarcISBN( $record, $marcflavour );
 
 Get all ISBNs from the MARC record and returns them in an array.
-ISBNs stored in differents places depending on MARC flavour
+ISBNs stored in different fields depending on MARC flavour
 
 =cut
 
@@ -1433,12 +1426,38 @@ sub GetMarcISBN {
     return \@marcisbns;
 }    # end GetMarcISBN
 
+
+=head2 GetMarcISSN
+
+  $marcissnsarray = GetMarcISSN( $record, $marcflavour );
+
+Get all valid ISSNs from the MARC record and returns them in an array.
+ISSNs are stored in different fields depending on MARC flavour
+
+=cut
+
+sub GetMarcISSN {
+    my ( $record, $marcflavour ) = @_;
+    my $scope;
+    if ( $marcflavour eq "UNIMARC" ) {
+        $scope = '011';
+    }
+    else {    # assume MARC21 or NORMARC
+        $scope = '022';
+    }
+    my @marcissns;
+    foreach my $field ( $record->field($scope) ) {
+        push @marcissns, $field->subfield( 'a' );
+    }
+    return \@marcissns;
+}    # end GetMarcISSN
+
 =head2 GetMarcNotes
 
   $marcnotesarray = GetMarcNotes( $record, $marcflavour );
 
 Get all notes from the MARC record and returns them in an array.
-The note are stored in differents places depending on MARC flavour
+The note are stored in different fields depending on MARC flavour
 
 =cut
 
@@ -1478,7 +1497,7 @@ sub GetMarcNotes {
   $marcsubjcts = GetMarcSubjects($record,$marcflavour);
 
 Get all subjects from the MARC record and returns them in an array.
-The subjects are stored in differents places depending on MARC flavour
+The subjects are stored in different fields depending on MARC flavour
 
 =cut
 
@@ -1553,7 +1572,7 @@ sub GetMarcSubjects {
   authors = GetMarcAuthors($record,$marcflavour);
 
 Get all authors from the MARC record and returns them in an array.
-The authors are stored in differents places depending on MARC flavour
+The authors are stored in different fields depending on MARC flavour
 
 =cut
 
@@ -1690,7 +1709,7 @@ sub GetMarcUrls {
   $marcseriesarray = GetMarcSeries($record,$marcflavour);
 
 Get all series from the MARC record and returns them in an array.
-The series are stored in differents places depending on MARC flavour
+The series are stored in different fields depending on MARC flavour
 
 =cut
 
@@ -2450,232 +2469,6 @@ sub TransformMarcToKohaOneField {
     return $result;
 }
 
-=head1  OTHER FUNCTIONS
-
-
-=head2 PrepareItemrecordDisplay
-
-  PrepareItemrecordDisplay($itemrecord,$bibnum,$itemumber,$frameworkcode);
-
-Returns a hash with all the fields for Display a given item data in a template
-
-The $frameworkcode returns the item for the given frameworkcode, ONLY if bibnum is not provided
-
-=cut
-
-sub PrepareItemrecordDisplay {
-
-    my ( $bibnum, $itemnum, $defaultvalues, $frameworkcode ) = @_;
-
-    my $dbh = C4::Context->dbh;
-    $frameworkcode = &GetFrameworkCode($bibnum) if $bibnum;
-    my ( $itemtagfield, $itemtagsubfield ) = &GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
-    my $tagslib = &GetMarcStructure( 1, $frameworkcode );
-
-    # return nothing if we don't have found an existing framework.
-    return q{} unless $tagslib;
-    my $itemrecord;
-    if ($itemnum) {
-        $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum );
-    }
-    my @loop_data;
-    my $authorised_values_sth = $dbh->prepare( "SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib" );
-    foreach my $tag ( sort keys %{$tagslib} ) {
-        my $previous_tag = '';
-        if ( $tag ne '' ) {
-
-            # loop through each subfield
-            my $cntsubf;
-            foreach my $subfield ( sort keys %{ $tagslib->{$tag} } ) {
-                next if ( subfield_is_koha_internal_p($subfield) );
-                next if ( $tagslib->{$tag}->{$subfield}->{'tab'} ne "10" );
-                my %subfield_data;
-                $subfield_data{tag}           = $tag;
-                $subfield_data{subfield}      = $subfield;
-                $subfield_data{countsubfield} = $cntsubf++;
-                $subfield_data{kohafield}     = $tagslib->{$tag}->{$subfield}->{'kohafield'};
-
-                #        $subfield_data{marc_lib}=$tagslib->{$tag}->{$subfield}->{lib};
-                $subfield_data{marc_lib}   = $tagslib->{$tag}->{$subfield}->{lib};
-                $subfield_data{mandatory}  = $tagslib->{$tag}->{$subfield}->{mandatory};
-                $subfield_data{repeatable} = $tagslib->{$tag}->{$subfield}->{repeatable};
-                $subfield_data{hidden}     = "display:none"
-                  if $tagslib->{$tag}->{$subfield}->{hidden};
-                my ( $x, $defaultvalue );
-                if ($itemrecord) {
-                    ( $x, $defaultvalue ) = _find_value( $tag, $subfield, $itemrecord );
-                }
-                $defaultvalue = $tagslib->{$tag}->{$subfield}->{defaultvalue} unless $defaultvalue;
-                if ( !defined $defaultvalue ) {
-                    $defaultvalue = q||;
-                }
-                $defaultvalue =~ s/"/"/g;
-
-                # search for itemcallnumber if applicable
-                if ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.itemcallnumber'
-                    && C4::Context->preference('itemcallnumber') ) {
-                    my $CNtag      = substr( C4::Context->preference('itemcallnumber'), 0, 3 );
-                    my $CNsubfield = substr( C4::Context->preference('itemcallnumber'), 3, 1 );
-                    if ($itemrecord) {
-                        my $temp = $itemrecord->field($CNtag);
-                        if ($temp) {
-                            $defaultvalue = $temp->subfield($CNsubfield);
-                        }
-                    }
-                }
-                if (   $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.itemcallnumber'
-                    && $defaultvalues
-                    && $defaultvalues->{'callnumber'} ) {
-                    my $temp;
-                    if ($itemrecord) {
-                        $temp = $itemrecord->field($subfield);
-                    }
-                    unless ($temp) {
-                        $defaultvalue = $defaultvalues->{'callnumber'} if $defaultvalues;
-                    }
-                }
-                if (   ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.holdingbranch' || $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.homebranch' )
-                    && $defaultvalues
-                    && $defaultvalues->{'branchcode'} ) {
-                    my $temp;
-                    if ($itemrecord) {
-                        $temp = $itemrecord->field($subfield);
-                    }
-                    unless ($temp) {
-                        $defaultvalue = $defaultvalues->{branchcode} if $defaultvalues;
-                    }
-                }
-                if (   ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.location' )
-                    && $defaultvalues
-                    && $defaultvalues->{'location'} ) {
-                    my $temp = $itemrecord->field($subfield) if ($itemrecord);
-                    unless ($temp) {
-                        $defaultvalue = $defaultvalues->{location} if $defaultvalues;
-                    }
-                }
-                if ( $tagslib->{$tag}->{$subfield}->{authorised_value} ) {
-                    my @authorised_values;
-                    my %authorised_lib;
-
-                    # builds list, depending on authorised value...
-                    #---- branch
-                    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
-                        if (   ( C4::Context->preference("IndependantBranches") )
-                            && ( C4::Context->userenv->{flags} % 2 != 1 ) ) {
-                            my $sth = $dbh->prepare( "SELECT branchcode,branchname FROM branches WHERE branchcode = ? ORDER BY branchname" );
-                            $sth->execute( C4::Context->userenv->{branch} );
-                            push @authorised_values, ""
-                              unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
-                            while ( my ( $branchcode, $branchname ) = $sth->fetchrow_array ) {
-                                push @authorised_values, $branchcode;
-                                $authorised_lib{$branchcode} = $branchname;
-                            }
-                        } else {
-                            my $sth = $dbh->prepare( "SELECT branchcode,branchname FROM branches ORDER BY branchname" );
-                            $sth->execute;
-                            push @authorised_values, ""
-                              unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
-                            while ( my ( $branchcode, $branchname ) = $sth->fetchrow_array ) {
-                                push @authorised_values, $branchcode;
-                                $authorised_lib{$branchcode} = $branchname;
-                            }
-                        }
-
-                        #----- itemtypes
-                    } elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) {
-                        my $sth = $dbh->prepare( "SELECT itemtype,description FROM itemtypes ORDER BY description" );
-                        $sth->execute;
-                        push @authorised_values, ""
-                          unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
-                        while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) {
-                            push @authorised_values, $itemtype;
-                            $authorised_lib{$itemtype} = $description;
-                        }
-                        #---- class_sources
-                    } elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "cn_source" ) {
-                        push @authorised_values, "" unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
-
-                        my $class_sources = GetClassSources();
-                        my $default_source = C4::Context->preference("DefaultClassificationSource");
-
-                        foreach my $class_source (sort keys %$class_sources) {
-                            next unless $class_sources->{$class_source}->{'used'} or
-                                        ($class_source eq $default_source);
-                            push @authorised_values, $class_source;
-                            $authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'};
-                        }
-
-                        #---- "true" authorised value
-                    } else {
-                        $authorised_values_sth->execute( $tagslib->{$tag}->{$subfield}->{authorised_value} );
-                        push @authorised_values, ""
-                          unless ( $tagslib->{$tag}->{$subfield}->{mandatory} );
-                        while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) {
-                            push @authorised_values, $value;
-                            $authorised_lib{$value} = $lib;
-                        }
-                    }
-                    $subfield_data{marc_value} = CGI::scrolling_list(
-                        -name     => 'field_value',
-                        -values   => \@authorised_values,
-                        -default  => "$defaultvalue",
-                        -labels   => \%authorised_lib,
-                        -size     => 1,
-                        -tabindex => '',
-                        -multiple => 0,
-                    );
-                } elsif ( $tagslib->{$tag}->{$subfield}->{value_builder} ) {
-                        # opening plugin
-                        my $plugin = C4::Context->intranetdir . "/cataloguing/value_builder/" . $tagslib->{$tag}->{$subfield}->{'value_builder'};
-                        if (do $plugin) {
-                            my $temp;
-                            my $extended_param = plugin_parameters( $dbh, $temp, $tagslib, $subfield_data{id}, undef );
-                            my ( $function_name, $javascript ) = plugin_javascript( $dbh, $temp, $tagslib, $subfield_data{id}, undef );
-                            $subfield_data{random}     = int(rand(1000000));    # why do we need 2 different randoms?
-                            my $index_subfield = int(rand(1000000));
-                            $subfield_data{id} = "tag_".$tag."_subfield_".$subfield."_".$index_subfield;
-                            $subfield_data{marc_value} = qq[<input tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255"
-                                onfocus="Focus$function_name($subfield_data{random}, '$subfield_data{id}');"
-                                 onblur=" Blur$function_name($subfield_data{random}, '$subfield_data{id}');" />
-                                <a href="#" class="buttonDot" onclick="Clic$function_name('$subfield_data{id}'); return false;" title="Tag Editor">...</a>
-                                $javascript];
-                        } else {
-                            warn "Plugin Failed: $plugin";
-                            $subfield_data{marc_value} = qq(<input tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" />); # supply default input form
-                        }
-                }
-                elsif ( $tag eq '' ) {       # it's an hidden field
-                    $subfield_data{marc_value} = qq(<input type="hidden" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" value="$defaultvalue" />);
-                }
-                elsif ( $tagslib->{$tag}->{$subfield}->{'hidden'} ) {   # FIXME: shouldn't input type be "hidden" ?
-                    $subfield_data{marc_value} = qq(<input type="text" tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255" value="$defaultvalue" />);
-                }
-                elsif ( length($defaultvalue) > 100
-                            or (C4::Context->preference("marcflavour") eq "UNIMARC" and
-                                  300 <= $tag && $tag < 400 && $subfield eq 'a' )
-                            or (C4::Context->preference("marcflavour") eq "MARC21"  and
-                                  500 <= $tag && $tag < 600                     )
-                          ) {
-                    # oversize field (textarea)
-                    $subfield_data{marc_value} = qq(<textarea tabindex="1" id="$subfield_data{id}" name="field_value" class="input_marceditor" size="67" maxlength="255">$defaultvalue</textarea>\n");
-                } else {
-                    $subfield_data{marc_value} = "<input type=\"text\" name=\"field_value\" value=\"$defaultvalue\" size=\"50\" maxlength=\"255\" />";
-                }
-                push( @loop_data, \%subfield_data );
-            }
-        }
-    }
-    my $itemnumber;
-    if ( $itemrecord && $itemrecord->field($itemtagfield) ) {
-        $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield );
-    }
-    return {
-        'itemtagfield'    => $itemtagfield,
-        'itemtagsubfield' => $itemtagsubfield,
-        'itemnumber'      => $itemnumber,
-        'iteminformation' => \@loop_data
-    };
-}
 
 #"
 
@@ -2839,6 +2632,7 @@ sub EmbedItemsInMarcBiblio {
     my @item_fields;
     my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
     while (my ($itemnumber) = $sth->fetchrow_array) {
+        require C4::Items;
         my $item_marc = C4::Items::GetMarcItem($biblionumber, $itemnumber);
         push @item_fields, $item_marc->field($itemtag);
     }
@@ -3109,45 +2903,6 @@ sub _AddBiblioNoZebra {
     return %result;
 }
 
-=head2 _find_value
-
-  ($indicators, $value) = _find_value($tag, $subfield, $record,$encoding);
-
-Find the given $subfield in the given $tag in the given
-MARC::Record $record.  If the subfield is found, returns
-the (indicators, value) pair; otherwise, (undef, undef) is
-returned.
-
-PROPOSITION :
-Such a function is used in addbiblio AND additem and serial-edit and maybe could be used in Authorities.
-I suggest we export it from this module.
-
-=cut
-
-sub _find_value {
-    my ( $tagfield, $insubfield, $record, $encoding ) = @_;
-    my @result;
-    my $indicator;
-    if ( $tagfield < 10 ) {
-        if ( $record->field($tagfield) ) {
-            push @result, $record->field($tagfield)->data();
-        } else {
-            push @result, "";
-        }
-    } else {
-        foreach my $field ( $record->field($tagfield) ) {
-            my @subfields = $field->subfields();
-            foreach my $subfield (@subfields) {
-                if ( @$subfield[0] eq $insubfield ) {
-                    push @result, @$subfield[1];
-                    $indicator = $field->indicator(1) . $field->indicator(2);
-                }
-            }
-        }
-    }
-    return ( $indicator, @result );
-}
-
 =head2 _koha_marc_update_bib_ids
 
 
@@ -3632,112 +3387,6 @@ sub ModBiblioMarc {
     return $biblionumber;
 }
 
-=head2 z3950_extended_services
-
-  z3950_extended_services($serviceType,$serviceOptions,$record);
-
-z3950_extended_services is used to handle all interactions with Zebra's extended serices package, which is employed to perform all management of the MARC data stored in Zebra.
-
-C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
-
-C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
-
- action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
-
-and maybe
-
-  recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
-  syntax => the record syntax (transfer syntax)
-  databaseName = Database from connection object
-
-To set serviceOptions, call set_service_options($serviceType)
-
-C<$record> the record, if one is needed for the service type
-
-A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
-
-=cut
-
-sub z3950_extended_services {
-    my ( $server, $serviceType, $action, $serviceOptions ) = @_;
-
-    # get our connection object
-    my $Zconn = C4::Context->Zconn( $server, 0, 1 );
-
-    # create a new package object
-    my $Zpackage = $Zconn->package();
-
-    # set our options
-    $Zpackage->option( action => $action );
-
-    if ( $serviceOptions->{'databaseName'} ) {
-        $Zpackage->option( databaseName => $serviceOptions->{'databaseName'} );
-    }
-    if ( $serviceOptions->{'recordIdNumber'} ) {
-        $Zpackage->option( recordIdNumber => $serviceOptions->{'recordIdNumber'} );
-    }
-    if ( $serviceOptions->{'recordIdOpaque'} ) {
-        $Zpackage->option( recordIdOpaque => $serviceOptions->{'recordIdOpaque'} );
-    }
-
-    # this is an ILL request (Zebra doesn't support it, but Koha could eventually)
-    #if ($serviceType eq 'itemorder') {
-    #   $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
-    #   $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
-    #   $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
-    #   $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
-    #}
-
-    if ( $serviceOptions->{record} ) {
-        $Zpackage->option( record => $serviceOptions->{record} );
-
-        # can be xml or marc
-        if ( $serviceOptions->{'syntax'} ) {
-            $Zpackage->option( syntax => $serviceOptions->{'syntax'} );
-        }
-    }
-
-    # send the request, handle any exception encountered
-    eval { $Zpackage->send($serviceType) };
-    if ( $@ && $@->isa("ZOOM::Exception") ) {
-        return "error:  " . $@->code() . " " . $@->message() . "\n";
-    }
-
-    # free up package resources
-    $Zpackage->destroy();
-}
-
-=head2 set_service_options
-
-  my $serviceOptions = set_service_options($serviceType);
-
-C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
-
-Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
-
-=cut
-
-sub set_service_options {
-    my ($serviceType) = @_;
-    my $serviceOptions;
-
-    # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
-    #   $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
-
-    if ( $serviceType eq 'commit' ) {
-
-        # nothing to do
-    }
-    if ( $serviceType eq 'create' ) {
-
-        # nothing to do
-    }
-    if ( $serviceType eq 'drop' ) {
-        die "ERROR: 'drop' not currently supported (by Zebra)";
-    }
-    return $serviceOptions;
-}
-
 =head2 get_biblio_authorised_values
 
 find the types and values for all authorised values assigned to this biblio.