Browse Source
This patch replace the QOTD editor with our new way to CRUD the adminitration page (like libraries and STMP servers) Test plan: Play with the QOTD by adding, removing, updating quotes Try to find bugs :) Bug 27251: Fix capitalization Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com> Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>21.05.x
17 changed files with 833 additions and 425 deletions
@ -0,0 +1,139 @@ |
|||
package Koha::REST::V1::Quotes; |
|||
|
|||
# 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, see <http://www.gnu.org/licenses>. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use Mojo::Base 'Mojolicious::Controller'; |
|||
|
|||
use Koha::Quotes; |
|||
|
|||
use Try::Tiny; |
|||
|
|||
=head1 API |
|||
|
|||
=head2 Methods |
|||
|
|||
=head3 list |
|||
|
|||
=cut |
|||
|
|||
sub list { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
return try { |
|||
my $quotes_set = Koha::Quotes->new; |
|||
my $quotes = $c->objects->search( $quotes_set ); |
|||
return $c->render( status => 200, openapi => $quotes ); |
|||
} |
|||
catch { |
|||
$c->unhandled_exception($_); |
|||
}; |
|||
|
|||
} |
|||
|
|||
=head3 get |
|||
|
|||
=cut |
|||
|
|||
sub get { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
return try { |
|||
my $quote = Koha::Quotes->find( $c->validation->param('quote_id') ); |
|||
unless ($quote) { |
|||
return $c->render( status => 404, |
|||
openapi => { error => "quote not found" } ); |
|||
} |
|||
|
|||
return $c->render( status => 200, openapi => $quote->to_api ); |
|||
} |
|||
catch { |
|||
$c->unhandled_exception($_); |
|||
} |
|||
} |
|||
|
|||
=head3 add |
|||
|
|||
=cut |
|||
|
|||
sub add { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
return try { |
|||
my $quote = Koha::Quote->new_from_api( $c->validation->param('body') ); |
|||
$quote->store; |
|||
$c->res->headers->location( $c->req->url->to_string . '/' . $quote->id ); |
|||
return $c->render( |
|||
status => 201, |
|||
openapi => $quote->to_api |
|||
); |
|||
} |
|||
catch { |
|||
$c->unhandled_exception($_); |
|||
}; |
|||
} |
|||
|
|||
=head3 update |
|||
|
|||
=cut |
|||
|
|||
sub update { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
my $quote = Koha::Quotes->find( $c->validation->param('quote_id') ); |
|||
|
|||
if ( not defined $quote ) { |
|||
return $c->render( status => 404, |
|||
openapi => { error => "Object not found" } ); |
|||
} |
|||
|
|||
return try { |
|||
$quote->set_from_api( $c->validation->param('body') ); |
|||
$quote->store(); |
|||
return $c->render( status => 200, openapi => $quote->to_api ); |
|||
} |
|||
catch { |
|||
$c->unhandled_exception($_); |
|||
}; |
|||
} |
|||
|
|||
=head3 delete |
|||
|
|||
=cut |
|||
|
|||
sub delete { |
|||
my $c = shift->openapi->valid_input or return; |
|||
|
|||
my $quote = Koha::Quotes->find( $c->validation->param('quote_id') ); |
|||
if ( not defined $quote ) { |
|||
return $c->render( status => 404, |
|||
openapi => { error => "Object not found" } ); |
|||
} |
|||
|
|||
return try { |
|||
$quote->delete; |
|||
return $c->render( |
|||
status => 204, |
|||
openapi => q{} |
|||
); |
|||
} |
|||
catch { |
|||
$c->unhandled_exception($_); |
|||
}; |
|||
} |
|||
|
|||
1; |
@ -0,0 +1,22 @@ |
|||
{ |
|||
"type": "object", |
|||
"properties": { |
|||
"quote_id": { |
|||
"$ref": "../x-primitives.json#/quote_id" |
|||
}, |
|||
"source": { |
|||
"description": "source of the quote", |
|||
"type": "string" |
|||
}, |
|||
"text": { |
|||
"description": "text", |
|||
"type": ["string", "null"] |
|||
}, |
|||
"displayed_on": { |
|||
"description": "Last display date", |
|||
"type": ["string", "null"] |
|||
} |
|||
}, |
|||
"additionalProperties": false, |
|||
"required": ["quote_id", "source", "text"] |
|||
} |
@ -0,0 +1,9 @@ |
|||
{ |
|||
"quote_id_pp": { |
|||
"name": "quote_id", |
|||
"in": "path", |
|||
"description": "Quote internal identifier", |
|||
"required": true, |
|||
"type": "integer" |
|||
} |
|||
} |
@ -0,0 +1,327 @@ |
|||
{ |
|||
"/quotes": { |
|||
"get": { |
|||
"x-mojo-to": "Quotes#list", |
|||
"operationId": "listQuotes", |
|||
"tags": [ |
|||
"quotes" |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"name": "quote_id", |
|||
"in": "query", |
|||
"description": "Case insensitive search on quote id", |
|||
"required": false, |
|||
"type": "string" |
|||
}, |
|||
{ |
|||
"name": "source", |
|||
"in": "query", |
|||
"description": "Case insensitive search on source", |
|||
"required": false, |
|||
"type": "string" |
|||
}, |
|||
{ |
|||
"name": "text", |
|||
"in": "query", |
|||
"description": "Case insensitive search on text", |
|||
"required": false, |
|||
"type": "string" |
|||
}, |
|||
{ |
|||
"name": "displayed_on", |
|||
"in": "query", |
|||
"description": "Case Insensative search on last displayed date", |
|||
"required": false, |
|||
"type": "string" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/match" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/order_by" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/page" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/per_page" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/q_param" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/q_body" |
|||
}, |
|||
{ |
|||
"$ref": "../parameters.json#/q_header" |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "A list of quotes", |
|||
"schema": { |
|||
"type": "array", |
|||
"items": { |
|||
"$ref": "../definitions.json#/quote" |
|||
} |
|||
} |
|||
}, |
|||
"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": "Quotes#add", |
|||
"operationId": "addQuote", |
|||
"tags": [ |
|||
"quotes" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"name": "body", |
|||
"in": "body", |
|||
"description": "A JSON object containing informations about the new quote", |
|||
"required": true, |
|||
"schema": { |
|||
"$ref": "../definitions.json#/quote" |
|||
} |
|||
} |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"201": { |
|||
"description": "Quote added", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/quote" |
|||
} |
|||
}, |
|||
"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": { |
|||
"tools": "edit_quotes" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"/quotes/{quote_id}": { |
|||
"get": { |
|||
"x-mojo-to": "Quotes#get", |
|||
"operationId": "getQuote", |
|||
"tags": [ |
|||
"quotes" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"$ref": "../parameters.json#/quote_id_pp" |
|||
} |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "A Quote", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/quote" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Quote 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": "Quotes#update", |
|||
"operationId": "updateQuote", |
|||
"tags": [ |
|||
"quotes" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"$ref": "../parameters.json#/quote_id_pp" |
|||
}, |
|||
{ |
|||
"name": "body", |
|||
"in": "body", |
|||
"description": "a quote object", |
|||
"required": true, |
|||
"schema": { |
|||
"$ref": "../definitions.json#/quote" |
|||
} |
|||
} |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "A quote", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/quote" |
|||
} |
|||
}, |
|||
"401": { |
|||
"description": "Authentication required", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"403": { |
|||
"description": "Access forbidden", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Quote 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": { |
|||
"tools": "edit_quotes" |
|||
} |
|||
} |
|||
}, |
|||
"delete": { |
|||
"x-mojo-to": "Quotes#delete", |
|||
"operationId": "deleteQuote", |
|||
"tags": [ |
|||
"quotes" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"$ref": "../parameters.json#/quote_id_pp" |
|||
} |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"204": { |
|||
"description": "Quote deleted" |
|||
}, |
|||
"401": { |
|||
"description": "Authentication required", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"403": { |
|||
"description": "Access forbidden", |
|||
"schema": { |
|||
"$ref": "../definitions.json#/error" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Quote 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": { |
|||
"tools": "edit_quotes" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,5 +0,0 @@ |
|||
<div id="toolbar" class="btn-toolbar"> |
|||
<div class="btn-group"><a class="btn btn-default" id="add_quote" href="#"><i class="fa fa-plus"></i> Add quote</a></div> |
|||
<div class="btn-group"><a class="btn btn-default" id="delete_quote" href="#"><i class="fa fa-trash"></i> Delete quote(s)</a></div> |
|||
<div class="btn-group"><a class="btn btn-default" id="import_quotes" href="/cgi-bin/koha/tools/quotes-upload.pl"><i class="fa fa-folder-open"></i> Import quotes</a></div> |
|||
</div> |
@ -1,5 +0,0 @@ |
|||
<div id="toolbar" class="btn-toolbar" style="visibility: hidden; position: absolute"> |
|||
<div class="btn-group"><a class="btn btn-default" id="save_quotes" href="#"><i class="fa fa-save"></i> Save quotes</a></div> |
|||
<div class="btn-group"><a class="btn btn-default" id="delete_quote" href="#"><i class="fa fa-trash"></i> Delete quote(s)</a></div> |
|||
<div class="btn-group"><a href="/cgi-bin/koha/tools/quotes-upload.pl" id="cancel_quotes" class="btn btn-default"><i class="fa fa-remove"></i> Cancel import</a></div> |
|||
</div> |
@ -1,65 +0,0 @@ |
|||
#!/usr/bin/perl |
|||
|
|||
# Copyright 2012 Foundations Bible College Inc. |
|||
# |
|||
# 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, see <http://www.gnu.org/licenses>. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use CGI qw ( -utf8 ); |
|||
use JSON; |
|||
use URI::Escape; |
|||
use autouse 'Data::Dumper' => qw(Dumper); |
|||
|
|||
use C4::Auth; |
|||
use C4::Koha; |
|||
use C4::Context; |
|||
use C4::Output; |
|||
|
|||
my $cgi = CGI->new; |
|||
my $dbh = C4::Context->dbh; |
|||
|
|||
my ( $status, $cookie, $sessionID ) = C4::Auth::check_api_auth( $cgi, { tools => 'edit_quotes' } ); |
|||
unless ($status eq "ok") { |
|||
print $cgi->header(-type => 'application/json', -status => '403 Forbidden'); |
|||
print to_json({ auth_status => $status }); |
|||
exit 0; |
|||
} |
|||
|
|||
my $success = 'true'; |
|||
my $quotes_tmp = uri_unescape( $cgi->param('quote' ) ); |
|||
my $quotes = decode_json( $quotes_tmp ); |
|||
|
|||
my $action = $cgi->param('action'); |
|||
|
|||
my $sth = $dbh->prepare('INSERT INTO quotes (source, text) VALUES (?, ?);'); |
|||
|
|||
my $insert_count = 0; |
|||
|
|||
foreach my $quote (@$quotes) { |
|||
$insert_count++ if $sth->execute($quote->[1], $quote->[2]); |
|||
if ($sth->err) { |
|||
warn sprintf('Database returned the following error: %s', $sth->errstr); |
|||
$success = 'false'; |
|||
} |
|||
} |
|||
|
|||
print $cgi->header('application/json'); |
|||
|
|||
print to_json({ |
|||
success => $success, |
|||
records => $insert_count, |
|||
}); |
@ -1,109 +0,0 @@ |
|||
#!/usr/bin/perl |
|||
|
|||
# Copyright 2012 Foundations Bible College Inc. |
|||
# |
|||
# 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, see <http://www.gnu.org/licenses>. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use CGI qw ( -utf8 ); |
|||
use JSON; |
|||
use autouse 'Data::Dumper' => qw(Dumper); |
|||
|
|||
use C4::Auth; |
|||
use C4::Context; |
|||
|
|||
my $cgi = CGI->new; |
|||
my $dbh = C4::Context->dbh; |
|||
my $sort_columns = ["id", "source", "text", "timestamp"]; |
|||
|
|||
my ( $status, $cookie, $sessionID ) = C4::Auth::check_api_auth( $cgi, { tools => 'edit_quotes' } ); |
|||
unless ($status eq "ok") { |
|||
print $cgi->header(-type => 'application/json', -status => '403 Forbidden'); |
|||
print to_json({ auth_status => $status }); |
|||
exit 0; |
|||
} |
|||
|
|||
# NOTE: This is a collection of ajax functions for use with tools/quotes.pl |
|||
|
|||
my $params = $cgi->Vars; # NOTE: Multivalue parameters NOT allowed!! |
|||
|
|||
print $cgi->header('application/json; charset=utf-8'); |
|||
|
|||
my $action = $params->{'action'} || 'get'; |
|||
if ($action eq 'add') { |
|||
my $sth = $dbh->prepare('INSERT INTO quotes (source, text) VALUES (?, ?);'); |
|||
$sth->execute($params->{'source'}, $params->{'text'}); |
|||
if ($sth->err) { |
|||
warn sprintf('Database returned the following error: %s', $sth->errstr); |
|||
exit 0; |
|||
} |
|||
my $new_quote_id = $dbh->{q{mysql_insertid}}; # ALERT: mysqlism here |
|||
$sth = $dbh->prepare('SELECT * FROM quotes WHERE id = ?;'); |
|||
$sth->execute($new_quote_id); |
|||
print to_json($sth->fetchall_arrayref, {utf8 =>1}); |
|||
exit 0; |
|||
} |
|||
elsif ($action eq 'edit') { |
|||
my $aaData = []; |
|||
my $editable_columns = [qw(source text)]; # pay attention to element order; these columns match the quotes table columns |
|||
my $sth = $dbh->prepare("UPDATE quotes SET $editable_columns->[$params->{'column'}-1] = ? WHERE id = ?;"); |
|||
$sth->execute($params->{'value'}, $params->{'id'}); |
|||
if ($sth->err) { |
|||
warn sprintf('Database returned the following error: %s', $sth->errstr); |
|||
exit 1; |
|||
} |
|||
$sth = $dbh->prepare("SELECT $editable_columns->[$params->{'column'}-1] FROM quotes WHERE id = ?;"); |
|||
$sth->execute($params->{'id'}); |
|||
$aaData = $sth->fetchrow_array(); |
|||
print Encode::encode('utf8', $aaData); |
|||
|
|||
exit 0; |
|||
} |
|||
elsif ($action eq 'delete') { |
|||
my $sth = $dbh->prepare("DELETE FROM quotes WHERE id = ?;"); |
|||
$sth->execute($params->{'id'}); |
|||
if ($sth->err) { |
|||
warn sprintf('Database returned the following error: %s', $sth->errstr); |
|||
exit 1; |
|||
} |
|||
exit 0; |
|||
} |
|||
else { |
|||
my $aaData = []; |
|||
my $iTotalRecords = ''; |
|||
my $sth = ''; |
|||
|
|||
$iTotalRecords = $dbh->selectrow_array('SELECT count(*) FROM quotes;'); |
|||
$sth = $dbh->prepare("SELECT * FROM quotes;"); |
|||
|
|||
$sth->execute(); |
|||
if ($sth->err) { |
|||
warn sprintf('Database returned the following error: %s', $sth->errstr); |
|||
exit 1; |
|||
} |
|||
|
|||
$aaData = $sth->fetchall_arrayref; |
|||
my $iTotalDisplayRecords = $iTotalRecords; # no filtering happening here |
|||
|
|||
|
|||
print to_json({ |
|||
iTotalRecords => $iTotalRecords, |
|||
iTotalDisplayRecords=> $iTotalDisplayRecords, |
|||
sEcho => $params->{'sEcho'}, |
|||
aaData => $aaData, |
|||
}, {utf8 =>1}); |
|||
} |
Loading…
Reference in new issue