mirror of
https://github.com/moodle/moodle.git
synced 2025-03-31 05:52:51 +02:00
MDL-66301 forumreport_summary: Add course level reporting
This adds the ability to report on all forums the user has access to within a course.
This commit is contained in:
parent
d939d6e769
commit
54a3b94452
@ -58,13 +58,16 @@ class report_downloaded extends \core\event\base {
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
if ($this->other['hasviewall']) {
|
||||
return "The user with id '{$this->userid}' downloaded the summary report for the forum with " .
|
||||
"course module id '{$this->contextinstanceid}'.";
|
||||
$whose = $this->other['hasviewall'] ? 'the' : 'their own';
|
||||
$description = "The user with id '{$this->userid}' downloaded {$whose} summary report for ";
|
||||
|
||||
if ($this->other['forumid']) {
|
||||
$description .= "the forum with course module id '{$this->contextinstanceid}'.";
|
||||
} else {
|
||||
return "The user with id '{$this->userid}' downloaded their own summary report for the forum with " .
|
||||
"course module id '{$this->contextinstanceid}'.";
|
||||
$description .= "the course with id '{$this->contextinstanceid}'.";
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,14 +58,16 @@ class report_viewed extends \core\event\base {
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
if ($this->other['hasviewall']) {
|
||||
return "The user with id '{$this->userid}' viewed the summary report for the forum with " .
|
||||
"course module id '{$this->contextinstanceid}'.";
|
||||
$whose = $this->other['hasviewall'] ? 'the' : 'their own';
|
||||
$description = "The user with id '{$this->userid}' viewed {$whose} summary report for ";
|
||||
|
||||
if ($this->other['forumid']) {
|
||||
$description .= "the forum with course module id '{$this->contextinstanceid}'.";
|
||||
} else {
|
||||
return "The user with id '{$this->userid}' viewed their own summary report for the forum with " .
|
||||
"course module id '{$this->contextinstanceid}'.";
|
||||
$description .= "the course with id '{$this->contextinstanceid}'.";
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,11 +42,19 @@ defined('MOODLE_INTERNAL') || die();
|
||||
class filters implements renderable, templatable {
|
||||
|
||||
/**
|
||||
* Course module the report is being run within.
|
||||
* Course modules the report relates to.
|
||||
* Array of stdClass objects
|
||||
*
|
||||
* @var stdClass $cm
|
||||
* @var array $cms
|
||||
*/
|
||||
protected $cm;
|
||||
protected $cms;
|
||||
|
||||
/**
|
||||
* Course ID where the report is being generated.
|
||||
*
|
||||
* @var int $courseid
|
||||
*/
|
||||
protected $courseid;
|
||||
|
||||
/**
|
||||
* Moodle URL used as the form action on the generate button.
|
||||
@ -98,13 +106,14 @@ class filters implements renderable, templatable {
|
||||
/**
|
||||
* Builds renderable filter data.
|
||||
*
|
||||
* @param stdClass $cm The course module object.
|
||||
* @param array $cms Array of course module objects.
|
||||
* @param moodle_url $actionurl The form action URL.
|
||||
* @param array $filterdata (optional) Associative array of data that has been set on available filters, if any,
|
||||
* in the format filtertype => [values]
|
||||
* in the format filtertype => [values]
|
||||
*/
|
||||
public function __construct(stdClass $cm, moodle_url $actionurl, array $filterdata = []) {
|
||||
$this->cm = $cm;
|
||||
public function __construct(array $cms, moodle_url $actionurl, array $filterdata = []) {
|
||||
$this->cms = $cms;
|
||||
$this->courseid = $cms[0]->course;
|
||||
$this->actionurl = $actionurl;
|
||||
|
||||
// Prepare groups filter data.
|
||||
@ -126,26 +135,46 @@ class filters implements renderable, templatable {
|
||||
protected function prepare_groups_data(array $groupsdata): void {
|
||||
global $DB, $USER;
|
||||
|
||||
$groupmode = groups_get_activity_groupmode($this->cm);
|
||||
$context = \context_module::instance($this->cm->id);
|
||||
$aag = has_capability('moodle/site:accessallgroups', $context);
|
||||
$groupsavailable = [];
|
||||
$allowedgroupsobj = [];
|
||||
|
||||
// If no groups mode enabled, nothing to prepare.
|
||||
if (!in_array($groupmode, [VISIBLEGROUPS, SEPARATEGROUPS])) {
|
||||
return;
|
||||
$usergroups = groups_get_all_groups($this->courseid, $USER->id);
|
||||
$coursegroups = groups_get_all_groups($this->courseid);
|
||||
$forumids = [];
|
||||
$allgroups = false;
|
||||
|
||||
// Check if any forum gives the user access to all groups and no groups.
|
||||
foreach ($this->cms as $cm) {
|
||||
$forumids[] = $cm->instance;
|
||||
|
||||
// Only need to check for all groups access if not confirmed by a previous check.
|
||||
if (!$allgroups) {
|
||||
$groupmode = groups_get_activity_groupmode($cm);
|
||||
|
||||
// If no groups mode enabled on the forum, nothing to prepare.
|
||||
if (!in_array($groupmode, [VISIBLEGROUPS, SEPARATEGROUPS])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch for the current cm's forum.
|
||||
$context = \context_module::instance($cm->id);
|
||||
$aag = has_capability('moodle/site:accessallgroups', $context);
|
||||
|
||||
if ($groupmode == VISIBLEGROUPS || $aag) {
|
||||
$allgroups = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($groupmode == VISIBLEGROUPS || $aag) {
|
||||
// Any groups, and no groups.
|
||||
$allowedgroupsobj = groups_get_all_groups($this->cm->course, 0, $this->cm->groupingid);
|
||||
// Any groups, and no groups.
|
||||
if ($allgroups) {
|
||||
$nogroups = new stdClass();
|
||||
$nogroups->id = -1;
|
||||
$nogroups->name = get_string('groupsnone');
|
||||
$allowedgroupsobj[] = $nogroups;
|
||||
|
||||
$allowedgroupsobj = $coursegroups + [$nogroups];
|
||||
} else {
|
||||
// Only assigned groups.
|
||||
$allowedgroupsobj = groups_get_all_groups($this->cm->course, $USER->id, $this->cm->groupingid);
|
||||
$allowedgroupsobj = $usergroups;
|
||||
}
|
||||
|
||||
foreach ($allowedgroupsobj as $group) {
|
||||
@ -159,16 +188,15 @@ class filters implements renderable, templatable {
|
||||
$this->groupsavailable = $groupsavailable;
|
||||
$this->groupsselected = $groupsselected;
|
||||
|
||||
// If export links will require discussion filtering, find and set the discussion IDs.
|
||||
$groupsselectedcount = count($groupsselected);
|
||||
if ($groupsselectedcount > 0 && $groupsselectedcount < count($groupsavailable)) {
|
||||
list($forumidin, $forumidparams) = $DB->get_in_or_equal($forumids, SQL_PARAMS_NAMED);
|
||||
list($groupidin, $groupidparams) = $DB->get_in_or_equal($groupsselected, SQL_PARAMS_NAMED);
|
||||
$dwhere = "course = :courseid AND forum = :forumid AND groupid {$groupidin}";
|
||||
$dparams = [
|
||||
'courseid' => $this->cm->course,
|
||||
'forumid' => $this->cm->instance,
|
||||
];
|
||||
$dparams += $groupidparams;
|
||||
|
||||
$dwhere = "course = :courseid AND forum {$forumidin} AND groupid {$groupidin}";
|
||||
$dparams = ['courseid' => $this->courseid];
|
||||
$dparams += $forumidparams + $groupidparams;
|
||||
|
||||
$discussionids = $DB->get_fieldset_select('forum_discussions', 'DISTINCT id', $dwhere, $dparams);
|
||||
|
||||
foreach ($discussionids as $discussionid) {
|
||||
|
@ -62,8 +62,14 @@ class summary_table extends table_sql {
|
||||
/** @var array The values available for pagination size per page. */
|
||||
protected $perpageoptions = [50, 100, 200];
|
||||
|
||||
/** @var \stdClass The course module object of the forum being reported on. */
|
||||
protected $cm;
|
||||
/** @var int The course ID containing the forum(s) being reported on. */
|
||||
protected $courseid;
|
||||
|
||||
/** @var bool True if reporting on all forums in course, false if reporting on specific forum(s) */
|
||||
protected $accessallforums = false;
|
||||
|
||||
/** @var \stdClass The course module object(s) of the forum(s) being reported on. */
|
||||
protected $cms = [];
|
||||
|
||||
/**
|
||||
* @var int The user ID if only one user's summary will be generated.
|
||||
@ -77,9 +83,14 @@ class summary_table extends table_sql {
|
||||
protected $logreader = null;
|
||||
|
||||
/**
|
||||
* @var \context|null
|
||||
* @var array of \context objects for the forums included in the report.
|
||||
*/
|
||||
protected $context = null;
|
||||
protected $forumcontexts = [];
|
||||
|
||||
/**
|
||||
* @var context_course|context_module The context where the report is being run (either a specific forum or the course).
|
||||
*/
|
||||
protected $userfieldscontext = null;
|
||||
|
||||
/** @var bool Whether the user has the capability/capabilities to perform bulk operations. */
|
||||
protected $allowbulkoperations = false;
|
||||
@ -108,25 +119,22 @@ class summary_table extends table_sql {
|
||||
* @param bool $canseeprivatereplies Whether the user can see all private replies or not.
|
||||
* @param int $perpage The number of rows to display per page.
|
||||
* @param bool $canexport Is the user allowed to export records?
|
||||
* @param bool $accessallforums If user is running a course level report, do they have access to all forums in the course?
|
||||
*/
|
||||
public function __construct(int $courseid, array $filters, bool $allowbulkoperations,
|
||||
bool $canseeprivatereplies, int $perpage, bool $canexport) {
|
||||
bool $canseeprivatereplies, int $perpage, bool $canexport, bool $accessallforums) {
|
||||
global $USER, $OUTPUT;
|
||||
|
||||
$forumid = $filters['forums'][0];
|
||||
$uniqueid = $courseid . (empty($filters['forums']) ? '' : '_' . $filters['forums'][0]);
|
||||
parent::__construct("summaryreport_{$uniqueid}");
|
||||
|
||||
parent::__construct("summaryreport_{$courseid}_{$forumid}");
|
||||
|
||||
$this->cm = get_coursemodule_from_instance('forum', $forumid, $courseid);
|
||||
$this->context = \context_module::instance($this->cm->id);
|
||||
$this->courseid = $courseid;
|
||||
$this->accessallforums = $accessallforums;
|
||||
$this->allowbulkoperations = $allowbulkoperations;
|
||||
$this->canseeprivatereplies = $canseeprivatereplies;
|
||||
$this->perpage = $perpage;
|
||||
|
||||
// Only show their own summary unless they have permission to view all.
|
||||
if (!has_capability('forumreport/summary:viewall', $this->context)) {
|
||||
$this->userid = $USER->id;
|
||||
}
|
||||
$this->set_forum_properties($filters['forums']);
|
||||
|
||||
$columnheaders = [];
|
||||
|
||||
@ -180,6 +188,37 @@ class summary_table extends table_sql {
|
||||
$this->define_base_sql();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets properties that are determined by forum filter values.
|
||||
*
|
||||
* @param array $forumids The forum IDs passed in by the filter.
|
||||
* @return void
|
||||
*/
|
||||
protected function set_forum_properties(array $forumids): void {
|
||||
global $USER;
|
||||
|
||||
// If no forum IDs filtered, reporting on all forums in the course the user has access to.
|
||||
if ($this->accessallforums) {
|
||||
$this->userfieldscontext = \context_course::instance($this->courseid);
|
||||
}
|
||||
|
||||
foreach ($forumids as $forumid) {
|
||||
$cm = get_coursemodule_from_instance('forum', $forumid, $this->courseid);
|
||||
$this->cms[] = $cm;
|
||||
$this->forumcontexts[$cm->id] = \context_module::instance($cm->id);
|
||||
|
||||
// Set forum context if not reporting on course.
|
||||
if (!isset($this->userfieldscontext)) {
|
||||
$this->userfieldscontext = $this->forumcontexts[$cm->id];
|
||||
}
|
||||
|
||||
// Only show own summary unless they have permission to view all in every forum being reported.
|
||||
if (empty($this->userid) && !has_capability('forumreport/summary:viewall', $this->forumcontexts[$cm->id])) {
|
||||
$this->userid = $USER->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the string name of each filter type, to be used by errors.
|
||||
* Note: This does not use language strings as the value is injected into error strings.
|
||||
@ -230,7 +269,7 @@ class summary_table extends table_sql {
|
||||
}
|
||||
|
||||
global $OUTPUT;
|
||||
return $OUTPUT->user_picture($data, array('size' => 35, 'courseid' => $this->cm->course, 'includefullname' => true));
|
||||
return $OUTPUT->user_picture($data, array('size' => 35, 'courseid' => $this->courseid, 'includefullname' => true));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,12 +336,13 @@ class summary_table extends table_sql {
|
||||
global $OUTPUT;
|
||||
|
||||
// If no posts, nothing to export.
|
||||
if (empty($data->earliestpost)) {
|
||||
// If reporting on more than one forum (eg a course), unable to export (export only handles a single forum).
|
||||
if (empty($data->earliestpost) || count($this->cms) > 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$params = [
|
||||
'id' => $this->cm->instance, // Forum id.
|
||||
'id' => $this->cms[0]->instance, // Forum id.
|
||||
'userids[]' => $data->userid, // User id.
|
||||
];
|
||||
|
||||
@ -381,14 +421,15 @@ class summary_table extends table_sql {
|
||||
|
||||
switch($filtertype) {
|
||||
case self::FILTER_FORUM:
|
||||
// Requires exactly one forum ID.
|
||||
if (count($values) != 1) {
|
||||
// Requires at least one forum ID.
|
||||
if (empty($values)) {
|
||||
$paramcounterror = true;
|
||||
} else {
|
||||
// No select fields required - displayed in title.
|
||||
// No extra joins required, forum is already joined.
|
||||
$this->sql->filterwhere .= ' AND f.id = :forumid';
|
||||
$this->sql->params['forumid'] = $values[0];
|
||||
list($forumidin, $forumidparams) = $DB->get_in_or_equal($values, SQL_PARAMS_NAMED);
|
||||
$this->sql->filterwhere .= " AND f.id {$forumidin}";
|
||||
$this->sql->params += $forumidparams;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -498,13 +539,12 @@ class summary_table extends table_sql {
|
||||
protected function define_base_sql(): void {
|
||||
global $USER;
|
||||
|
||||
$userfields = get_extra_user_fields($this->context);
|
||||
$userfields = get_extra_user_fields($this->userfieldscontext);
|
||||
$userfieldssql = \user_picture::fields('u', $userfields);
|
||||
|
||||
// Define base SQL query format.
|
||||
$this->sql->basefields = ' ue.userid AS userid,
|
||||
e.courseid AS courseid,
|
||||
f.id as forumid,
|
||||
SUM(CASE WHEN p.parent = 0 THEN 1 ELSE 0 END) AS postcount,
|
||||
SUM(CASE WHEN p.parent != 0 THEN 1 ELSE 0 END) AS replycount,
|
||||
' . $userfieldssql . ',
|
||||
@ -543,10 +583,10 @@ class summary_table extends table_sql {
|
||||
|
||||
$this->sql->basewhere = 'e.courseid = :courseid';
|
||||
|
||||
$this->sql->basegroupby = 'ue.userid, e.courseid, f.id, u.id, ' . $userfieldssql;
|
||||
$this->sql->basegroupby = 'ue.userid, e.courseid, u.id, ' . $userfieldssql;
|
||||
|
||||
if ($this->logreader) {
|
||||
$this->fill_log_summary_temp_table($this->context->id);
|
||||
$this->fill_log_summary_temp_table();
|
||||
|
||||
$this->sql->basefields .= ', CASE WHEN tmp.viewcount IS NOT NULL THEN tmp.viewcount ELSE 0 END AS viewcount';
|
||||
$this->sql->basefromjoins .= ' LEFT JOIN {' . self::LOG_SUMMARY_TEMP_TABLE . '} tmp ON tmp.userid = u.id ';
|
||||
@ -561,7 +601,7 @@ class summary_table extends table_sql {
|
||||
|
||||
$this->sql->params += [
|
||||
'component' => 'mod_forum',
|
||||
'courseid' => $this->cm->course,
|
||||
'courseid' => $this->courseid,
|
||||
] + $privaterepliesparams;
|
||||
|
||||
// Handle if a user is limited to viewing their own summary.
|
||||
@ -642,8 +682,10 @@ class summary_table extends table_sql {
|
||||
* @return void.
|
||||
*/
|
||||
protected function apply_filters(array $filters): void {
|
||||
// Apply the forums filter.
|
||||
$this->add_filter(self::FILTER_FORUM, $filters['forums']);
|
||||
// Apply the forums filter if not reporting on whole course.
|
||||
if (!$this->accessallforums) {
|
||||
$this->add_filter(self::FILTER_FORUM, $filters['forums']);
|
||||
}
|
||||
|
||||
// Apply groups filter.
|
||||
$this->add_filter(self::FILTER_GROUPS, $filters['groups']);
|
||||
@ -719,10 +761,9 @@ class summary_table extends table_sql {
|
||||
/**
|
||||
* Fills the log summary temp table.
|
||||
*
|
||||
* @param int $contextid
|
||||
* @return null
|
||||
*/
|
||||
protected function fill_log_summary_temp_table(int $contextid) {
|
||||
protected function fill_log_summary_temp_table() {
|
||||
global $DB;
|
||||
|
||||
$this->create_log_summary_temp_table();
|
||||
@ -740,11 +781,19 @@ class summary_table extends table_sql {
|
||||
$datewhere = $this->sql->filterbase['dateslog'] ?? '';
|
||||
$dateparams = $this->sql->filterbase['dateslogparams'] ?? [];
|
||||
|
||||
$params = ['contextid' => $contextid] + $dateparams;
|
||||
$contextids = [];
|
||||
|
||||
foreach ($this->forumcontexts as $forumcontext) {
|
||||
$contextids[] = $forumcontext->id;
|
||||
}
|
||||
|
||||
list($contextidin, $contextidparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
|
||||
|
||||
$params = $contextidparams + $dateparams;
|
||||
$sql = "INSERT INTO {" . self::LOG_SUMMARY_TEMP_TABLE . "} (userid, viewcount)
|
||||
SELECT userid, COUNT(*) AS viewcount
|
||||
FROM {" . $logtable . "}
|
||||
WHERE contextid = :contextid
|
||||
WHERE contextid {$contextidin}
|
||||
$datewhere
|
||||
$nonanonymous
|
||||
GROUP BY userid";
|
||||
@ -797,42 +846,64 @@ class summary_table extends table_sql {
|
||||
protected function get_filter_groups(array $groups): array {
|
||||
global $USER;
|
||||
|
||||
$groupmode = groups_get_activity_groupmode($this->cm);
|
||||
$aag = has_capability('moodle/site:accessallgroups', $this->context);
|
||||
$usergroups = groups_get_all_groups($this->courseid, $USER->id);
|
||||
$coursegroupsobj = groups_get_all_groups($this->courseid);
|
||||
$allgroups = false;
|
||||
$allowedgroupsobj = [];
|
||||
$allowedgroups = [];
|
||||
$filtergroups = [];
|
||||
|
||||
// Filtering only valid if a forum groups mode is enabled.
|
||||
if (in_array($groupmode, [VISIBLEGROUPS, SEPARATEGROUPS])) {
|
||||
$allgroupsobj = groups_get_all_groups($this->cm->course, 0, $this->cm->groupingid);
|
||||
$allgroups = [];
|
||||
foreach ($this->cms as $cm) {
|
||||
// Only need to check for all groups access if not confirmed by a previous check.
|
||||
if (!$allgroups) {
|
||||
$groupmode = groups_get_activity_groupmode($cm);
|
||||
|
||||
foreach ($allgroupsobj as $group) {
|
||||
$allgroups[] = $group->id;
|
||||
// If no groups mode enabled on the forum, nothing to prepare.
|
||||
if (!in_array($groupmode, [VISIBLEGROUPS, SEPARATEGROUPS])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$aag = has_capability('moodle/site:accessallgroups', $this->forumcontexts[$cm->id]);
|
||||
|
||||
if ($groupmode == VISIBLEGROUPS || $aag) {
|
||||
$allgroups = true;
|
||||
|
||||
// All groups in course fetched, no need to continue checking for others.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($groupmode == VISIBLEGROUPS || $aag) {
|
||||
$nogroups = new \stdClass();
|
||||
$nogroups->id = -1;
|
||||
$nogroups->name = get_string('groupsnone');
|
||||
if ($allgroups) {
|
||||
$nogroups = new \stdClass();
|
||||
$nogroups->id = -1;
|
||||
$nogroups->name = get_string('groupsnone');
|
||||
|
||||
// Any groups and no groups.
|
||||
$allowedgroupsobj = $allgroupsobj + [$nogroups];
|
||||
} else {
|
||||
// Only assigned groups.
|
||||
$allowedgroupsobj = groups_get_all_groups($this->cm->course, $USER->id, $this->cm->groupingid);
|
||||
}
|
||||
// Any groups and no groups.
|
||||
$allowedgroupsobj = $coursegroupsobj + [$nogroups];
|
||||
} else {
|
||||
$allowedgroupsobj = $usergroups;
|
||||
}
|
||||
|
||||
foreach ($allowedgroupsobj as $group) {
|
||||
$allowedgroups[] = $group->id;
|
||||
}
|
||||
foreach ($allowedgroupsobj as $group) {
|
||||
$allowedgroups[] = $group->id;
|
||||
}
|
||||
|
||||
// If not all groups in course are selected, filter by allowed groups submitted.
|
||||
if (!empty($groups) && !empty(array_diff($allowedgroups, $groups))) {
|
||||
// If not all groups in course are selected, filter by allowed groups submitted.
|
||||
if (!empty($groups)) {
|
||||
if (!empty(array_diff($allowedgroups, $groups))) {
|
||||
$filtergroups = array_intersect($groups, $allowedgroups);
|
||||
} else if (!empty(array_diff($allgroups, $allowedgroups))) {
|
||||
} else {
|
||||
$coursegroups = [];
|
||||
|
||||
foreach ($coursegroupsobj as $group) {
|
||||
$coursegroups[] = $group->id;
|
||||
}
|
||||
|
||||
// If user's 'all groups' is a subset of the course groups, filter by all groups available to them.
|
||||
$filtergroups = $allowedgroups;
|
||||
if (!empty(array_diff($coursegroups, $allowedgroups))) {
|
||||
$filtergroups = $allowedgroups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,13 +934,21 @@ class summary_table extends table_sql {
|
||||
global $DB;
|
||||
|
||||
if (is_null($this->showwordcharcounts)) {
|
||||
$forumids = [];
|
||||
|
||||
foreach ($this->cms as $cm) {
|
||||
$forumids[] = $cm->instance;
|
||||
}
|
||||
|
||||
list($forumidin, $forumidparams) = $DB->get_in_or_equal($forumids, SQL_PARAMS_NAMED);
|
||||
|
||||
// This should be really fast.
|
||||
$sql = "SELECT 'x'
|
||||
FROM {forum_posts} fp
|
||||
JOIN {forum_discussions} fd ON fd.id = fp.discussion
|
||||
WHERE fd.forum = :forumid AND (fp.wordcount IS NULL OR fp.charcount IS NULL)";
|
||||
WHERE fd.forum {$forumidin} AND (fp.wordcount IS NULL OR fp.charcount IS NULL)";
|
||||
|
||||
if ($DB->record_exists_sql($sql, ['forumid' => $this->cm->instance])) {
|
||||
if ($DB->record_exists_sql($sql, $forumidparams)) {
|
||||
$this->showwordcharcounts = false;
|
||||
} else {
|
||||
$this->showwordcharcounts = true;
|
||||
|
@ -29,68 +29,133 @@ if (isguestuser()) {
|
||||
}
|
||||
|
||||
$courseid = required_param('courseid', PARAM_INT);
|
||||
$forumid = required_param('forumid', PARAM_INT);
|
||||
$forumid = optional_param('forumid', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', \forumreport_summary\summary_table::DEFAULT_PER_PAGE, PARAM_INT);
|
||||
$download = optional_param('download', '', PARAM_ALPHA);
|
||||
$filters = [];
|
||||
$pageurlparams = [
|
||||
'courseid' => $courseid,
|
||||
'perpage' => $perpage,
|
||||
];
|
||||
|
||||
// Establish filter values.
|
||||
$filters['forums'] = [$forumid];
|
||||
$filters['groups'] = optional_param_array('filtergroups', [], PARAM_INT);
|
||||
$filters['datefrom'] = optional_param_array('datefrom', ['enabled' => 0], PARAM_INT);
|
||||
$filters['dateto'] = optional_param_array('dateto', ['enabled' => 0], PARAM_INT);
|
||||
|
||||
$download = optional_param('download', '', PARAM_ALPHA);
|
||||
|
||||
$cm = null;
|
||||
$modinfo = get_fast_modinfo($courseid);
|
||||
$course = $modinfo->get_course();
|
||||
$courseforums = $modinfo->instances['forum'];
|
||||
$cms = [];
|
||||
|
||||
if (!isset($modinfo->instances['forum'][$forumid])) {
|
||||
throw new \moodle_exception("A valid forum ID is required to generate a summary report.");
|
||||
// Determine which forums the user has access to in the course.
|
||||
$allforumidsincourse = array_keys($courseforums);
|
||||
$forumsvisibletouser = [];
|
||||
|
||||
foreach ($courseforums as $courseforumid => $courseforum) {
|
||||
if ($courseforum->uservisible) {
|
||||
$forumsvisibletouser[$courseforumid] = $courseforum->name;
|
||||
}
|
||||
}
|
||||
|
||||
$foruminfo = $modinfo->instances['forum'][$forumid];
|
||||
$forumname = $foruminfo->name;
|
||||
$cm = $foruminfo->get_course_module_record();
|
||||
if ($forumid) {
|
||||
$filters['forums'] = [$forumid];
|
||||
|
||||
require_login($courseid, false, $cm);
|
||||
$context = \context_module::instance($cm->id);
|
||||
if (!isset($courseforums[$forumid])) {
|
||||
throw new \moodle_exception("A valid forum ID is required to generate a summary report.");
|
||||
}
|
||||
|
||||
// This capability is required to view any version of the report.
|
||||
if (!has_capability("forumreport/summary:view", $context)) {
|
||||
$foruminfo = $courseforums[$forumid];
|
||||
$title = $foruminfo->name;
|
||||
$forumcm = $foruminfo->get_course_module_record();
|
||||
$cms[] = $forumcm;
|
||||
|
||||
require_login($courseid, false, $forumcm);
|
||||
$context = \context_module::instance($forumcm->id);
|
||||
$canexport = !$download && has_capability('mod/forum:exportforum', $context);
|
||||
$redirecturl = new moodle_url("/mod/forum/view.php");
|
||||
$redirecturl->param('id', $forumid);
|
||||
redirect($redirecturl);
|
||||
$pageurlparams['forumid'] = $forumid;
|
||||
$accessallforums = false;
|
||||
} else {
|
||||
// Course level report
|
||||
require_login($courseid, false);
|
||||
|
||||
$filters['forums'] = array_keys($forumsvisibletouser);
|
||||
|
||||
// Fetch the forum cms for the course.
|
||||
foreach ($courseforums as $courseforum) {
|
||||
$cms[] = $courseforum->get_course_module_record();
|
||||
}
|
||||
|
||||
$context = \context_course::instance($courseid);
|
||||
$title = $course->fullname;
|
||||
// Export currently only supports single forum exports.
|
||||
$canexport = false;
|
||||
$redirecturl = new moodle_url("/course/view.php");
|
||||
$redirecturl->param('id', $courseid);
|
||||
|
||||
// Determine whether user has access to all forums in the course.
|
||||
$accessallforums = empty(array_diff($allforumidsincourse, $filters['forums']));
|
||||
}
|
||||
|
||||
$course = $modinfo->get_course();
|
||||
$pageurl = new moodle_url("/mod/forum/report/summary/index.php", $pageurlparams);
|
||||
|
||||
$urlparams = [
|
||||
'courseid' => $courseid,
|
||||
'forumid' => $forumid,
|
||||
'perpage' => $perpage,
|
||||
];
|
||||
$url = new moodle_url("/mod/forum/report/summary/index.php", $urlparams);
|
||||
|
||||
$PAGE->set_url($url);
|
||||
$PAGE->set_url($pageurl);
|
||||
$PAGE->set_pagelayout('report');
|
||||
$PAGE->set_title($forumname);
|
||||
$PAGE->set_title($title);
|
||||
$PAGE->set_heading($course->fullname);
|
||||
$PAGE->navbar->add(get_string('nodetitle', "forumreport_summary"));
|
||||
|
||||
// Prepare and display the report.
|
||||
$numforums = count($filters['forums']);
|
||||
$allowbulkoperations = !$download && !empty($CFG->messaging) && has_capability('moodle/course:bulkmessaging', $context);
|
||||
$canseeprivatereplies = has_capability('mod/forum:readprivatereplies', $context);
|
||||
$canexport = !$download && has_capability('mod/forum:exportforum', $context);
|
||||
$canseeprivatereplies = false;
|
||||
$hasviewall = false;
|
||||
$privatereplycapcount = 0;
|
||||
$viewallcount = 0;
|
||||
$canview = false;
|
||||
|
||||
foreach ($cms as $cm) {
|
||||
$forumcontext = \context_module::instance($cm->id);
|
||||
|
||||
// This capability is required in at least one of the given contexts to view any version of the report.
|
||||
if (has_capability("forumreport/summary:view", $forumcontext)) {
|
||||
$canview = true;
|
||||
}
|
||||
|
||||
if (has_capability('mod/forum:readprivatereplies', $forumcontext)) {
|
||||
$privatereplycapcount++;
|
||||
}
|
||||
|
||||
if (has_capability('forumreport/summary:viewall', $forumcontext)) {
|
||||
$viewallcount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$canview) {
|
||||
redirect($redirecturl);
|
||||
}
|
||||
|
||||
// Only use private replies if user has that cap in all forums in the report.
|
||||
if ($numforums === $privatereplycapcount) {
|
||||
$canseeprivatereplies = true;
|
||||
}
|
||||
|
||||
// Will only show all users if user has the cap for all forums in the report.
|
||||
if ($numforums === $viewallcount) {
|
||||
$hasviewall = true;
|
||||
}
|
||||
|
||||
// Prepare and display the report.
|
||||
$table = new \forumreport_summary\summary_table($courseid, $filters, $allowbulkoperations,
|
||||
$canseeprivatereplies, $perpage, $canexport);
|
||||
$table->baseurl = $url;
|
||||
$canseeprivatereplies, $perpage, $canexport, $accessallforums);
|
||||
$table->baseurl = $pageurl;
|
||||
|
||||
$eventparams = [
|
||||
'context' => $context,
|
||||
'other' => [
|
||||
'forumid' => $forumid,
|
||||
'hasviewall' => has_capability('forumreport/summary:viewall', $context),
|
||||
'hasviewall' => $hasviewall,
|
||||
],
|
||||
];
|
||||
|
||||
@ -101,16 +166,25 @@ if ($download) {
|
||||
\forumreport_summary\event\report_viewed::create($eventparams)->trigger();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('summarytitle', 'forumreport_summary', $forumname), 2, 'p-b-2');
|
||||
echo $OUTPUT->heading(get_string('summarytitle', 'forumreport_summary', $title), 2, 'p-b-2');
|
||||
|
||||
if (!empty($filters['groups'])) {
|
||||
\core\notification::info(get_string('viewsdisclaimer', 'forumreport_summary'));
|
||||
}
|
||||
|
||||
// Allow switching to course report (or other forum user has access to).
|
||||
$forumselectoptions = [0 => get_string('forumselectcourseoption', 'forumreport_summary')] + $forumsvisibletouser;
|
||||
$reporturl = new moodle_url("/mod/forum/report/summary/index.php");
|
||||
$reporturl->param('courseid', $courseid);
|
||||
$forumselect = new single_select($reporturl, 'forumid', $forumselectoptions, $forumid);
|
||||
$forumselect->set_label(get_string('forumselectlabel', 'forumreport_summary'));
|
||||
echo $OUTPUT->render($forumselect);
|
||||
|
||||
// Render the report filters form.
|
||||
$renderer = $PAGE->get_renderer('forumreport_summary');
|
||||
|
||||
echo $renderer->render_filters_form($cm, $url, $filters);
|
||||
unset($filters['forums']);
|
||||
echo $renderer->render_filters_form($cms, $pageurl, $filters);
|
||||
$table->show_download_buttons_at(array(TABLE_P_BOTTOM));
|
||||
echo $renderer->render_summary_table($table);
|
||||
echo $OUTPUT->footer();
|
||||
|
@ -38,6 +38,8 @@ $string['filter:groupsbuttonlabel'] = 'Open the groups filter';
|
||||
$string['filter:groupsname'] = 'Groups';
|
||||
$string['filter:groupscountall'] = 'Groups (all)';
|
||||
$string['filter:groupscountnumber'] = 'Groups ({$a})';
|
||||
$string['forumselectlabel'] = 'Forum selected';
|
||||
$string['forumselectcourseoption'] = 'All forums in course';
|
||||
$string['latestpost'] = 'Most recent post';
|
||||
$string['exportposts'] = 'Export posts';
|
||||
$string['exportpostslabel'] = 'Export posts for {$a}';
|
||||
@ -48,6 +50,6 @@ $string['privacy:metadata'] = 'The Forum summary report plugin does not store an
|
||||
$string['replycount'] = 'Number of replies posted';
|
||||
$string['summary:viewall'] = 'Access summary report data for each user within a given forum or forums';
|
||||
$string['summary:view'] = 'Access summary report within a given forum or forums';
|
||||
$string['summarytitle'] = 'Summary report - {$a}';
|
||||
$string['summarytitle'] = 'Forum summary report - {$a}';
|
||||
$string['viewsdisclaimer'] = 'Number of views column is not filtered by group';
|
||||
$string['wordcount'] = 'Word count';
|
||||
|
@ -37,13 +37,13 @@ class forumreport_summary_renderer extends plugin_renderer_base {
|
||||
/**
|
||||
* Render the filters available for the forum summary report.
|
||||
*
|
||||
* @param stdClass $cm The course module object.
|
||||
* @param array $cms Array of course module objects.
|
||||
* @param moodle_url $actionurl The form action URL.
|
||||
* @param array $filters Optional array of currently applied filter values.
|
||||
* @return string The filter form HTML.
|
||||
*/
|
||||
public function render_filters_form(stdClass $cm, moodle_url $actionurl, array $filters = []): string {
|
||||
$renderable = new \forumreport_summary\output\filters($cm, $actionurl, $filters);
|
||||
public function render_filters_form(array $cms, moodle_url $actionurl, array $filters = []): string {
|
||||
$renderable = new \forumreport_summary\output\filters($cms, $actionurl, $filters);
|
||||
$templatecontext = $renderable->export_for_template($this);
|
||||
|
||||
return $this->render_from_template('forumreport_summary/filters', $templatecontext);
|
||||
|
@ -61,7 +61,7 @@
|
||||
}
|
||||
}}
|
||||
|
||||
<div class="pb-4" data-report-id="{{uniqid}}">
|
||||
<div class="pb-4 pt-4" data-report-id="{{uniqid}}">
|
||||
<form id="filtersform" name="filtersform" method="post" action="{{actionurl}}">
|
||||
<input type="hidden" name="submitted" value="true">
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user