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.
   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   * Contains the default activity availability information.
  19   *
  20   * @package   core_courseformat
  21   * @copyright 2023 Ferran Recio <ferran@moodle.com>
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core_courseformat\output\local\content\cm;
  26  
  27  use cm_info;
  28  use core_courseformat\base as course_format;
  29  use core_courseformat\output\local\courseformat_named_templatable;
  30  use core\output\choicelist;
  31  use core\output\local\dropdown\status;
  32  use core\output\named_templatable;
  33  use pix_icon;
  34  use renderable;
  35  use section_info;
  36  use stdClass;
  37  
  38  /**
  39   * Base class to render a course module availability inside a course format.
  40   *
  41   * @package   core_courseformat
  42   * @copyright 2020 Ferran Recio <ferran@moodle.com>
  43   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  44   */
  45  class visibility implements named_templatable, renderable {
  46      use courseformat_named_templatable;
  47  
  48      /** @var course_format the course format */
  49      protected $format;
  50  
  51      /** @var section_info the section object */
  52      protected $section;
  53  
  54      /** @var cm_info the course module instance */
  55      protected $mod;
  56  
  57      /**
  58       * Constructor.
  59       * @param course_format $format the course format
  60       * @param section_info $section the section info
  61       * @param cm_info $mod the course module ionfo
  62       */
  63      public function __construct(course_format $format, section_info $section, cm_info $mod) {
  64          $this->format = $format;
  65          $this->section = $section;
  66          $this->mod = $mod;
  67      }
  68  
  69      /**
  70       * Export this data so it can be used as the context for a mustache template.
  71       *
  72       * @param \renderer_base $output typically, the renderer that's calling this function
  73       * @return stdClass|null data context for a mustache template
  74       */
  75      public function export_for_template(\renderer_base $output): ?stdClass {
  76          if (!$this->show_visibility()) {
  77              return null;
  78          }
  79          $format = $this->format;
  80          // In rare legacy cases, the section could be stealth (orphaned) but they are not editable.
  81          if (!$format->show_editor()) {
  82              return $this->build_static_data($output);
  83          } else {
  84              return $this->build_editor_data($output);
  85          }
  86      }
  87  
  88      /**
  89       * Check if the visibility is displayed.
  90       * @return bool
  91       */
  92      protected function show_visibility(): bool {
  93          return !$this->mod->visible || $this->mod->is_stealth();
  94      }
  95  
  96      /**
  97       * Get the icon for the section visibility.
  98       * @param string $selected the visibility selected value
  99       * @return pix_icon
 100       */
 101      protected function get_icon(string $selected): pix_icon {
 102          if ($selected === 'hide') {
 103              return new pix_icon('t/show', '');
 104          } else if ($selected === 'stealth') {
 105              return new pix_icon('t/stealth', '');
 106          } else {
 107              return new pix_icon('t/hide', '');
 108          }
 109      }
 110  
 111      /**
 112       * Build the data for the editor.
 113       * @param \renderer_base $output typically, the renderer that's calling this function
 114       * @return stdClass|null data context for a mustache template
 115       */
 116      public function build_editor_data(\renderer_base $output): ?stdClass {
 117          $choice = $this->get_choice_list();
 118          return $this->get_dropdown_data($output, $choice);
 119      }
 120  
 121      /**
 122       * Build the data for the interactive dropdown.
 123       * @param \renderer_base $output
 124       * @param choicelist $choice the choice list
 125       * @return stdClass
 126       */
 127      protected function get_dropdown_data(
 128          \renderer_base $output,
 129          choicelist $choice,
 130      ): stdClass {
 131          $badgetext = $output->sr_text(get_string('availability'));
 132  
 133          if (!$this->mod->visible) {
 134              $badgetext .= get_string('hiddenfromstudents');
 135              $icon = $this->get_icon('hide');
 136          } else if ($this->mod->is_stealth()) {
 137              $badgetext .= get_string('hiddenoncoursepage');
 138              $icon = $this->get_icon('stealth');
 139          } else {
 140              $badgetext .= get_string("availability_show", 'core_courseformat');
 141              $icon = $this->get_icon('show');
 142          }
 143          $dropdown = new status(
 144              $output->render($icon) . ' ' . $badgetext,
 145              $choice,
 146              ['dialogwidth' => status::WIDTH['big']],
 147          );
 148          return (object) [
 149              'isInteractive' => true,
 150              'dropwdown' => $dropdown->export_for_template($output),
 151          ];
 152      }
 153  
 154      /**
 155       * Get the availability choice list.
 156       * @return choicelist
 157       */
 158      public function get_choice_list(): choicelist {
 159          $choice = $this->create_choice_list();
 160          $choice->set_selected_value($this->get_selected_choice_value());
 161          return $choice;
 162      }
 163  
 164      /**
 165       * Get the selected choice value depending on the course, section and stealth settings.
 166       * @return string
 167       */
 168      protected function get_selected_choice_value(): string {
 169          if (!$this->mod->visible) {
 170              return 'hide';
 171          }
 172          if (!$this->mod->is_stealth()) {
 173              return 'show';
 174          }
 175          if (!$this->section->visible) {
 176              // All visible activities in a hidden sections are considered stealth
 177              // but they don't use the stealth attribute for it. It is just implicit.
 178              return 'show';
 179          }
 180          return 'stealth';
 181      }
 182  
 183      /**
 184       * Create a choice list for the dropdown.
 185       * @return choicelist the choice list
 186       */
 187      protected function create_choice_list(): choicelist {
 188          global $CFG;
 189  
 190          $choice = new choicelist();
 191          if ($this->section->visible || $this->mod->has_view()) {
 192              $label = $this->section->visible ? 'show' : 'stealth';
 193              $choice->add_option(
 194                  'show',
 195                  get_string("availability_{$label}", 'core_courseformat'),
 196                  $this->get_option_data($label, 'cmShow')
 197              );
 198          }
 199          $choice->add_option(
 200              'hide',
 201              get_string('availability_hide', 'core_courseformat'),
 202              $this->get_option_data('hide', 'cmHide')
 203          );
 204  
 205          if ($CFG->allowstealth && $this->format->allow_stealth_module_visibility($this->mod, $this->section)) {
 206              $choice->add_option(
 207                  'stealth',
 208                  get_string('availability_stealth', 'core_courseformat'),
 209                  $this->get_option_data('stealth', 'cmStealth')
 210              );
 211          }
 212          return $choice;
 213      }
 214  
 215      /**
 216       * Get the data for the option.
 217       * @param string $name the name of the option
 218       * @param string $action the state action of the option
 219       * @return array
 220       */
 221      private function get_option_data(string $name, string $action): array {
 222          return [
 223              'description' => get_string("availability_{$name}_help", 'core_courseformat'),
 224              'icon' => $this->get_icon($name),
 225              // Non-ajax behat is not smart enough to discrimante hidden links
 226              // so we need to keep providing the non-ajax links.
 227              'url' => $this->format->get_non_ajax_cm_action_url($action, $this->mod),
 228              'extras' => [
 229                  'data-id' => $this->mod->id,
 230                  'data-action' => $action,
 231              ]
 232          ];
 233      }
 234  
 235      /**
 236       * Build the static badges data.
 237       * @param \renderer_base $output typically, the renderer that's calling this function
 238       * @return stdClass|null data context for a mustache template
 239       */
 240      public function build_static_data(\renderer_base $output): ?stdClass {
 241          $data = (object) [
 242              'isInteractive' => false,
 243          ];
 244  
 245          if (!$this->mod->visible) {
 246              $data->modhiddenfromstudents = true;
 247          } else if ($this->mod->is_stealth()) {
 248              $data->modstealth = true;
 249          }
 250          return $data;
 251      }
 252  }