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

(-)a/Koha/REST/V1/Cities.pm (-36 / +113 lines)
Lines 19-25 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Koha::City;
23
use Koha::Cities;
22
use Koha::Cities;
24
23
25
use Try::Tiny;
24
use Try::Tiny;
Lines 27-42 use Try::Tiny; Link Here
27
sub list {
26
sub list {
28
    my $c = shift->openapi->valid_input or return;
27
    my $c = shift->openapi->valid_input or return;
29
28
30
    my $cities;
31
    my $filter;
32
    my $args = $c->req->params->to_hash;
33
34
    for my $filter_param ( keys %$args ) {
35
        $filter->{$filter_param} = { LIKE => $args->{$filter_param} . "%" };
36
    }
37
38
    return try {
29
    return try {
39
        $cities = Koha::Cities->search($filter);
30
        my $cities_set = Koha::Cities->new;
31
        my $cities = $c->objects->search( $cities_set, \&_to_model, \&_to_api );
40
        return $c->render( status => 200, openapi => $cities );
32
        return $c->render( status => 200, openapi => $cities );
41
    }
33
    }
42
    catch {
34
    catch {
Lines 55-86 sub list { Link Here
55
sub get {
47
sub get {
56
    my $c = shift->openapi->valid_input or return;
48
    my $c = shift->openapi->valid_input or return;
57
49
58
    my $city = Koha::Cities->find( $c->validation->param('cityid') );
50
    my $city = Koha::Cities->find( $c->validation->param('city_id') );
59
    unless ($city) {
51
    unless ($city) {
60
        return $c->render( status  => 404,
52
        return $c->render( status  => 404,
61
                           openapi => { error => "City not found" } );
53
                           openapi => { error => "City not found" } );
62
    }
54
    }
63
55
64
    return $c->render( status => 200, openapi => $city );
56
    return $c->render( status => 200, openapi => _to_api($city->TO_JSON) );
65
}
57
}
66
58
67
sub add {
59
sub add {
68
    my $c = shift->openapi->valid_input or return;
60
    my $c = shift->openapi->valid_input or return;
69
61
70
    my $city = Koha::City->new( $c->validation->param('body') );
71
72
    return try {
62
    return try {
63
        my $city = Koha::City->new( _to_model( $c->validation->param('body') ) );
73
        $city->store;
64
        $city->store;
74
        return $c->render( status => 200, openapi => $city );
65
        return $c->render( status => 200, openapi => _to_api($city->TO_JSON) );
75
    }
66
    }
76
    catch {
67
    catch {
77
        if ( $_->isa('DBIx::Class::Exception') ) {
68
        if ( $_->isa('DBIx::Class::Exception') ) {
78
            return $c->render( status  => 500,
69
            return $c->render(
79
                               openapi => { error => $_->{msg} } );
70
                status  => 500,
71
                openapi => { error => $_->{msg} }
72
            );
80
        }
73
        }
81
        else {
74
        else {
82
            return $c->render( status => 500,
75
            return $c->render(
83
                openapi => { error => "Something went wrong, check the logs."} );
76
                status  => 500,
77
                openapi => { error => "Something went wrong, check the logs." }
78
            );
84
        }
79
        }
85
    };
80
    };
86
}
81
}
Lines 88-108 sub add { Link Here
88
sub update {
83
sub update {
89
    my $c = shift->openapi->valid_input or return;
84
    my $c = shift->openapi->valid_input or return;
90
85
91
    my $city;
86
    my $city = Koha::Cities->find( $c->validation->param('city_id') );
87
88
    if ( not defined $city ) {
89
        return $c->render( status  => 404,
90
                           openapi => { error => "Object not found" } );
91
    }
92
92
93
    return try {
93
    return try {
94
        $city = Koha::Cities->find( $c->validation->param('cityid') );
95
        my $params = $c->req->json;
94
        my $params = $c->req->json;
96
        $city->set( $params );
95
        $city->set( _to_model($params) );
97
        $city->store();
96
        $city->store();
98
        return $c->render( status => 200, openapi => $city );
97
        return $c->render( status => 200, openapi => _to_api($city->TO_JSON) );
99
    }
98
    }
100
    catch {
99
    catch {
101
        if ( not defined $city ) {
100
        if ( $_->isa('Koha::Exceptions::Object') ) {
102
            return $c->render( status  => 404,
103
                               openapi => { error => "Object not found" } );
104
        }
105
        elsif ( $_->isa('Koha::Exceptions::Object') ) {
106
            return $c->render( status  => 500,
101
            return $c->render( status  => 500,
107
                               openapi => { error => $_->message } );
102
                               openapi => { error => $_->message } );
108
        }
103
        }
Lines 111-135 sub update { Link Here
111
                openapi => { error => "Something went wrong, check the logs."} );
106
                openapi => { error => "Something went wrong, check the logs."} );
112
        }
107
        }
113
    };
108
    };
114
115
}
109
}
116
110
117
sub delete {
111
sub delete {
118
    my $c = shift->openapi->valid_input or return;
112
    my $c = shift->openapi->valid_input or return;
119
113
120
    my $city;
114
    my $city = Koha::Cities->find( $c->validation->param('city_id') );
115
    if ( not defined $city ) {
116
        return $c->render( status  => 404,
117
                           openapi => { error => "Object not found" } );
118
    }
121
119
122
    return try {
120
    return try {
123
        $city = Koha::Cities->find( $c->validation->param('cityid') );
124
        $city->delete;
121
        $city->delete;
125
        return $c->render( status => 200, openapi => "" );
122
        return $c->render( status => 200, openapi => "" );
126
    }
123
    }
127
    catch {
124
    catch {
128
        if ( not defined $city ) {
125
        if ( $_->isa('DBIx::Class::Exception') ) {
129
            return $c->render( status  => 404,
130
                               openapi => { error => "Object not found" } );
131
        }
132
        elsif ( $_->isa('DBIx::Class::Exception') ) {
133
            return $c->render( status  => 500,
126
            return $c->render( status  => 500,
134
                               openapi => { error => $_->{msg} } );
127
                               openapi => { error => $_->{msg} } );
135
        }
128
        }
Lines 138-144 sub delete { Link Here
138
                openapi => { error => "Something went wrong, check the logs."} );
131
                openapi => { error => "Something went wrong, check the logs."} );
139
        }
132
        }
140
    };
133
    };
134
}
135
136
=head3 _to_api
137
138
Helper function that maps a hashref of Koha::City attributes into REST api
139
attribute names.
140
141
=cut
142
143
sub _to_api {
144
    my $city    = shift;
141
145
146
    # Rename attributes
147
    foreach my $column ( keys %{ $Koha::REST::V1::Cities::to_api_mapping } ) {
148
        my $mapped_column = $Koha::REST::V1::Cities::to_api_mapping->{$column};
149
        if (    exists $city->{ $column }
150
             && defined $mapped_column )
151
        {
152
            # key /= undef
153
            $city->{ $mapped_column } = delete $city->{ $column };
154
        }
155
        elsif (    exists $city->{ $column }
156
                && !defined $mapped_column )
157
        {
158
            # key == undef => to be deleted
159
            delete $city->{ $column };
160
        }
161
    }
162
163
    return $city;
142
}
164
}
143
165
166
=head3 _to_model
167
168
Helper function that maps REST api objects into Koha::Cities
169
attribute names.
170
171
=cut
172
173
sub _to_model {
174
    my $city = shift;
175
176
    foreach my $attribute ( keys %{ $Koha::REST::V1::Cities::to_model_mapping } ) {
177
        my $mapped_attribute = $Koha::REST::V1::Cities::to_model_mapping->{$attribute};
178
        if (    exists $city->{ $attribute }
179
             && defined $mapped_attribute )
180
        {
181
            # key /= undef
182
            $city->{ $mapped_attribute } = delete $city->{ $attribute };
183
        }
184
        elsif (    exists $city->{ $attribute }
185
                && !defined $mapped_attribute )
186
        {
187
            # key == undef => to be deleted
188
            delete $city->{ $attribute };
189
        }
190
    }
191
192
    return $city;
193
}
194
195
=head2 Global variables
196
197
=head3 $to_api_mapping
198
199
=cut
200
201
our $to_api_mapping = {
202
    cityid       => 'city_id',
203
    city_country => 'country',
204
    city_name    => 'name',
205
    city_state   => 'state',
206
    city_zipcode => 'postal_code'
207
};
208
209
=head3 $to_model_mapping
210
211
=cut
212
213
our $to_model_mapping = {
214
    city_id     => 'cityid',
215
    country     => 'city_country',
216
    name        => 'city_name',
217
    postal_code => 'city_zipcode',
218
    state       => 'city_state'
219
};
220
144
1;
221
1;
(-)a/api/v1/swagger/definitions/city.json (-8 / +8 lines)
Lines 1-26 Link Here
1
{
1
{
2
  "type": "object",
2
  "type": "object",
3
  "properties": {
3
  "properties": {
4
    "cityid": {
4
    "city_id": {
5
      "$ref": "../x-primitives.json#/cityid"
5
      "$ref": "../x-primitives.json#/city_id"
6
    },
6
    },
7
    "city_name": {
7
    "name": {
8
      "description": "city name",
8
      "description": "city name",
9
      "type": "string"
9
      "type": "string"
10
    },
10
    },
11
    "city_state": {
11
    "state": {
12
      "description": "city state",
12
      "description": "city state",
13
      "type": ["string", "null"]
13
      "type": ["string", "null"]
14
    },
14
    },
15
    "city_zipcode": {
15
    "postal_code": {
16
      "description": "city zipcode",
16
      "description": "city postal code",
17
      "type": ["string", "null"]
17
      "type": ["string", "null"]
18
    },
18
    },
19
    "city_country": {
19
    "country": {
20
      "description": "city country",
20
      "description": "city country",
21
      "type": ["string", "null"]
21
      "type": ["string", "null"]
22
    }
22
    }
23
  },
23
  },
24
  "additionalProperties": false,
24
  "additionalProperties": false,
25
  "required": ["city_name", "city_state", "city_zipcode", "city_country"]
25
  "required": ["name", "state", "postal_code", "country"]
26
}
26
}
(-)a/api/v1/swagger/parameters.json (-2 / +2 lines)
Lines 5-12 Link Here
5
  "patron_id_qp": {
5
  "patron_id_qp": {
6
    "$ref": "parameters/patron.json#/patron_id_qp"
6
    "$ref": "parameters/patron.json#/patron_id_qp"
7
  },
7
  },
