From ee16afe07e7959cb2306199800f5bb42541fe1a2 Mon Sep 17 00:00:00 2001 From: Cori Lynn Arnold Date: Tue, 3 Dec 2019 14:55:34 +0000 Subject: [PATCH] Bug 17268: Advanced cataloging editor - rancor - macros are lost when browser storage cleared First pass at api code --- Koha/AdvancedEditorMacro.pm | 61 +++++ Koha/AdvancedEditorMacros.pm | 50 ++++ Koha/REST/V1/AdvancedEditorMacros.pm | 249 +++++++++++++++++++ Koha/Schema/Result/Borrower.pm | 19 +- api/v1/swagger/definitions.json | 3 + .../swagger/definitions/advancededitormacro.json | 26 ++ api/v1/swagger/parameters.json | 3 + api/v1/swagger/parameters/advancededitormacro.json | 9 + api/v1/swagger/paths.json | 6 + api/v1/swagger/paths/advancededitormacros.json | 267 +++++++++++++++++++++ api/v1/swagger/x-primitives.json | 17 ++ 11 files changed, 708 insertions(+), 2 deletions(-) create mode 100644 Koha/AdvancedEditorMacro.pm create mode 100644 Koha/AdvancedEditorMacros.pm create mode 100644 Koha/REST/V1/AdvancedEditorMacros.pm create mode 100644 api/v1/swagger/definitions/advancededitormacro.json create mode 100644 api/v1/swagger/parameters/advancededitormacro.json create mode 100644 api/v1/swagger/paths/advancededitormacros.json diff --git a/Koha/AdvancedEditorMacro.pm b/Koha/AdvancedEditorMacro.pm new file mode 100644 index 0000000000..2b51ba7bc4 --- /dev/null +++ b/Koha/AdvancedEditorMacro.pm @@ -0,0 +1,61 @@ +package Koha::AdvancedEditorMacro; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use base qw(Koha::Object); + +=head1 NAME + +Koha::AdvancedEditorMacro - Koha Advanced Editor Macro Object class + +=head1 API + +=head2 Class methods + +=head3 to_api_mapping + +This method returns the mapping for representing a Koha::AdvancedEditorMacro object +on the API. + +=cut + +sub to_api_mapping { + return { + id => 'macro_id', + name => 'name', + macro => 'macro_text', + borrowernumber => 'borrowernumber', + public => 'public' + }; +} + +=head2 Internal methods + +=head3 _type + +=cut + +sub _type { + return 'AdvancedEditorMacro'; +} + +1; diff --git a/Koha/AdvancedEditorMacros.pm b/Koha/AdvancedEditorMacros.pm new file mode 100644 index 0000000000..67d44281a1 --- /dev/null +++ b/Koha/AdvancedEditorMacros.pm @@ -0,0 +1,50 @@ +package Koha::AdvancedEditorMacros; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use Koha::AdvancedEditorMacro; + +use base qw(Koha::Objects); + +=head1 NAME + +Koha::AdvancedEditorMacros - Koha Advanced Editor Macro Object set class + +=head1 API + +=head2 Class Methods + +=cut + +=head3 type + +=cut + +sub _type { + return 'AdvancedEditorMacro'; +} + +sub object_class { + return 'Koha::AdvancedEditorMacro'; +} + +1; diff --git a/Koha/REST/V1/AdvancedEditorMacros.pm b/Koha/REST/V1/AdvancedEditorMacros.pm new file mode 100644 index 0000000000..984046e8ca --- /dev/null +++ b/Koha/REST/V1/AdvancedEditorMacros.pm @@ -0,0 +1,249 @@ +package Koha::REST::V1::AdvancedEditorMacros; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::AdvancedEditorMacros; + +use Try::Tiny; + +=head1 API + +=head2 Class Methods + +=head3 list + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $macros_set = Koha::AdvancedEditorMacros->new; + my $macros = $c->objects->search( $macros_set, \&_to_model, \&_to_api ); + return $c->render( status => 200, openapi => $macros ); + } + catch { + if ( $_->isa('DBIx::Class::Exception') ) { + return $c->render( status => 500, + openapi => { error => $_->{msg} } ); + } + else { + return $c->render( status => 500, + openapi => { error => "Something went wrong, check the logs. $_"} ); + } + }; + +} + +=head3 get + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + my $macro = Koha::AdvancedEditorMacros->find( $c->validation->param('macro_id') ); + unless ($macro) { + return $c->render( status => 404, + openapi => { error => "Macro not found" } ); + } + + return $c->render( status => 200, openapi => $macro->to_api ); +} + +=head3 add + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $macro = Koha::AdvancedEditorMacro->new( _to_model( $c->validation->param('body') ) ); + $macro->store; + $c->res->headers->location( $c->req->url->to_string . '/' . $macro->id ); + return $c->render( + status => 201, + openapi => $macro->to_api + ); + } + catch { + if ( $_->isa('DBIx::Class::Exception') ) { + return $c->render( + status => 500, + openapi => { error => $_->{msg} } + ); + } + else { + return $c->render( + status => 500, + openapi => { error => "Something went wrong, check the logs." } + ); + } + }; +} + +=head3 update + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $macro = Koha::AdvancedEditorMacro->find( $c->validation->param('macro_id') ); + + if ( not defined $macro ) { + return $c->render( status => 404, + openapi => { error => "Object not found" } ); + } + + return try { + my $params = $c->req->json; + $macro->set( _to_model($params) ); + $macro->store(); + return $c->render( status => 200, openapi => $macro->to_api ); + } + catch { + if ( $_->isa('Koha::Exceptions::Object') ) { + return $c->render( status => 500, + openapi => { error => $_->message } ); + } + else { + return $c->render( status => 500, + openapi => { error => "Something went wrong, check the logs."} ); + } + }; +} + +=head3 delete + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $macro = Koha::AdvancedEditorMacro->find( $c->validation->param('macro_id') ); + if ( not defined $macro ) { + return $c->render( status => 404, + openapi => { error => "Object not found" } ); + } + + return try { + $macro->delete; + return $c->render( status => 200, openapi => "" ); + } + catch { + if ( $_->isa('DBIx::Class::Exception') ) { + return $c->render( status => 500, + openapi => { error => $_->{msg} } ); + } + else { + return $c->render( status => 500, + openapi => { error => "Something went wrong, check the logs. line 159"} ); + } + }; +} + +=head3 _to_api + +Helper function that maps a hashref of Koha::AdvancedEditorMacro attributes into REST api +attribute names. + +=cut + +sub _to_api { + my $macro = shift; + + # Rename attributes + foreach my $column ( keys %{ $Koha::REST::V1::AdvancedEditorMacro::to_api_mapping } ) { + my $mapped_column = $Koha::REST::V1::AdvancedEditorMacro::to_api_mapping->{$column}; + if ( exists $macro->{ $column } + && defined $mapped_column ) + { + # key /= undef + $macro->{ $mapped_column } = delete $macro->{ $column }; + } + elsif ( exists $macro->{ $column } + && !defined $mapped_column ) + { + # key == undef => to be deleted + delete $macro->{ $column }; + } + } + + return $macro; +} + +=head3 _to_model + +Helper function that maps REST api objects into Koha::AdvancedEditorMacros +attribute names. + +=cut + +sub _to_model { + my $macro = shift; + + foreach my $attribute ( keys %{ $Koha::REST::V1::AdvancedEditorMacros::to_model_mapping } ) { + my $mapped_attribute = $Koha::REST::V1::AdvancedEditorMacros::to_model_mapping->{$attribute}; + if ( exists $macro->{ $attribute } + && defined $mapped_attribute ) + { + # key /= undef + $macro->{ $mapped_attribute } = delete $macro->{ $attribute }; + } + elsif ( exists $macro->{ $attribute } + && !defined $mapped_attribute ) + { + # key == undef => to be deleted + delete $macro->{ $attribute }; + } + } + + return $macro; +} + +=head2 Global variables + +=head3 $to_api_mapping + +=cut + +our $to_api_mapping = { + id => 'macro_id', + name => 'name', + macro => 'macro_text', + borrrowernumber => 'borrowernumber', + public => 'public' +}; + +=head3 $to_model_mapping + +=cut + +our $to_model_mapping = { + macro_id => 'id', + name => 'name', + macro_text => 'macro', + borrowernumber => 'borrowernumber', + public => 'public' +}; + +1; diff --git a/Koha/Schema/Result/Borrower.pm b/Koha/Schema/Result/Borrower.pm index f7224cc299..a4a7c22094 100644 --- a/Koha/Schema/Result/Borrower.pm +++ b/Koha/Schema/Result/Borrower.pm @@ -734,6 +734,21 @@ __PACKAGE__->has_many( { cascade_copy => 0, cascade_delete => 0 }, ); +=head2 advanced_editor_macros + +Type: has_many + +Related object: L + +=cut + +__PACKAGE__->has_many( + "advanced_editor_macros", + "Koha::Schema::Result::AdvancedEditorMacro", + { "foreign.borrowernumber" => "self.borrowernumber" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + =head2 api_keys Type: has_many @@ -1635,8 +1650,8 @@ Composing rels: L -> ordernumber __PACKAGE__->many_to_many("ordernumbers", "aqorder_users", "ordernumber"); -# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-10-10 14:31:00 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:GjJLIOViIFRm185Yjl9vYA +# Created by DBIx::Class::Schema::Loader v0.07046 @ 2019-11-27 13:18:35 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:RRiPuHSENnEJfBGhqakEAQ __PACKAGE__->add_columns( '+anonymized' => { is_boolean => 1 }, diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json index 90374145a7..9cc7ac77b6 100644 --- a/api/v1/swagger/definitions.json +++ b/api/v1/swagger/definitions.json @@ -26,6 +26,9 @@ "item": { "$ref": "definitions/item.json" }, + "advancededitormacro": { + "$ref": "definitions/advancededitormacro.json" + }, "patron": { "$ref": "definitions/patron.json" }, diff --git a/api/v1/swagger/definitions/advancededitormacro.json b/api/v1/swagger/definitions/advancededitormacro.json new file mode 100644 index 0000000000..a7a87fadf9 --- /dev/null +++ b/api/v1/swagger/definitions/advancededitormacro.json @@ -0,0 +1,26 @@ +{ + "type": "object", + "properties": { + "id": { + "$ref": "../x-primitives.json#/advancededitormacro_id" + }, + "name": { + "description": "macro name", + "type": "string" + }, + "macro": { + "description": "macro text", + "type": ["string", "null"] + }, + "borrowernumber": { + "description": "borrower number", + "type": ["integer", "null"] + }, + "public": { + "description": "is macro public", + "type": ["string", "null"] + } + }, + "additionalProperties": false, + "required": ["name", "macro", "borrowernumber", "public"] +} diff --git a/api/v1/swagger/parameters.json b/api/v1/swagger/parameters.json index 932d251d42..3f4def67a0 100644 --- a/api/v1/swagger/parameters.json +++ b/api/v1/swagger/parameters.json @@ -2,6 +2,9 @@ "biblio_id_pp": { "$ref": "parameters/biblio.json#/biblio_id_pp" }, + "advancededitormacro_id_pp": { + "$ref": "parameters/advancededitormacro.json#/advancededitormacro_id_pp" + }, "patron_id_pp": { "$ref": "parameters/patron.json#/patron_id_pp" }, diff --git a/api/v1/swagger/parameters/advancededitormacro.json b/api/v1/swagger/parameters/advancededitormacro.json new file mode 100644 index 0000000000..482e0bc917 --- /dev/null +++ b/api/v1/swagger/parameters/advancededitormacro.json @@ -0,0 +1,9 @@ +{ + "advancededitormacro_id_pp": { + "name": "advancededitormacro_id", + "in": "path", + "description": "Advanced Editor Macro internal identifier", + "required": true, + "type": "integer" + } +} diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index 95278ec23a..61b83f65b8 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -59,6 +59,12 @@ "/checkouts/{checkout_id}/allows_renewal": { "$ref": "paths/checkouts.json#/~1checkouts~1{checkout_id}~1allows_renewal" }, + "/advancededitormacros": { + "$ref": "paths/advancededitormacros.json#/~1advancededitormacros" + }, + "/advancededitormacros/{advancededitormacro_id}": { + "$ref": "paths/advancededitormacros.json#/~1advancededitormacros~1{advancededitormacro_id}" + }, "/patrons": { "$ref": "paths/patrons.json#/~1patrons" }, diff --git a/api/v1/swagger/paths/advancededitormacros.json b/api/v1/swagger/paths/advancededitormacros.json new file mode 100644 index 0000000000..9ff2e63e4a --- /dev/null +++ b/api/v1/swagger/paths/advancededitormacros.json @@ -0,0 +1,267 @@ +{ + "/advancededitormacros": { + "get": { + "x-mojo-to": "AdvancedEditorMacros#list", + "operationId": "listMacros", + "tags": ["advancededitormacros"], + "produces": [ + "application/json" + ], + "parameters": [{ + "name": "name", + "in": "query", + "description": "Case insensative search on macro name", + "required": false, + "type": "string" + }], + "responses": { + "200": { + "description": "A list of macros", + "schema": { + "type": "array", + "items": { + "$ref": "../definitions.json#/advancededitormacro" + } + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "catalogue": "1" + } + } + }, + "post": { + "x-mojo-to": "AdvancedEditorMacros#add", + "operationId": "addAdvancedEditorMacro", + "tags": ["advancededitormacros"], + "parameters": [{ + "name": "body", + "in": "body", + "description": "A JSON object containing informations about the new macro", + "required": true, + "schema": { + "$ref": "../definitions.json#/advancededitormacro" + } + }], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Macro added", + "schema": { + "$ref": "../definitions.json#/advancededitormacro" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "parameters": "manage_advancededitormacros" + } + } + } + }, + "/advancededitormacros/{advancededitormacro_id}": { + "get": { + "x-mojo-to": "AdvancedEditorMacros#get", + "operationId": "getAdvancedEditorMacro", + "tags": ["advancededitormacros"], + "parameters": [{ + "$ref": "../parameters.json#/advancededitormacro_id_pp" + }], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "A macro", + "schema": { + "$ref": "../definitions.json#/advancededitormacro" + } + }, + "404": { + "description": "AdvancedEditorMacro not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "catalogue": "1" + } + } + }, + "put": { + "x-mojo-to": "AdvancedEditorMacro#update", + "operationId": "updateAdvancedEditorMacro", + "tags": ["advancededitormacros"], + "parameters": [{ + "$ref": "../parameters.json#/advancededitormacro_id_pp" + }, { + "name": "body", + "in": "body", + "description": "An advanced editor macro object", + "required": true, + "schema": { + "$ref": "../definitions.json#/advancededitormacro" + } + }], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "An advanced editor macro", + "schema": { + "$ref": "../definitions.json#/advancededitormacro" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Macro not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "parameters": "manage_advancededitormacro" + } + } + }, + "delete": { + "x-mojo-to": "AdvancedEditorMacros#delete", + "operationId": "deleteAdvancedEditorMacro", + "tags": ["advancededitormacros"], + "parameters": [{ + "$ref": "../parameters.json#/advancededitormacro_id_pp" + }], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Advanced editor macro deleted", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Macro not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "parameters": "manage_advancededitormacros" + } + } + } + } +} diff --git a/api/v1/swagger/x-primitives.json b/api/v1/swagger/x-primitives.json index ee15fa6aa1..29445e40da 100644 --- a/api/v1/swagger/x-primitives.json +++ b/api/v1/swagger/x-primitives.json @@ -3,6 +3,23 @@ "type": "integer", "description": "Internal biblio identifier" }, + "advancededitormacro_id": { + "type": "integer", + "description": "Internal advanced editor macro identifier", + "readOnly": true + }, + "public":{ + "type": "boolean", + "description": "advanced editor macro is public" + }, + "macro": { + "type": "string", + "description": "macro text" + }, + "borrowernumber": { + "type": "integer", + "description": "Internal intranet user" + }, "patron_id": { "type": "integer", "description": "Internal patron identifier" -- 2.11.0