Skip to content

Commit 2e5ff48

Browse files
Send review notification to reviewers
1 parent 5298000 commit 2e5ff48

File tree

7 files changed

+262
-18
lines changed

7 files changed

+262
-18
lines changed

classes/task/send_mails.php

+101
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
namespace mod_moodleoverflow\task;
2626

27+
use core\session\exception;
28+
use mod_moodleoverflow\output\moodleoverflow_email;
29+
2730
defined('MOODLE_INTERNAL') || die();
2831
require_once(__DIR__ . '/../../locallib.php');
2932

@@ -53,10 +56,108 @@ public function execute() {
5356
// Send mail notifications.
5457
moodleoverflow_send_mails();
5558

59+
$this->send_review_notifications();
60+
5661
// The cron is finished.
5762
return true;
5863

5964
}
6065

66+
/**
67+
* Sends initial notifications for needed reviews to all users with review capability.
68+
*/
69+
public function send_review_notifications() {
70+
global $DB, $OUTPUT, $PAGE;
71+
72+
$rendererhtml = $PAGE->get_renderer('mod_moodleoverflow', 'email', 'htmlemail');
73+
$renderertext = $PAGE->get_renderer('mod_moodleoverflow', 'email', 'textemail');
74+
75+
$postinfos = $DB->get_records_sql(
76+
'SELECT p.*, d.course as cid, d.moodleoverflow as mid, d.id as did FROM {moodleoverflow_posts} p ' .
77+
'JOIN {moodleoverflow_discussions} d ON p.discussion = d.id ' .
78+
"WHERE p.mailed = :mailpending AND p.reviewed = 0 AND p.created < :timecutoff " .
79+
"ORDER BY d.course, d.moodleoverflow, d.id",
80+
[
81+
'mailpending' => MOODLEOVERFLOW_MAILED_PENDING,
82+
'timecutoff' => time() - get_config('moodleoverflow', 'reviewpossibleaftertime')
83+
]
84+
);
85+
86+
if (empty($postinfos)) {
87+
mtrace('No review notifications to send.');
88+
return;
89+
}
90+
91+
$course = null;
92+
93+
$moodleoverflow = null;
94+
$usersto = null;
95+
$cm = null;
96+
97+
$discussion = null;
98+
99+
$success = [];
100+
101+
foreach ($postinfos as $postinfo) {
102+
if ($course == null || $course->id != $postinfo->cid) {
103+
$course = get_course($postinfo->cid);
104+
}
105+
106+
if ($moodleoverflow == null || $moodleoverflow->id != $postinfo->mid) {
107+
$cm = get_coursemodule_from_instance('moodleoverflow', $postinfo->mid, 0, false, MUST_EXIST);
108+
$modulecontext = \context_module::instance($cm->id);
109+
$usersto = get_users_by_capability($modulecontext, 'mod/moodleoverflow:reviewpost');
110+
$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $postinfo->mid], '*', MUST_EXIST);
111+
}
112+
113+
if ($discussion == null || $discussion->id != $postinfo->did) {
114+
$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $postinfo->did], '*', MUST_EXIST);
115+
}
116+
117+
$post = $postinfo;
118+
$userfrom = \core_user::get_user($postinfo->userid, '*', MUST_EXIST);
119+
120+
foreach ($usersto as $userto) {
121+
try {
122+
cron_setup_user($userto, $course);
123+
124+
$maildata = new moodleoverflow_email(
125+
$course,
126+
$cm,
127+
$moodleoverflow,
128+
$discussion,
129+
$post,
130+
$userfrom,
131+
$userto,
132+
false
133+
);
134+
135+
$textcontext = $maildata->export_for_template($renderertext, true);
136+
$htmlcontext = $maildata->export_for_template($rendererhtml, false);
137+
138+
email_to_user(
139+
$userto,
140+
\core_user::get_noreply_user(),
141+
get_string('email_review_needed_subject', 'moodleoverflow', $textcontext),
142+
$OUTPUT->render_from_template('mod_moodleoverflow/email_review_needed_text', $textcontext),
143+
$OUTPUT->render_from_template('mod_moodleoverflow/email_review_needed_html', $htmlcontext)
144+
);
145+
} catch (exception $e) {
146+
mtrace("Error sending review notification for post $post->id to user $userto->id!");
147+
}
148+
}
149+
$success[] = $post->id;
150+
}
151+
152+
if (!empty($success)) {
153+
list($insql, $inparams) = $DB->get_in_or_equal($success);
154+
$DB->set_field_select(
155+
'moodleoverflow_posts', 'mailed', MOODLEOVERFLOW_MAILED_REVIEW_SUCCESS,
156+
'id ' . $insql, $inparams
157+
);
158+
mtrace('Sent review notifications for ' . count($success) . ' posts successfully!');
159+
}
160+
}
161+
61162
}
62163