8
  "cityidPathParam": {
8
  "city_id_pp": {
9
    "$ref": "parameters/city.json#/cityidPathParam"
9
    "$ref": "parameters/city.json#/city_id_pp"
10
  },
10
  },
11
  "holdIdPathParam": {
11
  "holdIdPathParam": {
12
    "$ref": "parameters/hold.json#/holdIdPathParam"
12
    "$ref": "parameters/hold.json#/holdIdPathParam"
(-)a/api/v1/swagger/parameters/city.json (-3 / +3 lines)
Lines 1-8 Link Here
1
{
1
{
2
    "cityidPathParam": {
2
    "city_id_pp": {
3
      "name": "cityid",
3
      "name": "city_id",
4
      "in": "path",
4
      "in": "path",
5
      "description": "City id",
5
      "description": "City internal identifier",
6
      "required": true,
6
      "required": true,
7
      "type": "integer"
7
      "type": "integer"
8
    }
8
    }
(-)a/api/v1/swagger/paths.json (-2 / +2 lines)
Lines 8-15 Link Here
8
  "/cities": {
8
  "/cities": {
9
    "$ref": "paths/cities.json#/~1cities"
9
    "$ref": "paths/cities.json#/~1cities"
10
  },
10
  },
11
  "/cities/{cityid}": {
11
  "/cities/{city_id}": {
12
    "$ref": "paths/cities.json#/~1cities~1{cityid}"
12
    "$ref": "paths/cities.json#/~1cities~1{city_id}"
13
  },
13
  },
14
  "/holds": {
14
  "/holds": {
15
    "$ref": "paths/holds.json#/~1holds"
15
    "$ref": "paths/holds.json#/~1holds"
(-)a/api/v1/swagger/paths/cities.json (-13 / +13 lines)
Lines 8-34 Link Here
8
        "application/json"
8
        "application/json"
9
      ],
9
      ],
10
      "parameters": [{
10
      "parameters": [{
11
        "name": "city_name",
11
        "name": "name",
12
        "in": "query",
12
        "in": "query",
13
        "description": "Case insensative 'starts-with' search on city name",
13
        "description": "Case insensative search on city name",
14
        "required": false,
14
        "required": false,
15
        "type": "string"
15
        "type": "string"
16
      }, {
16
      }, {
17
        "name": "city_state",
17
        "name": "state",
18
        "in": "query",
18
        "in": "query",
19
        "description": "Case insensative 'starts-with' search on city state",
19
        "description": "Case insensative search on city state",
20
        "required": false,
20
        "required": false,
21
        "type": "string"
21
        "type": "string"
22
      }, {
22
      }, {
23
        "name": "city_country",
23
        "name": "country",
24
        "in": "query",
24
        "in": "query",
25
        "description": "Case insensative 'starts_with' search on city country",
25
        "description": "Case insensative search on city country",
26
        "required": false,
26
        "required": false,
27
        "type": "string"
27
        "type": "string"
28
      }, {
28
      }, {
29
        "name": "city_zipcode",
29
        "name": "postal_code",
30
        "in": "query",
30
        "in": "query",
31
        "description": "Case Insensative 'starts-with' search on zipcode",
31
        "description": "Case Insensative search on city postal code",
32
        "required": false,
32
        "required": false,
33
        "type": "string"
33
        "type": "string"
34
      }],
34
      }],
Lines 117-129 Link Here
117
      }
117
      }
118
    }
118
    }
