View | Details | Raw Unified | Return to bug 24502
Collapse All | Expand All

(-)a/Koha/REST/Plugin/Objects.pm (+4 lines)
Lines 97-102 sub register { Link Here
97
                }
97
                }
98
            }
98
            }
99
99
100
            if( defined $reserved_params->{q} ) {
101
                $filtered_params //={};
102
                $filtered_params = $c->merge_q_params( $filtered_params, $reserved_params->{q}, $result_set );
103
            }
100
            # Perform search
104
            # Perform search
101
            my $objects = $result_set->search( $filtered_params, $attributes );
105
            my $objects = $result_set->search( $filtered_params, $attributes );
102
106
(-)a/Koha/REST/Plugin/Query.pm (-1 / +72 lines)
Lines 20-25 use Modern::Perl; Link Here
20
use Mojo::Base 'Mojolicious::Plugin';
20
use Mojo::Base 'Mojolicious::Plugin';
21
use List::MoreUtils qw(any);
21
use List::MoreUtils qw(any);
22
use Scalar::Util qw(reftype);
22
use Scalar::Util qw(reftype);
23
use JSON qw(decode_json);
23
24
24
use Koha::Exceptions;
25
use Koha::Exceptions;
25
26
Lines 179-184 is raised. Link Here
179
        }
180
        }
180
    );
181
    );
181
182
183
=head3 merge_q_params
184
185
    $c->merge_q_params( $filtered_params, $q_params, $result_set );
186
187
Merges parameters from $q_params into $filtered_params.
188
189
=cut
190
191
    $app->helper(
192
        'merge_q_params' => sub {
193
194
            my ( $c, $filtered_params, $q_params, $result_set ) = @_;
195
196
            $q_params = decode_json($q_params) unless reftype $q_params;
197
            $q_params = $q_params->{q} if exists $q_params->{q} && scalar(keys %{$q_params}) == 1;
198
199
            my $params = _parse_dbic_query($q_params, $result_set);
200
201
            return $params unless scalar(keys %{$filtered_params});
202
            return {'-and' => [$params, $filtered_params ]};
203
        }
204
    );
205
182
=head3 stash_embed
206
=head3 stash_embed
183
207
184
    $c->stash_embed( $c->match->endpoint->pattern->defaults->{'openapi.op_spec'} );
208
    $c->stash_embed( $c->match->endpoint->pattern->defaults->{'openapi.op_spec'} );
