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

(-)a/Koha/REST/Plugin/Objects.pm (-30 / +115 lines)
Lines 38-47 sub register { Link Here
38
38
39
    my $patrons_rs = Koha::Patrons->new;
39
    my $patrons_rs = Koha::Patrons->new;
40
    my $patrons = $c->objects->find( $patrons_rs, $id );
40
    my $patrons = $c->objects->find( $patrons_rs, $id );
41
    . . .
42
    return $c->render({ status => 200, openapi => $patron });
41
43
42
Performs a database search using given Koha::Objects object and the $id.
44
Performs a database search using given Koha::Objects object and the $id.
43
45
44
Returns I<undef> if no object is found Returns the I<API representation> of
46
Returns I<undef> if no object is found or the I<API representation> of
45
the requested object. It passes through any embeds if specified.
47
the requested object. It passes through any embeds if specified.
46
48
47
=cut
49
=cut
Lines 49-60 the requested object. It passes through any embeds if specified. Link Here
49
    $app->helper(
51
    $app->helper(
50
        'objects.find' => sub {
52
        'objects.find' => sub {
51
            my ( $c, $result_set, $id ) = @_;
53
            my ( $c, $result_set, $id ) = @_;
54
            my $object = $c->objects->find_rs( $result_set, $id );
55
            return unless $object;
56
            return $c->objects->to_api($object);
57
        }
58
    );
52
59
53
            my $attributes = {};
54
60
55
            # Look for embeds
61
=head3 objects.find_rs
56
            my $embed   = $c->stash('koha.embed');
62
57
            my $strings = $c->stash('koha.strings');
63
    my $patrons_rs = Koha::Patrons->new;
64
    my $patron_rs = $c->objects->find_rs( $patrons_rs, $id );
65
    . . .
66
    return $c->render({ status => 200, openapi => $patron_rs->to_api });
67
68
Returns the passed Koha::Objects resultset filtered to the passed $id and
69
with any embeds requested by the api applied.
70
71
The resultset can then be used for further processing.
72
73
=cut
74
75
    $app->helper(
76
        'objects.find_rs' => sub {
77
            my ( $c, $result_set, $id ) = @_;
78
79
            my $attributes = {};
58
80
59
            # Generate prefetches for embedded stuff
81
            # Generate prefetches for embedded stuff
60
            $c->dbic_merge_prefetch(
82
            $c->dbic_merge_prefetch(
Lines 66-74 the requested object. It passes through any embeds if specified. Link Here
66
88
67
            my $object = $result_set->find( $id, $attributes );
89
            my $object = $result_set->find( $id, $attributes );
68
90
69
            return unless $object;
91
            return $object;
70
71
            return $object->to_api({ embed => $embed, strings => $strings });
72
        }
92
        }
73
    );
93
    );
74
94
Lines 76-83 the requested object. It passes through any embeds if specified. Link Here
76
96
77
    my $patrons_rs = Koha::Patrons->new;
97
    my $patrons_rs = Koha::Patrons->new;
78
    my $patrons = $c->objects->search( $patrons_rs );
98
    my $patrons = $c->objects->search( $patrons_rs );
99
    . . .
100
    return $c->render({ status => 200, openapi => $patrons });
79
101
80
Performs a database search using given Koha::Objects object and query parameters.
102
Performs a database search using given Koha::Objects object with any api
103
query parameters applied.
81
104
82
Returns an arrayref of the hashrefs representing the resulting objects
105
Returns an arrayref of the hashrefs representing the resulting objects
83
for API rendering.
106
for API rendering.
Lines 91-106 shouldn't be called twice in it. Link Here
91
        'objects.search' => sub {
114
        'objects.search' => sub {
92
            my ( $c, $result_set ) = @_;
115
            my ( $c, $result_set ) = @_;
93
116
94
            my $args = $c->validation->output;
117
            return $c->objects->to_api( $c->objects->search_rs($result_set) );
118
        }
119
    );
120
121
=head3 objects.search_rs
122
123
    my $patrons_rs = Koha::Patrons->new;
124
    my $patrons_rs = $c->objects->search_rs( $patrons_rs );
125
    . . .
126
    return $c->render({ status => 200, openapi => $patrons_rs->to_api });
127
128
Returns the passed Koha::Objects resultset filtered as requested by the api query
129
parameters and with requested embeds applied.
130
131
Warning: this helper adds pagination headers to the calling controller, and thus
132
shouldn't be called twice in it.
133
134
=cut
135
136
    $app->helper(
137
        'objects.search_rs' => sub {
138
            my ( $c, $result_set ) = @_;
139
140
            my $args       = $c->validation->output;
95
            my $attributes = {};
141
            my $attributes = {};
96
142
97
            # Extract reserved params
143
            # Extract reserved params
98
            my ( $filtered_params, $reserved_params, $path_params ) = $c->extract_reserved_params($args);
144
            my ( $filtered_params, $reserved_params, $path_params ) =
99
            # Privileged reques?
145
              $c->extract_reserved_params($args);
100
            my $is_public = $c->stash('is_public');
101
            # Look for embeds
102
            my $embed   = $c->stash('koha.embed');
103
            my $strings = $c->stash('koha.strings');
104
146
105
            # Merge sorting into query attributes
147
            # Merge sorting into query attributes
106
            $c->dbic_merge_sorting(
148
            $c->dbic_merge_sorting(
Lines 112-121 shouldn't be called twice in it. Link Here
112
            );
154
            );
113
155
114
            # If no pagination parameters are passed, default
156
            # If no pagination parameters are passed, default
115
            $reserved_params->{_per_page} //= C4::Context->preference('RESTdefaultPageSize');
157
            $reserved_params->{_per_page} //=
116
            $reserved_params->{_page}     //= 1;
158
              C4::Context->preference('RESTdefaultPageSize');
159
            $reserved_params->{_page} //= 1;
117
160
118
            unless ( $reserved_params->{_per_page} == -1 ) {
161
            unless ( $reserved_params->{_per_page} == -1 ) {
162
119
                # Merge pagination into query attributes
163
                # Merge pagination into query attributes
120
                $c->dbic_merge_pagination(
164
                $c->dbic_merge_pagination(
121
                    {
165
                    {
Lines 137-144 shouldn't be called twice in it. Link Here
137
            if ( defined $filtered_params ) {
181
            if ( defined $filtered_params ) {
138
182
139
                # Apply the mapping function to the passed params
183
                # Apply the mapping function to the passed params
140
                $filtered_params = $result_set->attributes_from_api($filtered_params);
184
                $filtered_params =
141
                $filtered_params = $c->build_query_params( $filtered_params, $reserved_params );
185
                  $result_set->attributes_from_api($filtered_params);
186
                $filtered_params =
187
                  $c->build_query_params( $filtered_params, $reserved_params );
142
            }
188
            }
143
189
144
            if (   defined $reserved_params->{q}
190
            if (   defined $reserved_params->{q}
Lines 155-172 shouldn't be called twice in it. Link Here
155
201
156
                my $json = JSON->new;
202
                my $json = JSON->new;
157
203
158
                if ( ref($reserved_params->{q}) eq 'ARRAY' ) {
204
                if ( ref( $reserved_params->{q} ) eq 'ARRAY' ) {
159
                    # q is defined as multi => JSON::Validator generates an array
205
206
                   # q is defined as multi => JSON::Validator generates an array
160
                    foreach my $q ( @{ $reserved_params->{q} } ) {
207
                    foreach my $q ( @{ $reserved_params->{q} } ) {
161
                        push @query_params_array, $json->decode($q)
208
                        push @query_params_array, $json->decode($q)
162
                        if $q; # skip if exists but is empty
209
                          if $q;    # skip if exists but is empty
163
                    }
210
                    }
164
                }
211
                }
165
                else {
212
                else {
166
                    # objects.search called outside OpenAPI context
213
                    # objects.search called outside OpenAPI context
167
                    # might be a hashref
214
                    # might be a hashref
168
                    push @query_params_array, $json->decode($reserved_params->{q})
215
                    push @query_params_array,
169
                        if $reserved_params->{q};
216
                      $json->decode( $reserved_params->{q} )
217
                      if $reserved_params->{q};
170
                }
218
                }
171
219
172
                push @query_params_array,
220
                push @query_params_array,
Lines 182-197 shouldn't be called twice in it. Link Here
182
                    $query_params = $query_params_array[0];
230
                    $query_params = $query_params_array[0];
183
                }
231
                }
184
232
185
                $filtered_params = $c->merge_q_params( $filtered_params, $query_params, $result_set );
233
                $filtered_params =
234
                  $c->merge_q_params( $filtered_params, $query_params,
235
                    $result_set );
186
            }
236
            }
187
237
188
            # request sequence id (i.e. 'draw' Datatables parameter)
238
            # request sequence id (i.e. 'draw' Datatables parameter)
189
            $c->res->headers->add( 'x-koha-request-id' => $reserved_params->{'x-koha-request-id'} )
239
            $c->res->headers->add(
240
                'x-koha-request-id' => $reserved_params->{'x-koha-request-id'} )
190
              if $reserved_params->{'x-koha-request-id'};
241
              if $reserved_params->{'x-koha-request-id'};
191
242
192
            # If search_limited exists, use it
243
            # If search_limited exists, use it
193
            $result_set = $result_set->search_limited,
244
            $result_set = $result_set->search_limited,
194
                if $result_set->can('search_limited');
245
              if $result_set->can('search_limited');
195
246
196
            # Perform search
247
            # Perform search
197
            my $objects = $result_set->search( $filtered_params, $attributes );
248
            my $objects = $result_set->search( $filtered_params, $attributes );
Lines 199-211 shouldn't be called twice in it. Link Here
199
250
200
            $c->add_pagination_headers(
251
            $c->add_pagination_headers(
201
                {
252
                {
202
                    total      => ($objects->is_paged ? $objects->pager->total_entries : $objects->count),
253
                    total => (
254
                          $objects->is_paged
255
                        ? $objects->pager->total_entries
256
                        : $objects->count
257
                    ),
203
                    base_total => $total,
258
                    base_total => $total,
204
                    params     => $args,
259
                    params     => $args,
205
                }
260
                }
206
            );
261
            );
207
262
208
            return $objects->to_api({ embed => $embed, public => $is_public, strings => $strings });
263
            return $objects;
264
        }
265
    );
266
267
=head3 objects.to_api
268
269
    my $patrons_rs = Koha::Patrons->new;
270
    my $api_representation = $c->objects->to_api( $patrons_rs );
271
272
Returns the API representation of the passed resultset.
273
274
=cut
275
276
    $app->helper(
277
        'objects.to_api' => sub {
278
            my ( $c, $object ) = @_;
279
280
            # Privileged request?
281
            my $public = $c->stash('is_public');
282
283
            # Look for embeds
284
            my $embed   = $c->stash('koha.embed');
285
            my $strings = $c->stash('koha.strings');
286
287
            return $object->to_api(
288
                {
289
                    embed   => $embed,
290
                    public  => $public,
291
                    strings => $strings
292
                }
293
            );
209
        }
294
        }
210
    );
295
    );
211
}
296
}
(-)a/t/db_dependent/Koha/REST/Plugin/Objects.t (-2 / +110 lines)
Lines 43-48 get '/cities' => sub { Link Here
43
    $c->render( status => 200, json => $cities );
43
    $c->render( status => 200, json => $cities );
44
};
44
};
45
45
46
get '/cities/rs' => sub {
47
    my $c = shift;
48
    $c->validation->output( $c->req->params->to_hash );
49
    $c->stash_embed;
50
    my $cities = $c->objects->search_rs( Koha::Cities->new );
51
52
    $c->render( status => 200, json => { count => $cities->count } );
53
};
54
46
get '/cities/:city_id' => sub {
55
get '/cities/:city_id' => sub {
47
    my $c = shift;
56
    my $c = shift;
48
    my $id = $c->stash("city_id");
57
    my $id = $c->stash("city_id");
Lines 120-127 get '/my_patrons' => sub { Link Here
120
    );
129
    );
121
};
130
};
122
131
132
get '/cities/:city_id/rs' => sub {
133
    my $c = shift;
134
    $c->validation->output( $c->req->params->to_hash );
135
    $c->stash_embed;
136
    my $city_id = $c->param('city_id');
137
    my $city    = $c->objects->find_rs( Koha::Cities->new, $city_id );
138
139
    $c->render( status => 200, json => { name => $city->city_name } );
140
};
141
123
# The tests
142
# The tests
124
use Test::More tests => 16;
143
use Test::More tests => 18;
125
use Test::Mojo;
144
use Test::Mojo;
126
145
127
use t::lib::Mocks;
146
use t::lib::Mocks;
Lines 508-513 subtest 'objects.search helper order by embedded columns' => sub { Link Here
508
    $schema->storage->txn_rollback;
527
    $schema->storage->txn_rollback;
509
};
528
};
510
529
530
subtest 'objects.search_rs helper' => sub {
531
    plan tests => 3;
532
533
    $schema->storage->txn_begin;
534
535
    # Remove existing cities to have more control on the search results
536
    Koha::Cities->delete;
537
538
 # Create three sample cities that match the query. This makes sure we
539
 # always have a "next" link regardless of Mojolicious::Plugin::OpenAPI version.
540
    $builder->build_object(
541
        {
542
            class => 'Koha::Cities',
543
            value => {
544
                city_name => 'city1'
545
            }
546
        }
547
    );
548
    $builder->build_object(
549
        {
550
            class => 'Koha::Cities',
551
            value => {
552
                city_name => 'city2'
553
            }
554
        }
555
    );
556
    $builder->build_object(
557
        {
558
            class => 'Koha::Cities',
559
            value => {
560
                city_name => 'city3'
561
            }
562
        }
563
    );
564
565
    my $t = Test::Mojo->new;
566
    $t->get_ok('/cities/rs')->status_is(200)->json_is( '/count' => 3 );
567
568
    $schema->storage->txn_rollback;
569
};
570
511
subtest 'objects.find helper' => sub {
571
subtest 'objects.find helper' => sub {
512
572
513
    plan tests => 9;
573
    plan tests => 9;
Lines 850-852 subtest 'objects.search helper with expanded authorised values' => sub { Link Here
850
910
851
    $schema->storage->txn_rollback;
911
    $schema->storage->txn_rollback;
852
};
912
};
853
- 
913
914
subtest 'objects.find_rs helper' => sub {
915
    plan tests => 9;
916
917
    $schema->storage->txn_begin;
918
919
    # Remove existing cities to have more control on the search results
920
    Koha::Cities->delete;
921
922
 # Create three sample cities that match the query. This makes sure we
923
 # always have a "next" link regardless of Mojolicious::Plugin::OpenAPI version.
924
    my $city1 = $builder->build_object(
925
        {
926
            class => 'Koha::Cities',
927
            value => {
928
                city_name => 'city1'
929
            }
930
        }
931
    );
932
    my $city2 = $builder->build_object(
933
        {
934
            class => 'Koha::Cities',
935
            value => {
936
                city_name => 'city2'
937
            }
938
        }
939
    );
940
    my $city3 = $builder->build_object(
941
        {
942
            class => 'Koha::Cities',
943
            value => {
944
                city_name => 'city3'
945
            }
946
        }
947
    );
948
949
    my $t = Test::Mojo->new;
950
951
    $t->get_ok( '/cities/' . $city1->id . '/rs' )->status_is(200)
952
      ->json_is( '/name' => 'city1' );
953
954
    $t->get_ok( '/cities/' . $city2->id . '/rs' )->status_is(200)
955
      ->json_is( '/name' => 'city2' );
956
957
    $t->get_ok( '/cities/' . $city3->id . '/rs' )->status_is(200)
958
      ->json_is( '/name' => 'city3' );
959
960
    $schema->storage->txn_rollback;
961
};

Return to bug 33080