Bugzilla – Attachment 98185 Details for
Bug 24502
Add a query language and param (q=) to the API
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 24502: object.search also filter by prefetched columns
Bug-24502-objectsearch-also-filter-by-prefetched-c.patch (text/plain), 9.31 KB, created by
Agustín Moyano
on 2020-01-30 19:27:18 UTC
(
hide
)
Description:
Bug 24502: object.search also filter by prefetched columns
Filename:
MIME Type:
Creator:
Agustín Moyano
Created:
2020-01-30 19:27:18 UTC
Size:
9.31 KB
patch
obsolete
>From 284053abcdf982b156bbf95fa466ebe62ad60994 Mon Sep 17 00:00:00 2001 >From: Agustin Moyano <agustinmoyano@theke.io> >Date: Fri, 24 Jan 2020 23:59:32 -0300 >Subject: [PATCH] Bug 24502: object.search also filter by prefetched columns > >This patch adds the possibility to object.search helper, to also filter by prefetched columns. > >In order to dynamically add filter parameters, they must be coded as json and placed in the body of the request, within the q parameter. > >The coded json, is in fact dbix syntax. > >To test: >1. apply this patch >2. prove t/Koha/REST/Plugin/Query.t t/db_dependent/Koha/REST/Plugin/Objects.t >3. Sign off >--- > Koha/REST/Plugin/Objects.pm | 4 ++ > Koha/REST/Plugin/Query.pm | 73 ++++++++++++++++++++++- > t/Koha/REST/Plugin/Query.t | 61 ++++++++++++++++++- > t/db_dependent/Koha/REST/Plugin/Objects.t | 42 ++++++++++++- > 4 files changed, 177 insertions(+), 3 deletions(-) > >diff --git a/Koha/REST/Plugin/Objects.pm b/Koha/REST/Plugin/Objects.pm >index b120f4842c..ef2631fc63 100644 >--- a/Koha/REST/Plugin/Objects.pm >+++ b/Koha/REST/Plugin/Objects.pm >@@ -97,6 +97,10 @@ sub register { > } > } > >+ if( defined $reserved_params->{q} ) { >+ $filtered_params //={}; >+ $filtered_params = $c->merge_q_params( $filtered_params, $reserved_params->{q}, $result_set ); >+ } > # Perform search > my $objects = $result_set->search( $filtered_params, $attributes ); > >diff --git a/Koha/REST/Plugin/Query.pm b/Koha/REST/Plugin/Query.pm >index 2d2463222f..db8215df88 100644 >--- a/Koha/REST/Plugin/Query.pm >+++ b/Koha/REST/Plugin/Query.pm >@@ -20,6 +20,7 @@ use Modern::Perl; > use Mojo::Base 'Mojolicious::Plugin'; > use List::MoreUtils qw(any); > use Scalar::Util qw(reftype); >+use JSON qw(decode_json); > > use Koha::Exceptions; > >@@ -179,6 +180,29 @@ is raised. > } > ); > >+=head3 merge_q_params >+ >+ $c->merge_q_params( $filtered_params, $q_params, $result_set ); >+ >+Merges parameters from $q_params into $filtered_params. >+ >+=cut >+ >+ $app->helper( >+ 'merge_q_params' => sub { >+ >+ my ( $c, $filtered_params, $q_params, $result_set ) = @_; >+ >+ $q_params = decode_json($q_params) unless reftype $q_params; >+ $q_params = $q_params->{q} if exists $q_params->{q} && scalar(keys %{$q_params}) == 1; >+ >+ my $params = _parse_dbic_query($q_params, $result_set); >+ >+ return $params unless scalar(keys %{$filtered_params}); >+ return {'-and' => [$params, $filtered_params ]}; >+ } >+ ); >+ > =head3 stash_embed > > $c->stash_embed( $c->match->endpoint->pattern->defaults->{'openapi.op_spec'} ); >@@ -229,7 +253,7 @@ is raised. > > sub _reserved_words { > >- my @reserved_words = qw( _match _order_by _page _per_page ); >+ my @reserved_words = qw( _match _order_by _page _per_page q ); > return \@reserved_words; > } > >@@ -340,4 +364,51 @@ sub _parse_prefetch { > return $prefetch; > } > >+sub _from_api_param { >+ my ($key, $result_set) = @_; >+ >+ if($key =~ /\./) { >+ >+ my ($curr, $next) = split /\s*\.\s*/, $key, 2; >+ >+ my $ko_class = $result_set->prefetch_whitelist->{$curr}; >+ >+ Koha::Exceptions::BadParameter->throw("Cannot find Koha::Object class for $curr") >+ unless defined $ko_class; >+ >+ $result_set = $ko_class->new; >+ >+ if ($next =~ /\./) { >+ return _from_api_param($next, $result_set); >+ } else { >+ return $curr.'.'.(defined $result_set->from_api_mapping ? $result_set->from_api_mapping->{$next}:$next); >+ } >+ } else { >+ return defined $result_set->from_api_mapping->{$key} ? $result_set->from_api_mapping->{$key} : $key; >+ } >+} >+ >+sub _parse_dbic_query { >+ my ($q_params, $result_set) = @_; >+ >+ if(reftype($q_params) && reftype($q_params) eq 'HASH') { >+ my $parsed_hash; >+ foreach my $key (keys %{$q_params}) { >+ if($key =~ /-?(not_?)?bool/i ) { >+ $parsed_hash->{$key} = _from_api_param($q_params->{$key}, $result_set); >+ next; >+ } >+ my $k = _from_api_param($key, $result_set); >+ $parsed_hash->{$k} = _parse_dbic_query($q_params->{$key}, $result_set); >+ } >+ return $parsed_hash; >+ } elsif (reftype($q_params) && reftype($q_params) eq 'ARRAY') { >+ my @mapped = map{ _parse_dbic_query($_, $result_set) } @$q_params; >+ return \@mapped; >+ } else { >+ return $q_params; >+ } >+ >+} >+ > 1; >diff --git a/t/Koha/REST/Plugin/Query.t b/t/Koha/REST/Plugin/Query.t >index 46e4760c68..ca9aeb839d 100644 >--- a/t/Koha/REST/Plugin/Query.t >+++ b/t/Koha/REST/Plugin/Query.t >@@ -23,6 +23,7 @@ use Try::Tiny; > > use Koha::Cities; > use Koha::Holds; >+use Koha::Biblios; > > app->log->level('error'); > >@@ -134,6 +135,15 @@ get '/dbic_merge_prefetch' => sub { > $c->render( json => $attributes, status => 200 ); > }; > >+get '/merge_q_params' => sub { >+ my $c = shift; >+ my $filtered_params = {'biblio_id' => 1}; >+ my $result_set = Koha::Biblios->new; >+ $filtered_params = $c->merge_q_params($filtered_params, $c->req->json->{q}, $result_set); >+ >+ $c->render( json => $filtered_params, status => 200 ); >+}; >+ > get '/build_query' => sub { > my $c = shift; > my ( $filtered_params, $reserved_params ) = >@@ -208,7 +218,7 @@ sub to_model { > > # The tests > >-use Test::More tests => 5; >+use Test::More tests => 6; > use Test::Mojo; > > subtest 'extract_reserved_params() tests' => sub { >@@ -296,6 +306,55 @@ subtest '/dbic_merge_prefetch' => sub { > ->json_like( '/prefetch/1' => qr/item|biblio/ ); > }; > >+subtest '/merge_q_params' => sub { >+ plan tests => 3; >+ my $t = Test::Mojo->new; >+ >+ $t->get_ok('/merge_q_params' => json => { >+ q => { >+ "-not_bool" => "suggestions.suggester.patron_card_lost", >+ "-or" => [ >+ { >+ "creation_date" => { >+ "!=" => ["fff", "zzz", "xxx"] >+ } >+ }, >+ { "suggestions.suggester.housebound_profile.frequency" => "123" }, >+ { >+ "suggestions.suggester.library_id" => {"like" => "%CPL%"} >+ } >+ ] >+ } >+ })->status_is(200) >+ ->json_is( '/-and' => [ >+ { >+ "-not_bool" => "suggester.lost", >+ "-or" => [ >+ { >+ "datecreated" => { >+ "!=" => [ >+ "fff", >+ "zzz", >+ "xxx" >+ ] >+ } >+ }, >+ { >+ "housebound_profile.frequency" => 123 >+ }, >+ { >+ "suggester.branchcode" => { >+ "like" => "\%CPL\%" >+ } >+ } >+ ] >+ }, >+ { >+ "biblio_id" => 1 >+ } >+ ]); >+}; >+ > subtest '_build_query_params_from_api' => sub { > > plan tests => 16; >diff --git a/t/db_dependent/Koha/REST/Plugin/Objects.t b/t/db_dependent/Koha/REST/Plugin/Objects.t >index 9785d7e3f0..9831d44d92 100644 >--- a/t/db_dependent/Koha/REST/Plugin/Objects.t >+++ b/t/db_dependent/Koha/REST/Plugin/Objects.t >@@ -20,6 +20,7 @@ use Modern::Perl; > use Koha::Acquisition::Orders; > use Koha::Cities; > use Koha::Holds; >+use Koha::Biblios; > > # Dummy app for testing the plugin > use Mojolicious::Lite; >@@ -55,8 +56,24 @@ get '/patrons/:patron_id/holds' => sub { > $c->render( status => 200, json => {count => scalar(@$holds)} ); > }; > >+get '/biblios' => sub { >+ my $c = shift; >+ $c->validation->output($c->req->json); >+ my $biblios_set = Koha::Biblios->new; >+ $c->stash("koha.embed", { >+ "suggestions" => { >+ children => { >+ "suggester" => {} >+ } >+ } >+ }); >+ my $biblios = $c->objects->search($biblios_set); >+ >+ $c->render( status => 200, json => {count => scalar(@$biblios)} ); >+}; >+ > # The tests >-use Test::More tests => 4; >+use Test::More tests => 5; > use Test::Mojo; > > use t::lib::TestBuilder; >@@ -220,3 +237,26 @@ subtest 'objects.search helper, with path parameters and _match' => sub { > > $schema->storage->txn_rollback; > }; >+ >+subtest 'object.search helper with q parameter' => sub { >+ plan tests => 4; >+ >+ $schema->storage->txn_begin; >+ >+ my $patron1 = $builder->build_object( { class => "Koha::Patrons" } ); >+ my $patron2 = $builder->build_object( { class => "Koha::Patrons" } ); >+ my $biblio1 = $builder->build_sample_biblio; >+ my $biblio2 = $builder->build_sample_biblio; >+ my $biblio3 = $builder->build_sample_biblio; >+ my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } ); >+ my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } ); >+ my $suggestion3 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio3->biblionumber} } ); >+ >+ $t->get_ok('/biblios' => json => {q => { "suggestions.suggester.patron_id" => $patron1->borrowernumber }}) >+ ->json_is('/count' => 1, 'there should be 1 biblio with suggestions of patron 1'); >+ >+ $t->get_ok('/biblios' => json => {q => { "suggestions.suggester.patron_id" => $patron2->borrowernumber }}) >+ ->json_is('/count' => 2, 'there should be 2 biblios with suggestions of patron 2'); >+ >+ $schema->storage->txn_rollback; >+} >-- >2.17.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 24502
:
97934
|
98185
|
98186
|
98596
|
98597
|
98605
|
98606
|
98611
|
99252
|
99253
|
99351
|
99352
|
99946
|
99947