Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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  declare(strict_types=1);
  18  
  19  namespace core_reportbuilder\form;
  20  
  21  use context;
  22  use core_user;
  23  use html_writer;
  24  use moodle_url;
  25  use core\output\notification;
  26  use core_form\dynamic_form;
  27  use core_reportbuilder\manager;
  28  use core_reportbuilder\permission;
  29  use core_reportbuilder\local\helpers\audience;
  30  use core_reportbuilder\local\helpers\schedule as helper;
  31  use core_reportbuilder\local\models\schedule as model;
  32  use core_reportbuilder\local\report\base;
  33  
  34  /**
  35   * Schedule form
  36   *
  37   * @package     core_reportbuilder
  38   * @copyright   2021 Paul Holden <paulh@moodle.com>
  39   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  class schedule extends dynamic_form {
  42  
  43      /**
  44       * Return instance of the system report using the filter form
  45       *
  46       * @return base
  47       */
  48      private function get_report(): base {
  49          $reportid = $this->optional_param('reportid', 0, PARAM_INT);
  50          return manager::get_report_from_id($reportid);
  51      }
  52  
  53      /**
  54       * Return the context for the form, it should be that of the report itself
  55       *
  56       * @return context
  57       */
  58      protected function get_context_for_dynamic_submission(): context {
  59          return $this->get_report()->get_context();
  60      }
  61  
  62      /**
  63       * Ensure current user is able to use this form
  64       *
  65       * A {@see \core_reportbuilder\report_access_exception} will be thrown if they can't
  66       */
  67      protected function check_access_for_dynamic_submission(): void {
  68          $persistent = $this->get_report()->get_report_persistent();
  69          permission::require_can_edit_report($persistent);
  70      }
  71  
  72      /**
  73       * Form definition
  74       */
  75      protected function definition() {
  76          global $OUTPUT;
  77  
  78          $mform = $this->_form;
  79  
  80          $mform->addElement('hidden', 'reportid');
  81          $mform->setType('reportid', PARAM_INT);
  82  
  83          $mform->addElement('hidden', 'id');
  84          $mform->setType('id', PARAM_INT);
  85  
  86          // General fields.
  87          $mform->addElement('header', 'headergeneral', get_string('general'));
  88  
  89          $mform->addElement('text', 'name', get_string('name'));
  90          $mform->setType('name', PARAM_TEXT);
  91          $mform->addRule('name', null, 'required', null, 'client');
  92          $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255);
  93  
  94          $mform->addElement('select', 'format', get_string('format'), helper::get_format_options());
  95          $mform->setType('format', PARAM_PLUGIN);
  96  
  97          $mform->addElement('date_time_selector', 'timescheduled', get_string('startingfrom'), ['optional' => false]);
  98          $mform->setType('timescheduled', PARAM_INT);
  99  
 100          $mform->addElement('select', 'recurrence', get_string('recurrence', 'core_reportbuilder'),
 101              helper::get_recurrence_options());
 102          $mform->setType('recurrence', PARAM_INT);
 103  
 104          // View report data as.
 105          $context = $this->get_context_for_dynamic_submission();
 106          if (has_capability('moodle/reportbuilder:scheduleviewas', $context)) {
 107              $mform->addElement('select', 'userviewas', get_string('scheduleviewas', 'core_reportbuilder'),
 108                  helper::get_viewas_options());
 109              $mform->setType('userviewas', PARAM_INT);
 110  
 111              $options = [
 112                  'ajax' => 'core_user/form_user_selector',
 113                  'multiple' => false,
 114                  'valuehtmlcallback' => function($userid) use ($context): string {
 115                      $user = core_user::get_user($userid);
 116                      return fullname($user, has_capability('moodle/site:viewfullnames', $context));
 117                  }
 118              ];
 119              $mform->addElement('autocomplete', 'user', get_string('user'), [], $options)->setHiddenLabel(true);
 120              $mform->hideIf('user', 'userviewas', 'neq', model::REPORT_VIEWAS_USER);
 121          }
 122  
 123          // Audience fields.
 124          $mform->addElement('header', 'headeraudience', get_string('audience', 'core_reportbuilder'));
 125          $mform->setExpanded('headeraudience', true);
 126  
 127          $audiences = audience::get_base_records($this->optional_param('reportid', 0, PARAM_INT));
 128          if (empty($audiences)) {
 129              $notification = new notification(get_string('noaudiences', 'core_reportbuilder'), notification::NOTIFY_INFO, false);
 130              $mform->addElement('static', 'noaudiences', '', $OUTPUT->render($notification));
 131          }
 132  
 133          $audiencecheckboxes = [];
 134          foreach ($audiences as $audience) {
 135              $persistent = $audience->get_persistent();
 136  
 137              // Check for a custom name, otherwise fall back to default.
 138              if ('' === $audiencelabel = $persistent->get_formatted_heading($context)) {
 139                  $audiencelabel = get_string('audiencelabel', 'core_reportbuilder', (object) [
 140                      'name' => $audience->get_name(),
 141                      'description' => $audience->get_description(),
 142                  ]);
 143              }
 144  
 145              $audiencecheckboxes[] = $mform->createElement('checkbox', $persistent->get('id'), $audiencelabel);
 146          }
 147  
 148          $mform->addElement('group', 'audiences', '', $audiencecheckboxes, html_writer::div('', 'w-100 mb-2'));
 149  
 150          // Message fields.
 151          $mform->addElement('header', 'headermessage', get_string('messagecontent', 'core_reportbuilder'));
 152  
 153          $mform->addElement('text', 'subject', get_string('messagesubject', 'core_reportbuilder'));
 154          $mform->setType('subject', PARAM_TEXT);
 155          $mform->addRule('subject', null, 'required', null, 'client');
 156          $mform->addRule('subject', get_string('maximumchars', '', 255), 'maxlength', 255);
 157  
 158          $mform->addElement('editor', 'message', get_string('messagebody', 'core_reportbuilder'), null, ['autosave' => false]);
 159          $mform->setType('message', PARAM_RAW);
 160          $mform->addRule('message', null, 'required', null, 'client');
 161  
 162          // Advanced.
 163          $mform->addElement('header', 'headeradvanced', get_string('advanced'));
 164  
 165          $mform->addElement('select', 'reportempty', get_string('scheduleempty', 'core_reportbuilder'),
 166              helper::get_report_empty_options());
 167          $mform->setType('reportempty', PARAM_INT);
 168      }
 169  
 170      /**
 171       * Load form data if we are editing an existing schedule
 172       */
 173      public function set_data_for_dynamic_submission(): void {
 174          $reportid = $this->optional_param('reportid', 0, PARAM_INT);
 175          $scheduleid = $this->optional_param('id', 0, PARAM_INT);
 176  
 177          if ($scheduleid > 0) {
 178              $schedule = model::get_record(['id' => $scheduleid, 'reportid' => $reportid]);
 179  
 180              $data = (array) $schedule->to_record();
 181  
 182              // Pre-process some of the form fields.
 183              if (!in_array($data['userviewas'], [model::REPORT_VIEWAS_CREATOR, model::REPORT_VIEWAS_RECIPIENT])) {
 184                  $data['user'] = $data['userviewas'];
 185                  $data['userviewas'] = model::REPORT_VIEWAS_USER;
 186              }
 187  
 188              $audiences = json_decode($data['audiences']);
 189              $data['audiences'] = array_fill_keys($audiences, 1);
 190  
 191              $data['message'] = [
 192                  'text' => $data['message'],
 193                  'format' => $data['messageformat'],
 194              ];
 195  
 196              $this->set_data($data);
 197          } else {
 198              $this->set_data(['reportid' => $reportid]);
 199          }
 200      }
 201  
 202      /**
 203       * Form validation
 204       *
 205       * @param array $data
 206       * @param array $files
 207       * @return array
 208       */
 209      public function validation($data, $files): array {
 210          $errors = parent::validation($data, $files);
 211  
 212          if (trim($data['name']) === '') {
 213              $errors['name'] = get_string('required');
 214          }
 215  
 216          // Make sure specific user was selected, if required.
 217          if (array_key_exists('userviewas', $data) &&
 218                  (int) $data['userviewas'] === model::REPORT_VIEWAS_USER && empty($data['user'])) {
 219  
 220              $errors['user'] = get_string('required');
 221          }
 222  
 223          if (empty($data['audiences'])) {
 224              $errors['audiences'] = get_string('required');
 225          }
 226  
 227          return $errors;
 228      }
 229  
 230      /**
 231       * Process form submission
 232       */
 233      public function process_dynamic_submission(): void {
 234          $data = $this->get_data();
 235  
 236          // Pre-process some of the form fields.
 237          if (property_exists($data, 'userviewas') && (int) $data->userviewas === model::REPORT_VIEWAS_USER) {
 238              $data->userviewas = (int) $data->user;
 239          }
 240  
 241          $data->audiences = json_encode(array_keys($data->audiences));
 242          ['text' => $data->message, 'format' => $data->messageformat] = $data->message;
 243  
 244          if ($data->id) {
 245              helper::update_schedule($data);
 246          } else {
 247              helper::create_schedule($data);
 248          }
 249      }
 250  
 251      /**
 252       * URL of the page using this form
 253       *
 254       * @return moodle_url
 255       */
 256      protected function get_page_url_for_dynamic_submission(): moodle_url {
 257          return new moodle_url('/reportbuilder/edit.php', ['id' => $this->optional_param('reportid', 0, PARAM_INT)], 'schedules');
 258      }
 259  }