Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
/user/ -> renderer.php (source)

Differences Between: [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   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   * Provides user rendering functionality such as printing private files tree and displaying a search utility
  19   *
  20   * @package    core_user
  21   * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Provides user rendering functionality such as printing private files tree and displaying a search utility
  29   * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
  30   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   */
  32  class core_user_renderer extends plugin_renderer_base {
  33  
  34      /**
  35       * Prints user search utility that can search user by first initial of firstname and/or first initial of lastname
  36       * Prints a header with a title and the number of users found within that subset
  37       * @param string $url the url to return to, complete with any parameters needed for the return
  38       * @param string $firstinitial the first initial of the firstname
  39       * @param string $lastinitial the first initial of the lastname
  40       * @param int $usercount the amount of users meeting the search criteria
  41       * @param int $totalcount the amount of users of the set/subset being searched
  42       * @param string $heading heading of the subset being searched, default is All Participants
  43       * @return string html output
  44       */
  45      public function user_search($url, $firstinitial, $lastinitial, $usercount, $totalcount, $heading = null) {
  46  
  47          if ($firstinitial !== 'all') {
  48              set_user_preference('ifirst', $firstinitial);
  49          }
  50          if ($lastinitial !== 'all') {
  51              set_user_preference('ilast', $lastinitial);
  52          }
  53  
  54          if (!isset($heading)) {
  55              $heading = get_string('allparticipants');
  56          }
  57  
  58          $content = html_writer::start_tag('form', array('action' => new moodle_url($url)));
  59          $content .= html_writer::start_tag('div');
  60  
  61          // Search utility heading.
  62          $content .= $this->output->heading($heading.get_string('labelsep', 'langconfig').$usercount.'/'.$totalcount, 3);
  63  
  64          // Initials bar.
  65          $prefixfirst = 'sifirst';
  66          $prefixlast = 'silast';
  67          $content .= $this->output->initials_bar($firstinitial, 'firstinitial', get_string('firstname'), $prefixfirst, $url);
  68          $content .= $this->output->initials_bar($lastinitial, 'lastinitial', get_string('lastname'), $prefixlast, $url);
  69  
  70          $content .= html_writer::end_tag('div');
  71          $content .= html_writer::tag('div', '&nbsp;');
  72          $content .= html_writer::end_tag('form');
  73  
  74          return $content;
  75      }
  76  
  77      /**
  78       * Displays the list of tagged users
  79       *
  80       * @param array $userlist
  81       * @param bool $exclusivemode if set to true it means that no other entities tagged with this tag
  82       *             are displayed on the page and the per-page limit may be bigger
  83       * @return string
  84       */
  85      public function user_list($userlist, $exclusivemode) {
  86          $tagfeed = new core_tag\output\tagfeed();
  87          foreach ($userlist as $user) {
  88              $userpicture = $this->output->user_picture($user, array('size' => $exclusivemode ? 100 : 35));
  89              $fullname = fullname($user);
  90              if (user_can_view_profile($user)) {
  91                  $profilelink = new moodle_url('/user/view.php', array('id' => $user->id));
  92                  $fullname = html_writer::link($profilelink, $fullname);
  93              }
  94              $tagfeed->add($userpicture, $fullname);
  95          }
  96  
  97          $items = $tagfeed->export_for_template($this->output);
  98  
  99          if ($exclusivemode) {
 100              $output = '<div><ul class="inline-list">';
 101              foreach ($items['items'] as $item) {
 102                  $output .= '<li><div class="user-box">'. $item['img'] . $item['heading'] ."</div></li>\n";
 103              }
 104              $output .= "</ul></div>\n";
 105              return $output;
 106          }
 107  
 108          return $this->output->render_from_template('core_tag/tagfeed', $items);
 109      }
 110  
 111      /**
 112       * Renders the unified filter element for the course participants page.
 113       * @deprecated since Moodle 3.9 MDL-68612 - Please use participants_filter() instead.
 114       *
 115       * @param stdClass $course The course object.
 116       * @param context $context The context object.
 117       * @param array $filtersapplied Array of currently applied filters.
 118       * @param string|moodle_url $baseurl The url with params needed to call up this page.
 119       * @return bool|string
 120       */
 121      public function unified_filter($course, $context, $filtersapplied, $baseurl = null) {
 122          global $CFG, $DB, $USER;
 123  
 124          debugging('core_user_renderer->unified_filter() is deprecated. Please use participants_filter() instead.', DEBUG_DEVELOPER);
 125  
 126          require_once($CFG->dirroot . '/enrol/locallib.php');
 127          require_once($CFG->dirroot . '/lib/grouplib.php');
 128          $manager = new course_enrolment_manager($this->page, $course);
 129  
 130          $filteroptions = [];
 131  
 132          // Filter options for role.
 133          $roleseditable = has_capability('moodle/role:assign', $context);
 134          $roles = get_viewable_roles($context);
 135          if ($roleseditable) {
 136              $roles += get_assignable_roles($context, ROLENAME_ALIAS);
 137          }
 138  
 139          $criteria = get_string('role');
 140          $roleoptions = $this->format_filter_option(USER_FILTER_ROLE, $criteria, -1, get_string('noroles', 'role'));
 141          foreach ($roles as $id => $role) {
 142              $roleoptions += $this->format_filter_option(USER_FILTER_ROLE, $criteria, $id, $role);
 143          }
 144          $filteroptions += $roleoptions;
 145  
 146          // Filter options for groups, if available.
 147          if (has_capability('moodle/site:accessallgroups', $context) || $course->groupmode != SEPARATEGROUPS) {
 148              // List all groups if the user can access all groups, or we are in visible group mode or no groups mode.
 149              $groups = $manager->get_all_groups();
 150              if (!empty($groups)) {
 151                  // Add 'No group' option, to enable filtering users without any group.
 152                  $nogroup[USERSWITHOUTGROUP] = (object)['name' => get_string('nogroup', 'group')];
 153                  $groups = $nogroup + $groups;
 154              }
 155          } else {
 156              // Otherwise, just list the groups the user belongs to.
 157              $groups = groups_get_all_groups($course->id, $USER->id);
 158          }
 159          $criteria = get_string('group');
 160          $groupoptions = [];
 161          foreach ($groups as $id => $group) {
 162              $groupoptions += $this->format_filter_option(USER_FILTER_GROUP, $criteria, $id, $group->name);
 163          }
 164          $filteroptions += $groupoptions;
 165  
 166          $canreviewenrol = has_capability('moodle/course:enrolreview', $context);
 167  
 168          // Filter options for status.
 169          if ($canreviewenrol) {
 170              $criteria = get_string('status');
 171              // Add statuses.
 172              $filteroptions += $this->format_filter_option(USER_FILTER_STATUS, $criteria, ENROL_USER_ACTIVE, get_string('active'));
 173              $filteroptions += $this->format_filter_option(USER_FILTER_STATUS, $criteria, ENROL_USER_SUSPENDED,
 174                  get_string('inactive'));
 175          }
 176  
 177          // Filter options for enrolment methods.
 178          if ($canreviewenrol && $enrolmentmethods = $manager->get_enrolment_instance_names(true)) {
 179              $criteria = get_string('enrolmentinstances', 'enrol');
 180              $enroloptions = [];
 181              foreach ($enrolmentmethods as $id => $enrolname) {
 182                  $enroloptions += $this->format_filter_option(USER_FILTER_ENROLMENT, $criteria, $id, $enrolname);
 183              }
 184              $filteroptions += $enroloptions;
 185          }
 186  
 187          $isfrontpage = ($course->id == SITEID);
 188  
 189          // Get the list of fields we have to hide.
 190          $hiddenfields = array();
 191          if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
 192              $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
 193          }
 194          $haslastaccess = !isset($hiddenfields['lastaccess']);
 195          // Filter options for last access.
 196          if ($haslastaccess) {
 197              // Get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far.
 198              // We need to make it diferently for normal courses and site course.
 199              if (!$isfrontpage) {
 200                  $params = ['courseid' => $course->id, 'timeaccess' => 0];
 201                  $select = 'courseid = :courseid AND timeaccess != :timeaccess';
 202                  $minlastaccess = $DB->get_field_select('user_lastaccess', 'MIN(timeaccess)', $select, $params);
 203                  $lastaccess0exists = $DB->record_exists('user_lastaccess', $params);
 204              } else {
 205                  $params = ['lastaccess' => 0];
 206                  $select = 'lastaccess != :lastaccess';
 207                  $minlastaccess = $DB->get_field_select('user', 'MIN(lastaccess)', $select, $params);
 208                  $lastaccess0exists = $DB->record_exists('user', $params);
 209              }
 210              $now = usergetmidnight(time());
 211              $timeoptions = [];
 212              $criteria = get_string('usersnoaccesssince');
 213  
 214              // Days.
 215              for ($i = 1; $i < 7; $i++) {
 216                  $timestamp = strtotime('-' . $i . ' days', $now);
 217                  if ($timestamp < $minlastaccess) {
 218                      break;
 219                  }
 220                  $value = get_string('numdays', 'moodle', $i);
 221                  $timeoptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $value);
 222              }
 223              // Weeks.
 224              for ($i = 1; $i < 10; $i++) {
 225                  $timestamp = strtotime('-'.$i.' weeks', $now);
 226                  if ($timestamp < $minlastaccess) {
 227                      break;
 228                  }
 229                  $value = get_string('numweeks', 'moodle', $i);
 230                  $timeoptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $value);
 231              }
 232              // Months.
 233              for ($i = 2; $i < 12; $i++) {
 234                  $timestamp = strtotime('-'.$i.' months', $now);
 235                  if ($timestamp < $minlastaccess) {
 236                      break;
 237                  }
 238                  $value = get_string('nummonths', 'moodle', $i);
 239                  $timeoptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $value);
 240              }
 241              // Try a year.
 242              $timestamp = strtotime('-1 year', $now);
 243              if ($timestamp >= $minlastaccess) {
 244                  $value = get_string('numyear', 'moodle', 1);
 245                  $timeoptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $value);
 246              }
 247              if (!empty($lastaccess0exists)) {
 248                  $value = get_string('never', 'moodle');
 249                  $timeoptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $value);
 250              }
 251              if (count($timeoptions) > 1) {
 252                  $filteroptions += $timeoptions;
 253              }
 254          }
 255  
 256          // Add missing applied filters to the filter options.
 257          $filteroptions = $this->handle_missing_applied_filters($filtersapplied, $filteroptions);
 258  
 259          $indexpage = new \core_user\output\unified_filter($filteroptions, $filtersapplied, $baseurl);
 260          $context = $indexpage->export_for_template($this->output);
 261  
 262          return $this->output->render_from_template('core_user/unified_filter', $context);
 263      }
 264  
 265      /**
 266       * Render the data required for the participants filter on the course participants page.
 267       *
 268       * @param context $context The context of the course being displayed
 269       * @param string $tableregionid The table to be updated by this filter
 270       * @return string
 271       */
 272      public function participants_filter(context $context, string $tableregionid): string {
 273          $renderable = new \core_user\output\participants_filter($context, $tableregionid);
 274          $templatecontext = $renderable->export_for_template($this->output);
 275  
 276          return $this->output->render_from_template('core_user/participantsfilter', $templatecontext);
 277      }
 278  
 279      /**
 280       * Returns a formatted filter option.
 281       *
 282       * @param int $filtertype The filter type (e.g. status, role, group, enrolment, last access).
 283       * @param string $criteria The string label of the filter type.
 284       * @param int $value The value for the filter option.
 285       * @param string $label The string representation of the filter option's value.
 286       * @return array The formatted option with the ['filtertype:value' => 'criteria: label'] format.
 287       */
 288      protected function format_filter_option($filtertype, $criteria, $value, $label) {
 289          $optionlabel = get_string('filteroption', 'moodle', (object)['criteria' => $criteria, 'value' => $label]);
 290          $optionvalue = "$filtertype:$value";
 291          return [$optionvalue => $optionlabel];
 292      }
 293  
 294      /**
 295       * Handles cases when after reloading the applied filters are missing in the filter options.
 296       *
 297       * @param array $filtersapplied The applied filters.
 298       * @param array $filteroptions The filter options.
 299       * @return array The formatted options with the ['filtertype:value' => 'criteria: label'] format.
 300       */
 301      private function handle_missing_applied_filters($filtersapplied, $filteroptions) {
 302          global $DB;
 303  
 304          foreach ($filtersapplied as $filter) {
 305              if (!array_key_exists($filter, $filteroptions)) {
 306                  $filtervalue = explode(':', $filter);
 307                  if (count($filtervalue) !== 2) {
 308                      continue;
 309                  }
 310                  $key = $filtervalue[0];
 311                  $value = $filtervalue[1];
 312  
 313                  switch($key) {
 314                      case USER_FILTER_LAST_ACCESS:
 315                          $now = usergetmidnight(time());
 316                          $criteria = get_string('usersnoaccesssince');
 317                          // Days.
 318                          for ($i = 1; $i < 7; $i++) {
 319                              $timestamp = strtotime('-' . $i . ' days', $now);
 320                              if ($timestamp < $value) {
 321                                  break;
 322                              }
 323                              $val = get_string('numdays', 'moodle', $i);
 324                              $filteroptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $val);
 325                          }
 326                          // Weeks.
 327                          for ($i = 1; $i < 10; $i++) {
 328                              $timestamp = strtotime('-'.$i.' weeks', $now);
 329                              if ($timestamp < $value) {
 330                                  break;
 331                              }
 332                              $val = get_string('numweeks', 'moodle', $i);
 333                              $filteroptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $val);
 334                          }
 335                          // Months.
 336                          for ($i = 2; $i < 12; $i++) {
 337                              $timestamp = strtotime('-'.$i.' months', $now);
 338                              if ($timestamp < $value) {
 339                                  break;
 340                              }
 341                              $val = get_string('nummonths', 'moodle', $i);
 342                              $filteroptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $val);
 343                          }
 344                          // Try a year.
 345                          $timestamp = strtotime('-1 year', $now);
 346                          if ($timestamp >= $value) {
 347                              $val = get_string('numyear', 'moodle', 1);
 348                              $filteroptions += $this->format_filter_option(USER_FILTER_LAST_ACCESS, $criteria, $timestamp, $val);
 349                          }
 350                          break;
 351                      case USER_FILTER_ROLE:
 352                          $criteria = get_string('role');
 353                          if ($role = $DB->get_record('role', array('id' => $value))) {
 354                              $role = role_get_name($role);
 355                              $filteroptions += $this->format_filter_option(USER_FILTER_ROLE, $criteria, $value, $role);
 356                          }
 357                          break;
 358                  }
 359              }
 360          }
 361          return $filteroptions;
 362      }
 363  }