Able to call haspermission w/o $dbh, and add error msg on deletemember.
[koha.git] / C4 / Biblio.pm
old mode 100644 (file)
new mode 100755 (executable)
index f0257fc..83ddd6d
@@ -258,7 +258,7 @@ sub AddItem {
     $sth =
       $dbh->prepare(
         "SELECT notforloan FROM itemtypes WHERE itemtype=?");
-    $sth->execute( C4::Context->preference('item-level_itype') ? $item->{'ccode'} : $itemtype );
+    $sth->execute( C4::Context->preference('item-level_itypes') ? $item->{'itype'} : $itemtype );
     my $notforloan = $sth->fetchrow;
     ##Change the notforloan field if $notforloan found
     if ( $notforloan > 0 ) {
@@ -465,14 +465,22 @@ sub ModItemInMarconefield {
 
     my $record = GetMarcItem( $biblionumber, $itemnumber );
     my ($tagfield, $tagsubfield) = GetMarcFromKohaField( $itemfield,'');
-    if ($tagfield && $tagsubfield) {
+    # FIXME - the condition is done this way because GetMarcFromKohaField
+    # returns (0, 0) if it can't field a MARC tag for the kohafield.  However,
+    # some fields like items.wthdrawn are mapped to subfield $0, making the
+    # customary test of "if ($tagfield && $tagsubfield)" incorrect.
+    # GetMarcFromKohaField should probably be returning (undef, undef), making
+    # the correct test "if (defined $tagfield && defined $tagsubfield)", but
+    # this would be a large change and consequently deferred for after 3.0.
+    if (not(int($tagfield) == 0 && int($tagsubfield) == 0)) { 
         my $tag = $record->field($tagfield);
         if ($tag) {
 #             my $tagsubs = $record->field($tagfield)->subfield($tagsubfield);
             $tag->update( $tagsubfield => $newvalue );
             $record->delete_field($tag);
             $record->insert_fields_ordered($tag);
-            &ModItemInMarc( $record, $biblionumber, $itemnumber, 0 );
+            my $frameworkcode = GetFrameworkCode( $biblionumber );
+            &ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode );
         }
     }
 }
@@ -481,7 +489,7 @@ sub ModItemInMarconefield {
 
 =over
 
-&ModItemInMarc( $record, $biblionumber, $itemnumber )
+&ModItemInMarc( $record, $biblionumber, $itemnumber, $frameworkcode )
 
 =back
 
@@ -563,7 +571,7 @@ sub DelBiblio {
     # - we need to read the biblio if NoZebra is set (to remove it from the indexes
     # - if something goes wrong, the biblio may be deleted from Koha but not from zebra
     #   and we would have no way to remove it (except manually in zebra, but I bet it would be very hard to handle the problem)
-    ModZebra($biblionumber, "delete_record", "biblioserver", undef);
+    ModZebra($biblionumber, "recordDelete", "biblioserver", undef);
 
     # delete biblioitems and items from Koha tables and save in deletedbiblioitems,deleteditems
     $sth =
@@ -652,14 +660,21 @@ sub GetBiblioData {
     my ( $bibnum ) = @_;
     my $dbh = C4::Context->dbh;
 
-    my $query = "
-        SELECT * , biblioitems.notes AS bnotes, itemtypes.notforloan as bi_notforloan, biblio.notes
-        FROM biblio
+  #  my $query =  C4::Context->preference('item-level_itypes') ? 
+       #       " SELECT * , biblioitems.notes AS bnotes, biblio.notes
+    #          FROM biblio
+    #        LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
+    #          WHERE biblio.biblionumber = ?
+    #        AND biblioitems.biblionumber = biblio.biblionumber
+    #";
+       
+       my $query = " SELECT * , biblioitems.notes AS bnotes, itemtypes.notforloan as bi_notforloan, biblio.notes
+               FROM biblio
             LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
             LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
-        WHERE biblio.biblionumber = ?
-            AND biblioitems.biblionumber = biblio.biblionumber
-    ";
+               WHERE biblio.biblionumber = ?
+            AND biblioitems.biblionumber = biblio.biblionumber ";
+                
     my $sth = $dbh->prepare($query);
     $sth->execute($bibnum);
     my $data;
@@ -726,25 +741,25 @@ sub GetItemsInfo {
     my $query = "SELECT *,items.notforloan as itemnotforloan
                  FROM items 
                  LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
-                 LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
-                 LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype
-                WHERE items.biblionumber = ?
-                ORDER BY items.dateaccessioned desc
-                 ";
+                 LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber";
+       $query .=  (C4::Context->preference('item-level_itypes')) ?
+                                        " LEFT JOIN itemtypes on items.itype = itemtypes.itemtype "
+                                       : " LEFT JOIN itemtypes on biblioitems.itemtype = itemtypes.itemtype ";
+       $query .= "WHERE items.biblionumber = ? ORDER BY items.dateaccessioned desc" ;
     my $sth = $dbh->prepare($query);
     $sth->execute($biblionumber);
     my $i = 0;
     my @results;
     my ( $date_due, $count_reserves );
 
+    my $isth    = $dbh->prepare(
+        "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname,borrowers.branchcode as bcode
+        FROM   issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber
+        WHERE  itemnumber = ?
+            AND returndate IS NULL"
+       );
     while ( my $data = $sth->fetchrow_hashref ) {
         my $datedue = '';
-        my $isth    = $dbh->prepare(
-            "SELECT issues.*,borrowers.cardnumber,borrowers.surname,borrowers.firstname
-            FROM   issues LEFT JOIN borrowers ON issues.borrowernumber=borrowers.borrowernumber
-            WHERE  itemnumber = ?
-                AND returndate IS NULL"
-        );
         $isth->execute( $data->{'itemnumber'} );
         if ( my $idata = $isth->fetchrow_hashref ) {
             $data->{borrowernumber} = $idata->{borrowernumber};
@@ -752,13 +767,18 @@ sub GetItemsInfo {
             $data->{surname}     = $idata->{surname};
             $data->{firstname}     = $idata->{firstname};
             $datedue                = format_date( $idata->{'date_due'} );
+           if (C4::Context->preference("IndependantBranches")){
+               my $userenv = C4::Context->userenv;
+               if ( ($userenv) && ( $userenv->{flags} != 1 ) ) { 
+                   $data->{'NOTSAMEBRANCH'} = 1 if ($idata->{'bcode'} ne $userenv->{branch});
+               }
+           }
         }
         if ( $datedue eq '' ) {
             #$datedue="Available";
             my ( $restype, $reserves ) =
               C4::Reserves::CheckReserves( $data->{'itemnumber'} );
             if ($restype) {
-
                 #$datedue=$restype;
                 $count_reserves = $restype;
             }
@@ -1135,13 +1155,14 @@ that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
 sub GetBiblioItemData {
     my ($biblioitemnumber) = @_;
     my $dbh       = C4::Context->dbh;
-    my $sth       =
-      $dbh->prepare(
-       "SELECT *,biblioitems.notes AS bnotes
-               FROM biblioitems,biblio,itemtypes 
-       WHERE biblio.biblionumber = biblioitems.biblionumber 
-               AND biblioitemnumber = ? "
-      );
+       my $query = "SELECT *,biblioitems.notes AS bnotes
+               FROM biblio, biblioitems ";
+       unless(C4::Context->preference('item-level_itypes')) { 
+               $query .= "LEFT JOIN itemtypes on biblioitems.itemtype=itemtypes.itemtype ";
+       }        
+       $query .= " WHERE biblio.biblionumber = biblioitems.biblionumber 
+               AND biblioitemnumber = ? ";
+    my $sth       =  $dbh->prepare($query);
     my $data;
     $sth->execute($biblioitemnumber);
     $data = $sth->fetchrow_hashref;
@@ -1201,9 +1222,9 @@ sub GetBiblioItemByBiblioNumber {
 
 =over 4
 
-$item = &GetBiblioFromItemNumber($itemnumber);
+$item = &GetBiblioFromItemNumber($itemnumber,$barcode);
 
-Looks up the item with the given itemnumber.
+Looks up the item with the given itemnumber. if undef, try the barcode.
 
 C<&itemnodata> returns a reference-to-hash whose keys are the fields
 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
@@ -1215,16 +1236,22 @@ database.
 
 #'
 sub GetBiblioFromItemNumber {
-    my ( $itemnumber ) = @_;
+    my ( $itemnumber, $barcode ) = @_;
     my $dbh = C4::Context->dbh;
-    my $sth = $dbh->prepare(
-        "SELECT * FROM items 
-        LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
-        LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
-         WHERE items.itemnumber = ?"
-    );
-
-    $sth->execute($itemnumber);
+    my $sth;
+    if($itemnumber) {
+               $sth=$dbh->prepare(  "SELECT * FROM items 
+           LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+           LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+                WHERE items.itemnumber = ?") ; 
+       $sth->execute($itemnumber);
+       } else {
+               $sth=$dbh->prepare(  "SELECT * FROM items 
+           LEFT JOIN biblio ON biblio.biblionumber = items.biblionumber
+           LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
+                WHERE items.barcode = ?") ; 
+       $sth->execute($barcode);
+       }
     my $data = $sth->fetchrow_hashref;
     $sth->finish;
     return ($data);
@@ -1702,23 +1729,49 @@ Returns MARC::Record of the item passed in parameter.
 
 sub GetMarcItem {
     my ( $biblionumber, $itemnumber ) = @_;
-    my $dbh = C4::Context->dbh;
-    my $newrecord = MARC::Record->new();
-    my $marcflavour = C4::Context->preference('marcflavour');
-    
-    my $marcxml = GetXmlBiblio($biblionumber);
-    my $record = MARC::Record->new();
-    $record = MARC::Record::new_from_xml( $marcxml, "utf8", $marcflavour );
-    # now, find where the itemnumber is stored & extract only the item
-    my ( $itemnumberfield, $itemnumbersubfield ) =
-      GetMarcFromKohaField( 'items.itemnumber', '' );
-    my @fields = $record->field($itemnumberfield);
-    foreach my $field (@fields) {
-        if ( $field->subfield($itemnumbersubfield) eq $itemnumber ) {
-            $newrecord->insert_fields_ordered($field);
-        }
-    }
-    return $newrecord;
+
+    # GetMarcItem has been revised so that it does the following:
+    #  1. Gets the item information from the items table.
+    #  2. Converts it to a MARC field for storage in the bib record.
+    #
+    # The previous behavior was:
+    #  1. Get the bib record.
+    #  2. Return the MARC tag corresponding to the item record.
+    #
+    # The difference is that one treats the items row as authoritative,
+    # while the other treats the MARC representation as authoritative
+    # under certain circumstances.
+    #
+    # FIXME - a big one
+    #
+    # As of 2007-11-27, this change hopefully does not introduce
+    # any bugs.  However, it does mean that for code that uses
+    # ModItemInMarconefield to update one subfield (corresponding to
+    # an items column) is now less efficient.
+    #
+    # The API needs to be shifted to the following:
+    #  1. User updates items record.
+    #  2. Linked bib is sent for indexing.
+    # 
+    # The missing step 1.5 is updating the item tag in the bib MARC record
+    # so that the indexes are updated.  Depending on performance considerations,
+    # this may ultimately mean of of the following:
+    #  a. MARC field for item is updated right away.
+    #  b. MARC field for item is updated only as part of indexing.
+    #  c. MARC field for item is never actually stored in bib record; instead
+    #     it is generated only when needed for indexing, item export, and
+    #     (maybe) OPAC display.
+    #
+
+    my $itemrecord = GetItem($itemnumber);
+
+    # Tack on 'items.' prefix to column names so that TransformKohaToMarc will work.
+    # Also, don't emit a subfield if the underlying field is blank.
+    my $mungeditem = { map {  $itemrecord->{$_} ne '' ? ("items.$_" => $itemrecord->{$_}) : ()  } keys %{ $itemrecord } };
+
+    my $itemmarc = TransformKohaToMarc($mungeditem);
+    return $itemmarc;
+
 }
 
 
@@ -1802,6 +1855,8 @@ sub GetMarcSubjects {
         my @subfields = $field->subfields();
                my $counter = 0;
                my @link_loop;
+               # if there is an authority link, build the link with an= subfield9
+               my $subfield9 = $field->subfield('9');
                for my $subject_subfield (@subfields ) {
                        # don't load unimarc subfields 3,4,5
                        next if (($marcflavour eq "UNIMARC") and ($subject_subfield->[0] =~ (3|4|5) ) );
@@ -1810,7 +1865,11 @@ sub GetMarcSubjects {
                        my $linkvalue = $value;
                        $linkvalue =~ s/(\(|\))//g;
                        my $operator = " and " unless $counter==0;
-                       push @link_loop, {link => $linkvalue, operator => $operator };
+                       if ($subfield9) {
+                @link_loop = ({'limit' => 'an' ,link => "$subfield9" });
+            } else {
+                push @link_loop, {'limit' => 'su', link => $linkvalue, operator => $operator };
+            }
                        my $separator = C4::Context->preference("authoritysep") unless $counter==0;
                        # ignore $9
                        push @subfields_loop, {code => $code, value => $value, link_loop => \@link_loop, separator => $separator} unless ($subject_subfield->[0] == 9 );
@@ -1850,7 +1909,7 @@ sub GetMarcAuthors {
         $maxtag = "720"; 
     }
     elsif ( $marcflavour eq "UNIMARC" ) {    # assume unimarc if not marc21
-        $mintag = "701";
+        $mintag = "700";
         $maxtag = "712";
     }
        else {
@@ -2305,7 +2364,7 @@ sub TransformHtmlToMarc {
             if($tag < 10){ # no code for theses fields
     # in MARC editor, 000 contains the leader.
                 if ($tag eq '000' ) {
-                    $record->leader($cgi->param($params->[$j+1])) if length($cgi->param($params->[$j+1]))==25;
+                    $record->leader($cgi->param($params->[$j+1])) if length($cgi->param($params->[$j+1]))==24;
     # between 001 and 009 (included)
                 } else {
                     $newfield = MARC::Field->new(
@@ -2342,7 +2401,6 @@ sub TransformHtmlToMarc {
     }
     
     $record->append_fields(@fields);
-    warn "RESULT : ".$record->as_formatted;
     return $record;
 }
 
@@ -3067,10 +3125,13 @@ sub GetNoZebraIndexes {
     my %indexes;
     foreach my $line (split /('|"),/,$index) {
         $line =~ /(.*)=>(.*)/;
+warn $line;
         my $index = substr($1,1); # get the index, don't forget to remove initial ' or "
         my $fields = $2;
-        $index =~ s/'|"| //g;
-        $fields =~ s/'|"| //g;
+        $index =~ s/'|"|\s//g;
+
+
+        $fields =~ s/'|"|\s//g;
         $indexes{$index}=$fields;
     }
     return %indexes;
@@ -3776,9 +3837,13 @@ sub _koha_new_items {
             paidfor            = ?,
                        location                        = ?,
                        onloan                          = ?,
+                       issues                          = ?,
+                       renewals                        = ?,
+                       reserves                        = ?,
                        cn_source                       = ?,
                        cn_sort                         = ?,
                        ccode                           = ?,
+                       itype                           = ?,
                        materials                       = ?,
                        uri                             = ?
           ";
@@ -3805,9 +3870,13 @@ sub _koha_new_items {
                        $item->{'paidfor'},
                        $item->{'location'},
                        $item->{'onloan'},
+                       $item->{'issues'},
+                       $item->{'renewals'},
+                       $item->{'reserves'},
                        $item->{'items.cn_source'},
                        $items_cn_sort,
                        $item->{'ccode'},
+                       $item->{'itype'},
                        $item->{'materials'},
                        $item->{'uri'},
     );