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  namespace core_course\output;
  18  
  19  use cm_info;
  20  use core_availability\info;
  21  use core_completion\cm_completion_details;
  22  use core_user;
  23  use core_user\fields;
  24  use renderable;
  25  use renderer_base;
  26  use stdClass;
  27  use templatable;
  28  
  29  /**
  30   * The activity completion renderable class.
  31   *
  32   * @package    core_course
  33   * @copyright  2023 Mikel Martín <mikel@moodle.com>
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class activity_completion implements renderable, templatable {
  37  
  38      /**
  39       * Constructor.
  40       *
  41       * @param cm_info $cminfo The course module information.
  42       * @param cm_completion_details $cmcompletion The course module information.
  43       */
  44      public function __construct(
  45          protected cm_info $cminfo,
  46          protected cm_completion_details $cmcompletion
  47      ) {
  48      }
  49  
  50      /**
  51       * Export this data so it can be used as the context for a mustache template.
  52       *
  53       * @param renderer_base $output Renderer base.
  54       * @return stdClass
  55       */
  56      public function export_for_template(renderer_base $output): stdClass {
  57          global $CFG;
  58  
  59          $overallcompletion = $this->cmcompletion->get_overall_completion();
  60          $isoverallcomplete = $this->cmcompletion->is_overall_complete();
  61          $overrideby = $this->get_overrideby();
  62          $course = $this->cminfo->get_course();
  63  
  64          // Whether the completion of this activity controls the availability of other activities/sections in the course.
  65          // An activity with manual completion tracking which is used to enable access to other activities/sections in
  66          // the course needs to refresh the page after having its completion state toggled. This withavailability flag will enable
  67          // this functionality on the course homepage. Otherwise, the completion toggling will just happen normally via ajax.
  68          if ($this->cmcompletion->has_completion() && $this->cmcompletion->is_manual()) {
  69              $withavailability = !empty($CFG->enableavailability) && info::completion_value_used($course, $this->cminfo->id);
  70          }
  71  
  72          return (object) [
  73              'cmid' => $this->cminfo->id,
  74              'activityname' => $this->cminfo->get_formatted_name(),
  75              'uservisible' => $this->cminfo->uservisible,
  76              'hascompletion' => $this->cmcompletion->has_completion(),
  77              'isautomatic' => $this->cmcompletion->is_automatic(),
  78              'ismanual' => $this->cmcompletion->is_manual(),
  79              'showmanualcompletion' => $this->cmcompletion->show_manual_completion(),
  80              'istrackeduser' => $this->cmcompletion->is_tracked_user(),
  81              'overallcomplete' => $isoverallcomplete,
  82              'overallincomplete' => !$isoverallcomplete,
  83              'withavailability' => $withavailability ?? false,
  84              'overrideby' => $overrideby,
  85              'completiondetails' => $this->get_completion_details($overrideby),
  86              'accessibledescription' => $this->get_accessible_description($overrideby, $overallcompletion),
  87          ];
  88      }
  89  
  90      /**
  91       * Returns the name of the user overriding the completion condition, if available.
  92       *
  93       * @return string
  94       */
  95      private function get_overrideby(): string {
  96          $overrideby = $this->cmcompletion->overridden_by();
  97          if (!empty($overrideby)) {
  98              $userfields = fields::for_name();
  99              $overridebyrecord = core_user::get_user($overrideby, 'id ' . $userfields->get_sql()->selects, MUST_EXIST);
 100              return fullname($overridebyrecord);
 101          }
 102          return '';
 103      }
 104  
 105      /**
 106       * Returns automatic completion details
 107       *
 108       * @param string $overrideby The name of the user overriding the completion condition, if available.
 109       * @return array
 110       */
 111      private function get_completion_details($overrideby): array {
 112          $details = [];
 113  
 114          foreach ($this->cmcompletion->get_details() as $key => $detail) {
 115              $detail->key = $key;
 116              $detail->statuscomplete = in_array($detail->status, [COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS]);
 117              $detail->statuscompletefail = $detail->status == COMPLETION_COMPLETE_FAIL;
 118              // This is not used by core themes but may be needed in custom themes.
 119              $detail->statuscompletepass = $detail->status == COMPLETION_COMPLETE_PASS;
 120              $detail->statusincomplete = $detail->status == COMPLETION_INCOMPLETE;
 121  
 122              // Add an accessible description to be used for title and aria-label attributes for overridden completion details.
 123              if ($overrideby) {
 124                  $setbydata = (object)[
 125                      'condition' => $detail->description,
 126                      'setby' => $overrideby,
 127                  ];
 128                  $overridestatus = $detail->statuscomplete ? 'done' : 'todo';
 129                  $detail->accessibledescription = get_string('completion_setby:auto:' . $overridestatus, 'course', $setbydata);
 130              }
 131  
 132              unset($detail->status);
 133              $details[] = $detail;
 134          }
 135          return $details;
 136      }
 137  
 138      /**
 139       * Returns the accessible description for manual completions with overridden completion state.
 140       *
 141       * @param string $overrideby The name of the user overriding the completion condition, if available.
 142       * @param int $overallcompletion The overall completion state of the activity.
 143       * @return string
 144       */
 145      private function get_accessible_description($overrideby, $overallcompletion): string {
 146          if ($this->cmcompletion->is_manual() && $overrideby) {
 147              $setbydata = (object)[
 148                  'activityname' => $this->cminfo->get_formatted_name(),
 149                  'setby' => $overrideby,
 150              ];
 151              $isoverallcompleted = $overallcompletion == COMPLETION_COMPLETE;
 152              $setbylangkey = $isoverallcompleted ? 'completion_setby:manual:done' : 'completion_setby:manual:markdone';
 153              return get_string($setbylangkey, 'course', $setbydata);
 154          }
 155          return '';
 156      }
 157  }