Merge branch 'wip-MDL-59495-master' of git://github.com/marinaglancy/moodle

This commit is contained in:
Andrew Nicols
2017-09-27 15:11:20 +08:00
36 changed files with 2469 additions and 2832 deletions
+433
View File
@@ -0,0 +1,433 @@
<?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 communication
*
* @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 webservice_xmlrpc_client;
use moodle_exception;
use curl;
use stdClass;
use coding_exception;
use moodle_url;
/**
* Methods to communicate with moodle.net web services
*
* @package core
* @copyright 2017 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class api {
/** @var File type: Course screenshot */
const HUB_SCREENSHOT_FILE_TYPE = 'screenshot';
/** @var File type: Hub screenshot */
const HUB_HUBSCREENSHOT_FILE_TYPE = 'hubscreenshot';
/** @var File type: Backup */
const HUB_BACKUP_FILE_TYPE = 'backup';
/**
* Calls moodle.net WS
*
* @param string $function name of WS function
* @param array $data parameters of WS function
* @param bool $allowpublic allow request without moodle.net registration
* @return mixed depends on the function
* @throws moodle_exception
*/
protected static function call($function, array $data = [], $allowpublic = false) {
$token = registration::get_token() ?: 'publichub';
if (!$allowpublic && $token === 'publichub') {
// This will throw an exception.
registration::require_registration();
}
if (extension_loaded('xmlrpc')) {
// Use XMLRPC protocol.
return self::call_xmlrpc($token, $function, $data);
} else {
// Use REST.
return self::call_rest($token, $function, $data);
}
}
/**
* Performs REST request to moodle.net (using GET method)
*
* @param string $token
* @param string $function
* @param array $data
* @return mixed
* @throws moodle_exception
*/
protected static function call_xmlrpc($token, $function, array $data) {
global $CFG;
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
$serverurl = HUB_MOODLEORGHUBURL . "/local/hub/webservice/webservices.php";
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $token);
try {
return $xmlrpcclient->call($function, $data);
} catch (\Exception $e) {
// Function webservice_xmlrpc_client::call() can throw Exception, wrap it into moodle_exception.
throw new moodle_exception('errorws', 'hub', '', $e->getMessage());
}
}
/**
* Performs REST request to moodle.net (using GET method)
*
* @param string $token
* @param string $function
* @param array $data
* @return mixed
* @throws moodle_exception
*/
protected static function call_rest($token, $function, array $data) {
$params = [
'wstoken' => $token,
'wsfunction' => $function,
'moodlewsrestformat' => 'json'
] + $data;
$curl = new curl();
$serverurl = HUB_MOODLEORGHUBURL . "/local/hub/webservice/webservices.php";
$curloutput = @json_decode($curl->get($serverurl, $params), true);
$info = $curl->get_info();
if ($curl->get_errno()) {
throw new moodle_exception('errorconnect', 'hub', '', $curl->error);
} else if (isset($curloutput['exception'])) {
// Error message returned by web service.
throw new moodle_exception('errorws', 'hub', '', $curloutput['message']);
} else if ($info['http_code'] != 200) {
throw new moodle_exception('errorconnect', 'hub', '', $info['http_code']);
} else {
return $curloutput;
}
}
/**
* Update site registration on moodle.net
*
* @param array $siteinfo
* @throws moodle_exception
*/
public static function update_registration(array $siteinfo) {
$params = array('siteinfo' => $siteinfo);
self::call('hub_update_site_info', $params);
}
/**
* Returns information about moodle.net
*
* Example of the return array:
* {
* "courses": 384,
* "description": "Moodle.net connects you with free content and courses shared by Moodle ...",
* "downloadablecourses": 190,
* "enrollablecourses": 194,
* "hublogo": 1,
* "language": "en",
* "name": "Moodle.net",
* "sites": 274175,
* "url": "https://moodle.net",
* "imgurl": "https://moodle.net/local/hub/webservice/download.php?filetype=hubscreenshot"
* }
*
* @return array
* @throws moodle_exception
*/
public static function get_hub_info() {
$info = self::call('hub_get_info', [], true);
$info['imgurl'] = new moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/webservice/download.php',
['filetype' => self::HUB_HUBSCREENSHOT_FILE_TYPE]);
return $info;
}
/**
* Calls WS function hub_get_courses
*
* Parameter $options may have any of these fields:
* [
* 'ids' => new external_multiple_structure(new external_value(PARAM_INTEGER, 'id of a course in the hub course
* directory'), 'ids of course', VALUE_OPTIONAL),
* 'sitecourseids' => new external_multiple_structure(new external_value(PARAM_INTEGER, 'id of a course in the
* site'), 'ids of course in the site', VALUE_OPTIONAL),
* 'coverage' => new external_value(PARAM_TEXT, 'coverage', VALUE_OPTIONAL),
* 'licenceshortname' => new external_value(PARAM_ALPHANUMEXT, 'licence short name', VALUE_OPTIONAL),
* 'subject' => new external_value(PARAM_ALPHANUM, 'subject', VALUE_OPTIONAL),
* 'audience' => new external_value(PARAM_ALPHA, 'audience', VALUE_OPTIONAL),
* 'educationallevel' => new external_value(PARAM_ALPHA, 'educational level', VALUE_OPTIONAL),
* 'language' => new external_value(PARAM_ALPHANUMEXT, 'language', VALUE_OPTIONAL),
* 'orderby' => new external_value(PARAM_ALPHA, 'orderby method: newest, eldest, publisher, fullname,
* ratingaverage', VALUE_OPTIONAL),
* 'givememore' => new external_value(PARAM_INT, 'next range of result - range size being set by the hub
* server ', VALUE_OPTIONAL),
* 'allsitecourses' => new external_value(PARAM_INTEGER,
* 'if 1 return all not visible and visible courses whose siteid is the site
* matching token. Only courses of this site are returned.
* givememore parameter is ignored if this param = 1.
* In case of public token access, this param option is ignored', VALUE_DEFAULT, 0),
* ]
*
* Each course in the returned array of courses will have fields:
* [
* 'id' => new external_value(PARAM_INTEGER, 'id'),
* 'fullname' => new external_value(PARAM_TEXT, 'course name'),
* 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
* 'description' => new external_value(PARAM_TEXT, 'course description'),
* 'language' => new external_value(PARAM_ALPHANUMEXT, 'course language'),
* 'publishername' => new external_value(PARAM_TEXT, 'publisher name'),
* 'publisheremail' => new external_value(PARAM_EMAIL, 'publisher email', VALUE_OPTIONAL),
* 'privacy' => new external_value(PARAM_INT, 'privacy: published or not', VALUE_OPTIONAL),
* 'sitecourseid' => new external_value(PARAM_INT, 'course id on the site', VALUE_OPTIONAL),
* 'contributornames' => new external_value(PARAM_TEXT, 'contributor names', VALUE_OPTIONAL),
* 'coverage' => new external_value(PARAM_TEXT, 'coverage', VALUE_OPTIONAL),
* 'creatorname' => new external_value(PARAM_TEXT, 'creator name'),
* 'licenceshortname' => new external_value(PARAM_ALPHANUMEXT, 'licence short name'),
* 'subject' => new external_value(PARAM_ALPHANUM, 'subject'),
* 'audience' => new external_value(PARAM_ALPHA, 'audience'),
* 'educationallevel' => new external_value(PARAM_ALPHA, 'educational level'),
* 'creatornotes' => new external_value(PARAM_RAW, 'creator notes'),
* 'creatornotesformat' => new external_value(PARAM_INTEGER, 'notes format'),
* 'demourl' => new external_value(PARAM_URL, 'demo URL', VALUE_OPTIONAL),
* 'courseurl' => new external_value(PARAM_URL, 'course URL', VALUE_OPTIONAL),
* 'backupsize' => new external_value(PARAM_INT, 'course backup size in bytes', VALUE_OPTIONAL),
* 'enrollable' => new external_value(PARAM_BOOL, 'is the course enrollable'),
* 'screenshots' => new external_value(PARAM_INT, 'total number of screenshots'),
* 'timemodified' => new external_value(PARAM_INT, 'time of last modification - timestamp'),
* 'contents' => new external_multiple_structure(new external_single_structure(
* array(
* 'moduletype' => new external_value(PARAM_ALPHA, 'the type of module (activity/block)'),
* 'modulename' => new external_value(PARAM_TEXT, 'the name of the module (forum, resource etc)'),
* 'contentcount' => new external_value(PARAM_INT, 'how many time the module is used in the course'),
* )), 'contents', VALUE_OPTIONAL),
* 'rating' => new external_single_structure (
* array(
* 'aggregate' => new external_value(PARAM_FLOAT, 'Rating average', VALUE_OPTIONAL),
* 'scaleid' => new external_value(PARAM_INT, 'Rating scale'),
* 'count' => new external_value(PARAM_INT, 'Rating count'),
* ), 'rating', VALUE_OPTIONAL),
* 'comments' => new external_multiple_structure(new external_single_structure (
* array(
* 'comment' => new external_value(PARAM_TEXT, 'the comment'),
* 'commentator' => new external_value(PARAM_TEXT, 'the name of commentator'),
* 'date' => new external_value(PARAM_INT, 'date of the comment'),
* )), 'contents', VALUE_OPTIONAL),
* 'outcomes' => new external_multiple_structure(new external_single_structure(
* array(
* 'fullname' => new external_value(PARAM_TEXT, 'the outcome fullname')
* )), 'outcomes', VALUE_OPTIONAL)
* ]
*
* Additional fields for each course:
* 'screenshotbaseurl' (moodle_url) URL of the first screenshot, only set if $course['screenshots']>0
* 'commenturl' (moodle_url) URL for comments
*
* @param string $search search string
* @param bool $downloadable return downloadable courses
* @param bool $enrollable 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]
* @throws \coding_exception
* @throws moodle_exception
*/
public static function get_courses($search, $downloadable, $enrollable, $options) {
static $availableoptions = ['ids', 'sitecourseids', 'coverage', 'licenceshortname', 'subject', 'audience',
'educationallevel', 'language', 'orderby', 'givememore', 'allsitecourses'];
if (empty($options)) {
$options = [];
} else if (is_object($options)) {
$options = (array)$options;
} else if (!is_array($options)) {
throw new \coding_exception('Parameter $options is invalid');
}
if ($unknownkeys = array_diff(array_keys($options), $availableoptions)) {
throw new \coding_exception('Unknown option(s): ' . join(', ', $unknownkeys));
}
$params = [
'search' => $search,
'downloadable' => (int)(bool)$downloadable,
'enrollable' => (int)(bool)$enrollable,
'options' => $options
];
$result = self::call('hub_get_courses', $params, true);
$courses = $result['courses'];
$coursetotal = $result['coursetotal'];
foreach ($courses as $idx => $course) {
$courses[$idx]['screenshotbaseurl'] = null;
if (!empty($course['screenshots'])) {
$courses[$idx]['screenshotbaseurl'] = new moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/webservice/download.php',
array('courseid' => $course['id'],
'filetype' => self::HUB_SCREENSHOT_FILE_TYPE));
}
$courses[$idx]['commenturl'] = new moodle_url(HUB_MOODLEORGHUBURL,
array('courseid' => $course['id'], 'mustbelogged' => true));
}
return [$courses, $coursetotal];
}
/**
* Unregister the site
*
* @throws moodle_exception
*/
public static function unregister_site() {
self::call('hub_unregister_site');
}
/**
* Unpublish courses
*
* @param int[]|int $courseids
* @throws moodle_exception
*/
public static function unregister_courses($courseids) {
$courseids = (array)$courseids;
$params = array('courseids' => $courseids);
self::call('hub_unregister_courses', $params);
}
/**
* Publish one course
*
* Expected contents of $courseinfo:
* [
* 'sitecourseid' => new external_value(PARAM_INT, 'the id of the course on the publishing site'),
* 'fullname' => new external_value(PARAM_TEXT, 'course name'),
* 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
* 'description' => new external_value(PARAM_TEXT, 'course description'),
* 'language' => new external_value(PARAM_ALPHANUMEXT, 'course language'),
* 'publishername' => new external_value(PARAM_TEXT, 'publisher name'),
* 'publisheremail' => new external_value(PARAM_EMAIL, 'publisher email'),
* 'contributornames' => new external_value(PARAM_TEXT, 'contributor names'),
* 'coverage' => new external_value(PARAM_TEXT, 'coverage'),
* 'creatorname' => new external_value(PARAM_TEXT, 'creator name'),
* 'licenceshortname' => new external_value(PARAM_ALPHANUMEXT, 'licence short name'),
* 'subject' => new external_value(PARAM_ALPHANUM, 'subject'),
* 'audience' => new external_value(PARAM_ALPHA, 'audience'),
* 'educationallevel' => new external_value(PARAM_ALPHA, 'educational level'),
* 'creatornotes' => new external_value(PARAM_RAW, 'creator notes'),
* 'creatornotesformat' => new external_value(PARAM_INTEGER, 'notes format'),
* 'demourl' => new external_value(PARAM_URL, 'demo URL', VALUE_OPTIONAL),
* 'courseurl' => new external_value(PARAM_URL, 'course URL', VALUE_OPTIONAL),
* 'enrollable' => new external_value(PARAM_BOOL, 'is the course enrollable', VALUE_DEFAULT, 0),
* 'screenshots' => new external_value(PARAM_INT, 'the number of screenhots', VALUE_OPTIONAL),
* 'deletescreenshots' => new external_value(PARAM_INT, 'ask to delete all the existing screenshot files
* (it does not reset the screenshot number)', VALUE_DEFAULT, 0),
* 'contents' => new external_multiple_structure(new external_single_structure(
* array(
* 'moduletype' => new external_value(PARAM_ALPHA, 'the type of module (activity/block)'),
* 'modulename' => new external_value(PARAM_TEXT, 'the name of the module (forum, resource etc)'),
* 'contentcount' => new external_value(PARAM_INT, 'how many time the module is used in the course'),
* )), 'contents', VALUE_OPTIONAL),
* 'outcomes' => new external_multiple_structure(new external_single_structure(
* array(
* 'fullname' => new external_value(PARAM_TEXT, 'the outcome fullname')
* )), 'outcomes', VALUE_OPTIONAL)
* ]
*
* @param array|\stdClass $courseinfo
* @return int id of the published course on the hub
* @throws moodle_exception if communication to moodle.net failed or course could not be published
*/
public static function register_course($courseinfo) {
$params = array('courses' => array($courseinfo));
$hubcourseids = self::call('hub_register_courses', $params);
if (count($hubcourseids) != 1) {
throw new moodle_exception('errorcoursewronglypublished', 'hub');
}
return $hubcourseids[0];
}
/**
* Uploads a screenshot for the published course
*
* @param int $hubcourseid id of the published course on moodle.net, it must be published from this site
* @param \stored_file $file
* @param int $screenshotnumber ordinal number of the screenshot
*/
public static function add_screenshot($hubcourseid, \stored_file $file, $screenshotnumber) {
$curl = new \curl();
$params = array();
$params['filetype'] = self::HUB_SCREENSHOT_FILE_TYPE;
$params['file'] = $file;
$params['courseid'] = $hubcourseid;
$params['filename'] = $file->get_filename();
$params['screenshotnumber'] = $screenshotnumber;
$params['token'] = registration::get_token(MUST_EXIST);
$curl->post(HUB_MOODLEORGHUBURL . "/local/hub/webservice/upload.php", $params);
}
/**
* Downloads course backup
*
* @param int $hubcourseid id of the course on moodle.net
* @param string $path local path (in tempdir) to save the downloaded backup to.
*/
public static function download_course_backup($hubcourseid, $path) {
$fp = fopen($path, 'w');
$curlurl = new \moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/webservice/download.php',
['filetype' => self::HUB_BACKUP_FILE_TYPE, 'courseid' => $hubcourseid]);
// Send an identification token if the site is registered.
if ($token = registration::get_token()) {
$curlurl->param('token', $token);
}
$ch = curl_init($curlurl->out(false));
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
curl_close($ch);
fclose($fp);
}
/**
* 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) {
$curl = new \curl();
$params = array();
$params['filetype'] = self::HUB_BACKUP_FILE_TYPE;
$params['courseid'] = $hubcourseid;
$params['file'] = $backupfile;
$params['token'] = registration::get_token();
$curl->post(HUB_MOODLEORGHUBURL . '/local/hub/webservice/upload.php', $params);
}
}
+308
View File
@@ -0,0 +1,308 @@
<?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 course_publication_form
*
* @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 stdClass;
use license_manager;
use moodle_url;
use core_collator;
global $CFG;
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->libdir . '/licenselib.php');
/**
* The forms used for course publication
*
* @package core
* @copyright 2017 Marina Glancy
* @author Jerome Mouneyrac <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_publication_form extends \moodleform {
/**
* Form definition
*/
public function definition() {
global $CFG, $USER, $PAGE;
$strrequired = get_string('required');
$mform = & $this->_form;
$course = $this->_customdata['course'];
if (!empty($this->_customdata['publication'])) {
// We are editing existing publication.
$publication = $this->_customdata['publication'];
$advertise = $publication->enrollable;
$publishedcourse = publication::get_published_course($publication);
} else {
$publication = null;
$advertise = $this->_customdata['advertise'];
}
$share = !$advertise;
if (!empty($publishedcourse)) {
$hubcourseid = $publishedcourse['id'];
$defaultfullname = $publishedcourse['fullname'];
$defaultshortname = $publishedcourse['shortname'];
$defaultsummary = $publishedcourse['description'];
$defaultlanguage = $publishedcourse['language'];
$defaultpublishername = $publishedcourse['publishername'];
$defaultpublisheremail = $publishedcourse['publisheremail'];
$defaultcontributornames = $publishedcourse['contributornames'];
$defaultcoverage = $publishedcourse['coverage'];
$defaultcreatorname = $publishedcourse['creatorname'];
$defaultlicenceshortname = $publishedcourse['licenceshortname'];
$defaultsubject = $publishedcourse['subject'];
$defaultaudience = $publishedcourse['audience'];
$defaulteducationallevel = $publishedcourse['educationallevel'];
$defaultcreatornotes = $publishedcourse['creatornotes'];
$defaultcreatornotesformat = $publishedcourse['creatornotesformat'];
$screenshotsnumber = $publishedcourse['screenshots'];
$screenshotbaseurl = $publishedcourse['screenshotbaseurl'];
$privacy = $publishedcourse['privacy'];
if (($screenshotsnumber > 0) and !empty($privacy)) {
$PAGE->requires->yui_module('moodle-block_community-imagegallery',
'M.blocks_community.init_imagegallery',
array(array('imageids' => array($hubcourseid),
'imagenumbers' => array($screenshotsnumber),
'huburl' => HUB_MOODLEORGHUBURL)));
}
} else {
$defaultfullname = $course->fullname;
$defaultshortname = $course->shortname;
$defaultsummary = clean_param($course->summary, PARAM_TEXT);
if (empty($course->lang)) {
$language = get_site()->lang;
if (empty($language)) {
$defaultlanguage = current_language();
} else {
$defaultlanguage = $language;
}
} else {
$defaultlanguage = $course->lang;
}
$defaultpublishername = $USER->firstname . ' ' . $USER->lastname;
$defaultpublisheremail = $USER->email;
$defaultcontributornames = '';
$defaultcoverage = '';
$defaultcreatorname = $USER->firstname . ' ' . $USER->lastname;
$defaultlicenceshortname = 'cc';
$defaultsubject = 'none';
$defaultaudience = publication::HUB_AUDIENCE_STUDENTS;
$defaulteducationallevel = publication::HUB_EDULEVEL_TERTIARY;
$defaultcreatornotes = '';
$defaultcreatornotesformat = FORMAT_HTML;
$screenshotsnumber = 0;
$screenshotbaseurl = null;
}
// The input parameters.
$mform->addElement('header', 'moodle', get_string('publicationinfo', 'hub'));
$mform->addElement('text', 'name', get_string('coursename', 'hub'),
array('class' => 'metadatatext'));
$mform->addRule('name', $strrequired, 'required', null, 'client');
$mform->setType('name', PARAM_TEXT);
$mform->setDefault('name', $defaultfullname);
$mform->addHelpButton('name', 'name', 'hub');
$mform->addElement('hidden', 'id', $course->id);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'publicationid', $publication ? $publication->id : null);
$mform->setType('publicationid', PARAM_INT);
if ($share) {
$buttonlabel = get_string('shareon', 'hub', 'Moodle.net');
$mform->addElement('hidden', 'share', $share);
$mform->setType('share', PARAM_BOOL);
$mform->addElement('text', 'demourl', get_string('demourl', 'hub'),
array('class' => 'metadatatext'));
$mform->setType('demourl', PARAM_URL);
$mform->setDefault('demourl', new moodle_url("/course/view.php?id=" . $course->id));
$mform->addHelpButton('demourl', 'demourl', 'hub');
}
if ($advertise) {
if (!$publication) {
$buttonlabel = get_string('advertiseon', 'hub', 'Moodle.net');
} else {
$buttonlabel = get_string('readvertiseon', 'hub', 'Moodle.net');
}
$mform->addElement('hidden', 'advertise', $advertise);
$mform->setType('advertise', PARAM_BOOL);
$mform->addElement('hidden', 'courseurl', $CFG->wwwroot . "/course/view.php?id=" . $course->id);
$mform->setType('courseurl', PARAM_URL);
$mform->addElement('static', 'courseurlstring', get_string('courseurl', 'hub'));
$mform->setDefault('courseurlstring', new moodle_url("/course/view.php?id=" . $course->id));
$mform->addHelpButton('courseurlstring', 'courseurl', 'hub');
}
$mform->addElement('text', 'courseshortname', get_string('courseshortname', 'hub'),
array('class' => 'metadatatext'));
$mform->setDefault('courseshortname', $defaultshortname);
$mform->addHelpButton('courseshortname', 'courseshortname', 'hub');
$mform->setType('courseshortname', PARAM_TEXT);
$mform->addElement('textarea', 'description', get_string('description', 'hub'), array('rows' => 10,
'cols' => 57));
$mform->addRule('description', $strrequired, 'required', null, 'client');
$mform->setDefault('description', $defaultsummary);
$mform->setType('description', PARAM_TEXT);
$mform->addHelpButton('description', 'description', 'hub');
$languages = get_string_manager()->get_list_of_languages();
core_collator::asort($languages);
$mform->addElement('select', 'language', get_string('language'), $languages);
$mform->setDefault('language', $defaultlanguage);
$mform->addHelpButton('language', 'language', 'hub');
$mform->addElement('text', 'publishername', get_string('publishername', 'hub'),
array('class' => 'metadatatext'));
$mform->setDefault('publishername', $defaultpublishername);
$mform->addRule('publishername', $strrequired, 'required', null, 'client');
$mform->addHelpButton('publishername', 'publishername', 'hub');
$mform->setType('publishername', PARAM_NOTAGS);
$mform->addElement('text', 'publisheremail', get_string('publisheremail', 'hub'),
array('class' => 'metadatatext'));
$mform->setDefault('publisheremail', $defaultpublisheremail);
$mform->addRule('publisheremail', $strrequired, 'required', null, 'client');
$mform->addHelpButton('publisheremail', 'publisheremail', 'hub');
$mform->setType('publisheremail', PARAM_EMAIL);
$mform->addElement('text', 'creatorname', get_string('creatorname', 'hub'),
array('class' => 'metadatatext'));
$mform->addRule('creatorname', $strrequired, 'required', null, 'client');
$mform->setType('creatorname', PARAM_NOTAGS);
$mform->setDefault('creatorname', $defaultcreatorname);
$mform->addHelpButton('creatorname', 'creatorname', 'hub');
$mform->addElement('text', 'contributornames', get_string('contributornames', 'hub'),
array('class' => 'metadatatext'));
$mform->setDefault('contributornames', $defaultcontributornames);
$mform->addHelpButton('contributornames', 'contributornames', 'hub');
$mform->setType('contributornames', PARAM_NOTAGS);
$mform->addElement('text', 'coverage', get_string('tags', 'hub'),
array('class' => 'metadatatext'));
$mform->setType('coverage', PARAM_TEXT);
$mform->setDefault('coverage', $defaultcoverage);
$mform->addHelpButton('coverage', 'tags', 'hub');
$licensemanager = new license_manager();
$licences = $licensemanager->get_licenses();
$options = array();
foreach ($licences as $license) {
$options[$license->shortname] = get_string($license->shortname, 'license');
}
$mform->addElement('select', 'licence', get_string('license'), $options);
$mform->setDefault('licence', $defaultlicenceshortname);
unset($options);
$mform->addHelpButton('licence', 'licence', 'hub');
$options = publication::get_sorted_subjects();
$mform->addElement('searchableselector', 'subject',
get_string('subject', 'hub'), $options);
unset($options);
$mform->addHelpButton('subject', 'subject', 'hub');
$mform->setDefault('subject', $defaultsubject);
$mform->addRule('subject', $strrequired, 'required', null, 'client');
$options = publication::audience_options();
$mform->addElement('select', 'audience', get_string('audience', 'hub'), $options);
$mform->setDefault('audience', $defaultaudience);
unset($options);
$mform->addHelpButton('audience', 'audience', 'hub');
$options = publication::educational_level_options();
$mform->addElement('select', 'educationallevel', get_string('educationallevel', 'hub'), $options);
$mform->setDefault('educationallevel', $defaulteducationallevel);
unset($options);
$mform->addHelpButton('educationallevel', 'educationallevel', 'hub');
$editoroptions = array('maxfiles' => 0, 'maxbytes' => 0, 'trusttext' => false, 'forcehttps' => false);
$mform->addElement('editor', 'creatornotes', get_string('creatornotes', 'hub'), '', $editoroptions);
$mform->addRule('creatornotes', $strrequired, 'required', null, 'client');
$mform->setType('creatornotes', PARAM_CLEANHTML);
$mform->addHelpButton('creatornotes', 'creatornotes', 'hub');
if ($advertise) {
if (!empty($screenshotsnumber)) {
if (!empty($privacy)) {
$screenshothtml = \html_writer::empty_tag('img',
array('src' => $screenshotbaseurl, 'alt' => $defaultfullname));
$screenshothtml = \html_writer::tag('div', $screenshothtml,
array('class' => 'coursescreenshot',
'id' => 'image-' . $hubcourseid));
} else {
$screenshothtml = get_string('existingscreenshotnumber', 'hub', $screenshotsnumber);
}
$mform->addElement('static', 'existingscreenshots', get_string('existingscreenshots', 'hub'), $screenshothtml);
$mform->addHelpButton('existingscreenshots', 'deletescreenshots', 'hub');
$mform->addElement('checkbox', 'deletescreenshots', '', ' ' . get_string('deletescreenshots', 'hub'));
}
$mform->addElement('hidden', 'existingscreenshotnumber', $screenshotsnumber);
$mform->setType('existingscreenshotnumber', PARAM_INT);
}
$mform->addElement('filemanager', 'screenshots', get_string('addscreenshots', 'hub'), null,
array('subdirs' => 0,
'maxbytes' => 1000000,
'maxfiles' => 3
));
$mform->addHelpButton('screenshots', 'screenshots', 'hub');
$this->add_action_buttons(false, $buttonlabel);
// Set default value for creatornotes editor.
$data = new stdClass();
$data->creatornotes = array();
$data->creatornotes['text'] = $defaultcreatornotes;
$data->creatornotes['format'] = $defaultcreatornotesformat;
$this->set_data($data);
}
/**
* Custom form validation
*
* @param array $data
* @param array $files
* @return array
*/
public function validation($data, $files) {
$errors = parent::validation($data, $files);
if ($this->_form->_submitValues['subject'] == 'none') {
$errors['subject'] = get_string('mustselectsubject', 'hub');
}
return $errors;
}
}
+409
View File
@@ -0,0 +1,409 @@
<?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 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");
make_temp_directory('backup');
$filename = md5(time() . '-' . $hubcourseid . '-'. $USER->id . '-'. random_string(20));
$path = $CFG->tempdir.'/backup/'.$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);
}
}
+410
View File
@@ -0,0 +1,410 @@
<?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 registration
*
* @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_system;
use stdClass;
/**
* Methods to use when publishing and searching courses on moodle.net
*
* @package core
* @copyright 2017 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class registration {
/** @var Fields used in a site registration form */
const FORM_FIELDS = ['name', 'description', 'contactname', 'contactemail', 'contactphone', 'imageurl', 'privacy', 'street',
'regioncode', 'countrycode', 'geolocation', 'contactable', 'emailalert', 'language'];
/** @var Site privacy: not displayed */
const HUB_SITENOTPUBLISHED = 'notdisplayed';
/** @var Site privacy: public */
const HUB_SITENAMEPUBLISHED = 'named';
/** @var Site privacy: public and global */
const HUB_SITELINKPUBLISHED = 'linked';
/** @var stdClass cached site registration information */
protected static $registration = null;
/**
* Get site registration
*
* @param bool $confirmed
* @return stdClass|null
*/
protected static function get_registration($confirmed = true) {
global $DB;
if (self::$registration === null) {
self::$registration = $DB->get_record('registration_hubs', ['huburl' => HUB_MOODLEORGHUBURL]);
}
if (self::$registration && (bool)self::$registration->confirmed == (bool)$confirmed) {
return self::$registration;
}
return null;
}
/**
* Same as get_registration except it throws exception if site not registered
*
* @return stdClass
* @throws \moodle_exception
*/
public static function require_registration() {
if ($registration = self::get_registration()) {
return $registration;
}
if (has_capability('moodle/site:config', context_system::instance())) {
throw new moodle_exception('registrationwarning', 'admin', new moodle_url('/admin/registration/index.php'));
} else {
throw new moodle_exception('registrationwarningcontactadmin', 'admin');
}
}
/**
* Checks if site is registered
*
* @return bool
*/
public static function is_registered() {
return self::get_registration() ? true : false;
}
/**
* Returns registration token
*
* @param int $strictness if set to MUST_EXIST and site is not registered will throw an exception
* @return null
* @throws moodle_exception
*/
public static function get_token($strictness = IGNORE_MISSING) {
if ($strictness == MUST_EXIST) {
$registration = self::require_registration();
} else if (!$registration = self::get_registration()) {
return null;
}
return $registration->token;
}
/**
* When was the registration last updated
*
* @return int|null timestamp or null if site is not registered
*/
public static function get_last_updated() {
if ($registration = self::get_registration()) {
return $registration->timemodified;
}
return null;
}
/**
* Calculates and prepares site information to send to moodle.net as part of registration or update
*
* @param array $defaults default values for inputs in the registration form (if site was never registered before)
* @return array site info
*/
public static function get_site_info($defaults = []) {
global $CFG, $DB;
require_once($CFG->libdir . '/badgeslib.php');
require_once($CFG->dirroot . "/course/lib.php");
$siteinfo = array();
$cleanhuburl = clean_param(HUB_MOODLEORGHUBURL, PARAM_ALPHANUMEXT);
foreach (self::FORM_FIELDS as $field) {
$siteinfo[$field] = get_config('hub', 'site_'.$field.'_' . $cleanhuburl);
if ($siteinfo[$field] === false && array_key_exists($field, $defaults)) {
$siteinfo[$field] = $defaults[$field];
}
}
// Statistical data.
$siteinfo['courses'] = $DB->count_records('course') - 1;
$siteinfo['users'] = $DB->count_records('user', array('deleted' => 0));
$siteinfo['enrolments'] = $DB->count_records('role_assignments');
$siteinfo['posts'] = $DB->count_records('forum_posts');
$siteinfo['questions'] = $DB->count_records('question');
$siteinfo['resources'] = $DB->count_records('resource');
$siteinfo['badges'] = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
$siteinfo['issuedbadges'] = $DB->count_records('badge_issued');
$siteinfo['participantnumberaverage'] = average_number_of_participants();
$siteinfo['modulenumberaverage'] = average_number_of_courses_modules();
// Version and url.
$siteinfo['moodleversion'] = $CFG->version;
$siteinfo['moodlerelease'] = $CFG->release;
$siteinfo['url'] = $CFG->wwwroot;
// Mobile related information.
$siteinfo['mobileservicesenabled'] = 0;
$siteinfo['mobilenotificationsenabled'] = 0;
$siteinfo['registereduserdevices'] = 0;
$siteinfo['registeredactiveuserdevices'] = 0;
if (!empty($CFG->enablewebservices) && !empty($CFG->enablemobilewebservice)) {
$siteinfo['mobileservicesenabled'] = 1;
$siteinfo['registereduserdevices'] = $DB->count_records('user_devices');
$airnotifierextpath = $CFG->dirroot . '/message/output/airnotifier/externallib.php';
if (file_exists($airnotifierextpath)) { // Maybe some one uninstalled the plugin.
require_once($airnotifierextpath);
$siteinfo['mobilenotificationsenabled'] = \message_airnotifier_external::is_system_configured();
$siteinfo['registeredactiveuserdevices'] = $DB->count_records('message_airnotifier_devices', array('enable' => 1));
}
}
return $siteinfo;
}
/**
* Save registration info locally so it can be retrieved when registration needs to be updated
*
* @param stdClass $formdata data from {@link site_registration_form}
*/
public static function save_site_info($formdata) {
$cleanhuburl = clean_param(HUB_MOODLEORGHUBURL, PARAM_ALPHANUMEXT);
foreach (self::FORM_FIELDS as $field) {
set_config('site_' . $field . '_' . $cleanhuburl, $formdata->$field, 'hub');
}
}
/**
* Updates site registration when "Update reigstration" button is clicked by admin
*/
public static function update_manual() {
global $DB;
if (!$registration = self::get_registration()) {
return false;
}
$siteinfo = self::get_site_info();
try {
api::update_registration($siteinfo);
} catch (moodle_exception $e) {
\core\notification::add(get_string('errorregistrationupdate', 'hub', $e->getMessage()),
\core\output\notification::NOTIFY_ERROR);
return false;
}
$DB->update_record('registration_hubs', ['id' => $registration->id, 'timemodified' => time()]);
\core\notification::add(get_string('siteregistrationupdated', 'hub'),
\core\output\notification::NOTIFY_SUCCESS);
self::$registration = null;
return true;
}
/**
* Updates site registration via cron
*
* @throws moodle_exception
*/
public static function update_cron() {
global $DB;
if (!$registration = self::get_registration()) {
mtrace(get_string('registrationwarning', 'admin'));
return;
}
$siteinfo = self::get_site_info();
api::update_registration($siteinfo);
$DB->update_record('registration_hubs', ['id' => $registration->id, 'timemodified' => time()]);
mtrace(get_string('siteregistrationupdated', 'hub'));
self::$registration = null;
}
/**
* Confirms registration by moodle.net
*
* @param string $token
* @param string $newtoken
* @param string $hubname
* @throws moodle_exception
*/
public static function confirm_registration($token, $newtoken, $hubname) {
global $DB;
$registration = self::get_registration(false);
if (!$registration || $registration->token !== $token) {
throw new moodle_exception('wrongtoken', 'hub', new moodle_url('/admin/registration/index.php'));
}
$record = ['id' => $registration->id];
$record['token'] = $newtoken;
$record['confirmed'] = 1;
$record['hubname'] = $hubname;
$record['timemodified'] = time();
$DB->update_record('registration_hubs', $record);
self::$registration = null;
}
/**
* Retrieve the options for site privacy form element to use in registration form
* @return array
*/
public static function site_privacy_options() {
return [
self::HUB_SITENOTPUBLISHED => get_string('siteprivacynotpublished', 'hub'),
self::HUB_SITENAMEPUBLISHED => get_string('siteprivacypublished', 'hub'),
self::HUB_SITELINKPUBLISHED => get_string('siteprivacylinked', 'hub')
];
}
/**
* Registers a site
*
* This method will make sure that unconfirmed registration record is created and then redirect to
* registration script on https://moodle.net
* Moodle.net will check that the site is accessible, register it and redirect back
* to /admin/registration/confirmregistration.php
*
* @throws \coding_exception
*/
public static function register() {
global $DB;
if (self::is_registered()) {
// Caller of this method must make sure that site is not registered.
throw new \coding_exception('Site already registered');
}
$hub = self::get_registration(false);
if (empty($hub)) {
// Create a new record in 'registration_hubs'.
$hub = new stdClass();
$hub->token = get_site_identifier();
$hub->secret = $hub->token;
$hub->huburl = HUB_MOODLEORGHUBURL;
$hub->hubname = 'Moodle.net';
$hub->confirmed = 0;
$hub->timemodified = time();
$hub->id = $DB->insert_record('registration_hubs', $hub);
self::$registration = null;
}
$params = self::get_site_info();
$params['token'] = $hub->token;
redirect(new moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/siteregistration.php', $params));
}
/**
* Unregister site
*
* @param bool $unpublishalladvertisedcourses
* @param bool $unpublishalluploadedcourses
* @return bool
*/
public static function unregister($unpublishalladvertisedcourses, $unpublishalluploadedcourses) {
global $DB;
if (!$hub = self::get_registration()) {
return true;
}
// Unpublish the courses.
try {
publication::delete_all_publications($unpublishalladvertisedcourses, $unpublishalluploadedcourses);
} catch (moodle_exception $e) {
$errormessage = $e->getMessage();
$errormessage .= \html_writer::empty_tag('br') .
get_string('errorunpublishcourses', 'hub');
\core\notification::add(get_string('unregistrationerror', 'hub', $errormessage),
\core\output\notification::NOTIFY_ERROR);
return false;
}
// Course unpublish went ok, unregister the site now.
try {
api::unregister_site();
} catch (moodle_exception $e) {
\core\notification::add(get_string('unregistrationerror', 'hub', $e->getMessage()),
\core\output\notification::NOTIFY_ERROR);
return false;
}
$DB->delete_records('registration_hubs', array('id' => $hub->id));
self::$registration = null;
return true;
}
/**
* Generate a new token for the site that is not registered
*
* @param string $token
* @throws moodle_exception
*/
public static function reset_site_identifier($token) {
global $DB, $CFG;
$registration = self::get_registration(false);
if (!$registration || $registration->token != $token) {
throw new moodle_exception('wrongtoken', 'hub',
new moodle_url('/admin/registration/index.php'));
}
$DB->delete_records('registration_hubs', array('id' => $registration->id));
self::$registration = null;
$CFG->siteidentifier = null;
get_site_identifier();
}
/**
* Returns information about moodle.net
*
* Example of the return array:
* {
* "courses": 384,
* "description": "Moodle.net connects you with free content and courses shared by Moodle ...",
* "downloadablecourses": 190,
* "enrollablecourses": 194,
* "hublogo": 1,
* "language": "en",
* "name": "Moodle.net",
* "sites": 274175,
* "url": "https://moodle.net",
* "imgurl": moodle_url : "https://moodle.net/local/hub/webservice/download.php?filetype=hubscreenshot"
* }
*
* @return array|null
*/
public static function get_moodlenet_info() {
try {
return api::get_hub_info();
} catch (moodle_exception $e) {
// Ignore error, we only need it for displaying information about moodle.net, if this request
// fails, it's not a big deal.
return null;
}
}
}
+226
View File
@@ -0,0 +1,226 @@
<?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 site_registration_form
*
* @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 context_course;
global $CFG;
require_once($CFG->libdir . '/formslib.php');
/**
* The site registration form. Information will be sent to moodle.net
*
* @author Jerome Mouneyrac <[email protected]>
* @package core
* @copyright 2017 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class site_registration_form extends \moodleform {
/**
* Form definition
*/
public function definition() {
global $CFG;
$strrequired = get_string('required');
$mform = & $this->_form;
$admin = get_admin();
$site = get_site();
$siteinfo = registration::get_site_info([
'name' => format_string($site->fullname, true, array('context' => context_course::instance(SITEID))),
'description' => $site->summary,
'contactname' => fullname($admin, true),
'contactemail' => $admin->email,
'contactphone' => $admin->phone1,
'street' => '',
'countrycode' => $admin->country ?: $CFG->country,
'regioncode' => '-', // Not supported yet.
'language' => explode('_', current_language())[0],
'geolocation' => '',
'emailalert' => 1,
]);
$mform->addElement('header', 'moodle', get_string('registrationinfo', 'hub'));
$mform->addElement('text', 'name', get_string('sitename', 'hub'),
array('class' => 'registration_textfield'));
$mform->addRule('name', $strrequired, 'required', null, 'client');
$mform->setType('name', PARAM_TEXT);
$mform->addHelpButton('name', 'sitename', 'hub');
$mform->addElement('select', 'privacy', get_string('siteprivacy', 'hub'), registration::site_privacy_options());
$mform->setType('privacy', PARAM_ALPHA);
$mform->addHelpButton('privacy', 'privacy', 'hub');
unset($options);
$mform->addElement('textarea', 'description', get_string('sitedesc', 'hub'),
array('rows' => 8, 'cols' => 41));
$mform->addRule('description', $strrequired, 'required', null, 'client');
$mform->setType('description', PARAM_TEXT);
$mform->addHelpButton('description', 'sitedesc', 'hub');
$languages = get_string_manager()->get_list_of_languages();
\core_collator::asort($languages);
$mform->addElement('select', 'language', get_string('sitelang', 'hub'), $languages);
$mform->setType('language', PARAM_ALPHANUMEXT);
$mform->addHelpButton('language', 'sitelang', 'hub');
$mform->addElement('textarea', 'street', get_string('postaladdress', 'hub'),
array('rows' => 4, 'cols' => 41));
$mform->setType('street', PARAM_TEXT);
$mform->addHelpButton('street', 'postaladdress', 'hub');
$mform->addElement('hidden', 'regioncode', '-');
$mform->setType('regioncode', PARAM_ALPHANUMEXT);
$countries = ['' => ''] + get_string_manager()->get_list_of_countries();
$mform->addElement('select', 'countrycode', get_string('sitecountry', 'hub'), $countries);
$mform->setType('countrycode', PARAM_ALPHANUMEXT);
$mform->addHelpButton('countrycode', 'sitecountry', 'hub');
$mform->addRule('countrycode', $strrequired, 'required', null, 'client');
$mform->addElement('text', 'geolocation', get_string('sitegeolocation', 'hub'),
array('class' => 'registration_textfield'));
$mform->setType('geolocation', PARAM_RAW);
$mform->addHelpButton('geolocation', 'sitegeolocation', 'hub');
$mform->addElement('text', 'contactname', get_string('siteadmin', 'hub'),
array('class' => 'registration_textfield'));
$mform->addRule('contactname', $strrequired, 'required', null, 'client');
$mform->setType('contactname', PARAM_TEXT);
$mform->addHelpButton('contactname', 'siteadmin', 'hub');
$mform->addElement('text', 'contactphone', get_string('sitephone', 'hub'),
array('class' => 'registration_textfield'));
$mform->setType('contactphone', PARAM_TEXT);
$mform->addHelpButton('contactphone', 'sitephone', 'hub');
$mform->setForceLtr('contactphone');
$mform->addElement('text', 'contactemail', get_string('siteemail', 'hub'),
array('class' => 'registration_textfield'));
$mform->addRule('contactemail', $strrequired, 'required', null, 'client');
$mform->setType('contactemail', PARAM_EMAIL);
$mform->addHelpButton('contactemail', 'siteemail', 'hub');
$options = array();
$options[0] = get_string("registrationcontactno");
$options[1] = get_string("registrationcontactyes");
$mform->addElement('select', 'contactable', get_string('siteregistrationcontact', 'hub'), $options);
$mform->setType('contactable', PARAM_INT);
$mform->addHelpButton('contactable', 'siteregistrationcontact', 'hub');
unset($options);
$options = array();
$options[0] = get_string("registrationno");
$options[1] = get_string("registrationyes");
$mform->addElement('select', 'emailalert', get_string('siteregistrationemail', 'hub'), $options);
$mform->setType('emailalert', PARAM_INT);
$mform->addHelpButton('emailalert', 'siteregistrationemail', 'hub');
unset($options);
// TODO site logo.
$mform->addElement('hidden', 'imageurl', ''); // TODO: temporary.
$mform->setType('imageurl', PARAM_URL);
$mform->addElement('static', 'urlstring', get_string('siteurl', 'hub'), $siteinfo['url']);
$mform->addHelpButton('urlstring', 'siteurl', 'hub');
$mform->addElement('static', 'versionstring', get_string('siteversion', 'hub'), $CFG->version);
$mform->addElement('hidden', 'moodleversion', $siteinfo['moodleversion']);
$mform->setType('moodleversion', PARAM_INT);
$mform->addHelpButton('versionstring', 'siteversion', 'hub');
$mform->addElement('static', 'releasestring', get_string('siterelease', 'hub'), $CFG->release);
$mform->addElement('hidden', 'moodlerelease', $siteinfo['moodlerelease']);
$mform->setType('moodlerelease', PARAM_TEXT);
$mform->addHelpButton('releasestring', 'siterelease', 'hub');
// Display statistic that are going to be retrieve by moodle.net.
$mform->addElement('static', 'courseslabel', get_string('sendfollowinginfo', 'hub'),
" " . get_string('coursesnumber', 'hub', $siteinfo['courses']));
$mform->addHelpButton('courseslabel', 'sendfollowinginfo', 'hub');
$mform->addElement('static', 'userslabel', '',
" " . get_string('usersnumber', 'hub', $siteinfo['users']));
$mform->addElement('static', 'roleassignmentslabel', '',
" " . get_string('roleassignmentsnumber', 'hub', $siteinfo['enrolments']));
$mform->addElement('static', 'postslabel', '',
" " . get_string('postsnumber', 'hub', $siteinfo['posts']));
$mform->addElement('static', 'questionslabel', '',
" " . get_string('questionsnumber', 'hub', $siteinfo['questions']));
$mform->addElement('static', 'resourceslabel', '',
" " . get_string('resourcesnumber', 'hub', $siteinfo['resources']));
$mform->addElement('static', 'badgeslabel', '',
" " . get_string('badgesnumber', 'hub', $siteinfo['badges']));
$mform->addElement('static', 'issuedbadgeslabel', '',
" " . get_string('issuedbadgesnumber', 'hub', $siteinfo['issuedbadges']));
$mform->addElement('static', 'participantnumberaveragelabel', '',
" " . get_string('participantnumberaverage', 'hub', $siteinfo['participantnumberaverage']));
$mform->addElement('static', 'modulenumberaveragelabel', '',
" " . get_string('modulenumberaverage', 'hub', $siteinfo['modulenumberaverage']));
$mobileservicestatus = $siteinfo['mobileservicesenabled'] ? get_string('yes') : get_string('no');
$mform->addElement('static', 'mobileservicesenabledlabel', '',
" " . get_string('mobileservicesenabled', 'hub', $mobileservicestatus));
$mobilenotificationsstatus = $siteinfo['mobilenotificationsenabled'] ? get_string('yes') : get_string('no');
$mform->addElement('static', 'mobilenotificationsenabledlabel', '',
" " . get_string('mobilenotificationsenabled', 'hub', $mobilenotificationsstatus));
$mform->addElement('static', 'registereduserdeviceslabel', '',
" " . get_string('registereduserdevices', 'hub', $siteinfo['registereduserdevices']));
$mform->addElement('static', 'registeredactiveuserdeviceslabel', '',
" " . get_string('registeredactiveuserdevices', 'hub', $siteinfo['registeredactiveuserdevices']));
// Check if it's a first registration or update.
if (registration::is_registered()) {
$buttonlabel = get_string('updatesite', 'hub', 'Moodle.net');
$mform->addElement('hidden', 'update', true);
$mform->setType('update', PARAM_BOOL);
} else {
$buttonlabel = get_string('registersite', 'hub', 'Moodle.net');
}
$this->add_action_buttons(false, $buttonlabel);
$this->set_data($siteinfo);
}
}
@@ -0,0 +1,61 @@
<?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 site_unregistration_form
*
* @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();
global $CFG;
require_once($CFG->libdir . '/formslib.php');
/**
* This form display a unregistration form.
*
* @author Jerome Mouneyrac <[email protected]>
* @package core
* @copyright 2017 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class site_unregistration_form extends \moodleform {
/**
* Form definition
*/
public function definition() {
$mform = & $this->_form;
$mform->addElement('header', 'site', get_string('unregister', 'hub'));
$unregisterlabel = get_string('unregister', 'hub');
$mform->addElement('advcheckbox', 'unpublishalladvertisedcourses', '',
' ' . get_string('unpublishalladvertisedcourses', 'hub'));
$mform->setType('unpublishalladvertisedcourses', PARAM_INT);
$mform->addElement('advcheckbox', 'unpublishalluploadedcourses', '',
' ' . get_string('unpublishalluploadedcourses', 'hub'));
$mform->setType('unpublishalluploadedcourses', PARAM_INT);
$mform->addElement('hidden', 'unregistration', 1);
$mform->setType('unregistration', PARAM_INT);
$this->add_action_buttons(true, $unregisterlabel);
}
}
+1 -5
View File
@@ -42,11 +42,7 @@ class registration_cron_task extends scheduled_task {
* Throw exceptions on errors (the job will be retried).
*/
public function execute() {
global $CFG;
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
$registrationmanager = new \registration_manager();
$registrationmanager->cron();
\core\hub\registration::update_cron();
}
}