db/install.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
<FIELD NAME="message" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="text of the post"/>
6868
<FIELD NAME="messageformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
6969
<FIELD NAME="attachment" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/>
70-
<FIELD NAME="mailed" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
70+
<FIELD NAME="mailed" TYPE="int" LENGTH="2" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
7171
<FIELD NAME="reviewed" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
7272
<FIELD NAME="timereviewed" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
7373
</FIELDS>

db/upgrade.php

+4
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ function xmldb_moodleoverflow_upgrade($oldversion) {
222222
$dbman->add_field($table, $field);
223223
}
224224

225+
$field = new xmldb_field('mailed', XMLDB_TYPE_INTEGER, '2', null, null, null, '0', 'attachment');
226+
// Launch change of precision for field mailed.
227+
$dbman->change_field_precision($table, $field);
228+
225229
// Moodleoverflow savepoint reached.
226230
upgrade_mod_savepoint(true, 2022072000, 'moodleoverflow');
227231
}

lang/en/moodleoverflow.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -432,13 +432,16 @@
432432
$string['post_was_approved'] = 'The post was approved.';
433433
$string['post_was_rejected'] = 'The post was rejected.';
434434
$string['jump_to_next_post_needing_review'] = 'Jump to next post needing to be reviewed.';
435-
$string['there_are_no_posts_needing_review'] = 'There are no more posts needing to be reviewed.';
435+
$string['there_are_no_posts_needing_review'] = 'There are no more posts in this forum that need to be reviewed.';
436436
$string['give_a_reason'] = 'Give a reason (optional)';
437437
$string['approve'] = 'Approve';
438438
$string['reject'] = 'Reject';
439439
$string['reviewpossibleaftertime'] = 'Review possible after (secs)';
440440
$string['reviewpossibleaftertime_desc'] = 'A teacher can only reject or approve a post at least this amount of time (in seconds) after the creation of the post. After a teacher has approved a post, the post cannot be edited by it\'s author anymore, even if still within the maxeditingtime duration.';
441441
$string['pending_review_but_cannot_now'] = 'Pending review, but can only be approved at least {$a} after the creation of this post to allow the author a bit of time to edit it.';
442442

443-
$string['rejected_email_subject'] = 'One of your posts in {$a->course} {$a->activity} has been rejected.';
444-
$string['rejected_email_content'] = 'This post has been rejected in {$a->course} {$a->activity}';
443+
$string['review_needed'] = 'Review needed!';
444+
445+
$string['email_review_needed_subject'] = 'Review needed in {$a->coursename}: {$a->subject}';
446+
447+
$string['email_rejected_subject'] = '{$a->coursename}: One of your posts has been rejected.';

lib.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
define('MOODLEOVERFLOW_MAILED_PENDING', 0);
4949
define('MOODLEOVERFLOW_MAILED_SUCCESS', 1);
5050
define('MOODLEOVERFLOW_MAILED_ERROR', 2);
51+
define('MOODLEOVERFLOW_MAILED_REVIEW_SUCCESS', 3);
5152

