Merge branch 'MDL-57228' of git://github.com/timhunt/moodle
authorJake Dallimore <jake@moodle.com>
Wed, 4 Oct 2017 05:42:51 +0000 (13:42 +0800)
committerJake Dallimore <jake@moodle.com>
Wed, 4 Oct 2017 05:42:51 +0000 (13:42 +0800)
276 files changed:
admin/index.php
admin/registration/confirmregistration.php
admin/registration/forms.php
admin/registration/index.php
admin/registration/lib.php
admin/registration/register.php
admin/registration/renderer.php
admin/registration/renewregistration.php
admin/renderer.php
admin/search.php
admin/settings/plugins.php
admin/settings/server.php
admin/settings/top.php
admin/tool/mobile/classes/api.php
admin/tool/mobile/classes/external.php
admin/tool/mobile/db/services.php
admin/tool/mobile/tests/externallib_test.php
admin/tool/mobile/upgrade.txt
admin/tool/mobile/version.php
admin/tool/templatelibrary/classes/external.php
analytics/classes/local/indicator/base.php
analytics/classes/local/time_splitting/base.php
analytics/tests/prediction_test.php
auth/email/classes/external.php
backup/moodle2/backup_stepslib.php
blocks/calendar_month/block_calendar_month.php
blocks/community/communitycourse.php
blocks/community/forms.php
blocks/community/locallib.php
blocks/community/renderer.php
blocks/community/styles.css
blocks/messages/block_messages.php [deleted file]
blocks/messages/db/access.php [deleted file]
blocks/messages/lang/en/block_messages.php [deleted file]
blocks/messages/styles.css [deleted file]
blocks/messages/tests/behat/block_messages_course.feature [deleted file]
blocks/messages/tests/behat/block_messages_dashboard.feature [deleted file]
blocks/messages/tests/behat/block_messages_frontpage.feature [deleted file]
blocks/messages/version.php [deleted file]
blocks/upgrade.txt
calendar/amd/build/calendar.min.js
calendar/amd/build/calendar_threemonth.min.js
calendar/amd/build/modal_event_form.min.js
calendar/amd/build/repository.min.js
calendar/amd/build/selectors.min.js
calendar/amd/build/view_manager.min.js
calendar/amd/src/calendar.js
calendar/amd/src/calendar_threemonth.js
calendar/amd/src/modal_event_form.js
calendar/amd/src/repository.js
calendar/amd/src/selectors.js
calendar/amd/src/view_manager.js
calendar/classes/external/calendar_event_exporter.php
calendar/classes/external/day_exporter.php
calendar/classes/external/event_exporter.php
calendar/classes/external/event_exporter_base.php
calendar/classes/external/event_icon_exporter.php
calendar/classes/external/footer_options_exporter.php
calendar/classes/external/month_exporter.php
calendar/classes/external/week_day_exporter.php
calendar/classes/local/api.php
calendar/classes/local/event/container.php
calendar/classes/local/event/data_access/event_vault.php
calendar/classes/local/event/data_access/event_vault_interface.php
calendar/classes/local/event/entities/action_event.php
calendar/classes/local/event/entities/event.php
calendar/classes/local/event/entities/event_interface.php
calendar/classes/local/event/factories/event_abstract_factory.php
calendar/classes/local/event/forms/create.php
calendar/classes/local/event/mappers/event_mapper.php
calendar/classes/local/event/proxies/coursecat_proxy.php [new file with mode: 0644]
calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php
calendar/classes/local/event/strategies/raw_event_retrieval_strategy_interface.php
calendar/event.php
calendar/export.php
calendar/externallib.php
calendar/lib.php
calendar/renderer.php
calendar/templates/add_event_button.mustache [new file with mode: 0644]
calendar/templates/event_summary_body.mustache
calendar/templates/footer_options.mustache
calendar/templates/month_detailed.mustache
calendar/templates/month_mini.mustache
calendar/tests/action_event_test.php
calendar/tests/behat/calendar.feature
calendar/tests/behat/calendar_lookahead.feature
calendar/tests/behat/category_events.feature [new file with mode: 0644]
calendar/tests/container_test.php
calendar/tests/coursecat_proxy_test.php [new file with mode: 0644]
calendar/tests/event_factory_test.php
calendar/tests/event_mapper_test.php
calendar/tests/event_test.php
calendar/tests/externallib_test.php
calendar/tests/helpers.php
calendar/tests/raw_event_retrieval_strategy_test.php
calendar/tests/repeat_event_collection_test.php
calendar/tests/rrule_manager_test.php
calendar/view.php
cohort/externallib.php
comment/classes/external.php
competency/tests/api_test.php
config-dist.php
course/publish/backup.php
course/publish/forms.php
course/publish/hubselector.php
course/publish/index.php
course/publish/lib.php
course/publish/metadata.php
course/publish/renderer.php
enrol/meta/tests/behat/enrol_meta.feature
enrol/self/tests/behat/self_enrolment.feature
files/externallib.php
filter/mathjaxloader/db/upgrade.php
filter/mathjaxloader/version.php
group/externallib.php
lang/en/admin.php
lang/en/calendar.php
lang/en/deprecated.txt
lang/en/error.php
lang/en/hub.php
lang/en/role.php
lib/amd/build/chartjs-lazy.min.js
lib/amd/src/chartjs-lazy.js
lib/behat/classes/partial_named_selector.php
lib/classes/external/coursecat_summary_exporter.php [new file with mode: 0644]
lib/classes/hub/api.php [new file with mode: 0644]
lib/classes/hub/course_publication_form.php [new file with mode: 0644]
lib/classes/hub/publication.php [new file with mode: 0644]
lib/classes/hub/registration.php [new file with mode: 0644]
lib/classes/hub/site_registration_form.php [new file with mode: 0644]
lib/classes/hub/site_unregistration_form.php [new file with mode: 0644]
lib/classes/output/icon_system_fontawesome.php
lib/classes/plugin_manager.php
lib/classes/task/registration_cron_task.php
lib/coursecatlib.php
lib/db/install.xml
lib/db/upgrade.php
lib/filestorage/file_system.php
lib/flickrclient.php [new file with mode: 0644]
lib/flickrlib.php
lib/htmlpurifier/HTMLPurifier.php
lib/htmlpurifier/HTMLPurifier.safe-includes.php
lib/htmlpurifier/HTMLPurifier/AttrDef.php
lib/htmlpurifier/HTMLPurifier/AttrDef/CSS.php
lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/Color.php
lib/htmlpurifier/HTMLPurifier/AttrDef/URI/Host.php
lib/htmlpurifier/HTMLPurifier/AttrTransform/TargetNoopener.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ChildDef/List.php
lib/htmlpurifier/HTMLPurifier/Config.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema.php
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt
lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php
lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer/README [changed mode: 0644->0755]
lib/htmlpurifier/HTMLPurifier/Encoder.php
lib/htmlpurifier/HTMLPurifier/EntityParser.php
lib/htmlpurifier/HTMLPurifier/Filter/ExtractStyleBlocks.php
lib/htmlpurifier/HTMLPurifier/Generator.php
lib/htmlpurifier/HTMLPurifier/HTMLModule/TargetNoopener.php [new file with mode: 0644]
lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php
lib/htmlpurifier/HTMLPurifier/Lexer.php
lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php
lib/htmlpurifier/HTMLPurifier/Lexer/DirectLex.php
lib/htmlpurifier/HTMLPurifier/Lexer/PH5P.php
lib/htmlpurifier/HTMLPurifier/Strategy/MakeWellFormed.php
lib/htmlpurifier/HTMLPurifier/Token.php
lib/htmlpurifier/HTMLPurifier/URI.php
lib/htmlpurifier/readme_moodle.txt
lib/markdown/License.md
lib/markdown/Markdown.php
lib/markdown/MarkdownExtra.php
lib/markdown/MarkdownInterface.php
lib/markdown/Readme.md
lib/markdown/readme_moodle.txt
lib/minify/matthiasmullie-minify/data/js/keywords_before.txt
lib/minify/matthiasmullie-minify/data/js/operators_after.txt
lib/minify/matthiasmullie-minify/src/CSS.php
lib/minify/matthiasmullie-minify/src/JS.php
lib/minify/matthiasmullie-minify/src/Minify.php
lib/minify/matthiasmullie-pathconverter/src/Converter.php
lib/minify/matthiasmullie-pathconverter/src/ConverterInterface.php [new file with mode: 0644]
lib/minify/matthiasmullie-pathconverter/src/NoConverter.php [new file with mode: 0644]
lib/minify/readme_moodle.txt
lib/moodlelib.php
lib/oauthlib.php
lib/scssphp/Base/Range.php
lib/scssphp/Block.php
lib/scssphp/Colors.php
lib/scssphp/Compiler.php
lib/scssphp/Compiler/Environment.php
lib/scssphp/Exception/CompilerException.php
lib/scssphp/Exception/ParserException.php
lib/scssphp/Exception/RangeException.php [new file with mode: 0644]
lib/scssphp/Exception/ServerException.php
lib/scssphp/Formatter.php
lib/scssphp/Formatter/Compact.php
lib/scssphp/Formatter/Compressed.php
lib/scssphp/Formatter/Crunched.php
lib/scssphp/Formatter/Debug.php
lib/scssphp/Formatter/Expanded.php
lib/scssphp/Formatter/Nested.php
lib/scssphp/Formatter/OutputBlock.php
lib/scssphp/Node.php
lib/scssphp/Node/Number.php
lib/scssphp/Parser.php
lib/scssphp/Server.php
lib/scssphp/Type.php
lib/scssphp/Util.php
lib/scssphp/Version.php
lib/scssphp/moodle_readme.txt
lib/simplepie/LICENSE.txt [new file with mode: 0644]
lib/simplepie/autoloader.php
lib/simplepie/library/SimplePie.php
lib/simplepie/library/SimplePie/Category.php
lib/simplepie/library/SimplePie/Content/Type/Sniffer.php
lib/simplepie/library/SimplePie/File.php
lib/simplepie/library/SimplePie/Item.php
lib/simplepie/library/SimplePie/Locator.php
lib/simplepie/library/SimplePie/Misc.php
lib/simplepie/library/SimplePie/Parse/Date.php
lib/simplepie/library/SimplePie/Sanitize.php
lib/simplepie/readme_moodle.txt
lib/testing/generator/data_generator.php
lib/tests/behat/behat_data_generators.php
lib/tests/coursecatlib_test.php
lib/tests/filelib_test.php
lib/tests/htmlpurifier_test.php
lib/tests/markdown_test.php
lib/tests/moodlelib_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
message/externallib.php
message/tests/behat/delete_all_messages.feature
mod/data/export_form.php
mod/lti/view.php
mod/quiz/classes/structure.php
mod/quiz/lang/en/quiz.php
mod/quiz/report/overview/report.php
mod/quiz/report/responses/report.php
mod/quiz/tests/behat/editing_section_headings.feature
mod/workshop/assessment.php
mod/workshop/classes/external.php
mod/workshop/classes/external/assessment_exporter.php [new file with mode: 0644]
mod/workshop/classes/external/submission_exporter.php [new file with mode: 0644]
mod/workshop/db/services.php
mod/workshop/form/assessment_form.php
mod/workshop/locallib.php
mod/workshop/submission.php
mod/workshop/tests/external_test.php
mod/workshop/version.php
notes/externallib.php
pix/i/categoryevent.svg [new file with mode: 0644]
portfolio/flickr/lib.php
question/classes/external.php
report/insights/classes/output/insight.php
report/security/lang/en/report_security.php
repository/flickr/db/upgrade.php [new file with mode: 0644]
repository/flickr/lib.php
repository/flickr/version.php
repository/googledocs/lib.php
repository/onedrive/lib.php
repository/tests/behat/cancel_add_file.feature
search/classes/manager.php
search/tests/manager_test.php
tag/classes/external.php
tags.txt [deleted file]
theme/boost/scss/moodle/calendar.scss
theme/boost/tests/behat/behat_theme_boost_behat_blocks.php
theme/bootstrapbase/less/moodle/calendar.less
theme/bootstrapbase/style/moodle.css
user/externallib.php
user/tests/behat/edit_user_enrolment.feature
version.php

