Skip to content

Instantly share code, notes, and snippets.

@willianmano
Created June 24, 2019 14:29
Show Gist options
  • Save willianmano/9785bb1b6ff8f047905f04917c5a0b77 to your computer and use it in GitHub Desktop.
Save willianmano/9785bb1b6ff8f047905f04917c5a0b77 to your computer and use it in GitHub Desktop.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A utility course class.
*
* @package theme_olm
* @copyright 2019 Willian Mano - http://conecti.me
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace theme_olm\util;
use cm_info;
use completion_info;
use context_module;
use core_availability\info;
use core_course_list_element;
use html_writer;
use moodle_url;
use pix_icon;
use stdClass;
defined('MOODLE_INTERNAL') || die;
/**
* A utility course class
*
* @package theme_olm
* @copyright 2019 Willian Mano - http://conecti.me
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course {
protected $course;
public function __construct($course)
{
$this->course = $course;
}
public function get_sections_and_actvities($currentcoursemodule = null ) {
$sections = course_get_format($this->course)->get_sections();
$data = [];
foreach ($sections as $section) {
if (!$section->visible) {
continue;
}
$active = false;
if ($currentcoursemodule && $currentcoursemodule->section == $section->id) {
$active = true;
}
$sectionactivities = $this->get_section_coursemodule_list($this->course, $section, $currentcoursemodule);
$progress = $this->calculate_section_progress($sectionactivities);
$data[] = [
'id' => $section->id,
'name' => get_section_name($this->course->id, $section),
'active' => $active,
'activities' => $sectionactivities,
'progress' => $progress,
'iscompleted' => ($progress == 100) ? true : false,
'available' => $section->available,
'availableinfo' => $this->format_info($section->availableinfo, $this->course)
];
}
return $data;
}
protected function calculate_section_progress($sectionactivities) {
$totalactivities = count($sectionactivities);
if ($totalactivities === 0) {
return 0;
}
$totalcompleted = 0;
foreach ($sectionactivities as $activity) {
if ($activity['completed']) {
$totalcompleted++;
}
}
if ($totalcompleted === 0) {
return 0;
}
return (int)(($totalcompleted * 100) / $totalactivities);
}
public function get_section_coursemodule_list($course, $section, $currentcoursemodule = null) {
$modinfo = get_fast_modinfo($course);
$section = $modinfo->get_section_info($section->section);
$completioninfo = new completion_info($course);
// Get the list of modules visible to user (excluding the module being moved if there is one)
$sectionmodules = [];
if (!empty($modinfo->sections[$section->section])) {
foreach ($modinfo->sections[$section->section] as $modnumber) {
$mod = $modinfo->cms[$modnumber];
if ($module = $this->get_cm_list_item($mod,
$completioninfo, $currentcoursemodule)) {
$sectionmodules[] = $module;
}
}
}
return $sectionmodules;
}
public function get_cm_list_item(cm_info $mod, &$completioninfo, $currentcoursemodule = null) {
if (!$this->can_view_activity($mod)) {
return null;
}
$completed = $this->course_section_cm_completion($this->course, $completioninfo, $mod);
list($available, $availableinfo) = $this->course_section_cm_availability($mod);
$active = false;
if ($currentcoursemodule && $currentcoursemodule->id == $mod->id) {
$active = true;
}
return [
'id' => $mod->id,
'url' => $mod->url,
'name' => $mod->name,
'instance' => $mod->instance,
'active' => $active,
'completed' => $completed,
'available' => $available,
'availableinfo' => $availableinfo
];
}
public function can_view_activity($mod) {
if (!$mod->is_visible_on_course_page() || !$mod->visible) {
$modcontext = context_module::instance($mod->id);
$canviewhidden = has_capability('moodle/course:viewhiddenactivities', $modcontext);
if ($canviewhidden && !$mod->visible && $mod->get_section_info()->visible) {
return true;
}
return false;
}
return true;
}
/**
* Renders html for completion box on course page
*
* If completion is disabled, returns null
* If completion is completed returns true, false otherwise
*
* @param stdClass $course course object
* @param completion_info $completioninfo completion info for the course, it is recommended
* to fetch once for all modules in course/section for performance
* @param cm_info $mod module to show completion for
* @return string
*
* @throws \coding_exception
*/
public function course_section_cm_completion($course, &$completioninfo, cm_info $mod) {
global $USER;
$istrackeduser = $completioninfo->is_tracked_user($USER->id);
if (!$istrackeduser || !isloggedin() || isguestuser() || !$mod->uservisible) {
return null;
}
if ($completioninfo === null) {
$completioninfo = new completion_info($course);
}
$completion = $completioninfo->is_enabled($mod);
if ($completion == COMPLETION_TRACKING_NONE) {
return null;
}
$completiondata = $completioninfo->get_data($mod, true);
if ($completion == COMPLETION_TRACKING_MANUAL || $completion == COMPLETION_TRACKING_AUTOMATIC) {
switch($completiondata->completionstate) {
case COMPLETION_COMPLETE:
case COMPLETION_COMPLETE_PASS:
return true;
break;
}
}
return false;
}
/**
* Return true if the activity is available for the user, false otherwise
*
* @param cm_info $mod
*
* @return array
*
* @throws \coding_exception
* @throws \moodle_exception
*/
public function course_section_cm_availability(cm_info $mod) {
if (!$mod->uservisible && !empty($mod->availableinfo)) {
// this is a student who is not allowed to see the module but might be allowed
// to see availability info (i.e. "Available from ...")
$formattedinfo = $this->format_info($mod->availableinfo, $mod->get_course());
return [false, $formattedinfo];
}
// this is a teacher who is allowed to see module but still should see the
// information that module is not available to all/some students
$modcontext = context_module::instance($mod->id);
$canviewhidden = has_capability('moodle/course:viewhiddenactivities', $modcontext);
if ($canviewhidden && !$mod->visible && $mod->get_section_info()->visible) {
// This module is hidden but current user has capability to see it.
// Do not display the availability info if the whole section is hidden.
return [true, get_string('hiddenfromstudents')];
}
if ($mod->is_stealth()) {
// This module is available but is normally not displayed on the course page
// (this user can see it because they can manage it).
$output = [true, get_string('hiddenoncoursepage')];
}
return [true, null];
}
/**
* Formats the $cm->availableinfo string for display. This includes
* filling in the names of any course-modules that might be mentioned.
* Should be called immediately prior to display, or at least somewhere
* that we can guarantee does not happen from within building the modinfo
* object.
*
* @param \renderable|string $inforenderable Info string or renderable
* @param int|\stdClass $courseorid
* @return string Correctly formatted info string
* @throws \coding_exception
* @throws \moodle_exception
*/
public function format_info($inforenderable, $courseorid) {
global $PAGE;
// Use renderer if required.
if (is_string($inforenderable)) {
$info = $inforenderable;
} else {
$renderer = $PAGE->get_renderer('core', 'availability');
$info = $renderer->render($inforenderable);
}
// Don't waste time if there are no special tags.
if (strpos($info, '<AVAILABILITY_') === false) {
return $info;
}
// Handle CMNAME tags.
$modinfo = get_fast_modinfo($courseorid);
$context = \context_course::instance($modinfo->courseid);
$info = preg_replace_callback('~<AVAILABILITY_CMNAME_([0-9]+)/>~',
function($matches) use($modinfo, $context) {
$cm = $modinfo->get_cm($matches[1]);
if ($cm->has_view() and $cm->uservisible) {
// Help student by providing a link to the module which is preventing availability.
return format_string($cm->name, true, array('context' => $context));
} else {
return format_string($cm->name, true, array('context' => $context));
}
}, $info);
return $info;
}
/**
* Returns the first course's summary issue
*
* @param $course
* @param $courselink
*
* @return string
*
* @throws \moodle_exception
*/
public function get_summary_image_url() {
$courselist = new core_course_list_element($this->course);
foreach ($courselist->get_course_overviewfiles() as $file) {
if ($file->is_valid_image()) {
$pathcomponents = [
'/pluginfile.php',
$file->get_contextid(),
$file->get_component(),
$file->get_filearea() . $file->get_filepath() . $file->get_filename()
];
$path = implode('/', $pathcomponents);
return (new moodle_url($path))->out();
}
}
return (new moodle_url('/theme/olm/pix/default_course.jpg'))->out();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment