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.

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   * Forum summary report filters renderable.
  19   *
  20   * @package    forumreport_summary
  21   * @copyright  2019 Michael Hawkins <michaelh@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace forumreport_summary\output;
  26  
  27  use moodle_url;
  28  use renderable;
  29  use renderer_base;
  30  use stdClass;
  31  use templatable;
  32  use forumreport_summary;
  33  
  34  defined('MOODLE_INTERNAL') || die();
  35  
  36  /**
  37   * Forum summary report filters renderable.
  38   *
  39   * @copyright  2019 Michael Hawkins <michaelh@moodle.com>
  40   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  class filters implements renderable, templatable {
  43  
  44      /**
  45       * Course modules the report relates to.
  46       * Array of stdClass objects
  47       *
  48       * @var array $cms
  49       */
  50      protected $cms;
  51  
  52      /**
  53       * Course ID where the report is being generated.
  54       *
  55       * @var int $courseid
  56       */
  57      protected $courseid;
  58  
  59      /**
  60       * Moodle URL used as the form action on the generate button.
  61       *
  62       * @var moodle_url $actionurl
  63       */
  64      protected $actionurl;
  65  
  66      /**
  67       * Details of groups available for filtering.
  68       * Stored in the format groupid => groupname.
  69       *
  70       * @var array $groupsavailable
  71       */
  72      protected $groupsavailable = [];
  73  
  74      /**
  75       * IDs of groups selected for filtering.
  76       *
  77       * @var array $groupsselected
  78       */
  79      protected $groupsselected = [];
  80  
  81      /**
  82       * IDs of discussions required for export links.
  83       * If a subset of groups available are selected, this will include the discussion IDs
  84       * within that group in the forum.
  85       * If all groups are selected, or no groups mode is enabled, this will be empty as
  86       * no discussion filtering is required in the export.
  87       *
  88       * @var array $discussionids
  89       */
  90      protected $discussionids = [];
  91  
  92      /**
  93       * HTML for dates filter.
  94       *
  95       * @var array $datesdata
  96       */
  97      protected $datesdata = [];
  98  
  99      /**
 100       * Text to display on the dates filter button.
 101       *
 102       * @var string $datesbuttontext
 103       */
 104      protected $datesbuttontext;
 105  
 106      /**
 107       * Builds renderable filter data.
 108       *
 109       * @param stdClass $course The course object.
 110       * @param array $cms Array of course module objects.
 111       * @param moodle_url $actionurl The form action URL.
 112       * @param array $filterdata (optional) Associative array of data that has been set on available filters, if any,
 113       *                                     in the format filtertype => [values]
 114       */
 115      public function __construct(stdClass $course, array $cms, moodle_url $actionurl, array $filterdata = []) {
 116          $this->cms = $cms;
 117          $this->courseid = $course->id;
 118          $this->actionurl = $actionurl;
 119  
 120          // Prepare groups filter data.
 121          $groupsdata = $filterdata['groups'] ?? [];
 122          $this->prepare_groups_data($groupsdata);
 123  
 124          // Prepare dates filter data.
 125          $datefromdata = $filterdata['datefrom'] ?? [];
 126          $datetodata = $filterdata['dateto'] ?? [];
 127          $this->prepare_dates_data($datefromdata, $datetodata);
 128      }
 129  
 130      /**
 131       * Prepares groups data and sets relevant property values.
 132       *
 133       * @param array $groupsdata Groups selected for filtering.
 134       * @return void.
 135       */
 136      protected function prepare_groups_data(array $groupsdata): void {
 137          global $DB, $USER;
 138  
 139          $groupsavailable = [];
 140          $allowedgroupsobj = [];
 141  
 142          $usergroups = groups_get_all_groups($this->courseid, $USER->id);
 143          $coursegroups = groups_get_all_groups($this->courseid);
 144          $forumids = [];
 145          $allgroups = false;
 146          $hasgroups = false;
 147  
 148          // Check if any forum gives the user access to all groups and no groups.
 149          foreach ($this->cms as $cm) {
 150              $forumids[] = $cm->instance;
 151  
 152              // Only need to check for all groups access if not confirmed by a previous check.
 153              if (!$allgroups) {
 154                  $groupmode = groups_get_activity_groupmode($cm);
 155  
 156                  // If no groups mode enabled on the forum, nothing to prepare.
 157                  if (!in_array($groupmode, [VISIBLEGROUPS, SEPARATEGROUPS])) {
 158                      continue;
 159                  }
 160  
 161                  $hasgroups = true;
 162  
 163                  // Fetch for the current cm's forum.
 164                  $context = \context_module::instance($cm->id);
 165                  $aag = has_capability('moodle/site:accessallgroups', $context);
 166  
 167                  if ($groupmode == VISIBLEGROUPS || $aag) {
 168                      $allgroups = true;
 169                  }
 170              }
 171          }
 172  
 173          // If no groups mode enabled, nothing to prepare.
 174          if (!$hasgroups) {
 175              return;
 176          }
 177  
 178          // Any groups, and no groups.
 179          if ($allgroups) {
 180              $nogroups = new stdClass();
 181              $nogroups->id = -1;
 182              $nogroups->name = get_string('groupsnone');
 183  
 184              $allowedgroupsobj = $coursegroups + [$nogroups];
 185          } else {
 186              $allowedgroupsobj = $usergroups;
 187          }
 188  
 189          foreach ($allowedgroupsobj as $group) {
 190              $groupsavailable[$group->id] = $group->name;
 191          }
 192  
 193          // Set valid groups selected.
 194          $groupsselected = array_intersect($groupsdata, array_keys($groupsavailable));
 195  
 196          // Overwrite groups properties.
 197          $this->groupsavailable = $groupsavailable;
 198          $this->groupsselected = $groupsselected;
 199  
 200          $groupsselectedcount = count($groupsselected);
 201          if ($groupsselectedcount > 0 && $groupsselectedcount < count($groupsavailable)) {
 202              list($forumidin, $forumidparams) = $DB->get_in_or_equal($forumids, SQL_PARAMS_NAMED);
 203              list($groupidin, $groupidparams) = $DB->get_in_or_equal($groupsselected, SQL_PARAMS_NAMED);
 204  
 205              $discussionswhere = "course = :courseid AND forum {$forumidin} AND groupid {$groupidin}";
 206              $discussionsparams = ['courseid' => $this->courseid];
 207              $discussionsparams += $forumidparams + $groupidparams;
 208  
 209              $discussionids = $DB->get_fieldset_select('forum_discussions', 'DISTINCT id', $discussionswhere, $discussionsparams);
 210  
 211              foreach ($discussionids as $discussionid) {
 212                  $this->discussionids[] = ['discid' => $discussionid];
 213              }
 214          }
 215      }
 216  
 217      /**
 218       * Prepares from date, to date and button text.
 219       * Empty data will default to a disabled filter with today's date.
 220       *
 221       * @param array $datefromdata From date selected for filtering, and whether the filter is enabled.
 222       * @param array $datetodata To date selected for filtering, and whether the filter is enabled.
 223       * @return void.
 224       */
 225      private function prepare_dates_data(array $datefromdata, array $datetodata): void {
 226          $timezone = \core_date::get_user_timezone_object();
 227          $calendartype = \core_calendar\type_factory::get_calendar_instance();
 228          $timestamptoday = time();
 229          $datetoday  = $calendartype->timestamp_to_date_array($timestamptoday, $timezone);
 230  
 231          // Prepare date/enabled data.
 232          if (empty($datefromdata['enabled'])) {
 233              $fromdate = $datetoday;
 234              $fromtimestamp = $timestamptoday;
 235              $fromenabled = false;
 236          } else {
 237              $fromdate = $calendartype->timestamp_to_date_array($datefromdata['timestamp'], $timezone);
 238              $fromtimestamp = $datefromdata['timestamp'];
 239              $fromenabled = true;
 240          }
 241  
 242          if (empty($datetodata['enabled'])) {
 243              $todate = $datetoday;
 244              $totimestamp = $timestamptoday;
 245              $toenabled = false;
 246          } else {
 247              $todate = $calendartype->timestamp_to_date_array($datetodata['timestamp'], $timezone);
 248              $totimestamp = $datetodata['timestamp'];
 249              $toenabled = true;
 250          }
 251  
 252          $this->datesdata = [
 253              'from' => [
 254                  'day'       => $fromdate['mday'],
 255                  'month'     => $fromdate['mon'],
 256                  'year'      => $fromdate['year'],
 257                  'timestamp' => $fromtimestamp,
 258                  'enabled'   => $fromenabled,
 259              ],
 260              'to' => [
 261                  'day'       => $todate['mday'],
 262                  'month'     => $todate['mon'],
 263                  'year'      => $todate['year'],
 264                  'timestamp' => $totimestamp,
 265                  'enabled'   => $toenabled,
 266              ],
 267          ];
 268  
 269          // Prepare button string data.
 270          $displayformat = get_string('strftimedatemonthabbr', 'langconfig');
 271          $fromdatestring = $calendartype->timestamp_to_date_string($fromtimestamp, $displayformat, $timezone, true, true);
 272          $todatestring = $calendartype->timestamp_to_date_string($totimestamp, $displayformat, $timezone, true, true);
 273  
 274          if ($fromenabled && $toenabled) {
 275              $datestrings = [
 276                  'datefrom' => $fromdatestring,
 277                  'dateto'   => $todatestring,
 278              ];
 279              $this->datesbuttontext = get_string('filter:datesfromto', 'forumreport_summary', $datestrings);
 280          } else if ($fromenabled) {
 281              $this->datesbuttontext = get_string('filter:datesfrom', 'forumreport_summary', $fromdatestring);
 282          } else if ($toenabled) {
 283              $this->datesbuttontext = get_string('filter:datesto', 'forumreport_summary', $todatestring);
 284          } else {
 285              $this->datesbuttontext = get_string('filter:datesname', 'forumreport_summary');
 286          }
 287      }
 288  
 289      /**
 290       * Export data for use as the context of a mustache template.
 291       *
 292       * @param renderer_base $renderer The renderer to be used to display report filters.
 293       * @return array Data in a format compatible with a mustache template.
 294       */
 295      public function export_for_template(renderer_base $renderer): stdClass {
 296          $output = new stdClass();
 297  
 298          // Set formaction URL.
 299          $output->actionurl = $this->actionurl->out(false);
 300  
 301          // Set groups filter data.
 302          if (!empty($this->groupsavailable)) {
 303              $output->hasgroups = true;
 304  
 305              $groupscount = count($this->groupsselected);
 306  
 307              if (count($this->groupsavailable) <= $groupscount) {
 308                  $output->filtergroupsname = get_string('filter:groupscountall', 'forumreport_summary');
 309              } else if (!empty($this->groupsselected)) {
 310                  $output->filtergroupsname = get_string('filter:groupscountnumber', 'forumreport_summary', $groupscount);
 311              } else {
 312                  $output->filtergroupsname = get_string('filter:groupsname', 'forumreport_summary');
 313              }
 314  
 315              // Set groups filter.
 316              $groupsdata = [];
 317  
 318              foreach ($this->groupsavailable as $groupid => $groupname) {
 319                  $groupsdata[] = [
 320                      'groupid' => $groupid,
 321                      'groupname' => $groupname,
 322                      'checked' => in_array($groupid, $this->groupsselected),
 323                  ];
 324              }
 325  
 326              $output->filtergroups = $groupsdata;
 327          } else {
 328              $output->hasgroups = false;
 329          }
 330  
 331          // Set discussion IDs for use by export links (always included, as it will be empty if not required).
 332          $output->discussionids = $this->discussionids;
 333  
 334          // Set date button and generate dates popover mform.
 335          $datesformdata = [];
 336  
 337          if ($this->datesdata['from']['enabled']) {
 338              $datesformdata['filterdatefrompopover'] = $this->datesdata['from'];
 339          }
 340  
 341          if ($this->datesdata['to']['enabled']) {
 342              $datesformdata['filterdatetopopover'] = $this->datesdata['to'];
 343          }
 344  
 345          $output->filterdatesname = $this->datesbuttontext;
 346          $datesform = new forumreport_summary\form\dates_filter_form();
 347          $datesform->set_data($datesformdata);
 348          $output->filterdatesform = $datesform->render();
 349  
 350           // Set dates filter data within filters form.
 351          $disableddate = [
 352              'day' => '',
 353              'month' => '',
 354              'year' => '',
 355              'enabled' => '0',
 356          ];
 357          $datefromdata = ['type' => 'from'] + ($this->datesdata['from']['enabled'] ? $this->datesdata['from'] : $disableddate);
 358          $datetodata = ['type' => 'to'] + ($this->datesdata['to']['enabled'] ? $this->datesdata['to'] : $disableddate);
 359          $output->filterdatesdata = [$datefromdata, $datetodata];
 360  
 361          return $output;
 362      }
 363  }