Lines 229-235 is raised. Link Here
229
253
230
sub _reserved_words {
254
sub _reserved_words {
231
255
232
    my @reserved_words = qw( _match _order_by _page _per_page );
256
    my @reserved_words = qw( _match _order_by _page _per_page q );
233
    return \@reserved_words;
257
    return \@reserved_words;
234
}
258
}
235
259
Lines 340-343 sub _parse_prefetch { Link Here
340
    return $prefetch;
364
    return $prefetch;
341
}
365
}
342
366
367
sub _from_api_param {
368
    my ($key, $result_set) = @_;
369
370
    if($key =~ /\./) {
371
372
        my ($curr, $next) = split /\s*\.\s*/, $key, 2;
373
374
        my $ko_class = $result_set->prefetch_whitelist->{$curr};
375
376
        Koha::Exceptions::BadParameter->throw("Cannot find Koha::Object class for $curr")
377
            unless defined $ko_class;
378
379
        $result_set = $ko_class->new;
380
381
        if ($next =~ /\./) {
382
            return _from_api_param($next, $result_set);
383
        } else {
384
            return $curr.'.'.(defined $result_set->from_api_mapping ? $result_set->from_api_mapping->{$next}:$next);
385
        }
386
    } else {
387
        return defined $result_set->from_api_mapping->{$key} ? $result_set->from_api_mapping->{$key} : $key;
388
    }
389
}
390
391
sub _parse_dbic_query {
392
    my ($q_params, $result_set) = @_;
393
394
    if(reftype($q_params) && reftype($q_params) eq 'HASH') {
395
        my $parsed_hash;
396
        foreach my $key (keys %{$q_params}) {
397
            if($key =~ /-?(not_?)?bool/i ) {
398
                $parsed_hash->{$key} = _from_api_param($q_params->{$key}, $result_set);
399
                next;
400
            }
401
            my $k = _from_api_param($key, $result_set);
402
            $parsed_hash->{$k} = _parse_dbic_query($q_params->{$key}, $result_set);
403
        }
404
        return $parsed_hash;
405
    } elsif (reftype($q_params) && reftype($q_params) eq 'ARRAY') {
406
        my @mapped = map{ _parse_dbic_query($_, $result_set) } @$q_params;
407
        return \@mapped;
408
    } else {
409
        return $q_params;
410
    }
411
412
}
413
343
1;
414
1;
(-)a/t/Koha/REST/Plugin/Query.t (-1 / +60 lines)
Lines 23-28 use Try::Tiny; Link Here
23
23
24
use Koha::Cities;
24
use Koha::Cities;
25
use Koha::Holds;
25
use Koha::Holds;
26
use Koha::Biblios;
26
27
27
app->log->level('error');
28
app->log->level('error');
28
29
Lines 134-139 get '/dbic_merge_prefetch' => sub { Link Here
134
    $c->render( json => $attributes, status => 200 );
135
    $c->render( json => $attributes, status => 200 );
135
};
136
};
136
137
138
get '/merge_q_params' => sub {
139
  my $c = shift;
140
  my $filtered_params = {'biblio_id' => 1};
141
  my $result_set = Koha::Biblios->new;
142
  $filtered_params = $c->merge_q_params($filtered_params, $c->req->json->{q}, $result_set);
143
144
  $c->render( json => $filtered_params, status => 200 );
145
};
146
137
get '/build_query' => sub {
147
get '/build_query' => sub {
138
    my $c = shift;
148
    my $c = shift;
139
    my ( $filtered_params, $reserved_params ) =
149
    my ( $filtered_params, $reserved_params ) =
Lines 208-214 sub to_model { Link Here
208
218
209
# The tests
219
# The tests
210
220
211
use Test::More tests => 5;
221
use Test::More tests => 6;
212
use Test::Mojo;
222
use Test::Mojo;
213
223
214
subtest 'extract_reserved_params() tests' => sub {
224
subtest 'extract_reserved_params() tests' => sub {
Lines 296-301 subtest '/dbic_merge_prefetch' => sub { Link Here
296
      ->json_like( '/prefetch/1' => qr/item|biblio/ );
306
      ->json_like( '/prefetch/1' => qr/item|biblio/ );
297
};
307
};
298
308
309
subtest '/merge_q_params' => sub {
310
  plan tests => 3;
311
  my $t = Test::Mojo->new;
312
313
  $t->get_ok('/merge_q_params' => json => {
314
    q => {
315
      "-not_bool" => "suggestions.suggester.patron_card_lost",
316
      "-or" => [
317
        {
318
          "creation_date" => {
319
            "!=" => ["fff", "zzz", "xxx"]
320
          }
321
        },
322
        { "suggestions.suggester.housebound_profile.frequency" => "123" },
323
        {
324
          "suggestions.suggester.library_id" => {"like" => "%CPL%"}
325
        }
326
      ]
327
    }
328
  })->status_is(200)
329
    ->json_is( '/-and' => [
330
        {
331
          "-not_bool" => "suggester.lost",
332
          "-or" => [
333
            {
334
              "datecreated" => {
335
                "!=" => [
336
                  "fff",
337
                  "zzz",
338
                  "xxx"
339
                ]
340
              }
341
            },
342
            {
343
              "housebound_profile.frequency" => 123
344
            },
345
            {
346
              "suggester.branchcode" => {
347
                "like" => "\%CPL\%"
348
              }
349
            }
350
          ]
351
        },
352
        {
353
          "biblio_id" => 1
354
        }
355
      ]);
356
};
357
299
subtest '_build_query_params_from_api' => sub {
358
subtest '_build_query_params_from_api' => sub {
300
359
301
    plan tests => 16;
360
    plan tests => 16;
(-)a/t/db_dependent/Koha/REST/Plugin/Objects.t (-2 / +41 lines)
Lines 20-25 use Modern::Perl; Link Here
20
use Koha::Acquisition::Orders;
20
use Koha::Acquisition::Orders;
21
use Koha::Cities;
21
use Koha::Cities;
22
use Koha::Holds;
22
use Koha::Holds;
23
use Koha::Biblios;
23
24
24
# Dummy app for testing the plugin
25
# Dummy app for testing the plugin
25
use Mojolicious::Lite;
26
use Mojolicious::Lite;
Lines 55-62 get '/patrons/:patron_id/holds' => sub { Link Here
55
    $c->render( status => 200, json => {count => scalar(@$holds)} );
56
    $c->render( status => 200, json => {count => scalar(@$holds)} );
56
};
57
};
57
58
59
get '/biblios' => sub {
60
    my $c = shift;
61
    $c->validation->output($c->req->json);
62
    my $biblios_set = Koha::Biblios->new;
63
    $c->stash("koha.embed", {
64
        "suggestions" => {
65
            children => {
66
                "suggester" => {}
67
            }
68
        }
69
    });
70
    my $biblios = $c->objects->search($biblios_set);
71
72
    $c->render( status => 200, json => {count => scalar(@$biblios)} );
73
};
74
58
# The tests
75
# The tests
59
use Test::More tests => 4;
76
use Test::More tests => 5;
60
use Test::Mojo;
77
use Test::Mojo;
61
78
62
use t::lib::TestBuilder;
79
use t::lib::TestBuilder;
Lines 220-222 subtest 'objects.search helper, with path parameters and _match' => sub { Link Here
220
237
221
    $schema->storage->txn_rollback;
238
    $schema->storage->txn_rollback;
222
};
239
};
223
- 
240
241
subtest 'object.search helper with q parameter' => sub {
242
    plan tests => 4;
243
244
    $schema->storage->txn_begin;
245
246
    my $patron1 = $builder->build_object( { class => "Koha::Patrons" } );
247
    my $patron2 = $builder->build_object( { class => "Koha::Patrons" } );
248
    my $biblio1 = $builder->build_sample_biblio;
249
    my $biblio2 = $builder->build_sample_biblio;
250
    my $biblio3 = $builder->build_sample_biblio;
251
    my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } );
252
    my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } );
253
    my $suggestion3 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio3->biblionumber} } );
254
255
    $t->get_ok('/biblios' => json => {q => { "suggestions.suggester.patron_id" => $patron1->borrowernumber }})
256
      ->json_is('/count' => 1, 'there should be 1 biblio with suggestions of patron 1');
257
258
    $t->get_ok('/biblios' => json => {q => { "suggestions.suggester.patron_id" => $patron2->borrowernumber }})
259
      ->json_is('/count' => 2, 'there should be 2 biblios with suggestions of patron 2');
260
261
    $schema->storage->txn_rollback;
262
}

Return to bug 24502