From 101fd97cb70398f1c2d8cf49968356e2a0fd3f08 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Thu, 12 Sep 2024 11:19:36 +0200 Subject: [PATCH] Bug 37902: Make sure we loop over if a structure is passed Signed-off-by: Nick Clemens Signed-off-by: Kyle M Hall Signed-off-by: Katrin Fischer --- Koha/Object.pm | 60 ++++++++++++++++++++++-------------- Koha/REST/Plugin/Objects.pm | 14 +++++---- t/db_dependent/Koha/Object.t | 24 ++++++++++++++- 3 files changed, 68 insertions(+), 30 deletions(-) diff --git a/Koha/Object.pm b/Koha/Object.pm index ad34bbc948..0f179044eb 100644 --- a/Koha/Object.pm +++ b/Koha/Object.pm @@ -832,45 +832,59 @@ Returns the passed params, converted from API naming into the model. =cut -sub attributes_from_api { - my ( $self, $from_api_params ) = @_; - - my $from_api_mapping = $self->from_api_mapping; +sub _recursive_fixup { + my ( $self, $key, $value, $column_info ) = @_; - my $params; - my $columns_info = $self->_result->result_source->columns_info; - my $dtf = $self->_result->result_source->storage->datetime_parser; + if ( ref($value) && ref($value) eq 'HASH' ) { + my $hash; + for my $k ( keys %$value ) { + $hash->{$k} = $self->_recursive_fixup( $key, $value->{$k}, $column_info ); + } + return $hash; - while (my ($key, $value) = each %{ $from_api_params } ) { - my $koha_field_name = - exists $from_api_mapping->{$key} - ? $from_api_mapping->{$key} - : $key; + } elsif ( ref($value) && ref($value) eq 'ARRAY' ) { + return [ map { $self->_recursive_fixup( $key, $_, $column_info ) } @$value ]; + } else { + if ( $column_info->{is_boolean} ) { - if ( $columns_info->{$koha_field_name}->{is_boolean} ) { # TODO: Remove when D8 is formally deprecated # Handle booleans gracefully - $value = ( $value ) ? 1 : 0; - } - elsif ( _date_or_datetime_column_type( $columns_info->{$koha_field_name}->{data_type} ) ) { - if (defined $value) { + $value = ($value) ? 1 : 0; + } elsif ( _date_or_datetime_column_type( $column_info->{data_type} ) ) { + if ( defined $value ) { try { - if ( $columns_info->{$koha_field_name}->{data_type} eq 'date' ) { + my $dtf = $self->_result->result_source->storage->datetime_parser; + if ( $column_info->{data_type} eq 'date' ) { my $dt = DateTime::Format::MySQL->parse_date($value); $value = $dtf->format_date($dt); - } - else { + } else { my $dt = Koha::DateTime::Format::RFC3339->parse_datetime($value); $value = $dtf->format_datetime($dt); } - } - catch { + } catch { Koha::Exceptions::BadParameter->throw( parameter => $key ); }; } } + return $value; + } +} + +sub attributes_from_api { + my ( $self, $from_api_params ) = @_; + + my $from_api_mapping = $self->from_api_mapping; + + my $params; + my $columns_info = $self->_result->result_source->columns_info; + + while ( my ( $key, $value ) = each %{$from_api_params} ) { + my $koha_field_name = + exists $from_api_mapping->{$key} + ? $from_api_mapping->{$key} + : $key; - $params->{$koha_field_name} = $value; + $params->{$koha_field_name} = $self->_recursive_fixup( $key, $value, $columns_info->{$koha_field_name} ); } return $params; diff --git a/Koha/REST/Plugin/Objects.pm b/Koha/REST/Plugin/Objects.pm index 2b1dbbe83c..20c8ecca04 100644 --- a/Koha/REST/Plugin/Objects.pm +++ b/Koha/REST/Plugin/Objects.pm @@ -274,13 +274,15 @@ controller, and thus shouldn't be called twice in it. # Apply the mapping function to the passed params if ( defined $filtered_params ) { - $filtered_params = - $c->build_query_params( $filtered_params, $reserved_params ); - } + $filtered_params = $c->build_query_params( $filtered_params, $reserved_params ); + } - $filtered_params = - $c->merge_q_params( $filtered_params, $query_params, - $result_set ); + if ($query_params) { + $filtered_params = $c->merge_q_params( + $filtered_params, $query_params, + $result_set + ); + } $filtered_params = $result_set->attributes_from_api($filtered_params); diff --git a/t/db_dependent/Koha/Object.t b/t/db_dependent/Koha/Object.t index 6851817534..fe2c4ff54d 100755 --- a/t/db_dependent/Koha/Object.t +++ b/t/db_dependent/Koha/Object.t @@ -763,7 +763,7 @@ subtest 'attributes_from_api() tests' => sub { subtest 'date and date-time handling tests' => sub { - plan tests => 12; + plan tests => 13; my $patron = Koha::Patron->new(); @@ -803,6 +803,28 @@ subtest 'attributes_from_api() tests' => sub { 'Given an rfc3339 formatted date string, a date field is converted into an SQL formatted date string' ); + $attrs = $patron->attributes_from_api( + { + updated_on => { '>' => '2019-12-27T14:53:00Z' }, + last_seen => [ { '>' => '2019-12-27T14:53:00Z' }, { '=' => '2019-12-31T23:59:00Z' } ], + date_of_birth => [ { '>' => '2019-12-27' }, { '=' => '2019-12-31' } ], + } + ); + + is_deeply( + $attrs, + { + lastseen => [ + { + '>' => '2019-12-27 14:53:00', + }, + { '=' => '2019-12-31 23:59:00' } + ], + updated_on => { '>' => '2019-12-27 14:53:00' }, + dateofbirth => [ { '>', '2019-12-27'}, { '=' => '2019-12-31' } ] + } + ); + $attrs = $patron->attributes_from_api( { last_seen => undef, -- 2.39.5