index ba80a96..b077d44 100644 (file)
@@ -857,7 +857,7 @@ if ($updateschecker->enabled()) {
 
 $buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
 //check if the site is registered on Moodle.org
-$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
+$registered = \core\hub\registration::is_registered();
 // Check if there are any cache warnings.
 $cachewarnings = cache_helper::warnings();
 // Check if there are events 1 API handlers.
@@ -865,7 +865,7 @@ $eventshandlers = $DB->get_records_sql('SELECT DISTINCT component FROM {events_h
 $themedesignermode = !empty($CFG->themedesignermode);
 
 // Check if a directory with development libraries exists.
-if (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules')) {
+if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules'))) {
     $devlibdir = true;
 } else {
     $devlibdir = false;
index 77b2fb2..7fe7689 100644 (file)
@@ -20,7 +20,7 @@
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-/*
+/**
  * @package    moodle
  * @subpackage registration
  * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
@@ -36,7 +36,6 @@
 
 require('../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
 
 $newtoken = optional_param('newtoken', '', PARAM_ALPHANUM);
 $url = optional_param('url', '', PARAM_URL);
@@ -44,7 +43,11 @@ $hubname = optional_param('hubname', '', PARAM_TEXT);
 $token = optional_param('token', '', PARAM_TEXT);
 $error = optional_param('error', '', PARAM_ALPHANUM);
 
-admin_externalpage_setup('registrationhubs');
+admin_externalpage_setup('registrationmoodleorg');
+
+if ($url !== HUB_MOODLEORGHUBURL) {
+    throw new moodle_exception('errorotherhubsnotsupported', 'hub');
+}
 
 if (!empty($error) and $error == 'urlalreadyexist') {
     throw new moodle_exception('urlalreadyregistered', 'hub',
@@ -52,38 +55,20 @@ if (!empty($error) and $error == 'urlalreadyexist') {
 }
 
 //check that we are waiting a confirmation from this hub, and check that the token is correct
-$registrationmanager = new registration_manager();
-$registeredhub = $registrationmanager->get_unconfirmedhub($url);
-if (!empty($registeredhub) and $registeredhub->token == $token) {
-
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
+core\hub\registration::confirm_registration($token, $newtoken, $hubname);
 
-    $registeredhub->token = $newtoken;
-    $registeredhub->confirmed = 1;
-    $registeredhub->hubname = $hubname;
-    $registrationmanager->update_registeredhub($registeredhub);
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
 
-    // Display notification message.
-    echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
+// Display notification message.
+echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
 
-    //display continue button
-    $registrationpage = new moodle_url('/admin/registration/index.php');
-    $continuebutton = $OUTPUT->render(new single_button($registrationpage, get_string('continue', 'hub')));
-    $continuebutton = html_writer::tag('div', $continuebutton, array('class' => 'mdl-align'));
-    echo $continuebutton;
+// Display continue button.
+$registrationpage = new moodle_url('/admin/registration/index.php');
+$continuebutton = $OUTPUT->render(new single_button($registrationpage, get_string('continue')));
+$continuebutton = html_writer::tag('div', $continuebutton, array('class' => 'mdl-align'));
+echo $continuebutton;
 
-    if (!extension_loaded('xmlrpc')) {
-        //display notice about xmlrpc
-        $xmlrpcnotification = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
-        $xmlrpcnotification .= get_string('xmlrpcdisabledregistration', 'hub');
-        echo $OUTPUT->notification($xmlrpcnotification);
-    }
-
-    echo $OUTPUT->footer();
-} else {
-    throw new moodle_exception('wrongtoken', 'hub',
-            $CFG->wwwroot . '/' . $CFG->admin . '/registration/index.php');
-}
+echo $OUTPUT->footer();
 
 
index 0d70879..6fe9553 100644 (file)
@@ -20,7 +20,7 @@
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-/*
+/**
  * @package    moodle
  * @subpackage registration
  * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
  * The forms needed by registration pages.
  */
 
+defined('MOODLE_INTERNAL') || die();
 
-require_once($CFG->libdir . '/formslib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
-
-/**
- * This form display a unregistration form.
- */
-class site_unregistration_form extends moodleform {
-
-    public function definition() {
-        $mform = & $this->_form;
-        $mform->addElement('header', 'site', get_string('unregister', 'hub'));
-
-        $huburl = $this->_customdata['huburl'];
-        $hubname = $this->_customdata['hubname'];
-
-        $unregisterlabel = get_string('unregister', 'hub');
-        $mform->addElement('checkbox', 'unpublishalladvertisedcourses', '',
-                ' ' . get_string('unpublishalladvertisedcourses', 'hub'));
-        $mform->setType('unpublishalladvertisedcourses', PARAM_INT);
-        $mform->addElement('checkbox', 'unpublishalluploadedcourses', '',
-                ' ' . get_string('unpublishalluploadedcourses', 'hub'));
-        $mform->setType('unpublishalluploadedcourses', PARAM_INT);
-
-        $mform->addElement('hidden', 'confirm', 1);
-        $mform->setType('confirm', PARAM_INT);
-        $mform->addElement('hidden', 'unregistration', 1);
-        $mform->setType('unregistration', PARAM_INT);
-        $mform->addElement('hidden', 'huburl', $huburl);
-        $mform->setType('huburl', PARAM_URL);
-        $mform->addElement('hidden', 'hubname', $hubname);
-        $mform->setType('hubname', PARAM_TEXT);
-
-        $this->add_action_buttons(true, $unregisterlabel);
-    }
-
-}
-
-/**
- * This form display a clean registration data form.
- */
-class site_clean_registration_data_form extends moodleform {
-
-    public function definition() {
-        $mform = & $this->_form;
-        $mform->addElement('header', 'site', get_string('unregister', 'hub'));
-
-        $huburl = $this->_customdata['huburl'];
-        $hubname = $this->_customdata['hubname'];
-
-
-        $unregisterlabel = get_string('forceunregister', 'hub');
-        $mform->addElement('static', '', get_string('warning', 'hub'), get_string('forceunregisterconfirmation', 'hub', $hubname));
-
-        $mform->addElement('hidden', 'confirm', 1);
-        $mform->setType('confirm', PARAM_INT);
-        $mform->addElement('hidden', 'unregistration', 1);
-        $mform->setType('unregistration', PARAM_INT);
-        $mform->addElement('hidden', 'cleanregdata', 1);
-        $mform->setType('cleanregdata', PARAM_INT);
-        $mform->addElement('hidden', 'huburl', $huburl);
-        $mform->setType('huburl', PARAM_URL);
-        $mform->addElement('hidden', 'hubname', $hubname);
-        $mform->setType('hubname', PARAM_TEXT);
-
-        $this->add_action_buttons(true, $unregisterlabel);
-    }
-
-}
-
-/**
- * This form display a hub selector.
- * The hub list is retrieved from Moodle.org hub directory.
- * Also displayed, a text field to enter private hub url + its password
- */
-class hub_selector_form extends moodleform {
-
-    public function definition() {
-        global $CFG, $OUTPUT;
-        $mform = & $this->_form;
-        $mform->addElement('header', 'site', get_string('selecthub', 'hub'));
-
-        //retrieve the hub list on the hub directory by web service
-        $function = 'hubdirectory_get_hubs';
-        $params = array();
-        $serverurl = HUB_HUBDIRECTORYURL . "/local/hubdirectory/webservice/webservices.php";
-        require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
-        $xmlrpcclient = new webservice_xmlrpc_client($serverurl, 'publichubdirectory');
-        try {
-            $hubs = $xmlrpcclient->call($function, $params);
-        } catch (Exception $e) {
-            $error = $OUTPUT->notification(get_string('errorhublisting', 'hub', $e->getMessage()));
-            $mform->addElement('static', 'errorhub', '', $error);
-            $hubs = array();
-        }
-
-        //remove moodle.org from the hub list
-        foreach ($hubs as $key => $hub) {
-            if ($hub['url'] == HUB_MOODLEORGHUBURL || $hub['url'] == HUB_OLDMOODLEORGHUBURL) {
-                unset($hubs[$key]);
-            }
-        }
-
-        //Public hub list
-        $options = array();
-        foreach ($hubs as $hub) {
-            //to not display a name longer than 100 character (too big)
-            if (core_text::strlen($hub['name']) > 100) {
-                $hubname = core_text::substr($hub['name'], 0, 100);
-                $hubname = $hubname . "...";
-            } else {
-                $hubname = $hub['name'];
-            }
-            $options[$hub['url']] = $hubname;
-            $mform->addElement('hidden', clean_param($hub['url'], PARAM_ALPHANUMEXT), $hubname);
-            $mform->setType(clean_param($hub['url'], PARAM_ALPHANUMEXT), PARAM_ALPHANUMEXT);
-        }
-        if (!empty($hubs)) {
-            $mform->addElement('select', 'publichub', get_string('publichub', 'hub'),
-                    $options, array("size" => 15));
-            $mform->setType('publichub', PARAM_URL);
-        }
-
-        $mform->addElement('static', 'or', '', get_string('orenterprivatehub', 'hub'));
-
-        //Private hub
-        $mform->addElement('text', 'unlistedurl', get_string('privatehuburl', 'hub'),
-                array('class' => 'registration_textfield'));
-        $mform->setType('unlistedurl', PARAM_URL);
-        $mform->addElement('text', 'password', get_string('password'),
-                array('class' => 'registration_textfield'));
-        $mform->setType('password', PARAM_RAW);
-
-        $this->add_action_buttons(false, get_string('selecthub', 'hub'));
-    }
-
-    /**
-     * Check the unlisted URL is a URL
-     */
-    function validation($data, $files) {
-        global $CFG;
-        $errors = parent::validation($data, $files);
-
-        $unlistedurl = $this->_form->_submitValues['unlistedurl'];
-
-        if (empty($unlistedurl)) {
-            $errors['unlistedurl'] = get_string('badurlformat', 'hub');
-        }
-
-        return $errors;
-    }
-
-}
-
-/**
- * The site registration form. Information will be sent to a given hub.
- */
-class site_registration_form extends moodleform {
-
-    public function definition() {
-        global $CFG, $DB;
-
-        $strrequired = get_string('required');
-        $mform = & $this->_form;
-        $huburl = $this->_customdata['huburl'];
-        $hubname = $this->_customdata['hubname'];
-        $password = $this->_customdata['password'];
-        $admin = get_admin();
-        $site = get_site();
-
-        //retrieve config for this hub and set default if they don't exist
-        $cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
-        $sitename = get_config('hub', 'site_name_' . $cleanhuburl);
-        if ($sitename === false) {
-            $sitename = format_string($site->fullname, true, array('context' => context_course::instance(SITEID)));
-        }
-        $sitedescription = get_config('hub', 'site_description_' . $cleanhuburl);
-        if ($sitedescription === false) {
-            $sitedescription = $site->summary;
-        }
-        $contactname = get_config('hub', 'site_contactname_' . $cleanhuburl);
-        if ($contactname === false) {
-            $contactname = fullname($admin, true);
-        }
-        $contactemail = get_config('hub', 'site_contactemail_' . $cleanhuburl);
-        if ($contactemail === false) {
-            $contactemail = $admin->email;
-        }
-        $contactphone = get_config('hub', 'site_contactphone_' . $cleanhuburl);
-        if ($contactphone === false) {
-            $contactphone = $admin->phone1;
-        }
-        $imageurl = get_config('hub', 'site_imageurl_' . $cleanhuburl);
-        $privacy = get_config('hub', 'site_privacy_' . $cleanhuburl);
-        $address = get_config('hub', 'site_address_' . $cleanhuburl);
-        if ($address === false) {
-            $address = '';
-        }
-        $region = get_config('hub', 'site_region_' . $cleanhuburl);
-        $country = get_config('hub', 'site_country_' . $cleanhuburl);
-        if (empty($country)) {
-            $country = $admin->country ?: $CFG->country;
-        }
-        $language = get_config('hub', 'site_language_' . $cleanhuburl);
-        if ($language === false) {
-            $language = explode('_', current_language())[0];
-        }
-        $geolocation = get_config('hub', 'site_geolocation_' . $cleanhuburl);
-        if ($geolocation === false) {
-            $geolocation = '';
-        }
-        $contactable = get_config('hub', 'site_contactable_' . $cleanhuburl);
-        $emailalert = get_config('hub', 'site_emailalert_' . $cleanhuburl);
-        $emailalert = ($emailalert === false || $emailalert) ? 1 : 0;
-        $coursesnumber = get_config('hub', 'site_coursesnumber_' . $cleanhuburl);
-        $usersnumber = get_config('hub', 'site_usersnumber_' . $cleanhuburl);
-        $roleassignmentsnumber = get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl);
-        $postsnumber = get_config('hub', 'site_postsnumber_' . $cleanhuburl);
-        $questionsnumber = get_config('hub', 'site_questionsnumber_' . $cleanhuburl);
-        $resourcesnumber = get_config('hub', 'site_resourcesnumber_' . $cleanhuburl);
-        $badgesnumber = get_config('hub', 'site_badges_' . $cleanhuburl);
-        $issuedbadgesnumber = get_config('hub', 'site_issuedbadges_' . $cleanhuburl);
-        $mediancoursesize = get_config('hub', 'site_mediancoursesize_' . $cleanhuburl);
-        $participantnumberaveragecfg = get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl);
-        $modulenumberaveragecfg = get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl);
-        // Mobile related information.
-        $mobileservicesenabled = get_config('hub', 'site_mobileservicesenabled_' . $cleanhuburl);
-        $mobilenotificationsenabled = get_config('hub', 'site_mobilenotificationsenabled_' . $cleanhuburl);
-        $registereduserdevices = get_config('hub', 'site_registereduserdevices_' . $cleanhuburl);
-        $registeredactiveuserdevices = get_config('hub', 'site_registeredactiveuserdevices_' . $cleanhuburl);
-
-        //hidden parameters
-        $mform->addElement('hidden', 'huburl', $huburl);
-        $mform->setType('huburl', PARAM_URL);
-        $mform->addElement('hidden', 'hubname', $hubname);
-        $mform->setType('hubname', PARAM_TEXT);
-        $mform->addElement('hidden', 'password', $password);
-        $mform->setType('password', PARAM_RAW);
-
-        //the input parameters
-        $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->setDefault('name', $sitename);
-        $mform->addHelpButton('name', 'sitename', 'hub');
-
-        $options = array();
-        $registrationmanager = new registration_manager();
-        $options[HUB_SITENOTPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITENOTPUBLISHED);
-        $options[HUB_SITENAMEPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITENAMEPUBLISHED);
-        $options[HUB_SITELINKPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITELINKPUBLISHED);
-        $mform->addElement('select', 'privacy', get_string('siteprivacy', 'hub'), $options);
-        $mform->setDefault('privacy', $privacy);
-        $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->setDefault('description', $sitedescription);
-        $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->setDefault('language', $language);
-
-        $mform->addElement('textarea', 'address', get_string('postaladdress', 'hub'),
-                array('rows' => 4, 'cols' => 41));
-        $mform->setType('address', PARAM_TEXT);
-        $mform->setDefault('address', $address);
-        $mform->addHelpButton('address', 'postaladdress', 'hub');
-
-        //TODO: use the region array I generated
-//        $mform->addElement('select', 'region', get_string('selectaregion'), array('-' => '-'));
-//        $mform->setDefault('region', $region);
-        $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->setDefault('countrycode', $country);
-        $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->setDefault('geolocation', $geolocation);
-        $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->setDefault('contactname', $contactname);
-        $mform->addHelpButton('contactname', 'siteadmin', 'hub');
-
-        $mform->addElement('text', 'contactphone', get_string('sitephone', 'hub'),
-                array('class' => 'registration_textfield'));
-        $mform->setType('contactphone', PARAM_TEXT);
-        $mform->setDefault('contactphone', $contactphone);
-        $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->setDefault('contactemail', $contactemail);
-        $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->setDefault('contactable', $contactable);
-        $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->setDefault('emailalert', $emailalert);
-        $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'), $CFG->wwwroot);
-        $mform->addHelpButton('urlstring', 'siteurl', 'hub');
-
-        $mform->addElement('static', 'versionstring', get_string('siteversion', 'hub'), $CFG->version);
-        $mform->addElement('hidden', 'moodleversion', $CFG->version);
-        $mform->setType('moodleversion', PARAM_INT);
-        $mform->addHelpButton('versionstring', 'siteversion', 'hub');
-
-        $mform->addElement('static', 'releasestring', get_string('siterelease', 'hub'), $CFG->release);
-        $mform->addElement('hidden', 'moodlerelease', $CFG->release);
-        $mform->setType('moodlerelease', PARAM_TEXT);
-        $mform->addHelpButton('releasestring', 'siterelease', 'hub');
-
-        /// Display statistic that are going to be retrieve by the hub
-        $coursecount = $DB->count_records('course') - 1;
-        $usercount = $DB->count_records('user', array('deleted' => 0));
-        $roleassigncount = $DB->count_records('role_assignments');
-        $postcount = $DB->count_records('forum_posts');
-        $questioncount = $DB->count_records('question');
-        $resourcecount = $DB->count_records('resource');
-        require_once($CFG->dirroot . "/course/lib.php");
-        $participantnumberaverage = number_format(average_number_of_participants(), 2);
-        $modulenumberaverage = number_format(average_number_of_courses_modules(), 2);
-        require_once($CFG->libdir . '/badgeslib.php');
-        $badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
-        $issuedbadges = $DB->count_records('badge_issued');
-        // Mobile related information.
-        $ismobileenabled = false;
-        $aremobilenotificationsenabled = false;
-        $registereduserdevicescount = 0;
-        $registeredactiveuserdevicescount = 0;
-        if (!empty($CFG->enablewebservices) && !empty($CFG->enablemobilewebservice)) {
-            $ismobileenabled = true;
-            $registereduserdevicescount = $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);
-                $aremobilenotificationsenabled = (bool) message_airnotifier_external::is_system_configured();
-                $registeredactiveuserdevicescount = $DB->count_records('message_airnotifier_devices', array('enable' => 1));
-            }
-        }
-
-        if (HUB_MOODLEORGHUBURL != $huburl) {
-            $mform->addElement('checkbox', 'courses', get_string('sendfollowinginfo', 'hub'),
-                    " " . get_string('coursesnumber', 'hub', $coursecount));
-            $mform->setDefault('courses', $coursesnumber != -1);
-            $mform->setType('courses', PARAM_INT);
-            $mform->addHelpButton('courses', 'sendfollowinginfo', 'hub');
-
-            $mform->addElement('checkbox', 'users', '',
-                    " " . get_string('usersnumber', 'hub', $usercount));
-            $mform->setDefault('users', $usersnumber != -1);
-            $mform->setType('users', PARAM_INT);
-
-            $mform->addElement('checkbox', 'roleassignments', '',
-                    " " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
-            $mform->setDefault('roleassignments', $roleassignmentsnumber != -1);
-            $mform->setType('roleassignments', PARAM_INT);
-
-            $mform->addElement('checkbox', 'posts', '',
-                    " " . get_string('postsnumber', 'hub', $postcount));
-            $mform->setDefault('posts', $postsnumber != -1);
-            $mform->setType('posts', PARAM_INT);
-
-            $mform->addElement('checkbox', 'questions', '',
-                    " " . get_string('questionsnumber', 'hub', $questioncount));
-            $mform->setDefault('questions', $questionsnumber != -1);
-            $mform->setType('questions', PARAM_INT);
-
-            $mform->addElement('checkbox', 'resources', '',
-                    " " . get_string('resourcesnumber', 'hub', $resourcecount));
-            $mform->setDefault('resources', $resourcesnumber != -1);
-            $mform->setType('resources', PARAM_INT);
-
-            $mform->addElement('checkbox', 'badges', '',
-                    " " . get_string('badgesnumber', 'hub', $badges));
-            $mform->setDefault('badges', $badgesnumber != -1);
-            $mform->setType('badges', PARAM_INT);
-
-            $mform->addElement('checkbox', 'issuedbadges', '',
-                    " " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
-            $mform->setDefault('issuedbadges', $issuedbadgesnumber != -1);
-            $mform->setType('issuedbadges', PARAM_INT);
-
-            $mform->addElement('checkbox', 'participantnumberaverage', '',
-                    " " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
-            $mform->setDefault('participantnumberaverage', $participantnumberaveragecfg != -1);
-            $mform->setType('participantnumberaverage', PARAM_FLOAT);
-
-            $mform->addElement('checkbox', 'modulenumberaverage', '',
-                    " " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
-            $mform->setDefault('modulenumberaverage', $modulenumberaveragecfg != -1);
-            $mform->setType('modulenumberaverage', PARAM_FLOAT);
-
-            $mobileservicestatus = $ismobileenabled ? 'yes' : 'no';
-            $mform->addElement('checkbox', 'mobileservicesenabled', '',
-                    " " . get_string('mobileservicesenabled', 'hub', $mobileservicestatus));
-            $mform->setDefault('mobileservicesenabled', $mobileservicesenabled != -1);
-            $mform->setType('mobileservicesenabled', PARAM_INT);
-
-            $mobilenotificationsstatus = $aremobilenotificationsenabled ? 'yes' : 'no';
-            $mform->addElement('checkbox', 'mobilenotificationsenabled', '',
-                    " " . get_string('mobilenotificationsenabled', 'hub', $mobilenotificationsstatus));
-            $mform->setDefault('mobilenotificationsenabled', $mobilenotificationsenabled != -1);
-            $mform->setType('mobilenotificationsenabled', PARAM_INT);
-
-            $mform->addElement('checkbox', 'registereduserdevices', '',
-                    " " . get_string('registereduserdevices', 'hub', $registereduserdevicescount));
-            $mform->setDefault('registereduserdevices', $registereduserdevices != -1);
-            $mform->setType('registereduserdevices', PARAM_INT);
-
-            $mform->addElement('checkbox', 'registeredactiveuserdevices', '',
-                    " " . get_string('registeredactiveuserdevices', 'hub', $registeredactiveuserdevicescount));
-            $mform->setDefault('registeredactiveuserdevices', $registeredactiveuserdevices != -1);
-            $mform->setType('registeredactiveuserdevices', PARAM_INT);
-        } else {
-            $mform->addElement('static', 'courseslabel', get_string('sendfollowinginfo', 'hub'),
-                    " " . get_string('coursesnumber', 'hub', $coursecount));
-            $mform->addElement('hidden', 'courses', 1);
-            $mform->setType('courses', PARAM_INT);
-            $mform->addHelpButton('courseslabel', 'sendfollowinginfo', 'hub');
-
-            $mform->addElement('static', 'userslabel', '',
-                    " " . get_string('usersnumber', 'hub', $usercount));
-            $mform->addElement('hidden', 'users', 1);
-            $mform->setType('users', PARAM_INT);
-
-            $mform->addElement('static', 'roleassignmentslabel', '',
-                    " " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
-            $mform->addElement('hidden', 'roleassignments', 1);
-            $mform->setType('roleassignments', PARAM_INT);
-
-            $mform->addElement('static', 'postslabel', '',
-                    " " . get_string('postsnumber', 'hub', $postcount));
-            $mform->addElement('hidden', 'posts', 1);
-            $mform->setType('posts', PARAM_INT);
-
-            $mform->addElement('static', 'questionslabel', '',
-                    " " . get_string('questionsnumber', 'hub', $questioncount));
-            $mform->addElement('hidden', 'questions', 1);
-            $mform->setType('questions', PARAM_INT);
-
-            $mform->addElement('static', 'resourceslabel', '',
-                    " " . get_string('resourcesnumber', 'hub', $resourcecount));
-            $mform->addElement('hidden', 'resources', 1);
-            $mform->setType('resources', PARAM_INT);
-
-            $mform->addElement('static', 'badgeslabel', '',
-                    " " . get_string('badgesnumber', 'hub', $badges));
-            $mform->addElement('hidden', 'badges', 1);
-            $mform->setType('badges', PARAM_INT);
-
-            $mform->addElement('static', 'issuedbadgeslabel', '',
-                    " " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
-            $mform->addElement('hidden', 'issuedbadges', true);
-            $mform->setType('issuedbadges', PARAM_INT);
-
-            $mform->addElement('static', 'participantnumberaveragelabel', '',
-                    " " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
-            $mform->addElement('hidden', 'participantnumberaverage', 1);
-            $mform->setType('participantnumberaverage', PARAM_FLOAT);
-
-            $mform->addElement('static', 'modulenumberaveragelabel', '',
-                    " " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
-            $mform->addElement('hidden', 'modulenumberaverage', 1);
-            $mform->setType('modulenumberaverage', PARAM_FLOAT);
-
-            $mobileservicestatus = $ismobileenabled ? 'yes' : 'no';
-            $mform->addElement('static', 'mobileservicesenabledlabel', '',
-                    " " . get_string('mobileservicesenabled', 'hub', $mobileservicestatus));
-            $mform->addElement('hidden', 'mobileservicesenabled', 1);
-            $mform->setType('mobileservicesenabled', PARAM_INT);
-
-            $mobilenotificationsstatus = $aremobilenotificationsenabled ? 'yes' : 'no';
-            $mform->addElement('static', 'mobilenotificationsenabledlabel', '',
-                    " " . get_string('mobilenotificationsenabled', 'hub', $mobilenotificationsstatus));
-            $mform->addElement('hidden', 'mobilenotificationsenabled', 1);
-            $mform->setType('mobilenotificationsenabled', PARAM_INT);
-
-            $mform->addElement('static', 'registereduserdeviceslabel', '',
-                    " " . get_string('registereduserdevices', 'hub', $registereduserdevicescount));
-            $mform->addElement('hidden', 'registereduserdevices', 1);
-            $mform->setType('registereduserdevices', PARAM_INT);
-
-            $mform->addElement('static', 'registeredactiveuserdeviceslabel', '',
-                    " " . get_string('registeredactiveuserdevices', 'hub', $registeredactiveuserdevicescount));
-            $mform->addElement('hidden', 'registeredactiveuserdevices', 1);
-            $mform->setType('registeredactiveuserdevices', PARAM_INT);
-        }
-
-        //check if it's a first registration or update
-        $hubregistered = $registrationmanager->get_registeredhub($huburl);
-
-        if (!empty($hubregistered)) {
-            $buttonlabel = get_string('updatesite', 'hub',
-                            !empty($hubname) ? $hubname : $huburl);
-            $mform->addElement('hidden', 'update', true);
-            $mform->setType('update', PARAM_BOOL);
-        } else {
-            $buttonlabel = get_string('registersite', 'hub',
-                            !empty($hubname) ? $hubname : $huburl);
-        }
-
-        $this->add_action_buttons(false, $buttonlabel);
-    }
-
-}
-
+debugging('Support for alternative hubs has been removed from Moodle in 3.4. For communication with moodle.net ' .
+    'see lib/classes/hub/ .', DEBUG_DEVELOPER);
index b9aeb18..0adb27b 100644 (file)
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-/*
+/**
  * @package    moodle
  * @subpackage registration
  * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
  * @copyright  (C) 1999 onwards Martin Dougiamas  http://dougiamas.com
  *
- * On this page the administrator selects which hub he wants to register (except for moodle.net)
- * Admins can register with moodle.net via the site admin menu "Registration" link.
- * On this page the administrator can also unregister from any hubs including moodle.net.
+ * This page displays the site registration form for Moodle.net.
+ * It handles redirection to the hub to continue the registration workflow process.
+ * It also handles update operation by web service.
  */
 
-require('../../config.php');
-
+require_once('../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
-require_once($CFG->dirroot . '/course/publish/lib.php');
-require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
-
-admin_externalpage_setup('registrationhubs');
 
-$renderer = $PAGE->get_renderer('core', 'register');
+admin_externalpage_setup('registrationmoodleorg');
 
 $unregistration = optional_param('unregistration', 0, PARAM_INT);
-$cleanregdata = optional_param('cleanregdata', 0, PARAM_BOOL);
-$confirm = optional_param('confirm', 0, PARAM_INT);
-$huburl = optional_param('huburl', '', PARAM_URL);
-$cancel = optional_param('cancel', null, PARAM_ALPHA);
-
-$registrationmanager = new registration_manager();
-$publicationmanager = new course_publish_manager();
-$errormessage = '';
-if (empty($cancel) and $unregistration and $confirm and confirm_sesskey()) {
-
-    $hub = $registrationmanager->get_registeredhub($huburl);
-
-    //unpublish course and unregister the site by web service
-    if (!$cleanregdata) {
-
-        //check if we need to unpublish courses
-        //enrollable courses
-        $unpublishalladvertisedcourses = optional_param('unpublishalladvertisedcourses', 0, PARAM_INT);
-        $hubcourseids = array();
-        if ($unpublishalladvertisedcourses) {
-            $enrollablecourses = $publicationmanager->get_publications($huburl, null, 1);
-            if (!empty($enrollablecourses)) {
-                foreach ($enrollablecourses as $enrollablecourse) {
-                    $hubcourseids[] = $enrollablecourse->hubcourseid;
-                }
-            }
-        }
-        //downloadable courses
-        $unpublishalluploadedcourses = optional_param('unpublishalluploadedcourses', 0, PARAM_INT);
-        if ($unpublishalluploadedcourses) {
-            $downloadablecourses = $publicationmanager->get_publications($huburl, null, 0);
-            if (!empty($downloadablecourses)) {
-                foreach ($downloadablecourses as $downloadablecourse) {
-                    $hubcourseids[] = $downloadablecourse->hubcourseid;
-                }
-            }
-        }
 
-        //unpublish the courses by web service
-        if (!empty($hubcourseids)) {
-            $function = 'hub_unregister_courses';
-            $params = array('courseids' => $hubcourseids);
-            $serverurl = $huburl . "/local/hub/webservice/webservices.php";
-            $xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
-            try {
-                $result = $xmlrpcclient->call($function, $params);
-                //delete the published courses
-                if (!empty($enrollablecourses)) {
-                    $publicationmanager->delete_hub_publications($huburl, 1);
-                }
-                if (!empty($downloadablecourses)) {
-                    $publicationmanager->delete_hub_publications($huburl, 0);
-                }
-            } catch (Exception $e) {
-                $errormessage = $e->getMessage();
-                $errormessage .= html_writer::empty_tag('br') .
-                        get_string('errorunpublishcourses', 'hub');
-                $confirm = false;
-                $cleanregdata = 1;
-            }
-        }
-    }
+if ($unregistration && \core\hub\registration::is_registered()) {
+    $siteunregistrationform = new \core\hub\site_unregistration_form();
 
-    //course unpublish went ok, unregister the site now
-    if ($confirm) {
-        $function = 'hub_unregister_site';
-        $params = array();
-        $serverurl = $huburl . "/local/hub/webservice/webservices.php";
-        $xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
-        try {
-            $result = $xmlrpcclient->call($function, $params);
-        } catch (Exception $e) {
-            if (!$cleanregdata) {
-                $errormessage = $e->getMessage();
-                $confirm = false;
-                $cleanregdata = 1;
-            }
+    if ($siteunregistrationform->is_cancelled()) {
+        redirect(new moodle_url('/admin/registration/index.php'));
+    } else if ($data = $siteunregistrationform->get_data()) {
+        if (\core\hub\registration::unregister($data->unpublishalladvertisedcourses,
+            $data->unpublishalluploadedcourses)) {
+            redirect(new moodle_url('/admin/registration/index.php'));
         }
     }
 
-    //check that we are still processing the unregistration,
-    //it could have been unset if an exception were previsouly catched
-    if ($confirm) {
-        $registrationmanager->delete_registeredhub($huburl);
-    }
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', 'Moodle.net'), 3, 'main');
+    $siteunregistrationform->display();
+    echo $OUTPUT->footer();
+    exit;
 }
 
-if (empty($cancel) and $unregistration and !$confirm) {
-
-    echo $OUTPUT->header();
+$siteregistrationform = new \core\hub\site_registration_form();
+if ($fromform = $siteregistrationform->get_data()) {
 
-    //do not check sesskey if confirm = false because this script is linked into email message
-    if (!empty($errormessage)) {
-        echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
-    }
+    // Save the settings.
+    \core\hub\registration::save_site_info($fromform);
 
-    $hub = $registrationmanager->get_registeredhub($huburl);
-    echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', $hub->hubname), 3, 'main');
-    if ($cleanregdata) {
-        $siteunregistrationform = new site_clean_registration_data_form('',
-                        array('huburl' => $huburl, 'hubname' => $hub->hubname));
+    if (\core\hub\registration::is_registered()) {
+        \core\hub\registration::update_manual();
+        redirect(new moodle_url('/admin/registration/index.php'));
     } else {
-        $siteunregistrationform = new site_unregistration_form('',
-                        array('huburl' => $huburl, 'hubname' => $hub->hubname));
+        \core\hub\registration::register();
+        // This method will redirect away.
     }
 
-    $siteunregistrationform->display();
-} else {
-    $registeredonmoodleorg = false;
-    $moodleorghub = $registrationmanager->get_registeredhub(HUB_MOODLEORGHUBURL);
-    if (!empty($moodleorghub)) {
-        $registeredonmoodleorg = true;
-    }
-
-    // load the hub selector form
-    $hubselectorform = new hub_selector_form();
-    $fromform = $hubselectorform->get_data();
-    $selectedhuburl = optional_param('publichub', false, PARAM_URL);
-    $unlistedhuburl = optional_param('unlistedurl', false, PARAM_TEXT);
-    $password = optional_param('password', '', PARAM_RAW);
-    $registeringhuburl = null;
-    if (!empty($unlistedhuburl)) {
-        if (clean_param($unlistedhuburl, PARAM_URL) !== '') {
-            $registeringhuburl = $unlistedhuburl;
-        }
-    } else if (!empty($selectedhuburl)) {
-        $registeringhuburl = $selectedhuburl;
-    }
+}
 
-    // a hub has been selected, redirect to the hub registration page
-    if (empty($cancel) and !empty($registeringhuburl) and confirm_sesskey()) {
-        $hubname = optional_param(clean_param($registeringhuburl, PARAM_ALPHANUMEXT), '', PARAM_TEXT);
-        $params = array('sesskey' => sesskey(), 'huburl' => $registeringhuburl,
-            'password' => $password, 'hubname' => $hubname);
-        redirect(new moodle_url($CFG->wwwroot . "/" . $CFG->admin . "/registration/register.php",
-                        $params));
-    }
+// OUTPUT SECTION.
 
-    echo $OUTPUT->header();
+echo $OUTPUT->header();
 
-    //check if the site is registered on Moodle.org and display a message about registering on MOOCH
-    $adminrenderer = $PAGE->get_renderer('core', 'admin');
-    echo $adminrenderer->warn_if_not_registered();
+// Current status of registration on Moodle.net.
 
-    //do not check sesskey if confirm = false because this script is linked into email message
-    if (!empty($errormessage)) {
-        echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
+$notificationtype = \core\output\notification::NOTIFY_ERROR;
+if (\core\hub\registration::is_registered()) {
+    $lastupdated = \core\hub\registration::get_last_updated();
+    if ($lastupdated == 0) {
+        $registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
+    } else {
+        $lastupdated = userdate($lastupdated, get_string('strftimedate', 'langconfig'));
+        $registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
+        $notificationtype = \core\output\notification::NOTIFY_INFO;
     }
+    echo $OUTPUT->notification($registrationmessage, $notificationtype);
+} else {
+    $registrationmessage = get_string('registrationwarning', 'admin');
+    echo $OUTPUT->notification($registrationmessage, $notificationtype);
+}
 
-    echo $OUTPUT->heading(get_string('registerwith', 'hub'));
+// Heading.
+if (\core\hub\registration::is_registered()) {
+    echo $OUTPUT->heading(get_string('updatesite', 'hub', 'Moodle.net'));
+} else {
+    echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
+}
 
-    $hubselectorform->display();
+$renderer = $PAGE->get_renderer('core', 'register');
+echo $renderer->moodleorg_registration_message();
 
-    if (extension_loaded('xmlrpc')) {
-        $hubs = $registrationmanager->get_registered_on_hubs();
-        if (!empty($hubs)) {
-            echo $OUTPUT->heading(get_string('registeredon', 'hub'), 3, 'main');
-            echo $renderer->registeredonhublisting($hubs);
-        }
-    } else { //display notice about xmlrpc
-        $xmlrpcnotification = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
-        $xmlrpcnotification .= get_string('xmlrpcdisabledregistration', 'hub');
-        echo $OUTPUT->notification($xmlrpcnotification);
-    }
+$siteregistrationform->display();
+
+if (\core\hub\registration::is_registered()) {
+    // Unregister link.
+    $unregisterhuburl = new moodle_url("/admin/registration/index.php", ['unregistration' => 1]);
+    echo html_writer::div(html_writer::link($unregisterhuburl, get_string('unregister', 'hub')), 'unregister');
 }
 echo $OUTPUT->footer();
index 8d1f8db..72330f6 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-
-
-
-//// SITE PRIVACY /////
-
-/**
- * Site privacy: private
- */
-define('HUB_SITENOTPUBLISHED', 'notdisplayed');
-
-/**
- * Site privacy: public
- */
-define('HUB_SITENAMEPUBLISHED', 'named');
-
-/**
- * Site privacy: public and global
- */
-define('HUB_SITELINKPUBLISHED', 'linked');
-
-/**
- *
- * Site registration library
- *
- * @package   course
- * @copyright 2010 Moodle Pty Ltd (http://moodle.com)
- * @author    Jerome Mouneyrac
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class registration_manager {
-
-    /**
-     * Automatically update the registration on all hubs
-     */
-    public function cron() {
-        global $CFG;
-        if (extension_loaded('xmlrpc')) {
-            $function = 'hub_update_site_info';
-            require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
-
-            // Update all hubs where the site is registered.
-            $hubs = $this->get_registered_on_hubs();
-            if (empty($hubs)) {
-                mtrace(get_string('registrationwarning', 'admin'));
-            }
-            foreach ($hubs as $hub) {
-                // Update the registration.
-                $siteinfo = $this->get_site_info($hub->huburl);
-                $params = array('siteinfo' => $siteinfo);
-                $serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
-                $xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
-                try {
-                    $result = $xmlrpcclient->call($function, $params);
-                    $this->update_registeredhub($hub); // To update timemodified.
-                    mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
-                } catch (Exception $e) {
-                    $errorparam = new stdClass();
-                    $errorparam->errormessage = $e->getMessage();
-                    $errorparam->hubname = $hub->hubname;
-                    mtrace(get_string('errorcron', 'hub', $errorparam));
-                }
-            }
-        } else {
-            mtrace(get_string('errorcronnoxmlrpc', 'hub'));
-        }
-    }
-
-    /**
-     * Return the site secret for a given hub
-     * site identifier is assigned to Mooch
-     * each hub has a unique and personal site secret.
-     * @param string $huburl
-     * @return string site secret
-     */
-    public function get_site_secret_for_hub($huburl) {
-        global $DB;
-
-        $existingregistration = $DB->get_record('registration_hubs',
-                    array('huburl' => $huburl));
-
-        if (!empty($existingregistration)) {
-            return $existingregistration->secret;
-        }
-
-        if ($huburl == HUB_MOODLEORGHUBURL) {
-            $siteidentifier =  get_site_identifier();
-        } else {
-            $siteidentifier = random_string(32) . $_SERVER['HTTP_HOST'];
-        }
-
-        return $siteidentifier;
-
-    }
-
-    /**
-     * When the site register on a hub, he must call this function
-     * @param object $hub where the site is registered on
-     * @return integer id of the record
-     */
-    public function add_registeredhub($hub) {
-        global $DB;
-        $hub->timemodified = time();
-        $id = $DB->insert_record('registration_hubs', $hub);
-        return $id;
-    }
-
-    /**
-     * When a site unregister from a hub, he must call this function
-     * @param string $huburl the huburl to delete
-     */
-    public function delete_registeredhub($huburl) {
-        global $DB;
-        $DB->delete_records('registration_hubs', array('huburl' => $huburl));
-    }
-
-    /**
-     * Get a hub on which the site is registered for a given url or token
-     * Mostly use to check if the site is registered on a specific hub
-     * @param string $huburl
-     * @param string $token
-     * @return object the  hub
-     */
-    public function get_registeredhub($huburl = null, $token = null) {
-        global $DB;
-
-        $params = array();
-        if (!empty($huburl)) {
-            $params['huburl'] = $huburl;
-        }
-        if (!empty($token)) {
-            $params['token'] = $token;
-        }
-        $params['confirmed'] = 1;
-        $token = $DB->get_record('registration_hubs', $params);
-        return $token;
-    }
-
-    /**
-     * Get the hub which has not confirmed that the site is registered on,
-     * but for which a request has been sent
-     * @param string $huburl
-     * @return object the  hub
-     */
-    public function get_unconfirmedhub($huburl) {
-        global $DB;
-
-        $params = array();
-        $params['huburl'] = $huburl;
-        $params['confirmed'] = 0;
-        $token = $DB->get_record('registration_hubs', $params);
-        return $token;
-    }
-
-    /**
-     * Update a registered hub (mostly use to update the confirmation status)
-     * @param object $hub the hub
-     */
-    public function update_registeredhub($hub) {
-        global $DB;
-        $hub->timemodified = time();
-        $DB->update_record('registration_hubs', $hub);
-    }
-
-    /**
-     * Return all hubs where the site is registered
-     */
-    public function get_registered_on_hubs() {
-        global $DB;
-        $hubs = $DB->get_records('registration_hubs', array('confirmed' => 1));
-        return $hubs;
-    }
-
-    /**
-     * Return site information for a specific hub
-     * @param string $huburl
-     * @return array site info
-     */
-    public function get_site_info($huburl) {
-        global $CFG, $DB;
-
-        $siteinfo = array();
-        $cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
-        $siteinfo['name'] = get_config('hub', 'site_name_' . $cleanhuburl);
-        $siteinfo['description'] = get_config('hub', 'site_description_' . $cleanhuburl);
-        $siteinfo['contactname'] = get_config('hub', 'site_contactname_' . $cleanhuburl);
-        $siteinfo['contactemail'] = get_config('hub', 'site_contactemail_' . $cleanhuburl);
-        $siteinfo['contactphone'] = get_config('hub', 'site_contactphone_' . $cleanhuburl);
-        $siteinfo['imageurl'] = get_config('hub', 'site_imageurl_' . $cleanhuburl);
-        $siteinfo['privacy'] = get_config('hub', 'site_privacy_' . $cleanhuburl);
-        $siteinfo['street'] = get_config('hub', 'site_address_' . $cleanhuburl);
-        $siteinfo['regioncode'] = get_config('hub', 'site_region_' . $cleanhuburl);
-        $siteinfo['countrycode'] = get_config('hub', 'site_country_' . $cleanhuburl);
-        $siteinfo['geolocation'] = get_config('hub', 'site_geolocation_' . $cleanhuburl);
-        $siteinfo['contactable'] = get_config('hub', 'site_contactable_' . $cleanhuburl);
-        $siteinfo['emailalert'] = get_config('hub', 'site_emailalert_' . $cleanhuburl);
-        if (get_config('hub', 'site_coursesnumber_' . $cleanhuburl) == -1) {
-            $coursecount = -1;
-        } else {
-            $coursecount = $DB->count_records('course') - 1;
-        }
-        $siteinfo['courses'] = $coursecount;
-        if (get_config('hub', 'site_usersnumber_' . $cleanhuburl) == -1) {
-            $usercount = -1;
-        } else {
-            $usercount = $DB->count_records('user', array('deleted' => 0));
-        }
-        $siteinfo['users'] = $usercount;
-
-        if (get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl) == -1) {
-            $roleassigncount = -1;
-        } else {
-            $roleassigncount = $DB->count_records('role_assignments');
-        }
-        $siteinfo['enrolments'] = $roleassigncount;
-        if (get_config('hub', 'site_postsnumber_' . $cleanhuburl) == -1) {
-            $postcount = -1;
-        } else {
-            $postcount = $DB->count_records('forum_posts');
-        }
-        $siteinfo['posts'] = $postcount;
-        if (get_config('hub', 'site_questionsnumber_' . $cleanhuburl) == -1) {
-            $questioncount = -1;
-        } else {
-            $questioncount = $DB->count_records('question');
-        }
-        $siteinfo['questions'] = $questioncount;
-        if (get_config('hub', 'site_resourcesnumber_' . $cleanhuburl) == -1) {
-            $resourcecount = -1;
-        } else {
-            $resourcecount = $DB->count_records('resource');
-        }
-        $siteinfo['resources'] = $resourcecount;
-        // Badge statistics.
-        require_once($CFG->libdir . '/badgeslib.php');
-        if (get_config('hub', 'site_badges_' . $cleanhuburl) == -1) {
-            $badges = -1;
-        } else {
-            $badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
-        }
-        $siteinfo['badges'] = $badges;
-        if (get_config('hub', 'site_issuedbadges_' . $cleanhuburl) == -1) {
-            $issuedbadges = -1;
-        } else {
-            $issuedbadges = $DB->count_records('badge_issued');
-        }
-        $siteinfo['issuedbadges'] = $issuedbadges;
-        //TODO
-        require_once($CFG->dirroot . "/course/lib.php");
-        if (get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl) == -1) {
-            $participantnumberaverage = -1;
-        } else {
-            $participantnumberaverage = average_number_of_participants();
-        }
-        $siteinfo['participantnumberaverage'] = $participantnumberaverage;
-        if (get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl) == -1) {
-            $modulenumberaverage = -1;
-        } else {
-            $modulenumberaverage = average_number_of_courses_modules();
-        }
-        $siteinfo['modulenumberaverage'] = $modulenumberaverage;
-        $siteinfo['language'] = get_config('hub', 'site_language_' . $cleanhuburl);
-        $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;
-    }
-
-    /**
-     * Retrieve the site privacy string matching the define value
-     * @param string $privacy must match the define into moodlelib.php
-     * @return string
-     */
-    public function get_site_privacy_string($privacy) {
-        switch ($privacy) {
-            case HUB_SITENOTPUBLISHED:
-                $privacystring = get_string('siteprivacynotpublished', 'hub');
-                break;
-            case HUB_SITENAMEPUBLISHED:
-                $privacystring = get_string('siteprivacypublished', 'hub');
-                break;
-            case HUB_SITELINKPUBLISHED:
-                $privacystring = get_string('siteprivacylinked', 'hub');
-                break;
-        }
-        if (empty($privacystring)) {
-            throw new moodle_exception('unknownprivacy');
-        }
-        return $privacystring;
-    }
-
-}
-?>
+defined('MOODLE_INTERNAL') || die();
index 2b7cf96..ee2d534 100644 (file)
@@ -20,7 +20,7 @@
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-/*
+/**
  * @package    moodle
  * @subpackage registration
  * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
 
 
 require_once('../../config.php');
-require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
-require_once($CFG->dirroot . '/webservice/lib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
 
-require_sesskey();
-
-$huburl = required_param('huburl', PARAM_URL);
-$huburl = rtrim($huburl, "/");
-
-if ($huburl == HUB_MOODLEORGHUBURL) { // register to Moodle.org
-    admin_externalpage_setup('registrationmoodleorg');
-} else { //register to a hub
-    admin_externalpage_setup('registrationhub');
-}
-
-$password = optional_param('password', '', PARAM_TEXT);
-$hubname = optional_param('hubname', '', PARAM_TEXT);
-
-$registrationmanager = new registration_manager();
-
-$registeredhub = $registrationmanager->get_registeredhub($huburl);
-
-$siteregistrationform = new site_registration_form('',
-                array('alreadyregistered' => !empty($registeredhub->token),
-                    'huburl' => $huburl, 'hubname' => $hubname,
-                    'password' => $password));
-$fromform = $siteregistrationform->get_data();
-
-if (!empty($fromform) and confirm_sesskey()) {
-
-    // Set to -1 all optional data marked as "don't send" by the admin.
-    // The function get_site_info() will not calculate the optional data if config is set to -1.
-    $inputnames = array('courses', 'users', 'roleassignments', 'posts', 'questions', 'resources',
-        'badges', 'issuedbadges', 'modulenumberaverage', 'participantnumberaverage',
-        'mobileservicesenabled', 'mobilenotificationsenabled', 'registereduserdevices', 'registeredactiveuserdevices');
-    foreach ($inputnames as $inputname) {
-        if (empty($fromform->{$inputname})) {
-            $fromform->{$inputname} = -1;
-        }
-    }
-
-    // Save the settings.
-    $cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
-    set_config('site_name_' . $cleanhuburl, $fromform->name, 'hub');
-    set_config('site_description_' . $cleanhuburl, $fromform->description, 'hub');
-    set_config('site_contactname_' . $cleanhuburl, $fromform->contactname, 'hub');
-    set_config('site_contactemail_' . $cleanhuburl, $fromform->contactemail, 'hub');
-    set_config('site_contactphone_' . $cleanhuburl, $fromform->contactphone, 'hub');
-    set_config('site_imageurl_' . $cleanhuburl, $fromform->imageurl, 'hub');
-    set_config('site_privacy_' . $cleanhuburl, $fromform->privacy, 'hub');
-    set_config('site_address_' . $cleanhuburl, $fromform->address, 'hub');
-    set_config('site_region_' . $cleanhuburl, $fromform->regioncode, 'hub');
-    set_config('site_country_' . $cleanhuburl, $fromform->countrycode, 'hub');
-    set_config('site_language_' . $cleanhuburl, $fromform->language, 'hub');
-    set_config('site_geolocation_' . $cleanhuburl, $fromform->geolocation, 'hub');
-    set_config('site_contactable_' . $cleanhuburl, $fromform->contactable, 'hub');
-    set_config('site_emailalert_' . $cleanhuburl, $fromform->emailalert, 'hub');
-    set_config('site_coursesnumber_' . $cleanhuburl, $fromform->courses, 'hub');
-    set_config('site_usersnumber_' . $cleanhuburl, $fromform->users, 'hub');
-    set_config('site_roleassignmentsnumber_' . $cleanhuburl, $fromform->roleassignments, 'hub');
-    set_config('site_postsnumber_' . $cleanhuburl, $fromform->posts, 'hub');
-    set_config('site_questionsnumber_' . $cleanhuburl, $fromform->questions, 'hub');
-    set_config('site_resourcesnumber_' . $cleanhuburl, $fromform->resources, 'hub');
-    set_config('site_badges_' . $cleanhuburl, $fromform->badges, 'hub');
-    set_config('site_issuedbadges_' . $cleanhuburl, $fromform->issuedbadges, 'hub');
-    set_config('site_modulenumberaverage_' . $cleanhuburl, $fromform->modulenumberaverage, 'hub');
-    set_config('site_participantnumberaverage_' . $cleanhuburl, $fromform->participantnumberaverage, 'hub');
-    set_config('site_mobileservicesenabled_' . $cleanhuburl, $fromform->mobileservicesenabled, 'hub');
-    set_config('site_mobilenotificationsenabled_' . $cleanhuburl, $fromform->mobilenotificationsenabled, 'hub');
-    set_config('site_registereduserdevices_' . $cleanhuburl, $fromform->registereduserdevices, 'hub');
-    set_config('site_registeredactiveuserdevices_' . $cleanhuburl, $fromform->registeredactiveuserdevices, 'hub');
-}
-
-/////// UPDATE ACTION ////////
-
-// update the hub registration
-$update = optional_param('update', 0, PARAM_INT);
-if ($update and confirm_sesskey()) {
-
-    //update the registration
-    $function = 'hub_update_site_info';
-    $siteinfo = $registrationmanager->get_site_info($huburl);
-    $params = array('siteinfo' => $siteinfo);
-    $serverurl = $huburl . "/local/hub/webservice/webservices.php";
-    require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
-    $xmlrpcclient = new webservice_xmlrpc_client($serverurl, $registeredhub->token);
-    try {
-        $result = $xmlrpcclient->call($function, $params);
-        $registrationmanager->update_registeredhub($registeredhub); // To update timemodified.
-    } catch (Exception $e) {
-        $error = $OUTPUT->notification(get_string('errorregistration', 'hub', $e->getMessage()));
-    }
-}
-
-/////// FORM REGISTRATION ACTION //////
-
-if (!empty($fromform) and empty($update) and confirm_sesskey()) {
-
-    if (!empty($fromform) and confirm_sesskey()) { // if the register button has been clicked
-
-        // Retrieve the optional info (specially course number, user number, module number average...).
-        $siteinfo = $registrationmanager->get_site_info($huburl);
-        $fromform->courses = $siteinfo['courses'];
-        $fromform->users = $siteinfo['users'];
-        $fromform->enrolments = $siteinfo['enrolments'];
-        $fromform->posts = $siteinfo['posts'];
-        $fromform->questions = $siteinfo['questions'];
-        $fromform->resources = $siteinfo['resources'];
-        $fromform->badges = $siteinfo['badges'];
-        $fromform->issuedbadges = $siteinfo['issuedbadges'];
-        $fromform->modulenumberaverage = $siteinfo['modulenumberaverage'];
-        $fromform->participantnumberaverage = $siteinfo['participantnumberaverage'];
-        $fromform->street = $siteinfo['street'];
-        $fromform->mobileservicesenabled = $siteinfo['mobileservicesenabled'];
-        $fromform->mobilenotificationsenabled = $siteinfo['mobilenotificationsenabled'];
-        $fromform->registereduserdevices = $siteinfo['registereduserdevices'];
-        $fromform->registeredactiveuserdevices = $siteinfo['registeredactiveuserdevices'];
-
-        $params = (array) $fromform; //we are using the form input as the redirection parameters (token, url and name)
-
-        $unconfirmedhub = $registrationmanager->get_unconfirmedhub($huburl);
-        if (empty($unconfirmedhub)) {
-            //we save the token into the communication table in order to have a reference
-            $unconfirmedhub = new stdClass();
-            $unconfirmedhub->token = $registrationmanager->get_site_secret_for_hub($huburl);
-            $unconfirmedhub->secret = $unconfirmedhub->token;
-            $unconfirmedhub->huburl = $huburl;
-            $unconfirmedhub->hubname = $hubname;
-            $unconfirmedhub->confirmed = 0;
-            $unconfirmedhub->id = $registrationmanager->add_registeredhub($unconfirmedhub);
-        }
-
-        $params['token'] = $unconfirmedhub->token;
-        $params['url'] = $CFG->wwwroot;
-        redirect(new moodle_url($huburl . '/local/hub/siteregistration.php', $params));
-    }
-}
-
-/////// OUTPUT SECTION /////////////
-
-echo $OUTPUT->header();
-//Display update notification result
-if (!empty($registeredhub->confirmed)) {
-    if (!empty($result)) {
-        echo $OUTPUT->notification(get_string('siteregistrationupdated', 'hub'), 'notifysuccess');
-    }
-}
-
-if (!empty($error)) {
-    echo $error;
-}
-
-// Some Moodle.org registration explanation.
-if ($huburl == HUB_MOODLEORGHUBURL) {
-    $notificationtype = \core\output\notification::NOTIFY_ERROR;
-    if (!empty($registeredhub->token)) {
-        if ($registeredhub->timemodified == 0) {
-            $registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
-        } else {
-            $lastupdated = userdate($registeredhub->timemodified, get_string('strftimedate', 'langconfig'));
-            $registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
-            $notificationtype = \core\output\notification::NOTIFY_INFO;
-        }
-    } else {
-        $registrationmessage = get_string('registrationwarning', 'admin');
-    }
-    echo $OUTPUT->notification($registrationmessage, $notificationtype);
-
-    echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
-    $renderer = $PAGE->get_renderer('core', 'register');
-    echo $renderer->moodleorg_registration_message();
-}
-
-$siteregistrationform->display();
-echo $OUTPUT->footer();
+redirect(new moodle_url('/admin/registration/index.php'));
\ No newline at end of file
index 09d2735..196d680 100644 (file)
@@ -46,50 +46,4 @@ class core_register_renderer extends plugin_renderer_base {
         $moodleorgregmsg .= html_writer::alist($items);
         return $moodleorgregmsg;
     }
-
-    /**
-     * Display a box message confirming a site registration (add or update)
-     * @param string $confirmationmessage
-     * @return string
-     */
-    public function registration_confirmation($confirmationmessage) {
-        $linktositelist = html_writer::tag('a', get_string('sitelist', 'hub'),
-                        array('href' => new moodle_url('/local/hub/index.php')));
-        $message = $confirmationmessage . html_writer::empty_tag('br') . $linktositelist;
-        return $this->output->box($message);
-    }
-
-    /**
-     * Display the listing of registered on hub
-     */
-    public function registeredonhublisting($hubs) {
-        global $CFG;
-        $table = new html_table();
-        $table->head = array(get_string('hub', 'hub'), get_string('operation', 'hub'));
-        $table->size = array('80%', '20%');
-
-        foreach ($hubs as $hub) {
-            if ($hub->huburl == HUB_MOODLEORGHUBURL) {
-                $hub->hubname = get_string('registeredmoodleorg', 'hub', $hub->hubname);
-            }
-            $hublink = html_writer::tag('a', $hub->hubname, array('href' => $hub->huburl));
-            $hublinkcell = html_writer::tag('div', $hublink, array('class' => 'registeredhubrow'));
-
-            $unregisterhuburl = new moodle_url("/" . $CFG->admin . "/registration/index.php",
-                            array('sesskey' => sesskey(), 'huburl' => $hub->huburl,
-                                'unregistration' => 1));
-            $unregisterbutton = new single_button($unregisterhuburl,
-                            get_string('unregister', 'hub'));
-            $unregisterbutton->class = 'centeredbutton';
-            $unregisterbuttonhtml = $this->output->render($unregisterbutton);
-
-            //add button cells
-            $cells = array($hublinkcell, $unregisterbuttonhtml);
-            $row = new html_table_row($cells);
-            $table->data[] = $row;
-        }
-
-        return html_writer::table($table);
-    }
-
 }
index dd15463..7926e0f 100644 (file)
@@ -20,7 +20,7 @@
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
-/*
+/**
  * @package    moodle
  * @subpackage registration
  * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
 
 require('../../config.php');
 require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
 
 $url = optional_param('url', '', PARAM_URL);
-$hubname = optional_param('hubname', '', PARAM_TEXT);
 $token = optional_param('token', '', PARAM_TEXT);
 
-admin_externalpage_setup('registrationhubs');
+admin_externalpage_setup('registrationmoodleorg');
 
-//check that we are waiting a confirmation from this hub, and check that the token is correct
-$registrationmanager = new registration_manager();
-$registeredhub = $registrationmanager->get_unconfirmedhub($url);
-if (!empty($registeredhub) and $registeredhub->token == $token) {
-
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
-    $hublink = html_writer::tag('a', $hubname, array('href' => $url));
+if ($url !== HUB_MOODLEORGHUBURL) {
+    throw new moodle_exception('errorotherhubsnotsupported', 'hub');
+}
 
-    $registrationmanager->delete_registeredhub($url);
+// Check that we are waiting a confirmation from this hub, and check that the token is correct.
+\core\hub\registration::reset_site_identifier($token);
 
-    //Mooch case, need to recreate the siteidentifier
-    if ($url == HUB_MOODLEORGHUBURL) {
-        $CFG->siteidentifier = null;
-        get_site_identifier();
-    }
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
+$hublink = html_writer::tag('a', 'Moodle.net', array('href' => HUB_MOODLEORGHUBURL));
 
-    $deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
+$deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
 
-    $button = new single_button(new moodle_url('/admin/registration/index.php'),
-                    get_string('restartregistration', 'hub'));
-    $button->class = 'restartregbutton';
+$button = new single_button(new moodle_url('/admin/registration/index.php'),
+                get_string('restartregistration', 'hub'));
+$button->class = 'restartregbutton';
 
-    echo html_writer::tag('div', $deletedregmsg . $OUTPUT->render($button),
-            array('class' => 'mdl-align'));
+echo html_writer::tag('div', $deletedregmsg . $OUTPUT->render($button),
+        array('class' => 'mdl-align'));
 
-    echo $OUTPUT->footer();
-} else {
-    throw new moodle_exception('wrongtoken', 'hub',
-            $CFG->wwwroot . '/' . $CFG->admin . '/registration/index.php');
-}
+echo $OUTPUT->footer();
 
 
index 561b24a..7dd4808 100644 (file)
@@ -805,8 +805,7 @@ class core_admin_renderer extends plugin_renderer_base {
         if (!$registered) {
 
             if (has_capability('moodle/site:config', context_system::instance())) {
-                $registerbutton = $this->single_button(new moodle_url('/admin/registration/register.php',
-                    array('huburl' =>  HUB_MOODLEORGHUBURL, 'hubname' => 'Moodle.net')),
+                $registerbutton = $this->single_button(new moodle_url('/admin/registration/index.php'),
                     get_string('register', 'admin'));
                 $str = 'registrationwarning';
             } else {
@@ -828,10 +827,7 @@ class core_admin_renderer extends plugin_renderer_base {
      * @return string
      */
     public function warn_if_not_registered() {
-        global $CFG;
-        require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
-        $registrationmanager = new registration_manager();
-        return $this->registration_warning($registrationmanager->get_registeredhub(HUB_MOODLEORGHUBURL) ? true : false);
+        return $this->registration_warning(\core\hub\registration::is_registered());
     }
 
     /**
index fb38431..623cf1c 100644 (file)
@@ -5,11 +5,19 @@
 require_once('../config.php');
 require_once($CFG->libdir.'/adminlib.php');
 
+redirect_if_major_upgrade_required();
+
 $query = trim(optional_param('query', '', PARAM_NOTAGS));  // Search string
 
 $context = context_system::instance();
 $PAGE->set_context($context);
 
+$hassiteconfig = has_capability('moodle/site:config', $context);
+
+if ($hassiteconfig && moodle_needs_upgrading()) {
+    redirect(new moodle_url('/admin/index.php'));
+}
+
 admin_externalpage_setup('search', '', array('query' => $query)); // now hidden page
 
 $adminroot = admin_get_root(); // need all settings here
@@ -55,7 +63,7 @@ if ($errormsg !== '') {
 
 $showsettingslinks = true;
 
-if (has_capability('moodle/site:config', $context)) {
+if ($hassiteconfig) {
     require_once("admin_settings_search_form.php");
     $form = new admin_settings_search_form();
     $form->display();
index 3bb3c4a..4444ff0 100644 (file)
@@ -557,13 +557,21 @@ if ($hassiteconfig) {
     $temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
     $temp->add(new admin_setting_configselect('searchengine',
                                 new lang_string('selectsearchengine', 'admin'), '', 'solr', $engines));
-    $temp->add(new admin_setting_heading('searchindexingheading', new lang_string('searchoptions', 'admin'), ''));
+    $temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
     $temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
             new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
             0));
     $temp->add(new admin_setting_configduration('searchindextime',
             new lang_string('searchindextime', 'admin'), new lang_string('searchindextime_desc', 'admin'),
             600));
+    $options = [
+        0 => new lang_string('searchallavailablecourses_off', 'admin'),
+        1 => new lang_string('searchallavailablecourses_on', 'admin')
+    ];
+    $temp->add(new admin_setting_configselect('searchallavailablecourses',
+            new lang_string('searchallavailablecourses', 'admin'),
+            new lang_string('searchallavailablecourses_desc', 'admin'),
+            0, $options));
 
     $ADMIN->add('searchplugins', $temp);
     $ADMIN->add('searchplugins', new admin_externalpage('searchareas', new lang_string('searchareas', 'admin'),
index e847077..c0d57c3 100644 (file)
@@ -211,9 +211,6 @@ $temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('
 $ADMIN->add('server', $temp);
 
 
-$ADMIN->add('server', new admin_externalpage('adminregistration', new lang_string('hubs', 'admin'),
-    "$CFG->wwwroot/$CFG->admin/registration/index.php"));
-
 // E-mail settings.
 $ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
 
index be45ef6..17621cb 100644 (file)
@@ -11,14 +11,7 @@ $hassiteconfig = has_capability('moodle/site:config', $systemcontext);
 $ADMIN->add('root', new admin_externalpage('adminnotifications', new lang_string('notifications'), "$CFG->wwwroot/$CFG->admin/index.php"));
 
 $ADMIN->add('root', new admin_externalpage('registrationmoodleorg', new lang_string('registration', 'admin'),
-        "$CFG->wwwroot/$CFG->admin/registration/register.php?huburl=" . HUB_MOODLEORGHUBURL . "&hubname=Moodle.net&sesskey=" . sesskey()));
-$ADMIN->add('root', new admin_externalpage('registrationhub', new lang_string('registerwith', 'hub'),
-        "$CFG->wwwroot/$CFG->admin/registration/register.php", 'moodle/site:config', true));
-$ADMIN->add('root', new admin_externalpage('registrationhubs', new lang_string('hubs', 'admin'),
-        "$CFG->wwwroot/$CFG->admin/registration/index.php", 'moodle/site:config', true));
-$ADMIN->add('root', new admin_externalpage('siteregistrationconfirmed',
-        new lang_string('registrationconfirmed', 'hub'),
-        $CFG->wwwroot."/".$CFG->admin."/registration/confirmregistration.php", 'moodle/site:config', true));
+        new moodle_url("/admin/registration/index.php")));
  // hidden upgrade script
 $ADMIN->add('root', new admin_externalpage('upgradesettings', new lang_string('upgradesettings', 'admin'), "$CFG->wwwroot/$CFG->admin/upgradesettings.php", 'moodle/site:config', true));
 
index 3c247e3..493b7da 100644 (file)
@@ -58,15 +58,26 @@ class api {
         global $CFG;
         require_once($CFG->libdir . '/adminlib.php');
 
+        $cachekey = 'mobileplugins';
+        if (!isloggedin()) {
+            $cachekey = 'authmobileplugins';    // Use a different cache for not logged users.
+        }
+
         // Check if we can return this from cache.
         $cache = \cache::make('tool_mobile', 'plugininfo');
-        $pluginsinfo = $cache->get('mobileplugins');
+        $pluginsinfo = $cache->get($cachekey);
         if ($pluginsinfo !== false) {
             return (array)$pluginsinfo;
         }
 
         $pluginsinfo = [];
-        $plugintypes = core_component::get_plugin_types();
+        // For not logged users return only auth plugins.
+        // This is to avoid anyone (not being a registered user) to obtain and download all the site remote add-ons.
+        if (!isloggedin()) {
+            $plugintypes = array('auth' => $CFG->dirroot.'/auth');
+        } else {
+            $plugintypes = core_component::get_plugin_types();
+        }
 
         foreach ($plugintypes as $plugintype => $unused) {
             // We need to include files here.
@@ -100,7 +111,7 @@ class api {
             }
         }
 
-        $cache->set('mobileplugins', $pluginsinfo);
+        $cache->set($cachekey, $pluginsinfo);
 
         return $pluginsinfo;
     }
@@ -211,6 +222,7 @@ class api {
         }
 
         if (empty($section) or $section == 'sitepolicies') {
+            $settings->sitepolicy = $CFG->sitepolicy;
             $settings->disableuserimages = $CFG->disableuserimages;
         }
 
index 3c60740..d54d748 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 namespace tool_mobile;
+defined('MOODLE_INTERNAL') || die();
 
 require_once("$CFG->libdir/externallib.php");
 
index 9a22aa8..aa64cc7 100644 (file)
@@ -30,7 +30,9 @@ $functions = array(
         'methodname'  => 'get_plugins_supporting_mobile',
         'description' => 'Returns a list of Moodle plugins supporting the mobile app.',
         'type'        => 'read',
-        'services'    => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
+        'services'    => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+        'ajax'          => true,
+        'loginrequired' => false,
     ),
 
     'tool_mobile_get_public_config' => array(
index 126ea1c..328011a 100644 (file)
@@ -123,6 +123,10 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         require_once($CFG->dirroot . '/course/format/lib.php');
 
         $this->resetAfterTest(true);
+
+        $mysitepolicy = 'http://mysite.is/policy/';
+        set_config('sitepolicy', $mysitepolicy);
+
         $result = external::get_config();
         $result = external_api::clean_returnvalue(external::get_config_returns(), $result);
 
@@ -143,6 +147,7 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
             array('name' => 'numsections', 'value' => course_get_format($SITE)->get_last_section_number()),
             array('name' => 'newsitems', 'value' => $SITE->newsitems),
             array('name' => 'commentsperpage', 'value' => $CFG->commentsperpage),
+            array('name' => 'sitepolicy', 'value' => $mysitepolicy),
             array('name' => 'disableuserimages', 'value' => $CFG->disableuserimages),
             array('name' => 'mygradesurl', 'value' => user_mygrades_url()->out(false)),
             array('name' => 'tool_mobile_forcelogout', 'value' => 0),
index 9a93520..6c2c704 100644 (file)
@@ -1,6 +1,11 @@
 This files describes changes in tool_mobile code.
 Information provided here is intended especially for developers.
 
+=== 3.4 ===
+
+ * External function tool_mobile::tool_mobile_get_plugins_supporting_mobile is now available via AJAX for not logged users.
+   When called via AJAX without a user session the function will return only auth plugins.
+
 === 3.3 ===
 
  * External function tool_mobile::get_public_config now returns the mobilecssurl field (Mobile custom CSS theme).
index 0903cc5..34163ae 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 defined('MOODLE_INTERNAL') || die();
-$plugin->version   = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->version   = 2017051501; // The current plugin version (Date: YYYYMMDDXX).
 $plugin->requires  = 2017050500; // Requires this Moodle version.
 $plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
 $plugin->dependencies = array(
index b92f608..f1c72f5 100644 (file)
@@ -22,6 +22,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 namespace tool_templatelibrary;
+defined('MOODLE_INTERNAL') || die();
 
 require_once("$CFG->libdir/externallib.php");
 
index 7c6aa3a..5cd88b9 100644 (file)
@@ -147,7 +147,7 @@ abstract class base extends \core_analytics\calculable {
      * @param integer $starttime Limit the calculation to this timestart
      * @param integer $endtime Limit the calculation to this timeend
      * @param array $existingcalculations Existing calculations of this indicator, indexed by sampleid.
-     * @return array array[0] with format [sampleid] = int[]|float[], array[1] with format [sampleid] = int|float
+     * @return array [0] = [$sampleid => int[]|float[]], [1] = [$sampleid => int|float], [2] = [$sampleid => $sampleid]
      */
     public function calculate($sampleids, $samplesorigin, $starttime = false, $endtime = false, $existingcalculations = array()) {
 
@@ -157,6 +157,7 @@ abstract class base extends \core_analytics\calculable {
 
         $calculations = array();
         $newcalculations = array();
+        $notnulls = array();
         foreach ($sampleids as $sampleid => $unusedsampleid) {
 
             if (isset($existingcalculations[$sampleid])) {
@@ -166,9 +167,12 @@ abstract class base extends \core_analytics\calculable {
                 $newcalculations[$sampleid] = $calculatedvalue;
             }
 
-            if (!is_null($calculatedvalue) && ($calculatedvalue > self::MAX_VALUE || $calculatedvalue < self::MIN_VALUE)) {
-                throw new \coding_exception('Calculated values should be higher than ' . self::MIN_VALUE .
-                    ' and lower than ' . self::MAX_VALUE . ' ' . $calculatedvalue . ' received');
+            if (!is_null($calculatedvalue)) {
+                $notnulls[$sampleid] = $sampleid;
+                if ($calculatedvalue > self::MAX_VALUE || $calculatedvalue < self::MIN_VALUE) {
+                    throw new \coding_exception('Calculated values should be higher than ' . self::MIN_VALUE .
+                        ' and lower than ' . self::MAX_VALUE . ' ' . $calculatedvalue . ' received');
+                }
             }
 
             $calculations[$sampleid] = $calculatedvalue;
@@ -176,6 +180,6 @@ abstract class base extends \core_analytics\calculable {
 
         $features = $this->to_features($calculations);
 
-        return array($features, $newcalculations);
+        return array($features, $newcalculations, $notnulls);
     }
 }
index f45934a..11532a9 100644 (file)
@@ -231,6 +231,9 @@ abstract class base {
                 $range['start'], $range['end'], $samplesorigin);
         }
 
+        // Here we store samples which calculations are not all null.
+        $notnulls = array();
+
         // Fill the dataset samples with indicators data.
         $newcalculations = array();
         foreach ($indicators as $indicator) {
@@ -250,7 +253,7 @@ abstract class base {
                 }
 
                 // Calculate the indicator for each sample in this time range.
-                list($samplesfeatures, $newindicatorcalculations) = $rangeindicator->calculate($sampleids,
+                list($samplesfeatures, $newindicatorcalculations, $indicatornotnulls) = $rangeindicator->calculate($sampleids,
                     $samplesorigin, $range['start'], $range['end'], $prevcalculations);
 
                 // Copy the features data to the dataset.
@@ -258,6 +261,10 @@ abstract class base {
 
                     $uniquesampleid = $this->append_rangeindex($analysersampleid, $rangeindex);
 
+                    if (!isset($notnulls[$uniquesampleid]) && !empty($indicatornotnulls[$analysersampleid])) {
+                        $notnulls[$uniquesampleid] = $uniquesampleid;
+                    }
+
                     // Init the sample if it is still empty.
                     if (!isset($dataset[$uniquesampleid])) {
                         $dataset[$uniquesampleid] = array();
@@ -307,6 +314,15 @@ abstract class base {
             $DB->insert_records('analytics_indicator_calc', $newcalculations);
         }
 
+        // Delete rows where all calculations are null.
+        // We still store the indicator calculation and we still store the sample id as
+        // processed so we don't have to process this sample again, but we exclude it
+        // from the dataset because it is not useful.
+        $nulls = array_diff_key($dataset, $notnulls);
+        foreach ($nulls as $uniqueid => $ignoredvalues) {
+            unset($dataset[$uniqueid]);
+        }
+
         return $dataset;
     }
 
index 1e21d8d..7f30037 100644 (file)
@@ -361,6 +361,57 @@ class core_analytics_prediction_testcase extends advanced_testcase {
         list($values, $unused) = $indicator->calculate($sampleids, $sampleorigin, $starttime, $endtime, $existingcalcs);
     }
 
+    /**
+     * test_not_null_samples
+     */
+    public function test_not_null_samples() {
+        $this->resetAfterTest(true);
+
+        $classname = '\core\analytics\time_splitting\quarters';
+        $timesplitting = \core_analytics\manager::get_time_splitting($classname);
+        $timesplitting->set_analysable(new \core_analytics\site());
+
+        $ranges = array(
+            array('start' => 111, 'end' => 222, 'time' => 222),
+            array('start' => 222, 'end' => 333, 'time' => 333)
+        );
+        $samples = array(123 => 123, 321 => 321);
+
+        $indicator1 = $this->getMockBuilder('test_indicator_max')
+            ->setMethods(['calculate_sample'])
+            ->getMock();
+        $indicator1->method('calculate_sample')
+            ->willReturn(null);
+
+        $indicator2 = \core_analytics\manager::get_indicator('test_indicator_min');
+
+        // Samples with at least 1 not null value are returned.
+        $params = array(
+            $samples,
+            'whatever',
+            array($indicator1, $indicator2),
+            $ranges
+        );
+        $dataset = phpunit_util::call_internal_method($timesplitting, 'calculate_indicators', $params, $classname);
+        $this->assertArrayHasKey('123-0', $dataset);
+        $this->assertArrayHasKey('123-1', $dataset);
+        $this->assertArrayHasKey('321-0', $dataset);
+        $this->assertArrayHasKey('321-1', $dataset);
+
+        // Samples with only null values are not returned.
+        $params = array(
+            $samples,
+            'whatever',
+            array($indicator1),
+            $ranges
+        );
+        $dataset = phpunit_util::call_internal_method($timesplitting, 'calculate_indicators', $params, $classname);
+        $this->assertArrayNotHasKey('123-0', $dataset);
+        $this->assertArrayNotHasKey('123-1', $dataset);
+        $this->assertArrayNotHasKey('321-0', $dataset);
+        $this->assertArrayNotHasKey('321-1', $dataset);
+    }
+
     /**
      * provider_ml_test_evaluation
      *
index d951a2f..a36ceb3 100644 (file)
@@ -137,7 +137,7 @@ class auth_email_external extends external_api {
                      new external_value(PARAM_NOTAGS, 'The order of the name fields')
                 ),
                 'passwordpolicy' => new external_value(PARAM_RAW, 'Password policy', VALUE_OPTIONAL),
-                'sitepolicy' => new external_value(PARAM_URL, 'Site policy url', VALUE_OPTIONAL),
+                'sitepolicy' => new external_value(PARAM_RAW, 'Site policy', VALUE_OPTIONAL),
                 'defaultcity' => new external_value(PARAM_NOTAGS, 'Default city', VALUE_OPTIONAL),
                 'country' => new external_value(PARAM_ALPHA, 'Default country', VALUE_OPTIONAL),
                 'profilefields' => new external_multiple_structure(
index 122408f..af22ff5 100644 (file)
@@ -529,7 +529,7 @@ class backup_enrolments_structure_step extends backup_structure_step {
         $enrol->annotate_ids('role', 'roleid');
 
         // Add enrol plugin structure.
-        $this->add_plugin_structure('enrol', $enrol, false);
+        $this->add_plugin_structure('enrol', $enrol, true);
 
         return $enrolments;
     }
index 18a57d7..0825798 100644 (file)
@@ -38,40 +38,37 @@ class block_calendar_month extends block_base {
     public function get_content() {
         global $CFG;
 
-        $calm = optional_param('cal_m', 0, PARAM_INT);
-        $caly = optional_param('cal_y', 0, PARAM_INT);
-        $time = optional_param('time', 0, PARAM_INT);
-
         require_once($CFG->dirroot.'/calendar/lib.php');
 
         if ($this->content !== null) {
             return $this->content;
         }
 
-        // If a day, month and year were passed then convert it to a timestamp. If these were passed then we can assume
-        // the day, month and year are passed as Gregorian, as no where in core should we be passing these values rather
-        // than the time. This is done for BC.
-        if (!empty($calm) && (!empty($caly))) {
-            $time = make_timestamp($caly, $calm, 1);
-        } else if (empty($time)) {
-            $time = time();
-        }
-
         $this->content = new stdClass;
         $this->content->text = '';
         $this->content->footer = '';
 
-        // [pj] To me it looks like this if would never be needed, but Penny added it
-        // when committing the /my/ stuff. Reminder to discuss and learn what it's about.
-        // It definitely needs SOME comment here!
         $courseid = $this->page->course->id;
         $issite = ($courseid == SITEID);
 
+        $course = null;
+        $courses = null;
+        $categories = null;
+
         if ($issite) {
             // Being displayed at site level. This will cause the filter to fall back to auto-detecting
             // the list of courses it will be grabbing events from.
             $course = get_site();
             $courses = calendar_get_default_courses();
+
+            if ($this->page->context->contextlevel === CONTEXT_COURSECAT) {
+                // Restrict to categories, and their parents, and the courses that the user is enrolled in within those
+                // categories.
+                $categories = array_keys($this->page->categories);
+                $courses = array_filter($courses, function($course) use ($categories) {
+                    return array_search($course->category, $categories) !== false;
+                });
+            }
         } else {
             // Forcibly filter events to include only those from the particular course we are in.
             $course = $this->page->course;
@@ -80,8 +77,8 @@ class block_calendar_month extends block_base {
 
         $renderer = $this->page->get_renderer('core_calendar');
 
-        $calendar = new calendar_information(0, 0, 0, $time);
-        $calendar->prepare_for_view($course, $courses);
+        $calendar = new calendar_information();
+        $calendar->set_sources($course, $courses, $this->page->category);
 
         list($data, $template) = calendar_get_view($calendar, 'mini');
         $this->content->text .= $renderer->render_from_template($template, $data);
index d27cb07..bc13ad2 100644 (file)
@@ -31,7 +31,6 @@
 require('../../config.php');
 require_once($CFG->dirroot . '/blocks/community/locallib.php');
 require_once($CFG->dirroot . '/blocks/community/forms.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
 
 require_login();
 $courseid = required_param('courseid', PARAM_INT); //if no courseid is given
@@ -48,21 +47,8 @@ $PAGE->navbar->add(get_string('searchcourse', 'block_community'));
 $search = optional_param('search', null, PARAM_TEXT);
 
 //if no capability to search course, display an error message
-$usercansearch = has_capability('moodle/community:add', $context);
+require_capability('moodle/community:add', $context);
 $usercandownload = has_capability('moodle/community:download', $context);
-if (empty($usercansearch)) {
-    $notificationerror = get_string('cannotsearchcommunity', 'hub');
-} else if (!extension_loaded('xmlrpc')) {
-    $notificationerror = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
-    $notificationerror .= get_string('xmlrpcdisabledcommunity', 'hub');
-}
-if (!empty($notificationerror)) {
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('searchcommunitycourse', 'block_community'), 3, 'main');
-    echo $OUTPUT->notification($notificationerror);
-    echo $OUTPUT->footer();
-    die();
-}
 
 $communitymanager = new block_community_manager();
 $renderer = $PAGE->get_renderer('block_community');
@@ -93,17 +79,11 @@ if ($usercandownload and $cancelrestore and confirm_sesskey()) {
 }
 
 /// Download
-$huburl = optional_param('huburl', false, PARAM_URL);
 $download = optional_param('download', -1, PARAM_INT);
 $downloadcourseid = optional_param('downloadcourseid', '', PARAM_INT);
 $coursefullname = optional_param('coursefullname', '', PARAM_ALPHANUMEXT);
 $backupsize = optional_param('backupsize', 0, PARAM_INT);
 if ($usercandownload and $download != -1 and !empty($downloadcourseid) and confirm_sesskey()) {
-    $course = new stdClass();
-    $course->fullname = $coursefullname;
-    $course->id = $downloadcourseid;
-    $course->huburl = $huburl;
-
     //OUTPUT: display restore choice page
     echo $OUTPUT->header();
     echo $OUTPUT->heading(get_string('downloadingcourse', 'block_community'), 3, 'main');
@@ -115,12 +95,12 @@ if ($usercandownload and $download != -1 and !empty($downloadcourseid) and confi
         ob_flush();
     }
     flush();
-    $filenames = $communitymanager->block_community_download_course_backup($course);
+    list($privatefilename, $tmpfilename) = \core\hub\publication::download_course_backup($downloadcourseid, $coursefullname);
     echo html_writer::tag('div', get_string('downloaded', 'block_community'),
             array('class' => 'textinfo'));
     echo $OUTPUT->notification(get_string('downloadconfirmed', 'block_community',
-                    '/downloaded_backup/' . $filenames['privatefile']), 'notifysuccess');
-    echo $renderer->restore_confirmation_box($filenames['tmpfile'], $context);
+                    $privatefilename), 'notifysuccess');
+    echo $renderer->restore_confirmation_box($tmpfilename, $context);
     echo $OUTPUT->footer();
     die();
 }
@@ -145,7 +125,6 @@ $fromformdata['language'] = optional_param('language', current_language(), PARAM
 $fromformdata['educationallevel'] = optional_param('educationallevel', 'all', PARAM_ALPHANUMEXT);
 $fromformdata['downloadable'] = optional_param('downloadable', $usercandownload, PARAM_ALPHANUM);
 $fromformdata['orderby'] = optional_param('orderby', 'newest', PARAM_ALPHA);
-$fromformdata['huburl'] = optional_param('huburl', HUB_MOODLEORGHUBURL, PARAM_URL);
 $fromformdata['search'] = $search;
 $fromformdata['courseid'] = $courseid;
 $hubselectorform = new community_hub_search_form('', $fromformdata);
@@ -181,35 +160,14 @@ if (optional_param('executesearch', 0, PARAM_INT) and confirm_sesskey()) {
     //the range of course requested
     $options->givememore = optional_param('givememore', 0, PARAM_INT);
 
-    //check if the selected hub is from the registered list (in this case we use the private token)
-    $token = 'publichub';
-    $registrationmanager = new registration_manager();
-    $registeredhubs = $registrationmanager->get_registered_on_hubs();
-    foreach ($registeredhubs as $registeredhub) {
-        if ($huburl == $registeredhub->huburl) {
-            $token = $registeredhub->token;
-        }
-    }
-
-    $function = 'hub_get_courses';
-    $params = array('search' => $search, 'downloadable' => $downloadable,
-        'enrollable' => intval(!$downloadable), 'options' => $options);
-    $serverurl = $huburl . "/local/hub/webservice/webservices.php";
-    require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
-    $xmlrpcclient = new webservice_xmlrpc_client($serverurl, $token);
-    try {
-        $result = $xmlrpcclient->call($function, array_values($params));
-        $courses = $result['courses'];
-        $coursetotal = $result['coursetotal'];
-    } catch (Exception $e) {
-        $errormessage = $OUTPUT->notification(
-                        get_string('errorcourselisting', 'block_community', $e->getMessage()));
-    }
+    list($courses, $coursetotal) = \core\hub\publication::search($search, $downloadable, $options);
 }
 
 // OUTPUT
 echo $OUTPUT->header();
 echo $OUTPUT->heading(get_string('searchcommunitycourse', 'block_community'), 3, 'main');
+echo $renderer->moodlenet_info();
+
 $hubselectorform->display();
 if (!empty($errormessage)) {
     echo $errormessage;
@@ -232,9 +190,9 @@ $PAGE->requires->yui_module('moodle-block_community-comments', 'M.blocks_communi
         array(array('commentids' => $commentedcourseids, 'closeButtonTitle' => get_string('close', 'editor'))));
 $PAGE->requires->yui_module('moodle-block_community-imagegallery', 'M.blocks_community.init_imagegallery',
         array(array('imageids' => $courseids, 'imagenumbers' => $courseimagenumbers,
-                'huburl' => $huburl, 'closeButtonTitle' => get_string('close', 'editor'))));
+                'huburl' => HUB_MOODLEORGHUBURL, 'closeButtonTitle' => get_string('close', 'editor'))));
 
-echo highlight($search, $renderer->course_list($courses, $huburl, $courseid));
+echo highlight($search, $renderer->course_list($courses, null, $courseid));
 
 //display givememore/Next link if more course can be displayed
 if (!empty($courses)) {
index a61b273..8142b5c 100644 (file)
  */
 
 require_once($CFG->libdir . '/formslib.php');
-require_once($CFG->dirroot . '/course/publish/lib.php');
-require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
 
 class community_hub_search_form extends moodleform {
 
     public function definition() {
-        global $CFG, $USER, $OUTPUT;
-        $strrequired = get_string('required');
+        global $CFG;
         $mform = & $this->_form;
 
         //set default value
@@ -81,11 +78,6 @@ class community_hub_search_form extends moodleform {
         } else {
             $orderby = 'newest';
         }
-        if (isset($this->_customdata['huburl'])) {
-            $huburl = $this->_customdata['huburl'];
-        } else {
-            $huburl = HUB_MOODLEORGHUBURL;
-        }
 
         $mform->addElement('header', 'site', get_string('search', 'block_community'));
 
@@ -95,222 +87,87 @@ class community_hub_search_form extends moodleform {
         $mform->addElement('hidden', 'executesearch', 1);
         $mform->setType('executesearch', PARAM_INT);
 
-        //retrieve the hub list on the hub directory by web service
-        $function = 'hubdirectory_get_hubs';
-        $params = array();
-        $serverurl = HUB_HUBDIRECTORYURL . "/local/hubdirectory/webservice/webservices.php";
-        require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
-        $xmlrpcclient = new webservice_xmlrpc_client($serverurl, 'publichubdirectory');
-        try {
-            $hubs = $xmlrpcclient->call($function, $params);
-        } catch (Exception $e) {
-            $hubs = array();
-            $error = $OUTPUT->notification(get_string('errorhublisting', 'block_community', $e->getMessage()));
-            $mform->addElement('static', 'errorhub', '', $error);
-        }
-
-        // Hubdirectory returns old URL for the moodle.net hub, substitute it.
-        foreach ($hubs as $key => $hub) {
-            if ($hub['url'] === HUB_OLDMOODLEORGHUBURL) {
-                $hubs[$key]['url'] = HUB_MOODLEORGHUBURL;
-            }
-        }
-
-        //display list of registered on hub
-        $registrationmanager = new registration_manager();
-        $registeredhubs = $registrationmanager->get_registered_on_hubs();
-        //retrieve some additional hubs that we will add to
-        //the hub list got from the hub directory
-        $additionalhubs = array();
-        foreach ($registeredhubs as $registeredhub) {
-            $inthepubliclist = false;
-            foreach ($hubs as $hub) {
-                if ($hub['url'] == $registeredhub->huburl) {
-                    $inthepubliclist = true;
-                    $hub['registeredon'] = true;
-                }
-            }
-            if (!$inthepubliclist) {
-                $additionalhub = array();
-                $additionalhub['name'] = $registeredhub->hubname;
-                $additionalhub['url'] = $registeredhub->huburl;
-                $additionalhubs[] = $additionalhub;
-            }
-        }
-        if (!empty($additionalhubs)) {
-            $hubs = array_merge($hubs, $additionalhubs);
-        }
-
-        if (!empty($hubs)) {
-            $htmlhubs = array();
-            foreach ($hubs as $hub) {
-                // Name can come from hub directory - need some cleaning.
-                $hubname = clean_text($hub['name'], PARAM_TEXT);
-                $smalllogohtml = '';
-                if (array_key_exists('id', $hub)) {
-
-                    // Retrieve hub logo + generate small logo.
-                    $params = array('hubid' => $hub['id'], 'filetype' => HUB_HUBSCREENSHOT_FILE_TYPE);
-                    $imgurl = new moodle_url(HUB_HUBDIRECTORYURL . "/local/hubdirectory/webservice/download.php", $params);
-                    $imgsize = getimagesize($imgurl->out(false));
-                    if ($imgsize[0] > 1) {
-                        $ascreenshothtml = html_writer::empty_tag('img', array('src' => $imgurl, 'alt' => $hubname));
-                        $smalllogohtml = html_writer::empty_tag('img', array('src' => $imgurl, 'alt' => $hubname
-                                        , 'height' => 30, 'width' => 40));
-                    } else {
-                        $ascreenshothtml = '';
-                    }
-                    $hubimage = html_writer::tag('div', $ascreenshothtml, array('class' => 'hubimage'));
-
-                    // Statistics + trusted info.
-                    $hubstats = '';
-                    if (isset($hub['enrollablecourses'])) { //check needed to avoid warnings for Moodle version < 2011081700
-                        $additionaldesc = get_string('enrollablecourses', 'block_community') . ': ' . $hub['enrollablecourses'] . ' - ' .
-                                get_string('downloadablecourses', 'block_community') . ': ' . $hub['downloadablecourses'];
-                        $hubstats .= html_writer::tag('div', $additionaldesc);
-                    }
-                    if ($hub['trusted']) {
-                        $hubtrusted =  get_string('hubtrusted', 'block_community');
-                        $hubstats .= $OUTPUT->doc_link('trusted_hubs') . html_writer::tag('div', $hubtrusted);
-                    }
-                    $hubstats = html_writer::tag('div', $hubstats, array('class' => 'hubstats'));
-
-                    // hub name link + hub description.
-                    $hubnamelink = html_writer::link($hub['url'], html_writer::tag('h2',$hubname),
-                                    array('class' => 'hubtitlelink'));
-                    // The description can come from the hub directory - need to clean.
-                    $hubdescription = clean_param($hub['description'], PARAM_TEXT);
-                    $hubdescriptiontext = html_writer::tag('div', format_text($hubdescription, FORMAT_PLAIN),
-                                    array('class' => 'hubdescription'));
-
-                    $hubtext = html_writer::tag('div', $hubdescriptiontext . $hubstats, array('class' => 'hubtext'));
-
-                    $hubimgandtext = html_writer::tag('div', $hubimage . $hubtext, array('class' => 'hubimgandtext'));
-
-                    $hubfulldesc = html_writer::tag('div', $hubnamelink . $hubimgandtext, array('class' => 'hubmainhmtl'));
-                } else {
-                    $hubfulldesc = html_writer::link($hub['url'], $hubname);
-                }
-
-                // Add hub to the hub items.
-                $hubinfo = new stdClass();
-                $hubinfo->mainhtml = $hubfulldesc;
-                $hubinfo->rowhtml = html_writer::tag('div', $smalllogohtml , array('class' => 'hubsmalllogo')) . $hubname;
-                $hubitems[$hub['url']] = $hubinfo;
-            }
-
-            // Hub listing form element.
-            $mform->addElement('listing','huburl', '', '', array('items' => $hubitems,
-                'showall' => get_string('showall', 'block_community'),
-                'hideall' => get_string('hideall', 'block_community')));
-            $mform->setDefault('huburl', $huburl);
+        // Display enrol/download select box if the USER has the download capability on the course.
+        if (has_capability('moodle/community:download',
+                        context_course::instance($this->_customdata['courseid']))) {
+            $options = array(0 => get_string('enrollable', 'block_community'),
+                1 => get_string('downloadable', 'block_community'));
+            $mform->addElement('select', 'downloadable', get_string('enroldownload', 'block_community'),
+                    $options);
+            $mform->addHelpButton('downloadable', 'enroldownload', 'block_community');
 
-            //display enrol/download select box if the USER has the download capability on the course
-            if (has_capability('moodle/community:download',
-                            context_course::instance($this->_customdata['courseid']))) {
-                $options = array(0 => get_string('enrollable', 'block_community'),
-                    1 => get_string('downloadable', 'block_community'));
-                $mform->addElement('select', 'downloadable', get_string('enroldownload', 'block_community'),
-                        $options);
-                $mform->addHelpButton('downloadable', 'enroldownload', 'block_community');
-
-                $mform->setDefault('downloadable', $downloadable);
-            } else {
-                $mform->addElement('hidden', 'downloadable', 0);
-            }
-            $mform->setType('downloadable', PARAM_INT);
-
-            $options = array();
-            $options['all'] = get_string('any');
-            $options[HUB_AUDIENCE_EDUCATORS] = get_string('audienceeducators', 'hub');
-            $options[HUB_AUDIENCE_STUDENTS] = get_string('audiencestudents', 'hub');
-            $options[HUB_AUDIENCE_ADMINS] = get_string('audienceadmins', 'hub');
-            $mform->addElement('select', 'audience', get_string('audience', 'block_community'), $options);
-            $mform->setDefault('audience', $audience);
-            unset($options);
-            $mform->addHelpButton('audience', 'audience', 'block_community');
-
-            $options = array();
-            $options['all'] = get_string('any');
-            $options[HUB_EDULEVEL_PRIMARY] = get_string('edulevelprimary', 'hub');
-            $options[HUB_EDULEVEL_SECONDARY] = get_string('edulevelsecondary', 'hub');
-            $options[HUB_EDULEVEL_TERTIARY] = get_string('eduleveltertiary', 'hub');
-            $options[HUB_EDULEVEL_GOVERNMENT] = get_string('edulevelgovernment', 'hub');
-            $options[HUB_EDULEVEL_ASSOCIATION] = get_string('edulevelassociation', 'hub');
-            $options[HUB_EDULEVEL_CORPORATE] = get_string('edulevelcorporate', 'hub');
-            $options[HUB_EDULEVEL_OTHER] = get_string('edulevelother', 'hub');
-            $mform->addElement('select', 'educationallevel',
-                    get_string('educationallevel', 'block_community'), $options);
-            $mform->setDefault('educationallevel', $educationallevel);
-            unset($options);
-            $mform->addHelpButton('educationallevel', 'educationallevel', 'block_community');
-
-            $publicationmanager = new course_publish_manager();
-            $options = $publicationmanager->get_sorted_subjects();
-            $mform->addElement('searchableselector', 'subject', get_string('subject', 'block_community'),
-                    $options, array('id' => 'communitysubject'));
-            $mform->setDefault('subject', $subject);
-            unset($options);
-            $mform->addHelpButton('subject', 'subject', 'block_community');
-
-            require_once($CFG->libdir . "/licenselib.php");
-            $licensemanager = new license_manager();
-            $licences = $licensemanager->get_licenses();
-            $options = array();
-            $options['all'] = get_string('any');
-            foreach ($licences as $license) {
-                $options[$license->shortname] = get_string($license->shortname, 'license');
-            }
-            $mform->addElement('select', 'licence', get_string('licence', 'block_community'), $options);
-            unset($options);
-            $mform->addHelpButton('licence', 'licence', 'block_community');
-            $mform->setDefault('licence', $licence);
-
-            $languages = get_string_manager()->get_list_of_languages();
-            core_collator::asort($languages);
-            $languages = array_merge(array('all' => get_string('any')), $languages);
-            $mform->addElement('select', 'language', get_string('language'), $languages);
-
-            $mform->setDefault('language', $language);
-            $mform->addHelpButton('language', 'language', 'block_community');
-
-            $mform->addElement('select', 'orderby', get_string('orderby', 'block_community'),
-                array('newest' => get_string('orderbynewest', 'block_community'),
-                    'eldest' => get_string('orderbyeldest', 'block_community'),
-                    'fullname' => get_string('orderbyname', 'block_community'),
-                    'publisher' => get_string('orderbypublisher', 'block_community'),
-                    'ratingaverage' => get_string('orderbyratingaverage', 'block_community')));
-
-            $mform->setDefault('orderby', $orderby);
-            $mform->addHelpButton('orderby', 'orderby', 'block_community');
-            $mform->setType('orderby', PARAM_ALPHA);
-
-            $mform->setAdvanced('audience');
-            $mform->setAdvanced('educationallevel');
-            $mform->setAdvanced('subject');
-            $mform->setAdvanced('licence');
-            $mform->setAdvanced('language');
-            $mform->setAdvanced('orderby');
-
-            $mform->addElement('text', 'search', get_string('keywords', 'block_community'),
-                array('size' => 30));
-            $mform->addHelpButton('search', 'keywords', 'block_community');
-            $mform->setType('search', PARAM_NOTAGS);
-
-            $mform->addElement('submit', 'submitbutton', get_string('search', 'block_community'));
+            $mform->setDefault('downloadable', $downloadable);
+        } else {
+            $mform->addElement('hidden', 'downloadable', 0);
         }
-    }
-
-    function validation($data, $files) {
-        global $CFG;
-
-        $errors = array();
-
-        if (empty($this->_form->_submitValues['huburl'])) {
-            $errors['huburl'] = get_string('nohubselected', 'hub');
+        $mform->setType('downloadable', PARAM_INT);
+
+        $options = \core\hub\publication::audience_options(true);
+        $mform->addElement('select', 'audience', get_string('audience', 'block_community'), $options);
+        $mform->setDefault('audience', $audience);
+        unset($options);
+        $mform->addHelpButton('audience', 'audience', 'block_community');
+
+        $options = \core\hub\publication::educational_level_options(true);
+        $mform->addElement('select', 'educationallevel',
+                get_string('educationallevel', 'block_community'), $options);
+        $mform->setDefault('educationallevel', $educationallevel);
+        unset($options);
+        $mform->addHelpButton('educationallevel', 'educationallevel', 'block_community');
+
+        $options = \core\hub\publication::get_sorted_subjects();
+        $mform->addElement('searchableselector', 'subject', get_string('subject', 'block_community'),
+                $options, array('id' => 'communitysubject'));
+        $mform->setDefault('subject', $subject);
+        unset($options);
+        $mform->addHelpButton('subject', 'subject', 'block_community');
+
+        require_once($CFG->libdir . "/licenselib.php");
+        $licensemanager = new license_manager();
+        $licences = $licensemanager->get_licenses();
+        $options = array();
+        $options['all'] = get_string('any');
+        foreach ($licences as $license) {
+            $options[$license->shortname] = get_string($license->shortname, 'license');
         }
+        $mform->addElement('select', 'licence', get_string('licence', 'block_community'), $options);
+        unset($options);
+        $mform->addHelpButton('licence', 'licence', 'block_community');
+        $mform->setDefault('licence', $licence);
+
+        $languages = get_string_manager()->get_list_of_languages();
+        core_collator::asort($languages);
+        $languages = array_merge(array('all' => get_string('any')), $languages);
+        $mform->addElement('select', 'language', get_string('language'), $languages);
+
+        $mform->setDefault('language', $language);
+        $mform->addHelpButton('language', 'language', 'block_community');
+
+        $mform->addElement('select', 'orderby', get_string('orderby', 'block_community'),
+            array('newest' => get_string('orderbynewest', 'block_community'),
+                'eldest' => get_string('orderbyeldest', 'block_community'),
+                'fullname' => get_string('orderbyname', 'block_community'),
+                'publisher' => get_string('orderbypublisher', 'block_community'),
+                'ratingaverage' => get_string('orderbyratingaverage', 'block_community')));
+
+        $mform->setDefault('orderby', $orderby);
+        $mform->addHelpButton('orderby', 'orderby', 'block_community');
+        $mform->setType('orderby', PARAM_ALPHA);
+
+        $mform->setAdvanced('audience');
+        $mform->setAdvanced('educationallevel');
+        $mform->setAdvanced('subject');
+        $mform->setAdvanced('licence');
+        $mform->setAdvanced('language');
+        $mform->setAdvanced('orderby');
+
+        $mform->addElement('text', 'search', get_string('keywords', 'block_community'),
+            array('size' => 30));
+        $mform->addHelpButton('search', 'keywords', 'block_community');
+        $mform->setType('search', PARAM_NOTAGS);
+
+        $mform->addElement('submit', 'submitbutton', get_string('search', 'block_community'));
 
-        return $errors;
     }
 
 }
index 330d3da..d975078 100644 (file)
@@ -73,66 +73,6 @@ class block_community_manager {
                 array('courseurl' => $courseurl, 'userid' => $userid));
     }
 
-    /**
-     * Download the community course backup and save it in file API
-     * @param integer $courseid
-     * @param string $huburl
-     * @return array 'privatefile' the file name saved in private area
-     *               'tmpfile' the file name saved in the moodledata temp dir (for restore)
-     */
-    public function block_community_download_course_backup($course) {
-        global $CFG, $USER;
-        require_once($CFG->libdir . "/filelib.php");
-        require_once($CFG->dirroot. "/course/publish/lib.php");
-
-        $params['courseid'] = $course->id;
-        $params['filetype'] = HUB_BACKUP_FILE_TYPE;
-
-        make_temp_directory('backup');
-
-        $filename = md5(time() . '-' . $course->id . '-'. $USER->id . '-'. random_string(20));
-
-        $url  = new moodle_url($course->huburl.'/local/hub/webservice/download.php', $params);
-        $path = $CFG->tempdir.'/backup/'.$filename.".mbz";
-        $fp = fopen($path, 'w');
-        $curlurl = $course->huburl.'/local/hub/webservice/download.php?filetype='
-                .HUB_BACKUP_FILE_TYPE.'&courseid='.$course->id;
-
-        //send an identification token if the site is registered on the hub
-        require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
-        $registrationmanager = new registration_manager();
-        $registeredhub = $registrationmanager->get_registeredhub($course->huburl);
-        if (!empty($registeredhub)) {
-            $token = $registeredhub->token;
-            $curlurl .= '&token='.$token;
-        }
-
-        $ch = curl_init($curlurl);
-        curl_setopt($ch, CURLOPT_FILE, $fp);
-        $data = curl_exec($ch);
-        curl_close($ch);
-        fclose($fp);
-
-        $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($course->fullname)."_".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,
-                    $CFG->tempdir.'/backup/'.$filename.".mbz");
-        }
-
-        $filenames = array();
-        $filenames['privatefile'] = $record->filename;
-        $filenames['tmpfile'] = $filename;
-        return $filenames;
-    }
-
     /**
      * Delete a community course
      * @param integer $communityid
index f29d301..f415204 100644 (file)
@@ -85,14 +85,43 @@ class block_community_renderer extends plugin_renderer_base {
         return html_writer::tag('div', $nextlink, array( 'class' => 'nextlink'));
     }
 
+    /**
+     * Displays information about moodle.net above course search form
+     *
+     * @return string
+     */
+    public function moodlenet_info() {
+        if (!$info = \core\hub\registration::get_moodlenet_info()) {
+            return '';
+        }
+
+        $image = html_writer::div(html_writer::img($info['imgurl'], $info['name']), 'hubimage');
+
+        $namelink = html_writer::link($info['url'], html_writer::tag('h2', $info['name']), array('class' => 'hubtitlelink'));
+        $description = clean_param($info['description'], PARAM_TEXT);
+        $descriptiontext = html_writer::div(format_text($description, FORMAT_PLAIN), 'hubdescription');
+
+        $additionaldesc = get_string('enrollablecourses', 'block_community') . ': ' . $info['enrollablecourses'] . ' - ' .
+            get_string('downloadablecourses', 'block_community') . ': ' . $info['downloadablecourses'];
+        $stats = html_writer::div(html_writer::tag('div', $additionaldesc), 'hubstats');
+
+        $text = html_writer::div($descriptiontext . $stats, 'hubtext');
+
+        $imgandtext = html_writer::div($image . $text, 'hubimgandtext');
+
+        $fulldesc = html_writer::div($namelink . $imgandtext, 'hubmainhmtl clearfix');
+
+        return html_writer::div($fulldesc, 'formlisting');
+    }
+
     /**
      * Display a list of courses
      * @param array $courses
-     * @param boolean $withwriteaccess
+     * @param mixed $unused parameter is not used
      * @param int $contextcourseid context course id
      * @return string
      */
-    public function course_list($courses, $huburl, $contextcourseid) {
+    public function course_list($courses, $unused, $contextcourseid) {
         global $CFG;
 
         $renderedhtml = '';
@@ -128,12 +157,9 @@ class block_community_renderer extends plugin_renderer_base {
 
                 // create screenshots html
                 $screenshothtml = '';
-                if (!empty($course->screenshots)) {
-                    $baseurl = new moodle_url($huburl . '/local/hub/webservice/download.php',
-                                    array('courseid' => $course->id,
-                                        'filetype' => HUB_SCREENSHOT_FILE_TYPE));
+                if (!empty($course->screenshotbaseurl)) {
                     $screenshothtml = html_writer::empty_tag('img',
-                        array('src' => $baseurl, 'alt' => $course->fullname));
+                        array('src' => $course->screenshotbaseurl, 'alt' => $course->fullname));
                 }
                 $coursescreenshot = html_writer::tag('div', $screenshothtml,
                                 array('class' => 'coursescreenshot',
@@ -269,7 +295,7 @@ class block_community_renderer extends plugin_renderer_base {
                 if (!$course->enrollable) {
                     $params = array('sesskey' => sesskey(), 'download' => 1, 'confirmed' => 1,
                         'remotemoodleurl' => $CFG->wwwroot, 'courseid' => $contextcourseid,
-                        'downloadcourseid' => $course->id, 'huburl' => $huburl,
+                        'downloadcourseid' => $course->id,
                         'coursefullname' => $course->fullname, 'backupsize' => $course->backupsize);
                     $downloadurl = new moodle_url("/blocks/community/communitycourse.php", $params);
                     $downloadbuttonhtml = html_writer::tag('a', get_string('install', 'block_community'),
@@ -339,10 +365,8 @@ class block_community_renderer extends plugin_renderer_base {
 
                 //link rate and comment
                 $rateandcomment = html_writer::tag('div',
-                                html_writer::tag('a', get_string('rateandcomment', 'block_community'),
-                                        array('href' => new moodle_url($huburl,
-                                                    array('courseid' => $course->id, 'mustbelogged' => true)),
-                                            'onclick' => 'this.target="_blank"')),
+                                html_writer::link($course->commenturl, get_string('rateandcomment', 'block_community'),
+                                            ['onclick' => 'this.target="_blank"']),
                                 array('class' => 'hubrateandcomment'));
 
                 //the main DIV tags
index c6704e6..f9ecac8 100644 (file)
     padding-left: 165px;
 }
 
-#page-blocks-community-communitycourse .hubimgandtext {
-    display: table;
-}
-
 #page-blocks-community-communitycourse .hubimage {
     float: left;
     display: block;
diff --git a/blocks/messages/block_messages.php b/blocks/messages/block_messages.php
deleted file mode 100644 (file)
index 79d74b8..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-<?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/>.
-
-/**
- * Mentees block.
- *
- * @package    block_messages
- * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-class block_messages extends block_base {
-    function init() {
-        $this->title = get_string('pluginname', 'block_messages');
-    }
-
-    function get_content() {
-        global $USER, $CFG, $DB, $OUTPUT;
-
-        if (!$CFG->messaging) {
-            $this->content = new stdClass;
-            $this->content->text = '';
-            $this->content->footer = '';
-            if ($this->page->user_is_editing()) {
-                $this->content->text = get_string('disabled', 'message');
-            }
-            return $this->content;
-        }
-
-        if ($this->content !== NULL) {
-            return $this->content;
-        }
-
-        $this->content = new stdClass;
-        $this->content->text = '';
-        $this->content->footer = '';
-
-        if (empty($this->instance) or !isloggedin() or isguestuser() or empty($CFG->messaging)) {
-            return $this->content;
-        }
-
-        $link = '/message/index.php';
-        $action = null; //this was using popup_action() but popping up a fullsize window seems wrong
-        $this->content->footer = $OUTPUT->action_link($link, get_string('messages', 'message'), $action);
-
-        $ufields = user_picture::fields('u', array('lastaccess'));
-        $users = $DB->get_records_sql("SELECT $ufields, COUNT(m.useridfrom) AS count
-                                         FROM {user} u, {message} m
-                                        WHERE m.useridto = ? AND u.id = m.useridfrom AND m.notification = 0
-                                     GROUP BY $ufields", array($USER->id));
-
-
-        //Now, we have in users, the list of users to show
-        //Because they are online
-        if (!empty($users)) {
-            $this->content->text .= '<ul class="list">';
-            foreach ($users as $user) {
-                $timeago = format_time(time() - $user->lastaccess);
-                $this->content->text .= '<li class="listentry"><div class="user"><a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.SITEID.'" title="'.$timeago.'">';
-                $this->content->text .= $OUTPUT->user_picture($user, array('courseid'=>SITEID)); //TODO: user might not have capability to view frontpage profile :-(
-                $this->content->text .= fullname($user).'</a></div>';
-
-                $link = '/message/index.php?usergroup=unread&id='.$user->id;
-                $anchortagcontents = $OUTPUT->pix_icon('t/message', fullname($user)) . '&nbsp;' . $user->count;
-
-                $action = null; // popup is gone now
-                $anchortag = $OUTPUT->action_link($link, $anchortagcontents, $action);
-
-                $this->content->text .= '<div class="message">'.$anchortag.'</div></li>';
-            }
-            $this->content->text .= '</ul>';
-        } else {
-            $this->content->text .= '<div class="info">';
-            $this->content->text .= get_string('nomessages', 'message');
-            $this->content->text .= '</div>';
-        }
-
-        return $this->content;
-    }
-}
-
-
diff --git a/blocks/messages/db/access.php b/blocks/messages/db/access.php
deleted file mode 100644 (file)
index 4ea589d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-<?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/>.
-
-/**
- * Messages block caps.
- *
- * @package    block_messages
- * @copyright  Mark Nelson <markn@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-$capabilities = array(
-
-    'block/messages:myaddinstance' => array(
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_SYSTEM,
-        'archetypes' => array(
-            'user' => CAP_ALLOW
-        ),
-
-        'clonepermissionsfrom' => 'moodle/my:manageblocks'
-    ),
-
-    'block/messages:addinstance' => array(
-        'riskbitmask' => RISK_SPAM | RISK_XSS,
-
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_BLOCK,
-        'archetypes' => array(
-            'editingteacher' => CAP_ALLOW,
-            'manager' => CAP_ALLOW
-        ),
-
-        'clonepermissionsfrom' => 'moodle/site:manageblocks'
-    ),
-);
diff --git a/blocks/messages/lang/en/block_messages.php b/blocks/messages/lang/en/block_messages.php
deleted file mode 100644 (file)
index c41e51c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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/>.
-
-/**
- * Strings for component 'block_messages', language 'en', branch 'MOODLE_20_STABLE'
- *
- * @package   block_messages
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$string['messages:addinstance'] = 'Add a new messages block';
-$string['messages:myaddinstance'] = 'Add a new messages block to Dashboard';
-$string['pluginname'] = 'Messages';
diff --git a/blocks/messages/styles.css b/blocks/messages/styles.css
deleted file mode 100644 (file)
index 176f756..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-.block_messages .content {
-    text-align: left;
-    padding-top: 5px;
-}
-
-.block_messages .content .list li.listentry {
-    clear: both;
-}
-
-.block_messages .content .list li.listentry .user {
-    float: left;
-    position: relative;
-}
-
-.block_messages .content .list li.listentry .message {
-    float: right;
-}
-
-.block_messages .content .info {
-    text-align: center;
-}
-
-.block_messages .content .footer {
-    clear: both;
-}
diff --git a/blocks/messages/tests/behat/block_messages_course.feature b/blocks/messages/tests/behat/block_messages_course.feature
deleted file mode 100644 (file)
index 63dd4a5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-@block @block_messages
-Feature: The messages block allows users to list new messages an a course
-  In order to enable the messages block in a course
-  As a teacher
-  I can add the messages block to a course and view my messages
-
-  Background:
-    Given the following "users" exist:
-      | username | firstname | lastname | email | idnumber |
-      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
-      | student1 | Student | 1 | student1@example.com | S1 |
-    And the following "courses" exist:
-      | fullname | shortname | category |
-      | Course 1 | C1 | 0 |
-    And the following "course enrolments" exist:
-      | user | course | role |
-      | teacher1 | C1 | editingteacher |
-      | student1 | C1 | student |
-
-  Scenario: View the block by a user with messaging disabled.
-    Given the following config values are set as admin:
-      | messaging       | 0 |
-    And I log in as "teacher1"
-    And I am on "Course 1" course homepage with editing mode on
-    And I add the "Messages" block
-    Then I should see "Messaging is disabled on this site" in the "Messages" "block"
-
-  Scenario: View the block by a user who does not have any messages.
-    Given I log in as "teacher1"
-    And I am on "Course 1" course homepage with editing mode on
-    And I add the "Messages" block
-    Then I should see "No messages" in the "Messages" "block"
-
-  @javascript
-  Scenario: View the block by a user who has messages.
-    Given I log in as "student1"
-    And I follow "Messages" in the user menu
-    And I send "This is message 1" message to "Teacher 1" user
-    And I send "This is message 2" message to "Teacher 1" user
-    And I log out
-    And I log in as "teacher1"
-    And I am on "Course 1" course homepage with editing mode on
-    And I add the "Messages" block
-    Then I should see "Student 1" in the "Messages" "block"
-
-  @javascript
-  Scenario: Use the block to send a message to a user.
-    Given I log in as "teacher1"
-    And I am on "Course 1" course homepage with editing mode on
-    And I add the "Messages" block
-    And I click on "//a[normalize-space(.) = 'Messages']" "xpath_element" in the "Messages" "block"
-    And I send "This is message 1" message to "Student 1" user
-    And I log out
-    When I log in as "student1"
-    And I am on "Course 1" course homepage
-    Then I should see "Teacher 1" in the "Messages" "block"
diff --git a/blocks/messages/tests/behat/block_messages_dashboard.feature b/blocks/messages/tests/behat/block_messages_dashboard.feature
deleted file mode 100644 (file)
index 509057e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-@block @block_messages
-Feature: The messages block allows users to list new messages on the dashboard
-  In order to enable the messages block on the dashboard
-  As a user
-  I can add the messages block to a my dashboard and view my messages
-
-  Background:
-    Given the following "users" exist:
-      | username | firstname | lastname | email | idnumber |
-      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
-      | student1 | Student | 1 | student1@example.com | S1 |
-
-  Scenario: View the block by a user with messaging disabled.
-    Given the following config values are set as admin:
-      | messaging       | 0 |
-    And I log in as "teacher1"
-    And I press "Customise this page"
-    When I add the "Messages" block
-    Then I should see "Messaging is disabled on this site" in the "Messages" "block"
-
-  Scenario: View the block by a user who does not have any messages.
-    Given I log in as "teacher1"
-    And I press "Customise this page"
-    When I add the "Messages" block
-    Then I should see "No messages" in the "Messages" "block"
-
-  @javascript
-  Scenario: View the block by a user who has messages.
-    Given I log in as "student1"
-    And I follow "Messages" in the user menu
-    And I send "This is message 1" message to "Teacher 1" user
-    And I send "This is message 2" message to "Teacher 1" user
-    And I log out
-    When I log in as "teacher1"
-    And I press "Customise this page"
-    And I add the "Messages" block
-    Then I should see "Student 1" in the "Messages" "block"
-
-  @javascript
-  Scenario: Use the block to send a message to a user.
-    Given I log in as "teacher1"
-    And I press "Customise this page"
-    And I add the "Messages" block
-    And I click on "//a[normalize-space(.) = 'Messages']" "xpath_element" in the "Messages" "block"
-    And I send "This is message 1" message to "Student 1" user
-    And I log out
-    When I log in as "student1"
-    And I press "Customise this page"
-    And I add the "Messages" block
-    Then I should see "Teacher 1" in the "Messages" "block"
diff --git a/blocks/messages/tests/behat/block_messages_frontpage.feature b/blocks/messages/tests/behat/block_messages_frontpage.feature
deleted file mode 100644 (file)
index 2c71001..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-@block @block_messages
-Feature: The messages block allows users to list new messages on the frontpage
-  In order to enable the messages block on the frontpage
-  As an admin
-  I can add the messages block to a the frontpage and view my messages
-
-  Background:
-    Given the following "users" exist:
-      | username | firstname | lastname | email | idnumber |
-      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
-      | student1 | Student | 1 | student1@example.com | S1 |
-    And I log in as "admin"
-    And I am on site homepage
-    And I navigate to "Turn editing on" node in "Front page settings"
-    And I add the "Messages" block
-    And I log out
-
-  Scenario: View the block by a user with messaging disabled.
-    Given the following config values are set as admin:
-      | messaging       | 0 |
-    And I log in as "admin"
-    And I am on site homepage
-    When I navigate to "Turn editing on" node in "Front page settings"
-    And I should see "Messaging is disabled on this site" in the "Messages" "block"
-    Then I navigate to "Turn editing off" node in "Front page settings"
-    And I should not see "Messaging is disabled on this site"
-
-  Scenario: View the block by a user who does not have any messages.
-    Given I log in as "teacher1"
-    When I am on site homepage
-    Then I should see "No messages" in the "Messages" "block"
-
-  Scenario: Try to view the block as a guest user.
-    Given I log in as "guest"
-    When I am on site homepage
-    Then I should not see "Messages"
-
-  @javascript
-  Scenario: View the block by a user who has messages.
-    Given I log in as "student1"
-    And I follow "Messages" in the user menu
-    And I send "This is message 1" message to "Teacher 1" user
-    And I send "This is message 2" message to "Teacher 1" user
-    And I log out
-    When I log in as "teacher1"
-    And I am on site homepage
-    Then I should see "Student 1" in the "Messages" "block"
-
-  @javascript
-  Scenario: Use the block to send a message to a user.
-    Given I log in as "teacher1"
-    And I am on site homepage
-    And I click on "//a[normalize-space(.) = 'Messages']" "xpath_element" in the "Messages" "block"
-    And I send "This is message 1" message to "Student 1" user
-    And I log out
-    When I log in as "student1"
-    And I am on site homepage
-    Then I should see "Teacher 1" in the "Messages" "block"
diff --git a/blocks/messages/version.php b/blocks/messages/version.php
deleted file mode 100644 (file)
index 9faef4d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?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/>.
-
-/**
- * Version details
- *
- * @package    block_messages
- * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-$plugin->version   = 2017051500;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2017050500;        // Requires this Moodle version
-$plugin->component = 'block_messages';  // Full name of the plugin (used for diagnostics)
index 6b8fc56..7ef8f0a 100644 (file)
@@ -9,6 +9,7 @@ information provided here is intended especially for developers.
 * Blocks can now be included in Moodle global search, with some limitations (at present, the search
   works only for blocks located directly on course pages or site home page). See the HTML block for
   an example.
+* Block block_messages is no longer a part of core.
 
 === 3.3 ===
 
index 8e4150a..f9167a1 100644 (file)
Binary files a/calendar/amd/build/calendar.min.js and b/calendar/amd/build/calendar.min.js differ
index ac1bb8c..f0300b1 100644 (file)
Binary files a/calendar/amd/build/calendar_threemonth.min.js and b/calendar/amd/build/calendar_threemonth.min.js differ
index 4d52804..816815a 100644 (file)
Binary files a/calendar/amd/build/modal_event_form.min.js and b/calendar/amd/build/modal_event_form.min.js differ
index c970b3f..57dbe97 100644 (file)
Binary files a/calendar/amd/build/repository.min.js and b/calendar/amd/build/repository.min.js differ
index a81f332..ed31fd7 100644 (file)
Binary files a/calendar/amd/build/selectors.min.js and b/calendar/amd/build/selectors.min.js differ
index 18d2a61..04dc7f6 100644 (file)
Binary files a/calendar/amd/build/view_manager.min.js and b/calendar/amd/build/view_manager.min.js differ
index 10af845..ef43e41 100644 (file)
@@ -66,7 +66,8 @@ define([
         LOADING_ICON: '.loading-icon',
         VIEW_DAY_LINK: "[data-action='view-day-link']",
         CALENDAR_MONTH_WRAPPER: ".calendarwrapper",
-        COURSE_SELECTOR: 'select[name="course"]'
+        COURSE_SELECTOR: 'select[name="course"]',
+        TODAY: '.today',
     };
 
     /**
@@ -210,8 +211,7 @@ define([
                 templateContext: {
                     contextid: contextId
                 }
-            },
-            [root, SELECTORS.NEW_EVENT_BUTTON]
+            }
         );
     };
 
@@ -223,8 +223,7 @@ define([
      * @param {object} eventFormModalPromise A promise reolved with the event form modal
      */
     var registerCalendarEventListeners = function(root, eventFormModalPromise) {
-        var body = $('body'),
-            courseId = $(root).find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('courseid');
+        var body = $('body');
 
         body.on(CalendarEvents.created, function() {
             CalendarViewManager.reloadCurrentMonth(root);
@@ -246,20 +245,23 @@ define([
             CalendarViewManager.reloadCurrentMonth(root);
         });
 
-        eventFormModalPromise.then(function(modal) {
+        eventFormModalPromise
+        .then(function(modal) {
             // When something within the calendar tells us the user wants
             // to edit an event then show the event form modal.
             body.on(CalendarEvents.editEvent, function(e, eventId) {
                 modal.setEventId(eventId);
                 modal.show();
             });
-            modal.setCourseId(courseId);
             return;
-        });
+        })
+        .fail(Notification.exception);
     };
 
     /**
      * Register event listeners for the module.
+     *
+     * @param {object} root The calendar root element
      */
     var registerEventListeners = function(root) {
         // Bind click events to event links.
@@ -284,7 +286,7 @@ define([
         root.on('change', SELECTORS.COURSE_SELECTOR, function() {
             var selectElement = $(this);
             var courseId = selectElement.val();
-            CalendarViewManager.reloadCurrentMonth(root, courseId)
+            CalendarViewManager.reloadCurrentMonth(root, courseId, null)
                 .then(function() {
                     // We need to get the selector again because the content has changed.
                     return root.find(SELECTORS.COURSE_SELECTOR).val(courseId);
@@ -295,6 +297,32 @@ define([
         var eventFormPromise = registerEventFormModal(root);
         registerCalendarEventListeners(root, eventFormPromise);
 
+        // Bind click event on the new event button.
+        CustomEvents.define(root, [CustomEvents.events.activate]);
+        root.on('click', SELECTORS.NEW_EVENT_BUTTON, function(e) {
+            eventFormPromise.then(function(modal) {
+                var wrapper = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER);
+                modal.setCourseId(wrapper.data('courseid'));
+                var categoryId = wrapper.data('categoryid');
+                if (typeof categoryId !== 'undefined') {
+                    modal.setCategoryId(categoryId);
+                }
+
+                // Attempt to find the cell for today.
+                // If it can't be found, then use the start time of the first day on the calendar.
+                var today = root.find(SELECTORS.TODAY);
+                if (!today.length) {
+                    modal.setStartTime(root.find(SELECTORS.DAY).attr('data-new-event-timestamp'));
+                }
+
+                modal.show();
+                return;
+            })
+            .fail(Notification.exception);
+
+            e.preventDefault();
+        });
+
         // Bind click events to calendar days.
         root.on('click', SELECTORS.DAY, function(e) {
             var target = $(e.target);
@@ -302,10 +330,20 @@ define([
             if (!target.is(SELECTORS.VIEW_DAY_LINK)) {
                 var startTime = $(this).attr('data-new-event-timestamp');
                 eventFormPromise.then(function(modal) {
+                    var wrapper = target.closest(SELECTORS.CALENDAR_MONTH_WRAPPER);
+
+                    modal.setCourseId(wrapper.data('courseid'));
+
+                    var categoryId = wrapper.data('categoryid');
+                    if (typeof categoryId !== 'undefined') {
+                        modal.setCategoryId(categoryId);
+                    }
+
                     modal.setStartTime(startTime);
                     modal.show();
                     return;
-                });
+                })
+                .fail(Notification.exception);
 
                 e.preventDefault();
             }
index a043887..3743d4b 100644 (file)
@@ -24,6 +24,7 @@
  */
 define([
     'jquery',
+    'core/notification',
     'core_calendar/selectors',
     'core_calendar/events',
     'core/templates',
@@ -31,6 +32,7 @@ define([
 ],
 function(
     $,
+    Notification,
     CalendarSelectors,
     CalendarEvents,
     Templates,
@@ -45,18 +47,20 @@ function(
      */
     var registerCalendarEventListeners = function(root) {
         var body = $('body');
-        body.on(CalendarEvents.monthChanged, function(e, year, month, courseId) {
+        body.on(CalendarEvents.monthChanged, function(e, year, month, courseId, categoryId) {
             // We have to use a queue here because the calling code is decoupled from these listeners.
             // It's possible for the event to be called multiple times before one call is fully resolved.
             root.queue(function(next) {
-                return processRequest(e, year, month, courseId)
+                return processRequest(e, year, month, courseId, categoryId)
                 .then(function() {
                     return next();
-                });
+                })
+                .fail(Notification.exception)
+                ;
             });
         });
 
-        var processRequest = function(e, year, month, courseId) {
+        var processRequest = function(e, year, month, courseId, categoryId) {
             var newCurrentMonth = root.find('[data-year="' + year + '"][data-month="' + month + '"]');
             var newParent = newCurrentMonth.closest(CalendarSelectors.calendarPeriods.month);
             var allMonths = root.find(CalendarSelectors.calendarPeriods.month);
@@ -95,6 +99,7 @@ function(
                 requestYear,
                 requestMonth,
                 courseId,
+                categoryId,
                 placeHolder
             )
             .then(function() {
index 24f7b84..e057e29 100644 (file)
@@ -65,6 +65,7 @@ define([
         this.eventId = null;
         this.startTime = null;
         this.courseId = null;
+        this.categoryId = null;
         this.reloadingBody = false;
         this.reloadingTitle = false;
         this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);
@@ -94,6 +95,26 @@ define([
         return this.courseId;
     };
 
+    /**
+     * Set the category id to the given value.
+     *
+     * @method setCategoryId
+     * @param {int} id The event id
+     */
+    ModalEventForm.prototype.setCategoryId = function(id) {
+        this.categoryId = id;
+    };
+
+    /**
+     * Retrieve the current category id, if any.
+     *
+     * @method getCategoryId
+     * @return {int|null} The event id
+     */
+    ModalEventForm.prototype.getCategoryId = function() {
+        return this.categoryId;
+    };
+
     /**
      * Check if the modal has an course id.
      *
@@ -104,6 +125,16 @@ define([
         return this.courseId !== null;
     };
 
+    /**
+     * Check if the modal has an category id.
+     *
+     * @method hasCategoryId
+     * @return {bool}
+     */
+    ModalEventForm.prototype.hasCategoryId = function() {
+        return this.categoryId !== null;
+    };
+
     /**
      * Set the event id to the given value.
      *
@@ -220,7 +251,8 @@ define([
         .always(function() {
             this.reloadingTitle = false;
             return;
-        }.bind(this));
+        }.bind(this))
+        .fail(Notification.exception);
 
         return this.titlePromise;
     };
@@ -261,6 +293,10 @@ define([
             args.courseid = this.getCourseId();
         }
 
+        if (this.hasCategoryId()) {
+            args.categoryid = this.getCategoryId();
+        }
+
         if (typeof formData !== 'undefined') {
             args.formdata = formData;
         }
@@ -273,11 +309,12 @@ define([
             this.enableButtons();
             return;
         }.bind(this))
-        .catch(Notification.exception)
+        .fail(Notification.exception)
         .always(function() {
             this.reloadingBody = false;
             return;
-        }.bind(this));
+        }.bind(this))
+        .fail(Notification.exception);
 
         return this.bodyPromise;
     };
@@ -321,6 +358,8 @@ define([
         Modal.prototype.hide.call(this);
         this.setEventId(null);
         this.setStartTime(null);
+        this.setCourseId(null);
+        this.setCategoryId(null);
     };
 
     /**
@@ -361,7 +400,8 @@ define([
                     // If there was a server side validation error then
                     // we need to re-request the rendered form from the server
                     // in order to display the error for the user.
-                    return this.reloadBodyContent(formData);
+                    this.reloadBodyContent(formData);
+                    return;
                 } else {
                     // No problemo! Our work here is done.
                     this.hide();
@@ -382,8 +422,10 @@ define([
                 // the loading icon and re-enable the buttons.
                 loadingContainer.addClass('hidden');
                 this.enableButtons();
+
+                return;
             }.bind(this))
-            .catch(Notification.exception);
+            .fail(Notification.exception);
     };
 
     /**
index 5e1321c..0b59073 100644 (file)
@@ -29,7 +29,7 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
      *
      * @method deleteEvent
      * @param {int} eventId The event id.
-     * @arapm {bool} deleteSeries Whether to delete all events in the series
+     * @param {bool} deleteSeries Whether to delete all events in the series
      * @return {promise} Resolved with requested calendar event
      */
     var deleteEvent = function(eventId, deleteSeries) {
@@ -93,16 +93,18 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
      * @param {Number} year Year
      * @param {Number} month Month
      * @param {Number} courseid The course id.
+     * @param {Number} categoryid The category id.
      * @param {Bool} includenavigation Whether to include navigation.
      * @return {promise} Resolved with the month view data.
      */
-    var getCalendarMonthData = function(year, month, courseid, includenavigation) {
+    var getCalendarMonthData = function(year, month, courseid, categoryid, includenavigation) {
         var request = {
             methodname: 'core_calendar_get_calendar_monthly_view',
             args: {
                 year: year,
                 month: month,
                 courseid: courseid,
+                categoryid: categoryid,
                 includenavigation: includenavigation,
             }
         };
index a22a86d..ef7e52f 100644 (file)
@@ -26,12 +26,14 @@ define([], function() {
         eventFilterItem: "[data-action='filter-event-type']",
         eventType: {
             site: "[data-eventtype-site]",
+            category: "[data-eventtype-category]",
             course: "[data-eventtype-course]",
             group: "[data-eventtype-group]",
             user: "[data-eventtype-user]",
         },
         popoverType: {
             site: "[data-popover-eventtype-site]",
+            category: "[data-popover-eventtype-category]",
             course: "[data-popover-eventtype-course]",
             group: "[data-popover-eventtype-group]",
             user: "[data-popover-eventtype-user]",
index 9470a10..1ed771a 100644 (file)
@@ -40,9 +40,11 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
             root = $(root);
 
             root.on('click', SELECTORS.CALENDAR_NAV_LINK, function(e) {
-                var courseId = $(root).find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('courseid');
+                var wrapper = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER);
+                var courseId = wrapper.data('courseid');
+                var categoryId = wrapper.data('categoryid');
                 var link = $(e.currentTarget);
-                changeMonth(root, link.attr('href'), link.data('year'), link.data('month'), courseId);
+                changeMonth(root, link.attr('href'), link.data('year'), link.data('month'), courseId, categoryId);
 
                 e.preventDefault();
             });
@@ -55,16 +57,18 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
          * @param {Number} year Year
          * @param {Number} month Month
          * @param {Number} courseid The id of the course whose events are shown
+         * @param {Number} categoryid The id of the category whose events are shown
          * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.
          * @return {promise}
          */
-        var refreshMonthContent = function(root, year, month, courseid, target) {
+        var refreshMonthContent = function(root, year, month, courseid, categoryid, target) {
             startLoading(root);
 
             target = target || root.find(SELECTORS.CALENDAR_MONTH_WRAPPER);
 
+            M.util.js_pending([root.get('id'), year, month, courseid].join('-'));
             var includenavigation = root.data('includenavigation');
-            return CalendarRepository.getCalendarMonthData(year, month, courseid, includenavigation)
+            return CalendarRepository.getCalendarMonthData(year, month, courseid, categoryid, includenavigation)
                 .then(function(context) {
                     return Templates.render(root.attr('data-template'), context);
                 })
@@ -76,6 +80,7 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
                     return;
                 })
                 .always(function() {
+                    M.util.js_complete([root.get('id'), year, month, courseid].join('-'));
                     return stopLoading(root);
                 })
                 .fail(Notification.exception);
@@ -84,15 +89,16 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
         /**
          * Handle changes to the current calendar view.
          *
-         * @param {object} root The root element.
+         * @param {object} root The container element
          * @param {String} url The calendar url to be shown
          * @param {Number} year Year
          * @param {Number} month Month
          * @param {Number} courseid The id of the course whose events are shown
+         * @param {Number} categoryid The id of the category whose events are shown
          * @return {promise}
          */
-        var changeMonth = function(root, url, year, month, courseid) {
-            return refreshMonthContent(root, year, month, courseid)
+        var changeMonth = function(root, url, year, month, courseid, categoryid) {
+            return refreshMonthContent(root, year, month, courseid, categoryid)
                 .then(function() {
                     if (url.length && url !== '#') {
                         window.history.pushState({}, '', url);
@@ -100,7 +106,7 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
                     return arguments;
                 })
                 .then(function() {
-                    $('body').trigger(CalendarEvents.monthChanged, [year, month, courseid]);
+                    $('body').trigger(CalendarEvents.monthChanged, [year, month, courseid, categoryid]);
                     return arguments;
                 });
         };
@@ -110,16 +116,23 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
          *
          * @param {object} root The container element.
          * @param {Number} courseId The course id.
+         * @param {Number} categoryId The id of the category whose events are shown
          * @return {promise}
          */
-        var reloadCurrentMonth = function(root, courseId) {
+        var reloadCurrentMonth = function(root, courseId, categoryId) {
             var year = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('year');
             var month = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('month');
 
-            if (!courseId) {
+            if (typeof courseId === 'undefined') {
                 courseId = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('courseid');
             }
-            return refreshMonthContent(root, year, month, courseId);
+
+            if (typeof categoryId === 'undefined') {
+                categoryId = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('categoryid');
+            }
+
+            return refreshMonthContent(root, year, month, courseId, categoryId);
+
         };
 
         /**
index f20c7f7..423cd92 100644 (file)
@@ -82,6 +82,8 @@ class calendar_event_exporter extends event_exporter_base {
             $params = array('update' => $moduleid, 'return' => true, 'sesskey' => sesskey());
             $editurl = new \moodle_url('/course/mod.php', $params);
             $values['editurl'] = $editurl->out(false);
+        } else if ($event->get_type() == 'category') {
+            $url = $event->get_category()->get_proxied_instance()->get_view_link();
         } else if ($event->get_type() == 'course') {
             $url = course_get_url($event->get_course()->get('id') ?: SITEID);
         } else {
@@ -126,6 +128,17 @@ class calendar_event_exporter extends event_exporter_base {
             }
         }
 
+        // Include category name into the event name, if applicable.
+        $proxy = $this->event->get_category();
+        if ($proxy && $proxy->get('id')) {
+            $category = $proxy->get_proxied_instance();
+            $eventnameparams = (object) [
+                'name' => $values['popupname'],
+                'category' => $category->get_formatted_name(),
+            ];
+            $values['popupname'] = get_string('eventnameandcategory', 'calendar', $eventnameparams);
+        }
+
         // Include course's shortname into the event name, if applicable.
         $course = $this->event->get_course();
         if ($course && $course->get('id') && $course->get('id') !== SITEID) {
index 2965451..ebe8d86 100644 (file)
@@ -59,11 +59,20 @@ class day_exporter extends exporter {
      */
     public function __construct(\calendar_information $calendar, $data, $related) {
         $this->calendar = $calendar;
-        $this->url = new moodle_url('/calendar/view.php', [
-            'view' => 'day',
-            'time' => $calendar->time,
-            'course' => $this->calendar->course->id,
-        ]);
+
+        $url = new moodle_url('/calendar/view.php', [
+                'view' => 'day',
+                'time' => $calendar->time,
+            ]);
+
+        if ($this->calendar->course && SITEID !== $this->calendar->course->id) {
+            $url->param('course', $this->calendar->course->id);
+        } else if ($this->calendar->categoryid) {
+            $url->param('category', $this->calendar->categoryid);
+        }
+
+        $this->url = $url;
+
         parent::__construct($data, $related);
     }
 
@@ -179,9 +188,9 @@ class day_exporter extends exporter {
             'navigation' => $this->get_navigation(),
             'filter_selector' => $this->get_course_filter_selector($output),
             'new_event_button' => $this->get_new_event_button(),
+            'viewdaylink' => $this->url->out(false),
         ];
 
-        $return['viewdaylink'] = $this->url->out(false);
 
         $cache = $this->related['cache'];
         $eventexporters = array_map(function($event) use ($cache, $output) {
index 2642423..5ebfdce 100644 (file)
@@ -48,17 +48,13 @@ class event_exporter extends event_exporter_base {
      * @return array
      */
     protected static function define_other_properties() {
-
         $values = parent::define_other_properties();
+
         $values['url'] = ['type' => PARAM_URL];
         $values['action'] = [
             'type' => event_action_exporter::read_properties_definition(),
             'optional' => true,
         ];
-        $values['editurl'] = [
-            'type' => PARAM_URL,
-            'optional' => true,
-        ];
 
         return $values;
     }
@@ -86,6 +82,8 @@ class event_exporter extends event_exporter_base {
             $params = array('update' => $moduleid, 'return' => true, 'sesskey' => sesskey());
             $editurl = new \moodle_url('/course/mod.php', $params);
             $values['editurl'] = $editurl->out(false);
+        } else if ($event->get_type() == 'category') {
+            $url = $event->get_category()->get_proxied_instance()->get_view_link();
         } else if ($event->get_type() == 'course') {
             $url = \course_get_url($this->related['course'] ?: SITEID);
         } else {
index cb3ba80..85457e2 100644 (file)
@@ -34,6 +34,7 @@ use \core_calendar\local\event\container;
 use \core_calendar\local\event\entities\event_interface;
 use \core_calendar\local\event\entities\action_event_interface;
 use \core_course\external\course_summary_exporter;
+use \core\external\coursecat_summary_exporter;
 use \renderer_base;
 use moodle_url;
 
@@ -64,6 +65,7 @@ class event_exporter_base extends exporter {
         $endtimestamp = $event->get_times()->get_end_time()->getTimestamp();
         $groupid = $event->get_group() ? $event->get_group()->get('id') : null;
         $userid = $event->get_user() ? $event->get_user()->get('id') : null;
+        $categoryid = $event->get_category() ? $event->get_category()->get('id') : null;
 
         $data = new \stdClass();
         $data->id = $event->get_id();
@@ -79,6 +81,7 @@ class event_exporter_base extends exporter {
         $data->descriptionformat = $event->get_description()->get_format();
         $data->groupid = $groupid;
         $data->userid = $userid;
+        $data->categoryid = $categoryid;
         $data->eventtype = $event->get_type();
         $data->timestart = $starttimestamp;
         $data->timeduration = $endtimestamp - $starttimestamp;
@@ -120,6 +123,12 @@ class event_exporter_base extends exporter {
                 'default' => null,
                 'null' => NULL_ALLOWED
             ],
+            'categoryid' => [
+                'type' => PARAM_INT,
+                'optional' => true,
+                'default' => null,
+                'null' => NULL_ALLOWED
+            ],
             'groupid' => [
                 'type' => PARAM_INT,
                 'optional' => true,
@@ -175,6 +184,10 @@ class event_exporter_base extends exporter {
             'icon' => [
                 'type' => event_icon_exporter::read_properties_definition(),
             ],
+            'category' => [
+                'type' => coursecat_summary_exporter::read_properties_definition(),
+                'optional' => true,
+            ],
             'course' => [
                 'type' => course_summary_exporter::read_properties_definition(),
                 'optional' => true,
@@ -204,6 +217,9 @@ class event_exporter_base extends exporter {
             'iscourseevent' => [
                 'type' => PARAM_BOOL
             ],
+            'iscategoryevent' => [
+                'type' => PARAM_BOOL
+            ],
             'groupname' => [
                 'type' => PARAM_RAW,
                 'optional' => true,
@@ -226,10 +242,13 @@ class event_exporter_base extends exporter {
         $context = $this->related['context'];
         $values['isactionevent'] = false;
         $values['iscourseevent'] = false;
+        $values['iscategoryevent'] = false;
         if ($moduleproxy = $event->get_course_module()) {
             $values['isactionevent'] = true;
         } else if ($event->get_type() == 'course') {
             $values['iscourseevent'] = true;
+        } else if ($event->get_type() == 'category') {
+            $values['iscategoryevent'] = true;
         }
         $timesort = $event->get_times()->get_sort_time()->getTimestamp();
         $iconexporter = new event_icon_exporter($event, ['context' => $context]);
@@ -239,6 +258,13 @@ class event_exporter_base extends exporter {
         $subscriptionexporter = new event_subscription_exporter($event);
         $values['subscription'] = $subscriptionexporter->export($output);
 
+        $proxy = $this->event->get_category();
+        if ($proxy && $proxy->get('id')) {
+            $category = $proxy->get_proxied_instance();
+            $categorysummaryexporter = new coursecat_summary_exporter($category, ['context' => $context]);
+            $values['category'] = $categorysummaryexporter->export($output);
+        }
+
         if ($course = $this->related['course']) {
             $coursesummaryexporter = new course_summary_exporter($course, ['context' => $context]);
             $values['course'] = $coursesummaryexporter->export($output);
index 5f4bd4d..79d30da 100644 (file)
@@ -46,6 +46,8 @@ class event_icon_exporter extends exporter {
      */
     public function __construct(event_interface $event, $related = []) {
         $coursemodule = $event->get_course_module();
+        $category = $event->get_category();
+        $categoryid = $category ? $category->get('id') : null;
         $course = $event->get_course();
         $courseid = $course ? $course->get('id') : null;
         $group = $event->get_group();
@@ -54,6 +56,7 @@ class event_icon_exporter extends exporter {
         $userid = $user ? $user->get('id') : null;
         $isactivityevent = !empty($coursemodule);
         $isglobalevent = ($course && $courseid == SITEID);
+        $iscategoryevent = ($category && !empty($categoryid));
         $iscourseevent = ($course && !empty($courseid) && $courseid != SITEID && empty($groupid));
         $isgroupevent = ($group && !empty($groupid));
         $isuserevent = ($user && !empty($userid));
@@ -70,24 +73,28 @@ class event_icon_exporter extends exporter {
         } else if ($isglobalevent) {
             $key = 'i/siteevent';
             $component = 'core';
-            $alttext = get_string('globalevent', 'calendar');
+            $alttext = get_string('typesite', 'calendar');
+        } else if ($iscategoryevent) {
+            $key = 'i/categoryevent';
+            $component = 'core';
+            $alttext = get_string('typecategory', 'calendar');
         } else if ($iscourseevent) {
             $key = 'i/courseevent';
             $component = 'core';
-            $alttext = get_string('courseevent', 'calendar');
+            $alttext = get_string('typecourse', 'calendar');
         } else if ($isgroupevent) {
             $key = 'i/groupevent';
             $component = 'core';
-            $alttext = get_string('groupevent', 'calendar');
+            $alttext = get_string('typegroup', 'calendar');
         } else if ($isuserevent) {
             $key = 'i/userevent';
             $component = 'core';
-            $alttext = get_string('userevent', 'calendar');
+            $alttext = get_string('typeuser', 'calendar');
         } else {
             // Default to site event icon?
             $key = 'i/siteevent';
             $component = 'core';
-            $alttext = get_string('globalevent', 'calendar');
+            $alttext = get_string('typesite', 'calendar');
         }
 
         $data = new \stdClass();
index 23bb42f..e4478bb 100644 (file)
@@ -82,9 +82,10 @@ class footer_options_exporter extends exporter {
      * @return string The iCal url.
      */
     protected function get_ical_url() {
-        return new moodle_url('/calendar/export_execute.php', ['preset_what' => 'all',
-                'preset_time' => 'recentupcoming', 'userid' => $this->userid, 'authtoken' => $this->token]);
-
+        if ($this->token) {
+            return new moodle_url('/calendar/export_execute.php', ['preset_what' => 'all',
+                    'preset_time' => 'recentupcoming', 'userid' => $this->userid, 'authtoken' => $this->token]);
+        }
     }
 
     /**
@@ -113,10 +114,12 @@ class footer_options_exporter extends exporter {
         $values = new stdClass();
 
         if (!empty($CFG->enablecalendarexport)) {
-            $exportbutton = $this->get_export_calendar_button();
-            $managesubscriptionbutton = $this->get_manage_subscriptions_button();
-            $values->exportcalendarbutton = $exportbutton->export_for_template($output);
-            $values->managesubscriptionbutton = $managesubscriptionbutton->export_for_template($output);
+            if ($exportbutton = $this->get_export_calendar_button()) {
+                $values->exportcalendarbutton = $exportbutton->export_for_template($output);
+            }
+            if ($managesubscriptionbutton = $this->get_manage_subscriptions_button()) {
+                $values->managesubscriptionbutton = $managesubscriptionbutton->export_for_template($output);
+            }
             $values->icalurl = $this->get_ical_url()->out(false);
         }
 
@@ -132,12 +135,15 @@ class footer_options_exporter extends exporter {
         return array(
             'exportcalendarbutton' => [
                 'type' => PARAM_RAW,
+                'default' => null,
             ],
             'managesubscriptionbutton' => [
                 'type' => PARAM_RAW,
+                'default' => null,
             ],
             'icalurl' => [
                 'type' => PARAM_URL,
+                'default' => null,
             ],
         );
     }
index bb59946..e67c843 100644 (file)
@@ -75,8 +75,10 @@ class month_exporter extends exporter {
                 'time' => $calendar->time,
             ]);
 
-        if ($this->calendar->courseid) {
-            $this->url->param('course', $this->calendar->courseid);
+        if ($this->calendar->course && SITEID !== $this->calendar->course->id) {
+            $this->url->param('course', $this->calendar->course->id);
+        } else if ($this->calendar->categoryid) {
+            $this->url->param('category', $this->calendar->categoryid);
         }
 
         $related['type'] = $type;
@@ -106,6 +108,11 @@ class month_exporter extends exporter {
             'courseid' => [
                 'type' => PARAM_INT,
             ],
+            'categoryid' => [
+                'type' => PARAM_INT,
+                'optional' => true,
+                'default' => 0,
+            ],
             'filter_selector' => [
                 'type' => PARAM_RAW,
             ],
@@ -162,6 +169,10 @@ class month_exporter extends exporter {
                 // The right arrow defined by the theme.
                 'type' => PARAM_RAW,
             ],
+            'defaulteventcontext' => [
+                'type' => PARAM_INT,
+                'default' => null,
+            ],
         ];
     }
 
@@ -182,7 +193,7 @@ class month_exporter extends exporter {
         $previousperiodlink = new moodle_url($this->url);
         $previousperiodlink->param('time', $previousperiod[0]);
 
-        return [
+        $return = [
             'courseid' => $this->calendar->courseid,
             'filter_selector' => $this->get_course_filter_selector($output),
             'weeks' => $this->get_weeks($output),
@@ -200,6 +211,16 @@ class month_exporter extends exporter {
             'rarrow' => $output->rarrow(),
             'includenavigation' => $this->includenavigation,
         ];
+
+        if ($context = $this->get_default_add_context()) {
+            $return['defaulteventcontext'] = $context->id;
+        }
+
+        if ($this->calendar->categoryid) {
+            $return['categoryid'] = $this->calendar->categoryid;
+        }
+
+        return $return;
     }
 
     /**
@@ -211,9 +232,6 @@ class month_exporter extends exporter {
     protected function get_course_filter_selector(renderer_base $output) {
         $content = '';
         $content .= $output->course_filter_selector($this->url, get_string('detailedmonthviewfor', 'calendar'));
-        if (calendar_user_can_add_event($this->calendar->course)) {
-            $content .= $output->add_event_button($this->calendar->courseid, 0, 0, 0, $this->calendar->time);
-        }
 
         return $content;
     }
@@ -361,4 +379,17 @@ class month_exporter extends exporter {
 
         return $this;
     }
+
+    /**
+     * Get the default context for use when adding a new event.
+     *
+     * @return null|\context
+     */
+    protected function get_default_add_context() {
+        if (calendar_user_can_add_event($this->calendar->course)) {
+            return \context_course::instance($this->calendar->course->id);
+        }
+
+        return null;
+    }
 }
index e974154..5d87d18 100644 (file)
@@ -118,10 +118,16 @@ class week_day_exporter extends day_exporter {
         $url = new moodle_url('/calendar/view.php', [
                 'view' => 'day',
                 'time' => $timestamp,
-                'course' => $this->calendar->course->id,
-        ]);
+            ]);
+
+        if ($this->calendar->course && SITEID !== $this->calendar->course->id) {
+            $url->param('course', $this->calendar->course->id);
+        } else if ($this->calendar->categoryid) {
+            $url->param('category', $this->calendar->categoryid);
+        }
 
         $return['viewdaylink'] = $url->out(false);
+
         if ($popovertitle = $this->get_popover_title()) {
             $return['popovertitle'] = $popovertitle;
         }
index 0ba6d54..00713f4 100644 (file)
@@ -71,6 +71,7 @@ class api {
         array $usersfilter = null,
         array $groupsfilter = null,
         array $coursesfilter = null,
+        array $categoriesfilter = null,
         $withduration = true,
         $ignorehidden = true,
         callable $filter = null
@@ -102,6 +103,7 @@ class api {
             $usersfilter,
             $groupsfilter,
             $coursesfilter,
+            $categoriesfilter,
             $withduration,
             $ignorehidden,
             $filter
index 70c2cb7..398304e 100644 (file)
@@ -117,6 +117,15 @@ class container {
                 [self::class, 'apply_component_provide_event_action'],
                 [self::class, 'apply_component_is_event_visible'],
                 function ($dbrow) {
+                    if (!empty($dbrow->categoryid)) {
+                        // This is a category event. Check that the category is visible to this user.
+                        $category = \coursecat::get($dbrow->categoryid, IGNORE_MISSING, true);
+
+                        if (empty($category) || !$category->is_uservisible()) {
+                            return true;
+                        }
+                    }
+
                     // At present we only have a bail-out check for events in course modules.
                     if (empty($dbrow->modulename)) {
                         return false;
index c6c7c68..9111f39 100644 (file)
@@ -33,6 +33,8 @@ use core_calendar\local\event\factories\action_factory_interface;
 use core_calendar\local\event\factories\event_factory_interface;
 use core_calendar\local\event\strategies\raw_event_retrieval_strategy_interface;
 
+require_once($CFG->libdir . '/coursecatlib.php');
+
 /**
  * Event vault class.
  *
@@ -95,6 +97,7 @@ class event_vault implements event_vault_interface {
         array $usersfilter = null,
         array $groupsfilter = null,
         array $coursesfilter = null,
+        array $categoriesfilter = null,
         $withduration = true,
         $ignorehidden = true,
         callable $filter = null
@@ -162,6 +165,7 @@ class event_vault implements event_vault_interface {
             $usersfilter,
             $groupsfilter,
             $coursesfilter,
+            $categoriesfilter,
             $where,
             $params,
             "COALESCE(e.timesort, e.timestart) ASC, e.id ASC",
@@ -197,6 +201,10 @@ class event_vault implements event_vault_interface {
         event_interface $afterevent = null,
         $limitnum = 20
     ) {
+        $categoryids = array_map(function($category) {
+            return $category->id;
+        }, \coursecat::get_all());
+
         $courseids = array_map(function($course) {
             return $course->id;
         }, enrol_get_all_users_courses($user->id));
@@ -219,6 +227,7 @@ class event_vault implements event_vault_interface {
             [$user->id],
             $groupids ? $groupids : null,
             $courseids ? $courseids : null,
+            $categoryids ? $categoryids : null,
             true,
             true,
             function ($event) {
@@ -249,6 +258,7 @@ class event_vault implements event_vault_interface {
                 [$user->id],
                 $groupings[0] ? $groupings[0] : null,
                 [$course->id],
+                [],
                 true,
                 true,
                 function ($event) use ($course) {
@@ -375,6 +385,7 @@ class event_vault implements event_vault_interface {
                 [$userid],
                 null,
                 null,
+                null,
                 $whereconditions,
                 $whereparams,
                 $ordersql,
index 705b832..15c5a0c 100644 (file)
@@ -76,6 +76,7 @@ interface event_vault_interface {
         array $usersfilter = null,
         array $groupsfilter = null,
         array $coursesfilter = null,
+        array $categoriesfilter = null,
         $withduration = true,
         $ignorehidden = true,
         callable $filter = null
index 1c76999..ad1d98c 100644 (file)
@@ -50,6 +50,11 @@ class action_event implements action_event_interface {
      */
     protected $action;
 
+    /**
+     * @var proxy_interface $category Category for this event.
+     */
+    protected $category;
+
     /**
      * Constructor.
      *
@@ -73,6 +78,10 @@ class action_event implements action_event_interface {
         return $this->event->get_description();
     }
 
+    public function get_category() {
+        return $this->event->get_category();
+    }
+
     public function get_course() {
         return $this->event->get_course();
     }
index cd5a1df..f68544b 100644 (file)
@@ -52,6 +52,11 @@ class event implements event_interface {
      */
     protected $description;
 
+    /**
+     * @var proxy_interface $category Category for this event.
+     */
+    protected $category;
+
     /**
      * @var proxy_interface $course Course for this event.
      */
@@ -103,6 +108,7 @@ class event implements event_interface {
      * @param int                        $id             The event's ID in the database.
      * @param string                     $name           The event's name.
      * @param description_interface      $description    The event's description.
+     * @param proxy_interface            $category       The category associated with the event.
      * @param proxy_interface            $course         The course associated with the event.
      * @param proxy_interface            $group          The group associated with the event.
      * @param proxy_interface            $user           The user associated with the event.
@@ -117,6 +123,7 @@ class event implements event_interface {
         $id,
         $name,
         description_interface $description,
+        proxy_interface $category = null,
         proxy_interface $course = null,
         proxy_interface $group = null,
         proxy_interface $user = null,
@@ -130,6 +137,7 @@ class event implements event_interface {
         $this->id = $id;
         $this->name = $name;
         $this->description = $description;
+        $this->category = $category;
         $this->course = $course;
         $this->group = $group;
         $this->user = $user;
@@ -153,6 +161,10 @@ class event implements event_interface {
         return $this->description;
     }
 
+    public function get_category() {
+        return $this->category;
+    }
+
     public function get_course() {
         return $this->course;
     }
index 192e75d..400cf78 100644 (file)
@@ -56,6 +56,13 @@ interface event_interface {
      */
     public function get_description();
 
+    /**
+     * Get the category object associated with the event.
+     *
+     * @return proxy_interface
+     */
+    public function get_category();
+
     /**
      * Get the course object associated with the event.
      *
index 2695d93..b0242ae 100644 (file)
@@ -30,11 +30,14 @@ use core_calendar\local\event\entities\event;
 use core_calendar\local\event\entities\repeat_event_collection;
 use core_calendar\local\event\exceptions\invalid_callback_exception;
 use core_calendar\local\event\proxies\cm_info_proxy;
+use core_calendar\local\event\proxies\coursecat_proxy;
 use core_calendar\local\event\proxies\std_proxy;
 use core_calendar\local\event\value_objects\event_description;
 use core_calendar\local\event\value_objects\event_times;
 use core_calendar\local\event\entities\event_interface;
 
+require_once($CFG->libdir . '/coursecatlib.php');
+
 /**
  * Abstract factory for creating calendar events.
  *
@@ -126,6 +129,7 @@ abstract class event_abstract_factory implements event_factory_interface {
             return null;
         }
 
+        $category = null;
         $course = null;
         $group = null;
         $user = null;
@@ -136,6 +140,8 @@ abstract class event_abstract_factory implements event_factory_interface {
             $module = new cm_info_proxy($dbrow->modulename, $dbrow->instance, $dbrow->courseid);
         }
 
+        $category = new coursecat_proxy($dbrow->categoryid);
+
         $course = new std_proxy($dbrow->courseid, function($id) {
             return calendar_get_course_cached($this->coursecachereference, $id);
         });
@@ -163,6 +169,7 @@ abstract class event_abstract_factory implements event_factory_interface {
             $dbrow->id,
             $dbrow->name,
             new event_description($dbrow->description, $dbrow->format),
+            $category,
             $course,
             $group,
             $user,
index 0a6b757..8892bfb 100644 (file)
@@ -55,7 +55,7 @@ class create extends \moodleform {
     /**
      * The form definition
      */
-    public function definition () {
+    public function definition() {
         global $PAGE;
 
         $mform = $this->_form;
@@ -203,6 +203,9 @@ class create extends \moodleform {
         if (isset($eventtypes['course'])) {
             $options['course'] = get_string('course');
         }
+        if (isset($eventtypes['category'])) {
+            $options['category'] = get_string('category');
+        }
         if (isset($eventtypes['site'])) {
             $options['site'] = get_string('site');
         }
@@ -223,6 +226,16 @@ class create extends \moodleform {
             $mform->addElement('select', 'eventtype', get_string('eventkind', 'calendar'), $options);
         }
 
+        if (isset($eventtypes['category'])) {
+            $categoryoptions = [];
+            foreach ($eventtypes['category'] as $id => $category) {
+                $categoryoptions[$id] = $category;
+            }
+
+            $mform->addElement('select', 'categoryid', get_string('category'), $categoryoptions);
+            $mform->hideIf('categoryid', 'eventtype', 'noteq', 'category');
+        }
+
         if (isset($eventtypes['course'])) {
             $courseoptions = [];
             foreach ($eventtypes['course'] as $course) {
index 1561e02..2e33869 100644 (file)
@@ -69,6 +69,7 @@ class event_mapper implements event_mapper_interface {
                 'name' => $coalesce('name'),
                 'description' => $coalesce('description'),
                 'format' => $coalesce('format'),
+                'categoryid' => $coalesce('categoryid'),
                 'courseid' => $coalesce('courseid'),
                 'groupid' => $coalesce('groupid'),
                 'userid' => $coalesce('userid'),
diff --git a/calendar/classes/local/event/proxies/coursecat_proxy.php b/calendar/classes/local/event/proxies/coursecat_proxy.php
new file mode 100644 (file)
index 0000000..c585f3a
--- /dev/null
@@ -0,0 +1,92 @@
+<?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/>.
+
+/**
+ * Course category proxy.
+ *
+ * @package    core_calendar
+ * @copyright  2017 Andrew Nicols <andrew@nicols.co.uk>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_calendar\local\event\proxies;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir . '/coursecatlib.php');
+
+/**
+ * Course category proxy.
+ *
+ * This returns an instance of a coursecat rather than a stdClass.
+ *
+ * @copyright  2017 Andrew Nicols <andrew@nicols.co.uk>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class coursecat_proxy implements proxy_interface {
+    /**
+     * @var int $id The ID of the database record.
+     */
+    protected $id;
+
+    /**
+     * @var \stdClass $base Base class to get members from.
+     */
+    protected $base;
+
+    /**
+     * @var \coursecat $category The proxied instance.
+     */
+    protected $category;
+
+    /**
+     * coursecat_proxy constructor.
+     *
+     * @param int       $id       The ID of the record in the database.
+     */
+    public function __construct($id) {
+        $this->id = $id;
+        $this->base = (object) [
+            'id' => $id,
+        ];
+    }
+
+    /**
+     * Retrieve a member of the proxied class.
+     *
+     * @param string $member The name of the member to retrieve
+     * @return mixed The member.
+     */
+    public function get($member) {
+        if ($this->base && property_exists($this->base, $member)) {
+            return $this->base->{$member};
+        }
+
+        return $this->get_proxied_instance()->{$member};
+    }
+
+    /**
+     * Get the full instance of the proxied class.
+     *
+     * @return \coursecat
+     */
+    public function get_proxied_instance() : \coursecat {
+        if (!$this->category) {
+            $this->category = \coursecat::get($this->id, IGNORE_MISSING, true);
+        }
+        return $this->category;
+    }
+}
index 252d374..d4775ee 100644 (file)
@@ -40,6 +40,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         array $usersfilter = null,
         array $groupsfilter = null,
         array $coursesfilter = null,
+        array $categoriesfilter = null,
         array $whereconditions = null,
         array $whereparams = null,
         $ordersql = null,
@@ -51,6 +52,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
             !is_null($usersfilter) ? $usersfilter : true, // True means no filter in old implementation.
             !is_null($groupsfilter) ? $groupsfilter : true,
             !is_null($coursesfilter) ? $coursesfilter : true,
+            !is_null($categoriesfilter) ? $categoriesfilter : true,
             $whereconditions,
             $whereparams,
             $ordersql,
@@ -78,6 +80,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         $users,
         $groups,
         $courses,
+        $categories,
         $whereconditions,
         $whereparams,
         $ordersql,
@@ -89,7 +92,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
 
         $params = array();
         // Quick test.
-        if (empty($users) && empty($groups) && empty($courses)) {
+        if (empty($users) && empty($groups) && empty($courses) && empty($categories)) {
             return array();
         }
 
@@ -100,11 +103,11 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         if ((is_array($users) && !empty($users)) or is_numeric($users)) {
             // Events from a number of users.
             list($insqlusers, $inparamsusers) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED);
-            $filters[] = "(e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0)";
+            $filters[] = "(e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0 AND e.categoryid = 0)";
             $params = array_merge($params, $inparamsusers);
         } else if ($users === true) {
             // Events from ALL users.
-            $filters[] = "(e.userid != 0 AND e.courseid = 0 AND e.groupid = 0)";
+            $filters[] = "(e.userid != 0 AND e.courseid = 0 AND e.groupid = 0 AND e.categoryid = 0)";
         }
         // Boolean false (no users at all): We don't need to do anything.
 
@@ -130,6 +133,16 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
             $filters[] = "(e.groupid = 0 AND e.courseid != 0)";
         }
 
+        // Category filter.
+        if ((is_array($categories) && !empty($categories)) or is_numeric($categories)) {
+            list($insqlcategories, $inparamscategories) = $DB->get_in_or_equal($categories, SQL_PARAMS_NAMED);
+            $filters[] = "(e.groupid = 0 AND e.courseid = 0 AND e.categoryid $insqlcategories)";
+            $params = array_merge($params, $inparamscategories);
+        } else if ($categories === true) {
+            // Events from ALL categories.
+            $filters[] = "(e.groupid = 0 AND e.courseid = 0 AND e.categoryid != 0)";
+        }
+
         // Security check: if, by now, we have NOTHING in $whereclause, then it means
         // that NO event-selecting clauses were defined. Thus, we won't be returning ANY
         // events no matter what. Allowing the code to proceed might return a completely
@@ -168,7 +181,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
 
         if ($user) {
             // Set filter condition for the user's events.
-            $subqueryconditions[] = "(ev.userid = :user AND ev.courseid = 0 AND ev.groupid = 0)";
+            $subqueryconditions[] = "(ev.userid = :user AND ev.courseid = 0 AND ev.groupid = 0 AND ev.categoryid = 0)";
             $subqueryparams['user'] = $user;
 
             foreach ($usercourses as $courseid) {
@@ -210,10 +223,19 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
         // Set subquery filter condition for the courses.
         if (!empty($subquerycourses)) {
             list($incourses, $incoursesparams) = $DB->get_in_or_equal($subquerycourses, SQL_PARAMS_NAMED);
-            $subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid $incourses)";
+            $subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid $incourses AND ev.categoryid = 0)";
             $subqueryparams = array_merge($subqueryparams, $incoursesparams);
         }
 
+        // Set subquery filter condition for the categories.
+        if ($categories === true) {
+            $subqueryconditions[] = "(ev.categoryid != 0 AND ev.eventtype = 'category')";
+        } else if (!empty($categories)) {
+            list($incategories, $incategoriesparams) = $DB->get_in_or_equal($categories, SQL_PARAMS_NAMED);
+            $subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid = 0 AND ev.categoryid $incategories)";
+            $subqueryparams = array_merge($subqueryparams, $incategoriesparams);
+        }
+
         // Build the WHERE condition for the sub-query.
         if (!empty($subqueryconditions)) {
             $subquerywhere = 'WHERE ' . implode(" OR ", $subqueryconditions);
index cc670d3..9225a39 100644 (file)
@@ -39,6 +39,7 @@ interface raw_event_retrieval_strategy_interface {
      * @param array|null    $usersfilter     Array of users to retrieve events for.
      * @param array|null    $groupsfilter    Array of groups to retrieve events for.
      * @param array|null    $coursesfilter   Array of courses to retrieve events for.
+     * @param array|null    $categoriesfilter Array of categories to retrieve events for.
      * @param array|null    $whereconditions Array of where conditions to restrict results.
      * @param array|null    $whereparams     Array of parameters for $whereconditions.
      * @param string|null   $ordersql        SQL to order results.
@@ -51,6 +52,7 @@ interface raw_event_retrieval_strategy_interface {
         array $usersfilter = null,
         array $groupsfilter = null,
         array $coursesfilter = null,
+        array $categoriesfilter = null,
         array $whereconditions = null,
         array $whereparams = null,
         $ordersql = null,
index dad5fd5..9eb3708 100644 (file)
@@ -108,7 +108,7 @@ if ($action === 'delete' && $eventid > 0) {
 }
 
 $calendar = new calendar_information(0, 0, 0, $time);
-$calendar->prepare_for_view($course, $courses);
+$calendar->set_sources($course, $courses);
 
 $formoptions = new stdClass;
 if ($eventid !== 0) {
index 04e6cf3..89ca1e0 100644 (file)
@@ -100,7 +100,7 @@ if ($course !== NULL) {
 $PAGE->set_url($url);
 
 $calendar = new calendar_information(0, 0, 0, $time);
-$calendar->prepare_for_view($course, $courses);
+$calendar->set_sources($course, $courses);
 
 $pagetitle = get_string('export', 'calendar');
 
index 336c0f0..cf82f43 100644 (file)
@@ -882,10 +882,11 @@ class core_calendar_external extends external_api {
      * @param   int     $year The year to be shown
      * @param   int     $month The month to be shown
      * @param   int     $courseid The course to be included
+     * @param   int     $categoryid The category to be included
      * @param   bool    $includenavigation Whether to include navigation
      * @return  array
      */
-    public static function get_calendar_monthly_view($year, $month, $courseid, $includenavigation) {
+    public static function get_calendar_monthly_view($year, $month, $courseid, $categoryid, $includenavigation) {
         global $CFG, $DB, $USER, $PAGE;
         require_once($CFG->dirroot."/calendar/lib.php");
 
@@ -894,27 +895,45 @@ class core_calendar_external extends external_api {
             'year' => $year,
             'month' => $month,
             'courseid' => $courseid,
+            'categoryid' => $categoryid,
             'includenavigation' => $includenavigation,
         ]);
 
+        // TODO: Copy what we do in calendar/view.php.
+        $context = \context_user::instance($USER->id);
+        self::validate_context($context);
+        $PAGE->set_url('/calendar/');
+
         if ($courseid != SITEID && !empty($courseid)) {
             // Course ID must be valid and existing.
             $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
             $courses = [$course->id => $course];
+
+            $coursecat = \coursecat::get($course->category);
+            $category = $coursecat->get_db_record();
         } else {
             $course = get_site();
             $courses = calendar_get_default_courses();
+            $category = null;
+
+            if ($categoryid) {
+                self::validate_context(context_coursecat::instance($categoryid));
+                $ids = [$categoryid];
+                $category = \coursecat::get($categoryid);
+                $ids += $category->get_parents();
+                $categories = \coursecat::get_many($ids);
+                $courses = array_filter($courses, function($course) use ($categories) {
+                    return array_search($course->category, $categories) !== false;
+                });
+                $category = $category->get_db_record();
+            }
         }
 
-        // TODO: Copy what we do in calendar/view.php.
-        $context = \context_user::instance($USER->id);
-        self::validate_context($context);
-
         $type = \core_calendar\type_factory::get_calendar_instance();
 
         $time = $type->convert_to_timestamp($year, $month, 1);
         $calendar = new calendar_information(0, 0, 0, $time);
-        $calendar->prepare_for_view($course, $courses);
+        $calendar->set_sources($course, $courses, $category);
 
         list($data, $template) = calendar_get_view($calendar, 'month', $params['includenavigation']);
 
@@ -932,6 +951,7 @@ class core_calendar_external extends external_api {
                 'year' => new external_value(PARAM_INT, 'Month to be viewed', VALUE_REQUIRED),
                 'month' => new external_value(PARAM_INT, 'Year to be viewed', VALUE_REQUIRED),
                 'courseid' => new external_value(PARAM_INT, 'Course being viewed', VALUE_DEFAULT, SITEID, NULL_ALLOWED),
+                'categoryid' => new external_value(PARAM_INT, 'Category being viewed', VALUE_DEFAULT, null, NULL_ALLOWED),
                 'includenavigation' => new external_value(
                     PARAM_BOOL,
                     'Whether to show course navigation',
index d511497..1039d23 100644 (file)
@@ -27,6 +27,8 @@ if (!defined('MOODLE_INTERNAL')) {
     die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
 }
 
+require_once($CFG->libdir . '/coursecatlib.php');
+
 /**
  *  These are read by the administration component to provide default values
  */
@@ -89,6 +91,10 @@ define('CALENDAR_EVENT_GROUP', 4);
  */
 define('CALENDAR_EVENT_USER', 8);
 
+/**
+ * CALENDAR_EVENT_COURSECAT - Course category calendar event types
+ */
+define('CALENDAR_EVENT_COURSECAT', 16);
 
 /**
  * CALENDAR_IMPORT_FROM_FILE - import the calendar from a file
@@ -312,7 +318,9 @@ class calendar_event {
         global $USER, $DB;
 
         $context = null;
-        if (isset($this->properties->courseid) && $this->properties->courseid > 0) {
+        if (isset($this->properties->categoryid) && $this->properties->categoryid > 0) {
+            $context = \context_coursecat::instance($this->properties->categoryid);
+        } else if (isset($this->properties->courseid) && $this->properties->courseid > 0) {
             $context = \context_course::instance($this->properties->courseid);
         } else if (isset($this->properties->course) && $this->properties->course > 0) {
             $context = \context_course::instance($this->properties->course);
@@ -360,8 +368,7 @@ class calendar_event {
             if ($this->editorcontext === null) {
                 // Switch on the event type to decide upon the appropriate context to use for this event.
                 $this->editorcontext = $this->properties->context;
-                if ($this->properties->eventtype != 'user' && $this->properties->eventtype != 'course'
-                    && $this->properties->eventtype != 'site' && $this->properties->eventtype != 'group') {
+                if (!calendar_is_valid_eventtype($this->properties->eventtype)) {
                     return clean_text($this->properties->description, $this->properties->format);
                 }
             }
@@ -461,6 +468,11 @@ class calendar_event {
                         $this->properties->groupid = 0;
                         $this->properties->userid = $USER->id;
                         break;
+                    case 'category':
+                        $this->properties->groupid = 0;
+                        $this->properties->category = 0;
+                        $this->properties->userid = $USER->id;
+                        break;
                     case 'group':
                         $this->properties->userid = $USER->id;
                         break;
@@ -752,6 +764,14 @@ class calendar_event {
                     // We have a course and are within the course context so we had
                     // better use the courses max bytes value.
                     $this->editoroptions['maxbytes'] = $course->maxbytes;
+                } else if ($properties->eventtype === 'category') {
+                    // First check the course is valid.
+                    \coursecat::get($properties->categoryid, MUST_EXIST, true);
+                    // Course context.
+                    $this->editorcontext = $this->properties->context;
+                    // We have a course and are within the course context so we had
+                    // better use the courses max bytes value.
+                    $this->editoroptions['maxbytes'] = $course->maxbytes;
                 } else {
                     // If we get here we have a custom event type as used by some
                     // modules. In this case the event will have been added by
@@ -896,8 +916,7 @@ class calendar_event {
             // Switch on the event type to decide upon the appropriate context to use for this event.
             $this->editorcontext = $this->properties->context;
 
-            if ($this->properties->eventtype != 'user' && $this->properties->eventtype != 'course'
-                && $this->properties->eventtype != 'site' && $this->properties->eventtype != 'group') {
+            if (!calendar_is_valid_eventtype($this->properties->eventtype)) {
                 // We don't have a context here, do a normal format_text.
                 return external_format_text($this->properties->description, $this->properties->format, $this->editorcontext->id);
             }
@@ -939,6 +958,12 @@ class calendar_information {
     /** @var int A course id */
     public $courseid = null;
 
+    /** @var array An array of categories */
+    public $categories = array();
+
+    /** @var int The current category */
+    public $categoryid = null;
+
     /** @var array An array of courses */
     public $courses = array();
 
@@ -989,7 +1014,7 @@ class calendar_information {
      * @return  $this
      */
     public function set_time($time = null) {
-        if ($time === null) {
+        if (empty($time)) {
             $this->time = time();
         } else {
             $this->time = $time;
@@ -1001,17 +1026,71 @@ class calendar_information {
     /**
      * Initialize calendar information
      *
+     * @deprecated 3.4
      * @param stdClass $course object
      * @param array $coursestoload An array of courses [$course->id => $course]
      * @param bool $ignorefilters options to use filter
      */
     public function prepare_for_view(stdClass $course, array $coursestoload, $ignorefilters = false) {
-        $this->courseid = $course->id;
+        debugging('The prepare_for_view() function has been deprecated. Please update your code to use set_sources()',
+                DEBUG_DEVELOPER);
+        $this->set_sources($course, $coursestoload);
+    }
+
+    /**
+     * Set the sources for events within the calendar.
+     *
+     * If no category is provided, then the category path for the current
+     * course will be used.
+     *
+     * @param   stdClass    $course The current course being viewed.
+     * @param   int[]       $courses The list of all courses currently accessible.
+     * @param   stdClass    $category The current category to show.
+     */
+    public function set_sources(stdClass $course, array $courses, stdClass $category = null) {
+        // A cousre must always be specified.
         $this->course = $course;
-        list($courses, $group, $user) = calendar_set_filters($coursestoload, $ignorefilters);
-        $this->courses = $courses;
+        $this->courseid = $course->id;
+
+        list($courseids, $group, $user) = calendar_set_filters($courses);
+        $this->courses = $courseids;
         $this->groups = $group;
         $this->users = $user;
+
+        // Do not show category events by default.
+        $this->categoryid = null;
+        $this->categories = null;
+
+        if (null !== $category && $category->id > 0) {
+            // A specific category was requested - set the current category, and include all parents of that category.
+            $category = \coursecat::get($category->id);
+            $this->categoryid = $category->id;
+
+            $this->categories = $category->get_parents();
+            $this->categories[] = $category->id;
+        } else if (SITEID === $this->courseid) {
+            // This is the site.
+            // Show categories for all courses the user has access to.
+            $this->categories = true;
+            $categories = [];
+            foreach ($courses as $course) {
+                $category = \coursecat::get($course->category);
+                $categories = array_merge($categories, $category->get_parents());
+                $categories[] = $category->id;
+            }
+
+            // And all categories that the user can manage.
+            foreach (\coursecat::get_all() as $category) {
+                if (!$category->has_manage_capability()) {
+                    continue;
+                }
+
+                $categories = array_merge($categories, $category->get_parents());
+                $categories[] = $category->id;
+            }
+
+            $this->categories = array_unique($categories);
+        }
     }
 
     /**
@@ -1087,15 +1166,17 @@ class calendar_information {
  * @param boolean $withduration whether only events starting within time range selected
  *                              or events in progress/already started selected as well
  * @param boolean $ignorehidden whether to select only visible events or all events
+ * @param array|int|boolean $categories array of categories, category id or boolean for all/no course events
  * @return array $events of selected events or an empty array if there aren't any (or there was an error)
  */
-function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withduration=true, $ignorehidden=true) {
+function calendar_get_events($tstart, $tend, $users, $groups, $courses,
+        $withduration = true, $ignorehidden = true, $categories = []) {
     global $DB;
 
     $whereclause = '';
     $params = array();
     // Quick test.
-    if (empty($users) && empty($groups) && empty($courses)) {
+    if (empty($users) && empty($groups) && empty($courses) && empty($categories)) {
         return array();
     }
 
@@ -1103,12 +1184,12 @@ function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withdur
         // Events from a number of users
         if(!empty($whereclause)) $whereclause .= ' OR';
         list($insqlusers, $inparamsusers) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED);
-        $whereclause .= " (e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0)";
+        $whereclause .= " (e.userid $insqlusers AND e.courseid = 0 AND e.groupid = 0 AND e.categoryid = 0)";
         $params = array_merge($params, $inparamsusers);
     } else if($users === true) {
         // Events from ALL users
         if(!empty($whereclause)) $whereclause .= ' OR';
-        $whereclause .= ' (e.userid != 0 AND e.courseid = 0 AND e.groupid = 0)';
+        $whereclause .= ' (e.userid != 0 AND e.courseid = 0 AND e.groupid = 0 AND e.categoryid = 0)';
     } else if($users === false) {
         // No user at all, do nothing
     }
@@ -1137,6 +1218,21 @@ function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withdur
         $whereclause .= ' (e.groupid = 0 AND e.courseid != 0)';
     }
 
+    if ((is_array($categories) && !empty($categories)) || is_numeric($categories)) {
+        if (!empty($whereclause)) {
+            $whereclause .= ' OR';
+        }
+        list($insqlcategories, $inparamscategories) = $DB->get_in_or_equal($categories, SQL_PARAMS_NAMED);
+        $whereclause .= " (e.groupid = 0 AND e.courseid = 0 AND e.categoryid $insqlcategories)";
+        $params = array_merge($params, $inparamscategories);
+    } else if ($categories === true) {
+        // Events from ALL categories.
+        if (!empty($whereclause)) {
+            $whereclause .= ' OR';
+        }
+        $whereclause .= ' (e.groupid = 0 AND e.courseid = 0 AND e.categoryid != 0)';
+    }
+
     // Security check: if, by now, we have NOTHING in $whereclause, then it means
     // that NO event-selecting clauses were defined. Thus, we won't be returning ANY
     // events no matter what. Allowing the code to proceed might return a completely
@@ -2050,19 +2146,27 @@ function calendar_edit_event_allowed($event, $manualedit = false) {
         // Allow users to add/edit group events if -
         // 1) They have manageentries for the course OR
         // 2) They have managegroupentries AND are in the group.
+        $eventcontext = \context_course::instance($event->courseid);
         $group = $DB->get_record('groups', array('id' => $event->groupid));
         return $group && (
-                has_capability('moodle/calendar:manageentries', $event->context) ||
-                (has_capability('moodle/calendar:managegroupentries', $event->context)
+                has_capability('moodle/calendar:manageentries', $eventcontext) ||
+                (has_capability('moodle/calendar:managegroupentries', $eventcontext)
                     && groups_is_member($event->groupid)));
     } else if (!empty($event->courseid)) {
-        // If groupid is not set, but course is set, it's definiely a course event.
-        return has_capability('moodle/calendar:manageentries', $event->context);
+        // If groupid is not set, but course is set, it's definitely a course event.
+        $eventcontext = \context_course::instance($event->courseid);
+        return has_capability('moodle/calendar:manageentries', $eventcontext);
+    } else if (!empty($event->categoryid)) {
+        // If groupid is not set, but category is set, it's definitely a category event.
+        $eventcontext = \context_coursecat::instance($event->categoryid);
+        return has_capability('moodle/calendar:manageentries', $eventcontext);
     } else if (!empty($event->userid) && $event->userid == $USER->id) {
         // If course is not set, but userid id set, it's a user event.
-        return (has_capability('moodle/calendar:manageownentries', $event->context));
+        $eventcontext = \context_user::instance($event->userid);
+        return (has_capability('moodle/calendar:manageownentries', $eventcontext));
     } else if (!empty($event->userid)) {
-        return (has_capability('moodle/calendar:manageentries', $event->context));
+        $eventcontext = \context_user::instance($event->userid);
+        return (has_capability('moodle/calendar:manageentries', $eventcontext));
     }
 
     return false;
@@ -2237,7 +2341,8 @@ function calendar_show_event_type($type, $user = null) {
  */
 function calendar_set_event_type_display($type, $display = null, $user = null) {
     $persist = get_user_preferences('calendar_persistflt', 0, $user);
-    $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER;
+    $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP
+            + CALENDAR_EVENT_USER + CALENDAR_EVENT_COURSECAT;
     if ($persist === 0) {
         global $SESSION;
         if (!isset($SESSION->calendarshoweventtype)) {
@@ -2273,14 +2378,16 @@ function calendar_set_event_type_display($type, $display = null, $user = null) {
  * @param stdClass $allowed list of allowed edit for event  type
  * @param stdClass|int $course object of a course or course id
  * @param array $groups array of groups for the given course
+ * @param stdClass|int $category object of a category
  */
-function calendar_get_allowed_types(&$allowed, $course = null, $groups = null) {
+function calendar_get_allowed_types(&$allowed, $course = null, $groups = null, $category = null) {
     global $USER, $DB;
 
     $allowed = new \stdClass();
     $allowed->user = has_capability('moodle/calendar:manageownentries', \context_system::instance());
     $allowed->groups = false;
     $allowed->courses = false;
+    $allowed->categories = false;
     $allowed->site = has_capability('moodle/calendar:manageentries', \context_course::instance(SITEID));
     $getgroupsfunc = function($course, $context, $user) use ($groups) {
         if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
@@ -2316,6 +2423,13 @@ function calendar_get_allowed_types(&$allowed, $course = null, $groups = null) {
             }
         }
     }
+
+    if (!empty($category)) {
+        $catcontext = \context_coursecat::instance($category->id);
+        if (has_capability('moodle/category:manage', $catcontext)) {
+            $allowed->categories = [$category->id => 1];
+        }
+    }
 }
 
 /**
@@ -2325,6 +2439,7 @@ function calendar_get_allowed_types(&$allowed, $course = null, $groups = null) {
  * The returned array will optionally have 5 keys:
  *      'user' : true if the logged in user can create user events
  *      'site' : true if the logged in user can create site events
+ *      'category' : array of course categories that the user can create events for
  *      'course' : array of courses that the user can create events for
  *      'group': array of groups that the user can create events for
  *      'groupcourses' : array of courses that the groups belong to (can
@@ -2333,7 +2448,7 @@ function calendar_get_allowed_types(&$allowed, $course = null, $groups = null) {
  * @return array The array of allowed types.
  */
 function calendar_get_all_allowed_types() {
-    global $CFG, $USER;
+    global $CFG, $USER, $DB;
 
     require_once($CFG->libdir . '/enrollib.php');
 
@@ -2349,6 +2464,10 @@ function calendar_get_all_allowed_types() {
         $types['site'] = true;
     }
 
+    if (coursecat::has_manage_capability_on_any()) {
+        $types['category'] = coursecat::make_categories_list('moodle/category:manage');
+    }
+
     // This function warms the context cache for the course so the calls
     // to load the course context in calendar_get_allowed_types don't result
     // in additional DB queries.
@@ -2401,7 +2520,7 @@ function calendar_user_can_add_event($course) {
 
     calendar_get_allowed_types($allowed, $course);
 
-    return (bool)($allowed->user || $allowed->groups || $allowed->courses || $allowed->site);
+    return (bool)($allowed->user || $allowed->groups || $allowed->courses || $allowed->category || $allowed->site);
 }
 
 /**
@@ -2426,6 +2545,8 @@ function calendar_add_event_allowed($event) {
     }
 
     switch ($event->eventtype) {
+        case 'category':
+            return has_capability('moodle/category:manage', $event->context);
         case 'course':
             return has_capability('moodle/calendar:manageentries', $event->context);
         case 'group':
@@ -2485,6 +2606,9 @@ function calendar_get_eventtype_choices($courseid) {
     if (!empty($allowed->courses)) {
         $choices['course'] = get_string('courseevents', 'calendar');
     }
+    if (!empty($allowed->categories)) {
+        $choices['category'] = get_string('categoryevents', 'calendar');
+    }
     if (!empty($allowed->groups) and is_array($allowed->groups)) {
         $choices['group'] = get_string('group');
     }
@@ -2505,6 +2629,8 @@ function calendar_add_subscription($sub) {
         $sub->courseid = $SITE->id;
     } else if ($sub->eventtype === 'group' || $sub->eventtype === 'course') {
         $sub->courseid = $sub->course;
+    } else if ($sub->eventtype === 'category') {
+        $sub->categoryid = $sub->category;
     } else {
         // User events.
         $sub->courseid = 0;
@@ -2956,11 +3082,12 @@ function core_calendar_user_preferences() {
  * @param boolean $ignorehidden whether to select only visible events or all events
  * @return array $events of selected events or an empty array if there aren't any (or there was an error)
  */
-function calendar_get_legacy_events($tstart, $tend, $users, $groups, $courses, $withduration = true, $ignorehidden = true) {
+function calendar_get_legacy_events($tstart, $tend, $users, $groups, $courses,
+        $withduration = true, $ignorehidden = true, $categories = []) {
     // Normalise the users, groups and courses parameters so that they are compliant with \core_calendar\local\api::get_events().
     // Existing functions that were using the old c