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 activity title.
  19   *
  20   * This class is usually rendered inside the cmname inplace editable.
  21   *
  22   * @package   core_courseformat
  23   * @copyright 2020 Ferran Recio <ferran@moodle.com>
  24   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  namespace core_courseformat\output\local\content\cm;
  28  
  29  use cm_info;
  30  use core\output\inplace_editable;
  31  use core\output\named_templatable;
  32  use core_courseformat\base as course_format;
  33  use core_text;
  34  use lang_string;
  35  use renderable;
  36  use section_info;
  37  use stdClass;
  38  use external_api;
  39  use context_module;
  40  
  41  /**
  42   * Base class to render a course module title inside a course format.
  43   *
  44   * @package   core_courseformat
  45   * @copyright 2020 Ferran Recio <ferran@moodle.com>
  46   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  47   */
  48  class title extends inplace_editable implements named_templatable, renderable {
  49  
  50      /** @var course_format the course format */
  51      protected $format;
  52  
  53      /** @var section_info the section object */
  54      private $section;
  55  
  56      /** @var cm_info the course module instance */
  57      protected $mod;
  58  
  59      /** @var array optional display options */
  60      protected $displayoptions;
  61  
  62      /** @var editable if the title is editable */
  63      protected $editable;
  64  
  65      /** @var displaytemplate the default display template */
  66      protected $displaytemplate = 'core_courseformat/local/content/cm/title';
  67  
  68      /**
  69       * Constructor.
  70       *
  71       * @param course_format $format the course format
  72       * @param section_info $section the section info
  73       * @param cm_info $mod the course module ionfo
  74       * @param array $displayoptions optional extra display options
  75       * @param bool|null $editable force editable value
  76       */
  77      public function __construct(
  78          course_format $format,
  79          section_info $section,
  80          cm_info $mod,
  81          array $displayoptions = [],
  82          ?bool $editable = null
  83      ) {
  84          $this->format = $format;
  85          $this->section = $section;
  86          $this->mod = $mod;
  87  
  88          // Usually displayoptions are loaded in the main cm output. However when the user uses the inplace editor
  89          // the cmname output does not calculate the css classes.
  90          $this->displayoptions = $this->load_display_options($displayoptions);
  91  
  92          if ($editable === null) {
  93              $editable = $format->show_editor();
  94          }
  95          $this->editable = $editable;
  96  
  97          // Setup inplace editable.
  98          parent::__construct(
  99              'core_course',
 100              'activityname',
 101              $mod->id,
 102              $this->editable,
 103              $mod->name,
 104              $mod->name,
 105              new lang_string('edittitle'),
 106              new lang_string('newactivityname', '', $mod->get_formatted_name())
 107          );
 108      }
 109  
 110      /**
 111       * Get the name of the template to use for this templatable.
 112       *
 113       * @param \renderer_base $renderer The renderer requesting the template name
 114       * @return string
 115       */
 116      public function get_template_name(\renderer_base $renderer): string {
 117          return 'core/inplace_editable';
 118      }
 119  
 120      /**
 121       * Export this data so it can be used as the context for a mustache template.
 122       *
 123       * @param \renderer_base $output typically, the renderer that's calling this function
 124       * @return stdClass data context for a mustache template
 125       */
 126      public function export_for_template(\renderer_base $output): array {
 127  
 128          // Inplace editable uses pre-rendered elements and does not allow line beaks in the UI value.
 129          $this->displayvalue = str_replace("\n", "", $this->get_title_displayvalue());
 130  
 131          if (trim($this->displayvalue) == '') {
 132              $this->editable = false;
 133          }
 134          return parent::export_for_template($output);
 135      }
 136  
 137      /**
 138       * Return the title template data to be used inside the inplace editable.
 139       *
 140       */
 141      protected function get_title_displayvalue (): string {
 142          global $PAGE;
 143  
 144          // Inplace editable uses core renderer by default. However, course elements require
 145          // the format specific renderer.
 146          $courseoutput = $this->format->get_renderer($PAGE);
 147  
 148          $mod = $this->mod;
 149  
 150          $data = (object)[
 151              'url' => $mod->url,
 152              'instancename' => $mod->get_formatted_name(),
 153              'uservisible' => $mod->uservisible,
 154              'linkclasses' => $this->displayoptions['linkclasses'],
 155          ];
 156  
 157          // File type after name, for alphabetic lists (screen reader).
 158          if (strpos(
 159              core_text::strtolower($data->instancename),
 160              core_text::strtolower($mod->modfullname)
 161          ) === false) {
 162              $data->altname = get_accesshide(' ' . $mod->modfullname);
 163          }
 164  
 165          // Get on-click attribute value if specified and decode the onclick - it
 166          // has already been encoded for display (puke).
 167          $data->onclick = htmlspecialchars_decode($mod->onclick, ENT_QUOTES);
 168  
 169          return $courseoutput->render_from_template(
 170              $this->displaytemplate,
 171              $data
 172          );
 173      }
 174  
 175      /**
 176       * Load the required display options if not present already.
 177       *
 178       * In most cases, display options are provided as a param when creating the
 179       * object. However, inplace_editable and some blocks does not know all of them as it is
 180       * called in a webservice and we need to ensure it is calculated.
 181       *
 182       * @param array $displayoptions the provided dispaly options
 183       * @return array the full display options list
 184       */
 185      protected function load_display_options(array $displayoptions): array {
 186          $format = $this->format;
 187          $mod = $this->mod;
 188  
 189          if (
 190              isset($displayoptions['linkclasses']) &&
 191              isset($displayoptions['textclasses']) &&
 192              isset($displayoptions['onclick'])
 193          ) {
 194              return $displayoptions;
 195          }
 196  
 197          $cmclass = $format->get_output_classname('content\\cm');
 198          $cmoutput = new $cmclass(
 199              $format,
 200              $this->section,
 201              $mod,
 202              $displayoptions
 203          );
 204          $displayoptions['linkclasses'] = $cmoutput->get_link_classes();
 205          $displayoptions['textclasses'] = $cmoutput->get_text_classes();
 206          $displayoptions['onclick'] = $cmoutput->get_onclick_code();
 207          return $displayoptions;
 208      }
 209  
 210      /**
 211       * Updates course module name.
 212       *
 213       * This method is used mainly by inplace_editable webservice.
 214       *
 215       * @param int $itemid course module id
 216       * @param string $newvalue new name
 217       * @return static
 218       */
 219      public static function update($itemid, $newvalue) {
 220          $context = context_module::instance($itemid);
 221          // Check access.
 222          external_api::validate_context($context);
 223          require_capability('moodle/course:manageactivities', $context);
 224  
 225          // Trim module name and Update value.
 226          set_coursemodule_name($itemid, trim($newvalue));
 227          $coursemodulerecord = get_coursemodule_from_id('', $itemid, 0, false, MUST_EXIST);
 228          // Return instance.
 229          $modinfo = get_fast_modinfo($coursemodulerecord->course);
 230          $cm = $modinfo->get_cm($itemid);
 231          $section = $modinfo->get_section_info($cm->sectionnum);
 232  
 233          $format = course_get_format($cm->course);
 234          return new static($format, $section, $cm, [], true);
 235      }
 236  }