View | Details | Raw Unified | Return to bug 20664
Collapse All | Expand All

(-)a/C4/Biblio.pm (-45 / +49 lines)
Lines 344-350 sub ModBiblio { Link Here
344
344
345
=head2 _strip_item_fields
345
=head2 _strip_item_fields
346
346
347
  _strip_item_fields($record, $frameworkcode)
347
  _strip_item_fields($record)
348
348
349
Utility routine to remove item tags from a
349
Utility routine to remove item tags from a
350
MARC bib.
350
MARC bib.
Lines 355-361 sub _strip_item_fields { Link Here
355
    my $record = shift;
355
    my $record = shift;
356
    my $frameworkcode = shift;
356
    my $frameworkcode = shift;
357
    # get the items before and append them to the biblio before updating the record, atm we just have the biblio
357
    # get the items before and append them to the biblio before updating the record, atm we just have the biblio
358
    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
358
    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber" );
359
359
360
    # delete any item fields from incoming record to avoid
360
    # delete any item fields from incoming record to avoid
361
    # duplication or incorrect data - use AddItem() or ModItem()
361
    # duplication or incorrect data - use AddItem() or ModItem()
Lines 1053-1066 sub GetMarcSubfieldStructure { Link Here
1053
sub GetMarcFromKohaField {
1053
sub GetMarcFromKohaField {
1054
    my ( $kohafield ) = @_;
1054
    my ( $kohafield ) = @_;
1055
    return unless $kohafield;
1055
    return unless $kohafield;
1056
    # The next call uses the Default framework since it is AUTHORITATIVE
1056
1057
    # for all Koha to MARC mappings.
1057
    my $cache     = Koha::Caches->get_instance();
1058
    my $mss = GetMarcSubfieldStructure( '' ); # Do not change framework
1058
    my $cache_key = "MarcFromKohaField-$kohafield";
1059
    my @retval;
1059
    my $cached    = $cache->get_from_cache($cache_key);
1060
    foreach( @{ $mss->{$kohafield} } ) {
1060
    if ( !defined $cached ) {
1061
        push @retval, $_->{tagfield}, $_->{tagsubfield};
1061
        # The next call uses the Default framework since it is AUTHORITATIVE
1062
    }
1062
        # for all Koha to MARC mappings.
1063
    return wantarray ? @retval : ( @retval ? $retval[0] : undef );
1063
        my $mss = GetMarcSubfieldStructure( '' ); # Do not change framework
1064
        my @retval;
1065
        foreach( @{ $mss->{$kohafield} } ) {
1066
            push @retval, $_->{tagfield}, $_->{tagsubfield};
1067
        }
1068
        $cached = \@retval;
1069
        $cache->set_in_cache( $cache_key, $cached );
1070
    }
1071
    return wantarray ? @$cached : ( @$cached ? $cached->[0] : undef );
1064
}
1072
}
1065
1073
1066
=head2 GetMarcSubfieldStructureFromKohaField
1074
=head2 GetMarcSubfieldStructureFromKohaField
Lines 1137-1146 sub GetMarcBiblio { Link Here
1137
        return;
1145
        return;
1138
    }
1146
    }
1139
1147
1140
    my $dbh          = C4::Context->dbh;
1148
    # Use state to speed up repeated calls in batch processes
1141
    my $sth          = $dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=? ");
1149
    state $sth = C4::Context->dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=? ");
1142
    $sth->execute($biblionumber);
1150
    $sth->execute($biblionumber);
1143
    my $row     = $sth->fetchrow_hashref;
1151
    my $row     = $sth->fetchrow_hashref;
1152
    $sth->finish;
1144
    my $biblioitemnumber = $row->{'biblioitemnumber'};
1153
    my $biblioitemnumber = $row->{'biblioitemnumber'};
1145
    my $marcxml = GetXmlBiblio( $biblionumber );
1154
    my $marcxml = GetXmlBiblio( $biblionumber );
1146
    $marcxml = StripNonXmlChars( $marcxml );
1155
    $marcxml = StripNonXmlChars( $marcxml );
Lines 1179-1195 The XML should only contain biblio information (item information is no longer st Link Here
1179
1188
1180
sub GetXmlBiblio {
1189
sub GetXmlBiblio {
1181
    my ($biblionumber) = @_;
1190
    my ($biblionumber) = @_;
1182
    my $dbh = C4::Context->dbh;
1183
    return unless $biblionumber;
1191
    return unless $biblionumber;
1184
    my ($marcxml) = $dbh->selectrow_array(
1192
1193
    # Use state to speed up repeated calls in batch processes
1194
    state $sth = C4::Context->dbh->prepare(
1185
        q|
1195
        q|
1186
        SELECT metadata
1196
        SELECT metadata
1187
        FROM biblio_metadata
1197
        FROM biblio_metadata
1188
        WHERE biblionumber=?
1198
        WHERE biblionumber=?
1189
            AND format='marcxml'
1199
            AND format='marcxml'
1190
            AND marcflavour=?
1200
            AND marcflavour=?
1191
    |, undef, $biblionumber, C4::Context->preference('marcflavour')
1201
        |
1192
    );
1202
    );
1203
1204
    $sth->execute( $biblionumber, C4::Context->preference('marcflavour') );
1205
    my ($marcxml) = $sth->fetchrow();
1206
    $sth->finish;
1193
    return $marcxml;
1207
    return $marcxml;
1194
}
1208
}
1195
1209
Lines 2090-2099 sub UpsertMarcControlField { Link Here
2090
2104
2091
sub GetFrameworkCode {
2105
sub GetFrameworkCode {
2092
    my ($biblionumber) = @_;
2106
    my ($biblionumber) = @_;
2093
    my $dbh            = C4::Context->dbh;
2107
    # Use state to speed up repeated calls in batch processes
2094
    my $sth            = $dbh->prepare("SELECT frameworkcode FROM biblio WHERE biblionumber=?");
2108
    state $sth         = C4::Context->dbh->prepare("SELECT frameworkcode FROM biblio WHERE biblionumber=?");
2095
    $sth->execute($biblionumber);
2109
    $sth->execute($biblionumber);
2096
    my ($frameworkcode) = $sth->fetchrow;
2110
    my ($frameworkcode) = $sth->fetchrow;
2111
    $sth->finish;
2097
    return $frameworkcode;
2112
    return $frameworkcode;
2098
}
2113
}
2099
2114
Lines 2756-2791 sub EmbedItemsInMarcBiblio { Link Here
2756
2771
2757
    $itemnumbers = [] unless defined $itemnumbers;
2772
    $itemnumbers = [] unless defined $itemnumbers;
2758
2773
2759
    my $frameworkcode = GetFrameworkCode($biblionumber);
2774
    _strip_item_fields($marc);
2760
    _strip_item_fields($marc, $frameworkcode);
2775
2776
    my $hidingrules = {};
2777
    my $yaml = $opac ? C4::Context->preference('OpacHiddenItems') : '';
2778
    if ( $yaml =~ /\S/ ) {
2779
        $yaml = "$yaml\n\n"; # YAML is anal on ending \n. Surplus does not hurt
2780
        eval {
2781
            $hidingrules = YAML::Load($yaml);
2782
        };
2783
        if ($@) {
2784
            carp "Unable to parse OpacHiddenItems syspref : $@";
2785
        }
2786
    }
2761
2787
2762
    # ... and embed the current items
2763
    my $dbh = C4::Context->dbh;
2764
    my $sth = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?");
2765
    $sth->execute($biblionumber);
2766
    my @item_fields;
2767
    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
2768
    my @items;
2769
    my $opachiddenitems = $opac
2770
      && ( C4::Context->preference('OpacHiddenItems') !~ /^\s*$/ );
2771
    require C4::Items;
2788
    require C4::Items;
2772
    while ( my ($itemnumber) = $sth->fetchrow_array ) {
2789
2773
        next if @$itemnumbers and not grep { $_ == $itemnumber } @$itemnumbers;
2790
    my $item_fields = C4::Items::GetMarcItemFields( $biblionumber, $itemnumbers, $hidingrules );
2774
        my $i = $opachiddenitems ? C4::Items::GetItem($itemnumber) : undef;
2791
2775
        push @items, { itemnumber => $itemnumber, item => $i };
2792
    $marc->append_fields(@$item_fields) if ( @$item_fields );
2776
    }
2777
    my @hiddenitems =
2778
      $opachiddenitems
2779
      ? C4::Items::GetHiddenItemnumbers( map { $_->{item} } @items )
2780
      : ();
2781
    # Convert to a hash for quick searching
2782
    my %hiddenitems = map { $_ => 1 } @hiddenitems;
2783
    foreach my $itemnumber ( map { $_->{itemnumber} } @items ) {
2784
        next if $hiddenitems{$itemnumber};
2785
        my $item_marc = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
2786
        push @item_fields, $item_marc->field($itemtag);
2787
    }
2788
    $marc->append_fields(@item_fields);
2789
}
2793
}
2790
2794
2791
=head1 INTERNAL FUNCTIONS
2795
=head1 INTERNAL FUNCTIONS
(-)a/C4/Items.pm (-5 / +72 lines)
Lines 21-26 package C4::Items; Link Here
21
use strict;
21
use strict;
22
#use warnings; FIXME - Bug 2505
22
#use warnings; FIXME - Bug 2505
23
23
24
use Modern::Perl;
24
use Carp;
25
use Carp;
25
use C4::Context;
26
use C4::Context;
26
use C4::Koha;
27
use C4::Koha;
Lines 1524-1529 sub Item2Marc { Link Here
1524
	return $itemmarc;
1525
	return $itemmarc;
1525
}
1526
}
1526
1527
1528
=head2 GetMarcItemFields
1529
1530
  my @marc_fields = GetMarcItemFields($biblionumber);
1531
1532
Returns an array of MARC::Record objects of the items for the biblio.
1533
1534
=cut
1535
1536
sub GetMarcItemFields {
1537
	my ( $biblionumber, $itemnumbers, $hidingrules ) = @_;
1538
1539
    my $item_level_itype = C4::Context->preference('item-level_itypes');
1540
    # This is so much faster than using Koha::Items->search that it makes sense even if it's ugly.
1541
    state $sth = C4::Context->dbh->prepare( 'SELECT * FROM items WHERE biblionumber = ?' );
1542
    $sth->execute( $biblionumber );
1543
    my $items = $sth->fetchall_arrayref({});
1544
    $sth->finish();
1545
    my @item_fields;
1546
    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( 'items.itemnumber' );
1547
1548
    ITEMLOOP: foreach my $item (@$items) {
1549
1550
        # Check itemnumbers
1551
        next if ( @$itemnumbers && !any { $_ == $item->{itemnumber} } @$itemnumbers );
1552
1553
        # Check hiding rules
1554
        if ( defined $hidingrules ) {
1555
            foreach my $field (keys %$hidingrules) {
1556
                my $val = $item->{$field};
1557
                $val = '' unless defined $val;
1558
1559
                # If the results matches the values in the hiding rules, skip the item
1560
                if (any { $val eq $_ } @{$hidingrules->{$field}}) {
1561
                    next ITEMLOOP;
1562
                }
1563
            }
1564
        }
1565
1566
        # Set correct item type
1567
        if ( !$item_level_itype || !$item->{itype} ) {
1568
            warn 'item-level_itypes set but no itemtype set for item (' . $item->{itemnumber} . ')' if ( !$item->{itype} );
1569
            my $biblioitem = Koha::Biblioitems->find( $item->{biblioitemnumber} );
1570
            $item->{itype} = $biblioitem->itemtype;
1571
        }
1572
1573
        my $mungeditem = {
1574
            map {
1575
                defined($item->{$_}) && $item->{$_} ne '' ? ("items.$_" => $item->{$_}) : ()
1576
            } keys %{ $item }
1577
        };
1578
        my $itemmarc = TransformKohaToMarc($mungeditem);
1579
1580
        my $unlinked_item_subfields = _parse_unlinked_item_subfields_from_xml($mungeditem->{'items.more_subfields_xml'});
1581
        if (defined $unlinked_item_subfields and $#$unlinked_item_subfields > -1) {
1582
            foreach my $field ($itemmarc->field($itemtag)){
1583
                $field->add_subfields(@$unlinked_item_subfields);
1584
            }
1585
        }
1586
1587
        push @item_fields, $itemmarc->field( $itemtag );
1588
    }
1589
1590
    return \@item_fields;
1591
}
1592
1527
=head1 PRIVATE FUNCTIONS AND VARIABLES
1593
=head1 PRIVATE FUNCTIONS AND VARIABLES
1528
1594
1529
The following functions are not meant to be called
1595
The following functions are not meant to be called
Lines 1660-1669 sub _do_column_fixes_for_mod { Link Here
1660
        (not defined $item->{'withdrawn'} or $item->{'withdrawn'} eq '')) {
1726
        (not defined $item->{'withdrawn'} or $item->{'withdrawn'} eq '')) {
1661
        $item->{'withdrawn'} = 0;
1727
        $item->{'withdrawn'} = 0;
1662
    }
1728
    }
1663
    if (exists $item->{location}
1729
    if (exists $item->{'location'}
1664
        and $item->{location} ne 'CART'
1730
        and defined $item->{'location'}
1665
        and $item->{location} ne 'PROC'
1731
        and $item->{'location'} ne 'CART'
1666
        and not $item->{permanent_location}
1732
        and $item->{'location'} ne 'PROC'
1733
        and (not defined $item->{'permanent_location'} or not $item->{'permanent_location'})
1667
    ) {
1734
    ) {
1668
        $item->{'permanent_location'} = $item->{'location'};
1735
        $item->{'permanent_location'} = $item->{'location'};
1669
    }
1736
    }
Lines 2328-2334 sub _SearchItems_build_where_fragment { Link Here
2328
        push @columns, Koha::Database->new()->schema()->resultset('Biblioitem')->result_source->columns;
2395
        push @columns, Koha::Database->new()->schema()->resultset('Biblioitem')->result_source->columns;
2329
        my @operators = qw(= != > < >= <= like);
2396
        my @operators = qw(= != > < >= <= like);
2330
        my $field = $filter->{field};
2397
        my $field = $filter->{field};
2331
        if ( (0 < grep /^$field$/, @columns) or (substr($field, 0, 5) eq 'marc:') ) {
2398
        if ( defined $field and ((0 < grep /^$field$/, @columns) or (substr($field, 0, 5) eq 'marc:')) ) {
2332
            my $op = $filter->{operator};
2399
            my $op = $filter->{operator};
2333
            my $query = $filter->{query};
2400
            my $query = $filter->{query};
2334
2401
(-)a/t/db_dependent/Items.t (-7 / +3 lines)
Lines 667-673 subtest 'C4::Items::_build_default_values_for_mod_marc' => sub { Link Here
667
    Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => '9', kohafield => 'items.itemnumber' })->store;
667
    Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => '9', kohafield => 'items.itemnumber' })->store;
668
    Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => 'p', kohafield => 'items.barcode' })->store;
