Merge branch 'MDL-86995-main' of https://github.com/sh-csg/moodle

This commit is contained in:
Mihail Geshoski
2025-12-23 16:46:57 +08:00
13 changed files with 167 additions and 18 deletions
@@ -38,13 +38,35 @@ class backup_forum_activity_structure_step extends backup_activity_structure_ste
// Define each element separated
$forum = new backup_nested_element('forum', array('id'), array(
'type', 'name', 'intro', 'introformat', 'duedate', 'cutoffdate',
'assessed', 'assesstimestart', 'assesstimefinish', 'scale',
'maxbytes', 'maxattachments', 'forcesubscribe', 'trackingtype',
'rsstype', 'rssarticles', 'timemodified', 'warnafter',
'blockafter', 'blockperiod', 'completiondiscussions', 'completionreplies',
'completionposts', 'displaywordcount', 'lockdiscussionafter', 'grade_forum'));
$forum = new backup_nested_element('forum', ['id'], [
'type',
'name',
'intro',
'introformat',
'duedate',
'cutoffdate',
'assessed',
'assesstimestart',
'assesstimefinish',
'scale',
'maxbytes',
'maxattachments',
'forcesubscribe',
'trackingtype',
'rsstype',
'rssarticles',
'timemodified',
'warnafter',
'blockafter',
'blockperiod',
'completiondiscussions',
'completionreplies',
'completionposts',
'displaywordcount',
'lockdiscussionafter',
'grade_forum',
'showimmediately',
]);
$discussions = new backup_nested_element('discussions');
@@ -73,7 +73,8 @@ class forum {
'displaywordcount' => $forum->should_display_word_count(),
'lockdiscussionafter' => $forum->get_lock_discussions_after(),
'duedate' => $forum->get_due_date(),
'cutoffdate' => $forum->get_cutoff_date()
'cutoffdate' => $forum->get_cutoff_date(),
'showimmediately' => $forum->get_showimmediately(),
];
}, $forums);
}
@@ -107,6 +107,8 @@ class forum {
private $duedate;
/** @var int $cutoffdate Timestamp after which forum posts will no longer be accepted */
private $cutoffdate;
/** @var bool $showimmediately Whether to show replies in a qanda forum immediately */
private bool $showimmediately;
/**
* Constructor
@@ -144,6 +146,7 @@ class forum {
* @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
* @param bool $showimmediately Whether to show replies in a qanda forum immediately
*/
public function __construct(
context $context,
@@ -178,7 +181,8 @@ class forum {
bool $displaywordcount,
int $lockdiscussionafter,
int $duedate,
int $cutoffdate
int $cutoffdate,
bool $showimmediately
) {
$this->context = $context;
$this->coursemodule = $coursemodule;
@@ -213,6 +217,7 @@ class forum {
$this->lockdiscussionafter = $lockdiscussionafter;
$this->duedate = $duedate;
$this->cutoffdate = $cutoffdate;
$this->showimmediately = $showimmediately;
}
/**
@@ -669,4 +674,13 @@ class forum {
return $this->is_discussion_time_locked($discussion);
}
/**
* Get the value of showimmediately
*
* @return bool
*/
public function get_showimmediately(): bool {
return $this->showimmediately;
}
}
@@ -104,7 +104,8 @@ class entity {
$record->displaywordcount,
$record->lockdiscussionafter,
$record->duedate,
$record->cutoffdate
$record->cutoffdate,
$record->showimmediately
);
}
+2 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/forum/db" VERSION="20250414" COMMENT="XMLDB file for Moodle mod/forum"
<XMLDB PATH="mod/forum/db" VERSION="20251105" COMMENT="XMLDB file for Moodle mod/forum"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@@ -35,6 +35,7 @@
<FIELD NAME="completionposts" TYPE="int" LENGTH="9" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Nonzero if a certain number of posts or replies (total) are required to mark this forum complete for a user."/>
<FIELD NAME="displaywordcount" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="lockdiscussionafter" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="showimmediately" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+14
View File
@@ -69,5 +69,19 @@ function xmldb_forum_upgrade($oldversion) {
// Automatically generated Moodle v5.1.0 release upgrade line.
// Put any upgrade step following this.
if ($oldversion < 2025110500) {
// Define field showimmediately to be added to forum.
$table = new xmldb_table('forum');
$field = new xmldb_field('showimmediately', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'lockdiscussionafter');
// Conditionally launch add field showimmediately.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Forum savepoint reached.
upgrade_mod_savepoint(true, 2025110500, 'forum');
}
return true;
}
+8 -2
View File
@@ -139,7 +139,7 @@ class mod_forum_external extends external_api {
// Also, the return type declaration is wrong, but I am not changing it now because I don't want ot break things.
return new external_multiple_structure(
new external_single_structure(
array(
[
'id' => new external_value(PARAM_INT, 'Forum id'),
'course' => new external_value(PARAM_INT, 'Course id'),
'type' => new external_value(PARAM_TEXT, 'The forum type'),
@@ -176,7 +176,13 @@ class mod_forum_external extends external_api {
'istracked' => new external_value(PARAM_BOOL, 'If the user is tracking the forum', VALUE_OPTIONAL),
'unreadpostscount' => new external_value(PARAM_INT, 'The number of unread posts for tracked forums',
VALUE_OPTIONAL),
), 'forum'
'showimmediately' => new external_value(
PARAM_BOOL,
'Whether to show replies immediately in a Q&A forum',
VALUE_OPTIONAL
),
],
'forum'
)
);
}
+2
View File
@@ -370,6 +370,8 @@ $string['indicator:socialbreadth_help'] = 'This indicator is based on the social
$string['indicator:socialbreadthdef'] = 'Forum social';
$string['indicator:socialbreadthdef_help'] = 'The participant has reached this percentage of the social engagement offered by the Forum activities during this analysis interval (Levels = No participation, Participant alone, Participant with others)';
$string['indicator:socialbreadthdef_link'] = 'Learning_analytics_indicators#Social_breadth';
$string['showimmediately'] = 'Show other replies immediately after posting';
$string['showimmediately_help'] = 'This will show the replies of other participants before reaching the maximum editing time ({$a} minutes). Participants could still change their post during this time.';
$string['starredonly'] = 'Search starred discussions only';
$string['indexoutoftotal'] = '{$a->index} out of {$a->total}';
$string['inforum'] = 'in {$a}';
+4 -3
View File
@@ -580,7 +580,7 @@ function forum_print_recent_activity($course, $viewfullnames, $timestart) {
f.scale, f.grade_forum, f.maxbytes, f.maxattachments, f.forcesubscribe,
f.trackingtype, f.rsstype, f.rssarticles, f.timemodified, f.warnafter, f.blockafter,
f.blockperiod, f.completiondiscussions, f.completionreplies, f.completionposts,
f.displaywordcount, f.lockdiscussionafter, f.grade_forum_notify,
f.displaywordcount, f.lockdiscussionafter, f.grade_forum_notify, f.showimmediately,
d.name AS discussionname, d.firstpost, d.userid AS discussionstarter,
d.assessed AS discussionassessed, d.timemodified, d.usermodified, d.forum, d.groupid,
d.timestart, d.timeend, d.pinned, d.timelocked,
@@ -672,7 +672,8 @@ function forum_print_recent_activity($course, $viewfullnames, $timestart) {
'completionposts' => $post->completionposts,
'displaywordcount' => $post->displaywordcount,
'lockdiscussionafter' => $post->lockdiscussionafter,
'grade_forum_notify' => $post->grade_forum_notify
'grade_forum_notify' => $post->grade_forum_notify,
'showimmediately' => $post->showimmediately,
];
// Build the forum entity from the factory.
$forumentity = $entityfactory->get_forum_from_stdclass($forumrecord, $context, $coursemodule, $course);
@@ -3901,7 +3902,7 @@ function forum_user_can_see_post($forum, $discussion, $post, $user = null, $cm =
return true;
}
$userfirstpost = forum_get_user_posted_time($discussion->id, $user->id);
return (($userfirstpost !== false && (time() - $userfirstpost >= $CFG->maxeditingtime)));
return ($userfirstpost !== false && (time() - $userfirstpost >= $CFG->maxeditingtime || $forum->showimmediately));
}
return true;
}
+5
View File
@@ -56,6 +56,11 @@ class mod_forum_mod_form extends moodleform_mod {
$mform->addHelpButton('type', 'forumtype', 'forum');
$mform->setDefault('type', 'general');
$mform->addElement('advcheckbox', 'showimmediately', get_string('showimmediately', 'forum'));
$mform->addHelpButton('showimmediately', 'showimmediately', 'forum', '', false, $CFG->maxeditingtime / 60);
$mform->setDefault('showimmediately', 0);
$mform->hideIf('showimmediately', 'type', 'neq', 'qanda');
$mform->addElement('header', 'availability', get_string('availability', 'forum'));
$name = get_string('duedate', 'forum');
@@ -0,0 +1,80 @@
@mod @mod_forum
Feature: QandA forum discussion type
In order to let students first see other replies to a post after replying themselves
As a teacher
I need to create a forum of qand a type
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "activities" exist:
| activity | name | intro | type | course | idnumber | showimmediately |
| forum | Q and A forum | Q and A forum description | qanda | C1 | forum | 0 |
And the following "mod_forum > discussions" exist:
| forum | name | subject | message | user |
| forum | Discussion 1 | Discussion 1 | Discussion contents 1, first message | student1 |
| forum | Discussion 2 | Discussion 2 | Discussion contents 2, first message | teacher1 |
And the following "mod_forum > posts" exist:
| parentsubject | subject | message | user |
| Discussion 1 | Reply 1 to discussion 1 | Discussion contents 1, second message | student2 |
| Discussion 2 | Reply 1 to discussion 2 | Discussion contents 2, second message | student2 |
Scenario: Students can see all replies to own discussions
When I am on the "Q and A forum" "forum activity" page logged in as student1
And I follow "Discussion 1"
Then I should see "Reply 1 to discussion 1"
Scenario: Teachers can see all replies
When I am on the "Q and A forum" "forum activity" page logged in as teacher1
And I follow "Discussion 1"
Then I should see "Reply 1 to discussion 1"
Scenario: Students can't see replies to discussions from other users they didn't reply to yet
When I am on the "Q and A forum" "forum activity" page logged in as student1
And I follow "Discussion 2"
Then I should not see "Reply 1 to discussion 2"
Scenario: Students can't see replies to discussions from other users when they have replied but they are within the maximum editing time
Given the following "mod_forum > posts" exist:
| parentsubject | subject | message | user |
| Discussion 2 | Reply 2 to discussion 1 | Discussion contents 2, third message | student1 |
When I am on the "Q and A forum" "forum activity" page logged in as student1
And I follow "Discussion 2"
Then I should not see "Reply 1 to discussion 2"
Scenario: Students can see replies to discussions from other users when they have replied and they can't edit the post anymore
Given the following "mod_forum > posts" exist:
| parentsubject | subject | message | user | created |
| Discussion 2 | Reply 2 to discussion 2 | Discussion contents 2, third message | student1 | ##now +1 second## |
And the following config values are set as admin:
| maxeditingtime | 1 |
And I wait "2" seconds
When I am on the "Q and A forum" "forum activity" page logged in as student1
And I follow "Discussion 2"
Then I should see "Reply 1 to discussion 2"
Scenario: Students can see replies to discussions from other users when they have replied regardless of editing time when showimmediately option is set
Given the following "activities" exist:
| activity | name | intro | type | course | idnumber | showimmediately |
| forum | Q and A forum showimmediately | Q and A forum description | qanda | C1 | forum2 | 1 |
And the following "mod_forum > discussions" exist:
| forum | name | subject | message | user |
| forum2 | Discussion 3 | Discussion 3 | Discussion contents 3, first message | teacher1 |
And the following "mod_forum > posts" exist:
| parentsubject | subject | message | user |
| Discussion 3 | Reply 1 to discussion 3 | Discussion contents 3, second message | student2 |
| Discussion 3 | Reply 2 to discussion 3 | Discussion contents 3, second message | student1 |
When I am on the "Q and A forum showimmediately" "forum activity" page logged in as student1
And I follow "Discussion 3"
Then I should see "Reply 1 to discussion 3"
@@ -91,6 +91,7 @@ final class entities_forum_test extends \advanced_testcase {
$duedate = 0;
$cutoffdate = 0;
$sendnotification = false;
$showimmediately = false;
$forum = new forum_entity(
$context,
$coursemodule,
@@ -124,7 +125,8 @@ final class entities_forum_test extends \advanced_testcase {
$displaywordcount,
$lockdiscussionafter,
$duedate,
$cutoffdate
$cutoffdate,
$showimmediately
);
$this->assertEquals($context, $forum->get_context());
+1 -1
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2025100600; // The current module version (Date: YYYYMMDDXX).
$plugin->version = 2025110500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2025092600; // Requires this Moodle version.
$plugin->component = 'mod_forum'; // Full name of the plugin (used for diagnostics)