first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,85 @@
<?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/>.
/**
* Class for exporting a course module summary from an stdClass.
*
* @package core_course
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_course\external;
defined('MOODLE_INTERNAL') || die();
use renderer_base;
/**
* Class for exporting a course module summary from a cm_info class.
*
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_summary_exporter extends \core\external\exporter {
protected static function define_related() {
return array('cm' => 'cm_info');
}
protected function get_other_values(renderer_base $output) {
$cm = $this->related['cm'];
$values = array(
'id' => $cm->id,
'name' => $cm->name,
'iconurl' => $cm->get_icon_url()->out()
);
if ($cm->url) {
$values['url'] = $cm->url->out();
}
return $values;
}
/**
* Get the format parameters for name.
*
* @return array
*/
protected function get_format_parameters_for_name() {
$cm = $this->related['cm'];
$context = $cm->context;
return [
'context' => $context,
];
}
public static function define_other_properties() {
return array(
'id' => array(
'type' => PARAM_INT,
),
'name' => array(
'type' => PARAM_TEXT
),
'url' => array(
'type' => PARAM_URL,
'optional' => true,
),
'iconurl' => array(
'type' => PARAM_URL
)
);
}
}
+233
View File
@@ -0,0 +1,233 @@
<?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/>.
/**
* Class for exporting a course summary from an stdClass.
*
* @package core_course
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_course\external;
defined('MOODLE_INTERNAL') || die();
use renderer_base;
use moodle_url;
/**
* Class for exporting a course summary from an stdClass.
*
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_summary_exporter extends \core\external\exporter {
/**
* Constructor - saves the persistent object, and the related objects.
*
* @param mixed $data - Either an stdClass or an array of values.
* @param array $related - An optional list of pre-loaded objects related to this object.
*/
public function __construct($data, $related = array()) {
if (!array_key_exists('isfavourite', $related)) {
$related['isfavourite'] = false;
}
parent::__construct($data, $related);
}
protected static function define_related() {
// We cache the context so it does not need to be retrieved from the course.
return array('context' => '\\context', 'isfavourite' => 'bool?');
}
protected function get_other_values(renderer_base $output) {
global $CFG;
$courseimage = self::get_course_image($this->data);
if (!$courseimage) {
$courseimage = $output->get_generated_image_for_id($this->data->id);
}
$progress = self::get_course_progress($this->data);
$hasprogress = false;
if ($progress === 0 || $progress > 0) {
$hasprogress = true;
}
$progress = floor($progress ?? 0);
$coursecategory = \core_course_category::get($this->data->category, MUST_EXIST, true);
return array(
'fullnamedisplay' => get_course_display_name_for_list($this->data),
'viewurl' => (new moodle_url('/course/view.php', array('id' => $this->data->id)))->out(false),
'courseimage' => $courseimage,
'progress' => $progress,
'hasprogress' => $hasprogress,
'isfavourite' => $this->related['isfavourite'],
'hidden' => boolval(get_user_preferences('block_myoverview_hidden_course_' . $this->data->id, 0)),
'showshortname' => $CFG->courselistshortnames ? true : false,
'coursecategory' => $coursecategory->name
);
}
public static function define_properties() {
return array(
'id' => array(
'type' => PARAM_INT,
),
'fullname' => array(
'type' => PARAM_TEXT,
),
'shortname' => array(
'type' => PARAM_TEXT,
),
'idnumber' => array(
'type' => PARAM_RAW,
),
'summary' => array(
'type' => PARAM_RAW,
'null' => NULL_ALLOWED,
'default' => null,
),
'summaryformat' => array(
'type' => PARAM_INT,
'default' => FORMAT_MOODLE,
),
'startdate' => array(
'type' => PARAM_INT,
),
'enddate' => array(
'type' => PARAM_INT,
),
'visible' => array(
'type' => PARAM_BOOL,
),
'showactivitydates' => [
'type' => PARAM_BOOL,
'null' => NULL_ALLOWED
],
'showcompletionconditions' => [
'type' => PARAM_BOOL,
'null' => NULL_ALLOWED
],
'pdfexportfont' => [
'type' => PARAM_TEXT,
'null' => NULL_ALLOWED,
'default' => null,
],
);
}
/**
* Get the formatting parameters for the summary.
*
* @return array
*/
protected function get_format_parameters_for_summary() {
return [
'component' => 'course',
'filearea' => 'summary',
];
}
public static function define_other_properties() {
return array(
'fullnamedisplay' => array(
'type' => PARAM_TEXT,
),
'viewurl' => array(
'type' => PARAM_URL,
),
'courseimage' => array(
'type' => PARAM_RAW,
),
'progress' => array(
'type' => PARAM_INT,
'optional' => true
),
'hasprogress' => array(
'type' => PARAM_BOOL
),
'isfavourite' => array(
'type' => PARAM_BOOL
),
'hidden' => array(
'type' => PARAM_BOOL
),
'timeaccess' => array(
'type' => PARAM_INT,
'optional' => true
),
'showshortname' => array(
'type' => PARAM_BOOL
),
'coursecategory' => array(
'type' => PARAM_TEXT
)
);
}
/**
* Get the course image if added to course.
*
* @param object $course
* @return string|false url of course image or false if it's not exist.
*/
public static function get_course_image($course) {
$image = \cache::make('core', 'course_image')->get($course->id);
if (is_null($image)) {
$image = false;
}
return $image;
}
/**
* Get the course pattern datauri.
*
* The datauri is an encoded svg that can be passed as a url.
* @param object $course
* @return string datauri
* @deprecated 3.7
*/
public static function get_course_pattern($course) {
global $OUTPUT;
debugging('course_summary_exporter::get_course_pattern() is deprecated. ' .
'Please use $OUTPUT->get_generated_image_for_id() instead.', DEBUG_DEVELOPER);
return $OUTPUT->get_generated_image_for_id($course->id);
}
/**
* Get the course progress percentage.
*
* @param object $course
* @return int progress
*/
public static function get_course_progress($course) {
return \core_completion\progress::get_course_progress_percentage($course);
}
/**
* Get the course color.
*
* @param int $courseid
* @return string hex color code.
* @deprecated 3.7
*/
public static function coursecolor($courseid) {
global $OUTPUT;
debugging('course_summary_exporter::coursecolor() is deprecated. ' .
'Please use $OUTPUT->get_generated_color_for_id() instead.', DEBUG_DEVELOPER);
return $OUTPUT->get_generated_color_for_id($courseid);
}
}
@@ -0,0 +1,220 @@
<?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/>.
namespace core_course\external;
defined('MOODLE_INTERNAL') || die();
use context_user;
use core_calendar_external;
use core_course_external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
require_once("{$CFG->dirroot}/calendar/externallib.php");
require_once("{$CFG->dirroot}/course/externallib.php");
/**
* Class for fetching courses which have action event(s) and match given filter parameters.
*
* @package core_course
* @copyright 2022 Michael Hawkins <michaelh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class get_enrolled_courses_with_action_events_by_timeline_classification extends external_api {
/**
* Returns the description of method parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters(
[
'classification' => new external_value(PARAM_ALPHA, 'future, inprogress, or past'),
'limit' => new external_value(PARAM_INT, 'Result set limit', VALUE_DEFAULT, 0),
'offset' => new external_value(PARAM_INT, 'Result set offset', VALUE_DEFAULT, 0),
'sort' => new external_value(PARAM_TEXT, 'Sort string', VALUE_DEFAULT, null),
'customfieldname' => new external_value(PARAM_ALPHANUMEXT, 'Used when classification = customfield',
VALUE_DEFAULT, null),
'customfieldvalue' => new external_value(PARAM_RAW, 'Used when classification = customfield',
VALUE_DEFAULT, null),
'searchvalue' => new external_value(PARAM_RAW, 'The value a user wishes to search against',
VALUE_DEFAULT, null),
'eventsfrom' => new external_value(PARAM_INT, 'Optional starting timestamp for action events',
VALUE_DEFAULT, null),
'eventsto' => new external_value(PARAM_INT, 'Optional ending timestamp for action events',
VALUE_DEFAULT, null),
]
);
}
/**
* Get courses matching the given timeline classification which have action event(s).
*
* Fetches courses by timeline classification which have at least one action event within the specified filtering.
*
* @param string $classification past, inprogress, or future
* @param int $limit Number of courses with events to attempt to fetch
* @param int $offset Offset the full course set before timeline classification is applied
* @param string $sort SQL sort string for results
* @param string $customfieldname Custom field name used when when classification is customfield
* @param string $customfieldvalue Custom field value used when when classification is customfield
* @param string $searchvalue Text search being applied
* @param int $eventsfrom The start timestamp (inclusive) to search from for action events in the course
* @param int $eventsto The end timestamp (inclusive) to search to for action events in the course
* @return array list of courses and any warnings
*/
public static function execute(
string $classification,
int $limit = 0,
int $offset = 0,
string $sort = null,
string $customfieldname = null,
string $customfieldvalue = null,
string $searchvalue = null,
int $eventsfrom = null,
int $eventsto = null
): array {
global $USER;
self::validate_context(context_user::instance($USER->id));
$params = self::validate_parameters(
self::execute_parameters(),
[
'classification' => $classification,
'limit' => $limit,
'offset' => $offset,
'sort' => $sort,
'customfieldname' => $customfieldname,
'customfieldvalue' => $customfieldvalue,
'searchvalue' => $searchvalue,
'eventsfrom' => $eventsfrom,
'eventsto' => $eventsto,
]
);
$classification = $params['classification'];
$limit = $params['limit'];
$offset = $params['offset'];
$sort = $params['sort'];
$customfieldname = $params['customfieldname'];
$customfieldvalue = $params['customfieldvalue'];
$searchvalue = clean_param($params['searchvalue'], PARAM_TEXT);
$eventsfrom = $params['eventsfrom'];
$eventsto = $params['eventsto'];
$morecoursestofetch = true;
$morecoursespossible = true;
$coursesfinal = [];
do {
// Fetch courses.
[
'courses' => $coursesfetched,
'nextoffset' => $offset,
] = core_course_external::get_enrolled_courses_by_timeline_classification($classification, $limit,
$offset, $sort, $customfieldname, $customfieldvalue, $searchvalue);
$courseids = array_column($coursesfetched, 'id');
$coursesfetched = array_combine($courseids, $coursesfetched);
if (!empty($courseids)) {
// Need to check this to know how many are expected (since it is possible for this to be less than the limit).
$numcoursesfetched = count($courseids);
$numfetchedwithevents = 0;
// If less courses are fetched than we requested, we know it is not possible for more courses to be available.
if ($numcoursesfetched < $limit) {
$morecoursestofetch = false;
$morecoursespossible = false;
}
// Try to fetch one action event within the time/search parameters for each course.
$events = core_calendar_external::get_calendar_action_events_by_courses($courseids, $eventsfrom, $eventsto, 1,
$searchvalue);
foreach ($events->groupedbycourse as $courseevents) {
$courseid = $courseevents->courseid;
// Only include courses which contain at least one event.
if (empty($courseevents->events)) {
unset($coursesfetched[$courseid]);
} else {
$numfetchedwithevents++;
}
}
// Add courses with events to the final course list in order.
$coursesfinal = array_merge($coursesfinal, $coursesfetched);
// If any courses did not have events, adjust the limit so we can attempt to fetch as many as are still required.
if ($numfetchedwithevents < $numcoursesfetched) {
$limit -= $numfetchedwithevents;
} else {
// If we have found as many courses as required or are available, no need to attempt fetching more.
$morecoursestofetch = false;
}
} else {
$morecoursestofetch = false;
$morecoursespossible = false;
}
} while ($morecoursestofetch);
static $isrecursivecall = false;
$morecoursesavailable = false;
// Recursively call this method to check if at least one more course is available if we know that is a possibility.
if (!$isrecursivecall && $morecoursespossible) {
// Prevent infinite recursion.
$isrecursivecall = true;
$additionalcourses = self::execute(
$classification, 1, $offset, $sort, $customfieldname, $customfieldvalue, $searchvalue, $eventsfrom, $eventsto
);
if (!empty($additionalcourses['courses'])) {
$morecoursesavailable = true;
}
}
return [
'courses' => $coursesfinal,
'nextoffset' => $offset,
'morecoursesavailable' => $morecoursesavailable,
];
}
/**
* Returns description of method result value.
*
* @return \core_external\external_description
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure(
[
'courses' => new external_multiple_structure(course_summary_exporter::get_read_structure(), 'Course'),
'nextoffset' => new external_value(PARAM_INT, 'Offset for the next request'),
'morecoursesavailable' => new external_value(PARAM_BOOL,
'Whether more courses with events exist within the provided parameters'),
]
);
}
}
@@ -0,0 +1,137 @@
<?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/>.
namespace core_course\external;
use context_module;
use core_external\external_description;
use core_external\external_files;
use core_external\external_format_value;
use core_external\util as external_util;
use core_external\external_value;
/**
* This class helps implement the get_..._by_courses web service that every activity should have.
*
* It has helper methods to add the standard course-module fields to the results, and the declaration of the return value.
*
* @package core_course
* @copyright 2022 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class helper_for_get_mods_by_courses {
/**
* Add the value of all the standard fields to the results to be returned by the service.
* This is designed to be used in the implementation of the get_..._by_courses web service methods.
*
* Note that $modinstance is also updated in-place.
*
* @param \stdClass $modinstance one of the objects returned from a call to {@see get_all_instances_in_courses()}.
* @param string $component the plugin name, e.g. 'mod_book'.
* @param string $capabilityforgroups capability to check before including group/visible/section info in the results.
* @param string|null $capabilityforintro capability to check before including intro info in the results.
* null means always include (the default).
* @return array with the containing all the values declared in {@see standard_coursemodule_elements_returns()}.
*/
public static function standard_coursemodule_element_values(\stdClass $modinstance, string $component,
string $capabilityforgroups = 'moodle/course:manageactivities', string $capabilityforintro = null): array {
self::format_name_and_intro($modinstance, $component);
$context = context_module::instance($modinstance->coursemodule);
// First, we return information that any user can see in the web interface.
$moddetails['id'] = $modinstance->id;
$moddetails['coursemodule'] = $modinstance->coursemodule;
$moddetails['course'] = $modinstance->course;
$moddetails['name'] = $modinstance->name;
$moddetails['lang'] = clean_param($modinstance->lang, PARAM_LANG);
if (!$capabilityforintro || has_capability($capabilityforintro, $context)) {
$moddetails['intro'] = $modinstance->intro;
$moddetails['introformat'] = $modinstance->introformat;
$moddetails['introfiles'] = $modinstance->introfiles;
}
// Now add information only available to people who can edit.
if (has_capability($capabilityforgroups, $context)) {
$moddetails['section'] = $modinstance->section;
$moddetails['visible'] = $modinstance->visible;
$moddetails['groupmode'] = $modinstance->groupmode;
$moddetails['groupingid'] = $modinstance->groupingid;
}
return $moddetails;
}
/**
* Format the module name an introduction ready to be exported to a web service.
*
* Note that $modinstance is updated in-place.
*
* @param \stdClass $modinstance one of the objects returned from a call to {@see get_all_instances_in_courses()}.
* @param string $component the plugin name, e.g. 'mod_book'.
*/
public static function format_name_and_intro(\stdClass $modinstance, string $component) {
$context = context_module::instance($modinstance->coursemodule);
$modinstance->name = \core_external\util::format_string($modinstance->name, $context);
[$modinstance->intro, $modinstance->introformat] = \core_external\util::format_text(
$modinstance->intro, $modinstance->introformat, $context,
$component, 'intro', null, ['noclean' => true]);
$modinstance->introfiles = external_util::get_area_files($context->id, $component, 'intro', false, false);
}
/**
* Get the list of standard fields, to add to the declaration of the return values.
*
* Example usage combine the fields returned here with any extra ones your activity uses:
*
* public static function execute_returns() {
* return new external_single_structure([
* 'bigbluebuttonbns' => new external_multiple_structure(
* new external_single_structure(array_merge(
* helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(),
* [
* 'meetingid' => new external_value(PARAM_RAW, 'Meeting id'),
* 'timemodified' => new external_value(PARAM_INT, 'Last time the instance was modified'),
* ]
* ))
* ),
* 'warnings' => new external_warnings(),
* ]
* );
* }
*
* @param bool $introoptional if true, the intro fields are marked as optional. Default false.
* @return external_description[] array of standard fields, to which you can add your activity-specific ones.
*/
public static function standard_coursemodule_elements_returns(bool $introoptional = false): array {
return [
'id' => new external_value(PARAM_INT, 'Activity instance id'),
'coursemodule' => new external_value(PARAM_INT, 'Course module id'),
'course' => new external_value(PARAM_INT, 'Course id'),
'name' => new external_value(PARAM_RAW, 'Activity name'),
'intro' => new external_value(PARAM_RAW, 'Activity introduction', $introoptional ? VALUE_OPTIONAL : VALUE_REQUIRED),
'introformat' => new external_format_value('intro', $introoptional ? VALUE_OPTIONAL : VALUE_REQUIRED),
'introfiles' => new external_files('Files in the introduction', VALUE_OPTIONAL),
'section' => new external_value(PARAM_INT, 'Course section id', VALUE_OPTIONAL),
'visible' => new external_value(PARAM_BOOL, 'Visible', VALUE_OPTIONAL),
'groupmode' => new external_value(PARAM_INT, 'Group mode', VALUE_OPTIONAL),
'groupingid' => new external_value(PARAM_INT, 'Group id', VALUE_OPTIONAL),
'lang' => new external_value(PARAM_SAFEDIR, 'Forced activity language', VALUE_OPTIONAL),
];
}
}