668
    Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => 'p', kohafield => 'items.barcode' })->store;
669
    Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => 'y', kohafield => 'items.itype' })->store;
669
    Koha::MarcSubfieldStructure->new({ frameworkcode => '', tagfield => '952', tagsubfield => 'y', kohafield => 'items.itype' })->store;
670
    Koha::Caches->get_instance->clear_from_cache( "MarcSubfieldStructure-" );
670
    Koha::Caches->get_instance()->flush_all();
671
671
672
    my $itemtype = $builder->build({ source => 'Itemtype' })->{itemtype};
672
    my $itemtype = $builder->build({ source => 'Itemtype' })->{itemtype};
673
673
Lines 708-716 subtest 'C4::Items::_build_default_values_for_mod_marc' => sub { Link Here
708
    Koha::MarcSubfieldStructures->search({ frameworkcode => '', tagfield => '952', tagsubfield => 'p' })->delete;
708
    Koha::MarcSubfieldStructures->search({ frameworkcode => '', tagfield => '952', tagsubfield => 'p' })->delete;
709
709
710
    # And make sure the caches are cleared
710
    # And make sure the caches are cleared
711
    my $cache = Koha::Caches->get_instance();
711
    Koha::Caches->get_instance()->flush_all();
712
    $cache->clear_from_cache("default_value_for_mod_marc-");
713
    $cache->clear_from_cache("MarcSubfieldStructure-");
714
712
715
    # Update the MARC field with another value
713
    # Update the MARC field with another value
716
    $item_record->delete_fields( $barcode_field );
714
    $item_record->delete_fields( $barcode_field );
Lines 725-732 subtest 'C4::Items::_build_default_values_for_mod_marc' => sub { Link Here
725
    $item = GetItem($item_itemnumber);
723
    $item = GetItem($item_itemnumber);
726
    is ( $item->{barcode}, $a_barcode, 'items.barcode is not mapped anymore, so the DB column has not been updated' );
724
    is ( $item->{barcode}, $a_barcode, 'items.barcode is not mapped anymore, so the DB column has not been updated' );
727
725
728
    $cache->clear_from_cache("default_value_for_mod_marc-");
726
    Koha::Caches->get_instance()->flush_all();
729
    $cache->clear_from_cache( "MarcSubfieldStructure-" );
730
    $schema->storage->txn_rollback;
727
    $schema->storage->txn_rollback;
731
};
728
};
732
729
733
- 

Return to bug 20664