Bug 19410: Move build_query_params_from_api into a helper

This patch creates the 'build_query_params' helper, instead of the
original function in Koha::Objects.

Unit tests are removed for Koha::Objects::_build_query_params_from_api and
written for the helper plugin.

The objects.search helper gets a call to build_query_params added. Tests for it
updated to match this behaviour change.

To test:
- Apply this patches
- Run:
  $ kshell
 k$ prove t/Koha/REST/Plugin/Query.t \
          t/db_dependent/Koha/Objects.t \
          t/db_dependent/Koha/REST/Plugin/Objects.t
=> SUCCESS: Tests pass!
- Sign off :-D

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Julian Maurice <julian.maurice@biblibre.com>

Signed-off-by: Lari Taskula <lari.taskula@jns.fi>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
Tomas Cohen Arazi 2017-11-21 16:12:08 -03:00 committed by Jonathan Druart
parent 86706c3b34
commit f1163dba9d
6 changed files with 172 additions and 125 deletions

View File

@ -171,47 +171,6 @@ sub search_related {
}
}
=head2 _build_query_params_from_api
my $params = _build_query_params_from_api( $filtered_params, $reserved_params );
Builds the params for searching on DBIC based on the selected matching algorithm.
Valid options are I<contains>, I<starts_with>, I<ends_with> and I<exact>. Default is
I<contains>. If other value is passed, a Koha::Exceptions::WrongParameter exception
is raised.
=cut
sub _build_query_params_from_api {
my ( $filtered_params, $reserved_params ) = @_;
my $params;
my $match = $reserved_params->{_match} // 'contains';
foreach my $param ( keys %{$filtered_params} ) {
if ( $match eq 'contains' ) {
$params->{$param} =
{ like => '%' . $filtered_params->{$param} . '%' };
}
elsif ( $match eq 'starts_with' ) {
$params->{$param} = { like => $filtered_params->{$param} . '%' };
}
elsif ( $match eq 'ends_with' ) {
$params->{$param} = { like => '%' . $filtered_params->{$param} };
}
elsif ( $match eq 'exact' ) {
$params->{$param} = $filtered_params->{$param};
}
else {
Koha::Exceptions::WrongParameter->throw(
"Invalid value for _match param ($match)");
}
}
return $params;
}
=head3 single
my $object = Koha::Objects->search({}, { rows => 1 })->single

View File

@ -67,6 +67,7 @@ sub register {
}
);
$filtered_params = $c->build_query_params( $filtered_params, $reserved_params );
# Perform search
my $objects = $objects_set->search( $filtered_params, $attributes );

View File

@ -19,6 +19,8 @@ use Modern::Perl;
use Mojo::Base 'Mojolicious::Plugin';
use Koha::Exceptions;
=head1 NAME
Koha::REST::Plugin::Query
@ -88,6 +90,51 @@ Generates the DBIC order_by attributes based on I<$params>, and merges into I<$a
return $attributes;
}
);
=head3 _build_query_params_from_api
my $params = _build_query_params_from_api( $filtered_params, $reserved_params );
Builds the params for searching on DBIC based on the selected matching algorithm.
Valid options are I<contains>, I<starts_with>, I<ends_with> and I<exact>. Default is
I<contains>. If other value is passed, a Koha::Exceptions::WrongParameter exception
is raised.
=cut
$app->helper(
'build_query_params' => sub {
my ( $c, $filtered_params, $reserved_params ) = @_;
my $params;
my $match = $reserved_params->{_match} // 'contains';
foreach my $param ( keys %{$filtered_params} ) {
if ( $match eq 'contains' ) {
$params->{$param} =
{ like => '%' . $filtered_params->{$param} . '%' };
}
elsif ( $match eq 'starts_with' ) {
$params->{$param} = { like => $filtered_params->{$param} . '%' };
}
elsif ( $match eq 'ends_with' ) {
$params->{$param} = { like => '%' . $filtered_params->{$param} };
}
elsif ( $match eq 'exact' ) {
$params->{$param} = $filtered_params->{$param};
}
else {
# We should never reach here, because the OpenAPI plugin should
# prevent invalid params to be passed
Koha::Exceptions::WrongParameter->throw(
"Invalid value for _match param ($match)");
}
}
return $params;
}
);
}
=head2 Internal methods

