. /** * Class publication * * @package core * @copyright 2017 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\hub; defined('MOODLE_INTERNAL') || die(); use moodle_exception; use moodle_url; use context_user; use stdClass; use html_writer; /** * Methods to work with site registration on moodle.net * * @package core * @copyright 2017 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class publication { /** @var Audience: educators */ const HUB_AUDIENCE_EDUCATORS = 'educators'; /** @var Audience: students */ const HUB_AUDIENCE_STUDENTS = 'students'; /** @var Audience: admins */ const HUB_AUDIENCE_ADMINS = 'admins'; /** @var Educational level: primary */ const HUB_EDULEVEL_PRIMARY = 'primary'; /** @var Educational level: secondary */ const HUB_EDULEVEL_SECONDARY = 'secondary'; /** @var Educational level: tertiary */ const HUB_EDULEVEL_TERTIARY = 'tertiary'; /** @var Educational level: government */ const HUB_EDULEVEL_GOVERNMENT = 'government'; /** @var Educational level: association */ const HUB_EDULEVEL_ASSOCIATION = 'association'; /** @var Educational level: corporate */ const HUB_EDULEVEL_CORPORATE = 'corporate'; /** @var Educational level: other */ const HUB_EDULEVEL_OTHER = 'other'; /** * Retrieve all the sorted course subjects * * @return array $subjects */ public static function get_sorted_subjects() { $subjects = get_string_manager()->load_component_strings('edufields', current_language()); // Sort the subjects. $return = []; asort($subjects); foreach ($subjects as $key => $option) { $keylength = strlen($key); if ($keylength == 12) { $return[$key] = $option; // We want only selectable categories. } } return $return; } /** * Get all publication for a course * * @param int $courseid local course id * @return array of publication */ public static function get_course_publications($courseid) { global $DB; $sql = 'SELECT cp.id, cp.status, cp.timechecked, cp.timepublished, rh.hubname, rh.huburl, cp.courseid, cp.enrollable, cp.hubcourseid FROM {course_published} cp, {registration_hubs} rh WHERE cp.huburl = rh.huburl and cp.courseid = :courseid and rh.huburl = :huburl ORDER BY cp.enrollable DESC, rh.hubname, cp.timepublished'; $params = array('courseid' => $courseid, 'huburl' => HUB_MOODLEORGHUBURL); $records = $DB->get_records_sql($sql, $params); // Add links for publications that are listed. foreach ($records as $id => $record) { if ($record->status) { $records[$id]->link = new moodle_url(HUB_MOODLEORGHUBURL, ['courseid' => $record->hubcourseid]); } } return $records; } /** * Load publication information from local db * * @param int $id * @param int $courseid if specified publication will be checked that it is in the current course * @param int $strictness * @return stdClass */ public static function get_publication($id, $courseid = 0, $strictness = IGNORE_MISSING) { global $DB; if (!$id && $strictness != MUST_EXIST) { return false; } $params = ['id' => $id, 'huburl' => HUB_MOODLEORGHUBURL]; if ($courseid) { $params['courseid'] = $courseid; } return $DB->get_record('course_published', $params, '*', $strictness); } /** * Update a course publication * @param stdClass $publication */ protected static function update_publication($publication) { global $DB; $DB->update_record('course_published', $publication); } /** * Check all courses published from this site if they have been approved */ public static function request_status_update() { global $DB; list($sitecourses, $coursetotal) = api::get_courses('', 1, 1, ['allsitecourses' => 1]); // Update status for all these course. foreach ($sitecourses as $sitecourse) { // Get the publication from the hub course id. $publication = $DB->get_record('course_published', ['hubcourseid' => $sitecourse['id']]); if (!empty($publication)) { $publication->status = $sitecourse['privacy']; $publication->timechecked = time(); self::update_publication($publication); } else { $msgparams = new stdClass(); $msgparams->id = $sitecourse['id']; $msgparams->hubname = html_writer::tag('a', 'Moodle.net', array('href' => HUB_MOODLEORGHUBURL)); \core\notification::add(get_string('detectednotexistingpublication', 'hub', $msgparams)); // TODO action? } } } /** * Unpublish a course * * @param stdClass $publication */ public static function unpublish($publication) { global $DB; // Unpublish the publication by web service. api::unregister_courses($publication->hubcourseid); // Delete the publication from the database. $DB->delete_records('course_published', array('id' => $publication->id)); // Add confirmation message. $course = get_course($publication->courseid); $context = \context_course::instance($course->id); $publication->courseshortname = format_string($course->shortname, true, ['context' => $context]); $publication->hubname = 'Moodle.net'; \core\notification::add(get_string('courseunpublished', 'hub', $publication), \core\output\notification::NOTIFY_SUCCESS); } /** * Publish a course * * @param \stdClass $courseinfo * @param \stored_file[] $files */ public static function publish_course($courseinfo, $files) { global $DB; // Register course and get id of the course on moodle.net ($hubcourseid). $courseid = $courseinfo->sitecourseid; try { $hubcourseid = api::register_course($courseinfo); } catch (Exception $e) { throw new moodle_exception('errorcoursepublish', 'hub', new moodle_url('/course/view.php', array('id' => $courseid)), $e->getMessage()); } // Insert/update publication record in the local DB. $publication = $DB->get_record('course_published', array('hubcourseid' => $hubcourseid, 'huburl' => HUB_MOODLEORGHUBURL)); if ($publication) { $DB->update_record('course_published', ['id' => $publication->id, 'timepublished' => time()]); } else { $publication = new stdClass(); $publication->huburl = HUB_MOODLEORGHUBURL; $publication->courseid = $courseid; $publication->hubcourseid = $hubcourseid; $publication->enrollable = (int)$courseinfo->enrollable; $publication->timepublished = time(); $publication->id = $DB->insert_record('course_published', $publication); } // Send screenshots. if ($files) { $screenshotnumber = $courseinfo->screenshots - count($files); foreach ($files as $file) { $screenshotnumber++; api::add_screenshot($hubcourseid, $file, $screenshotnumber); } } return $hubcourseid; } /** * Delete all publications * * @param int $advertised search for advertised courses * @param int $shared search for shared courses * @throws moodle_exception */ public static function delete_all_publications($advertised = true, $shared = true) { global $DB; if (!$advertised && !$shared) { // Nothing to do. return true; } $params = ['huburl' => HUB_MOODLEORGHUBURL]; if (!$advertised || !$shared) { // Retrieve ONLY advertised or ONLY shared. $params['enrollable'] = $advertised ? 1 : 0; } if (!$publications = $DB->get_records('course_published', $params)) { // Nothing to unpublish. return true; } foreach ($publications as $publication) { $hubcourseids[] = $publication->hubcourseid; } api::unregister_courses($hubcourseids); // Delete the published courses from local db. $DB->delete_records('course_published', $params); return true; } /** * Get an array of all block instances for a given context * @param int $contextid a context id * @return array of block instances. */ public static function get_block_instances_by_context($contextid) { global $DB; return $DB->get_records('block_instances', array('parentcontextid' => $contextid), 'blockname'); } /** * List of available educational levels * * @param bool $any add option for "Any" (for search forms) * @return array */ public static function educational_level_options($any = false) { $options = array(); if ($any) { $options['all'] = get_string('any'); } $options[self::HUB_EDULEVEL_PRIMARY] = get_string('edulevelprimary', 'hub'); $options[self::HUB_EDULEVEL_SECONDARY] = get_string('edulevelsecondary', 'hub'); $options[self::HUB_EDULEVEL_TERTIARY] = get_string('eduleveltertiary', 'hub'); $options[self::HUB_EDULEVEL_GOVERNMENT] = get_string('edulevelgovernment', 'hub'); $options[self::HUB_EDULEVEL_ASSOCIATION] = get_string('edulevelassociation', 'hub'); $options[self::HUB_EDULEVEL_CORPORATE] = get_string('edulevelcorporate', 'hub'); $options[self::HUB_EDULEVEL_OTHER] = get_string('edulevelother', 'hub'); return $options; } /** * List of available audience options * * @param bool $any add option for "Any" (for search forms) * @return array */ public static function audience_options($any = false) { $options = array(); if ($any) { $options['all'] = get_string('any'); } $options[self::HUB_AUDIENCE_EDUCATORS] = get_string('audienceeducators', 'hub'); $options[self::HUB_AUDIENCE_STUDENTS] = get_string('audiencestudents', 'hub'); $options[self::HUB_AUDIENCE_ADMINS] = get_string('audienceadmins', 'hub'); return $options; } /** * Search for courses * * For the list of fields returned for each course see {@link communication::get_courses} * * @param string $search search string * @param bool $downloadable true - return downloadable courses, false - return enrollable courses * @param array|\stdClass $options other options from the list of allowed options: * 'ids', 'sitecourseids', 'coverage', 'licenceshortname', 'subject', 'audience', * 'educationallevel', 'language', 'orderby', 'givememore', 'allsitecourses' * @return array of two elements: [$courses, $coursetotal] */ public static function search($search, $downloadable, $options) { try { return api::get_courses($search, $downloadable, !$downloadable, $options); } catch (moodle_exception $e) { \core\notification::add(get_string('errorcourselisting', 'block_community', $e->getMessage()), \core\output\notification::NOTIFY_ERROR); return [[], 0]; } } /** * Retrieves information about published course * * For the list of fields returned for the course see {@link communication::get_courses} * * @param stdClass $publication * @return array|null */ public static function get_published_course($publication) { try { list($courses, $unused) = api::get_courses('', !$publication->enrollable, $publication->enrollable, ['ids' => [$publication->hubcourseid], 'allsitecourses' => 1]); return reset($courses); } catch (\Exception $e) { \core\notification::add(get_string('errorcourseinfo', 'hub', $e->getMessage()), \core\output\notification::NOTIFY_ERROR); } return null; } /** * Downloads course backup and stores it in the user private files * * @param int $hubcourseid * @param string $coursename * @return array */ public static function download_course_backup($hubcourseid, $coursename) { global $CFG, $USER; require_once($CFG->libdir . "/filelib.php"); $backuptempdir = make_backup_temp_directory(''); $filename = md5(time() . '-' . $hubcourseid . '-'. $USER->id . '-'. random_string(20)); $path = $backuptempdir.'/'.$filename.".mbz"; api::download_course_backup($hubcourseid, $path); $fs = get_file_storage(); $record = new stdClass(); $record->contextid = context_user::instance($USER->id)->id; $record->component = 'user'; $record->filearea = 'private'; $record->itemid = 0; $record->filename = urlencode($coursename).'_'.time().".mbz"; $record->filepath = '/downloaded_backup/'; if (!$fs->file_exists($record->contextid, $record->component, $record->filearea, 0, $record->filepath, $record->filename)) { $fs->create_file_from_pathname($record, $path); } return [$record->filepath . $record->filename, $filename]; } /** * Uploads a course backup * * @param int $hubcourseid id of the published course on moodle.net, it must be published from this site * @param \stored_file $backupfile */ public static function upload_course_backup($hubcourseid, \stored_file $backupfile) { api::upload_course_backup($hubcourseid, $backupfile); } }