diff --git a/Koha/Items.pm b/Koha/Items.pm index cee46e52f2..0e50413cbd 100644 --- a/Koha/Items.pm +++ b/Koha/Items.pm @@ -691,13 +691,47 @@ sub _process_params { } } +=head3 _validate_params + +Verify is the input provided with _status is valid. + +Since we have to tweak the search for researches involving the _status parameter, if the search involves a _status, we need to check that the provided hashref is compatible with the use case. +An hashref is compatible if it is not nested or if the lonely level of nesting is under a "-and" parameter + +=cut + +sub _validate_params { + my ( $clean_params, $custom_attrs ) = @_; + + return 1 unless exists $custom_attrs->{_status}; + + if ( ref($clean_params) eq 'HASH' ) { + if ( grep { $_ eq '-and' } keys %$clean_params ) { + my $and_hashref = $clean_params->{'-and'}; + if ( ref($and_hashref) eq 'HASH' && !grep { ref( $and_hashref->{$_} ) eq 'HASH' } keys %$and_hashref ) { + return 1; + } + } + return 1 unless grep { ref( $clean_params->{$_} ) eq 'HASH' } keys %$clean_params; + } + + return 0; +} + sub search { my ( $self, $params, $attributes ) = @_; my ( $custom_attrs, $clean_params ) = _extract_custom_attrs($params); - $params = $clean_params; + unless ( _validate_params( $clean_params, $custom_attrs ) ) { + Koha::Exceptions::BadParameter->throw( + error => "Filtering on status is only implemented for -and search", + ); + } + + $params = $clean_params; my $status = $custom_attrs->{_status}; + if ($status) { if ( $status eq 'checked_out' ) { $self = $self->filter_by_checked_out( { onsite_checkout => 0 } ); diff --git a/t/db_dependent/Koha/Items.t b/t/db_dependent/Koha/Items.t index 377009d74d..fb3b30dcf8 100755 --- a/t/db_dependent/Koha/Items.t +++ b/t/db_dependent/Koha/Items.t @@ -75,7 +75,7 @@ is( $retrieved_item_1->barcode, $new_item_1->barcode, 'Find a item by id should subtest 'search' => sub { - plan tests => 16; + plan tests => 18; $schema->storage->txn_begin; my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); @@ -102,6 +102,29 @@ subtest 'search' => sub { { -and => { _status => 'available', biblionumber => $biblio->biblionumber } }, ); is( $available_items->count, 2, "Filtered to 2 available items - works when _status is in nested structure" ); + throws_ok { + $available_items = Koha::Items->search( + { -or => { _status => 'available', biblionumber => $biblio->biblionumber } }, + ); + } + 'Koha::Exceptions::BadParameter', + "Filtered to 3 available items - returns an error when _status is in nested structure using or"; + + throws_ok { + $available_items = Koha::Items->search( + { + -and => { + _status => 'available', + -and => { + biblionumber => $biblio->biblionumber, + biblionumber => $biblio->biblionumber + } + }, + } + ); + } + 'Koha::Exceptions::BadParameter', + "Filtered to 3 available items - returns an error when _status is in nested structure with more than one level"; my $item_3 = $builder->build_sample_item( {