|
Lines 102-112
sub inject_routes {
Link Here
|
| 102 |
sub merge_spec { |
102 |
sub merge_spec { |
| 103 |
my ( $spec, $plugin ) = @_; |
103 |
my ( $spec, $plugin ) = @_; |
| 104 |
|
104 |
|
| 105 |
if($plugin->can('api_routes')) { |
105 |
# Prefer the new api_spec() to inject a full OpenAPI2 spec instead of just the route definitions, if both are defined, to prevent duplicate routes. |
|
|
106 |
# This way we can use the same plugin release for the new and the old versions of Koha. |
| 107 |
if($plugin->can('api_routes') && not($plugin->can('api_spec'))) { # Deprecated |
| 106 |
my $plugin_spec = $plugin->api_routes; |
108 |
my $plugin_spec = $plugin->api_routes; |
| 107 |
|
109 |
|
| 108 |
foreach my $route ( keys %{ $plugin_spec } ) { |
110 |
foreach my $route ( keys %{ $plugin_spec } ) { |
| 109 |
my $THE_route = '/contrib/' . $plugin->api_namespace . $route; |
111 |
my $THE_route = get_normalized_plugin_path($plugin->api_namespace, $route); |
| 110 |
if ( exists $spec->{ $THE_route } ) { |
112 |
if ( exists $spec->{ $THE_route } ) { |
| 111 |
# Route exists, overwriting is forbidden |
113 |
# Route exists, overwriting is forbidden |
| 112 |
Koha::Exceptions::Plugin::ForbiddenAction->throw( |
114 |
Koha::Exceptions::Plugin::ForbiddenAction->throw( |
|
Lines 118-129
sub merge_spec {
Link Here
|
| 118 |
} |
120 |
} |
| 119 |
} |
121 |
} |
| 120 |
|
122 |
|
|
|
123 |
if($plugin->can('api_spec')) { |
| 124 |
my $plugin_namespace = $plugin->api_namespace; |
| 125 |
my $plugin_spec = $plugin->api_spec; |
| 126 |
my @errors; |
| 127 |
if ($plugin_spec->{definitions}) { |
| 128 |
while (my ($k, $v) = each %{$plugin_spec->{definitions}}) { |
| 129 |
if ($spec->{definitions}->{$k}) { |
| 130 |
push(@errors, "Duplicate OpenAPI definition '$k'. Plugin needs to rename one of it's definitions."); |
| 131 |
} else { |
| 132 |
$spec->{definitions}->{$k} = $v; |
| 133 |
} |
| 134 |
} |
| 135 |
} |
| 136 |
if ($plugin_spec->{parameters}) { |
| 137 |
while (my ($k, $v) = each %{$plugin_spec->{parameters}}) { |
| 138 |
if ($spec->{parameters}->{$k}) { |
| 139 |
push(@errors, "Duplicate OpenAPI parameter '$k'. Plugin needs to rename one of it's parameters."); |
| 140 |
} else { |
| 141 |
$spec->{parameters}->{$k} = $v; |
| 142 |
} |
| 143 |
} |
| 144 |
} |
| 145 |
if ($plugin_spec->{tags}) { |
| 146 |
if ($spec->{tags}) { |
| 147 |
push(@{$spec->{tags}}, @{$plugin_spec->{tags}}); |
| 148 |
} else { |
| 149 |
$spec->{tags} = $plugin_spec->{tags}; |
| 150 |
} |
| 151 |
} |
| 152 |
if ($plugin_spec->{paths}) { |
| 153 |
while (my ($k, $v) = each %{$plugin_spec->{paths}}) { |
| 154 |
if ($spec->{paths}->{$k}) { |
| 155 |
push(@errors, "Duplicate OpenAPI parameter '$k'. Plugin needs to rename one of it's paths."); |
| 156 |
} else { |
| 157 |
$spec->{paths}->{get_normalized_plugin_path($plugin_namespace, $k)} = $v; |
| 158 |
} |
| 159 |
} |
| 160 |
} |
| 161 |
if (@errors) { |
| 162 |
Koha::Exceptions::Plugin::ForbiddenAction->throw( |
| 163 |
"Plugin '".$plugin->{class}."' had the following errors while merging OpenAPI specs:\n".join(', ', @errors) |
| 164 |
); |
| 165 |
} |
| 166 |
} |
| 167 |
|
| 121 |
if($plugin->can('static_routes')) { |
168 |
if($plugin->can('static_routes')) { |
| 122 |
my $plugin_spec = $plugin->static_routes; |
169 |
my $plugin_spec = $plugin->static_routes; |
| 123 |
|
170 |
|
| 124 |
foreach my $route ( keys %{ $plugin_spec } ) { |
171 |
foreach my $route ( keys %{ $plugin_spec } ) { |
| 125 |
|
172 |
|
| 126 |
my $THE_route = '/contrib/' . $plugin->api_namespace . '/static'.$route; |
173 |
my $THE_route = get_normalized_plugin_static_path($plugin->api_namespace, $route); |
| 127 |
if ( exists $spec->{ $THE_route } ) { |
174 |
if ( exists $spec->{ $THE_route } ) { |
| 128 |
# Route exists, overwriting is forbidden |
175 |
# Route exists, overwriting is forbidden |
| 129 |
Koha::Exceptions::Plugin::ForbiddenAction->throw( |
176 |
Koha::Exceptions::Plugin::ForbiddenAction->throw( |
|
Lines 153-156
sub spec_ok {
Link Here
|
| 153 |
return !$schema->is_invalid; |
200 |
return !$schema->is_invalid; |
| 154 |
} |
201 |
} |
| 155 |
|
202 |
|
|
|
203 |
=head3 get_normalized_plugin_path |
| 204 |
|
| 205 |
public static subroutine |
| 206 |
Normalizes a plugin's route path to /contrib/<plugin-namespace>/<plugin-route-path> |
| 207 |
|
| 208 |
=cut |
| 209 |
|
| 210 |
sub get_normalized_plugin_path { |
| 211 |
my ($plugin_api_namespace, $plugin_path_name) = @_; |
| 212 |
return '/contrib/' . $plugin_api_namespace . $plugin_path_name; |
| 213 |
} |
| 214 |
|
| 215 |
=head3 get_normalized_plugin_static_path |
| 216 |
|
| 217 |
public static subroutine |
| 218 |
Normalizes a plugin's static route path to /contrib/<plugin-namespace>/static/<plugin-route-path> |
| 219 |
|
| 220 |
=cut |
| 221 |
|
| 222 |
sub get_normalized_plugin_static_path { |
| 223 |
my ($plugin_api_namespace, $plugin_path_name) = @_; |
| 224 |
return '/contrib/' . $plugin_api_namespace . '/static' . $plugin_path_name; |
| 225 |
} |
| 226 |
|
| 156 |
1; |
227 |
1; |