Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Class for rendering user filters on the course participants page.
 *
 * @package    core_user
 * @copyright  2020 Michael Hawkins <michaelh@moodle.com>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
namespace core_user\output;

< use context_course;
use core_user\fields;
< use renderable;
use renderer_base; use stdClass;
< use templatable;
/** * Class for rendering user filters on the course participants page. * * @copyright 2020 Michael Hawkins <michaelh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */
< class participants_filter implements renderable, templatable { < < /** @var context_course $context The context where the filters are being rendered. */ < protected $context; < < /** @var string $tableregionid The table to be updated by this filter */ < protected $tableregionid; < < /** @var stdClass $course The course shown */ < protected $course; < < /** < * Participants filter constructor. < * < * @param context_course $context The context where the filters are being rendered. < * @param string $tableregionid The table to be updated by this filter < */ < public function __construct(context_course $context, string $tableregionid) { < $this->context = $context; < $this->tableregionid = $tableregionid; < < $this->course = get_course($context->instanceid); < }
> class participants_filter extends \core\output\datafilter {
/** * Get data for all filter types. * * @return array */ protected function get_filtertypes(): array { $filtertypes = []; $filtertypes[] = $this->get_keyword_filter(); if ($filtertype = $this->get_enrolmentstatus_filter()) { $filtertypes[] = $filtertype; } if ($filtertype = $this->get_roles_filter()) { $filtertypes[] = $filtertype; } if ($filtertype = $this->get_enrolments_filter()) { $filtertypes[] = $filtertype; } if ($filtertype = $this->get_groups_filter()) { $filtertypes[] = $filtertype; } if ($filtertype = $this->get_accesssince_filter()) { $filtertypes[] = $filtertype; } if ($filtertype = $this->get_country_filter()) { $filtertypes[] = $filtertype; } return $filtertypes; } /** * Get data for the enrolment status filter. * * @return stdClass|null */ protected function get_enrolmentstatus_filter(): ?stdClass { if (!has_capability('moodle/course:enrolreview', $this->context)) { return null; } return $this->get_filter_object( 'status', get_string('participationstatus', 'core_enrol'), false, true, null, [ (object) [ 'value' => ENROL_USER_ACTIVE, 'title' => get_string('active'), ], (object) [ 'value' => ENROL_USER_SUSPENDED, 'title' => get_string('inactive'), ], ] ); } /** * Get data for the roles filter. * * @return stdClass|null */ protected function get_roles_filter(): ?stdClass { $roles = []; $roles += [-1 => get_string('noroles', 'role')]; $roles += get_viewable_roles($this->context, null, ROLENAME_BOTH); if (has_capability('moodle/role:assign', $this->context)) { $roles += get_assignable_roles($this->context, ROLENAME_BOTH); } return $this->get_filter_object( 'roles', get_string('roles', 'core_role'), false, true, null, array_map(function($id, $title) { return (object) [ 'value' => $id, 'title' => $title, ]; }, array_keys($roles), array_values($roles)) ); } /** * Get data for the roles filter. * * @return stdClass|null */ protected function get_enrolments_filter(): ?stdClass { if (!has_capability('moodle/course:enrolreview', $this->context)) { return null; } if ($this->course->id == SITEID) { // No enrolment methods for the site. return null; } $instances = enrol_get_instances($this->course->id, true); $plugins = enrol_get_plugins(false); return $this->get_filter_object( 'enrolments', get_string('enrolmentinstances', 'core_enrol'), false, true, null, array_filter(array_map(function($instance) use ($plugins): ?stdClass { if (!array_key_exists($instance->enrol, $plugins)) { return null; } return (object) [ 'value' => $instance->id, 'title' => $plugins[$instance->enrol]->get_instance_name($instance), ]; }, array_values($instances))) ); } /** * Get data for the groups filter. * * @return stdClass|null */ protected function get_groups_filter(): ?stdClass { global $USER; // Filter options for groups, if available. $seeallgroups = has_capability('moodle/site:accessallgroups', $this->context); $seeallgroups = $seeallgroups || ($this->course->groupmode != SEPARATEGROUPS); if ($seeallgroups) { $groups = []; $groups += [USERSWITHOUTGROUP => (object) [ 'id' => USERSWITHOUTGROUP, 'name' => get_string('nogroup', 'group'), ]]; $groups += groups_get_all_groups($this->course->id); } else { // Otherwise, just list the groups the user belongs to. $groups = groups_get_all_groups($this->course->id, $USER->id); } // Return no data if no groups found (which includes if the only value is 'No group'). if (empty($groups) || (count($groups) === 1 && array_key_exists(-1, $groups))) { return null; } return $this->get_filter_object( 'groups', get_string('groups', 'core_group'), false, true, null, array_map(function($group) { return (object) [ 'value' => $group->id, 'title' => format_string($group->name, true, ['context' => $this->context]), ]; }, array_values($groups)) ); } /** * Get data for the accesssince filter. * * @return stdClass|null */ protected function get_accesssince_filter(): ?stdClass { global $CFG, $DB; $hiddenfields = []; if (!has_capability('moodle/course:viewhiddenuserfields', $this->context)) { $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); } if (array_key_exists('lastaccess', $hiddenfields)) { return null; } // Get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far. // We need to make it diferently for normal courses and site course. if (!$this->course->id == SITEID) { // Regular course. $params = [ 'courseid' => $this->course->id, 'timeaccess' => 0, ]; $select = 'courseid = :courseid AND timeaccess != :timeaccess'; $minlastaccess = $DB->get_field_select('user_lastaccess', 'MIN(timeaccess)', $select, $params); $lastaccess0exists = $DB->record_exists('user_lastaccess', $params); } else { // Front page. $params = ['lastaccess' => 0]; $select = 'lastaccess != :lastaccess'; $minlastaccess = $DB->get_field_select('user', 'MIN(lastaccess)', $select, $params); $lastaccess0exists = $DB->record_exists('user', $params); } $now = usergetmidnight(time()); $timeoptions = []; $criteria = get_string('usersnoaccesssince'); $getoptions = function(int $count, string $singletype, string $type) use ($now, $minlastaccess): array { $values = []; for ($i = 1; $i <= $count; $i++) { $timestamp = strtotime("-{$i} {$type}", $now); if ($timestamp < $minlastaccess) { break; } if ($i === 1) { $title = get_string("num{$singletype}", 'moodle', $i); } else { $title = get_string("num{$type}", 'moodle', $i); } $values[] = [ 'value' => $timestamp, 'title' => $title, ]; } return $values; }; $values = array_merge( $getoptions(6, 'day', 'days'), $getoptions(10, 'week', 'weeks'), $getoptions(11, 'month', 'months'), $getoptions(1, 'year', 'years') ); if ($lastaccess0exists) { $values[] = [ 'value' => time(), 'title' => get_string('never', 'moodle'), ]; } if (count($values) <= 1) { // Nothing to show. return null; } return $this->get_filter_object( 'accesssince', get_string('usersnoaccesssince'), false, false, null, $values ); } /** * Get data for the country filter * * @return stdClass|null */ protected function get_country_filter(): ?stdClass { $extrauserfields = fields::get_identity_fields($this->context, false); if (array_search('country', $extrauserfields) === false) { return null; } $countries = get_string_manager()->get_list_of_countries(true); return $this->get_filter_object( 'country', get_string('country'), false, true,
< 'core_user/local/participantsfilter/filtertypes/country',
> 'core/datafilter/filtertypes/country',
array_map(function(string $code, string $name): stdClass { return (object) [ 'value' => $code, 'title' => $name, ]; }, array_keys($countries), array_values($countries)) ); } /** * Get data for the keywords filter. * * @return stdClass|null */ protected function get_keyword_filter(): ?stdClass { return $this->get_filter_object( 'keywords', get_string('filterbykeyword', 'core_user'), true, true,
< 'core_user/local/participantsfilter/filtertypes/keyword',
> 'core/datafilter/filtertypes/keyword',
[], true ); } /** * Export the renderer data in a mustache template friendly format. * * @param renderer_base $output Unused. * @return stdClass Data in a format compatible with a mustache template. */ public function export_for_template(renderer_base $output): stdClass { return (object) [ 'tableregionid' => $this->tableregionid, 'courseid' => $this->context->instanceid, 'filtertypes' => $this->get_filtertypes(), 'rownumber' => 1, ]; return $data;
< } < < /** < * Get a standardised filter object. < * < * @param string $name < * @param string $title < * @param bool $custom < * @param bool $multiple < * @param string|null $filterclass < * @param array $values < * @param bool $allowempty < * @return stdClass|null < */ < protected function get_filter_object( < string $name, < string $title, < bool $custom, < bool $multiple, < ?string $filterclass, < array $values, < bool $allowempty = false < ): ?stdClass { < < if (!$allowempty && empty($values)) { < // Do not show empty filters. < return null; < } < < return (object) [ < 'name' => $name, < 'title' => $title, < 'allowcustom' => $custom, < 'allowmultiple' => $multiple, < 'filtertypeclass' => $filterclass, < 'values' => $values, < ];
} }