Bug 5549 : fixed datetime issue so time is shown in output for circulation.pl and...
[koha_gimpoz] / C4 / Items.pm
index 23eb1eb..676c91b 100644 (file)
@@ -29,10 +29,6 @@ use C4::Dates qw/format_date format_date_in_iso/;
 use MARC::Record;
 use C4::ClassSource;
 use C4::Log;
 use MARC::Record;
 use C4::ClassSource;
 use C4::Log;
-use C4::Branch;
-require C4::Reserves;
-use C4::Charset;
-use C4::Acquisition;
 use List::MoreUtils qw/any/;
 use Data::Dumper; # used as part of logging item record changes, not just for
                   # debugging; so please don't remove this
 use List::MoreUtils qw/any/;
 use Data::Dumper; # used as part of logging item record changes, not just for
                   # debugging; so please don't remove this
@@ -74,14 +70,18 @@ BEGIN {
        get_hostitemnumbers_of
         GetItemnumberFromBarcode
         GetBarcodeFromItemnumber
        get_hostitemnumbers_of
         GetItemnumberFromBarcode
         GetBarcodeFromItemnumber
-      GetHiddenItemnumbers
-
+        GetHiddenItemnumbers
                DelItemCheck
                MoveItemFromBiblio 
                GetLatestAcquisitions
         CartToShelf
 
        GetAnalyticsCount
                DelItemCheck
                MoveItemFromBiblio 
                GetLatestAcquisitions
         CartToShelf
 
        GetAnalyticsCount
+        GetItemHolds
+
+
+        PrepareItemrecordDisplay
+
     );
 }
 
     );
 }
 
@@ -401,6 +401,8 @@ Note that only columns that can be directly
 changed from the cataloging and serials
 item editors are included in this hash.
 
 changed from the cataloging and serials
 item editors are included in this hash.
 
+Returns item record
+
 =cut
 
 my %default_values_for_mod_from_marc = (
 =cut
 
 my %default_values_for_mod_from_marc = (
@@ -450,13 +452,13 @@ sub ModItemFromMarc {
     }
     my $unlinked_item_subfields = _get_unlinked_item_subfields( $localitemmarc, $frameworkcode );
 
     }
     my $unlinked_item_subfields = _get_unlinked_item_subfields( $localitemmarc, $frameworkcode );
 
-    return ModItem($item, $biblionumber, $itemnumber, $dbh, $frameworkcode, $unlinked_item_subfields); 
+    ModItem($item, $biblionumber, $itemnumber, $dbh, $frameworkcode, $unlinked_item_subfields); 
+    return $item;
 }
 
 =head2 ModItem
 
 }
 
 =head2 ModItem
 
-  ModItem({ column => $newvalue }, $biblionumber, 
-                  $itemnumber[, $original_item_marc]);
+  ModItem({ column => $newvalue }, $biblionumber, $itemnumber);
 
 Change one or more columns in an item record and update
 the MARC representation of the item.
 
 Change one or more columns in an item record and update
 the MARC representation of the item.
@@ -499,6 +501,9 @@ sub ModItem {
     };
 
     $item->{'itemnumber'} = $itemnumber or return undef;
     };
 
     $item->{'itemnumber'} = $itemnumber or return undef;
+
+    $item->{onloan} = undef if $item->{itemlost};
+
     _set_derived_columns_for_mod($item);
     _do_column_fixes_for_mod($item);
     # FIXME add checks
     _set_derived_columns_for_mod($item);
     _do_column_fixes_for_mod($item);
     # FIXME add checks
