Skip to content
Permalink
Browse files

MDL-31355 mod_forum: Prevent users from posting after cut-off date

  • Loading branch information...
rezaies committed Jun 14, 2018
1 parent 99bcb31 commit cbf63d8efc874a1b6d9e66fbfde1c4ceb6352f4f
@@ -69,7 +69,9 @@ public function to_legacy_objects(array $forums) : array {
'completionreplies' => $forum->get_completion_replies(),
'completionposts' => $forum->get_completion_posts(),
'displaywordcount' => $forum->should_display_word_count(),
'lockdiscussionafter' => $forum->get_lock_discussions_after()
'lockdiscussionafter' => $forum->get_lock_discussions_after(),
'duedate' => $forum->get_due_date(),
'cutoffdate' => $forum->get_cutoff_date()
];
}, $forums);
}
@@ -99,6 +99,10 @@ class forum {
private $displaywordcounts;
/** @var bool $lockdiscussionafter Timestamp after which discussions should be locked */
private $lockdiscussionafter;
/** @var int $duedate Timestamp that represents the due date for forum posts */
private $duedate;
/** @var int $cutoffdate Timestamp after which forum posts will no longer be accepted */
private $cutoffdate;
/**
* Constructor
@@ -132,6 +136,8 @@ class forum {
* @param int $completionposts Completion posts
* @param bool $displaywordcount Should display word counts in posts
* @param int $lockdiscussionafter Timestamp after which discussions should be locked
* @param int $duedate Timestamp that represents the due date for forum posts
* @param int $cutoffdate Timestamp after which forum posts will no longer be accepted
*/
public function __construct(
context $context,
@@ -162,7 +168,9 @@ public function __construct(
int $completionreplies,
int $completionposts,
bool $displaywordcount,
int $lockdiscussionafter
int $lockdiscussionafter,
int $duedate,
int $cutoffdate
) {
$this->context = $context;
$this->coursemodule = $coursemodule;
@@ -193,6 +201,8 @@ public function __construct(
$this->completionposts = $completionposts;
$this->displaywordcount = $displaywordcount;
$this->lockdiscussionafter = $lockdiscussionafter;
$this->duedate = $duedate;
$this->cutoffdate = $cutoffdate;
}
/**
@@ -546,4 +556,66 @@ public function is_discussion_locked(discussion_entity $discussion) : bool {
return (($discussion->get_time_modified() + $this->get_lock_discussions_after()) < time());
}
/**
* Get the cutoff date.
*
* @return int
*/
public function get_cutoff_date() : int {
return $this->cutoffdate;
}
/**
* Does the forum have a cutoff date?
*
* @return bool
*/
public function has_cutoff_date() : bool {
return !empty($this->get_cutoff_date());
}
/**
* Is the cutoff date for the forum reached?
*
* @return bool
*/
public function is_cutoff_date_reached() : bool {
if ($this->has_cutoff_date() && ($this->get_cutoff_date() < time())) {
return true;
}
return false;
}
/**
* Get the due date.
*
* @return int
*/
public function get_due_date() : int {
return $this->duedate;
}
/**
* Does the forum have a due date?
*
* @return bool
*/
public function has_due_date() : bool {
return !empty($this->get_due_date());
}
/**
* Is the due date for the forum reached?
*
* @return bool
*/
public function is_due_date_reached() : bool {
if ($this->has_due_date() && ($this->get_due_date() < time())) {
return true;
}
return false;
}
}
@@ -100,7 +100,9 @@ public function get_forum_from_stdclass(
$record->completionreplies,
$record->completionposts,
$record->displaywordcount,
$record->lockdiscussionafter
$record->lockdiscussionafter,
$record->duedate,
$record->cutoffdate
);
}
@@ -110,6 +110,12 @@ public function can_create_discussions(stdClass $user, int $groupid = null) : bo
return false;
}
if ($this->forum->is_cutoff_date_reached()) {
if (!has_capability('mod/forum:canoverridecutoff', $this->get_context())) {
return false;
}
}
switch ($this->forum->get_type()) {
case 'news':
$capability = 'mod/forum:addnews';
@@ -377,6 +377,18 @@ private function get_notifications($user) : array {
$forum = $this->forum;
$renderer = $this->renderer;
if ($forum->is_cutoff_date_reached()) {
$notifications[] = (new notification(
get_string('cutoffdatereached', 'forum'),
notification::NOTIFY_INFO
))->set_show_closebutton();
} else if ($forum->has_due_date()) {
$notifications[] = (new notification(
get_string('thisforumhasduedate', 'forum', userdate($forum->get_due_date())),
notification::NOTIFY_INFO
))->set_show_closebutton();
}
if ($forum->is_discussion_locked($discussion)) {
$notifications[] = (new notification(
get_string('discussionlocked', 'forum'),
@@ -327,6 +327,18 @@ private function get_notifications(stdClass $user, ?int $groupid) : array {
$renderer = $this->renderer;
$capabilitymanager = $this->capabilitymanager;
if ($forum->is_cutoff_date_reached()) {
$notifications[] = (new notification(
get_string('cutoffdatereached', 'forum'),
notification::NOTIFY_INFO
))->set_show_closebutton();
} else if ($forum->has_due_date()) {
$notifications[] = (new notification(
get_string('thisforumhasduedate', 'forum', userdate($forum->get_due_date())),
notification::NOTIFY_INFO
))->set_show_closebutton();
}
if ($forum->has_blocking_enabled()) {
$notifications[] = (new notification(
get_string('thisforumisthrottled', 'forum', [
@@ -395,5 +395,15 @@
'manager' => CAP_ALLOW
)
),
'mod/forum:canoverridecutoff' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'mod/forum:canoverridediscussionlock'
),
);
@@ -126,6 +126,7 @@
$string['crontask'] = 'Forum mailings and maintenance jobs';
$string['cutoffdate'] = 'Cut-off date';
$string['cutoffdate_help'] = 'If set, the forum will not accept posts after this date.';
$string['cutoffdatereached'] = 'The cut-off date for posting to this forum is reached so you can no longer post to it.';
$string['cutoffdatevalidation'] = 'The cut-off date cannot be earlier than the due date.';
$string['delete'] = 'Delete';
$string['deleteddiscussion'] = 'The discussion topic has been deleted';
@@ -235,6 +236,7 @@
$string['forum:addnews'] = 'Add announcements';
$string['forum:addquestion'] = 'Add question';
$string['forum:allowforcesubscribe'] = 'Allow force subscribe';
$string['forum:canoverridecutoff'] = 'Post to forums after their cut-off date';
$string['forum:canoverridediscussionlock'] = 'Reply to locked discussions';
$string['forumauthorhidden'] = 'Author (hidden)';
$string['forumblockingalmosttoomanyposts'] = 'You are approaching the posting threshold. You have posted {$a->numposts} times in the last {$a->blockperiod} and the limit is {$a->blockafter} posts.';
@@ -587,6 +589,7 @@
$string['tagarea_forum_posts'] = 'Forum posts';
$string['tagsdeleted'] = 'Forum tags have been deleted';
$string['thisforumisthrottled'] = 'This forum has a limit to the number of forum postings you can make in a given time period - this is currently set at {$a->blockafter} posting(s) in {$a->blockperiod}';
$string['thisforumhasduedate'] = 'The due date for posting to this forum is {$a}.';
$string['timedhidden'] = 'Timed status: Hidden from students';
$string['timedposts'] = 'Timed posts';
$string['timedvisible'] = 'Timed status: Visible to all users';
@@ -3703,6 +3703,12 @@ function forum_user_can_post_discussion($forum, $currentgroup=null, $unused=-1,
$context = context_module::instance($cm->id);
}
if (forum_is_cutoff_date_reached($forum)) {
if (!has_capability('mod/forum:canoverridecutoff', $context)) {
return false;
}
}
if ($currentgroup === null) {
$currentgroup = groups_get_activity_group($cm);
}
@@ -3796,6 +3802,12 @@ function forum_user_can_post($forum, $discussion, $user=NULL, $cm=NULL, $course=
$context = context_module::instance($cm->id);
}
if (forum_is_cutoff_date_reached($forum)) {
if (!has_capability('mod/forum:canoverridecutoff', $context)) {
return false;
}
}
// Check whether the discussion is locked.
if (forum_discussion_is_locked($forum, $discussion)) {
if (!has_capability('mod/forum:canoverridediscussionlock', $context)) {
@@ -6305,6 +6317,26 @@ function mod_forum_inplace_editable($itemtype, $itemid, $newvalue) {
}
}
/**
* Determine whether the specified forum's cutoff date is reached.
*
* @param stdClass $forum The forum
* @return bool
*/
function forum_is_cutoff_date_reached($forum) {
$entityfactory = \mod_forum\local\container::get_entity_factory();
$coursemoduleinfo = get_fast_modinfo($forum->course);
$cminfo = $coursemoduleinfo->instances['forum'][$forum->id];
$forumentity = $entityfactory->get_forum_from_stdclass(
$forum,
context_module::instance($cminfo->id),
$cminfo->get_course_module_record(),
$cminfo->get_course()
);
return $forumentity->is_cutoff_date_reached();
}
/**
* Determine whether the specified discussion is time-locked.
*
@@ -92,6 +92,8 @@ public function test_entity() {
$completionposts = 0;
$displaywordcount = false;
$lockdiscussionafter = 0;
$duedate = 0;
$cutoffdate = 0;
$forum = new forum_entity(
$context,
@@ -122,7 +124,9 @@ public function test_entity() {
$completionreplies,
$completionposts,
$displaywordcount,
$lockdiscussionafter
$lockdiscussionafter,
$duedate,
$cutoffdate
);
$this->assertEquals($context, $forum->get_context());
@@ -160,5 +164,9 @@ public function test_entity() {
$this->assertEquals($lockdiscussionafter, $forum->get_lock_discussions_after());
$this->assertEquals(false, $forum->has_lock_discussions_after());
$this->assertEquals(false, $forum->is_discussion_locked($discussion));
$this->assertEquals(false, $forum->has_due_date());
$this->assertEquals(false, $forum->is_due_date_reached());
$this->assertEquals(false, $forum->has_cutoff_date());
$this->assertEquals(false, $forum->is_cutoff_date_reached());
}
}
@@ -1458,7 +1458,34 @@ public function test_can_add_discussion() {
$this->assertTrue($result['status']);
$this->assertTrue($result['canpindiscussions']);
$this->assertTrue($result['cancreateattachment']);
}
/*
* A basic test to make sure users cannot post to forum after the cutoff date.
*/
public function test_can_add_discussion_after_cutoff() {
$this->resetAfterTest(true);
// Create courses to add the modules.
$course = self::getDataGenerator()->create_course();
$user = self::getDataGenerator()->create_user();
// Create a forum with cutoff date set to a past date.
$forum = self::getDataGenerator()->create_module('forum', ['course' => $course->id, 'cutoffdate' => time() - 1]);
// User with no mod/forum:canoverridecutoff capability.
self::setUser($user);
$this->getDataGenerator()->enrol_user($user->id, $course->id);
$result = mod_forum_external::can_add_discussion($forum->id);
$result = external_api::clean_returnvalue(mod_forum_external::can_add_discussion_returns(), $result);
$this->assertFalse($result['status']);
self::setAdminUser();
$result = mod_forum_external::can_add_discussion($forum->id);
$result = external_api::clean_returnvalue(mod_forum_external::can_add_discussion_returns(), $result);
$this->assertTrue($result['status']);
}
/**

0 comments on commit cbf63d8

Please sign in to comment.
You can’t perform that action at this time.