From 38e2d7dacaf6699b3306313cef5163d3419300a4 Mon Sep 17 00:00:00 2001 From: Olli-Antti Kivilahti Date: Mon, 23 Apr 2018 18:04:13 +0000 Subject: [PATCH] Bug 1985: Send email alert when comment posted. Many blog systems have a feature where the admin gets an email when someone posts a new comment that needs to be moderated. It would be nice to incorporate this into Koha. Ideally, you could set an email address in system preferences where notifications should be sent (since the Koha administrator is probably not the one approving comments). The body of the email would contain the comments, and offer a direct link to approve or delete the comment. The authorship was corrected to Olli-Antti Kivilahti. In comment #11, it was mentioned that title and biblionumber from the biblio table were not available as variables in the letter. This corrects this by converting the parameter list to a hashref, and adding the missing biblio number. It also cleans up the license on C4/Review.pm to be in line with the current coding guidelines license. Also strict and warning have been changed to the 'Use Modern::Perl;' now. Additionally, <> is now usable in the letter, as is <>. These were required additions, because comment #1 expressly says there should be a direct link to approve or delete. I also included a review everything link, since there could be multiple comments outstanding. The default letter was tweaked as well to reflect these changes. Fixed bad URLs as noted in comment #26. TEST PLAN --------- 1) Create test branch and apply patch 2) run installer/data/mysql/updatedatabase.pl -- this will add the required default letter. 3) In the staff client: a) set the CommentModeratorsEmail system preference. -- not setting it will mean you won't get any queued letters. a) set the staffClientBaseURL system preference. -- not setting it will mean your email links won't be valid (i.e http:///...). b) modify the COMMENT_CREATED default letter as desired. -- feel free to add other things. 4) In the OPAC: a) Log in b) Find something c) Click on the 'Comments' tab -- Holdings/Title notes/Comments (#) is at the bottom d) Click 'Post or edit your comments on this item' e) In the window that pops up, type your comment. f) Click 'Submit and close this window'. g) Click 'Edit' and repeat steps e and f again. 5) In a mysql client: a) Open the koha database b) SELECT * FROM message_queue WHERE letter_code='COMMENT_CREATED'; -- There should be at least two. -- They should be able to contain the borrower number, biblio title, and other borrower and biblio related things. -- Comments are at a biblio level, so items, and issues don't make sense as variables for the letter. -- Confirm the URLs are valid by pasting into a browser. 6) prove -v t/db_dependent/Koha/Reviews.t -- six new tests should run. 7) Run the koha qa test tool. --- C4/Letters.pm | 5 ++- Koha/Review.pm | 51 +++++++++++++++++++++- installer/data/mysql/atomicupdate/bug_1985.sql | 38 ++++++++++++++++ .../data/mysql/en/mandatory/sample_notices.sql | 25 +++++++++++ installer/data/mysql/sysprefs.sql | 1 + .../prog/en/modules/admin/preferences/opac.pref | 4 ++ opac/opac-review.pl | 31 +++++++++---- t/db_dependent/Koha/Reviews.t | 44 ++++++++++++++++++- 8 files changed, 188 insertions(+), 11 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/bug_1985.sql diff --git a/C4/Letters.pm b/C4/Letters.pm index 40cd364..6a07485 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -727,8 +727,10 @@ sub GetPreparedLetter { } } - my $OPACBaseURL = C4::Context->preference('OPACBaseURL'); + my $OPACBaseURL = C4::Context->preference('OPACBaseURL') // q{}; $letter->{content} =~ s/<>/$OPACBaseURL/go; + my $staff_client_base_url = C4::Context->preference('staffClientBaseURL') // q{}; + $letter->{content} =~ s/<>/$staff_client_base_url/go; if ($want_librarian) { # parsing librarian name @@ -850,6 +852,7 @@ sub _parseletter_sth { ($table eq 'aqbooksellers') ? "SELECT * FROM $table WHERE id = ?" : ($table eq 'aqorders' ) ? "SELECT * FROM $table WHERE ordernumber = ?" : ($table eq 'opac_news' ) ? "SELECT * FROM $table WHERE idnew = ?" : + ($table eq 'reviews' ) ? "SELECT * FROM $table WHERE reviewid = ?" : ($table eq 'article_requests') ? "SELECT * FROM $table WHERE id = ?" : ($table eq 'borrower_modifications') ? "SELECT * FROM $table WHERE verification_token = ?" : ($table eq 'subscription') ? "SELECT * FROM $table WHERE subscriptionid = ?" : diff --git a/Koha/Review.pm b/Koha/Review.pm index 72e3e2f..e2e6b32 100644 --- a/Koha/Review.pm +++ b/Koha/Review.pm @@ -19,7 +19,9 @@ use Modern::Perl; use Carp; -use Koha::Database; +# Koha::Database is used in the nested mess of C4::Letters; +# As is C4::Context. +use C4::Letters; use base qw(Koha::Object); @@ -67,4 +69,51 @@ sub _type { return 'Review'; } +=head3 SendReviewAlert + + $review->SendReviewAlert($parameters); + +Queue an outgoing email alert when a borrower posts a review, +using the passed parameters in a hash reference. + +=cut + +sub SendReviewAlert { + my ( $self, $params ) = @_; + + my $borrowernumber = $params->{borrowernumber}; + my $reviewid = $params->{reviewid}; + my $biblionumber = $params->{biblionumber}; + + my $moderatorEmail = C4::Context->preference('CommentModeratorsEmail'); + unless ($moderatorEmail) { + carp 'CommentModeratorsEmail is not set!'; + return; + } + + my $letter = C4::Letters::GetPreparedLetter ( + module => 'members', + letter_code => 'COMMENT_CREATED', + tables => { + 'reviews' => $reviewid, + 'borrowers' => $borrowernumber, + 'biblio' => $biblionumber, + 'biblioitems' => $biblionumber, + } + ); + unless ($letter) { + carp 'COMMENT_CREATED member letter not found!'; + return; + } + + C4::Letters::EnqueueLetter({ + letter => $letter, + borrowernumber => $borrowernumber, + message_transport_type => 'email', + to_address => $moderatorEmail, + }); + + return 1; +} + 1; diff --git a/installer/data/mysql/atomicupdate/bug_1985.sql b/installer/data/mysql/atomicupdate/bug_1985.sql new file mode 100644 index 0000000..6c23ef1 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_1985.sql @@ -0,0 +1,38 @@ +INSERT IGNORE INTO letter + (module, code, branchcode, name, is_html, + title, + content, message_transport_type) +VALUES + ('members', 'COMMENT_CREATED', '', 'Comment created notification', '0', + 'Comment from <> is waiting for moderation', +'Dear moderator, + +We want to inform you that borrower <> has just created a new comment on <>, which is biblionumber <>. + +--- BEGIN COMMENT --- +<> +--- END COMMENT --- + +To approve: +http://<>/cgi-bin/koha/reviews/reviewswaiting.pl?op=approve&reviewid=<> + +To delete: +http://<>/cgi-bin/koha/reviews/reviewswaiting.pl?op=delete&reviewid=<> + +Or to review all comments: +http://<>/cgi-bin/koha/reviews/reviewswaiting.pl + +Check it out! + +Your library.', +'email' + ); + +INSERT IGNORE INTO systempreferences + (variable, value,options, + explanation, + type) +VALUES + ('CommentModeratorsEmail','', '', + 'The email address where to send a notification (template code COMMENT_CREATED) when a Borrower adds/modifies a review/comment for a Biblio. Set to empty to disable sending email notifications.', + 'Textarea'); diff --git a/installer/data/mysql/en/mandatory/sample_notices.sql b/installer/data/mysql/en/mandatory/sample_notices.sql index dee5836..2d5476b 100644 --- a/installer/data/mysql/en/mandatory/sample_notices.sql +++ b/installer/data/mysql/en/mandatory/sample_notices.sql @@ -129,6 +129,31 @@ Your library account has been created. Please verify your email address by click If you did not initiate this request, you may safely ignore this one-time message. The request will expire shortly.' ); +INSERT INTO letter (module, code, branchcode, name, is_html, title, content, message_transport_type) +VALUES ( 'members', 'COMMENT_CREATED', '', 'Comment created notification', '0', 'Comment from <> is waiting for moderation', +'Dear moderator, + +We want to inform you that borrower <> has just created a new comment on <>, which is biblionumber <>. + +--- BEGIN COMMENT --- +<> +--- END COMMENT --- + +To approve: +http://<>/cgi-bin/koha/reviews/reviewswaiting.pl?op=approve&reviewid=<> + +To delete: +http://<>/cgi-bin/koha/reviews/reviewswaiting.pl?op=delete&reviewid=<> + +Or to review all comments: +http://<>/cgi-bin/koha/reviews/reviewswaiting.pl + +Check it out! + +Your library.', +'email' +); + INSERT INTO letter (module, code, branchcode, name, is_html, title, content) VALUES ('members', 'SHARE_INVITE', '', 'Invitation for sharing a list', '0', 'Share list <>', 'Dear patron, diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index f01f572..ea63fad 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -113,6 +113,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('CoceHost', '', NULL, 'Coce server URL', 'Free'), ('CoceProviders', '', 'aws,gb,ol', 'Coce providers', 'multiple'), ('COinSinOPACResults','1','','If ON, use COinS in OPAC search results page. NOTE: this can slow down search response time significantly','YesNo'), +('CommentModeratorsEmail','','','The email address where to send a notification (template code COMMENT_CREATED) when a Borrower adds/modifies a review/comment for a Biblio. Set to empty to disable sending email notifications.','Textarea'), ('ConfirmFutureHolds','0','','Number of days for confirming future holds','Integer'), ('ConsiderOnSiteCheckoutsAsNormalCheckouts','1',NULL,'Consider on-site checkouts as normal checkouts','YesNo'), ('CronjobLog','0',NULL,'If ON, log information from cron jobs.','YesNo'), diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index f46dda3..2d23b16 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -451,6 +451,10 @@ OPAC: no: Hide - reviewer's avatar beside comments in OPAC. The avatar will be searched on www.libravatar.org using the patron's e-mail address. - + - The email address where to send a notification (template code COMMENT_CREATED) when a Borrower adds/modifies a review/comment for a Biblio. Set to empty to disable sending email notifications. + - pref: CommentModeratorsEmail + class: textarea + - - pref: RequestOnOpac choices: yes: Allow diff --git a/opac/opac-review.pl b/opac/opac-review.pl index f6284fb..e4c7ef0 100755 --- a/opac/opac-review.pl +++ b/opac/opac-review.pl @@ -33,8 +33,8 @@ use Koha::Reviews; my $query = new CGI; my $biblionumber = $query->param('biblionumber'); -my $review = $query->param('review'); -my $reviewid = $query->param('reviewid'); +my $review = $query->param('review'); # if defined submit +my $reviewid = $query->param('reviewid'); # if defined edit my ( $template, $borrowernumber, $cookie ) = get_template_and_user( { template_name => "opac-review.tt", @@ -46,7 +46,11 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( # FIXME: need to allow user to delete their own comment(s) -my ( $clean, @errors, $savedreview ); +my ( $clean, @errors, $savedreview, $affectedreview ); + +my $submitting = ( defined $review && $review ne q{} ) ? 1 : 0; +my $editing = ( defined $reviewid ) ? 1 : 0; + my $biblio = Koha::Biblios->find( $biblionumber ); if( !$biblio ) { @@ -60,7 +64,7 @@ if( !$biblio ) { $review = $savedreview? $savedreview->review: $review; } -if( !@errors && defined $review ) { +if( !@errors && $submitting ) { if ($review !~ /\S/) { push @errors, {empty=>1}; } else { @@ -74,23 +78,34 @@ if( !@errors && defined $review ) { my $js_ok_review = $clean; $js_ok_review =~ s/"/"/g; # probably redundant w/ TMPL ESCAPE=JS $template->param(clean_review=>$js_ok_review); - if ($savedreview) { - $savedreview->set( + if ($editing) { + my $updatedreview = $savedreview->set( { review => $clean, approved => 0, datereviewed => dt_from_string } )->store; + $affectedreview = $updatedreview; } else { - $reviewid = Koha::Review->new( + my $newreview = Koha::Review->new( { biblionumber => $biblionumber, borrowernumber => $borrowernumber, review => $clean, datereviewed => dt_from_string } - )->store->reviewid; + )->store; + $reviewid = $newreview ? $newreview->reviewid : 0; + $affectedreview = $newreview; } + if ($reviewid) { + $affectedreview->SendReviewAlert({ + 'borrowernumber' => $borrowernumber, + 'reviewid' => $reviewid, + 'biblionumber' => $biblionumber + }); + } + unless (@errors){ $template->param(WINDOW_CLOSE=>1); } } } diff --git a/t/db_dependent/Koha/Reviews.t b/t/db_dependent/Koha/Reviews.t index 8688789..e3b03f3 100644 --- a/t/db_dependent/Koha/Reviews.t +++ b/t/db_dependent/Koha/Reviews.t @@ -19,13 +19,17 @@ use Modern::Perl; -use Test::More tests => 8; +use Test::More tests => 14; +use Test::Warn; use Koha::Patrons; use Koha::Reviews; +use Koha::Notice::Messages; +use Koha::Notice::Templates; use Koha::Database; use t::lib::TestBuilder; +use t::lib::Mocks; my $schema = Koha::Database->new->schema; $schema->storage->txn_begin; @@ -37,6 +41,7 @@ $patron_1 = Koha::Patrons->find( $patron_1->{borrowernumber} ); $patron_2 = Koha::Patrons->find( $patron_2->{borrowernumber} ); my $biblio_1 = $builder->build({ source => 'Biblio' }); my $biblio_2 = $builder->build({ source => 'Biblio' }); +my $nb_of_messages = Koha::Notice::Messages->search->count; my $nb_of_reviews = Koha::Reviews->search->count; my $nb_of_approved_reviews = Koha::Reviews->search({ approved => 1 })->count; my $new_review_1_1 = Koha::Review->new({ @@ -82,6 +87,43 @@ subtest 'search_limited' => sub { $retrieved_review_1_1->delete; is( Koha::Reviews->search->count, $nb_of_reviews + 2, 'Delete should have deleted the review' ); +# Test SendReview Alert + +# empty CommentModeratorsEmail +t::lib::Mocks::mock_preference('CommentModeratorsEmail',undef); +warning_like { +$new_review_1_2->SendReviewAlert({ + borrowernumber => $patron_1->{borrowernumber}, + biblionumber => $biblio_2->{biblionumber}, + reviewid => $new_review_1_2->reviewid +}) } qr/CommentModeratorsEmail is not set!/, 'SendReviewAlert triggered expected CommentModeratorsEmail warning.'; +is( Koha::Notice::Messages->search->count, $nb_of_messages, 'SendReviewAlert lacking CommentModeratorsEmail triggered nothing.' ); + +# set CommentModeratorsEmail +t::lib::Mocks::mock_preference('CommentModeratorsEmail','test@test.test'); +warning_is { +$new_review_1_2->SendReviewAlert({ + borrowernumber => $patron_1->{borrowernumber}, + biblionumber => $biblio_2->{biblionumber}, + reviewid => $new_review_1_2->reviewid +}) } '', 'SendReviewAlert triggered no warnings as expected.'; +is( Koha::Notice::Messages->search->count, $nb_of_messages+1, 'SendReviewAlert triggered notice.' ); + +# letter missing +Koha::Notice::Templates->search({ + module => 'members', + code => 'COMMENT_CREATED' +})->delete; +warnings_like { +$new_review_1_2->SendReviewAlert({ + borrowernumber => $patron_1->{borrowernumber}, + biblionumber => $biblio_2->{biblionumber}, + reviewid => $new_review_1_2->reviewid +}) } +[ qr/No members COMMENT_CREATED letter transported by email/, + qr/COMMENT_CREATED member letter not found!/ ] , 'SendReviewAlert triggered expected COMMENT_CREATED warnings.'; +is( Koha::Notice::Messages->search->count, $nb_of_messages+1, 'SendReviewAlert lacking letter triggered nothing new.' ); + $schema->storage->txn_rollback; sub set_logged_in_user { -- 2.1.4