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.

Differences Between: [Versions 401 and 402] [Versions 401 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   * Contains the default section course format output class.
  19   *
  20   * @package   core_courseformat
  21   * @copyright 2020 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;
  26  
  27  use context_course;
  28  use core\output\named_templatable;
  29  use core_courseformat\base as course_format;
  30  use core_courseformat\output\local\courseformat_named_templatable;
  31  use renderable;
  32  use renderer_base;
  33  use section_info;
  34  use stdClass;
  35  
  36  /**
  37   * Base class to render a course section.
  38   *
  39   * @package   core_courseformat
  40   * @copyright 2020 Ferran Recio <ferran@moodle.com>
  41   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class section implements named_templatable, renderable {
  44      use courseformat_named_templatable;
  45  
  46      /** @var course_format the course format */
  47      protected $format;
  48  
  49      /** @var section_info the section info */
  50      protected $section;
  51  
  52      /** @var section header output class */
  53      protected $headerclass;
  54  
  55      /** @var cm list output class */
  56      protected $cmlistclass;
  57  
  58      /** @var section summary output class */
  59      protected $summaryclass;
  60  
  61      /** @var activities summary output class */
  62      protected $cmsummaryclass;
  63  
  64      /** @var section control menu output class */
  65      protected $controlclass;
  66  
  67      /** @var section availability output class */
  68      protected $availabilityclass;
  69  
  70      /** @var optional move here output class */
  71      protected $movehereclass;
  72  
  73      /** @var bool if the title is hidden for some reason */
  74      protected $hidetitle = false;
  75  
  76      /** @var bool if the title is hidden for some reason */
  77      protected $hidecontrols = false;
  78  
  79      /** @var bool if the section is considered stealth */
  80      protected $isstealth = false;
  81  
  82  
  83      /**
  84       * Constructor.
  85       *
  86       * @param course_format $format the course format
  87       * @param section_info $section the section info
  88       */
  89      public function __construct(course_format $format, section_info $section) {
  90          $this->format = $format;
  91          $this->section = $section;
  92  
  93          if ($section->section > $format->get_last_section_number()) {
  94              $this->isstealth = true;
  95          }
  96  
  97          // Load output classes names from format.
  98          $this->headerclass = $format->get_output_classname('content\\section\\header');
  99          $this->cmlistclass = $format->get_output_classname('content\\section\\cmlist');
 100          $this->summaryclass = $format->get_output_classname('content\\section\\summary');
 101          $this->cmsummaryclass = $format->get_output_classname('content\\section\\cmsummary');
 102          $this->controlmenuclass = $format->get_output_classname('content\\section\\controlmenu');
 103          $this->availabilityclass = $format->get_output_classname('content\\section\\availability');
 104          $this->movehereclass = $format->get_output_classname('content\\section\\movehere');
 105      }
 106  
 107      /**
 108       * Hide the section title.
 109       *
 110       * This is used on blocks or in the home page where an isolated section is displayed.
 111       */
 112      public function hide_title(): void {
 113          $this->hidetitle = true;
 114      }
 115  
 116      /**
 117       * Hide the section controls.
 118       *
 119       * This is used on blocks or in the home page where an isolated section is displayed.
 120       */
 121      public function hide_controls(): void {
 122          $this->hidecontrols = true;
 123      }
 124  
 125      /**
 126       * Export this data so it can be used as the context for a mustache template.
 127       *
 128       * @param renderer_base $output typically, the renderer that's calling this function
 129       * @return stdClass data context for a mustache template
 130       */
 131      public function export_for_template(renderer_base $output): stdClass {
 132          global $USER, $PAGE;
 133  
 134          $format = $this->format;
 135          $course = $format->get_course();
 136          $section = $this->section;
 137  
 138          $summary = new $this->summaryclass($format, $section);
 139  
 140          $data = (object)[
 141              'num' => $section->section ?? '0',
 142              'id' => $section->id,
 143              'sectionreturnid' => $format->get_section_number(),
 144              'insertafter' => false,
 145              'summary' => $summary->export_for_template($output),
 146              'highlightedlabel' => $format->get_section_highlighted_name(),
 147              'sitehome' => $course->id == SITEID,
 148              'editing' => $PAGE->user_is_editing()
 149          ];
 150  
 151          $haspartials = [];
 152          $haspartials['availability'] = $this->add_availability_data($data, $output);
 153          $haspartials['visibility'] = $this->add_visibility_data($data, $output);
 154          $haspartials['editor'] = $this->add_editor_data($data, $output);
 155          $haspartials['header'] = $this->add_header_data($data, $output);
 156          $haspartials['cm'] = $this->add_cm_data($data, $output);
 157          $this->add_format_data($data, $haspartials, $output);
 158  
 159          return $data;
 160      }
 161  
 162      /**
 163       * Add the section header to the data structure.
 164       *
 165       * @param stdClass $data the current cm data reference
 166       * @param renderer_base $output typically, the renderer that's calling this function
 167       * @return bool if the cm has name data
 168       */
 169      protected function add_header_data(stdClass &$data, renderer_base $output): bool {
 170          if (!empty($this->hidetitle)) {
 171              return false;
 172          }
 173  
 174          $section = $this->section;
 175          $format = $this->format;
 176  
 177          $header = new $this->headerclass($format, $section);
 178          $headerdata = $header->export_for_template($output);
 179  
 180          // When a section is displayed alone the title goes over the section, not inside it.
 181          if ($section->section != 0 && $section->section == $format->get_section_number()) {
 182              $data->singleheader = $headerdata;
 183          } else {
 184              $data->header = $headerdata;
 185          }
 186          return true;
 187      }
 188  
 189      /**
 190       * Add the section cm list to the data structure.
 191       *
 192       * @param stdClass $data the current cm data reference
 193       * @param renderer_base $output typically, the renderer that's calling this function
 194       * @return bool if the cm has name data
 195       */
 196      protected function add_cm_data(stdClass &$data, renderer_base $output): bool {
 197          $result = false;
 198  
 199          $section = $this->section;
 200          $format = $this->format;
 201  
 202          $showsummary = ($section->section != 0 &&
 203              $section->section != $format->get_section_number() &&
 204              $format->get_course_display() == COURSE_DISPLAY_MULTIPAGE &&
 205              !$format->show_editor()
 206          );
 207  
 208          $showcmlist = $section->uservisible;
 209  
 210          // Add activities summary if necessary.
 211          if ($showsummary) {
 212              $cmsummary = new $this->cmsummaryclass($format, $section);
 213              $data->cmsummary = $cmsummary->export_for_template($output);
 214              $data->onlysummary = true;
 215              $result = true;
 216  
 217              if (!$format->is_section_current($section)) {
 218                  // In multipage, only the current section (and the section zero) has elements.
 219                  $showcmlist = false;
 220              }
 221          }
 222          // Add the cm list.
 223          if ($showcmlist) {
 224              $cmlist = new $this->cmlistclass($format, $section);
 225              $data->cmlist = $cmlist->export_for_template($output);
 226              $result = true;
 227          }
 228          return $result;
 229      }
 230  
 231      /**
 232       * Add the section availability to the data structure.
 233       *
 234       * @param stdClass $data the current cm data reference
 235       * @param renderer_base $output typically, the renderer that's calling this function
 236       * @return bool if the cm has name data
 237       */
 238      protected function add_availability_data(stdClass &$data, renderer_base $output): bool {
 239          $availability = new $this->availabilityclass($this->format, $this->section);
 240          $data->availability = $availability->export_for_template($output);
 241          $data->restrictionlock = !empty($this->section->availableinfo);
 242          $data->hasavailability = $availability->has_availability($output);
 243          return true;
 244      }
 245  
 246      /**
 247       * Add the section vibility information to the data structure.
 248       *
 249       * @param stdClass $data the current cm data reference
 250       * @param renderer_base $output typically, the renderer that's calling this function
 251       * @return bool if the cm has name data
 252       */
 253      protected function add_visibility_data(stdClass &$data, renderer_base $output): bool {
 254          global $USER;
 255          $result = false;
 256          $course = $this->format->get_course();
 257          $context = context_course::instance($course->id);
 258          // Check if it is a stealth sections (orphaned).
 259          if ($this->isstealth) {
 260              $data->isstealth = true;
 261              $data->ishidden = true;
 262              $result = true;
 263          }
 264          if (!$this->section->visible) {
 265              $data->ishidden = true;
 266              $data->notavailable = true;
 267              if (has_capability('moodle/course:viewhiddensections', $context, $USER)) {
 268                  $data->hiddenfromstudents = true;
 269                  $data->notavailable = false;
 270                  $result = true;
 271              }
 272          }
 273          return $result;
 274      }
 275  
 276      /**
 277       * Add the section editor attributes to the data structure.
 278       *
 279       * @param stdClass $data the current cm data reference
 280       * @param renderer_base $output typically, the renderer that's calling this function
 281       * @return bool if the cm has name data
 282       */
 283      protected function add_editor_data(stdClass &$data, renderer_base $output): bool {
 284          if (!$this->format->show_editor()) {
 285              return false;
 286          }
 287  
 288          $course = $this->format->get_course();
 289          if (empty($this->hidecontrols)) {
 290              $controlmenu = new $this->controlmenuclass($this->format, $this->section);
 291              $data->controlmenu = $controlmenu->export_for_template($output);
 292          }
 293          if (!$this->isstealth) {
 294              $data->cmcontrols = $output->course_section_add_cm_control(
 295                  $course,
 296                  $this->section->section,
 297                  $this->format->get_section_number()
 298              );
 299          }
 300          return true;
 301      }
 302  
 303      /**
 304       * Add the section format attributes to the data structure.
 305       *
 306       * @param stdClass $data the current cm data reference
 307       * @param bool[] $haspartials the result of loading partial data elements
 308       * @param renderer_base $output typically, the renderer that's calling this function
 309       * @return bool if the cm has name data
 310       */
 311      protected function add_format_data(stdClass &$data, array $haspartials, renderer_base $output): bool {
 312          $section = $this->section;
 313          $format = $this->format;
 314  
 315          $data->iscoursedisplaymultipage = ($format->get_course_display() == COURSE_DISPLAY_MULTIPAGE);
 316  
 317          if ($data->num === 0 && !$data->iscoursedisplaymultipage) {
 318              $data->collapsemenu = true;
 319          }
 320  
 321          $data->contentcollapsed = false;
 322          $preferences = $format->get_sections_preferences();
 323          if (isset($preferences[$section->id])) {
 324              $sectionpreferences = $preferences[$section->id];
 325              if (!empty($sectionpreferences->contentcollapsed)) {
 326                  $data->contentcollapsed = true;
 327              }
 328          }
 329  
 330          if ($format->is_section_current($section)) {
 331              $data->iscurrent = true;
 332              $data->currentlink = get_accesshide(
 333                  get_string('currentsection', 'format_' . $format->get_format())
 334              );
 335          }
 336          return true;
 337      }
 338  }