View File

@ -19,6 +19,7 @@ use Modern::Perl;
# Dummy app for testing the plugin
use Mojolicious::Lite;
use Try::Tiny;
app->log->level('error');
@ -79,9 +80,26 @@ get '/dbic_merge_sorting' => sub {
$c->render( json => $attributes, status => 200 );
};
get '/build_query' => sub {
my $c = shift;
my ( $filtered_params, $reserved_params ) =
$c->extract_reserved_params( $c->req->params->to_hash );
my $query;
try {
$query = $c->build_query_params( $filtered_params, $reserved_params );
$c->render( json => { query => $query }, status => 200 );
}
catch {
$c->render(
json => { exception_msg => $_->message, exception_type => ref($_) },
status => 400
);
};
};
# The tests
use Test::More tests => 2;
use Test::More tests => 3;
use Test::Mojo;
subtest 'extract_reserved_params() tests' => sub {
@ -128,3 +146,40 @@ subtest 'dbic_merge_sorting() tests' => sub {
]
);
};
subtest '_build_query_params_from_api' => sub {
plan tests => 16;
my $t = Test::Mojo->new;
# _match => contains
$t->get_ok('/build_query?_match=contains&title=Ender&author=Orson')
->status_is(200)
->json_is( '/query' =>
{ author => { like => '%Orson%' }, title => { like => '%Ender%' } } );
# _match => starts_with
$t->get_ok('/build_query?_match=starts_with&title=Ender&author=Orson')
->status_is(200)
->json_is( '/query' =>
{ author => { like => 'Orson%' }, title => { like => 'Ender%' } } );
# _match => ends_with
$t->get_ok('/build_query?_match=ends_with&title=Ender&author=Orson')
->status_is(200)
->json_is( '/query' =>
{ author => { like => '%Orson' }, title => { like => '%Ender' } } );
# _match => exact
$t->get_ok('/build_query?_match=exact&title=Ender&author=Orson')
->status_is(200)
->json_is( '/query' => { author => 'Orson', title => 'Ender' } );
# _match => blah
$t->get_ok('/build_query?_match=blah&title=Ender&author=Orson')
->status_is(400)
->json_is( '/exception_msg' => 'Invalid value for _match param (blah)' )
->json_is( '/exception_type' => 'Koha::Exceptions::WrongParameter' );
};

View File

@ -19,7 +19,7 @@
use Modern::Perl;
use Test::More tests => 16;
use Test::More tests => 15;
use Test::Exception;
use Test::Warn;
@ -239,66 +239,3 @@ subtest '->is_paged and ->pager tests' => sub {
$schema->storage->txn_rollback;
};
subtest '_build_query_params_from_api' => sub {
plan tests => 5;
my $filtered_params = {
title => "Ender",
author => "Orson"
};
subtest '_match => contains' => sub {
plan tests => 2;
my $reserved_params = { _match => 'contains' };
my $params = Koha::Objects::_build_query_params_from_api( $filtered_params, $reserved_params );
is_deeply( $params->{author}, { like => '%Orson%' } );
is_deeply( $params->{title}, { like => '%Ender%' } );
};
subtest '_match => starts_with' => sub {
plan tests => 2;
my $reserved_params = { _match => 'starts_with' };
my $params = Koha::Objects::_build_query_params_from_api( $filtered_params, $reserved_params );
is_deeply( $params->{author}, { like => 'Orson%' } );
is_deeply( $params->{title}, { like => 'Ender%' } );
};
subtest '_match => ends_with' => sub {
plan tests => 2;
my $reserved_params = { _match => 'ends_with' };
my $params = Koha::Objects::_build_query_params_from_api( $filtered_params, $reserved_params );
is_deeply( $params->{author}, { like => '%Orson' } );
is_deeply( $params->{title}, { like => '%Ender' } );
};
subtest '_match => exact' => sub {
plan tests => 2;
my $reserved_params = { _match => 'exact' };
my $params = Koha::Objects::_build_query_params_from_api( $filtered_params, $reserved_params );
is( $params->{author}, 'Orson' );
is( $params->{title}, 'Ender' );
};
subtest '_match => blah' => sub {
plan tests => 2;
my $reserved_params = { _match => 'blah' };
throws_ok {
Koha::Objects::_build_query_params_from_api( $filtered_params,
$reserved_params );
}
'Koha::Exceptions::WrongParameter',
'Exception thrown on invalid _match parameter';
is( $@,
'Invalid value for _match param (blah)',
'Exception carries the right message'
);
};
};