5253
// Constants for the post rating.
5354
define('MOODLEOVERFLOW_PREFERENCE_STARTER', 0);
@@ -1005,16 +1006,18 @@ function moodleoverflow_get_unmailed_posts($starttime, $endtime) {
10051006

10061007
// Set params for the sql query.
10071008
$params = array();
1008-
$params['mailed'] = MOODLEOVERFLOW_MAILED_PENDING;
10091009
$params['ptimestart'] = $starttime;
10101010
$params['ptimeend'] = $endtime;
10111011

1012+
$pendingmail = MOODLEOVERFLOW_MAILED_PENDING;
1013+
$reviewsent = MOODLEOVERFLOW_MAILED_REVIEW_SUCCESS;
1014+
10121015
// Retrieve the records.
10131016
$sql = "SELECT p.*, d.course, d.moodleoverflow
10141017
FROM {moodleoverflow_posts} p
10151018
JOIN {moodleoverflow_discussions} d ON d.id = p.discussion
1016-
WHERE p.mailed = :mailed AND p.reviewed = 1
1017-
AND COALESCE(p.timereview, p.created) >= :ptimestart AND COALESCE(p.timereview, p.created) < :ptimeend
1019+
WHERE p.mailed IN ($pendingmail, $reviewsent) AND p.reviewed = 1
1020+
AND COALESCE(p.timereviewed, p.created) >= :ptimestart AND p.created < :ptimeend
10181021
ORDER BY p.modified ASC";
10191022

10201023
return $DB->get_records_sql($sql, $params);
@@ -1036,14 +1039,15 @@ function moodleoverflow_mark_old_posts_as_mailed($endtime) {
10361039
// Define variables for the sql query.
10371040
$params = array();
10381041
$params['mailedsuccess'] = MOODLEOVERFLOW_MAILED_SUCCESS;
1042+
$params['mailedreviewsent'] = MOODLEOVERFLOW_MAILED_REVIEW_SUCCESS;
10391043
$params['now'] = $now;
10401044
$params['endtime'] = $endtime;
10411045
$params['mailedpending'] = MOODLEOVERFLOW_MAILED_PENDING;
10421046

10431047
// Define the sql query.
10441048
$sql = "UPDATE {moodleoverflow_posts}
10451049
SET mailed = :mailedsuccess
1046-
WHERE (created < :endtime) AND mailed = :mailedpending AND reviewed = 1";
1050+
WHERE (created < :endtime) AND mailed IN (:mailedpending, :mailedreviewsent) AND reviewed = 1";
10471051

10481052
return $DB->execute($sql, $params);
10491053

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
{{!
2+
This file is part of Moodle - http://moodle.org/
3+
4+
Moodle is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
Moodle is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
}}
17+
{{!
18+
@template mod_moodleoverflow/email_html
19+
20+
Template which defines a moodleoverflow post for sending in a single-post HTML email.
21+
22+
Classes required for JS:
23+
* none
24+
25+
Data attributes required for JS:
26+
* none
27+
28+
Context variables required for this template:
29+
* courselink
30+
* coursename
31+
* moodleoverflowindexlink
32+
* moodleoverflowviewlink
33+
* moodleoverflowname
34+
* discussionlink
35+
* discussionname
36+
* showdiscussionname
37+
* firstpost
38+
* subject
39+
* authorlink
40+
* authorpicture
41+
* authorfullname
42+
* postdate
43+
* grouppicture
44+
* attachments
45+
* message
46+
* parentpostlink
47+
* canreply
48+
* replylink
49+
* permalink
50+
* unsubscribemoodleoverflowlink
51+
* unsubscribediscussionlink
52+
53+
Example context (json):
54+
{
55+
"courselink": "https://example.com/course/view.php?id=2",
56+
"coursename": "Example course",
57+
"moodleoverflowindexlink": "https://example.com/mod/moodleoverflow/index.php?id=2",
58+
"moodleoverflowviewlink": "https://example.com/mod/moodleoverflow/view.php?f=2",
59+
"moodleoverflowname": "Lorem ipsum dolor",
60+
"discussionlink": "https://example.com/mod/moodleoverflow/discuss.php?d=70",
61+
"discussionname": "Is Lorem ipsum Latin?",
62+
"showdiscussionname": 1,
63+
"firstpost": 1,
64+
"subject": "Is Lorem ipsum Latin?",
65+
"authorlink": "https://example.com/user/view.php?id=2&course=2",
66+
"authorpicture": "<a href=\"https://example.com/user/view.php?id=2&amp;course=6\"><img src=\"https://example.com/theme/image.php?theme=clean&amp;component=core&amp;image=u%2Ff2&amp;svg=0\" alt=\"Picture of Admin User\" title=\"Picture of Admin User\" class=\"userpicture defaultuserpic\" width=\"35\" height=\"35\" /></a>",
67+
"authorfullname": "Lucius Caecilius lucundus",
68+
"postdate": "Sunday, 13 September 2015, 2:22 pm",
69+
"grouppicture": "",
70+
"attachments": "",
71+
"message": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum et auctor libero. Quisque porta egestas neque, et bibendum libero dignissim at. Nulla facilisi. Morbi eget accumsan felis. Nunc et vulputate odio, vel venenatis nisl. Nunc maximus ipsum sed tincidunt mollis. Integer nunc erat, luctus sit amet arcu tincidunt, volutpat dignissim mi. Sed ut magna quam. Mauris accumsan porta turpis sed aliquam. Etiam at justo tristique, imperdiet augue quis, consectetur sapien. Ut nec erat malesuada sem suscipit lobortis. Vivamus posuere nibh eu ipsum porta fringilla. Sed vitae dapibus ipsum, ac condimentum enim. Sed dignissim ante at elit mollis, ac tempor lacus iaculis. Etiam nec lectus vitae nibh vulputate volutpat. Nulla quis tellus aliquam, commodo nisi et, dictum est.</p><p><br /></p>",
72+
"parentpostlink": "",
73+
"canreply": 1,
74+
"replylink": "https://example.com/mod/moodleoverflow/post.php?reply=2",
75+
"permalink": "https://example.com/mod/moodleoverflow/discuss.php?d=2#2",
76+
"unsubscribemoodleoverflowlink": "https://example.com/mod/moodleoverflow/subscribe.php?id=2",
77+
"unsubscribediscussionlink": "https://example.com/mod/discussion/subscribe.php?id=2&d=2"
78+
}
79+
}}
80+
<div class="navbar">
81+
<a target="_blank" href="{{{ courselink }}}">{{{ coursename }}}</a>
82+
&raquo;
83+
<a target="_blank" href="{{{ moodleoverflowviewlink }}}">{{{ moodleoverflowname }}}</a>
84+
{{# showdiscussionname }}
85+
&raquo;
86+
<a target="_blank" href="{{{ discussionlink }}}">{{{ discussionname }}}</a>
87+
{{/ showdiscussionname }}
88+
</div>
89+
90+
<a href="{{{permalink}}}"><h3>{{#str}}review_needed, mod_moodleoverflow{{/str}}</h3></a>
91+
92+
<table border="0" cellpadding="3" cellspacing="0" class="moodleoverflowpost">
93+
<tr class="header">
94+
<td width="35" valign="top" class="picture left">
95+
{{{ authorpicture }}}
96+
</td>
97+
<td class="topic {{# firstpost }}starter{{/ firstpost }}">
98+
<div class="subject">
99+
{{{ subject }}}
100+
</div>
101+
<div class="author">
102+
{{# str }} bynameondatenorating, moodleoverflow, {
103+
"name":
104+
{{# authorlink }}{{# quote }} <a target='_blank' href='{{{ authorlink }}}'>{{ authorfullname }}</a>{{/ quote }}{{/authorlink}}
105+
{{^ authorlink }}{{# quote }} {{ authorfullname }} {{/ quote }}{{/ authorlink }} ,
106+
"date": {{# quote }}{{ postdate }}{{/ quote }}
107+
} {{/ str }}
108+
</div>
109+
</td>
110+
</tr>
111+
<tr>
112+
<td class="left side" valign="top">
113+
{{# grouppicture }}
114+
{{{ grouppicture }}}
115+
{{/ grouppicture }}
116+
{{^ grouppicture }}
117+
&nbsp;
118+
{{/ grouppicture }}
119+
</td>
120+
<td class="content">
121+
{{{ message }}}
122+
<div class="link">
123+
<a target="_blank" href="{{{ permalink }}}">
124+
{{# str }} review, mod_moodleoverflow {{/ str }}
125+
</a>
126+
</div>
127+
</td>
128+
</tr>
129+
</table>

templates/reject_email_html.mustache renamed to templates/email_review_needed_text.mustache

+13-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
1616
}}
1717
{{!
18-
@template mod_moodleoverflow/email_html
18+
@template mod_moodleoverflow/email_reject_text
1919
2020
Template which defines a moodleoverflow post for sending in a single-post HTML email.
2121
@@ -77,12 +77,15 @@
7777
"unsubscribediscussionlink": "https://example.com/mod/discussion/subscribe.php?id=2&d=2"
7878
}
7979
}}
80-
<div class="navbar">
81-
<a target="_blank" href="{{{ courselink }}}">{{{ coursename }}}</a>
82-
&raquo;
83-
<a target="_blank" href="{{{ moodleoverflowviewlink }}}">{{{ moodleoverflowname }}}</a>
84-
{{# showdiscussionname }}
85-
&raquo;
86-
<a target="_blank" href="{{{ discussionlink }}}">{{{ discussionname }}}</a>
87-
{{/ showdiscussionname }}
88-
</div>
80+
{{{ coursename }}} -> {{{ moodleoverflowname }}}{{# showdiscussionname }} -> {{{ discussionname }}} {{/ showdiscussionname }}
81+
82+
{{# str }}review_needed, mod_moodleoverflow {{/str}}: {{ permalink }}
83+
84+
{{{ subject }}}
85+
{{# str }} bynameondate, mod_moodleoverflow, {
86+
"name": {{# quote }}{{{ authorfullname }}}{{/ quote }},
87+
"date": {{# quote}}{{ postdate }}{{/ quote }}
88+
} {{/ str }}
89+
---------------------------------------------------------------------
90+
{{{ message }}}
91+
---------------------------------------------------------------------

0 commit comments

Comments
 (0)