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

(-)a/C4/Biblio.pm (-73 / +151 lines)
Lines 1108-1113 sub GetMarcSubfieldStructureFromKohaField { Link Here
1108
    return wantarray ? @{$mss->{$kohafield}} : $mss->{$kohafield}->[0];
1108
    return wantarray ? @{$mss->{$kohafield}} : $mss->{$kohafield}->[0];
1109
}
1109
}
1110
1110
1111
1112
sub GetMarcBiblio {
1113
    my ($params) = @_;
1114
1115
    if (not defined $params) {
1116
        carp 'GetMarcBiblio called without parameters';
1117
        return;
1118
    }
1119
    my $biblionumber = $params->{biblionumber};
1120
1121
    if (not defined $biblionumber) {
1122
        carp 'GetMarcBiblio called with undefined biblionumber';
1123
        return;
1124
    }
1125
    delete $params->{biblionumber};
1126
    $params->{biblionumbers} = [$biblionumber];
1127
    my ($biblio) = GetMarcBiblios($params);
1128
    return $biblio;
1129
}
1130
1111
=head2 GetMarcBiblio
1131
=head2 GetMarcBiblio
1112
1132
1113
  my $record = GetMarcBiblio({
1133
  my $record = GetMarcBiblio({
Lines 1148-1204 It only makes sense in combination both embed_items and opac values true. Link Here
1148
1168
1149
=cut
1169
=cut
1150
1170
1151
sub GetMarcBiblio {
1171
sub GetMarcBiblios {
1152
    my ($params) = @_;
1172
    my ($params) = @_;
1153
1173
1154
    if (not defined $params) {
1174
    if (not defined $params) {
1155
        carp 'GetMarcBiblio called without parameters';
1175
        carp 'GetMarcBiblios called without parameters';
1156
        return;
1176
        return;
1157
    }
1177
    }
1158
1178
1159
    my $biblionumber = $params->{biblionumber};
1179
    my $biblionumbers = $params->{biblionumbers};
1160
    my $embeditems   = $params->{embed_items} || 0;
1180
    my $embeditems   = $params->{embed_items} || 0;
1161
    my $opac         = $params->{opac} || 0;
1181
    my $opac         = $params->{opac} || 0;
1162
    my $borcat       = $params->{borcat} // q{};
1182
    my $borcat       = $params->{borcat} // q{};
1163
1183
1164
    if (not defined $biblionumber) {
1184
    ## START HERE ##
1165
        carp 'GetMarcBiblio called with undefined biblionumber';
1185
1186
    if (not defined $biblionumbers) {
1187
        carp 'GetMarcBiblio called with undefined biblionumbers';
1166
        return;
1188
        return;
1167
    }
1189
    }
1168
1190
1169
    my $dbh          = C4::Context->dbh;
1191
    my $in_placeholders = join ', ', (('?') x @{$biblionumbers});
1170
    my $sth          = $dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=? ");
1192
    my $dbh = C4::Context->dbh;
1171
    $sth->execute($biblionumber);
1193
    my $sth = $dbh->prepare("SELECT biblionumber, biblioitemnumber FROM biblioitems WHERE biblionumber IN ($in_placeholders)");
1172
    my $row     = $sth->fetchrow_hashref;
1194
    $sth->execute(@{$biblionumbers});
1173
    my $biblioitemnumber = $row->{'biblioitemnumber'};
1195
1174
    my $marcxml = GetXmlBiblio( $biblionumber );
1196
    my %marc_records;
1175
    $marcxml = StripNonXmlChars( $marcxml );
1197
    my ($biblionumber, $biblioitemnumber);
1176
    my $frameworkcode = GetFrameworkCode($biblionumber);
1198
    my $marc_flavour = C4::Context->preference('marcflavour');
1177
    MARC::File::XML->default_record_format( C4::Context->preference('marcflavour') );
1199
    while (my $biblio_keys = $sth->fetchrow_arrayref) {
1178
    my $record = MARC::Record->new();
1200
        ($biblionumber, $biblioitemnumber) = @{$biblio_keys};
1201
1202
        my $marcxml = GetXmlBiblio( $biblionumber );
1203
        $marcxml = StripNonXmlChars( $marcxml );
1204
        my $frameworkcode = GetFrameworkCode($biblionumber);
1205
        MARC::File::XML->default_record_format( $marc_flavour );
1206
        my $record = MARC::Record->new();
1207
1208
        if ($marcxml) {
1209
            $record = eval {
1210
                MARC::Record::new_from_xml( $marcxml, "utf8", $marc_flavour);
1211
            };
1212
            if ($@) { warn " problem with :$biblionumber : $@ \n$marcxml"; }
1213
            next unless $record;
1214
1215
            C4::Biblio::_koha_marc_update_bib_ids(
1216
                $record,
1217
                $frameworkcode,
1218
                $biblionumber,
1219
                $biblioitemnumber
1220
            );
1221
            $marc_records{$biblionumber} = $record;
1222
        }
1223
    }
1179
1224
1180
    if ($marcxml) {
1225
    if ($embeditems) {
1181
        $record = eval {
1226
        C4::Biblio::EmbedItemsInMarcBiblios({
1182
            MARC::Record::new_from_xml( $marcxml, "utf8",
1227
            marc_records  => \%marc_records,
1183
                C4::Context->preference('marcflavour') );
1184
        };
1185
        if ($@) { warn " problem with :$biblionumber : $@ \n$marcxml"; }
1186
        return unless $record;
1187
1188
        C4::Biblio::_koha_marc_update_bib_ids( $record, $frameworkcode, $biblionumber,
1189
            $biblioitemnumber );
1190
        C4::Biblio::EmbedItemsInMarcBiblio({
1191
            marc_record  => $record,
1192
            biblionumber => $biblionumber,
1193
            opac         => $opac,
1228
            opac         => $opac,
1194
            borcat       => $borcat })
1229
            borcat       => $borcat
1195
          if ($embeditems);
1230
        });
1196
1197
        return $record;
1198
    }
1199
    else {
1200
        return;
1201
    }
1231
    }
1232
    return wantarray ? values %marc_records : \%marc_records;
1202
}
1233
}
1203
1234
1204
=head2 GetXmlBiblio
1235
=head2 GetXmlBiblio
Lines 2790-2846 override if necessary. Link Here
2790
2821
2791
sub EmbedItemsInMarcBiblio {
2822
sub EmbedItemsInMarcBiblio {
2792
    my ($params) = @_;
2823
    my ($params) = @_;
2793
    my ($marc, $biblionumber, $itemnumbers, $opac, $borcat);
2824
2794
    $marc = $params->{marc_record};
2825
    if ( !$params->{marc_record} ) {
2795
    if ( !$marc ) {
2796
        carp 'EmbedItemsInMarcBiblio: No MARC record passed';
2826
        carp 'EmbedItemsInMarcBiblio: No MARC record passed';
2797
        return;
2827
        return;
2798
    }
2828
    }
2799
    $biblionumber = $params->{biblionumber};
2829
    if ( !$params->{biblionumber} ) {
2830
        carp 'EmbedItemsInMarcBiblio: No biblionumber passed';
2831
        return;
2832
    }
2833
2834
    $params->{marc_records} = { $params->{biblionumber} => $params->{marc_record} };
2835
    delete $params->{marc_record};
2836
    delete $params->{biblionumber};
2837
2838
    my ($marc_with_items) = EmbedItemsInMarcBiblios($params);
2839
    return $marc_with_items;
2840
}
2841
2842
sub EmbedItemsInMarcBiblios {
2843
    my ($params) = @_;
2844
    my ($marc_records, $biblionumber, $itemnumbers, $opac, $borcat);
2845
    $marc_records = $params->{marc_records};
2846
2800
    $itemnumbers = $params->{item_numbers};
2847
    $itemnumbers = $params->{item_numbers};
2801
    $opac = $params->{opac};
2848
    $opac = $params->{opac};
2802
    $borcat = $params->{borcat} // q{};
2849
    $borcat = $params->{borcat} // q{};
2803
2850
2804
    $itemnumbers = [] unless defined $itemnumbers;
2851
    $itemnumbers = [] unless defined $itemnumbers;
2805
2852
2806
    my $frameworkcode = GetFrameworkCode($biblionumber);
2807
    _strip_item_fields($marc, $frameworkcode);
2808
2809
    # ... and embed the current items
2853
    # ... and embed the current items
2810
    my $dbh = C4::Context->dbh;
2854
    my $dbh = C4::Context->dbh;
2811
    my $sth = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?");
2812
    $sth->execute($biblionumber);
2813
    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
2814
2855
2815
    my @item_fields; # Array holding the actual MARC data for items to be included.
2856
    my @biblionumbers = keys %{$marc_records};
2816
    my @items;       # Array holding items which are both in the list (sitenumbers)
2857
    my $in_placeholders = join ', ', (('?') x @biblionumbers);
2817
                     # and on this biblionumber
2818
2858
2819
    # Flag indicating if there is potential hiding.
2859
    my $biblio_itemnumbers = $dbh->selectcol_arrayref(
2820
    my $opachiddenitems = $opac
2860
        "SELECT itemnumber FROM items WHERE biblionumber IN ($in_placeholders)",
2821
      && ( C4::Context->preference('OpacHiddenItems') !~ /^\s*$/ );
2861
        undef,
2862
        @biblionumbers
2863
    );
2864
2865
    # Remove invalid item numbers by intersecting with all valid item numbers
2866
    # if $itemnumbers argument was provided
2822
2867
2868
    # TODO: MAKE SURE THERE IS A TEST FOR THIS
2869
    if(@{$itemnumbers}) {
2870
        my %h = map { $_ => undef } @{$itemnumbers};
2871
        $itemnumbers = [grep { exists $h{$_} } @{$biblio_itemnumbers}];
2872
    }
2873
    else {
2874
        $itemnumbers = $biblio_itemnumbers;
2875
    }
2876
    # If no item numbers then no point in continuing
2877
    return unless (@{$itemnumbers});
2878
2879
2880
    my $opachiddenitems = $opac
2881
        && ( C4::Context->preference('OpacHiddenItems') !~ /^\s*$/ );
2823
    require C4::Items;
2882
    require C4::Items;
2824
    while ( my ($itemnumber) = $sth->fetchrow_array ) {
2883
2825
        next if @$itemnumbers and not grep { $_ == $itemnumber } @$itemnumbers;
2884
    my $items = C4::Items::GetItems($itemnumbers);
2826
        my $i = $opachiddenitems ? C4::Items::GetItem($itemnumber) : undef;
2885
    # We have now fetched all items, time to partion by biblionumber
2827
        push @items, { itemnumber => $itemnumber, item => $i };
2886
    my %items_by_biblionumber = (map { ($_, []) } @biblionumbers);
2828
    }
2887
    foreach my $item (@{$items}) {
2829
    my @items2pass = map { $_->{item} } @items;
2888
        push @{$items_by_biblionumber{$item->{biblionumber}}}, $item;
2830
    my @hiddenitems =
2889
    }
2831
      $opachiddenitems
2890
2832
      ? C4::Items::GetHiddenItemnumbers({
2891
    foreach my $biblionumber (@biblionumbers) {
2833
            items  => \@items2pass,
2892
        my $marc_record = $marc_records->{$biblionumber};
2834
            borcat => $borcat })
2893
2835
      : ();
2894
        # Array holding items which are both in itemnumbers
2836
    # Convert to a hash for quick searching
2895
        # (if provided) and in biblionumbers itemnumbers
2837
    my %hiddenitems = map { $_ => 1 } @hiddenitems;
2896
        my $items = $items_by_biblionumber{$biblionumber};
2838
    foreach my $itemnumber ( map { $_->{itemnumber} } @items ) {
2897
2839
        next if $hiddenitems{$itemnumber};
2898
        # Could this be moved lower down and run only when items
2840
        my $item_marc = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
2899
        # exists for improved performance? Probably..
2841
        push @item_fields, $item_marc->field($itemtag);
2900
        my $frameworkcode = GetFrameworkCode($biblionumber);
2842
    }
2901
        _strip_item_fields($marc_record, $frameworkcode);
2843
    $marc->append_fields(@item_fields);
2902
2903
        # Flag indicating if there is potential hiding
2904
        if ($opachiddenitems) {
2905
            my %hidden_items = map { $_ => undef } C4::Items::GetHiddenItemnumbers({
2906
                items => @{$items},
2907
                borcat => $borcat
2908
            });
2909
            # Reduce items to non hidden items
2910
            $items = [grep { !(exists $hidden_items{$_->{itemnumber}}) } @{$items}];
2911
        }
2912
2913
        my ($itemtag) = GetMarcFromKohaField("items.itemnumber", $frameworkcode);
2914
        my @item_fields; # Array holding the actual MARC data for items to be included.
2915
        foreach my $item (@{$items}) {
2916
            my $item_marc = C4::Items::GetMarcItem($biblionumber, $item);
2917
            push @item_fields, $item_marc->field($itemtag);
2918
        }
2919
        $marc_record->append_fields(@item_fields);
2920
    }
2921
    return $marc_records;
2844
}
2922
}
2845
2923
2846
=head1 INTERNAL FUNCTIONS
2924
=head1 INTERNAL FUNCTIONS
Lines 3292-3298 sub ModBiblioMarc { Link Here
3292
3370
3293
    # deal with UNIMARC field 100 (encoding) : create it if needed & set encoding to unicode
3371
    # deal with UNIMARC field 100 (encoding) : create it if needed & set encoding to unicode
3294
    if ( $encoding eq "UNIMARC" ) {
3372
    if ( $encoding eq "UNIMARC" ) {
3295
	my $defaultlanguage = C4::Context->preference("UNIMARCField100Language");
3373
    my $defaultlanguage = C4::Context->preference("UNIMARCField100Language");
3296
        $defaultlanguage = "fre" if (!$defaultlanguage || length($defaultlanguage) != 3);
3374
        $defaultlanguage = "fre" if (!$defaultlanguage || length($defaultlanguage) != 3);
3297
        my $string = $record->subfield( 100, "a" );
3375
        my $string = $record->subfield( 100, "a" );
3298
        if ( ($string) && ( length( $record->subfield( 100, "a" ) ) == 36 ) ) {
3376
        if ( ($string) && ( length( $record->subfield( 100, "a" ) ) == 36 ) ) {
Lines 3302-3308 sub ModBiblioMarc { Link Here
3302
            $string = POSIX::strftime( "%Y%m%d", localtime );
3380
            $string = POSIX::strftime( "%Y%m%d", localtime );
3303
            $string =~ s/\-//g;
3381
            $string =~ s/\-//g;
3304
            $string = sprintf( "%-*s", 35, $string );
3382
            $string = sprintf( "%-*s", 35, $string );
3305
	    substr ( $string, 22, 3, $defaultlanguage);
3383
            substr ( $string, 22, 3, $defaultlanguage);
3306
        }
3384
        }
3307
        substr( $string, 25, 3, "y50" );
3385
        substr( $string, 25, 3, "y50" );
3308
        unless ( $record->subfield( 100, "a" ) ) {
3386
        unless ( $record->subfield( 100, "a" ) ) {
(-)a/C4/Items.pm (-21 / +47 lines)
Lines 129-162 of C<C4::Items> Link Here
129
129
130
Return item information, for a given itemnumber or barcode.
130
Return item information, for a given itemnumber or barcode.
131
The return value is a hashref mapping item column
131
The return value is a hashref mapping item column
132
names to values.  If C<$serial> is true, include serial publication data.
132
names to values, or undef if item was not found.  If C<$serial> is true, include serial publication data.
133
133
134
=cut
134
=cut
135
135
136
sub GetItem {
136
sub GetItem {
137
    my ($itemnumber,$barcode, $serial) = @_;
137
    my ($itemnumber, $barcode, $serial) = @_;
138
    my $dbh = C4::Context->dbh;
138
    my $items = GetItems($itemnumber ? [$itemnumber] : undef, $barcode ? [$barcode] : undef, $serial);
139
    return @{$items} ? $items->[0] : undef;
140
}
139
141
140
    my $item;
142
=head2 GetItems
141
    if ($itemnumber) {
142
        $item = Koha::Items->find( $itemnumber );
143
    } else {
144
        $item = Koha::Items->find( { barcode => $barcode } );
145
    }
146
143
147
    return unless ( $item );
144
  $item = GetItems($itemnumber,$barcode,$serial);
148
145
149
    my $data = $item->unblessed();
146
Return list of item information, for given itemnumbers or barcodes.
150
    $data->{itype} = $item->effective_itemtype(); # set the correct itype
147
The return value is an arrayref with hashrefs mapping item column
148
names to values, or an empty arrayref if no items were found.
149
If C<$serial> is true, include serial publication data.
151
150
151
=cut
152
153
sub GetItems {
154
    my ($itemnumbers, $barcodes, $serial) = @_;
155
    my $dbh = C4::Context->dbh;
156
    my $items_data = [];
157
158
    # Important: If 'item-level_itypes' preference is not set Koha::Item::effective_itemtype()
159
    # will be equal to $item->{itype} and it is possible to fetch the data directly from items table.
160
    # This will have a much smaller footprint then unblessing the item objects fetched through
161
    # find/search. If more calculated attributes are added in the future, this code will need
162
    # to account for that.
163
    if (C4::Context->preference('item-level_itypes')) {
164
        $items_data = Koha::Items->search_unblessed($itemnumbers ? $itemnumbers : { barcode => $barcodes });
165
    }
166
    else {
167
        my @items = Koha::Items->search(
168
            $itemnumbers ? { itemnumber => { IN => $itemnumbers } } : { barcode => { IN => $barcodes } }
169
        );
170
        foreach my $item (@items) {
171
            my $data = $item->unblessed();
172
            # Set the correct itype
173
            $data->{itype} = $item->effective_itemtype();
174
            push @{$items_data}, $data;
175
        }
176
    }
152
    if ($serial) {
177
    if ($serial) {
153
        my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=?");
178
        foreach my $data (@{$items_data}) {
154
        $ssth->execute( $data->{'itemnumber'} );
179
            my $ssth = $dbh->prepare("SELECT serialseq,publisheddate from serialitems left join serial on serialitems.serialid=serial.serialid where serialitems.itemnumber=?");
155
        ( $data->{'serialseq'}, $data->{'publisheddate'} ) = $ssth->fetchrow_array();
180
            $ssth->execute( $data->{'itemnumber'} );
181
            ( $data->{'serialseq'}, $data->{'publisheddate'} ) = $ssth->fetchrow_array();
182
        }
156
    }
183
    }
157
184
    return $items_data;
158
    return $data;
185
}
159
}    # sub GetItem
160
186
161
=head2 CartToShelf
187
=head2 CartToShelf
162
188
Lines 1331-1343 sub GetMarcItem { Link Here
1331
    # while the other treats the MARC representation as authoritative
1357
    # while the other treats the MARC representation as authoritative
1332
    # under certain circumstances.
1358
    # under certain circumstances.
1333
1359
1334
    my $itemrecord = GetItem($itemnumber);
1360
    my $itemrecord = ref($itemnumber) ? $itemnumber : GetItem($itemnumber);
1335
1361
1336
    # Tack on 'items.' prefix to column names so that C4::Biblio::TransformKohaToMarc will work.
1362
    # Tack on 'items.' prefix to column names so that C4::Biblio::TransformKohaToMarc will work.
1337
    # Also, don't emit a subfield if the underlying field is blank.
1363
    # Also, don't emit a subfield if the underlying field is blank.
1338
1364
1339
    
1365
1340
    return Item2Marc($itemrecord,$biblionumber);
1366
    return Item2Marc($itemrecord, $biblionumber);
1341
1367
1342
}
1368
}
1343
sub Item2Marc {
1369
sub Item2Marc {
(-)a/Koha/BiblioUtils.pm (-20 / +60 lines)
Lines 111-139 The iterator is a Koha::MetadataIterator object. Link Here
111
=cut
111
=cut
112
112
113
sub get_all_biblios_iterator {
113
sub get_all_biblios_iterator {
114
    my ($self, $params) = @_;
115
    my $batched;
116
    my $batch_size;
117
    if ($params) {
118
        $batched //= $params->{batched};
119
        $batch_size = $params->{batch_size} || 2000;
120
    }
121
114
    my $database = Koha::Database->new();
122
    my $database = Koha::Database->new();
115
    my $schema   = $database->schema();
123
    my $schema   = $database->schema();
116
    my $rs =
124
    my $rs = $schema->resultset('Biblio')->search(
117
      $schema->resultset('Biblio')->search( {},
125
        {},
118
        { columns => [qw/ biblionumber /] } );
126
        { columns => [qw/ biblionumber /] }
119
    my $next_func = sub {
127
    );
120
        # Warn and skip bad records, otherwise we break the loop
128
121
        while (1) {
129
    my $next_func;
122
            my $row = $rs->next();
130
    if ($batched) {
123
            return if !$row;
131
        my @marc_records_batch;
124
            my $marc = C4::Biblio::GetMarcBiblio({
132
        $next_func = sub {
125
                biblionumber => $row->biblionumber,
133
            unless (@marc_records_batch) {
126
                embed_items  => 1 });
134
                #Batch empty, nead to buffer up more records
127
            my $next = eval {
135
                my $limit = $batch_size;
128
                __PACKAGE__->new($marc, $row->biblionumber);
136
                my @biblionumbers;
129
            };
137
                while ($limit--) {
130
            if ($@) {
138
                    my $row = $rs->next();
131
                warn "Something went wrong reading record for biblio $row->biblionumber: $@\n";
139
                    last if !$row;
132
                next;
140
                    push @biblionumbers, $row->biblionumber;
141
                }
142
                if (@biblionumbers) {
143
                    my $marc_records = C4::Biblio::GetMarcBiblios({
144
                        biblionumbers => \@biblionumbers,
145
                        embed_items => 1
146
                    });
147
                    while (my ($biblionumber, $marc_record) = each %{$marc_records}) {
148
                        my $next = __PACKAGE__->new($marc_record, $biblionumber);
149
                        push @marc_records_batch, $next;
150
                    }
151
                }
133
            }
152
            }
134
            return $next;
153
            return pop @marc_records_batch;
135
        }
154
        };
136
    };
155
    }
156
    else {
157
        $next_func = sub {
158
            # Warn and skip bad records, otherwise we break the loop
159
            while (1) {
160
                my $row = $rs->next();
161
                return if !$row;
162
                my $marc = C4::Biblio::GetMarcBiblio({
163
                    biblionumber => $row->biblionumber,
164
                    embed_items => 1
165
                });
166
                my $next = eval {
167
                    __PACKAGE__->new($marc, $row->biblionumber);
168
                };
169
                if ($@) {
170
                    warn "Something went wrong reading record for biblio $row->biblionumber: $@\n";
171
                    next;
172
                }
173
                return $next;
174
            }
175
        };
176
    }
137
    return Koha::MetadataIterator->new($next_func);
177
    return Koha::MetadataIterator->new($next_func);
138
}
178
}
139
179
(-)a/Koha/Items.pm (+66 lines)
Lines 53-58 sub object_class { Link Here
53
    return 'Koha::Item';
53
    return 'Koha::Item';
54
}
54
}
55
55
56
=head2 search_unblessed
57
58
    $items = Koha::Items->search_unblessed($conditions);
59
60
In scalar context, returns an array reference with hashes containing item data, in list context returns an array.
61
Calling search_unblessed should produce the same result as calling Koha::Items->search and iterating
62
though the result unblessing each item. In cases where you only need the item data using this optimized
63
method is much faster. The arguments accepted are a subset and approximation of those supported by
64
Koha::items->search, with only the "barcode" and "itemnumber" attributes supported as conditions.
65
If called with a non-hash conditions argument a search will be performed as if "itemnumber" was the
66
provided condition. Only one condition is accepted and if more are provided the method will die with
67
an error.
68
69
=cut
70
71
sub search_unblessed {
72
    my ($self, $conditions) = @_;
73
    my $items = [];
74
    my $field_name;
75
    if (ref($conditions) eq 'HASH') {
76
        my %valid_condition_fields = (
77
            'barcode' => undef,
78
            'itemnumber' => undef,
79
        );
80
        my @fields = keys %{$conditions};
81
        if (@fields == 1) {
82
            foreach my $field (@fields) {
83
                die("Invalid condition: \"$field\"") unless exists $valid_condition_fields{$field};
84
            }
85
        }
86
        elsif(@fields > 1) {
87
            die("Multiple conditions are not supported");
88
        }
89
        else {
90
            die("No conditions provided");
91
        }
92
    }
93
    else {
94
        $conditions = {
95
            'itemnumber' => $conditions,
96
        };
97
    }
98
    # Only accepts one condition
99
    my ($field, $values) = (%{$conditions});
100
101
    if (ref($values) eq 'ARRAY' && @{$values} == 1) {
102
        ($values) = @{$values};
103
    }
104
    if (!ref($values)) {
105
        my $item = C4::Context->dbh->selectrow_hashref(qq{SELECT * FROM items WHERE $field = ?}, undef, $values);
106
        push @{$items}, $item;
107
    }
108
    elsif (ref($values) eq 'ARRAY') {
109
        my $in_placeholders = join ', ', (('?') x @{$values});
110
        my $sth = C4::Context->dbh->prepare(qq{SELECT * FROM items WHERE $field IN($in_placeholders)});
111
        $sth->execute(@{$values});
112
        while (my $item = $sth->fetchrow_hashref) {
113
            push @{$items}, $item;
114
        }
115
    }
116
    else {
117
        die("Invalid value for field: \"$field\"");
118
    }
119
    return wantarray ? @{$items} : $items;
120
}
121
56
=head1 AUTHOR
122
=head1 AUTHOR
57
123
58
Kyle M Hall <kyle@bywatersolutions.com>
124
Kyle M Hall <kyle@bywatersolutions.com>
(-)a/misc/search_tools/rebuild_elastic_search.pl (-1 / +1 lines)
Lines 131-137 if ($index_biblios) { Link Here
131
            return ($r, Koha::BiblioUtils->get_from_biblionumber($r, item_data => 1 ));
131
            return ($r, Koha::BiblioUtils->get_from_biblionumber($r, item_data => 1 ));
132
        };
132
        };
133
    } else {
133
    } else {
134
        my $records = Koha::BiblioUtils->get_all_biblios_iterator();
134
        my $records = Koha::BiblioUtils->get_all_biblios_iterator({ batched => 1 });
135
        $next = sub {
135
        $next = sub {
136
            $records->next();
136
            $records->next();
137
        }
137
        }
(-)a/t/db_dependent/Items.t (-6 / +79 lines)
Lines 42-48 my $location = 'My Location'; Link Here
42
42
43
subtest 'General Add, Get and Del tests' => sub {
43
subtest 'General Add, Get and Del tests' => sub {
44
44
45
    plan tests => 16;
45
    plan tests => 25;
46
47
    my $item_barcode = 123;
46
48
47
    $schema->storage->txn_begin;
49
    $schema->storage->txn_begin;
48
50
Lines 59-71 subtest 'General Add, Get and Del tests' => sub { Link Here
59
    my ($bibnum, $bibitemnum) = get_biblio();
61
    my ($bibnum, $bibitemnum) = get_biblio();
60
62
61
    # Add an item.
63
    # Add an item.
62
    my ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({ homebranch => $library->{branchcode}, holdingbranch => $library->{branchcode}, location => $location, itype => $itemtype->{itemtype} } , $bibnum);
64
    my ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({
65
            homebranch => $library->{branchcode},
66
            holdingbranch => $library->{branchcode},
67
            location => $location,
68
            itype => $itemtype->{itemtype},
69
            barcode => $item_barcode
70
        }, $bibnum
71
    );
63
    cmp_ok($item_bibnum, '==', $bibnum, "New item is linked to correct biblionumber.");
72
    cmp_ok($item_bibnum, '==', $bibnum, "New item is linked to correct biblionumber.");
64
    cmp_ok($item_bibitemnum, '==', $bibitemnum, "New item is linked to correct biblioitemnumber.");
73
    cmp_ok($item_bibitemnum, '==', $bibitemnum, "New item is linked to correct biblioitemnumber.");
65
74
66
    # Get item.
75
    # Get item.
67
    my $getitem = GetItem($itemnumber);
76
    my $getitem = GetItem($itemnumber);
68
    cmp_ok($getitem->{'itemnumber'}, '==', $itemnumber, "Retrieved item has correct itemnumber.");
77
    cmp_ok($getitem->{'itemnumber'}, '==', $itemnumber, "Retrieved item has correct itemnumber.");
78
    cmp_ok($getitem->{'barcode'}, '==', $item_barcode, "Retrieved item has correct barcode.");
69
    cmp_ok($getitem->{'biblioitemnumber'}, '==', $item_bibitemnum, "Retrieved item has correct biblioitemnumber.");
79
    cmp_ok($getitem->{'biblioitemnumber'}, '==', $item_bibitemnum, "Retrieved item has correct biblioitemnumber.");
70
    is( $getitem->{location}, $location, "The location should not have been modified" );
80
    is( $getitem->{location}, $location, "The location should not have been modified" );
71
    is( $getitem->{permanent_location}, $location, "The permanent_location should have been set to the location value" );
81
    is( $getitem->{permanent_location}, $location, "The permanent_location should have been set to the location value" );
Lines 75-92 subtest 'General Add, Get and Del tests' => sub { Link Here
75
    my $dbh = C4::Context->dbh;
85
    my $dbh = C4::Context->dbh;
76
    local $dbh->{RaiseError} = 1;
86
    local $dbh->{RaiseError} = 1;
77
    ModItem({}, $bibnum, $itemnumber);
87
    ModItem({}, $bibnum, $itemnumber);
88
    $getitem = GetItem(undef, $item_barcode);
89
    cmp_ok($getitem->{'itemnumber'}, '==', $itemnumber, "Item retrieved by barcode has correct itemnumber.");
78
90
79
    # Modify item; setting barcode.
91
    # Modify item; setting barcode.
80
    ModItem({ barcode => '987654321' }, $bibnum, $itemnumber);
92
    $item_barcode = '987654321';
93
    ModItem({ barcode => $item_barcode }, $bibnum, $itemnumber);
81
    my $moditem = GetItem($itemnumber);
94
    my $moditem = GetItem($itemnumber);
82
    cmp_ok($moditem->{'barcode'}, '==', '987654321', 'Modified item barcode successfully to: '.$moditem->{'barcode'} . '.');
95
    cmp_ok($moditem->{'barcode'}, '==', $item_barcode, 'Modified item barcode successfully to: ' . $moditem->{'barcode'} . '.');
96
97
	# Update some more properties to get larger coverage
98
	my $item_properties = {
99
		'dateaccessioned' => '2012-12-12',
100
		'datelastborrowed' => '2013-12-12',
101
		'datelastseen' => '2013-12-12',
102
		'notforloan' => '0',
103
		'damaged' => '0',
104
		'itemlost' => '0',
105
		'itemcallnumber' => '1234',
106
		'restricted' => '0',
107
	};
108
109
    # Clone item propreties since ModItem modifies this argument
110
    # causing later tests to fail
111
    ModItem({%{$item_properties}}, $bibnum, $itemnumber);
112
113
	# Search unblessed tests
114
	my $search_conditions = {
115
		'itemnumber' => $itemnumber,
116
	};
117
	my ($item_object) = Koha::Items->search($search_conditions);
118
	my $item_object_data = $item_object->unblessed;
119
	cmp_ok($item_object_data->{'itemnumber'}, '==', $itemnumber, "Item object retrieved by Koha::Items->search using \"itemnumber\" condition has correct itemnumber.");
120
121
	# Intersect with updated properties
122
	my $updated_item_properties = { map { ($_ => $item_object_data->{$_}) } keys %{$item_properties} };
123
124
	is_deeply($updated_item_properties, $item_properties, "Updated item properties have correct values.");
125
126
    my ($item_data) = Koha::Items->search_unblessed($search_conditions);
127
	cmp_ok(
128
		$item_data->{'itemnumber'},
129
		'==',
130
		$itemnumber,
131
		"Item data retrieved by Koha::Items->search_unblessed using \"itemnumber\" condition has correct itemnumber."
132
	);
133
134
    ($item_data) = Koha::Items->search_unblessed({ 'barcode' => $item_barcode });
135
	cmp_ok(
136
		$item_data->{'itemnumber'},
137
		'==',
138
		$itemnumber,
139
		"Item data retrieved by Koha::Items->search_unblessed using \"barcode\" condition has correct itemnumber."
140
	);
141
142
	is_deeply($item_object_data, $item_data, "Item data retrieved by unblessing item object is identical to item data from Koha::Items->search_unblessed.");
83
143
84
    # Delete item.
144
    # Delete item.
85
    DelItem({ biblionumber => $bibnum, itemnumber => $itemnumber });
145
    DelItem({ biblionumber => $bibnum, itemnumber => $itemnumber });
86
    my $getdeleted = GetItem($itemnumber);
146
    my $getdeleted = GetItem($itemnumber);
87
    is($getdeleted->{'itemnumber'}, undef, "Item deleted as expected.");
147
    is($getdeleted->{'itemnumber'}, undef, "Item deleted as expected.");
88
148
89
    ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({ homebranch => $library->{branchcode}, holdingbranch => $library->{branchcode}, location => $location, permanent_location => 'my permanent location', itype => $itemtype->{itemtype} } , $bibnum);
149
    ($item_bibnum, $item_bibitemnum, $itemnumber) = AddItem({
150
            homebranch => $library->{branchcode},
151
            holdingbranch => $library->{branchcode},
152
            location => $location,
153
            permanent_location => 'my permanent location',
154
            itype => $itemtype->{itemtype},
155
            barcode => $item_barcode
156
        },
157
        $bibnum
158
    );
90
    $getitem = GetItem($itemnumber);
159
    $getitem = GetItem($itemnumber);
91
    is( $getitem->{location}, $location, "The location should not have been modified" );
160
    is( $getitem->{location}, $location, "The location should not have been modified" );
92
    is( $getitem->{permanent_location}, 'my permanent location', "The permanent_location should not have modified" );
161
    is( $getitem->{permanent_location}, 'my permanent location', "The permanent_location should not have modified" );
Lines 104-109 subtest 'General Add, Get and Del tests' => sub { Link Here
104
    t::lib::Mocks::mock_preference('item-level_itypes', '1');
173
    t::lib::Mocks::mock_preference('item-level_itypes', '1');
105
    $getitem = GetItem($itemnumber);
174
    $getitem = GetItem($itemnumber);
106
    is( $getitem->{itype}, $itemtype->{itemtype}, "Itemtype set correctly when using item-level_itypes" );
175
    is( $getitem->{itype}, $itemtype->{itemtype}, "Itemtype set correctly when using item-level_itypes" );
176
    # Good to test this since different code for retrieving items is run in GetItems() depending on item-level_itypes preference
177
    is( $getitem->{itemnumber}, $itemnumber, "Item successfully retrieved by itemnumber when using item-level_itypes" );
178
    $getitem = GetItem(undef, $item_barcode);
179
    is( $getitem->{itemnumber}, $itemnumber, "Item successfully retrieved by barcode when using item-level_itypes" );
180
107
    t::lib::Mocks::mock_preference('item-level_itypes', '0');
181
    t::lib::Mocks::mock_preference('item-level_itypes', '0');
108
    $getitem = GetItem($itemnumber);
182
    $getitem = GetItem($itemnumber);
109
    is( $getitem->{itype}, undef, "Itemtype set correctly when not using item-level_itypes" );
183
    is( $getitem->{itype}, undef, "Itemtype set correctly when not using item-level_itypes" );
110
- 

Return to bug 19884