View File

@ -31,12 +31,11 @@ get '/patrons' => sub {
my $c = shift;
$c->validation->output($c->req->params->to_hash);
my $patrons = $c->objects->search(Koha::Patrons->new);
$c->render( status => 200, json => $patrons->TO_JSON );
$c->render( status => 200, json => $patrons );
};
# The tests
use Test::More tests => 1;
use Test::Mojo;
@ -44,34 +43,83 @@ use t::lib::TestBuilder;
use Koha::Database;
my $schema = Koha::Database->new()->schema();
$schema->storage->txn_begin();
my $builder = t::lib::TestBuilder->new;
$builder->build({
source => 'Borrower',
value => {
firstname => 'Manuel',
},
});
$builder->build({
source => 'Borrower',
value => {
firstname => 'Manuel',
},
});
subtest 'objects.search helper' => sub {
plan tests => 6;
plan tests => 34;
my $t = Test::Mojo->new;
$t->get_ok('/patrons?firstname=Manuel&_per_page=1&_page=1')
$schema->storage->txn_begin;
# Delete existing patrons
Koha::Patrons->search->delete;
# Create two sample patrons that match the query
$builder->build_object({
class => 'Koha::Patrons',
value => {
firstname => 'Manuel'
}
});
$builder->build_object({
class => 'Koha::Patrons',
value => {
firstname => 'Manuela'
}
});
$t->get_ok('/patrons?firstname=manuel&_per_page=1&_page=1')
->status_is(200)
->header_like( 'Link' => qr/<http:\/\/.*\?.*&_page=2.*>; rel="next",/ )
->json_has('/0')
->json_hasnt('/1')
->json_is('/0/firstname' => 'Manuel');
};
$schema->storage->txn_rollback();
$builder->build_object({
class => 'Koha::Patrons',
value => {
firstname => 'Emanuel'
}
});
# _match=starts_with
$t->get_ok('/patrons?firstname=manuel&_per_page=3&_page=1&_match=starts_with')
->status_is(200)
->json_has('/0')
->json_has('/1')
->json_hasnt('/2')
->json_is('/0/firstname' => 'Manuel')
->json_is('/1/firstname' => 'Manuela');
# _match=ends_with
$t->get_ok('/patrons?firstname=manuel&_per_page=3&_page=1&_match=ends_with')
->status_is(200)
->json_has('/0')
->json_has('/1')
->json_hasnt('/2')
->json_is('/0/firstname' => 'Manuel')
->json_is('/1/firstname' => 'Emanuel');
# _match=exact
$t->get_ok('/patrons?firstname=manuel&_per_page=3&_page=1&_match=exact')
->status_is(200)
->json_has('/0')
->json_hasnt('/1')
->json_is('/0/firstname' => 'Manuel');
# _match=contains
$t->get_ok('/patrons?firstname=manuel&_per_page=3&_page=1&_match=contains')
->status_is(200)
->json_has('/0')
->json_has('/1')
->json_has('/2')
->json_hasnt('/3')
->json_is('/0/firstname' => 'Manuel')
->json_is('/1/firstname' => 'Manuela')
->json_is('/2/firstname' => 'Emanuel');
$schema->storage->txn_rollback;
};