@@ -, +, @@ in query params "-and":[ [ { "extended_attributes.value":{ "like":"abc%" }, "extended_attributes.code":[ [ "arbitrary_attr_code", "another_attr_code" ] ] } ], [ { "extended_attributes.value":{ "like":"123%" }, "extended_attributes.code":[ [ "arbitrary_attr_code", "another_attr_code" ] ] } ] ] "-and":[ [ { "extended_attributes.value":{ "like":"abc%" }, "extended_attributes.code":[ [ "arbitrary_attr_code", "another_attr_code" ] ] } ], [ { "extended_attributes_2.value":{ "like":"123%" }, "extended_attributes_2.code":[ [ "arbitrary_attr_code", "another_attr_code" ] ] } ] ] --- Koha/REST/Plugin/Objects.pm | 8 ++ Koha/REST/Plugin/Query.pm | 152 ++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) --- a/Koha/REST/Plugin/Objects.pm +++ a/Koha/REST/Plugin/Objects.pm @@ -287,6 +287,14 @@ controller, and thus shouldn't be called twice in it. $c->stash('koha.pagination.base_total' => $result_set->count); $c->stash('koha.pagination.query_params' => $args); + # Check and handle related metadata table joins + $c->dbic_extended_attributes_join( + { + attributes => $attributes, + filtered_params => $filtered_params + } + ); + # Generate the resultset my $objects_rs = $result_set->search( $filtered_params, $attributes ); # Stash the page total if requires, total otherwise --- a/Koha/REST/Plugin/Query.pm +++ a/Koha/REST/Plugin/Query.pm @@ -159,6 +159,34 @@ Generates the DBIC prefetch attribute based on embedded relations, and merges in } ); +=head3 dbic_extended_attributes_join + + $attributes = $c->dbic_extended_attributes_join({ attributes => $attributes, result_set => $result_set }); + +Generates the DBIC join attribute based on extended_attributes query entries, and merges into I<$attributes>. + +=cut + + $app->helper( + 'dbic_extended_attributes_join' => sub { + my ( $c, $args ) = @_; + + my $attributes = $args->{attributes}; + my $filtered_params = $args->{filtered_params}; + + if ( reftype( $attributes->{prefetch} ) + && reftype( $attributes->{prefetch} ) eq 'ARRAY' + && grep ( /extended_attributes/, @{ $attributes->{prefetch} } ) ) + { + my $ea_entries = $self->_get_extended_attributes_entries( $filtered_params, 0 ); + while ( $ea_entries > 0 ) { + push( @{ $attributes->{join} }, 'extended_attributes' ); + $ea_entries--; + } + } + } + ); + =head3 _build_query_params_from_api my $params = _build_query_params_from_api( $filtered_params, $reserved_params ); @@ -486,7 +514,131 @@ sub _parse_dbic_query { } else { return $q_params; } +} + +=head3 _get_extended_attributes_entries + + $self->_get_extended_attributes_entries( $filtered_params, 0 ) + +Recursive function that returns the number of extended_attributes entries present in a query. +Example: Returns 2 if given a $filtered_params containing the below: + +{ + "-and":[ + [ + { + "extended_attributes.value":{ + "like":"abc%" + }, + "extended_attributes.code":[ + [ + "arbitrary_attr_code", + "another_attr_code" + ] + ] + } + ], + [ + { + "extended_attributes.value":{ + "like":"123%" + }, + "extended_attributes.code":[ + [ + "arbitrary_attr_code", + "another_attr_code" + ] + ] + } + ] + ] +} + +=cut + +sub _get_extended_attributes_entries { + my ( $self, $params, $extended_attributes_entries ) = @_; + + if ( reftype($params) && reftype($params) eq 'HASH' ) { + + # rewrite additional_field_values table query params + $extended_attributes_entries = + _rewrite_related_metadata_query( $params, $extended_attributes_entries, 'field_id', 'value' ) + if $params->{'extended_attributes.field_id'}; + + # rewrite borrower_attributes table query params + $extended_attributes_entries = + _rewrite_related_metadata_query( $params, $extended_attributes_entries, 'code', 'attribute' ) + if $params->{'extended_attributes.code'}; + + # rewrite illrequestattributes table query params + $extended_attributes_entries = + _rewrite_related_metadata_query( $params, $extended_attributes_entries, 'type', 'value' ) + if $params->{'extended_attributes.type'}; + + foreach my $key ( keys %{$params} ) { + return $self->_get_extended_attributes_entries( $params->{$key}, $extended_attributes_entries ); + } + } elsif ( reftype($params) && reftype($params) eq 'ARRAY' ) { + foreach my $ea_instance (@$params) { + $extended_attributes_entries = + +$self->_get_extended_attributes_entries( $ea_instance, $extended_attributes_entries ); + } + return $extended_attributes_entries; + } else { + return $extended_attributes_entries; + } +} + +=head3 _rewrite_related_metadata_query + + $extended_attributes_entries = + _rewrite_related_metadata_query( $params, $extended_attributes_entries, 'field_id', 'value' ) + +Helper function that rewrites all subsequent extended_attributes queries to match the alias generated by the dbic self left join +Take the below example (patrons), assuming it is the third instance of an extended_attributes query: +{ + "extended_attributes.value":{ + "like":"123%" + }, + "extended_attributes.code":[ + [ + "arbitrary_attr_code", + "another_attr_code" + ] + ] +} + +It'll be rewritten as: +{ + "extended_attributes_3.value":{ + "like":"123%" + }, + "extended_attributes_3.code":[ + [ + "arbitrary_attr_code", + "another_attr_code" + ] + ] +} + +=cut + +sub _rewrite_related_metadata_query { + my ( $params, $extended_attributes_entries, $key, $value ) = @_; + + $extended_attributes_entries++; + if ( $extended_attributes_entries > 1 ) { + my $old_key_value = delete $params->{ 'extended_attributes.' . $key }; + my $new_key_value = "extended_attributes_$extended_attributes_entries" . "." . $key; + $params->{$new_key_value} = $old_key_value; + + my $old_value_value = delete $params->{ 'extended_attributes.' . $value }; + my $new_value_value = "extended_attributes_$extended_attributes_entries" . "." . $value; + $params->{$new_value_value} = $old_value_value; + } + return $extended_attributes_entries; } 1; --