@@ -581,6 +586,7 @@ sub DelItem {
     # backup the record
     my $copy2deleted = $dbh->prepare("UPDATE deleteditems SET marc=? WHERE itemnumber=?");
     $copy2deleted->execute( $record->as_usmarc(), $itemnumber );
     # backup the record
     my $copy2deleted = $dbh->prepare("UPDATE deleteditems SET marc=? WHERE itemnumber=?");
     $copy2deleted->execute( $record->as_usmarc(), $itemnumber );
+    # This last update statement makes that the timestamp column in deleteditems is updated too. If you remove these lines, please add a line to update the timestamp separately. See Bugzilla report 7146 and Biblio.pm (DelBiblio).
 
     #search item field code
     logaction("CATALOGUING", "DELETE", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
 
     #search item field code
     logaction("CATALOGUING", "DELETE", $itemnumber, "item") if C4::Context->preference("CataloguingLog");
@@ -630,6 +636,7 @@ item that has a given branch code.
 
 sub CheckItemPreSave {
     my $item_ref = shift;
 
 sub CheckItemPreSave {
     my $item_ref = shift;
+    require C4::Branch;
 
     my %errors = ();
 
 
     my %errors = ();
 
@@ -646,7 +653,7 @@ sub CheckItemPreSave {
 
     # check for valid home branch
     if (exists $item_ref->{'homebranch'} and defined $item_ref->{'homebranch'}) {
 
     # check for valid home branch
     if (exists $item_ref->{'homebranch'} and defined $item_ref->{'homebranch'}) {
-        my $branch_name = GetBranchName($item_ref->{'homebranch'});
+        my $branch_name = C4::Branch::GetBranchName($item_ref->{'homebranch'});
         unless (defined $branch_name) {
             # relies on fact that branches.branchname is a non-NULL column,
             # so GetBranchName returns undef only if branch does not exist
         unless (defined $branch_name) {
             # relies on fact that branches.branchname is a non-NULL column,
             # so GetBranchName returns undef only if branch does not exist
@@ -656,7 +663,7 @@ sub CheckItemPreSave {
 
     # check for valid holding branch
     if (exists $item_ref->{'holdingbranch'} and defined $item_ref->{'holdingbranch'}) {
 
     # check for valid holding branch
     if (exists $item_ref->{'holdingbranch'} and defined $item_ref->{'holdingbranch'}) {
-        my $branch_name = GetBranchName($item_ref->{'holdingbranch'});
+        my $branch_name = C4::Branch::GetBranchName($item_ref->{'holdingbranch'});
         unless (defined $branch_name) {
             # relies on fact that branches.branchname is a non-NULL column,
             # so GetBranchName returns undef only if branch does not exist
         unless (defined $branch_name) {
             # relies on fact that branches.branchname is a non-NULL column,
             # so GetBranchName returns undef only if branch does not exist
@@ -1178,14 +1185,15 @@ sub GetItemsInfo {
            items.notforloan as itemnotforloan,
            itemtypes.description,
            itemtypes.notforloan as notforloan_per_itemtype,
            items.notforloan as itemnotforloan,
            itemtypes.description,
            itemtypes.notforloan as notforloan_per_itemtype,
-           branchurl
+           holding.branchurl
      FROM items
      FROM items
-     LEFT JOIN branches ON items.holdingbranch = branches.branchcode
+     LEFT JOIN branches AS holding ON items.holdingbranch = holding.branchcode
+     LEFT JOIN branches AS home ON items.homebranch=home.branchcode
      LEFT JOIN biblio      ON      biblio.biblionumber     = items.biblionumber
      LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
      LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
      . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
      LEFT JOIN biblio      ON      biblio.biblionumber     = items.biblionumber
      LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
      LEFT JOIN itemtypes   ON   itemtypes.itemtype         = "
      . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype');
-    $query .= " WHERE items.biblionumber = ? ORDER BY branches.branchname,items.dateaccessioned desc" ;
+    $query .= " WHERE items.biblionumber = ? ORDER BY home.branchname,items.dateaccessioned desc" ;
     my $sth = $dbh->prepare($query);
     $sth->execute($biblionumber);
     my $i = 0;
     my $sth = $dbh->prepare($query);
     $sth->execute($biblionumber);
     my $i = 0;
@@ -1200,13 +1208,13 @@ sub GetItemsInfo {
        my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=? "); 
        while ( my $data = $sth->fetchrow_hashref ) {
         my $datedue = '';
        my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=? "); 
        while ( my $data = $sth->fetchrow_hashref ) {
         my $datedue = '';
-        my $count_reserves;
         $isth->execute( $data->{'itemnumber'} );
         if ( my $idata = $isth->fetchrow_hashref ) {
             $data->{borrowernumber} = $idata->{borrowernumber};
             $data->{cardnumber}     = $idata->{cardnumber};
             $data->{surname}     = $idata->{surname};
             $data->{firstname}     = $idata->{firstname};
         $isth->execute( $data->{'itemnumber'} );
         if ( my $idata = $isth->fetchrow_hashref ) {
             $data->{borrowernumber} = $idata->{borrowernumber};
             $data->{cardnumber}     = $idata->{cardnumber};
             $data->{surname}     = $idata->{surname};
             $data->{firstname}     = $idata->{firstname};
+            $data->{lastreneweddate} = $idata->{lastreneweddate};
             $datedue                = $idata->{'date_due'};
         if (C4::Context->preference("IndependantBranches")){
         my $userenv = C4::Context->userenv;
             $datedue                = $idata->{'date_due'};
         if (C4::Context->preference("IndependantBranches")){
         my $userenv = C4::Context->userenv;
@@ -1220,14 +1228,6 @@ sub GetItemsInfo {
                        ($data->{'serialseq'} , $data->{'publisheddate'}) = $ssth->fetchrow_array();
                        $serial = 1;
         }
                        ($data->{'serialseq'} , $data->{'publisheddate'}) = $ssth->fetchrow_array();
                        $serial = 1;
         }
-               if ( $datedue eq '' ) {
-            my ( $restype, $reserves ) =
-              C4::Reserves::CheckReserves( $data->{'itemnumber'} );
-# Previous conditional check with if ($restype) is not needed because a true
-# result for one item will result in subsequent items defaulting to this true
-# value.
-            $count_reserves = $restype;
-        }
         #get branch information.....
         my $bsth = $dbh->prepare(
             "SELECT * FROM branches WHERE branchcode = ?
         #get branch information.....
         my $bsth = $dbh->prepare(
             "SELECT * FROM branches WHERE branchcode = ?
@@ -1238,7 +1238,6 @@ sub GetItemsInfo {
             $data->{'branchname'} = $bdata->{'branchname'};
         }
         $data->{'datedue'}        = $datedue;
             $data->{'branchname'} = $bdata->{'branchname'};
         }
         $data->{'datedue'}        = $datedue;
-        $data->{'count_reserves'} = $count_reserves;
 
         # get notforloan complete status if applicable
         my $sthnflstatus = $dbh->prepare(
 
         # get notforloan complete status if applicable
         my $sthnflstatus = $dbh->prepare(
@@ -1622,41 +1621,45 @@ sub GetHiddenItemnumbers {
     my @resultitems;
 
     my $yaml = C4::Context->preference('OpacHiddenItems');
     my @resultitems;
 
     my $yaml = C4::Context->preference('OpacHiddenItems');
+    $yaml = "$yaml\n\n"; # YAML is anal on ending \n. Surplus does not hurt
     my $hidingrules;
     eval {
     my $hidingrules;
     eval {
-       $hidingrules = YAML::Load($yaml);
+        $hidingrules = YAML::Load($yaml);
     };
     if ($@) {
     };
     if ($@) {
-       warn "Unable to parse OpacHiddenItems syspref : $@";
-       return ();
-    } else {
+        warn "Unable to parse OpacHiddenItems syspref : $@";
+        return ();
+    }
     my $dbh = C4::Context->dbh;
 
     my $dbh = C4::Context->dbh;
 
-       # For each item
-       foreach my $item (@items) {
+    # For each item
+    foreach my $item (@items) {
 
 
-           # We check each rule
-           foreach my $field (keys %$hidingrules) {
-               my $query = "SELECT $field from items where itemnumber = ?";
-               my $sth = $dbh->prepare($query);        
-               $sth->execute($item->{'itemnumber'});
-               my ($result) = $sth->fetchrow;
+        # We check each rule
+        foreach my $field (keys %$hidingrules) {
+            my $val;
+            if (exists $item->{$field}) {
+                $val = $item->{$field};
+            }
+            else {
+                my $query = "SELECT $field from items where itemnumber = ?";
+                $val = $dbh->selectrow_array($query, undef, $item->{'itemnumber'});
+            }
+            $val = '' unless defined $val;
 
 
-               # If the results matches the values in the yaml file
-               if (any { $result eq $_ } @{$hidingrules->{$field}}) {
+            # If the results matches the values in the yaml file
+            if (any { $val eq $_ } @{$hidingrules->{$field}}) {
 
 
-                   # We add the itemnumber to the list
-                   push @resultitems, $item->{'itemnumber'};       
+                # We add the itemnumber to the list
+                push @resultitems, $item->{'itemnumber'};
 
 
-                   # If at least one rule matched for an item, no need to test the others
-                   last;
-               }
-           }
-       }
-       return @resultitems;
+                # If at least one rule matched for an item, no need to test the others
+                last;
+            }
+        }
     }
     }
-
- }
+    return @resultitems;
+}
 
 =head3 get_item_authorised_values
 
 
 =head3 get_item_authorised_values
 
@@ -2133,10 +2136,15 @@ sub _koha_new_item {
             $item->{'copynumber'},
             $item->{'stocknumber'},
     );
             $item->{'copynumber'},
             $item->{'stocknumber'},
     );
-    my $itemnumber = $dbh->{'mysql_insertid'};
+
+    my $itemnumber;
     if ( defined $sth->errstr ) {
         $error.="ERROR in _koha_new_item $query".$sth->errstr;
     }
     if ( defined $sth->errstr ) {
         $error.="ERROR in _koha_new_item $query".$sth->errstr;
     }
+    else {
+        $itemnumber = $dbh->{'mysql_insertid'};
+    }
+
     return ( $itemnumber, $error );
 }
 
     return ( $itemnumber, $error );
 }
 
@@ -2162,11 +2170,12 @@ sub MoveItemFromBiblio {
         ModZebra( $tobiblio, "specialUpdate", "biblioserver", undef, undef );
         ModZebra( $frombiblio, "specialUpdate", "biblioserver", undef, undef );
            # Checking if the item we want to move is in an order 
         ModZebra( $tobiblio, "specialUpdate", "biblioserver", undef, undef );
         ModZebra( $frombiblio, "specialUpdate", "biblioserver", undef, undef );
            # Checking if the item we want to move is in an order 
-        my $order = GetOrderFromItemnumber($itemnumber);
+        require C4::Acquisition;
+        my $order = C4::Acquisition::GetOrderFromItemnumber($itemnumber);
            if ($order) {
                    # Replacing the biblionumber within the order if necessary
                    $order->{'biblionumber'} = $tobiblio;
            if ($order) {
                    # Replacing the biblionumber within the order if necessary
                    $order->{'biblionumber'} = $tobiblio;
-               ModOrder($order);
+               C4::Acquisition::ModOrder($order);
            }
         return $tobiblio;
        }
            }
         return $tobiblio;
        }
@@ -2198,7 +2207,7 @@ sub DelItemCheck {
     if ($onloan){
         $error = "book_on_loan" 
     }
     if ($onloan){
         $error = "book_on_loan" 
     }
-    elsif ( C4::Context->userenv->{flags} & 1 and
+    elsif ( !(C4::Context->userenv->{flags} & 1) and
             C4::Context->preference("IndependantBranches") and
            (C4::Context->userenv->{branch} ne
              $item->{C4::Context->preference("HomeOrHoldingBranch")||'homebranch'}) )
             C4::Context->preference("IndependantBranches") and
            (C4::Context->userenv->{branch} ne
              $item->{C4::Context->preference("HomeOrHoldingBranch")||'homebranch'}) )
@@ -2421,9 +2430,9 @@ sub _get_unlinked_subfields_xml {
 
 sub  _parse_unlinked_item_subfields_from_xml {
     my $xml = shift;
 
 sub  _parse_unlinked_item_subfields_from_xml {
     my $xml = shift;
-
+    require C4::Charset;
     return unless defined $xml and $xml ne "";
     return unless defined $xml and $xml ne "";
-    my $marc = MARC::Record->new_from_xml(StripNonXmlChars($xml),'UTF-8');
+    my $marc = MARC::Record->new_from_xml(C4::Charset::StripNonXmlChars($xml),'UTF-8');
     my $unlinked_subfields = [];
     my @fields = $marc->fields();
     if ($#fields > -1) {
     my $unlinked_subfields = [];
     my @fields = $marc->fields();
     if ($#fields > -1) {
@@ -2458,4 +2467,293 @@ sub GetAnalyticsCount {
     }
 }
 
     }
 }
 
+=head2 GetItemHolds
+
+=over 4
+$holds = &GetItemHolds($biblionumber, $itemnumber);
+
+=back
+
+This function return the count of holds with $biblionumber and $itemnumber
+
+=cut
+
+sub GetItemHolds {
+    my ($biblionumber, $itemnumber) = @_;
+    my $holds;
+    my $dbh            = C4::Context->dbh;
+    my $query          = "SELECT count(*)
+        FROM  reserves
+        WHERE biblionumber=? AND itemnumber=?";
+    my $sth = $dbh->prepare($query);
+    $sth->execute($biblionumber, $itemnumber);
+    $holds = $sth->fetchrow;
+    return $holds;
+}
+=head1  OTHER FUNCTIONS
+
+=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 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/"/&quot;/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
+    };
+}
+
 1;
 1;