119
  },
119
  },
120
  "/cities/{cityid}": {
120
  "/cities/{city_id}": {
121
    "get": {
121
    "get": {
122
      "x-mojo-to": "Cities#get",
122
      "x-mojo-to": "Cities#get",
123
      "operationId": "getCity",
123
      "operationId": "getCity",
124
      "tags": ["cities"],
124
      "tags": ["cities"],
125
      "parameters": [{
125
      "parameters": [{
126
        "$ref": "../parameters.json#/cityidPathParam"
126
        "$ref": "../parameters.json#/city_id_pp"
127
      }],
127
      }],
128
      "produces": [
128
      "produces": [
129
        "application/json"
129
        "application/json"
Lines 160-170 Link Here
160
      "operationId": "updateCity",
160
      "operationId": "updateCity",
161
      "tags": ["cities"],
161
      "tags": ["cities"],
162
      "parameters": [{
162
      "parameters": [{
163
        "$ref": "../parameters.json#/cityidPathParam"
163
        "$ref": "../parameters.json#/city_id_pp"
164
      }, {
164
      }, {
165
        "name": "body",
165
        "name": "body",
166
        "in": "body",
166
        "in": "body",
167
        "description": "A JSON object containing informations about the new hold",
167
        "description": "A city object",
168
        "required": true,
168
        "required": true,
169
        "schema": {
169
        "schema": {
170
          "$ref": "../definitions.json#/city"
170
          "$ref": "../definitions.json#/city"
Lines 222-228 Link Here
222
      "operationId": "deleteCity",
222
      "operationId": "deleteCity",
223
      "tags": ["cities"],
223
      "tags": ["cities"],
224
      "parameters": [{
224
      "parameters": [{
225
        "$ref": "../parameters.json#/cityidPathParam"
225
        "$ref": "../parameters.json#/city_id_pp"
226
      }],
226
      }],
227
      "produces": [
227
      "produces": [
228
        "application/json"
228
        "application/json"
(-)a/api/v1/swagger/x-primitives.json (-2 / +1 lines)
Lines 11-17 Link Here
11
    "type": ["string", "null"],
11
    "type": ["string", "null"],
12
    "description": "library assigned user identifier"
12
    "description": "library assigned user identifier"
13
  },
13
  },
14
  "cityid": {
14
  "city_id": {
15
    "type": "integer",
15
    "type": "integer",
16
    "description": "internally assigned city identifier",
16
    "description": "internally assigned city identifier",
17
    "readOnly": true
17
    "readOnly": true
18
- 

Return to bug 20004