AutorÃa | Ultima modificación | Ver Log |
<?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 tool_courserating;use core_customfield\data_controller;use core_customfield\field_controller;use tool_courserating\external\stars_exporter;/*** Additional helper functions** @package tool_courserating* @copyright 2022 Marina Glancy <marina.glancy@gmail.com>* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class helper {/*** Temporary function** @return void*/private function wordings() {// @codingStandardsIgnoreStart// Udemy.'You\'ve finished the last lesson in this course! Would you like to leave a review?';[1 => 'Awful, not what I was expecting at all',1.5 => 'Awful / Poor',2 => 'Poor, pretty disappointed',2.5 => 'Poor / Average',3 => 'Average, could be better',3.5 => 'Average / Good',4 => 'Good, what I expected',4.5 => 'Good / Amazing',5 => 'Amazing, above expectations',];'Tell us about your own personal experience taking this course. Was it a good match for you?';'Report'; 'Report abuse';'Flagged content is reviewed by Udemy staff to determine whether it violates Terms of Service or Community Guidelines. If you have a question or technical issue, please contact our Support team here.';'Issue type';['Inappropriate Course Content','Inappropriate Behavior','Udemy Policy Violation','Spammy Content','Other',];'Issue details';// @codingStandardsIgnoreEnd}/*** Checks if we are on a main course page** @return int*/public static function is_course_page(): int {global $PAGE, $CFG;if ($PAGE->course && $PAGE->url->out_omit_querystring() === $CFG->wwwroot . '/course/view.php') {return $PAGE->course->id;}return 0;}/*** Checks if we are on a main page of single-activity course** @return int*/public static function is_single_activity_course_page(): int {global $PAGE, $CFG;if ($PAGE->context->contextlevel == CONTEXT_MODULE && $PAGE->course->format === 'singleactivity' &&$PAGE->url->out_omit_querystring() === $CFG->wwwroot . '/mod/' . $PAGE->cm->modname . '/view.php') {return $PAGE->course->id;}return 0;}/*** Checks if we are on a course edit page** @return int*/public static function is_course_edit_page(): int {global $PAGE, $CFG;if ($PAGE->course && $PAGE->url->out_omit_querystring() === $CFG->wwwroot . '/course/edit.php') {return $PAGE->course->id;}return 0;}/*** Are course ratings enabled (or could be enabled) in any courses? Do we need to have a course rating field** @return bool*/public static function course_ratings_enabled_anywhere(): bool {if (self::get_setting(constants::SETTING_RATINGMODE) == constants::RATEBY_NOONE &&!self::get_setting(constants::SETTING_PERCOURSE)) {return false;}return true;}/*** Options for the review editor form element** @param \context $context* @return array*/public static function review_editor_options(\context $context) {global $CFG;require_once($CFG->dirroot.'/lib/formslib.php');return ['subdirs' => 0,'maxbytes' => $CFG->maxbytes,'maxfiles' => EDITOR_UNLIMITED_FILES,'changeformat' => 0,'context' => $context,];}/*** Retrieve and clean plugin setting** @param string $name* @return bool|mixed|object|string*/public static function get_setting(string $name) {$value = get_config('tool_courserating', $name);static $defaults = [constants::SETTING_STARCOLOR => constants::SETTING_STARCOLOR_DEFAULT,constants::SETTING_RATINGCOLOR => constants::SETTING_RATINGCOLOR_DEFAULT,constants::SETTING_DISPLAYEMPTY => false,constants::SETTING_PERCOURSE => false,constants::SETTING_RATINGMODE => constants::RATEBY_ANYTIME,constants::SETTING_USEHTML => false,];if (!isset($value) && array_key_exists($name, $defaults)) {// Can only happen if there is unfinished upgrade.return $defaults[$name];}if ($name === constants::SETTING_DISPLAYEMPTY || $name === constants::SETTING_PERCOURSE|| $name === constants::SETTING_USEHTML) {return !empty($value);}if ($name === constants::SETTING_STARCOLOR || $name === constants::SETTING_RATINGCOLOR) {$color = strtolower($value ?? '');return (preg_match('/^#[a-f0-9]{6}$/', $color)) ? $color : $defaults[$name];}if ($name === constants::SETTING_RATINGMODE) {static $available = [constants::RATEBY_NOONE, constants::RATEBY_ANYTIME, constants::RATEBY_COMPLETED];return in_array($value, $available) ? $value : $defaults[$name];}return $value;}/*** CSS for the stars colors to be added to the page** @return string*/public static function get_rating_colour_css() {return '.tool_courserating-stars { color: '.self::get_setting(constants::SETTING_STARCOLOR).'; }'."\n".'.tool_courserating-ratingcolor { color: '.self::get_setting(constants::SETTING_RATINGCOLOR).';}'."\n".'.tool_courserating-norating .tool_courserating-stars { color: '.constants::COLOR_GRAY.';}'."\n".'.tool_courserating-barcolor { background-color: '.self::get_setting(constants::SETTING_STARCOLOR).';}'."\n";}/*** Finds a field by its shortname** @param string $shortname* @return field_controller|null*/protected static function find_custom_field_by_shortname(string $shortname): ?field_controller {$handler = \core_course\customfield\course_handler::create();$categories = $handler->get_categories_with_fields();foreach ($categories as $category) {foreach ($category->get_fields() as $field) {if ($field->get('shortname') === $shortname) {return $field;}}}return null;}/*** Create a custom course field if it does not exist** @param string $shortname* @param string $type i.e. 'textarea', 'select', 'text* @param null|\lang_string $displayname* @param array $config additional field configuration, for example, options for 'select' element* @param string $description* @return field_controller|null*/protected static function create_custom_field(string $shortname, string $type = 'text', ?\lang_string $displayname = null,array $config = [], string $description = ''): ?field_controller {$handler = \core_course\customfield\course_handler::create();$categories = $handler->get_categories_with_fields();if (empty($categories)) {$categoryid = $handler->create_category();$category = \core_customfield\category_controller::create($categoryid);} else {$category = reset($categories);}$config += ['defaultvalue' => '','defaultvalueformat' => 1,'visibility' => \core_course\customfield\course_handler::VISIBLETOALL,'required' => 0,'uniquevalues' => 0,'locked' => 0,];$record = (object)['type' => $type,'shortname' => $shortname,'name' => $displayname ? (string)$displayname : $shortname,'descriptionformat' => FORMAT_HTML,'description' => $description,'configdata' => json_encode($config),];try {$field = \core_customfield\field_controller::create(0, $record, $category);} catch (\moodle_exception $e) {return null;}$handler->save_field_configuration($field, $record);// Fetch the field again because the categories cache was rebuilt.return self::find_custom_field_by_shortname($shortname);}/*** Retrieve course custom field responsible for storing course ratings, create if not found** @return field_controller|null*/public static function get_course_rating_field(): ?field_controller {$shortname = constants::CFIELD_RATING;$field = self::find_custom_field_by_shortname($shortname);if (!self::course_ratings_enabled_anywhere()) {if ($field) {$field->get_handler()->delete_field_configuration($field);}return null;}return $field ?? self::create_custom_field($shortname,'textarea',new \lang_string('ratinglabel', 'tool_courserating'),['locked' => 1],get_string('cfielddescription', 'tool_courserating'));}/*** Retrieve course custom field responsible for configuring per-course course rating mode, create if needed** @return field_controller|null*/public static function get_course_rating_mode_field(): ?field_controller {$shortname = constants::CFIELD_RATINGMODE;$field = self::find_custom_field_by_shortname($shortname);if (!self::get_setting(constants::SETTING_PERCOURSE)) {if ($field) {$field->get_handler()->delete_field_configuration($field);}return null;}$options = constants::rated_courses_options();$description = get_string('ratebydefault', 'tool_courserating',$options[self::get_setting(constants::SETTING_RATINGMODE)]);$field = $field ?? self::create_custom_field($shortname,'select',new \lang_string('ratingmode', 'tool_courserating'),['visibility' => \core_course\customfield\course_handler::NOTVISIBLE,'options' => join("\n", $options),],$description);if ($field && $field->get('description') !== $description) {$field->set('description', $description);$field->save();}return $field;}/*** Delete all course custom fields created by this plugin (on uninstall)** @return void*/public static function delete_all_custom_fields() {$shortname = constants::CFIELD_RATINGMODE;if ($field = self::find_custom_field_by_shortname($shortname)) {$field->get_handler()->delete_field_configuration($field);}$shortname = constants::CFIELD_RATING;if ($field = self::find_custom_field_by_shortname($shortname)) {$field->get_handler()->delete_field_configuration($field);}}/*** Retireve data stored in a course custom field** @param int $courseid* @param string $shortname* @return data_controller|null*/protected static function get_custom_field_data(int $courseid, string $shortname): ?data_controller {if ($f = self::find_custom_field_by_shortname($shortname)) {$fields = \core_customfield\api::get_instance_fields_data([$f->get('id') => $f], $courseid);foreach ($fields as $data) {if (!$data->get('id')) {$data->set('contextid', \context_course::instance($courseid)->id);}return $data;}}return null;}/*** Retrieve data stored in a course rating course custom field** @param int $courseid* @return data_controller|null*/public static function get_course_rating_data_in_cfield(int $courseid): ?data_controller {return self::get_custom_field_data($courseid, constants::CFIELD_RATING);}/*** Retireve data stored in a rating mode custom course field** @param int $courseid* @return data_controller|null*/public static function get_course_rating_enabled_data_in_cfield(int $courseid): ?data_controller {return self::get_custom_field_data($courseid, constants::CFIELD_RATINGMODE);}/*** Calculate the rating mode for a specific course** @param int $courseid* @return int*/public static function get_course_rating_mode(int $courseid): int {$mode = self::get_setting(constants::SETTING_RATINGMODE);if (self::get_setting(constants::SETTING_PERCOURSE)) {if ($data = self::get_course_rating_enabled_data_in_cfield($courseid)) {$modecourse = (int)$data->get('intvalue');if (array_key_exists($modecourse, constants::rated_courses_options())) {// Value is overridden for this course.return $modecourse;}}}return $mode;}/*** Formatter for average rating** @param float|null $avgrating* @param string $default* @return string*/public static function format_avgrating(?float $avgrating, string $default = ''): string {return $avgrating ? sprintf("%.1f", $avgrating) : $default;}/*** Formatter for stars** @param float|null $avgrating* @param \renderer_base|null $output* @return string*/public static function stars(?float $avgrating, ?\renderer_base $output = null): string {global $PAGE;if (!$avgrating) {return '';}$output = $output ?? $PAGE->get_renderer('tool_courserating');return $output->render_from_template('tool_courserating/stars',(new stars_exporter($avgrating))->export($output));}/*** Formatter for date* @param int $value* @return string*/public static function format_date($value): string {return $value ? userdate($value, get_string('strftimedatetimeshort', 'core_langconfig')) : '';}/*** Formatter for review** @param string $value* @param \stdClass $row* @return string*/public static function format_review($value, \stdClass $row): string {if (empty($row->id) || !strlen($row->review ?? '')) {return '';}$context = !empty($row->courseid) ? \context_course::instance($row->courseid) : \context_system::instance();$formatparams = ['options' => [],'striplinks' => true,'component' => 'tool_courserating','filearea' => 'review','itemid' => $row->id,'context' => $context,];if (self::get_setting(constants::SETTING_USEHTML)) {list($text, $format) = external_format_text($row->review, FORMAT_HTML, $formatparams['context'],$formatparams['component'], $formatparams['filearea'], $formatparams['itemid'], $formatparams['options']);return $text;} else {return format_text(clean_param($row->review, PARAM_TEXT), FORMAT_MOODLE, ['context' => $context]);}}/*** Actions column** @param int $id* @param \stdClass $row* @return string*/public static function format_actions($id, $row): string {if (!$id || !permission::can_delete_rating($id, $row->courseid)) {return '';}return "<span data-for=\"tool_courserating-rbcell\" data-ratingid=\"$id\">"."<a href=\"#\" data-action=\"tool_courserating-delete-rating\" data-ratingid=\"$id\">".get_string('deleterating', 'tool_courserating')."</a></span>";}/*** Format individual student rating in the course report** @param int $rating* @param \stdClass $row* @return string*/public static function format_rating_in_course_report($rating, $row): string {if (!$rating) {return '';}return \html_writer::span(self::stars((float)$rating).\html_writer::span($rating, 'tool_courserating-ratingcolor ml-2'),'tool_courserating-reportrating');}/*** Format flags count in course report** @param int|null $nofflags* @param \stdClass $row* @return string*/public static function format_flags_in_course_report(?int $nofflags, \stdClass $row): string {return $nofflags ? "<span class=\"badge badge-warning\">$nofflags</span>" : '';}}