Merge branch 'MDL-66551-master' of git://github.com/lameze/moodle
authorJake Dallimore <jake@moodle.com>
Thu, 5 Sep 2019 03:12:35 +0000 (11:12 +0800)
committerJake Dallimore <jake@moodle.com>
Thu, 5 Sep 2019 03:12:35 +0000 (11:12 +0800)
118 files changed:
.eslintrc
.jshintignore [new file with mode: 0644]
.nvmrc [new file with mode: 0644]
Gruntfile.js
admin/classes/form/purge_caches.php
admin/settings/appearance.php
admin/settings/subsystems.php
admin/tool/behat/tests/behat/edit_permissions.feature
admin/tool/capability/renderer.php
admin/tool/messageinbound/lang/en/tool_messageinbound.php
admin/tool/mobile/classes/external.php
admin/tool/mobile/lang/en/tool_mobile.php
admin/tool/mobile/launch.php
admin/tool/mobile/settings.php
admin/tool/mobile/tests/externallib_test.php
admin/tool/mobile/tests/fixtures/output/mobile.php
babel-plugin-add-module-to-define.js
backup/util/checks/backup_check.class.php
backup/util/checks/restore_check.class.php
backup/util/ui/renderer.php
backup/util/ui/tests/behat/restore_moodle2_courses.feature
blocks/community/block_community.php [deleted file]
blocks/community/classes/privacy/provider.php [deleted file]
blocks/community/communitycourse.php [deleted file]
blocks/community/db/access.php [deleted file]
blocks/community/db/install.xml [deleted file]
blocks/community/db/upgrade.php [deleted file]
blocks/community/forms.php [deleted file]
blocks/community/lang/en/block_community.php [deleted file]
blocks/community/locallib.php [deleted file]
blocks/community/renderer.php [deleted file]
blocks/community/styles.css [deleted file]
blocks/community/tests/privacy_test.php [deleted file]
blocks/community/version.php [deleted file]
blocks/community/yui/comments/comments.js [deleted file]
blocks/community/yui/imagegallery/imagegallery.js [deleted file]
blocks/myoverview/lang/en/block_myoverview.php
blocks/upgrade.txt
config-dist.php
course/amd/build/repository.min.js
course/amd/build/repository.min.js.map
course/amd/src/repository.js
course/edit.php
course/format/singleactivity/lib.php
course/format/singleactivity/tests/behat/create_course.feature [new file with mode: 0644]
course/lib.php
course/publish/backup.php [deleted file]
course/publish/forms.php [deleted file]
course/publish/hubselector.php [deleted file]
course/publish/index.php [deleted file]
course/publish/lib.php [deleted file]
course/publish/metadata.php [deleted file]
course/renderer.php
course/tests/behat/course_creation.feature
course/tests/courselib_test.php
course/tests/externallib_test.php
lang/en/admin.php
lang/en/analytics.php
lang/en/backup.php
lang/en/badges.php
lang/en/completion.php
lang/en/deprecated.txt
lang/en/error.php
lang/en/hub.php
lang/en/message.php
lang/en/moodle.php
lang/en/my.php
lang/en/role.php
lib/amd/build/templates.min.js
lib/amd/build/templates.min.js.map
lib/amd/src/templates.js
lib/behat/behat_base.php
lib/classes/hub/api.php
lib/classes/hub/course_publication_form.php [deleted file]
lib/classes/hub/publication.php [deleted file]
lib/classes/hub/registration.php
lib/classes/output/mustache_engine.php [new file with mode: 0644]
lib/classes/output/mustache_helper_collection.php [new file with mode: 0644]
lib/classes/plugin_manager.php
lib/db/access.php
lib/db/install.php
lib/db/upgrade.php
lib/dml/pgsql_native_moodle_database.php
lib/editor/atto/lang/en/editor_atto.php
lib/form/amd/build/submit.min.js [new file with mode: 0644]
lib/form/amd/build/submit.min.js.map [new file with mode: 0644]
lib/form/amd/src/submit.js [new file with mode: 0644]
lib/form/templates/element-submit-inline.mustache
lib/form/templates/element-submit.mustache
lib/mlbackend/python/classes/processor.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/setup.php
lib/tests/behat/behat_permissions.php
lib/tests/core_renderer_template_exploit_test.php [new file with mode: 0644]
lib/tests/output_mustache_helper_collection_test.php [new file with mode: 0644]
lib/upgrade.txt
message/tests/behat/block_user.feature
mod/assign/lang/en/assign.php
mod/assign/locallib.php
mod/assign/tests/behat/relative_dates.feature
mod/assign/tests/events_test.php
mod/data/field.php
mod/forum/subscribe.php
mod/quiz/lang/en/quiz.php
mod/scorm/classes/external.php
mod/scorm/tests/externallib_test.php
npm-shrinkwrap.json
package.json
rating/classes/external.php
user/selector/module.js
user/tests/behat/set_default_homepage.feature
version.php
webservice/externallib.php
webservice/tests/externallib_test.php
webservice/upgrade.txt

index 2388717..e44591a 100644 (file)
--- a/.eslintrc
+++ b/.eslintrc
       }
     },
     {
-      files: ["**/amd/src/*.js", "**/amd/src/**/*.js"],
+      files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js"],
       // We support es6 now. Woot!
       env: {
         es6: true
diff --git a/.jshintignore b/.jshintignore
new file mode 100644 (file)
index 0000000..5e61b7c
--- /dev/null
@@ -0,0 +1,2 @@
+**/amd/**
+/*.js
diff --git a/.nvmrc b/.nvmrc
new file mode 100644 (file)
index 0000000..7796292
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+v8.16.1
index 771bed1..bd41cf3 100644 (file)
@@ -24,6 +24,7 @@
  * Grunt configuration
  */
 
+/* eslint-env node */
 module.exports = function(grunt) {
     var path = require('path'),
         tasks = {},
@@ -575,6 +576,7 @@ module.exports = function(grunt) {
                 };
 
                 if (relativePath) {
+                    /* eslint-disable camelcase */
                     sub.relative_root = relativePath;
                 }
 
index 3151445..ce44d1e 100644 (file)
@@ -50,6 +50,7 @@ class purge_caches extends \moodleform {
             $mform->createElement('advcheckbox', 'theme', '', get_string('purgethemecache', 'admin')),
             $mform->createElement('advcheckbox', 'lang', '', get_string('purgelangcache', 'admin')),
             $mform->createElement('advcheckbox', 'js', '', get_string('purgejscache', 'admin')),
+            $mform->createElement('advcheckbox', 'template', '', get_string('purgetemplates', 'admin')),
             $mform->createElement('advcheckbox', 'filter', '', get_string('purgefiltercache', 'admin')),
             $mform->createElement('advcheckbox', 'muc', '', get_string('purgemuc', 'admin')),
             $mform->createElement('advcheckbox', 'other', '', get_string('purgeothercaches', 'admin'))
index 4730c32..dc924f7 100644 (file)
@@ -275,4 +275,10 @@ preferences,moodle|/user/preferences.php|t/preferences',
     $temp->add(new admin_setting_configtextarea('additionalhtmlfooter', new lang_string('additionalhtmlfooter', 'admin'), new lang_string('additionalhtmlfooter_desc', 'admin'), '', PARAM_RAW));
     $ADMIN->add('appearance', $temp);
 
+    $setting = new admin_setting_configcheckbox('cachetemplates', new lang_string('cachetemplates', 'admin'),
+        new lang_string('cachetemplates_help', 'admin'), 1);
+    $setting->set_updatedcallback('template_reset_all_caches');
+    $temp = new admin_settingpage('templates', new lang_string('templates', 'admin'));
+    $temp->add($setting);
+    $ADMIN->add('appearance', $temp);
 } // end of speedup
index e5c660b..de5f75b 100644 (file)
@@ -48,7 +48,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
 
     $optionalsubsystems->add(new admin_setting_configcheckbox('allowstealth', new lang_string('allowstealthmodules'),
         new lang_string('allowstealthmodules_help'), 0, 1, 0));
-
-    $optionalsubsystems->add(new admin_setting_configcheckbox('enablecoursepublishing',
-        new lang_string('enablecoursepublishing', 'hub'), new lang_string('enablecoursepublishing_help', 'hub'), 0));
 }
index 5de8e0a..e3ffc92 100644 (file)
@@ -20,12 +20,12 @@ Feature: Edit capabilities
     And I set the following system permissions of "Teacher" role:
       | capability | permission |
       | block/mnet_hosts:myaddinstance | Allow |
-      | moodle/community:add | Inherit |
+      | moodle/site:messageanyuser | Inherit |
       | moodle/grade:managesharedforms | Prevent |
       | moodle/course:request | Prohibit |
     When I follow "Edit Teacher role"
     Then "block/mnet_hosts:myaddinstance" capability has "Allow" permission
-    And "moodle/community:add" capability has "Not set" permission
+    And "moodle/site:messageanyuser" capability has "Not set" permission
     And "moodle/grade:managesharedforms" capability has "Prevent" permission
     And "moodle/course:request" capability has "Prohibit" permission
 
index dde7c3e..30a9628 100644 (file)
@@ -114,15 +114,17 @@ class tool_capability_renderer extends plugin_renderer_base {
         }
 
         // Start the list item, and print the context name as a link to the place to make changes.
-        if ($contextid == context_system::instance()->id) {
+        $context = context::instance_by_id($contextid);
+
+        if ($context instanceof context_system) {
             $url = new moodle_url('/admin/roles/manage.php');
-            $title = get_string('changeroles', 'tool_capability');
         } else {
-            $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid));
-            $title = get_string('changeoverrides', 'tool_capability');
+            $url = new moodle_url('/admin/roles/permissions.php', ['contextid' => $contextid]);
         }
-        $context = context::instance_by_id($contextid);
-        $html = $this->output->heading(html_writer::link($url, $context->get_context_name(), array('title' => $title)), 3);
+
+        $title = get_string('permissionsincontext', 'core_role', $context->get_context_name());
+
+        $html = $this->output->heading(html_writer::link($url, $title), 3);
         $html .= html_writer::table($table);
         // If there are any child contexts, print them recursively.
         if (!empty($contexts[$contextid]->children)) {
@@ -133,4 +135,4 @@ class tool_capability_renderer extends plugin_renderer_base {
         return $html;
     }
 
-}
\ No newline at end of file
+}
index 1711f5e..8daab15 100644 (file)
@@ -105,7 +105,7 @@ $string['requirevalidation'] = 'Validate sender address';
 $string['name'] = 'Name';
 $string['ssl'] = 'SSL (Auto-detect SSL version)';
 $string['sslv2'] = 'SSLv2 (Force SSL Version 2)';
-$string['sslv3'] = 'SSLv2 (Force SSL Version 3)';
+$string['sslv3'] = 'SSLv3 (Force SSL Version 3)';
 $string['taskcleanup'] = 'Cleanup of unverified incoming email';
 $string['taskpickup'] = 'Incoming email pickup';
 $string['tls'] = 'TLS (TLS; started via protocol-level negotiation over unencrypted channel; RECOMMENDED way of initiating secure connection)';
index e9d1c67..73c81ff 100644 (file)
@@ -369,12 +369,12 @@ class external extends external_api {
 
     /**
      * Returns a piece of content to be displayed in the Mobile app, it usually returns a template, javascript and
-     * other structured data that will be used to render a view in the Mobile app..
+     * other structured data that will be used to render a view in the Mobile app.
      *
      * Callbacks (placed in \$component\output\mobile) that are called by this web service are responsible for doing the
      * appropriate security checks to access the information to be returned.
      *
-     * @param string $component fame of the component.
+     * @param string $component name of the component.
      * @param string $method function method name in class \$component\output\mobile.
      * @param array $args optional arguments for the method.
      * @return array HTML, JavaScript and other required data and information to create a view in the app.
@@ -423,6 +423,7 @@ class external extends external_api {
             'otherdata'  => $otherdata,
             'files'      => !empty($result['files']) ? $result['files'] : array(),
             'restrict'   => !empty($result['restrict']) ? $result['restrict'] : array(),
+            'disabled'   => !empty($result['disabled']) ? true : false,
         );
     }
 
@@ -465,7 +466,8 @@ class external extends external_api {
                         ),
                     ),
                     'Restrict this content to certain users or courses.'
-                )
+                ),
+                'disabled' => new external_value(PARAM_BOOL, 'Whether we consider this disabled or not.', VALUE_OPTIONAL),
             )
         );
     }
index 0b6ba81..b02ff9e 100644 (file)
@@ -58,7 +58,7 @@ $string['downloadcourse'] = 'Download course';
 $string['downloadcourses'] = 'Download courses';
 $string['enablesmartappbanners'] = 'Enable App Banners';
 $string['enablesmartappbanners_desc'] = 'If enabled, a banner promoting the mobile app will be displayed when accessing the site using a mobile browser.';
-$string['forcedurlscheme'] = 'If you want to allow only your custom branded app to be opened via a browser window, then specify its URL scheme here; otherwise leave the field empty.';
+$string['forcedurlscheme'] = 'If you want to allow only your custom branded app to be opened via a browser window, then specify its URL scheme here. If you want to allow only the official app, then set the default value. Leave the field empty if you want to allow any app.';
 $string['forcedurlscheme_key'] = 'URL scheme';
 $string['forcelogout'] = 'Force log out';
 $string['forcelogout_desc'] = 'If enabled, the app option \'Change site\' is replaced by \'Log out\'. This results in the user being completely logged out. They must then re-enter their password the next time they wish to access the site.';
@@ -82,7 +82,7 @@ $string['mobileappearance'] = 'Mobile appearance';
 $string['mobileauthentication'] = 'Mobile authentication';
 $string['mobilecssurl'] = 'CSS';
 $string['mobilefeatures'] = 'Mobile features';
-$string['mobilenotificationsdisabledwarning'] = 'Mobile notifications are not enabled. They should be enabled in Manage message outputs.';
+$string['mobilenotificationsdisabledwarning'] = 'Mobile notifications are not enabled. They should be enabled in Notification settings.';
 $string['mobilesettings'] = 'Mobile settings';
 $string['offlineuse'] = 'Offline use';
 $string['pluginname'] = 'Moodle app tools';
index 1e74e37..2c5fc18 100644 (file)
@@ -30,7 +30,7 @@ require_once($CFG->libdir . '/externallib.php');
 
 $serviceshortname  = required_param('service',  PARAM_ALPHANUMEXT);
 $passport          = required_param('passport',  PARAM_RAW);    // Passport send from the app to validate the response URL.
-$urlscheme         = optional_param('urlscheme', 'moodlemobile', PARAM_NOTAGS); // The URL scheme the app supports.
+$urlscheme         = optional_param('urlscheme', 'moodlemobile', PARAM_ALPHANUM); // The URL scheme the app supports.
 $confirmed         = optional_param('confirmed', false, PARAM_BOOL);  // If we are being redirected after user confirmation.
 $oauthsso          = optional_param('oauthsso', 0, PARAM_INT); // Id of the OpenID issuer (for OAuth direct SSO).
 
index 5a313ed..b5033d8 100644 (file)
@@ -63,7 +63,7 @@ if ($hassiteconfig) {
 
         $temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
                     new lang_string('forcedurlscheme_key', 'tool_mobile'),
-                    new lang_string('forcedurlscheme', 'tool_mobile'), '', PARAM_NOTAGS));
+                    new lang_string('forcedurlscheme', 'tool_mobile'), 'moodlemobile', PARAM_ALPHANUM));
 
         $ADMIN->add('mobileapp', $temp);
 
index 6bfea7f..955fbb9 100644 (file)
@@ -371,6 +371,19 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         $this->assertEquals(array(1, 2), $result['restrict']['users']);
         $this->assertEquals(array(3, 4), $result['restrict']['courses']);
         $this->assertEmpty($result['files']);
+        $this->assertFalse($result['disabled']);
+    }
+
+    /**
+     * Test get_content disabled.
+     */
+    public function test_get_content_disabled() {
+
+        $paramval = 16;
+        $result = external::get_content('tool_mobile', 'test_view_disabled',
+            array(array('name' => 'param1', 'value' => $paramval)));
+        $result = external_api::clean_returnvalue(external::get_content_returns(), $result);
+        $this->assertTrue($result['disabled']);
     }
 
     /**
index d803743..451b00f 100644 (file)
@@ -38,7 +38,6 @@ class mobile {
     /**
      * Returns a test view.
      * @param  array $args Arguments from tool_mobile_get_content WS
-     *
      * @return array       HTML, javascript and otherdata
      */
     public static function test_view($args) {
@@ -57,4 +56,27 @@ class mobile {
             'files' => array()
         );
     }
+
+    /**
+     * Returns a test view disabled.
+     * @param  array $args Arguments from tool_mobile_get_content WS
+     * @return array       HTML, javascript and otherdata
+     */
+    public static function test_view_disabled($args) {
+        $args = (object) $args;
+
+        return array(
+            'templates' => array(
+                array(
+                    'id' => 'main',
+                    'html' => 'The HTML code',
+                ),
+            ),
+            'javascript' => 'alert();',
+            'otherdata' => array('otherdata1' => $args->param1),
+            'restrict' => array('users' => array(1, 2), 'courses' => array(3, 4)),
+            'files' => array(),
+            'disabled' => true,
+        );
+    }
 }
index 133df3f..cdbd8a7 100644 (file)
@@ -33,8 +33,9 @@
  */
 
 "use strict";
+/* eslint-env node */
 
-module.exports = ({ template, types }) => {
+module.exports = ({template, types}) => {
     const fs = require('fs');
     const path = require('path');
     const glob = require('glob');
@@ -120,15 +121,20 @@ module.exports = ({ template, types }) => {
         throw new Error('Unable to find module name for ' + searchFileName);
     }
 
-    // This is heavily inspired by the babel-plugin-add-module-exports plugin.
-    // See: https://github.com/59naga/babel-plugin-add-module-exports
-    //
-    // This is used when we detect a module using "export default Foo;" to make
-    // sure the transpiled code just returns Foo directly rather than an object
-    // with the default property (i.e. {default: Foo}).
-    //
-    // Note: This means that we can't support modules that combine named exports
-    // with a default export.
+    /**
+     * This is heavily inspired by the babel-plugin-add-module-exports plugin.
+     * See: https://github.com/59naga/babel-plugin-add-module-exports
+     *
+     * This is used when we detect a module using "export default Foo;" to make
+     * sure the transpiled code just returns Foo directly rather than an object
+     * with the default property (i.e. {default: Foo}).
+     *
+     * Note: This means that we can't support modules that combine named exports
+     * with a default export.
+     *
+     * @param {String} path
+     * @param {String} exportObjectName
+     */
     function addModuleExportsDefaults(path, exportObjectName) {
         const rootPath = path.findParent(path => {
             return path.key === 'body' || !path.parentPath;
@@ -136,7 +142,7 @@ module.exports = ({ template, types }) => {
 
         // HACK: `path.node.body.push` instead of path.pushContainer(due doesn't work in Plugin.post).
         // This is hardcoded to work specifically with AMD.
-        rootPath.node.body.push(template(`return ${exportObjectName}.default`)())
+        rootPath.node.body.push(template(`return ${exportObjectName}.default`)());
     }
 
     return {
@@ -174,9 +180,9 @@ module.exports = ({ template, types }) => {
 
                             // Check for any Object.defineProperty('exports', 'default') calls.
                             if (!this.addedReturnForDefaultExport && path.get('callee').matchesPattern('Object.defineProperty')) {
-                                const [identifier, prop] = path.get('arguments')
-                                const objectName = identifier.get('name').node
-                                const propertyName = prop.get('value').node
+                                const [identifier, prop] = path.get('arguments');
+                                const objectName = identifier.get('name').node;
+                                const propertyName = prop.get('value').node;
 
                                 if ((objectName === 'exports' || objectName === '_exports') && propertyName === 'default') {
                                     addModuleExportsDefaults(path, objectName);
index 164da0b..7cd4c14 100644 (file)
@@ -128,15 +128,6 @@ abstract class backup_check {
         // Now, if backup mode is hub or import, check userid has permissions for those modes
         // other modes will perform common checks only (backupxxxx capabilities in $typecapstocheck)
         switch ($mode) {
-            case backup::MODE_HUB:
-                if (!has_capability('moodle/backup:backuptargethub', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/backup:backuptargethub';
-                    throw new backup_controller_exception('backup_user_missing_capability', $a);
-                }
-                break;
             case backup::MODE_IMPORT:
                 if (!has_capability('moodle/backup:backuptargetimport', $coursectx, $userid)) {
                     $a = new stdclass();
index ee2b6cd..35fe2d9 100644 (file)
@@ -90,15 +90,6 @@ abstract class restore_check {
         // Now, if restore mode is hub or import, check userid has permissions for those modes
         // other modes will perform common checks only (restorexxxx capabilities in $typecapstocheck)
         switch ($mode) {
-            case backup::MODE_HUB:
-                if (!has_capability('moodle/restore:restoretargethub', $coursectx, $userid)) {
-                    $a = new stdclass();
-                    $a->userid = $userid;
-                    $a->courseid = $courseid;
-                    $a->capability = 'moodle/restore:restoretargethub';
-                    throw new restore_controller_exception('restore_user_missing_capability', $a);
-                }
-                break;
             case backup::MODE_IMPORT:
                 if (!has_capability('moodle/restore:restoretargetimport', $coursectx, $userid)) {
                     $a = new stdclass();
index a46499f..43e9dd7 100644 (file)
@@ -404,8 +404,10 @@ class core_backup_renderer extends plugin_renderer_base {
         $html .= $this->output->heading(get_string('importdatafrom'), 2, array('class' => 'header'));
         $html .= $this->backup_detail_pair(get_string('selectacourse', 'backup'), $this->render($courses));
         $attrs = array('type' => 'submit', 'value' => get_string('continue'), 'class' => 'btn btn-primary');
+        $html .= html_writer::start_tag('div', array('class' => 'mt-3'));
         $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', $attrs));
         $html .= html_writer::end_tag('div');
+        $html .= html_writer::end_tag('div');
         $html .= html_writer::end_tag('form');
         $html .= html_writer::end_tag('div');
         return $html;
@@ -787,7 +789,7 @@ class core_backup_renderer extends plugin_renderer_base {
         if ($component->get_count() === 0) {
             $output .= $this->output->notification(get_string('nomatchingcourses', 'backup'));
 
-            $output .= html_writer::start_tag('div', array('class' => 'ics-search'));
+            $output .= html_writer::start_tag('div', array('class' => 'ics-search form-inline'));
             $attrs = array(
                 'type' => 'text',
                 'name' => restore_course_search::$VAR_SEARCH,
@@ -799,7 +801,7 @@ class core_backup_renderer extends plugin_renderer_base {
                 'type' => 'submit',
                 'name' => 'searchcourses',
                 'value' => get_string('search'),
-                'class' => 'btn btn-secondary'
+                'class' => 'btn btn-secondary ml-1'
             );
             $output .= html_writer::empty_tag('input', $attrs);
             $output .= html_writer::end_tag('div');
@@ -845,7 +847,7 @@ class core_backup_renderer extends plugin_renderer_base {
         $output .= html_writer::table($table);
         $output .= html_writer::end_tag('div');
 
-        $output .= html_writer::start_tag('div', array('class' => 'ics-search'));
+        $output .= html_writer::start_tag('div', array('class' => 'ics-search form-inline'));
         $attrs = array(
             'type' => 'text',
             'name' => restore_course_search::$VAR_SEARCH,
@@ -856,7 +858,7 @@ class core_backup_renderer extends plugin_renderer_base {
             'type' => 'submit',
             'name' => 'searchcourses',
             'value' => get_string('search'),
-            'class' => 'btn btn-secondary'
+            'class' => 'btn btn-secondary ml-1'
         );
         $output .= html_writer::empty_tag('input', $attrs);
         $output .= html_writer::end_tag('div');
index bd24b15..d1bae45 100644 (file)
@@ -20,7 +20,7 @@ Feature: Restore Moodle 2 course backups
     And I add a "Forum" to section "1" and I fill the form with:
       | Forum name | Test forum name |
       | Description | Test forum description |
-    And I add the "Community finder" block
+    And I add the "Activities" block
 
   @javascript
   Scenario: Restore a course in another existing course
@@ -28,7 +28,7 @@ Feature: Restore Moodle 2 course backups
       | Confirmation | Filename | test_backup.mbz |
     And I restore "test_backup.mbz" backup into "Course 2" course using this options:
     Then I should see "Course 2"
-    And I should see "Community finder" in the "Community finder" "block"
+    And I should see "Activities" in the "Activities" "block"
     And I should see "Test forum name"
 
   @javascript
@@ -38,7 +38,7 @@ Feature: Restore Moodle 2 course backups
     And I restore "test_backup.mbz" backup into a new course using this options:
       | Schema | Course name | Course 1 restored in a new course |
     Then I should see "Course 1 restored in a new course"
-    And I should see "Community finder" in the "Community finder" "block"
+    And I should see "Activities" in the "Activities" "block"
     And I should see "Test forum name"
     And I should see "Topic 15"
     And I should not see "Topic 16"
@@ -72,7 +72,7 @@ Feature: Restore Moodle 2 course backups
     Then I should see "Course 1"
     And I should not see "Section 3"
     And I should not see "Test forum post backup name"
-    And I should see "Community finder" in the "Community finder" "block"
+    And I should see "Activities" in the "Activities" "block"
     And I should see "Test forum name"
 
   @javascript
diff --git a/blocks/community/block_community.php b/blocks/community/block_community.php
deleted file mode 100644 (file)
index fc345ca..0000000
+++ /dev/null
@@ -1,104 +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/>.
-
-/**
- * @package block_community
- * @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
- *
- * The community block
- */
-
-class block_community extends block_list {
-
-    function init() {
-        $this->title = get_string('pluginname', 'block_community');
-    }
-
-    function user_can_addto($page) {
-        // Don't allow people to add the block if they can't even use it
-        if (!has_capability('moodle/community:add', $page->context)) {
-            return false;
-        }
-
-        return parent::user_can_addto($page);
-    }
-
-    function user_can_edit() {
-        // Don't allow people to edit the block if they can't even use it
-        if (!has_capability('moodle/community:add',
-                        context::instance_by_id($this->instance->parentcontextid))) {
-            return false;
-        }
-        return parent::user_can_edit();
-    }
-
-    function get_content() {
-        global $CFG, $OUTPUT, $USER;
-
-        $coursecontext = context::instance_by_id($this->instance->parentcontextid);
-
-        if (!has_capability('moodle/community:add', $coursecontext)
-                or $this->content !== NULL) {
-            return $this->content;
-        }
-
-        $this->content = new stdClass();
-        $this->content->items = array();
-        $this->content->icons = array();
-        $this->content->footer = '';
-
-        if (!isloggedin()) {
-            return $this->content;
-        }
-
-        $icon = $OUTPUT->pix_icon('i/group', get_string('group'));
-        $addcourseurl = new moodle_url('/blocks/community/communitycourse.php',
-                        array('add' => true, 'courseid' => $this->page->course->id));
-        $searchlink = html_writer::tag('a', $icon . get_string('addcourse', 'block_community'),
-                        array('href' => $addcourseurl->out(false)));
-        $this->content->items[] = $searchlink;
-
-        require_once($CFG->dirroot . '/blocks/community/locallib.php');
-        $communitymanager = new block_community_manager();
-        $courses = $communitymanager->block_community_get_courses($USER->id);
-        if ($courses) {
-            $this->content->items[] = html_writer::empty_tag('hr');
-            $this->content->icons[] = '';
-            $this->content->items[] = get_string('mycommunities', 'block_community');
-            $this->content->icons[] = '';
-            foreach ($courses as $course) {
-                //delete link
-                $deleteicon = $OUTPUT->pix_icon('t/delete', get_string('removecommunitycourse', 'block_community'));
-                $deleteurl = new moodle_url('/blocks/community/communitycourse.php',
-                                array('remove' => true,
-                                    'courseid' => $this->page->course->id,
-                                    'communityid' => $course->id, 'sesskey' => sesskey()));
-                $deleteatag = html_writer::tag('a', $deleteicon, array('href' => $deleteurl));
-
-                $courselink = html_writer::tag('a', $course->coursename,
-                                array('href' => $course->courseurl));
-                $this->content->items[] = $courselink . ' ' . $deleteatag;
-                $this->content->icons[] = '';
-            }
-        }
-
-        return $this->content;
-    }
-
-}
-
diff --git a/blocks/community/classes/privacy/provider.php b/blocks/community/classes/privacy/provider.php
deleted file mode 100644 (file)
index dd32b8f..0000000
+++ /dev/null
@@ -1,220 +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/>.
-
-/**
- * Privacy Subsystem implementation for block_community.
- *
- * @package    block_community
- * @copyright  2018 Zig Tan <zig@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-namespace block_community\privacy;
-
-defined('MOODLE_INTERNAL') || die();
-
-use core_privacy\local\request\approved_contextlist;
-use core_privacy\local\request\contextlist;
-use core_privacy\local\request\writer;
-use core_privacy\local\request\deletion_criteria;
-use core_privacy\local\metadata\collection;
-use core_privacy\local\request\userlist;
-use core_privacy\local\request\approved_userlist;
-
-/**
- * Privacy Subsystem implementation for block_community.
- *
- * @copyright  2018 Zig Tan <zig@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class provider implements
-        \core_privacy\local\metadata\provider,
-        \core_privacy\local\request\core_userlist_provider,
-        \core_privacy\local\request\plugin\provider {
-
-    /**
-     * Returns information about how block_community stores its data.
-     *
-     * @param   collection     $collection The initialised collection to add items to.
-     * @return  collection     A listing of user data stored through this system.
-     */
-    public static function get_metadata(collection $collection) : collection {
-        $collection->add_database_table(
-            'block_community',
-            [
-                'coursename' => 'privacy:metadata:block_community:coursename',
-                'coursedescription' => 'privacy:metadata:block_community:coursedescription',
-                'courseurl' => 'privacy:metadata:block_community:courseurl',
-                'imageurl' => 'privacy:metadata:block_community:imageurl',
-                'userid' => 'privacy:metadata:block_community:userid',
-            ],
-            'privacy:metadata:block_community'
-        );
-
-        return $collection;
-    }
-
-    /**
-     * Get the list of contexts that contain user information for the specified user.
-     *
-     * @param   int         $userid     The user to search.
-     * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
-     */
-    public static function get_contexts_for_userid(int $userid) : contextlist {
-        $contextlist = new \core_privacy\local\request\contextlist();
-
-        // The block_community data is associated at the user context level, so retrieve the user's context id.
-        $sql = "SELECT c.id
-                  FROM {block_community} bc
-                  JOIN {context} c ON c.instanceid = bc.userid AND c.contextlevel = :contextuser
-                 WHERE bc.userid = :userid
-              GROUP BY c.id";
-
-        $params = [
-            'contextuser'   => CONTEXT_USER,
-            'userid'        => $userid
-        ];
-
-        $contextlist->add_from_sql($sql, $params);
-
-        return $contextlist;
-    }
-
-    /**
-     * Get the list of users within a specific context.
-     *
-     * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
-     */
-    public static function get_users_in_context(userlist $userlist) {
-        $context = $userlist->get_context();
-
-        if (!$context instanceof \context_user) {
-            return;
-        }
-
-        $sql = "SELECT userid
-                  FROM {block_community}
-                 WHERE userid = ?";
-        $params = [$context->instanceid];
-        $userlist->add_from_sql('userid', $sql, $params);
-    }
-
-    /**
-     * Export all user data for the specified user using the User context level.
-     *
-     * @param   approved_contextlist    $contextlist    The approved contexts to export information for.
-     */
-    public static function export_user_data(approved_contextlist $contextlist) {
-        global $DB;
-
-        // If the user has block_community data, then only the User context should be present so get the first context.
-        $contexts = $contextlist->get_contexts();
-        if (count($contexts) == 0) {
-            return;
-        }
-        $context = reset($contexts);
-
-        // Sanity check that context is at the User context level, then get the userid.
-        if ($context->contextlevel !== CONTEXT_USER) {
-            return;
-        }
-        $userid = $context->instanceid;
-
-        // The block_community data export is organised in: {User Context}/Community Finder/My communities/data.json.
-        $subcontext = [
-            get_string('pluginname', 'block_community'),
-            get_string('mycommunities', 'block_community')
-        ];
-
-        $sql = "SELECT bc.id as id,
-                       bc.coursename as name,
-                       bc.coursedescription as description,
-                       bc.courseurl as url,
-                       bc.imageurl as imageurl
-                  FROM {block_community} bc
-                 WHERE bc.userid = :userid
-              ORDER BY bc.coursename";
-
-        $params = [
-            'userid' => $userid
-        ];
-
-        $communities = $DB->get_records_sql($sql, $params);
-
-        $data = (object) [
-            'communities' => $communities
-        ];
-
-        writer::with_context($context)->export_data($subcontext, $data);
-    }
-
-    /**
-     * Delete all data for all users in the specified context.
-     *
-     * @param   context $context   The specific context to delete data for.
-     */
-    public static function delete_data_for_all_users_in_context(\context $context) {
-        global $DB;
-
-        // Sanity check that context is at the User context level, then get the userid.
-        if ($context->contextlevel !== CONTEXT_USER) {
-            return;
-        }
-        $userid = $context->instanceid;
-
-        $DB->delete_records('block_community', ['userid' => $userid]);
-    }
-
-    /**
-     * Delete multiple users within a single context.
-     *
-     * @param approved_userlist $userlist The approved context and user information to delete information for.
-     */
-    public static function delete_data_for_users(approved_userlist $userlist) {
-        global $DB;
-
-        $context = $userlist->get_context();
-
-        if ($context instanceof \context_user) {
-            $DB->delete_records('block_community', ['userid' => $context->instanceid]);
-        }
-    }
-
-    /**
-     * Delete all user data for the specified user.
-     *
-     * @param   approved_contextlist $contextlist  The approved contexts and user information to delete information for.
-     */
-    public static function delete_data_for_user(approved_contextlist $contextlist) {
-        global $DB;
-
-        // If the user has block_community data, then only the User context should be present so get the first context.
-        $contexts = $contextlist->get_contexts();
-        if (count($contexts) == 0) {
-            return;
-        }
-        $context = reset($contexts);
-
-        // Sanity check that context is at the User context level, then get the userid.
-        if ($context->contextlevel !== CONTEXT_USER) {
-            return;
-        }
-        $userid = $context->instanceid;
-
-        $DB->delete_records('block_community', ['userid' => $userid]);
-    }
-
-}
diff --git a/blocks/community/communitycourse.php b/blocks/community/communitycourse.php
deleted file mode 100644 (file)
index 67f024b..0000000
+++ /dev/null
@@ -1,208 +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/>.
-
-/**
- * Controller for various actions of the block.
- *
- * This page display the community course search form.
- * It also handles adding a course to the community block.
- * It also handles downloading a course template.
- *
- * @package    block_community
- * @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
- */
-
-require('../../config.php');
-require_once($CFG->dirroot . '/blocks/community/locallib.php');
-require_once($CFG->dirroot . '/blocks/community/forms.php');
-
-require_login();
-$courseid = required_param('courseid', PARAM_INT); //if no courseid is given
-$parentcourse = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
-
-$context = context_course::instance($courseid);
-$PAGE->set_course($parentcourse);
-$PAGE->set_url('/blocks/community/communitycourse.php');
-$PAGE->set_heading($SITE->fullname);
-$PAGE->set_pagelayout('incourse');
-$PAGE->set_title(get_string('searchcourse', 'block_community'));
-$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
-require_capability('moodle/community:add', $context);
-$usercandownload = has_capability('moodle/community:download', $context);
-
-$communitymanager = new block_community_manager();
-$renderer = $PAGE->get_renderer('block_community');
-
-/// Check if the page has been called with trust argument
-$add = optional_param('add', -1, PARAM_INT);
-$confirm = optional_param('confirmed', false, PARAM_INT);
-if ($add != -1 and $confirm and confirm_sesskey()) {
-    $course = new stdClass();
-    $course->name = optional_param('coursefullname', '', PARAM_TEXT);
-    $course->description = optional_param('coursedescription', '', PARAM_TEXT);
-    $course->url = optional_param('courseurl', '', PARAM_URL);
-    $course->imageurl = optional_param('courseimageurl', '', PARAM_URL);
-    $communitymanager->block_community_add_course($course, $USER->id);
-    echo $OUTPUT->header();
-    echo $renderer->save_link_success(
-            new moodle_url('/course/view.php', array('id' => $courseid)));
-    echo $OUTPUT->footer();
-    die();
-}
-
-/// Delete temp file when cancel restore
-$cancelrestore = optional_param('cancelrestore', false, PARAM_INT);
-if ($usercandownload and $cancelrestore and confirm_sesskey()) {
-    $filename = optional_param('filename', '', PARAM_ALPHANUMEXT);
-    //delete temp file
-    $backuptempdir = make_backup_temp_directory('');
-    unlink($backuptempdir . '/' . $filename . ".mbz");
-}
-
-/// Download
-$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()) {
-    //OUTPUT: display restore choice page
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('downloadingcourse', 'block_community'), 3, 'main');
-    $sizeinfo = new stdClass();
-    $sizeinfo->total = number_format($backupsize / 1000000, 2);
-    echo html_writer::tag('div', get_string('downloadingsize', 'block_community', $sizeinfo),
-            array('class' => 'textinfo'));
-    if (ob_get_level()) {
-        ob_flush();
-    }
-    flush();
-    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',
-                    $privatefilename), 'notifysuccess');
-    echo $renderer->restore_confirmation_box($tmpfilename, $context);
-    echo $OUTPUT->footer();
-    die();
-}
-
-/// Remove community
-$remove = optional_param('remove', '', PARAM_INT);
-$communityid = optional_param('communityid', '', PARAM_INT);
-if ($remove != -1 and !empty($communityid) and confirm_sesskey()) {
-    $communitymanager->block_community_remove_course($communityid, $USER->id);
-    echo $OUTPUT->header();
-    echo $renderer->remove_success(new moodle_url('/course/view.php', array('id' => $courseid)));
-    echo $OUTPUT->footer();
-    die();
-}
-
-//Get form default/current values
-$fromformdata['coverage'] = optional_param('coverage', 'all', PARAM_TEXT);
-$fromformdata['licence'] = optional_param('licence', 'all', PARAM_ALPHANUMEXT);
-$fromformdata['subject'] = optional_param('subject', 'all', PARAM_ALPHANUMEXT);
-$fromformdata['audience'] = optional_param('audience', 'all', PARAM_ALPHANUMEXT);
-$fromformdata['language'] = optional_param('language', current_language(), PARAM_ALPHANUMEXT);
-$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['search'] = $search;
-$fromformdata['courseid'] = $courseid;
-$hubselectorform = new community_hub_search_form('', $fromformdata);
-$hubselectorform->set_data($fromformdata);
-
-//Retrieve courses by web service
-$courses = null;
-if (optional_param('executesearch', 0, PARAM_INT) and confirm_sesskey()) {
-    $downloadable = optional_param('downloadable', false, PARAM_INT);
-
-    $options = new stdClass();
-    if (!empty($fromformdata['coverage'])) {
-        $options->coverage = $fromformdata['coverage'];
-    }
-    if ($fromformdata['licence'] != 'all') {
-        $options->licenceshortname = $fromformdata['licence'];
-    }
-    if ($fromformdata['subject'] != 'all') {
-        $options->subject = $fromformdata['subject'];
-    }
-    if ($fromformdata['audience'] != 'all') {
-        $options->audience = $fromformdata['audience'];
-    }
-    if ($fromformdata['educationallevel'] != 'all') {
-        $options->educationallevel = $fromformdata['educationallevel'];
-    }
-    if ($fromformdata['language'] != 'all') {
-        $options->language = $fromformdata['language'];
-    }
-
-    $options->orderby = $fromformdata['orderby'];
-
-    //the range of course requested
-    $options->givememore = optional_param('givememore', 0, PARAM_INT);
-
-    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;
-}
-
-//load javascript
-$commentedcourseids = array(); //result courses with comments only
-$courseids = array(); //all result courses
-$courseimagenumbers = array(); //number of screenshots of all courses (must be exact same order than $courseids)
-if (!empty($courses)) {
-    foreach ($courses as $course) {
-        if (!empty($course['comments'])) {
-            $commentedcourseids[] = $course['id'];
-        }
-        $courseids[] = $course['id'];
-        $courseimagenumbers[] = $course['screenshots'];
-    }
-}
-$PAGE->requires->yui_module('moodle-block_community-comments', 'M.blocks_community.init_comments',
-        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' => HUB_MOODLEORGHUBURL, 'closeButtonTitle' => get_string('close', 'editor'))));
-
-echo highlight($search, $renderer->course_list($courses, null, $courseid));
-
-//display givememore/Next link if more course can be displayed
-if (!empty($courses)) {
-    if (($options->givememore + count($courses)) < $coursetotal) {
-        $fromformdata['givememore'] = count($courses) + $options->givememore;
-        $fromformdata['executesearch'] = true;
-        $fromformdata['sesskey'] = sesskey();
-        echo $renderer->next_button($fromformdata);
-    }
-}
-
-echo $OUTPUT->footer();
diff --git a/blocks/community/db/access.php b/blocks/community/db/access.php
deleted file mode 100644 (file)
index 1ec36ed..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/>.
-
-/**
- * Community block caps.
- *
- * @package    block_community
- * @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/community:myaddinstance' => array(
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_SYSTEM,
-        'archetypes' => array(
-            'user' => CAP_ALLOW
-        ),
-
-        'clonepermissionsfrom' => 'moodle/my:manageblocks'
-    ),
-
-    'block/community: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/community/db/install.xml b/blocks/community/db/install.xml
deleted file mode 100644 (file)
index 58705d7..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="blocks/community/db" VERSION="20120122" COMMENT="XMLDB file for Moodle blocks/community"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
->
-  <TABLES>
-    <TABLE NAME="block_community" COMMENT="Community block">
-      <FIELDS>
-        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
-        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="coursename" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="coursedescription" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false"/>
-        <FIELD NAME="courseurl" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
-        <FIELD NAME="imageurl" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
-      </FIELDS>
-      <KEYS>
-        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
-      </KEYS>
-    </TABLE>
-  </TABLES>
-</XMLDB>
\ No newline at end of file
diff --git a/blocks/community/db/upgrade.php b/blocks/community/db/upgrade.php
deleted file mode 100644 (file)
index 1a593de..0000000
+++ /dev/null
@@ -1,65 +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/>.
-
-/**
- * This file keeps track of upgrades to the community block
- *
- * Sometimes, changes between versions involve alterations to database structures
- * and other major things that may break installations.
- *
- * The upgrade function in this file will attempt to perform all the necessary
- * actions to upgrade your older installation to the current version.
- *
- * If there's something it cannot do itself, it will tell you what you need to do.
- *
- * The commands in here will all be database-neutral, using the methods of
- * database_manager class
- *
- * Please do not forget to use upgrade_set_timeout()
- * before any action that may take longer time to finish.
- *
- * @since Moodle 2.0
- * @package block_community
- * @copyright 2010 Jerome Mouneyrac
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-/**
- *
- * @param int $oldversion
- */
-function xmldb_block_community_upgrade($oldversion) {
-    global $CFG;
-
-    // Automatically generated Moodle v3.3.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Automatically generated Moodle v3.4.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Automatically generated Moodle v3.5.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Automatically generated Moodle v3.6.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Automatically generated Moodle v3.7.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    return true;
-}
diff --git a/blocks/community/forms.php b/blocks/community/forms.php
deleted file mode 100644 (file)
index 8142b5c..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-<?php
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// This file is part of Moodle - http://moodle.org/                      //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//                                                                       //
-// 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/>.       //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-/**
- * Form for community search
- *
- * @package    block_community
- * @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
- */
-
-require_once($CFG->libdir . '/formslib.php');
-
-class community_hub_search_form extends moodleform {
-
-    public function definition() {
-        global $CFG;
-        $mform = & $this->_form;
-
-        //set default value
-        $search = $this->_customdata['search'];
-        if (isset($this->_customdata['coverage'])) {
-            $coverage = $this->_customdata['coverage'];
-        } else {
-            $coverage = 'all';
-        }
-        if (isset($this->_customdata['licence'])) {
-            $licence = $this->_customdata['licence'];
-        } else {
-            $licence = 'all';
-        }
-        if (isset($this->_customdata['subject'])) {
-            $subject = $this->_customdata['subject'];
-        } else {
-            $subject = 'all';
-        }
-        if (isset($this->_customdata['audience'])) {
-            $audience = $this->_customdata['audience'];
-        } else {
-            $audience = 'all';
-        }
-        if (isset($this->_customdata['language'])) {
-            $language = $this->_customdata['language'];
-        } else {
-            $language = current_language();
-        }
-        if (isset($this->_customdata['educationallevel'])) {
-            $educationallevel = $this->_customdata['educationallevel'];
-        } else {
-            $educationallevel = 'all';
-        }
-        if (isset($this->_customdata['downloadable'])) {
-            $downloadable = $this->_customdata['downloadable'];
-        } else {
-            $downloadable = 1;
-        }
-        if (isset($this->_customdata['orderby'])) {
-            $orderby = $this->_customdata['orderby'];
-        } else {
-            $orderby = 'newest';
-        }
-
-        $mform->addElement('header', 'site', get_string('search', 'block_community'));
-
-        //add the course id (of the context)
-        $mform->addElement('hidden', 'courseid', $this->_customdata['courseid']);
-        $mform->setType('courseid', PARAM_INT);
-        $mform->addElement('hidden', 'executesearch', 1);
-        $mform->setType('executesearch', PARAM_INT);
-
-        // 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 = \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'));
-
-    }
-
-}
diff --git a/blocks/community/lang/en/block_community.php b/blocks/community/lang/en/block_community.php
deleted file mode 100644 (file)
index 73e65d4..0000000
+++ /dev/null
@@ -1,121 +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_community', language 'en', branch 'MOODLE_20_STABLE'
- *
- * @package   block_community
- * @author    Jerome Mouneyrac <jerome@mouneyrac.com>
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$string['activities'] = 'Activities';
-$string['add'] = 'Add';
-$string['addedtoblock'] = 'A link to this course has been added in your community finder block';
-$string['addtocommunityblock'] = 'Save a link to this course';
-$string['addcommunitycourse'] = 'Add community course';
-$string['additionalcoursedesc'] = '{$a->lang} Creator: {$a->creatorname} - Publisher: {$a->publishername} - Subject: {$a->subject}
-    - Audience: {$a->audience} - Educational level: {$a->educationallevel} - License: {$a->license}';
-$string['addcourse'] = 'Search';
-$string['audience'] = 'Designed for';
-$string['audience_help'] = 'What kind of course are you looking for?  As well as traditional courses intended for students, you might search for communities of Educators or Moodle Administrators';
-$string['blocks'] = 'Blocks';
-$string['cannotselecttopsubject'] = 'Cannot select a top subject level';
-$string['comments'] = 'Comments ({$a})';
-$string['community:addinstance'] = 'Add a new community finder block';
-$string['community:myaddinstance'] = 'Add a new community finder block to Dashboard';
-$string['contentinfo'] = 'Subject: {$a->subject} - Audience: {$a->audience} - Educational level: {$a->educationallevel}';
-$string['continue'] = 'Continue';
-$string['contributors'] = ' - Contributors: {$a}';
-$string['coursedesc'] = 'Description';
-$string['courselang'] = 'Language';
-$string['coursename'] = 'Name';
-$string['courses'] = 'Courses';
-$string['coverage'] = 'Tags: {$a}';
-$string['donotrestore'] = 'No';
-$string['dorestore'] = 'Yes';
-$string['download'] = 'Download';
-$string['downloadable'] = 'courses I can download';
-$string['downloadablecourses'] = 'Downloadable courses';
-$string['downloadconfirmed'] = 'The backup has been saved in your private files {$a}';
-$string['downloaded'] = '...finished.';
-$string['downloadingcourse'] = 'Downloading course';
-$string['downloadingsize'] = 'Please wait the course file is downloading ({$a->total}Mb)...';
-$string['downloadtemplate'] = 'Create course from template';
-$string['educationallevel'] = 'Educational level';
-$string['educationallevel_help'] = 'What educational level are you searching for?  In the case of communities of educators, this level describes the level they are teaching.';
-$string['enroldownload'] = 'Find';
-$string['enroldownload_help'] = 'Some courses listed in the selected hub are being advertised so that people can come and participate in them on the original site.
-
-Others are course templates provided for you to download and use on your own Moodle site.';
-$string['enrollable'] = 'courses I can enrol in';
-$string['enrollablecourses'] = 'Enrollable courses';
-$string['errorcourselisting'] = 'An error occurred when retrieving the course listing from the selected hub, please try again later. ({$a})';
-$string['errorhublisting'] = 'An error occurred when retrieving the hub listing from Moodle.org, please try again later. ({$a})';
-$string['fileinfo'] = 'Language: {$a->lang} - License: {$a->license} -  Time updated: {$a->timeupdated}';
-$string['hideall'] = 'Hide hubs';
-$string['hub'] = 'hub';
-$string['hubnottrusted'] = 'Not trusted';
-$string['hubtrusted'] = 'This hub is trusted by Moodle.org';
-$string['install'] = 'Install';
-$string['keywords'] = 'Keywords';
-$string['keywords_help'] = 'You can search for courses containing specific text in the name, description and other fields of the database.';
-$string['langdesc'] = 'Language: {$a} - ';
-$string['language'] = 'Language';
-$string['language_help'] = 'You can search for courses written in a specific language.';
-$string['licence'] = 'License';
-$string['licence_help'] = 'You can search for courses that are licensed in a particular way.';
-$string['moredetails'] = 'More details';
-$string['mycommunities'] = 'My communities:';
-$string['next'] = 'Next >>>';
-$string['nocomments'] = 'No comments';
-$string['nocourse'] = 'No courses found';
-$string['noratings'] = 'No ratings';
-$string['operation'] = 'Operation';
-$string['orderby'] = 'Sort by';
-$string['orderby_help'] = 'The order the search results are displayed.';
-$string['orderbynewest'] = 'Newest';
-$string['orderbyeldest'] = 'Oldest';
-$string['orderbyname'] = 'Name';
-$string['orderbypublisher'] = 'Publisher';
-$string['orderbyratingaverage'] = 'Rating';
-$string['outcomes'] = 'Outcomes: {$a}';
-$string['pluginname'] = 'Community finder';
-$string['privacy:metadata:block_community'] = 'The Community block stores links to shared community courses users can enrol in.';
-$string['privacy:metadata:block_community:coursename'] = 'The name of the linked community course.';
-$string['privacy:metadata:block_community:coursedescription'] = 'The description of the linked community course.';
-$string['privacy:metadata:block_community:courseurl'] = 'The course URL of the linked community course.';
-$string['privacy:metadata:block_community:imageurl'] = 'The image URL of the linked community course.';
-$string['privacy:metadata:block_community:userid'] = 'The ID of the user who created the linked community course.';
-$string['rateandcomment'] = 'Rate and comment';
-$string['rating'] = 'Rating';
-$string['removecommunitycourse'] = 'Remove community course';
-$string['restorecourse'] = 'Restore course';
-$string['restorecourseinfo'] = 'Restore the course?';
-$string['screenshots'] = 'Screenshots';
-$string['search'] = 'Search';
-$string['searchcommunitycourse'] = 'Search for community course';
-$string['searchcourse'] = 'Search for community course';
-$string['selecthub'] = 'Select hub';
-$string['selecthub_help'] = 'Select hub where to search the courses.';
-$string['sites'] = 'Sites';
-$string['showall'] = 'Show all hubs';
-$string['subject'] = 'Subject';
-$string['subject_help'] = 'To narrow your search to courses about a particular subject, choose one from this list.';
-$string['userinfo'] = 'Creator: {$a->creatorname} - Publisher: {$a->publishername}';
-$string['visitdemo'] = 'Visit demo';
-$string['visitsite'] = 'Visit site';
diff --git a/blocks/community/locallib.php b/blocks/community/locallib.php
deleted file mode 100644 (file)
index d975078..0000000
+++ /dev/null
@@ -1,88 +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/>.
-
-/**
- * Community library
- *
- * @package    block_community
- * @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
- *
- *
- */
-
-class block_community_manager {
-
-    /**
-     * Add a community course
-     * @param object $course
-     * @param integer $userid
-     * @return id of course or false if already added
-     */
-    public function block_community_add_course($course, $userid) {
-        global $DB;
-
-        $community = $this->block_community_get_course($course->url, $userid);
-
-        if (empty($community)) {
-            $community = new stdClass();
-            $community->userid = $userid;
-            $community->coursename = $course->name;
-            $community->coursedescription = $course->description;
-            $community->courseurl = $course->url;
-            $community->imageurl = $course->imageurl;
-            return $DB->insert_record('block_community', $community);
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Return all community courses of a user
-     * @param integer $userid
-     * @return array of course
-     */
-    public function block_community_get_courses($userid) {
-        global $DB;
-        return $DB->get_records('block_community', array('userid' => $userid), 'coursename');
-    }
-
-    /**
-     * Return a community courses of a user
-     * @param integer $userid
-     * @param integer $userid
-     * @return array of course
-     */
-    public function block_community_get_course($courseurl, $userid) {
-        global $DB;
-        return $DB->get_record('block_community',
-                array('courseurl' => $courseurl, 'userid' => $userid));
-    }
-
-    /**
-     * Delete a community course
-     * @param integer $communityid
-     * @param integer $userid
-     * @return bool true
-     */
-    public function block_community_remove_course($communityid, $userid) {
-        global $DB, $USER;
-        return $DB->delete_records('block_community',
-                array('userid' => $userid, 'id' => $communityid));
-    }
-
-}
diff --git a/blocks/community/renderer.php b/blocks/community/renderer.php
deleted file mode 100644 (file)
index f415204..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-<?php
-
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// This file is part of Moodle - http://moodle.org/                      //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//                                                                       //
-// 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/>.       //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-/**
- * Block community renderer.
- * @package   block_community
- * @copyright 2010 Moodle Pty Ltd (http://moodle.com)
- * @author    Jerome Mouneyrac
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class block_community_renderer extends plugin_renderer_base {
-
-    public function restore_confirmation_box($filename, $context) {
-        $restoreurl = new moodle_url('/backup/restore.php',
-                        array('filename' => $filename . ".mbz", 'contextid' => $context->id));
-        $searchurl = new moodle_url('/blocks/community/communitycourse.php',
-                        array('add' => 1, 'courseid' => $context->instanceid,
-                            'cancelrestore' => 1, 'sesskey' => sesskey(),
-                            'filename' => $filename));
-        $formrestore = new single_button($restoreurl,
-                        get_string('dorestore', 'block_community'));
-        $formsearch = new single_button($searchurl,
-                        get_string('donotrestore', 'block_community'));
-        return $this->output->confirm(get_string('restorecourseinfo', 'block_community'),
-                $formrestore, $formsearch);
-    }
-
-    /**
-     * Display remove community success message and a button to be redirected to te referer page
-     * @param moodle_url $url the page to be redirected to
-     * @return string html
-     */
-    public function remove_success(moodle_url $url) {
-        $html = $this->output->notification(get_string('communityremoved', 'hub'),
-                    'notifysuccess');
-        $continuebutton = new single_button($url,
-                        get_string('continue', 'block_community'));
-        $html .= html_writer::tag('div', $this->output->render($continuebutton),
-                array('class' => 'continuebutton'));
-        return $html;
-    }
-
-    /**
-     * Display add community course success message and a button to be redirected to te referer page
-     * @param moodle_url $url the page to be redirected to
-     * @return string html
-     */
-    public function save_link_success(moodle_url $url) {
-        $html = $this->output->notification(get_string('addedtoblock', 'block_community'),
-                    'notifysuccess');
-        $continuebutton = new single_button($url,
-                        get_string('continue', 'block_community'));
-        $html .= html_writer::tag('div', $this->output->render($continuebutton),
-                array('class' => 'continuebutton'));
-        return $html;
-    }
-
-    /**
-     * The 'Next'/'more course result' link for a courses search
-     * @param array $data - the form parameter to execute the search on more result
-     * @return string html code
-     */
-    public function next_button($data) {
-        $nextlink = html_writer::tag('a', get_string('next', 'block_community'),
-                array('href' => new moodle_url('', $data)));
-        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 mixed $unused parameter is not used
-     * @param int $contextcourseid context course id
-     * @return string
-     */
-    public function course_list($courses, $unused, $contextcourseid) {
-        global $CFG;
-
-        $renderedhtml = '';
-
-        if (empty($courses)) {
-            if (isset($courses)) {
-                $renderedhtml .= get_string('nocourse', 'block_community');
-            }
-        } else {
-            $courseiteration = 0;
-            foreach ($courses as $course) {
-                $course = (object) $course;
-                $courseiteration = $courseiteration + 1;
-
-                //create visit link html
-                if (!empty($course->courseurl)) {
-                    $courseurl = new moodle_url($course->courseurl);
-                    $linktext = get_string('visitsite', 'block_community');
-                } else {
-                    $courseurl = new moodle_url($course->demourl);
-                    $linktext = get_string('visitdemo', 'block_community');
-                }
-
-                $visitlinkhtml = html_writer::tag('a', $linktext,
-                                array('href' => $courseurl, 'class' => 'hubcoursedownload',
-                                    'onclick' => 'this.target="_blank"'));
-
-                //create title html
-                $coursename = html_writer::tag('h3', $course->fullname,
-                                array('class' => 'hubcoursetitle'));
-                $coursenamehtml = html_writer::tag('div', $coursename,
-                        array('class' => 'hubcoursetitlepanel'));
-
-                // create screenshots html
-                $screenshothtml = '';
-                if (!empty($course->screenshotbaseurl)) {
-                    $screenshothtml = html_writer::empty_tag('img',
-                        array('src' => $course->screenshotbaseurl, 'alt' => $course->fullname));
-                }
-                $coursescreenshot = html_writer::tag('div', $screenshothtml,
-                                array('class' => 'coursescreenshot',
-                                    'id' => 'image-' . $course->id));
-
-                //create description html
-                $deschtml = html_writer::tag('div', $course->description,
-                                array('class' => 'hubcoursedescription'));
-
-                //create users related information html
-                $courseuserinfo = get_string('userinfo', 'block_community', $course);
-                if ($course->contributornames) {
-                    $courseuserinfo .= ' - ' . get_string('contributors', 'block_community',
-                                    $course->contributornames);
-                }
-                $courseuserinfohtml = html_writer::tag('div', $courseuserinfo,
-                                array('class' => 'hubcourseuserinfo'));
-
-                //create course content related information html
-                $course->subject = (get_string_manager()->string_exists($course->subject, 'edufields')) ?
-                        get_string($course->subject, 'edufields') : get_string('none');
-                $course->audience = get_string('audience' . $course->audience, 'hub');
-                $course->educationallevel = get_string('edulevel' . $course->educationallevel, 'hub');
-                $coursecontentinfo = '';
-                if (empty($course->coverage)) {
-                    $course->coverage = '';
-                } else {
-                    $coursecontentinfo .= get_string('coverage', 'block_community', $course->coverage);
-                    $coursecontentinfo .= ' - ';
-                }
-                $coursecontentinfo .= get_string('contentinfo', 'block_community', $course);
-                $coursecontentinfohtml = html_writer::tag('div', $coursecontentinfo,
-                                array('class' => 'hubcoursecontentinfo'));
-
-                ///create course file related information html
-                //language
-                if (!empty($course->language)) {
-                    $languages = get_string_manager()->get_list_of_languages();
-                    $course->lang = $languages[$course->language];
-                } else {
-                    $course->lang = '';
-                }
-                //licence
-                require_once($CFG->libdir . "/licenselib.php");
-                $licensemanager = new license_manager();
-                $licenses = $licensemanager->get_licenses();
-                foreach ($licenses as $license) {
-                    if ($license->shortname == $course->licenceshortname) {
-                        $course->license = $license->fullname;
-                    }
-                }
-                $course->timeupdated = userdate($course->timemodified);
-                $coursefileinfo = get_string('fileinfo', 'block_community', $course);
-                $coursefileinfohtml = html_writer::tag('div', $coursefileinfo,
-                                array('class' => 'hubcoursefileinfo'));
-
-
-
-                //Create course content html
-                $blocks = core_component::get_plugin_list('block');
-                $activities = core_component::get_plugin_list('mod');
-                if (!empty($course->contents)) {
-                    $activitieshtml = '';
-                    $blockhtml = '';
-                    foreach ($course->contents as $content) {
-                        $content = (object) $content;
-                        if ($content->moduletype == 'block') {
-                            if (!empty($blockhtml)) {
-                                $blockhtml .= ' - ';
-                            }
-                            if (array_key_exists($content->modulename, $blocks)) {
-                                $blockname = get_string('pluginname', 'block_' . $content->modulename);
-                            } else {
-                                $blockname = $content->modulename;
-                            }
-                            $blockhtml .= $blockname . " (" . $content->contentcount . ")";
-                        } else {
-                            if (!empty($activitieshtml)) {
-                                $activitieshtml .= ' - ';
-                            }
-                            if (array_key_exists($content->modulename, $activities)) {
-                                $activityname = get_string('modulename', $content->modulename);
-                            } else {
-                                $activityname = $content->modulename;
-                            }
-                            $activitieshtml .= $activityname . " (" . $content->contentcount . ")";
-                        }
-                    }
-
-                    $blocksandactivities = html_writer::tag('div',
-                                    get_string('activities', 'block_community') . " : " . $activitieshtml);
-
-                    //Uncomment following lines to display blocks information
-//                    $blocksandactivities .= html_writer::tag('span',
-//                                    get_string('blocks', 'block_community') . " : " . $blockhtml);
-                }
-
-                //Create outcomes html
-                $outcomes= '';
-                if (!empty($course->outcomes)) {
-                    foreach ($course->outcomes as $outcome) {
-                        if (!empty($outcomes)) {
-                            $outcomes .= ', ';
-                        }
-                        $outcomes .= $outcome['fullname'];
-                    }
-                    $outcomes = get_string('outcomes', 'block_community',
-                            $outcomes);
-                }
-                $outcomeshtml = html_writer::tag('div', $outcomes, array('class' => 'hubcourseoutcomes'));
-
-                //create additional information html
-                $additionaldesc = $courseuserinfohtml . $coursecontentinfohtml
-                        . $coursefileinfohtml . $blocksandactivities . $outcomeshtml;
-                $additionaldeschtml = html_writer::tag('div', $additionaldesc,
-                                array('class' => 'additionaldesc'));
-
-                //Create add button html
-                $addbuttonhtml = "";
-                if ($course->enrollable) {
-                    $params = array('sesskey' => sesskey(), 'add' => 1, 'confirmed' => 1,
-                        'coursefullname' => $course->fullname, 'courseurl' => $courseurl,
-                        'coursedescription' => $course->description,
-                        'courseid' => $contextcourseid);
-                    $addurl = new moodle_url("/blocks/community/communitycourse.php", $params);
-                    $addbuttonhtml = html_writer::tag('a',
-                                    get_string('addtocommunityblock', 'block_community'),
-                                    array('href' => $addurl, 'class' => 'centeredbutton, hubcoursedownload'));
-                }
-
-                //create download button html
-                $downloadbuttonhtml = "";
-                if (!$course->enrollable) {
-                    $params = array('sesskey' => sesskey(), 'download' => 1, 'confirmed' => 1,
-                        'remotemoodleurl' => $CFG->wwwroot, 'courseid' => $contextcourseid,
-                        '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'),
-                                    array('href' => $downloadurl, 'class' => 'centeredbutton, hubcoursedownload'));
-                }
-
-                //Create rating html
-                $rating = html_writer::tag('div', get_string('noratings', 'block_community'),
-                                array('class' => 'norating'));
-                if (!empty($course->rating)) {
-                    $course->rating = (object) $course->rating;
-                    if ($course->rating->count > 0) {
-
-                        //calculate size of the rating star
-                        $starimagesize = 20; //in px
-                        $numberofstars = 5;
-                        $size = ($course->rating->aggregate / $course->rating->scaleid)
-                                * $numberofstars * $starimagesize;
-                        $rating = html_writer::tag('li', '',
-                                        array('class' => 'current-rating',
-                                            'style' => 'width:' . $size . 'px;'));
-
-                        $rating = html_writer::tag('ul', $rating,
-                                        array('class' => 'star-rating clearfix'));
-                        $rating .= html_writer::tag('div', ' (' . $course->rating->count . ')',
-                                        array('class' => 'ratingcount clearfix'));
-                    }
-                }
-
-
-                //Create comments html
-                $coursecomments = html_writer::tag('div', get_string('nocomments', 'block_community'),
-                                array('class' => 'nocomments'));
-                $commentcount = 0;
-                if (!empty($course->comments)) {
-                    //display only if there is some comment if there is some comment
-                    $commentcount = count($course->comments);
-                    $coursecomments = html_writer::tag('div',
-                                    get_string('comments', 'block_community', $commentcount),
-                                    array('class' => 'commenttitle'));
-
-                    foreach ($course->comments as $comment) {
-                        $commentator = html_writer::tag('div',
-                                        $comment['commentator'],
-                                        array('class' => 'hubcommentator'));
-                        $commentdate = html_writer::tag('div',
-                                        ' - ' . userdate($comment['date'], '%e/%m/%y'),
-                                        array('class' => 'hubcommentdate clearfix'));
-
-                        $commenttext = html_writer::tag('div',
-                                        $comment['comment'],
-                                        array('class' => 'hubcommenttext'));
-
-                        $coursecomments .= html_writer::tag('div',
-                                        $commentator . $commentdate . $commenttext,
-                                        array('class' => 'hubcomment'));
-                    }
-                    $coursecommenticon = html_writer::tag('div',
-                                    get_string('comments', 'block_community', $commentcount),
-                                    array('class' => 'hubcoursecomments',
-                                        'id' => 'comments-' . $course->id));
-                    $coursecomments = $coursecommenticon . html_writer::tag('div',
-                                    $coursecomments,
-                                    array('class' => 'yui3-overlay-loading',
-                                        'id' => 'commentoverlay-' . $course->id));
-                }
-
-                //link rate and comment
-                $rateandcomment = html_writer::tag('div',
-                                html_writer::link($course->commenturl, get_string('rateandcomment', 'block_community'),
-                                            ['onclick' => 'this.target="_blank"']),
-                                array('class' => 'hubrateandcomment'));
-
-                //the main DIV tags
-                $buttonsdiv = html_writer::tag('div',
-                                $addbuttonhtml . $downloadbuttonhtml . $visitlinkhtml,
-                                array('class' => 'courseoperations'));
-                $screenshotbuttonsdiv = html_writer::tag('div',
-                                $coursescreenshot . $buttonsdiv,
-                                array('class' => 'courselinks'));
-
-                $coursedescdiv = html_writer::tag('div',
-                                $deschtml . $additionaldeschtml
-                                . $rating . $coursecomments . $rateandcomment,
-                                array('class' => 'coursedescription'));
-                $coursehtml =
-                        $coursenamehtml . html_writer::tag('div',
-                                $coursedescdiv . $screenshotbuttonsdiv,
-                                array('class' => 'hubcourseinfo clearfix'));
-
-                $renderedhtml .=html_writer::tag('div', $coursehtml,
-                                array('class' => 'fullhubcourse clearfix'));
-            }
-
-            $renderedhtml = html_writer::tag('div', $renderedhtml,
-                            array('class' => 'hubcourseresult'));
-        }
-
-        return $renderedhtml;
-    }
-
-}
diff --git a/blocks/community/styles.css b/blocks/community/styles.css
deleted file mode 100644 (file)
index f9ecac8..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/** General display rules **/
-
-/* HUB SELECTOR */
-#page-blocks-community-communitycourse .hubscreenshot {
-    float: left;
-}
-
-#page-blocks-community-communitycourse .hubtitlelink {
-    color: #999;
-}
-
-#page-blocks-community-communitycourse .hubsmalllogo {
-    padding-left: 3px;
-    padding-right: 7px;
-    float: left;
-}
-
-#page-blocks-community-communitycourse .hubtext {
-    display: block;
-    width: 68%;
-    padding-left: 165px;
-}
-
-#page-blocks-community-communitycourse .hubimage {
-    float: left;
-    display: block;
-    width: 100px;
-}
-
-#page-blocks-community-communitycourse .hubstats {
-    padding-top: 10px;
-}
-
-#page-blocks-community-communitycourse .hubstats .iconhelp {
-    float: left;
-    padding-right: 3px;
-}
-
-#page-blocks-community-communitycourse .hubadditionaldesc {
-    color: #666;
-    font-size: 90%;
-    display: block;
-}
-
-#page-blocks-community-communitycourse .hubscreenshot {
-    margin-right: 10px;
-}
-
-#page-blocks-community-communitycourse .hubtrusted {
-    display: inline;
-}
-
-#page-blocks-community-communitycourse .trustedtr {
-    background-color: #ffe1c3;
-}
-
-#page-blocks-community-communitycourse .prioritisetr {
-    background-color: #ffd4ff;
-}
-
-#page-blocks-community-communitycourse .blockdescription {
-    font-size: 80%;
-    color: #555;
-}
-
-#page-blocks-community-communitycourse .trusted {
-    font-size: 90%;
-    color: #063;
-    font-weight: normal;
-    font-style: italic;
-}
-
-/* COURSES RESULT */
-#page-blocks-community-communitycourse .additionaldesc {
-    font-size: 80%;
-    color: #8b8989;
-}
-
-#page-blocks-community-communitycourse .comment-link {
-    font-size: 80%;
-    color: #555;
-}
-
-#page-blocks-community-communitycourse .coursescreenshot {
-    text-align: center;
-    cursor: pointer;
-}
-
-#page-blocks-community-communitycourse .hubcourseinfo {
-    margin-left: 15px;
-}
-
-#page-blocks-community-communitycourse .pagingbar {
-    text-align: center;
-}
-
-#page-blocks-community-communitycourse .coursecomment {
-    float: right;
-}
-
-#page-blocks-community-communitycourse .courseoperations {
-    margin-top: 9px;
-    text-align: center;
-}
-
-#page-blocks-community-communitycourse .hubcoursedownload:hover {
-    background-color: #cdc9c9;
-}
-
-#page-blocks-community-communitycourse .courselinks {
-    float: right;
-    width: 180px;
-}
-
-#page-blocks-community-communitycourse .ratingaggregate {
-    float: left;
-    padding-right: 4px;
-}
-
-#page-blocks-community-communitycourse .hubcourserating {
-    padding-top: 3px;
-    font-size: 80%;
-    color: #555;
-}
-
-#page-blocks-community-communitycourse .coursedescription {
-    width: 70%;
-    float: left;
-}
-
-#page-blocks-community-communitycourse .fullhubcourse {
-    margin-bottom: 20px;
-}
-
-#page-blocks-community-communitycourse .hubcoursetitlepanel {
-    margin-bottom: 6px;
-}
-
-#page-blocks-community-communitycourse .hubcourseresult {
-    background: none repeat scroll 0 0 #fff;
-    clear: both;
-    margin: 30px auto 0;
-    z-index: 90;
-    width: 95%;
-    padding: 10px 10px 10px 10px;
-    border-style: solid;
-    border-width: 1px;
-}
-
-#page-blocks-community-communitycourse .hubcoursetitle {
-    -webkit-box-shadow: rgba(0, 0, 0, 0.546875) 0 0 4px;
-    -moz-box-shadow: rgba(0, 0, 0, 0.546875) 0 0 4px;
-    background: #8b8989;
-    left: -15px;
-    position: relative;
-    z-index: 0;
-    border: 0;
-    margin: 0;
-    outline: 0;
-    padding: 0;
-    vertical-align: baseline;
-    color: #fff;
-    padding-top: 6px;
-    padding-bottom: 6px;
-    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
-    text-align: left;
-    font-style: italic;
-    font-weight: normal;
-    line-height: 1.2em;
-    font-size: 140%;
-    width: 102%;
-    text-indent: 15px;
-}
-
-#page-blocks-community-communitycourse .hubcoursedownload {
-    display: inline-block;
-    padding: 5px 8px 6px;
-    color: black;
-    text-decoration: none;
-    -moz-border-radius: 6px;
-    -webkit-border-radius: 6px;
-    -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
-    -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
-    border-bottom: 1px solid rgba(0, 0, 0, 0.25);
-    position: relative;
-    cursor: pointer;
-    background-color: #eee9e9;
-    margin-left: 6px;
-    font-size: 95%;
-    margin-bottom: 9px;
-}
-
-/*  STAR RATING  */
-#page-blocks-community-communitycourse .ratingcount {
-    color: #8b8989;
-    font-size: 80%;
-    vertical-align: top;
-}
-
-#page-blocks-community-communitycourse .norating {
-    font-weight: bold;
-    color: #8b8989;
-    font-size: 80%;
-}
-
-#page-blocks-community-communitycourse .star-rating {
-    list-style: none;
-    margin: 4px 0 4px;
-    padding: 0;
-    width: 100px;
-    height: 20px;
-    position: relative;
-    background: url([[pix:i/star-rating]]) top left repeat-x;
-    float: left;
-}
-
-#page-blocks-community-communitycourse .star-rating li {
-    padding: 0;
-    margin: 0;
-    height: 20px;
-    width: 20px;
-    float: left;
-}
-
-#page-blocks-community-communitycourse .star-rating li.current-rating {
-    background: url([[pix:i/star-rating]]) left bottom;
-    position: absolute;
-    height: 20px;
-    display: block;
-    text-indent: -9000px;
-    z-index: 1;
-}
-
-/* COMMENTS */
-#page-blocks-community-communitycourse .nocomments {
-    font-weight: bold;
-    color: #8b8989;
-    font-size: 80%;
-}
-
-#page-blocks-community-communitycourse .hubcommentator {
-    float: left;
-    font-weight: bold;
-}
-
-#page-blocks-community-communitycourse .hubcommentdate {
-    font-weight: bold;
-}
-
-#page-blocks-community-communitycourse .hubcommenttext {
-    margin-bottom: 10px;
-}
-
-#page-blocks-community-communitycourse .hubnoscriptcoursecomments {
-    margin-left: 5px;
-}
-
-#page-blocks-community-communitycourse .yui3-overlay-loading {
-    /* Hide overlay markup while loading, if js is enabled */
-    top: -1000em;
-    left: -1000em;
-    position: absolute;
-    z-index: 1000;
-}
-
-#page-blocks-community-communitycourse .hubcoursecomments {
-    /* comment button */
-    display: inline-block;
-    padding: 3px 3px 3px 3px;
-    color: white;
-    text-decoration: none;
-    -moz-border-radius: 6px;
-    -webkit-border-radius: 6px;
-    position: relative;
-    cursor: pointer;
-    background-color: #8b8989;
-    margin-left: 0;
-    font-size: 80%;
-    margin-top: 15px;
-}
-
-#page-blocks-community-communitycourse .hubrateandcomment {
-    font-size: 80%;
-}
-
-#page-blocks-community-communitycourse .nextlink {
-    text-align: center;
-    margin-top: 6px;
-}
-
-#page-blocks-community-communitycourse .textinfo {
-    text-align: center;
-}
-
-#ss-mask {
-    z-index: 10;
-    position: fixed;
-    top: 0;
-    left: 0;
-    bottom: 0;
-    right: 0;
-    opacity: 0.35;
-    filter: alpha(opacity=35);
-    background: #000;
-}
-
-.hiddenoverlay {
-    display: none;
-    text-align: center;
-}
-
-.imagearrow {
-    font-size: 120%;
-    display: inline;
-    cursor: pointer;
-}
-
-.imagetitle {
-    display: inline;
-    cursor: pointer;
-}
-
-#page-blocks-community-communitycourse .moodle-dialogue-base .moodle-dialogue {
-    -moz-border-radius: 12px 12px 12px 12px;
-    -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
-    -webkit-border-radius: 12px 12px 12px 12px;
-    -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
-    border-width: 0 0 0 0;
-}
-
-#page-blocks-community-communitycourse .moodle-dialogue-base .moodle-dialogue-wrap {
-    -moz-border-radius: 12px 12px 0 0;
-    -webkit-border-radius: 12px 12px 0 0;
-    background-color: #fff;
-    border: 1px solid #555;
-}
-
-#page-blocks-community-communitycourse .moodle-dialogue-base .moodle-dialogue-hd {
-    -moz-border-radius: 12px 12px 0 0;
-    -webkit-border-radius: 12px 12px 0 0;
-    background-color: #f6f6f6;
-    border: 1px solid #ccc;
-    overflow: auto;
-    padding: 7px 6px;
-}
-
-#page-blocks-community-communitycourse .moodle-dialogue-base .moodle-dialogue-bd {
-    padding: 0;
-    margin-bottom: -5px;
-}
-
-#page-blocks-community-communitycourse .moodle-dialogue-base .closebutton {
-    margin-top: 4px;
-    margin-right: 4px;
-}
diff --git a/blocks/community/tests/privacy_test.php b/blocks/community/tests/privacy_test.php
deleted file mode 100644 (file)
index fce8b29..0000000
+++ /dev/null
@@ -1,401 +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/>.
-
-/**
- * Unit tests for the block_community implementation of the privacy API.
- *
- * @package    block_community
- * @category   test
- * @copyright  2018 Zig Tan <zig@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-use \core_privacy\local\metadata\collection;
-use \core_privacy\local\request\writer;
-use \core_privacy\local\request\approved_contextlist;
-use \block_community\privacy\provider;
-use \core_privacy\local\request\approved_userlist;
-
-/**
- * Unit tests for the block_community implementation of the privacy API.
- *
- * @copyright  2018 Zig Tan <zig@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class block_community_privacy_testcase extends \core_privacy\tests\provider_testcase {
-
-    /**
-     * Overriding setUp() function to always reset after tests.
-     */
-    public function setUp() {
-        $this->resetAfterTest(true);
-    }
-
-    /**
-     * Test for provider::get_metadata().
-     */
-    public function test_get_metadata() {
-        $collection = new collection('block_community');
-        $newcollection = provider::get_metadata($collection);
-        $itemcollection = $newcollection->get_collection();
-        $this->assertCount(1, $itemcollection);
-
-        $table = reset($itemcollection);
-        $this->assertEquals('block_community', $table->get_name());
-
-        $privacyfields = $table->get_privacy_fields();
-        $this->assertArrayHasKey('userid', $privacyfields);
-        $this->assertArrayHasKey('coursename', $privacyfields);
-        $this->assertArrayHasKey('coursedescription', $privacyfields);
-        $this->assertArrayHasKey('courseurl', $privacyfields);
-        $this->assertArrayHasKey('imageurl', $privacyfields);
-
-        $this->assertEquals('privacy:metadata:block_community', $table->get_summary());
-    }
-
-    /**
-     * Test for provider::get_contexts_for_userid().
-     */
-    public function test_get_contexts_for_userid() {
-        global $DB;
-
-        // Test setup.
-        $teacher = $this->getDataGenerator()->create_user();
-        $this->setUser($teacher);
-
-        // Add two community links for the User.
-        $community = (object)[
-            'userid' => $teacher->id,
-            'coursename' => 'Dummy Community Course Name - 1',
-            'coursedescription' => 'Dummy Community Course Description - 1',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-1',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        $community = (object)[
-            'userid' => $teacher->id,
-            'coursename' => 'Dummy Community Course Name - 2',
-            'coursedescription' => 'Dummy Community Course Description - 2',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-2',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        // Test the User's retrieved contextlist contains only one context.
-        $contextlist = provider::get_contexts_for_userid($teacher->id);
-        $contexts = $contextlist->get_contexts();
-        $this->assertCount(1, $contexts);
-
-        // Test the User's contexts equal the User's own context.
-        $context = reset($contexts);
-        $this->assertEquals(CONTEXT_USER, $context->contextlevel);
-        $this->assertEquals($teacher->id, $context->instanceid);
-    }
-
-    /**
-     * Test for provider::export_user_data().
-     */
-    public function test_export_user_data() {
-        global $DB;
-
-        // Test setup.
-        $teacher = $this->getDataGenerator()->create_user();
-        $this->setUser($teacher);
-
-        // Add 3 community links for the User.
-        $nocommunities = 3;
-        for ($c = 0; $c < $nocommunities; $c++) {
-            $community = (object)[
-                'userid' => $teacher->id,
-                'coursename' => 'Dummy Community Course Name - ' . $c,
-                'coursedescription' => 'Dummy Community Course Description - ' . $c,
-                'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-' . $c,
-                'imageurl' => ''
-            ];
-            $DB->insert_record('block_community', $community);
-        }
-
-        // Test the created block_community records matches the test number of communities specified.
-        $communities = $DB->get_records('block_community', ['userid' => $teacher->id]);
-        $this->assertCount($nocommunities, $communities);
-
-        // Test the User's retrieved contextlist contains only one context.
-        $contextlist = provider::get_contexts_for_userid($teacher->id);
-        $contexts = $contextlist->get_contexts();
-        $this->assertCount(1, $contexts);
-
-        // Test the User's contexts equal the User's own context.
-        $context = reset($contexts);
-        $this->assertEquals(CONTEXT_USER, $context->contextlevel);
-        $this->assertEquals($teacher->id, $context->instanceid);
-
-        $approvedcontextlist = new approved_contextlist($teacher, 'block_community', $contextlist->get_contextids());
-
-        // Retrieve Calendar Event and Subscriptions data only for this user.
-        provider::export_user_data($approvedcontextlist);
-
-        // Test the block_community data is exported at the User context level.
-        $user = $approvedcontextlist->get_user();
-        $contextuser = context_user::instance($user->id);
-        $writer = writer::with_context($contextuser);
-        $this->assertTrue($writer->has_any_data());
-    }
-
-    /**
-     * Test for provider::delete_data_for_all_users_in_context().
-     */
-    public function test_delete_data_for_all_users_in_context() {
-        global $DB;
-
-        // Test setup.
-        $teacher = $this->getDataGenerator()->create_user();
-        $this->setUser($teacher);
-
-        // Add a community link for the User.
-        $community = (object)[
-            'userid' => $teacher->id,
-            'coursename' => 'Dummy Community Course Name',
-            'coursedescription' => 'Dummy Community Course Description',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        // Test the User's retrieved contextlist contains only one context.
-        $contextlist = provider::get_contexts_for_userid($teacher->id);
-        $contexts = $contextlist->get_contexts();
-        $this->assertCount(1, $contexts);
-
-        // Test the User's contexts equal the User's own context.
-        $context = reset($contexts);
-        $this->assertEquals(CONTEXT_USER, $context->contextlevel);
-        $this->assertEquals($teacher->id, $context->instanceid);
-
-        // Test delete all users content by context.
-        provider::delete_data_for_all_users_in_context($context);
-        $blockcommunity = $DB->get_records('block_community', ['userid' => $teacher->id]);
-        $this->assertCount(0, $blockcommunity);
-    }
-
-    /**
-     * Test for provider::delete_data_for_user().
-     */
-    public function test_delete_data_for_user() {
-        global $DB;
-
-        // Test setup.
-        $teacher1 = $this->getDataGenerator()->create_user();
-        $teacher2 = $this->getDataGenerator()->create_user();
-        $this->setUser($teacher1);
-
-        // Add 3 community links for Teacher 1.
-        $nocommunities = 3;
-        for ($c = 0; $c < $nocommunities; $c++) {
-            $community = (object)[
-                'userid' => $teacher1->id,
-                'coursename' => 'Dummy Community Course Name - ' . $c,
-                'coursedescription' => 'Dummy Community Course Description - ' . $c,
-                'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-' . $c,
-                'imageurl' => ''
-            ];
-            $DB->insert_record('block_community', $community);
-        }
-
-        // Add 1 community link for Teacher 2.
-        $community = (object)[
-            'userid' => $teacher2->id,
-            'coursename' => 'Dummy Community Course Name - Blah',
-            'coursedescription' => 'Dummy Community Course Description - Blah',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-Blah',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        // Test the created block_community records for Teacher 1 equals test number of communities specified.
-        $communities = $DB->get_records('block_community', ['userid' => $teacher1->id]);
-        $this->assertCount($nocommunities, $communities);
-
-        // Test the created block_community records for Teacher 2 equals 1.
-        $communities = $DB->get_records('block_community', ['userid' => $teacher2->id]);
-        $this->assertCount(1, $communities);
-
-        // Test the deletion of block_community records for Teacher 1 results in zero records.
-        $contextlist = provider::get_contexts_for_userid($teacher1->id);
-        $contexts = $contextlist->get_contexts();
-        $this->assertCount(1, $contexts);
-
-        // Test the User's contexts equal the User's own context.
-        $context = reset($contexts);
-        $this->assertEquals(CONTEXT_USER, $context->contextlevel);
-        $this->assertEquals($teacher1->id, $context->instanceid);
-
-        $approvedcontextlist = new approved_contextlist($teacher1, 'block_community', $contextlist->get_contextids());
-        provider::delete_data_for_user($approvedcontextlist);
-        $communities = $DB->get_records('block_community', ['userid' => $teacher1->id]);
-        $this->assertCount(0, $communities);
-
-
-        // Test that Teacher 2's single block_community record still exists.
-        $contextlist = provider::get_contexts_for_userid($teacher2->id);
-        $contexts = $contextlist->get_contexts();
-        $this->assertCount(1, $contexts);
-
-        // Test the User's contexts equal the User's own context.
-        $context = reset($contexts);
-        $this->assertEquals(CONTEXT_USER, $context->contextlevel);
-        $this->assertEquals($teacher2->id, $context->instanceid);
-
-        $communities = $DB->get_records('block_community', ['userid' => $teacher2->id]);
-        $this->assertCount(1, $communities);
-    }
-
-    /**
-     * Test that only users within a course context are fetched.
-     */
-    public function test_get_users_in_context() {
-        global $DB;
-
-        $component = 'block_community';
-
-        // Create a user.
-        $teacher = $this->getDataGenerator()->create_user();
-        $teacherctx = \context_user::instance($teacher->id);
-
-        $userlist = new \core_privacy\local\request\userlist($teacherctx, $component);
-        provider::get_users_in_context($userlist);
-        $this->assertCount(0, $userlist);
-
-        $this->setUser($teacher);
-        // Add two community links for the user.
-        $community = (object)[
-            'userid' => $teacher->id,
-            'coursename' => 'Dummy Community Course Name - 1',
-            'coursedescription' => 'Dummy Community Course Description - 1',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-1',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        $community = (object)[
-            'userid' => $teacher->id,
-            'coursename' => 'Dummy Community Course Name - 2',
-            'coursedescription' => 'Dummy Community Course Description - 2',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-2',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        // The list of users within the user context should contain user.
-        provider::get_users_in_context($userlist);
-        $this->assertCount(1, $userlist);
-        $expected = [$teacher->id];
-        $actual = $userlist->get_userids();
-        $this->assertEquals($expected, $actual);
-
-        // The list of users within the system context should be empty.
-        $systemctx = \context_system::instance();
-        $userlist2 = new \core_privacy\local\request\userlist($systemctx, $component);
-        provider::get_users_in_context($userlist2);
-        $this->assertCount(0, $userlist2);
-    }
-
-    /**
-     * Test that data for users in approved userlist is deleted.
-     */
-    public function test_delete_data_for_users() {
-        global $DB;
-
-        $component = 'block_community';
-
-        // Create user1.
-        $user1 = $this->getDataGenerator()->create_user();
-        $userctx1 = \context_user::instance($user1->id);
-        // Create user2.
-        $user2 = $this->getDataGenerator()->create_user();
-        $userctx2 = \context_user::instance($user2->id);
-
-        $this->setUser($user1);
-        // Add a community link for user1.
-        $community = (object)[
-            'userid' => $user1->id,
-            'coursename' => 'Dummy Community Course Name - 1',
-            'coursedescription' => 'Dummy Community Course Description - 1',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-1',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        // Add a community link for user1.
-        $community = (object)[
-            'userid' => $user1->id,
-            'coursename' => 'Dummy Community Course Name - 2',
-            'coursedescription' => 'Dummy Community Course Description - 2',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-2',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        $this->setUser($user2);
-        // Add a community link for user2.
-        $community = (object)[
-            'userid' => $user2->id,
-            'coursename' => 'Dummy Community Course Name - 3',
-            'coursedescription' => 'Dummy Community Course Description - 3',
-            'courseurl' => 'https://moodle.org/community_courses/Dummy_Community_Course-3',
-            'imageurl' => ''
-        ];
-        $DB->insert_record('block_community', $community);
-
-        $userlist1 = new \core_privacy\local\request\userlist($userctx1, $component);
-        provider::get_users_in_context($userlist1);
-        $this->assertCount(1, $userlist1);
-
-        $userlist2 = new \core_privacy\local\request\userlist($userctx2, $component);
-        provider::get_users_in_context($userlist2);
-        $this->assertCount(1, $userlist2);
-
-        // Convert $userlist1 into an approved_contextlist.
-        $approvedlist1 = new approved_userlist($userctx1, $component, $userlist1->get_userids());
-        // Delete using delete_data_for_user.
-        provider::delete_data_for_users($approvedlist1);
-
-        // Re-fetch users in userctx1.
-        $userlist1 = new \core_privacy\local\request\userlist($userctx1, $component);
-        provider::get_users_in_context($userlist1);
-        // The user data in userctx1 should be deleted.
-        $this->assertCount(0, $userlist1);
-
-        // Re-fetch users in userctx2.
-        $userlist2 = new \core_privacy\local\request\userlist($userctx2, $component);
-        provider::get_users_in_context($userlist2);
-        // The user data in userctx2 should be still present.
-        $this->assertCount(1, $userlist2);
-
-        // Convert $userlist2 into an approved_contextlist in the system context.
-        $systemcontext = \context_system::instance();
-        $approvedlist2 = new approved_userlist($systemcontext, $component, $userlist2->get_userids());
-        // Delete using delete_data_for_user.
-        provider::delete_data_for_users($approvedlist2);
-        // Re-fetch users in userctx2.
-        $userlist2 = new \core_privacy\local\request\userlist($userctx2, $component);
-        provider::get_users_in_context($userlist2);
-        // The user data in systemcontext should not be deleted.
-        $this->assertCount(1, $userlist2);
-    }
-}
diff --git a/blocks/community/version.php b/blocks/community/version.php
deleted file mode 100644 (file)
index c7034eb..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_community
- * @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   = 2019052000;        // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2019051100;        // Requires this Moodle version
-$plugin->component = 'block_community'; // Full name of the plugin (used for diagnostics)
diff --git a/blocks/community/yui/comments/comments.js b/blocks/community/yui/comments/comments.js
deleted file mode 100644 (file)
index e720c18..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-YUI.add('moodle-block_community-comments', function(Y) {
-
-    var COMMENTSNAME = 'blocks_community_comments';
-
-    var COMMENTS = function() {
-        COMMENTS.superclass.constructor.apply(this, arguments);
-    };
-
-    Y.extend(COMMENTS, Y.Base, {
-
-        event:null,
-        panelevent: null,
-        panels: [], //all the comment boxes
-
-        initializer : function(params) {
-
-            //attach a show event on the div with id = comments
-            for (var i=0;i<this.get('commentids').length;i++)
-            {
-                var commentid = this.get('commentids')[i];
-                this.panels[commentid] = new M.core.dialogue({
-                    headerContent:Y.Node.create('<h1>')
-                        .append(Y.one('#commentoverlay-'+commentid+' .commenttitle').get('innerHTML')),
-                    bodyContent:Y.one('#commentoverlay-'+commentid).get('innerHTML'),
-                    visible: false, //by default it is not displayed
-                    modal: false,
-                    zIndex:100,
-                    closeButtonTitle: this.get('closeButtonTitle')
-                });
-
-                this.panels[commentid].get('contentBox').one('.commenttitle').remove();
-                this.panels[commentid].render();
-                this.panels[commentid].hide();
-
-                Y.one('#comments-'+commentid).on('click', this.show, this, commentid);
-            }
-
-        },
-
-        show : function (e, commentid) {
-
-            // Hide all panels.
-            for (var i=0;i<this.get('commentids').length;i++)
-            {
-                this.hide(e, this.get('commentids')[i]);
-            }
-
-            this.panels[commentid].show(); //show the panel
-
-            e.halt(); // we are going to attach a new 'hide panel' event to the body,
-            // because javascript always propagate event to parent tag,
-            // we need to tell Yahoo to stop to call the event on parent tag
-            // otherwise the hide event will be call right away.
-
-            // We add a new event on the body in order to hide the panel for the next click.
-            this.event = Y.one(document.body).on('click', this.hide, this, commentid);
-            // We add a new event on the panel in order to hide the panel for the next click (touch device).
-            this.panelevent = Y.one("#commentoverlay-"+commentid).on('click', this.hide, this, commentid);
-
-            // Focus on the close button
-            this.panels[commentid].get('buttons').header[0].focus();
-        },
-
-        hide : function (e, commentid) {
-            this.panels[commentid].hide(); //hide the panel
-            if (this.event != null) {
-                this.event.detach(); //we need to detach the body hide event
-            //Note: it would work without but create js warning everytime
-            //we click on the body
-            }
-            if (this.panelevent != null) {
-                this.panelevent.detach(); //we need to detach the panel hide event
-            //Note: it would work without but create js warning everytime
-            //we click on the body
-            }
-
-        }
-
-    }, {
-        NAME : COMMENTSNAME,
-        ATTRS : {
-            commentids: {},
-            closeButtonTitle : {
-                validator : Y.Lang.isString,
-                value : 'Close'
-            }
-        }
-    });
-
-    M.blocks_community = M.blocks_community || {};
-    M.blocks_community.init_comments = function(params) {
-        return new COMMENTS(params);
-    }
-
-}, '@VERSION@', {
-    requires:['base', 'moodle-core-notification']
-});
diff --git a/blocks/community/yui/imagegallery/imagegallery.js b/blocks/community/yui/imagegallery/imagegallery.js
deleted file mode 100644 (file)
index b48a204..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-YUI.add('moodle-block_community-imagegallery', function(Y) {
-
-    var IMAGEGALLERYNAME = 'blocks_community_imagegallery';
-
-    var IMAGEGALLERY = function() {
-        IMAGEGALLERY.superclass.constructor.apply(this, arguments);
-    };
-
-    Y.extend(IMAGEGALLERY, Y.Base, {
-
-        event:null,
-        previousevent:null,
-        nextevent:null,
-        panelevent:null,
-        panel:null, //all the images boxes
-        imageidnumbers: [],
-        imageloadingevent: null,
-        loadingimage: null,
-
-        initializer : function(params) {
-
-            //create the loading image
-            var objBody = Y.one(document.body);
-            this.loadingimage = Y.Node.create('<div id="hubloadingimage" class="hiddenoverlay">'
-                +'<img src=\'' + M.cfg.wwwroot +'/pix/i/loading.gif\'>'
-                +'</div>');
-            objBody.append(this.loadingimage);
-
-            // Create the div for panel.
-            var objBody = Y.one(document.body);
-            var paneltitle = Y.Node.create('<div id="imagetitleoverlay" class="hiddenoverlay"></div>');
-            objBody.append(paneltitle);
-            var panel = Y.Node.create('<div id="imageoverlay" class="hiddenoverlay"></div>');
-            objBody.append(panel);
-
-            /// Create the panel.
-            this.panel = new M.core.dialogue({
-                headerContent:Y.one('#imagetitleoverlay').get('innerHTML'),
-                bodyContent:Y.one('#imageoverlay').get('innerHTML'),
-                visible: false, //by default it is not displayed
-                modal: false,
-                zIndex:100
-            });
-
-            this.panel.render();
-            this.panel.hide();
-
-            //attach a show event on the image divs (<tag id='image-X'>)
-            for (var i=0;i<this.get('imageids').length;i++)
-            {
-                var imageid = this.get('imageids')[i];
-                this.imageidnumbers[imageid] = this.get('imagenumbers')[i];
-                Y.one('#image-'+imageid).on('click', this.show, this, imageid, 1);
-            }
-
-        },
-
-        show : function (e, imageid, screennumber) {
-
-            if (this.imageloadingevent != null) {
-                this.imageloadingevent.detach();
-            }
-
-            var url = this.get('huburl') + "/local/hub/webservice/download.php?courseid="
-            + imageid + "&filetype=screenshot&imagewidth=original&screenshotnumber=" + screennumber;
-
-            /// set the mask
-            if (this.get('maskNode')) {
-                this.get('maskNode').remove();
-            }
-            var objBody = Y.one(document.body);
-            var mask = Y.Node.create('<div id="ss-mask"><!-- --></div>');
-            objBody.prepend(mask);
-            this.set('maskNode', Y.one('#ss-mask'));
-
-            //display loading image
-            Y.one('#hubloadingimage').setStyle('display', 'block');
-            Y.one('#hubloadingimage').setStyle("position", 'fixed');
-            Y.one('#hubloadingimage').setStyle("top", '50%');
-            Y.one('#hubloadingimage').setStyle("left", '50%');
-
-            var windowheight = e.target.get('winHeight');
-            var windowwidth = e.target.get('winWidth');
-
-            var maxheight = windowheight - 150;
-
-            //load the title + link to next image
-            var paneltitle = Y.one('#imagetitleoverlay');
-            var previousimagelink = "<div id=\"previousarrow\" class=\"imagearrow\">←</div>";
-            var nextimagelink = "<div id=\"nextarrow\" class=\"imagearrow\">→</div>";
-
-            // Need to load the images in the panel.
-            var panel = Y.one('#imageoverlay');
-            panel.setContent('');
-
-            panel.append(Y.Node.create('<div style="text-align:center"><img id=\"imagetodisplay\" src="' + url
-                + '" style="max-height:' + maxheight + 'px;"></div>'));
-            this.panel.destroy();
-            this.panel = new M.core.dialogue({
-                headerContent:previousimagelink + '<div id=\"imagenumber\" class=\"imagetitle\"><h1> Image '
-                + screennumber + ' / ' + this.imageidnumbers[imageid] + ' </h1></div>' + nextimagelink,
-                bodyContent:Y.one('#imageoverlay').get('innerHTML'),
-                visible: false, //by default it is not displayed
-                modal: false,
-                zIndex:100,
-                closeButtonTitle: this.get('closeButtonTitle')
-            });
-            this.panel.render();
-            this.panel.hide(); //show the panel
-            this.panel.set("centered", true);
-
-            e.halt(); // we are going to attach a new 'hide panel' event to the body,
-            // because javascript always propagate event to parent tag,
-            // we need to tell Yahoo to stop to call the event on parent tag
-            // otherwise the hide event will be call right away.
-
-            //once the image is loaded, update display
-            this.imageloadingevent = Y.one('#imagetodisplay').on('load', function(e, url){
-                //hide the loading image
-                Y.one('#hubloadingimage').setStyle('display', 'none');
-
-                //display the screenshot
-                var screenshot = new Image();
-                screenshot.src = url;
-
-                var panelwidth = windowwidth - 100;
-                if(panelwidth > screenshot.width) {
-                    panelwidth = screenshot.width;
-                }
-
-                this.panel.set('width', panelwidth);
-                this.panel.set("centered", true);
-                this.panel.show();
-
-                // Focus on the close button
-                this.panel.get('buttons').header[0].focus();
-
-            }, this, url);
-
-            var previousnumber = screennumber - 1;
-            var nextnumber = screennumber + 1;
-            if (previousnumber == 0) {
-                previousnumber = this.imageidnumbers[imageid];
-            }
-            if (nextnumber > this.imageidnumbers[imageid]) {
-                nextnumber = 1;
-            }
-
-            Y.one('#previousarrow').on('click', this.show, this, imageid, previousnumber);
-            Y.one('#nextarrow').on('click', this.show, this, imageid, nextnumber);
-            Y.one('#imagenumber').on('click', this.show, this, imageid, nextnumber);
-
-            // We add a new event on the body in order to hide the panel for the next click.
-            this.event = Y.one(document.body).on('click', this.hide, this);
-            // We add a new event on the panel in order to hide the panel for the next click (touch device).
-            this.panelevent = Y.one("#imageoverlay").on('click', this.hide, this);
-
-            this.panel.on('visibleChange',function(e){
-                if(e.newVal == 0){
-                    this.get('maskNode').remove()
-                }
-            }, this);
-        },
-
-        hide : function (e) {
-
-            // remove the mask
-            this.get('maskNode').remove();
-
-            //hide the loading image
-            Y.one('#hubloadingimage').setStyle('display', 'none');
-
-            this.panel.hide(); //hide the panel
-            if (this.event != null) {
-                this.event.detach(); //we need to detach the body hide event
-            //Note: it would work without but create js warning everytime
-            //we click on the body
-            }
-            if (this.panelevent != null) {
-                this.panelevent.detach(); //we need to detach the panel hide event
-            //Note: it would work without but create js warning everytime
-            //we click on the body
-            }
-        }
-
-    }, {
-        NAME : IMAGEGALLERYNAME,
-        ATTRS : {
-            imageids: {},
-            imagenumbers: {},
-            huburl: {},
-            closeButtonTitle : {
-                validator : Y.Lang.isString,
-                value : 'Close'
-            }
-        }
-    });
-
-    M.blocks_community = M.blocks_community || {};
-    M.blocks_community.init_imagegallery = function(params) {
-        return new IMAGEGALLERY(params);
-    }
-
-}, '@VERSION@', {
-    requires:['base','node', 'moodle-core-notification']
-});
index 8fe7076..3c7226a 100644 (file)
@@ -57,8 +57,8 @@ $string['favourites'] = 'Starred';
 $string['future'] = 'Future';
 $string['inprogress'] = 'In progress';
 $string['lastaccessed'] = 'Last accessed';
-$string['layouts'] = 'Available Layouts';
-$string['layouts_help'] = 'The layouts which are available for selection by users';
+$string['layouts'] = 'Available layouts';
+$string['layouts_help'] = 'Course overview layouts which are available for selection by users. If none are selected, the card layout will be used.';
 $string['list'] = 'List';
 $string['myoverview:myaddinstance'] = 'Add a new course overview block to Dashboard';
 $string['past'] = 'Past';
index 258de45..0f370ee 100644 (file)
@@ -1,6 +1,9 @@
 This files describes API changes in /blocks/* - activity modules,
 information provided here is intended especially for developers.
 
+=== 3.8 ===
+* Block block_community is no longer a part of core.
+
 === 3.7 ===
 * The block:addinstance capability is no longer required if the block can only be added to a dashboard.
 
index 5e4ae97..cf3118a 100644 (file)
@@ -654,6 +654,9 @@ $CFG->admin = 'admin';
 // Prevent JS caching
 // $CFG->cachejs = false; // NOT FOR PRODUCTION SERVERS!
 //
+// Prevent Template caching
+// $CFG->cachetemplates = false; // NOT FOR PRODUCTION SERVERS!
+//
 // Restrict which YUI logging statements are shown in the browser console.
 // For details see the upstream documentation:
 //   http://yuilibrary.com/yui/docs/api/classes/config.html#property_logInclude
index 4fc5fff..3c301ff 100644 (file)
Binary files a/course/amd/build/repository.min.js and b/course/amd/build/repository.min.js differ
index 11f07a1..21f6694 100644 (file)
Binary files a/course/amd/build/repository.min.js.map and b/course/amd/build/repository.min.js.map differ
index 98b67d5..6340eab 100644 (file)
@@ -71,7 +71,7 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
         var args = {};
 
         if (typeof userid !== 'undefined') {
-            args.limit = limit;
+            args.userid = userid;
         }
 
         if (typeof limit !== 'undefined') {
index 81626d8..2072fe0 100644 (file)
@@ -166,7 +166,11 @@ if ($editform->is_cancelled()) {
 
         if (!empty($CFG->creatornewroleid) and !is_viewing($context, NULL, 'moodle/role:assign') and !is_enrolled($context, NULL, 'moodle/role:assign')) {
             // Deal with course creators - enrol them internally with default role.
-            enrol_try_internal_enrol($course->id, $USER->id, $CFG->creatornewroleid);
+            if (user_can_assign($context, $CFG->creatornewroleid)) {
+                enrol_try_internal_enrol($course->id, $USER->id, $CFG->creatornewroleid);
+            } else {
+                enrol_try_internal_enrol($course->id, $USER->id);
+            }
         }
 
         // The URL to take them to if they chose save and display.
index 50fa91a..5db9dea 100644 (file)
@@ -36,6 +36,9 @@ class format_singleactivity extends format_base {
     /** @var cm_info the current activity. Use get_activity() to retrieve it. */
     private $activity = false;
 
+    /** @var int The category ID guessed from the form data. */
+    private $categoryid = false;
+
     /**
      * The URL to use for the specified course
      *
@@ -145,6 +148,30 @@ class format_singleactivity extends format_base {
      */
     public function course_format_options($foreditform = false) {
         static $courseformatoptions = false;
+
+        $fetchtypes = $courseformatoptions === false;
+        $fetchtypes = $fetchtypes || ($foreditform && !isset($courseformatoptions['activitytype']['label']));
+
+        if ($fetchtypes) {
+            $availabletypes = $this->get_supported_activities();
+            if ($this->course) {
+                // The course exists. Test against the course.
+                $testcontext = context_course::instance($this->course->id);
+            } else if ($this->categoryid) {
+                // The course does not exist yet, but we have a category ID that we can test against.
+                $testcontext = context_coursecat::instance($this->categoryid);
+            } else {
+                // The course does not exist, and we somehow do not have a category. Test capabilities against the system context.
+                $testcontext = context_system::instance();
+            }
+            foreach (array_keys($availabletypes) as $activity) {
+                $capability = "mod/{$activity}:addinstance";
+                if (!has_capability($capability, $testcontext)) {
+                    unset($availabletypes[$activity]);
+                }
+            }
+        }
+
         if ($courseformatoptions === false) {
             $config = get_config('format_singleactivity');
             $courseformatoptions = array(
@@ -153,9 +180,13 @@ class format_singleactivity extends format_base {
                     'type' => PARAM_TEXT,
                 ),
             );
+
+            if (!empty($availabletypes) && !isset($availabletypes[$config->activitytype])) {
+                $courseformatoptions['activitytype']['default'] = array_keys($availabletypes)[0];
+            }
         }
+
         if ($foreditform && !isset($courseformatoptions['activitytype']['label'])) {
-            $availabletypes = $this->get_supported_activities();
             $courseformatoptionsedit = array(
                 'activitytype' => array(
                     'label' => new lang_string('activitytype', 'format_singleactivity'),
@@ -183,6 +214,11 @@ class format_singleactivity extends format_base {
      */
     public function create_edit_form_elements(&$mform, $forsection = false) {
         global $PAGE;
+
+        if (!$this->course && $submitvalues = $mform->getSubmitValues()) {
+            $this->categoryid = $submitvalues['category'];
+        }
+
         $elements = parent::create_edit_form_elements($mform, $forsection);
         if (!$forsection && ($course = $PAGE->course) && !empty($course->format) &&
                 $course->format !== 'site' && $course->format !== 'singleactivity') {
diff --git a/course/format/singleactivity/tests/behat/create_course.feature b/course/format/singleactivity/tests/behat/create_course.feature
new file mode 100644 (file)
index 0000000..6eee07f
--- /dev/null
@@ -0,0 +1,38 @@
+@format @format_singleactivity
+Feature: Courses can be created in Single Activity mode
+  In order to create a single activity course
+  As a manager
+  I need to create courses and set default values on them
+
+  Scenario: Create a course as a custom course creator
+    Given the following "users" exist:
+      | username  | firstname | lastname | email          |
+      | kevin  | Kevin   | the        | kevin@example.com |
+    And the following "roles" exist:
+      | shortname | name    | archetype |
+      | creator   | Creator |           |
+    And the following "system role assigns" exist:
+      | user   | role    | contextlevel |
+      | kevin  | creator | System       |
+    And I log in as "admin"
+    And I set the following system permissions of "Creator" role:
+      | capability | permission |
+      | moodle/course:create | Allow |
+      | moodle/course:update | Allow |
+      | moodle/course:manageactivities | Allow |
+      | moodle/course:viewparticipants | Allow |
+      | moodle/role:assign | Allow |
+      | mod/quiz:addinstance | Allow |
+    And I log out
+    And I log in as "kevin"
+    And I am on site homepage
+    When I press "Add a new course"
+    And I set the following fields to these values:
+      | Course full name  | My first course |
+      | Course short name | myfirstcourse |
+      | Format | Single activity format |
+    And I press "Update format"
+    Then I should see "Quiz" in the "Type of activity" "field"
+    And I should not see "Forum" in the "Type of activity" "field"
+    And I press "Save and display"
+    And I should see "Adding a new Quiz"
index 3eec792..205472d 100644 (file)
@@ -4045,7 +4045,6 @@ function course_get_user_administration_options($course, $context) {
         $options->outcomes = !empty($CFG->enableoutcomes) && has_capability('moodle/course:update', $context);
         $options->badges = !empty($CFG->enablebadges);
         $options->import = has_capability('moodle/restore:restoretargetimport', $context);
-        $options->publish = !empty($CFG->enablecoursepublishing) && has_capability('moodle/course:publish', $context);
         $options->reset = has_capability('moodle/course:reset', $context);
         $options->roles = has_capability('moodle/role:switchroles', $context);
     } else {
diff --git a/course/publish/backup.php b/course/publish/backup.php
deleted file mode 100644 (file)
index f9f9d7a..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// This file is part of Moodle - http://moodle.org/                      //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//                                                                       //
-// 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/>.       //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-/**
- * This page display the publication backup form
- *
- * @package    course
- * @subpackage publish
- * @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
- */
-
-define('NO_OUTPUT_BUFFERING', true);
-
-require_once('../../config.php');
-require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
-require_once($CFG->dirroot . '/backup/moodle2/backup_plan_builder.class.php');
-require_once($CFG->libdir . '/filelib.php');
-
-
-//retrieve initial page parameters
-$id = required_param('id', PARAM_INT);
-$hubcourseid = required_param('hubcourseid', PARAM_INT);
-
-//some permissions and parameters checking
-$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
-require_login($course);
-
-$context = context_course::instance($course->id);
-if (empty($CFG->enablecoursepublishing) || !has_capability('moodle/course:publish', $context) || !confirm_sesskey()) {
-    throw new moodle_exception('nopermission');
-}
-
-//page settings
-$PAGE->set_url('/course/publish/backup.php');
-$PAGE->set_pagelayout('incourse');
-$PAGE->set_title(get_string('course') . ': ' . $course->fullname);
-$PAGE->set_heading($course->fullname);
-
-//BEGIN backup processing
-$backupid = optional_param('backup', false, PARAM_ALPHANUM);
-if (!($bc = backup_ui::load_controller($backupid))) {
-    $bc = new backup_controller(backup::TYPE_1COURSE, $id, backup::FORMAT_MOODLE,
-                    backup::INTERACTIVE_YES, backup::MODE_HUB, $USER->id);
-}
-$backup = new backup_ui($bc,
-        array('id' => $id, 'hubcourseid' => $hubcourseid, 'huburl' => HUB_MOODLEORGHUBURL, 'hubname' => 'Moodle.net'));
-$backup->process();
-if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
-    $backup->execute();
-} else {
-    $backup->save_controller();
-}
-
-if ($backup->get_stage() !== backup_ui::STAGE_COMPLETE) {
-    $renderer = $PAGE->get_renderer('core', 'backup');
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('publishcourseon', 'hub', 'Moodle.net'), 3, 'main');
-    if ($backup->enforce_changed_dependencies()) {
-        debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER);
-    }
-    echo $renderer->progress_bar($backup->get_progress_bar());
-    echo $backup->display($renderer);
-    echo $OUTPUT->footer();
-    die();
-}
-
-//$backupfile = $backup->get_stage_results();
-$backupfile = $bc->get_results();
-$backupfile = $backupfile['backup_destination'];
-//END backup processing
-
-//display the sending file page
-echo $OUTPUT->header();
-echo $OUTPUT->heading(get_string('sendingcourse', 'hub'), 3, 'main');
-$renderer = $PAGE->get_renderer('core', 'course');
-echo $renderer->sendingbackupinfo($backupfile);
-if (ob_get_level()) {
-    ob_flush();
-}
-flush();
-
-//send backup file to the hub
-\core\hub\publication::upload_course_backup($hubcourseid, $backupfile);
-
-//delete the temp backup file from user_tohub aera
-$backupfile->delete();
-$bc->destroy();
-
-//Output sending success
-echo $renderer->sentbackupinfo($id, HUB_MOODLEORGHUBURL, 'Moodle.net');
-
-echo $OUTPUT->footer();
diff --git a/course/publish/forms.php b/course/publish/forms.php
deleted file mode 100644 (file)
index 288475e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// This file is part of Moodle - http://moodle.org/                      //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//                                                                       //
-// 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/>.       //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-/**
- * @package    course
- * @subpackage publish
- * @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
- *
- * The forms used for course publication
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-debugging('Support for alternative hubs has been removed from Moodle in 3.4. For communication with moodle.net ' .
-    'see lib/classes/hub/ .', DEBUG_DEVELOPER);
diff --git a/course/publish/hubselector.php b/course/publish/hubselector.php
deleted file mode 100644 (file)
index e731d4d..0000000
+++ /dev/null
@@ -1,30 +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/>.
-
-/*
- * @package    course
- * @subpackage publish
- * @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 user selects where he wants to publish the course
-*/
-
-require('../../config.php');
-
-$id = required_param('id', PARAM_INT);
-redirect(new moodle_url('/course/publish/index.php', ['id' => $id]));
\ No newline at end of file
diff --git a/course/publish/index.php b/course/publish/index.php
deleted file mode 100644 (file)
index 7bff473..0000000
+++ /dev/null
@@ -1,99 +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/>.
-
-/*
- * @package    course
- * @subpackage publish
- * @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
- *
- * The user selects if he wants to publish the course on Moodle.org hub or
- * on a specific hub. The site must be registered on a hub to be able to
- * publish a course on it.
-*/
-
-require('../../config.php');
-
-$courseid = required_param('id', PARAM_INT); // Course id.
-$publicationid = optional_param('publicationid', 0, PARAM_INT); // Id of course publication to unpublish.
-
-require_login($courseid);
-$shortname = format_string($COURSE->shortname);
-
-$PAGE->set_url('/course/publish/index.php', array('id' => $courseid));
-$PAGE->set_pagelayout('incourse');
-$PAGE->set_title(get_string('publish', 'core_hub') . ': ' . $COURSE->fullname);
-$PAGE->set_heading($COURSE->fullname);
-
-$context = context_course::instance($courseid);
-if (empty($CFG->enablecoursepublishing) || !has_capability('moodle/course:publish', $context)) {
-    throw new moodle_exception('nopermission');
-}
-
-// If the site is not registered display an error page.
-if (!\core\hub\registration::is_registered()) {
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(get_string('publishcourseon', 'hub', 'Moodle.net'), 3, 'main');
-    echo $OUTPUT->box(get_string('notregisteredonhub', 'hub'));
-    if (has_capability('moodle/site:config', context_system::instance())) {
-        echo $OUTPUT->single_button(new moodle_url('/admin/registration/index.php'), get_string('register', 'admin'));
-    }
-    echo $OUTPUT->footer();
-    die();
-}
-
-// When hub listing status is requested update statuses of all published courses.
-$updatestatusid = optional_param('updatestatusid', false, PARAM_INT);
-if (!empty($updatestatusid) && confirm_sesskey()) {
-    if (core\hub\publication::get_publication($updatestatusid, $courseid)) {
-        core\hub\publication::request_status_update();
-        redirect($PAGE->url);
-    }
-}
-
-$renderer = $PAGE->get_renderer('core', 'course');
-
-// Unpublish course.
-if ($publication = \core\hub\publication::get_publication($publicationid, $courseid)) {
-    $confirm = optional_param('confirm', 0, PARAM_BOOL);
-    if ($confirm && confirm_sesskey()) {
-        \core\hub\publication::unpublish($publication);
-    } else {
-        // Display confirmation page for unpublishing.
-        $publication = \core\hub\publication::get_publication($publicationid, $courseid, MUST_EXIST);
-        $publication->courseshortname = format_string($COURSE->shortname);
-        echo $OUTPUT->header();
-        echo $OUTPUT->heading(get_string('unpublishcourse', 'hub', $shortname), 3, 'main');
-        echo $renderer->confirmunpublishing($publication);
-        echo $OUTPUT->footer();
-        die();
-    }
-}
-
-// List current publications and "Publish" buttons.
-echo $OUTPUT->header();
-
-echo $OUTPUT->heading(get_string('publishcourse', 'hub', $shortname), 3, 'main');
-echo $renderer->publicationselector($courseid);
-
-$publications = \core\hub\publication::get_course_publications($courseid);
-if (!empty($publications)) {
-    echo $OUTPUT->heading(get_string('publishedon', 'hub'), 3, 'main');
-    echo $renderer->registeredonhublisting($courseid, $publications);
-}
-
-echo $OUTPUT->footer();
diff --git a/course/publish/lib.php b/course/publish/lib.php
deleted file mode 100644 (file)
index 72330f6..0000000
+++ /dev/null
@@ -1,17 +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/>.
-
-defined('MOODLE_INTERNAL') || die();
diff --git a/course/publish/metadata.php b/course/publish/metadata.php
deleted file mode 100644 (file)
index 3042864..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// This file is part of Moodle - http://moodle.org/                      //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//                                                                       //
-// 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/>.       //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-/*
- * @package    course
- * @subpackage publish
- * @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
- *
- * This page display the publication metadata form
- */
-
-require_once('../../config.php');
-require_once($CFG->libdir . '/filelib.php');
-
-
-//check user access capability to this page
-$id = required_param('id', PARAM_INT);
-
-$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
-require_login($course);
-
-//page settings
-$PAGE->set_url('/course/publish/metadata.php', array('id' => $course->id));
-$PAGE->set_pagelayout('incourse');
-$PAGE->set_title(get_string('course') . ': ' . $course->fullname);
-$PAGE->set_heading($course->fullname);
-
-$context = context_course::instance($course->id);
-if (empty($CFG->enablecoursepublishing) || !has_capability('moodle/course:publish', $context)) {
-    throw new moodle_exception('nopermission');
-}
-
-// Retrieve hub name and hub url.
-require_sesskey();
-
-// Set the publication form.
-$advertise = optional_param('advertise', false, PARAM_BOOL);
-$publicationid = optional_param('publicationid', false, PARAM_INT);
-$formparams = array('course' => $course, 'advertise' => $advertise);
-if ($publicationid) {
-    $publication = \core\hub\publication::get_publication($publicationid, $course->id, MUST_EXIST);
-    $formparams['publication'] = $publication;
-    $advertise = $formparams['advertise'] = $publication->enrollable;
-}
-$share = !$advertise;
-$coursepublicationform = new \core\hub\course_publication_form('', $formparams);
-$fromform = $coursepublicationform->get_data();
-
-if (!empty($fromform)) {
-
-    // Retrieve the course information.
-    $courseinfo = new stdClass();
-    $courseinfo->fullname = $fromform->name;
-    $courseinfo->shortname = $fromform->courseshortname;
-    $courseinfo->description = $fromform->description;
-    $courseinfo->language = $fromform->language;
-    $courseinfo->publishername = $fromform->publishername;
-    $courseinfo->publisheremail = $fromform->publisheremail;
-    $courseinfo->contributornames = $fromform->contributornames;
-    $courseinfo->coverage = $fromform->coverage;
-    $courseinfo->creatorname = $fromform->creatorname;
-    $courseinfo->licenceshortname = $fromform->licence;
-    $courseinfo->subject = $fromform->subject;
-    $courseinfo->audience = $fromform->audience;
-    $courseinfo->educationallevel = $fromform->educationallevel;
-    $creatornotes = $fromform->creatornotes;
-    $courseinfo->creatornotes = $creatornotes['text'];
-    $courseinfo->creatornotesformat = $creatornotes['format'];
-    $courseinfo->sitecourseid = $id;
-    if (!empty($fromform->deletescreenshots)) {
-        $courseinfo->deletescreenshots = $fromform->deletescreenshots;
-    }
-    if ($share) {
-        $courseinfo->demourl = $fromform->demourl;
-        $courseinfo->enrollable = false;
-    } else {
-        $courseinfo->courseurl = $fromform->courseurl;
-        $courseinfo->enrollable = true;
-    }
-
-    // Retrieve the outcomes of this course.
-    require_once($CFG->libdir . '/grade/grade_outcome.php');
-    $outcomes = grade_outcome::fetch_all_available($id);
-    if (!empty($outcomes)) {
-        foreach ($outcomes as $outcome) {
-            $sentoutcome = new stdClass();
-            $sentoutcome->fullname = $outcome->fullname;
-            $courseinfo->outcomes[] = $sentoutcome;
-        }
-    }
-
-    // Retrieve the content information from the course.
-    $coursecontext = context_course::instance($course->id);
-    $courseblocks = \core\hub\publication::get_block_instances_by_context($coursecontext->id);
-
-    if (!empty($courseblocks)) {
-        $blockname = '';
-        foreach ($courseblocks as $courseblock) {
-            if ($courseblock->blockname != $blockname) {
-                if (!empty($blockname)) {
-                    $courseinfo->contents[] = $content;
-                }
-
-                $blockname = $courseblock->blockname;
-                $content = new stdClass();
-                $content->moduletype = 'block';
-                $content->modulename = $courseblock->blockname;
-                $content->contentcount = 1;
-            } else {
-                $content->contentcount = $content->contentcount + 1;
-            }
-        }
-        $courseinfo->contents[] = $content;
-    }
-
-    $activities = get_fast_modinfo($course, $USER->id);
-    foreach ($activities->instances as $activityname => $activitydetails) {
-        $content = new stdClass();
-        $content->moduletype = 'activity';
-        $content->modulename = $activityname;
-        $content->contentcount = count($activities->instances[$activityname]);
-        $courseinfo->contents[] = $content;
-    }
-
-    // Save into screenshots field the references to the screenshot content hash
-    // (it will be like a unique id from the hub perspective).
-    if (!empty($fromform->deletescreenshots) or $share) {
-        $courseinfo->screenshots = 0;
-    } else {
-        $courseinfo->screenshots = $fromform->existingscreenshotnumber;
-    }
-    $files = [];
-    if (!empty($fromform->screenshots)) {
-        $fs = get_file_storage();
-        $files = $fs->get_area_files(context_user::instance($USER->id)->id, 'user', 'draft', $fromform->screenshots,
-            'filepath, filename', false);
-        $files = array_filter($files, function(stored_file $file) {
-            return $file->is_valid_image();
-        });
-        $courseinfo->screenshots += count($files);
-    }
-
-    // PUBLISH ACTION.
-    $hubcourseid = \core\hub\publication::publish_course($courseinfo, $files);
-
-    // Redirect to the backup process page.
-    if ($share) {
-        $params = array('sesskey' => sesskey(), 'id' => $id, 'hubcourseid' => $hubcourseid);
-        $backupprocessurl = new moodle_url("/course/publish/backup.php", $params);
-        redirect($backupprocessurl);
-    } else {
-        // Redirect to the index publis page.
-        redirect(new moodle_url('/course/publish/index.php', ['id' => $id]),
-            get_string('coursepublished', 'hub', 'Moodle.net'), null, \core\output\notification::NOTIFY_SUCCESS);
-    }
-}
-
-// OUTPUT SECTION.
-
-echo $OUTPUT->header();
-echo $OUTPUT->heading(get_string('publishcourseon', 'hub', 'Moodle.net'), 3, 'main');
-
-// Display hub information (logo, name, description).
-$renderer = $PAGE->get_renderer('core', 'course');
-if ($hubinfo = \core\hub\registration::get_moodlenet_info()) {
-    echo $renderer->hubinfo($hubinfo);
-}
-
-// Display metadata form.
-$coursepublicationform->display();
-echo $OUTPUT->footer();
index ba33b06..51b5254 100644 (file)
@@ -2106,128 +2106,6 @@ class core_course_renderer extends plugin_renderer_base {
         return $this->output->render_from_template('core_course/activity_navigation', $data);
     }
 
-    /**
-     * Display the selector to advertise or publish a course
-     * @param int $courseid
-     */
-    public function publicationselector($courseid) {
-        $text = '';
-
-        $advertiseurl = new moodle_url("/course/publish/metadata.php",
-            array('sesskey' => sesskey(), 'id' => $courseid, 'advertise' => true));
-        $advertisebutton = new single_button($advertiseurl, get_string('advertise', 'hub'));
-        $text .= $this->output->render($advertisebutton);
-        $text .= html_writer::tag('div', get_string('advertisepublication_help', 'hub'),
-            array('class' => 'publishhelp'));
-
-        $text .= html_writer::empty_tag('br');  // TODO Delete.
-
-        $uploadurl = new moodle_url("/course/publish/metadata.php",
-            array('sesskey' => sesskey(), 'id' => $courseid, 'share' => true));
-        $uploadbutton = new single_button($uploadurl, get_string('share', 'hub'));
-        $text .= $this->output->render($uploadbutton);
-        $text .= html_writer::tag('div', get_string('sharepublication_help', 'hub'),
-            array('class' => 'publishhelp'));
-
-        return $text;
-    }
-
-    /**
-     * Display the listing of hub where a course is registered on
-     * @param int $courseid
-     * @param array $publications
-     */
-    public function registeredonhublisting($courseid, $publications) {
-        global $CFG;
-        $table = new html_table();
-        $table->head = array(get_string('type', 'hub'),
-            get_string('date'), get_string('status', 'hub'), get_string('operation', 'hub'));
-        $table->size = array('20%', '30%', '%20', '%25');
-
-        $brtag = html_writer::empty_tag('br');
-
-        foreach ($publications as $publication) {
-
-            $params = array('id' => $publication->courseid, 'publicationid' => $publication->id);
-            $cancelurl = new moodle_url("/course/publish/index.php", $params);
-            $cancelbutton = new single_button($cancelurl, get_string('removefromhub', 'hub'));
-            $cancelbutton->class = 'centeredbutton';
-            $cancelbuttonhtml = $this->output->render($cancelbutton);
-
-            if ($publication->enrollable) {
-                $params = array('sesskey' => sesskey(), 'id' => $publication->courseid, 'publicationid' => $publication->id);
-                $updateurl = new moodle_url("/course/publish/metadata.php", $params);
-                $updatebutton = new single_button($updateurl, get_string('update', 'hub'));
-                $updatebutton->class = 'centeredbutton';
-                $updatebuttonhtml = $this->output->render($updatebutton);
-
-                $operations = $updatebuttonhtml . $brtag . $cancelbuttonhtml;
-            } else {
-                $operations = $cancelbuttonhtml;
-            }
-
-            // If the publication check time if bigger than May 2010, it has been checked.
-            if ($publication->timechecked > 1273127954) {
-                if ($publication->status == 0) {
-                    $status = get_string('statusunpublished', 'hub');
-                } else {
-                    $status = get_string('statuspublished', 'hub');
-                    if (!empty($publication->link)) {
-                        $status = html_writer::link($publication->link, $status);
-                    }
-                }
-
-                $status .= $brtag . html_writer::tag('a', get_string('updatestatus', 'hub'),
-                        array('href' => $CFG->wwwroot . '/course/publish/index.php?id='
-                            . $courseid . "&updatestatusid=" . $publication->id
-                            . "&sesskey=" . sesskey())) .
-                    $brtag . get_string('lasttimechecked', 'hub') . ": "
-                    . format_time(time() - $publication->timechecked);
-            } else {
-                $status = get_string('neverchecked', 'hub') . $brtag
-                    . html_writer::tag('a', get_string('updatestatus', 'hub'),
-                        array('href' => $CFG->wwwroot . '/course/publish/index.php?id='
-                            . $courseid . "&updatestatusid=" . $publication->id
-                            . "&sesskey=" . sesskey()));
-            }
-            // Add button cells.
-            $cells = array($publication->enrollable ?
-                get_string('advertised', 'hub') : get_string('shared', 'hub'),
-                userdate($publication->timepublished,
-                    get_string('strftimedatetimeshort')), $status, $operations);
-            $row = new html_table_row($cells);
-            $table->data[] = $row;
-        }
-
-        $contenthtml = html_writer::table($table);
-
-        return $contenthtml;
-    }
-
-    /**
-     * Display unpublishing confirmation page
-     * @param stdClass $publication
-     *      $publication->courseshortname
-     *      $publication->courseid
-     *      $publication->hubname
-     *      $publication->huburl
-     *      $publication->id
-     */
-    public function confirmunpublishing($publication) {
-        $optionsyes = array('sesskey' => sesskey(), 'id' => $publication->courseid,
-            'hubcourseid' => $publication->hubcourseid,
-            'cancel' => true, 'publicationid' => $publication->id, 'confirm' => true);
-        $optionsno = array('sesskey' => sesskey(), 'id' => $publication->courseid);
-        $publication->hubname = html_writer::tag('a', 'Moodle.net',
-            array('href' => HUB_MOODLEORGHUBURL));
-        $formcontinue = new single_button(new moodle_url("/course/publish/index.php",
-            $optionsyes), get_string('unpublish', 'hub'), 'post');
-        $formcancel = new single_button(new moodle_url("/course/publish/index.php",
-            $optionsno), get_string('cancel'), 'get');
-        return $this->output->confirm(get_string('unpublishconfirmation', 'hub', $publication),
-            $formcontinue, $formcancel);
-    }
-
     /**
      * Display waiting information about backup size during uploading backup process
      * @param object $backupfile the backup stored_file
@@ -2241,23 +2119,6 @@ class core_course_renderer extends plugin_renderer_base {
         return $html;
     }
 
-    /**
-     * Display upload successfull message and a button to the publish index page
-     * @param int $id the course id
-     * @return $html string
-     */
-    public function sentbackupinfo($id) {
-        $html = html_writer::tag('div', get_string('sent', 'hub'),
-            array('class' => 'courseuploadtextinfo'));
-        $publishindexurl = new moodle_url('/course/publish/index.php',
-            array('sesskey' => sesskey(), 'id' => $id,
-                'published' => true));
-        $continue = $this->output->render(
-            new single_button($publishindexurl, get_string('continue')));
-        $html .= html_writer::tag('div', $continue, array('class' => 'sharecoursecontinue'));
-        return $html;
-    }
-
     /**
      * Hub information (logo - name - description - link)
      * @param object $hubinfo
index 2596eb2..8571b97 100644 (file)
@@ -68,3 +68,48 @@ Feature: Managers can create courses
       | id_enddate_day | 24 |
       | id_enddate_month | October |
       | id_enddate_year | 2016 |
+
+  Scenario: Create a course as a custom course creator
+    Given the following "users" exist:
+      | username  | firstname | lastname | email          |
+      | kevin  | Kevin   | the        | kevin@example.com |
+    And the following "roles" exist:
+      | shortname | name    | archetype |
+      | creator   | Creator |           |
+    And the following "system role assigns" exist:
+      | user   | role    | contextlevel |
+      | kevin  | creator | System       |
+    And I log in as "admin"
+    And I set the following system permissions of "Creator" role:
+      | capability | permission |
+      | moodle/course:create | Allow |
+      | moodle/course:manageactivities | Allow |
+      | moodle/course:viewparticipants | Allow |
+      | moodle/role:assign | Allow |
+    And I log out
+    And I log in as "kevin"
+    And I am on site homepage
+    When I press "Add a new course"
+    And I set the following fields to these values:
+      | Course full name  | My first course |
+      | Course short name | myfirstcourse |
+    And I press "Save and display"
+    And I follow "Participants"
+    Then I should see "Kevin the"
+    And I should not see "Teacher"
+    And I log out
+    Given I log in as "admin"
+    And I define the allowed role assignments for the "Creator" role as:
+      | Teacher | Assignable |
+    And I log out
+    And I log in as "kevin"
+    And I am on site homepage
+    And I turn editing mode on
+    When I press "Add a new course"
+    And I set the following fields to these values:
+      | Course full name  | My second course |
+      | Course short name | mysecondcourse |
+    And I press "Save and display"
+    And I follow "Participants"
+    Then I should see "Kevin the"
+    And I should see "Teacher"
index 7f5482f..1b0a8ac 100644 (file)
@@ -3307,7 +3307,6 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertFalse($adminoptions->outcomes);
         $this->assertTrue($adminoptions->badges);
         $this->assertTrue($adminoptions->import);
-        $this->assertFalse($adminoptions->publish);
         $this->assertTrue($adminoptions->reset);
         $this->assertTrue($adminoptions->roles);
     }
@@ -3339,7 +3338,6 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertFalse($adminoptions->outcomes);
         $this->assertTrue($adminoptions->badges);
         $this->assertFalse($adminoptions->import);
-        $this->assertFalse($adminoptions->publish);
         $this->assertFalse($adminoptions->reset);
         $this->assertFalse($adminoptions->roles);
 
index 803ed5e..ab857e9 100644 (file)
@@ -2296,12 +2296,11 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
                 $this->assertFalse($adminoptions->outcomes);
                 $this->assertFalse($adminoptions->badges);
                 $this->assertFalse($adminoptions->import);
-                $this->assertFalse($adminoptions->publish);
                 $this->assertFalse($adminoptions->reset);
                 $this->assertFalse($adminoptions->roles);
                 $this->assertFalse($adminoptions->editcompletion);
             } else {
-                $this->assertCount(15, $course['options']);
+                $this->assertCount(14, $course['options']);
                 $this->assertFalse($adminoptions->update);
                 $this->assertFalse($adminoptions->filters);
                 $this->assertFalse($adminoptions->reports);
@@ -2313,7 +2312,6 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
                 $this->assertFalse($adminoptions->outcomes);
                 $this->assertTrue($adminoptions->badges);
                 $this->assertFalse($adminoptions->import);
-                $this->assertFalse($adminoptions->publish);
                 $this->assertFalse($adminoptions->reset);
                 $this->assertFalse($adminoptions->roles);
                 $this->assertFalse($adminoptions->editcompletion);
index fa8f10f..39e30aa 100644 (file)
@@ -104,6 +104,8 @@ $string['bookmarkdeleted'] = 'Bookmark deleted.';
 $string['bookmarkthispage'] = 'Bookmark this page';
 $string['cachejs'] = 'Cache Javascript';
 $string['cachejs_help'] = 'Javascript caching and compression greatly improves page loading performance. it is strongly recommended for production sites. Developers will probably want to disable this feature.';
+$string['cachetemplates'] = 'Cache Templates';
+$string['cachetemplates_help'] = 'Template caching will improve page loading performance and is strongly recommended for production sites. Developers will probably want to disable this feature.';
 $string['calendarexportsalt'] = 'Calendar export salt';
 $string['calendarsettings'] = 'Calendar';
 $string['calendartype'] = 'Calendar type';
@@ -200,7 +202,7 @@ $string['configdebug'] = 'If you turn this on, then PHP\'s error_reporting will
 $string['configdebugdisplay'] = 'Set to on, the error reporting will go to the HTML page. This is practical, but breaks XHTML, JS, cookies and HTTP headers in general. Set to off, it will send the output to your server logs, allowing better debugging. The PHP setting error_log controls which log this goes to.';
 $string['configdebugpageinfo'] = 'Enable if you want page information printed in page footer.';
 $string['configdebugvalidators'] = 'Enable if you want to have links to external validator servers in page footer. You may need to create new user with username <em>w3cvalidator</em>, and enable guest access. These changes may allow unauthorized access to server, do not enable on production sites!';
-$string['configdefaulthomepage'] = 'This determines the home page for logged in users';
+$string['configdefaulthomepage'] = 'This determines the first link in the navigation for logged-in users.';
 $string['configdefaultrequestcategory'] = 'Courses requested by users will be automatically placed in this category.';
 $string['configdefaultrequestedcategory'] = 'Default category to put courses that were requested into, if they\'re approved.';
 $string['configdefaultuserroleid'] = 'All logged in users will be given the capabilities of the role you specify here, at the site level, in ADDITION to any other roles they may have been given.  The default is the Authenticated user role.  Note that this will not conflict with other roles they have unless you prohibit capabilities, it just ensures that all users have capabilities that are not assignable at the course level (eg post blog entries, manage own calendar, etc).';
@@ -455,7 +457,7 @@ $string['debugvalidators'] = 'Show validator links';
 $string['defaultcity'] = 'Default city';
 $string['defaultcity_help'] = 'A city entered here will be the default city when creating new user accounts.';
 $string['defaultformatnotset'] = 'Error determining default course format. Please check site settings.';
-$string['defaulthomepage'] = 'Default home page for users';
+$string['defaulthomepage'] = 'Home page for users';
 $string['defaultrequestcategory'] = 'Default category for course requests';
 $string['defaultsettinginfo'] = 'Default: {$a}';
 $string['defaultuserroleid'] = 'Default role for all users';
@@ -563,8 +565,8 @@ $string['experimentalsettings'] = 'Experimental settings';
 $string['extendedusernamechars'] = 'Allow extended characters in usernames';
 $string['extramemorylimit'] = 'Extra PHP memory limit';
 $string['fatalsessionautostart'] = '<p>Serious configuration error detected, please notify server administrator.</p><p> To operate properly, Moodle requires that administrator changes PHP settings.</p><p><code>session.auto_start</code> must be set to <code>off</code>.</p><p>This setting is controlled by editing <code>php.ini</code>, Apache/IIS <br />configuration or <code>.htaccess</code> file on the server.</p>';
-$string['filescleanupperiod'] = 'Clean trash pool files';
-$string['filescleanupperiod_help'] = 'How often trash files are removed. These are files that are associated with a context that no longer exists';
+$string['filescleanupperiod'] = 'Clean up trash pool files';
+$string['filescleanupperiod_help'] = 'How often trash pool files are deleted. These are files that are associated with a context that no longer exists, for example when a course is deleted. Please note: This setting can result in missing files in a course which is backed up, deleted and then restored if the setting \'Include files\' (backup_auto_files) in \'Automated backup settings\' is disabled.';
 $string['fileconversioncleanuptask'] = 'Cleanup of temporary records for file conversions.';
 $string['filecreated'] = 'New file created';
 $string['filesizeunits'] = 'file size units';
@@ -1008,7 +1010,7 @@ $string['quizattemptsupgradedmessage'] = 'In Moodle 2.1 there was a major upgrad
 $string['recaptchaprivatekey'] = 'ReCAPTCHA secret key';
 $string['recaptchapublickey'] = 'ReCAPTCHA site key';
 $string['register'] = 'Register your site';
-$string['registermoodlenet'] = '<p>We\'d love to stay in touch and provide you with important things for your Moodle site!</p><p>By registering:</p><ul><li>You\'ll be one of the first to find out about important notifications such as security alerts and new Moodle releases.</li><li>You can access and activate mobile push notifications from your Moodle site through our free <a href="https://download.moodle.org/mobile/">Moodle app</a>.</li><li>You are contributing to our <a href="https://moodle.net/stats/">Moodle statistics</a> of the worldwide community, which help us improve Moodle and our community sites.</li><li>If you wish, your site can be included in the <a href="https://moodle.net/sites/">list of registered Moodle sites</a> in your country.</li></ul>';
+$string['registermoodlenet'] = '<p>We\'d love to stay in touch and provide you with important things for your Moodle site!</p><p>By registering:</p><ul><li>You can subscribe to receive notifications of new Moodle releases, security alerts and other important news.</li><li>You can access and activate mobile push notifications from your Moodle site through our free <a href="https://download.moodle.org/mobile/">Moodle app</a>.</li><li>You are contributing to our <a href="https://moodle.net/stats/">Moodle statistics</a> of the worldwide community, which help us improve Moodle and our community sites.</li><li>If you wish, your site can be included in the <a href="https://moodle.net/sites/">list of registered Moodle sites</a> in your country.</li></ul>';
 $string['registermoodleorg'] = 'When you register your site';
 $string['registermoodleorgli1'] = 'You are added to a low-volume mailing list for important notifications such as security alerts and new releases of Moodle.';
 $string['registermoodleorgli2'] = 'Statistics about your site will be added to the {$a} of the worldwide Moodle community.';
@@ -1041,6 +1043,7 @@ $string['purgemuc'] = 'All MUC caches';
 $string['purgeothercaches'] = 'All file and miscellaneous caches';
 $string['purgeselectedcaches'] = 'Purge selected caches';
 $string['purgeselectedcachesfinished'] = 'The selected caches were purged.';
+$string['purgetemplates'] = 'Templates';
 $string['purgethemecache'] = 'Themes';
 $string['requestcategoryselection'] = 'Enable category selection';
 $string['restorecourse'] = 'Restore course';
@@ -1264,6 +1267,7 @@ $string['taskstatscron'] = 'Background processing for statistics';
 $string['tasktagcron'] = 'Background processing for tags';
 $string['tasktempfilecleanup'] = 'Delete stale temp files';
 $string['tempdatafoldercleanup'] = 'Clean up temporary data files older than';
+$string['templates'] = 'Templates';
 $string['testoutgoingmailconf'] = 'Test outgoing mail configuration';
 $string['testoutgoingmaildetail'] = 'Note: Before testing, please save your configuration.<br />{$a}';
 $string['testoutgoingmailconf_message'] = 'This is a test message to confirm that you have successfully configured your site\'s outgoing mail.';
@@ -1302,6 +1306,7 @@ $string['unbookmarkthispage'] = 'Unbookmark this page';
 $string['unicoderequired'] = 'It is required that you store all your data in Unicode format (UTF-8). New installations must be performed into databases that have their default character set as Unicode.  If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
 $string['uninstallplugin'] = 'Uninstall';
 $string['unlockaccount'] = 'Unlock account';
+$string['unoconvwarning'] = 'The version of unoconv you have installed is not supported.';
 $string['unsettheme'] = 'Unset theme';
 $string['unsupported'] = 'Unsupported';
 $string['unsupporteddbfileformat'] = 'Your database uses Antelope as the file format. Full UTF-8 support in MySQL and MariaDB requires the Barracuda file format. Please switch to the Barracuda file format. See the documentation <a href="https://docs.moodle.org/en/admin/environment/custom check/mysql full unicode support">MySQL full unicode support</a> for details.';
@@ -1391,8 +1396,8 @@ $string['usermanagement'] = 'User management';
 $string['userpreference'] = 'User preference';
 $string['userpolicies'] = 'User policies';
 $string['users'] = 'Users';
-$string['userquota'] = 'User quota';
-$string['userquota_desc'] = 'The maximum number of bytes that a user can store in their own private file area.';
+$string['userquota'] = 'Private files space';
+$string['userquota_desc'] = 'The maximum amount of data that each user can store in their private files area.';
 $string['usesitenameforsitepages'] = 'Use site name for site pages';
 $string['usetags'] = 'Enable tags functionality';
 $string['validateemptylineerror'] = 'Empty lines are not valid';
index cbeceea..ff7e173 100644 (file)
@@ -97,8 +97,8 @@ $string['noevaluationbasedassumptions'] = 'Models based on assumptions cannot be
 $string['nodata'] = 'No data to analyse';
 $string['noinsightsmodel'] = 'This model does not generate insights';
 $string['noinsights'] = 'No insights reported';
-$string['nonewdata'] = 'No new data available. It will be analysed after the next analysis interval.';
-$string['nonewranges'] = 'No new predictions yet. It will be analysed after the next analysis interval.';
+$string['nonewdata'] = 'No new data available. The model will be analysed after the next analysis interval.';
+$string['nonewranges'] = 'No new predictions yet. The model will be analysed after the next analysis interval.';
 $string['nopredictionsyet'] = 'No predictions available yet';
 $string['noranges'] = 'No predictions yet';
 $string['notrainingbasedassumptions'] = 'Models based on assumptions do not need training';
index 9cfe05e..0c08c50 100644 (file)
@@ -127,7 +127,7 @@ $string['configgeneralblocks'] = 'Sets the default for including blocks in a bac
 $string['configgeneralcalendarevents'] = 'Sets the default for including calendar events in a backup.';
 $string['configgeneralcomments'] = 'Sets the default for including comments in a backup.';
 $string['configgeneralcompetencies'] = 'Sets the default for including competencies in a backup.';
-$string['configgeneralfiles'] = 'Sets the default for including files in a backup.';
+$string['configgeneralfiles'] = 'Sets the default for including files in a backup. Please note: Disabling this setting will result in a backup which only includes references to files. This is not a problem if the backup is restored on the same site and the files have not been deleted according to the setting \'Clean up trash pool files\' (filescleanupperiod).';
 $string['configgeneralfilters'] = 'Sets the default for including filters in a backup.';
 $string['configgeneralhistories'] = 'Sets the default for including user history within a backup.';
 $string['configgenerallogs'] = 'If enabled logs will be included in backups by default.';
index 7b54068..6ff0088 100644 (file)
@@ -111,7 +111,7 @@ $string['backpackemail_help'] = 'The email address associated with your backpack
 $string['backpackemailverificationpending'] = 'Verification pending';
 $string['backpackemailverifyemailbody'] = 'Hi,
 
-A new connection to your OpenBadges backpack has been requested from \'{$a->sitename}\' using your email address.
+A new connection to your badges backpack has been requested from \'{$a->sitename}\' using your email address.
 
 To confirm and activate the connection to your backpack, please go to
 
@@ -121,7 +121,7 @@ In most mail programs, this should appear as a blue link which you can just clic
 
 If you need help, please contact the site administrator,
 {$a->admin}';
-$string['backpackemailverifyemailsubject'] = '{$a}: OpenBadges Backpack email verification';
+$string['backpackemailverifyemailsubject'] = '{$a}: Badges backpack email verification';
 $string['backpackemailverifypending'] = 'A verification email has been sent to <strong>{$a}</strong>. Click on the verification link in the email to activate your Backpack connection.';
 $string['backpackemailverifysuccess'] = 'Thanks for verifying your email address. You are now connected to your backpack.';
 $string['backpackemailverifytokenmismatch'] = 'The token in the link you clicked does not match the stored token. Make sure you clicked the link in most recent email you received.';
index c0cf86b..cae7b1e 100644 (file)
@@ -148,7 +148,7 @@ $string['err_noactivities'] = 'Completion information is not enabled for any act
 $string['err_nocourses'] = 'Course completion is not enabled for any other courses, so none can be displayed. You can enable course completion in the course settings.';
 $string['err_nograde'] = 'A course pass grade has not been set for this course. To enable this criteria type you must create a pass grade for this course.';
 $string['err_noroles'] = 'There are no roles with the capability moodle/course:markcomplete in this course.';
-$string['err_nousers'] = 'There are no students on this course or group for whom completion information is displayed. (By default, completion information is displayed only for students, so if there are no students, you will see this error. Administrators can alter this option via the admin screens.)';
+$string['err_nousers'] = 'There are no students in this course or group for whom completion information is displayed. (Completion information is displayed only for users with the capability \'Be shown on completion reports\'. The capability is allowed for the default role of student only, so if there are no students, you will see this message.)';
 $string['err_settingslocked'] = 'One or more students have already completed a criterion so the settings have been locked. Unlocking the completion criteria settings will delete any existing user data and may cause confusion.';
 $string['err_system'] = 'An internal error occurred in the completion system. (System administrators can enable debugging information to see more detail.)';
 $string['eventcoursecompleted'] = 'Course completed';
index 32d16f2..91d0a4f 100644 (file)
@@ -48,3 +48,61 @@ purgedefinitionsuccess,core_cache
 purgestoresuccess,core_cache
 eventrolecapabilitiesupdated,core_role
 configuserquota,core_admin
+addscreenshots,core_hub
+advertise,core_hub
+advertised,core_hub
+advertiseon,core_hub
+readvertiseon,core_hub
+advertisepublication_help,core_hub
+courseunpublished,core_hub
+courseurl,core_hub
+courseurl_help,core_hub
+creatorname,core_hub
+creatorname_help,core_hub
+creatornotes,core_hub
+creatornotes_help,core_hub
+contributornames,core_hub
+contributornames_help,core_hub
+deletescreenshots,core_hub
+deletescreenshots_help,core_hub
+description,core_hub
+description_help,core_hub
+detectednotexistingpublication,core_hub
+errorcoursepublish,core_hub
+errorcourseinfo,core_hub
+errorcoursewronglypublished,core_hub
+errorbadimageheightwidth,core_hub
+errorregistration,core_hub
+errorunpublishcourses,core_hub
+existingscreenshotnumber,core_hub
+existingscreenshots,core_hub
+nosearch,core_hub
+notregisteredonhub,core_hub
+publicationinfo,core_hub
+publish,core_hub
+publishcourse,core_hub
+publishcourseon,core_hub
+publishedon,core_hub
+publisheremail,core_hub
+publisheremail_help,core_hub
+publishername,core_hub
+publishername_help,core_hub
+removefromhub,core_hub
+screenshots,core_hub
+screenshots_help,core_hub
+sendingcourse,core_hub
+share,core_hub
+shared,core_hub
+shareon,core_hub
+sharepublication_help,core_hub
+status,core_hub
+statuspublished,core_hub
+statusunpublished,core_hub
+tags,core_hub
+tags_help,core_hub
+unpublish,core_hub
+unpublishalladvertisedcourses,core_hub
+unpublishalluploadedcourses,core_hub
+unpublishconfirmation,core_hub
+unpublishcourse,core_hub
+updatestatus,core_hub
index 00a4c1f..5ae9f6e 100644 (file)
@@ -263,6 +263,7 @@ $string['filternotactive'] = 'Filter {$a} is not currently active';
 $string['filternotenabled'] = 'Filter not enabled!';
 $string['filternotinstalled'] = 'Filter {$a} is not currently installed';
 $string['forumblockingtoomanyposts'] = 'You have exceeded the posting threshold set for this forum';
+$string['functionalityremoved'] = 'You are trying to access functionality that has been removed.';
 $string['generalexceptionmessage'] = 'Exception - {$a}';
 $string['gradepubdisable'] = 'Grade publishing disabled';
 $string['gradesneedregrading'] = 'The course grades need to be recalculated';
index bd87b8a..ebe023f 100644 (file)
  * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-
-$string['addscreenshots'] = 'Add screenshots';
-$string['advertise'] = 'Share this course for people to join';
-$string['advertised'] = 'For people to join';
-$string['advertiseon'] = 'Share this course on {$a}';
-$string['readvertiseon'] = 'Update advertising information on {$a}';
-$string['advertisepublication_help'] = 'This course will be listed on Moodle.net as a course that people can enrol in and participate. Email-based self-registration should be enabled on the site and you need to enable self enrolment in this course.';
 $string['analyticsactions'] = 'Number of actions taken on generated predictions ({$a})';
 $string['analyticsactionsnotuseful'] = 'Number of actions marking a prediction as not useful ({$a})';
 $string['analyticsenabledmodels'] = 'Number of enabled prediction models ({$a})';
@@ -42,27 +35,13 @@ $string['badgesnumber'] = 'Number of badges ({$a})';
 $string['communityremoved'] = 'That course link has been removed from your list';
 $string['completeregistration'] = 'Complete registration with Moodle.net';
 $string['confirmregistration'] = 'Confirm registration';
-$string['contributornames'] = 'Other contributors';
-$string['contributornames_help'] = 'You can use this field to list the names of anyone else who contributed to this course.';
 $string['coursename'] = 'Name';
 $string['coursepublished'] = 'This course has been shared successfully on \'{$a}\'.';
 $string['courseshortname'] = 'Shortname';
 $string['courseshortname_help'] = 'Enter a short name for your course. It does not need to be unique.';
 $string['coursesnumber'] = 'Number of courses ({$a})';
-$string['courseunpublished'] = 'The course {$a->courseshortname} is no longer shared on {$a->hubname}.';
-$string['courseurl'] = 'Course URL';
-$string['courseurl_help'] = 'It is the URL of your course. This URL is displayed as a link in a search result.';
-$string['creatorname'] = 'Creator';
-$string['creatorname_help'] = 'The creator is the course creator.';
-$string['creatornotes'] = 'Creator notes';
-$string['creatornotes_help'] = 'Creator notes are a guide for teachers on how to use the course.';
-$string['deletescreenshots'] = 'Delete these screenshots';
-$string['deletescreenshots_help'] = 'Delete all the currently uploaded screenshots.';
 $string['demourl'] = 'Demo URL';
 $string['demourl_help'] = 'Enter the demo URL of your course. By default it is the URL of your course. The demo URL is displayed as a link in a search result.';
-$string['description'] = 'Description';
-$string['description_help'] = 'This description text will be showing in the course listing on Moodle.net.';
-$string['detectednotexistingpublication'] = '{$a->hubname} is listing a course that does not exist any more. Alert {$a->hubname} administrator that the publication number {$a->id} should be removed.';
 $string['downloadable'] = 'Downloadable';
 $string['educationallevel'] = 'Educational level';
 $string['educationallevel_help'] = 'Select the most appropriate educational level that the course fits into.';
@@ -75,21 +54,11 @@ $string['edulevelsecondary'] = 'Secondary';
 $string['eduleveltertiary'] = 'Tertiary';
 $string['emailalert'] = 'Email notifications';
 $string['emailalert_help'] = 'If this is enabled the hub administrator will send you emails about security issues and other important news.';
-$string['enablecoursepublishing'] = "Course sharing on Moodle.net";
-$string['enablecoursepublishing_help'] = "Moodle.net is our community site for sharing courses and content with other Moodle users worldwide. A course may be shared for others to enrol in (requires email-based self-registration on the site and self enrolment in the course) or as a backup file for others to download.";
 $string['enrollable'] = 'Enrollable';
-$string['errorbadimageheightwidth'] = 'The image should have a maximum size of {$a->width} X {$a->height}';
-$string['errorcourseinfo'] = 'An error occurred when retrieving course metadata from {$a}. Please try again to retrieve the course metadata by reloading this page later. Otherwise you can decide to continue the registration process with the following default metadata. ';
-$string['errorcoursepublish'] = 'An error occurred during the course publication ({$a}). Please try again later.';
-$string['errorcoursewronglypublished'] = 'A publication error has been returned by Moodle.net. Please try again later.';
 $string['errorotherhubsnotsupported'] = 'This page can no longer be used for registration with sites other than Moodle.net';
-$string['errorregistration'] = 'An error occurred during registration, please try again later. ({$a})';
-$string['errorunpublishcourses'] = 'Due to an unexpected error, the courses could not be deleted from Moodle.net. Try again later (recommended) or contact Moodle.net administrator.';
 $string['errorws'] = '{$a}';
 $string['errorwstokenreset'] = '{$a}. Registration token on this site has been reset. You can now register your site again.';
-$string['existingscreenshotnumber'] = '{$a} existing screenshots. You will be able to see these screenshots on this page, only once the Moodle.net administrator enables your course.';
 $string['errorregistrationupdate'] = 'An error occurred during registration update ({$a})';
-$string['existingscreenshots'] = 'Existing screenshots';
 $string['geolocation'] = 'Geolocation';
 $string['geolocation_help'] = 'In future we may provide location-based searching. If you want to specify the location for your course use a latitude/longitude value here (eg: -31.947884,115.871285).  One way to find this is to use Google Maps.';
 $string['imageurl'] = 'Image URL';
@@ -114,8 +83,6 @@ $string['no'] = 'No';
 $string['nocheckstatusfromunreghub'] = 'The site is not registered on the hub so the status can not be checked.';
 $string['nohubselected'] = 'No hub selected';
 $string['none'] = 'None';
-$string['nosearch'] = 'Don\'t publish hub or courses';
-$string['notregisteredonhub'] = 'Your administrator needs to register this site with Moodle.net before you can share a course.';
 $string['operation'] = 'Actions';
 $string['participantnumberaverage'] = 'Average number of participants ({$a})';
 $string['policyagreed'] = 'Privacy notice and data processing agreement';
@@ -124,15 +91,6 @@ $string['postaladdress'] = 'Postal address';
 $string['postaladdress_help'] = 'Postal address of this site, or of the entity represented by this site.';
 $string['postsnumber'] = 'Number of posts ({$a})';
 $string['previousregistrationdeleted'] = 'The previous registration has been deleted from {$a}. You can restart the registration process. Thank you.';
-$string['publicationinfo'] = 'Course publication information';
-$string['publish'] = 'Share';
-$string['publishcourse'] = 'Share {$a}';
-$string['publishcourseon'] = 'Share on {$a}';
-$string['publishedon'] = 'Course sharing';
-$string['publisheremail'] = 'Publisher email';
-$string['publisheremail_help'] = 'The publisher email address allows the hub administrator to alert the publisher about any changes to the status of the published course.';
-$string['publishername'] = 'Publisher';
-$string['publishername_help'] = 'The publisher is the person or organisation that is the official publisher of the course.  Unless you are publishing it on behalf of someone else, it will usually be you.';
 $string['questionsnumber'] = 'Number of questions ({$a})';
 $string['registeredcourses'] = 'Registered courses';
 $string['registeredsites'] = 'Registered sites';
@@ -142,29 +100,21 @@ $string['registeredactiveuserdevices'] = 'Number of active users with registered
 $string['registersite'] = 'Register with {$a}';
 $string['registrationconfirmed'] = 'Site registration confirmed';
 $string['registrationconfirmedon'] = 'Thank you for registering your site. Registration information will be kept up to date by the \'Site registration\' scheduled task.';
-$string['removefromhub'] = 'Remove from Moodle.net';
 $string['renewregistration'] = 'Renew registration';
 $string['resourcesnumber'] = 'Number of resources ({$a})';
 $string['restartregistration'] = 'Restart registration';
 $string['roleassignmentsnumber'] = 'Number of role assignments ({$a})';
-$string['screenshots'] = 'Screenshots';
-$string['screenshots_help'] = 'Any screenshots of the course will be displayed in search results.';
 $string['search'] = 'Search';
-$string['sendingcourse'] = 'Sending course';
 $string['sendingsize'] = 'Please wait the course file is uploading ({$a->total}Mb)...';
 $string['sendfollowinginfo'] = 'More information';
 $string['sendfollowinginfo_help'] = 'The following information will be sent to contribute to overall statistics only.  It will not be made public on any site listing.';
 $string['sent'] = '...finished';
-$string['share'] = 'Share this course for people to download';
-$string['shared'] = 'For people to download';
-$string['shareon'] = 'Upload this course to {$a}';
-$string['sharepublication_help'] = 'A backup of this course will be available on Moodle.net for people to restore and use on their own site.';
 $string['siteadmin'] = 'Administrator';
 $string['siteadmin_help'] = 'The full name of the site administrator.';
-$string['sitecommnews'] = 'Updates about Moodle news and features';
-$string['sitecommnews_help'] = 'You have the option of subscribing to our low volume email list including a newsletter about happenings in the Moodle community. ';
-$string['sitecommnewsno'] = 'No, I do not want to receive any email from Moodle HQ';
-$string['sitecommnewsyes'] = 'Yes please, include me in Moodle’s regular e-newsletter updates';
+$string['sitecommnews'] = 'Moodle newsletter';
+$string['sitecommnews_help'] = 'You have the option of subscribing to our Moodle newsletter. You may unsubscribe at any time.';
+$string['sitecommnewsno'] = 'No, I do not wish to receive any emails';
+$string['sitecommnewsyes'] = 'Yes, I would like to receive the Moodle newsletter';
 $string['sitecountry'] = 'Country';
 $string['sitecountry_help'] = 'The country your organisation or institution is located in.';
 $string['sitedesc'] = 'Description';
@@ -186,8 +136,8 @@ $string['siteprivacypublished'] = 'Only display my site name';
 $string['siteprivacylinked'] = 'Display my site name with the link';
 $string['siteregistrationcontact'] = 'Display contact form';
 $string['siteregistrationcontact_help'] = 'If you allow it, other people in our Moodle community (who need a login account) can contact you via a form on our Moodle community site. However, they will never be able to see your email address.';
-$string['siteregistrationemail'] = 'Notifications about important security and technical issues.';
-$string['siteregistrationemail_help'] = 'You have the option of subscribing to our low volume email list for important news (on security issues or new releases).';
+$string['siteregistrationemail'] = 'Notifications of new Moodle releases, security alerts and other important news';
+$string['siteregistrationemail_help'] = 'You have the option of subscribing to our low-volume mailing list for notifications of new Moodle releases, security alerts and other important news. You may unsubscribe at any time.';
 $string['siteregistrationupdated'] = 'Site registration updated';
 $string['siterelease'] = 'Moodle release';
 $string['sitereleasenum'] = 'Moodle release ({$a})';
@@ -199,25 +149,74 @@ $string['siteversion_help'] = 'The Moodle version of this site.';
 $string['skipregistration'] = 'Skip';
 $string['subject'] = 'Subject';
 $string['subject_help'] = 'Select the main subject area which the course covers.';
-$string['status'] = 'Listing status';
-$string['statuspublished'] = 'Listed';
-$string['statusunpublished'] = 'Not listed';
-$string['tags'] = 'Tags';
-$string['tags_help'] = 'Tags help to further categorise your course and help it to be found. Please use simple, meaningful words and separate them with a comma. Example: math, algebra, geometry';
 $string['type'] = 'Shared';
-$string['unpublish'] = 'Stop sharing';
-$string['unpublishalladvertisedcourses'] = 'Remove all courses that were shared on Moodle.net for people to join';
-$string['unpublishalluploadedcourses'] = 'Remove all courses that were shared on Moodle.net for people to download';
-$string['unpublishconfirmation'] = 'Do you really want to remove the course "{$a->courseshortname}" from "{$a->hubname}"';
-$string['unpublishcourse'] = 'Stop sharing {$a}';
 $string['unregister'] = 'Unregister';
 $string['unregisterfrom'] = 'Unregister from {$a}';
 $string['unregistrationerror'] = 'An error occurred when the site tried to unregister from Moodle.net: {$a}';
 $string['update'] = 'Update';
 $string['updatesite'] = 'Update registration on {$a}';
-$string['updatestatus'] = 'Check it now.';
 $string['usedifferentemail'] = 'Use different email';
 $string['unregisterexplained'] = 'If the site with URL {$a} is registered on Moodle.net its registration will be removed.';
 $string['urlalreadyregistered'] = 'Your site seems to be already registered on Moodle.net, which means something has gone wrong. Please contact the Moodle.net administrator to reset your registration so you can try again.';
 $string['usersnumber'] = 'Number of users ({$a})';
 $string['wrongtoken'] = 'The registration failed for some unknown reason (network?). Please try again.';
+
+// Deprecated since Moodle 3.8.
+$string['addscreenshots'] = 'Add screenshots';
+$string['advertise'] = 'Share this course for people to join';
+$string['advertised'] = 'For people to join';
+$string['advertiseon'] = 'Share this course on {$a}';
+$string['readvertiseon'] = 'Update advertising information on {$a}';
+$string['advertisepublication_help'] = 'This course will be listed on Moodle.net as a course that people can enrol in and participate. Email-based self-registration should be enabled on the site and you need to enable self enrolment in this course.';
+$string['courseunpublished'] = 'The course {$a->courseshortname} is no longer shared on {$a->hubname}.';
+$string['courseurl'] = 'Course URL';
+$string['courseurl_help'] = 'It is the URL of your course. This URL is displayed as a link in a search result.';
+$string['creatorname'] = 'Creator';
+$string['creatorname_help'] = 'The creator is the course creator.';
+$string['creatornotes'] = 'Creator notes';
+$string['creatornotes_help'] = 'Creator notes are a guide for teachers on how to use the course.';
+$string['contributornames'] = 'Other contributors';
+$string['contributornames_help'] = 'You can use this field to list the names of anyone else who contributed to this course.';
+$string['deletescreenshots'] = 'Delete these screenshots';
+$string['deletescreenshots_help'] = 'Delete all the currently uploaded screenshots.';
+$string['description'] = 'Description';
+$string['description_help'] = 'This description text will be showing in the course listing on Moodle.net.';
+$string['detectednotexistingpublication'] = '{$a->hubname} is listing a course that does not exist any more. Alert {$a->hubname} administrator that the publication number {$a->id} should be removed.';
+$string['errorcoursepublish'] = 'An error occurred during the course publication ({$a}). Please try again later.';
+$string['errorcourseinfo'] = 'An error occurred when retrieving course metadata from {$a}. Please try again to retrieve the course metadata by reloading this page later. Otherwise you can decide to continue the registration process with the following default metadata. ';
+$string['errorcoursewronglypublished'] = 'A publication error has been returned by Moodle.net. Please try again later.';
+$string['errorbadimageheightwidth'] = 'The image should have a maximum size of {$a->width} X {$a->height}';
+$string['errorregistration'] = 'An error occurred during registration, please try again later. ({$a})';
+$string['errorunpublishcourses'] = 'Due to an unexpected error, the courses could not be deleted from Moodle.net. Try again later (recommended) or contact Moodle.net administrator.';
+$string['existingscreenshotnumber'] = '{$a} existing screenshots. You will be able to see these screenshots on this page, only once the Moodle.net administrator enables your course.';
+$string['existingscreenshots'] = 'Existing screenshots';
+$string['nosearch'] = 'Don\'t publish hub or courses';
+$string['notregisteredonhub'] = 'Your administrator needs to register this site with Moodle.net before you can share a course.';
+$string['publicationinfo'] = 'Course publication information';
+$string['publish'] = 'Share';
+$string['publishcourse'] = 'Share {$a}';
+$string['publishcourseon'] = 'Share on {$a}';
+$string['publishedon'] = 'Course sharing';
+$string['publisheremail'] = 'Publisher email';
+$string['publisheremail_help'] = 'The publisher email address allows the hub administrator to alert the publisher about any changes to the status of the published course.';
+$string['publishername'] = 'Publisher';
+$string['publishername_help'] = 'The publisher is the person or organisation that is the official publisher of the course.  Unless you are publishing it on behalf of someone else, it will usually be you.';
+$string['removefromhub'] = 'Remove from Moodle.net';
+$string['screenshots'] = 'Screenshots';
+$string['screenshots_help'] = 'Any screenshots of the course will be displayed in search results.';
+$string['sendingcourse'] = 'Sending course';
+$string['share'] = 'Share this course for people to download';
+$string['shared'] = 'For people to download';
+$string['shareon'] = 'Upload this course to {$a}';
+$string['sharepublication_help'] = 'A backup of this course will be available on Moodle.net for people to restore and use on their own site.';
+$string['status'] = 'Listing status';
+$string['statuspublished'] = 'Listed';
+$string['statusunpublished'] = 'Not listed';
+$string['tags'] = 'Tags';
+$string['tags_help'] = 'Tags help to further categorise your course and help it to be found. Please use simple, meaningful words and separate them with a comma. Example: math, algebra, geometry';
+$string['unpublish'] = 'Stop sharing';
+$string['unpublishalladvertisedcourses'] = 'Remove all courses that were shared on Moodle.net for people to join';
+$string['unpublishalluploadedcourses'] = 'Remove all courses that were shared on Moodle.net for people to download';
+$string['unpublishconfirmation'] = 'Do you really want to remove the course "{$a->courseshortname}" from "{$a->hubname}"';
+$string['unpublishcourse'] = 'Stop sharing {$a}';
+$string['updatestatus'] = 'Check it now.';
\ No newline at end of file
index 21389c4..6ff6bfc 100644 (file)
@@ -39,7 +39,7 @@ $string['blockuserconfirm'] = 'Are you sure you want to block {$a}?';
 $string['blockuserconfirmbutton'] = 'Block';
 $string['blocknoncontacts'] = 'Prevent non-contacts from messaging me';
 $string['cancelselection'] = 'Cancel message selection';
-$string['cantblockuser'] = 'You are unable to block {$a} because they have a role with permission to message all users';
+$string['cantblockuser'] = 'You can\'t block {$a} because they have a role with permission to message all users.';
 $string['contactableprivacy'] = 'Accept messages from:';
 $string['contactableprivacy_onlycontacts'] = 'My contacts only';
 $string['contactableprivacy_coursemember'] = 'My contacts and anyone in my courses';
index b0cef08..1152336 100644 (file)
@@ -381,12 +381,11 @@ $string['coursesettings'] = 'Course default settings';
 $string['coursesmovedout'] = 'Courses moved out from {$a}';
 $string['coursespending'] = 'Courses pending approval';
 $string['coursesearch'] = 'Search courses';
-$string['coursesearch_help'] = '<p>You can search for multiple words at once and can refine your search as follows:</p>
-<ul>
-<li>word - find any match of this word within the text.</li>
-<li>+word - only exact matching words will be found.</li>
-<li>-word - don\'t include results containing this word.</li>
-</ul>';
+$string['coursesearch_help'] = 'You can search for multiple words at once and can refine your search as follows:
+
+* word - find any match of this word within the text
+* +word - only exact matching words will be found
+* -word - don\'t include results containing this word.';
 $string['coursestart'] = 'Course start';
 $string['coursesummary'] = 'Course summary';
 $string['coursesummary_help'] = 'The course summary is displayed in the list of courses. A course search searches course summary text in addition to course names.';
@@ -467,8 +466,8 @@ $string['defaultcoursesummary'] = 'Write a concise and interesting paragraph her
 $string['defaultcourseteacher'] = 'Teacher';
 $string['defaultcourseteacherdescription'] = 'Teachers can do anything within a course, including changing the activities and grading students.';
 $string['defaultcourseteachers'] = 'Teachers';
-$string['defaulthomepageuser'] = 'Default home page';
-$string['defaulthomepageuser_help'] = 'This determines the home page for your account';
+$string['defaulthomepageuser'] = 'Home page';
+$string['defaulthomepageuser_help'] = 'Your home page is the first link in the navigation.';
 $string['delete'] = 'Delete';
 $string['deleteablock'] = 'Delete a block';
 $string['deleteall'] = 'Delete all';
@@ -1145,7 +1144,7 @@ $string['maincoursepage'] = 'Main course page';
 $string['makeafolder'] = 'Create folder';
 $string['makeavailable'] = 'Make available';
 $string['makeeditable'] = 'If you make \'{$a}\' editable by the web server process (eg apache) then you could edit this file directly from this page';
-$string['makethismyhome'] = 'Make this my default home page';
+$string['makethismyhome'] = 'Make this my home page';
 $string['makeunavailable'] = 'Make unavailable';
 $string['manageblocks'] = 'Blocks';
 $string['managecategorythis'] = 'Manage this category';
@@ -1175,8 +1174,8 @@ $string['maxnumberweeks_desc'] = 'The maximum value in the number of sections dr
 $string['maxnumcoursesincombo'] = 'Browse <a href="{$a->link}">{$a->numberofcourses} courses</a>.';
 $string['maxsize'] = 'Max size: {$a}';
 $string['maxsizeandareasize'] = 'Maximum size for new files: {$a->size}, overall limit: {$a->areasize}';
-$string['maxsizeandattachments'] = 'Maximum size for new files: {$a->size}, maximum attachments: {$a->attachments}';
-$string['maxsizeandattachmentsandareasize'] = 'Maximum size for new files: {$a->size}, maximum attachments: {$a->attachments}, overall limit: {$a->areasize}';
+$string['maxsizeandattachments'] = 'Maximum file size: {$a->size}, maximum number of files: {$a->attachments}';
+$string['maxsizeandattachmentsandareasize'] = 'Maximum file size: {$a->size}, maximum number of files: {$a->attachments}, maximum total size: {$a->areasize}';
 $string['memberincourse'] = 'People in the course';
 $string['messagebody'] = 'Message body';
 $string['messagedselectedusers'] = 'Selected users have been messaged and the recipient list has been reset.';
@@ -1631,9 +1630,9 @@ for important notifications such as security alerts and new releases of Moodle.<
 <p>If you choose, you can allow your site name, country and URL to be added to the public list of Moodle Sites.</p>
 <p>All new registrations are verified manually before they are added to the list, but once you are added you can update your registration (and your entry on the public list) at any time by resubmitting this form.</p>';
 $string['registrationinfotitle'] = 'Registration information';
-$string['registrationno'] = 'No, I do not want to receive any email from Moodle HQ';
+$string['registrationno'] = 'No, I do not wish to receive any emails';
 $string['registrationsend'] = 'Send registration information to moodle.org';
-$string['registrationyes'] = 'Yes, notify me about important news (e.g. security issues or releases) ';
+$string['registrationyes'] = 'Yes, notify me of new Moodle releases, security alerts and other important news';
 $string['reject'] = 'Reject';
 $string['rejectdots'] = 'Reject...';
 $string['relativedatesmode'] = 'Relative dates mode';
@@ -1919,7 +1918,7 @@ $string['statsreport10'] = 'User activity';
 $string['statsreport11'] = 'Most active courses';
 $string['statsreport12'] = 'Most active courses (weighted)';
 $string['statsreport13'] = 'Most participatory courses (enrolments)';
-$string['statsreport14'] = 'Most participatory courses (views/posts)';
+$string['statsreport14'] = 'Most participatory courses (posts/views)';
 $string['statsreport2'] = 'Views (all roles)';
 $string['statsreport3'] = 'Posts (all roles)';
 $string['statsreport4'] = 'All activity (all roles)';
index 216b1ab..02b2a82 100644 (file)
@@ -38,4 +38,4 @@ $string['reseteveryonesdashboard'] = 'Reset Dashboard for all users';
 $string['reseteveryonesprofile'] = 'Reset profile for all users';
 $string['resetpage'] = 'Reset page to default';
 $string['reseterror'] = 'There was an error resetting your page';
-$string['privacy:metadata:core_my:preference:user_home_page_preference'] = 'The user home page preference configured for the Dashboard page.';
+$string['privacy:metadata:core_my:preference:user_home_page_preference'] = 'The user home page preference.';
index ead0c9e..6946b6f 100644 (file)
@@ -69,7 +69,6 @@ $string['backup:backupcourse'] = 'Backup courses';
 $string['backup:backupsection'] = 'Backup sections';
 $string['backup:configure'] = 'Configure backup options';
 $string['backup:downloadfile'] = 'Download files from backup areas';
-$string['backup:backuptargethub'] = 'Backup for publishing on Moodle.net';
 $string['backup:backuptargetimport'] = 'Backup for import';
 $string['backup:userinfo'] = 'Backup user data';
 $string['badges:awardbadge'] = 'Award badge to a user';
@@ -111,8 +110,6 @@ $string['cohort:manage'] = 'Create, delete and move cohorts';
 $string['comment:delete'] = 'Delete comments';
 $string['comment:post'] = 'Post comments';
 $string['comment:view'] = 'View comments';
-$string['community:add'] = 'Use the community block to search Moodle.net and find courses';
-$string['community:download'] = 'Download a course from the community block';
 $string['competency:competencymanage'] = 'Manage competency frameworks';
 $string['competency:competencygrade'] = 'Set competency rating';
 $string['competency:competencyview'] = 'View competency frameworks';
@@ -181,7 +178,6 @@ $string['course:managescales'] = 'Manage scales';
 $string['course:markcomplete'] = 'Mark users as complete in course completion';
 $string['course:movesections'] = 'Move sections';
 $string['course:overridecompletion'] = 'Override activity completion status';
-$string['course:publish'] = 'Publish a course';
 $string['course:renameroles'] = 'Rename roles';
 $string['course:request'] = 'Request new courses';
 $string['course:reset'] = 'Reset course';
@@ -363,7 +359,6 @@ $string['restore:createuser'] = 'Create users on restore';
 $string['restore:restoreactivity'] = 'Restore activities';
 $string['restore:restoresection'] = 'Restore sections';
 $string['restore:restorecourse'] = 'Restore courses';
-$string['restore:restoretargethub'] = 'Restore courses downloaded from Moodle.net';
 $string['restore:restoretargetimport'] = 'Restore from files targeted as import';
 $string['restore:rolldates'] = 'Allowed to roll activity configuration dates on restore';
 $string['restore:uploadfile'] = 'Upload files to backup areas';
index a2dcac9..d4e6b04 100644 (file)
Binary files a/lib/amd/build/templates.min.js and b/lib/amd/build/templates.min.js differ
index 88c4bb0..ff59240 100644 (file)
Binary files a/lib/amd/build/templates.min.js.map and b/lib/amd/build/templates.min.js.map differ
index 019118f..e11dc12 100644 (file)
@@ -65,6 +65,9 @@ define([
     /** @var {Bool} isLoadingTemplates - Whether templates are currently being loaded */
     var isLoadingTemplates = false;
 
+    /** @var {Array} blacklistedNestedHelpers - List of helpers that can't be called within other helpers */
+    var blacklistedNestedHelpers = ['js'];
+
     /**
      * Search the various caches for a template promise for the given search key.
      * The search key should be in the format <theme>/<component>/<template> e.g. boost/core/modal.
@@ -76,6 +79,11 @@ define([
      * @return {Object} jQuery promise resolved with the template source
      */
     var getTemplatePromiseFromCache = function(searchKey) {
+        // Do not cache anything if templaterev is not valid.
+        if (M.cfg.templaterev <= 0) {
+            return null;
+        }
+
         // First try the cache of promises.
         if (searchKey in templatePromises) {
             return templatePromises[searchKey];
@@ -89,7 +97,7 @@ define([
         }
 
         // Now try local storage.
-        var cached = storage.get('core_template/' + searchKey);
+        var cached = storage.get('core_template/' + M.cfg.templaterev + ':' + searchKey);
         if (cached) {
             // Add this to the module cache for future.
             templateCache[searchKey] = cached;
@@ -175,7 +183,7 @@ define([
                                 // Cache all of the dependent templates because we'll need them to render
                                 // the requested template.
                                 templateCache[tempSearchKey] = data.value;
-                                storage.set('core_template/' + tempSearchKey, data.value);
+                                storage.set('core_template/' + M.cfg.templaterev + ':' + tempSearchKey, data.value);
 
                                 if (data.component == component && data.name == name) {
                                     // This is the original template that was requested so remember it to return.
@@ -220,7 +228,7 @@ define([
 
         if (requests.length) {
             // We have requests to send so resolve the deferred with the promises.
-            serverRequestsDeferred.resolve(ajax.call(requests, true, false, false, 0, M.cfg.themerev));
+            serverRequestsDeferred.resolve(ajax.call(requests, true, false, false, 0, M.cfg.templaterev));
         } else {
             // Nothing to load so we can resolve our deferred.
             serverRequestsDeferred.resolve();
@@ -544,6 +552,60 @@ define([
         return '[[_t_' + index + ']]';
     };
 
+    /**
+     * Return a helper function to be added to the context for rendering the a
+     * template.
+     *
+     * This will parse the provided text before giving it to the helper function
+     * in order to remove any blacklisted nested helpers to prevent one helper
+     * from calling another.
+     *
+     * In particular to prevent the JS helper from being called from within another
+     * helper because it can lead to security issues when the JS portion is user
+     * provided.
+     *
+     * @param  {function} helperFunction The helper function to add
+     * @param  {object} context The template context for the helper function
+     * @return {Function} To be set in the context
+     */
+    Renderer.prototype.addHelperFunction = function(helperFunction, context) {
+        return function() {
+            return function(sectionText, helper) {
+                // Override the blacklisted helpers in the template context with
+                // a function that returns an empty string for use when executing
+                // other helpers. This is to prevent these helpers from being
+                // executed as part of the rendering of another helper in order to
+                // prevent any potential security issues.
+                var originalHelpers = blacklistedNestedHelpers.reduce(function(carry, name) {
+                    if (context.hasOwnProperty(name)) {
+                        carry[name] = context[name];
+                    }
+
+                    return carry;
+                }, {});
+
+                blacklistedNestedHelpers.forEach(function(helperName) {
+                    context[helperName] = function() {
+                        return '';
+                    };
+                });
+
+                // Execute the helper with the modified context that doesn't include
+                // the blacklisted nested helpers. This prevents the blacklisted
+                // helpers from being called from within other helpers.
+                var result = helperFunction.apply(this, [context, sectionText, helper]);
+
+                // Restore the original helper implementation in the context so that
+                // any further rendering has access to them again.
+                for (var name in originalHelpers) {
+                    context[name] = originalHelpers[name];
+                }
+
+                return result;
+            }.bind(this);
+        }.bind(this);
+    };
+
     /**
      * Add some common helper functions to all context objects passed to templates.
      * These helpers match exactly the helpers available in php.
@@ -558,24 +620,12 @@ define([
         this.requiredStrings = [];
         this.requiredJS = [];
         context.uniqid = (uniqInstances++);
-        context.str = function() {
-          return this.stringHelper.bind(this, context);
-        }.bind(this);
-        context.pix = function() {
-          return this.pixHelper.bind(this, context);
-        }.bind(this);
-        context.js = function() {
-          return this.jsHelper.bind(this, context);
-        }.bind(this);
-        context.quote = function() {
-          return this.quoteHelper.bind(this, context);
-        }.bind(this);
-        context.shortentext = function() {
-          return this.shortenTextHelper.bind(this, context);
-        }.bind(this);
-        context.userdate = function() {
-          return this.userDateHelper.bind(this, context);
-        }.bind(this);
+        context.str = this.addHelperFunction(this.stringHelper, context);
+        context.pix = this.addHelperFunction(this.pixHelper, context);
+        context.js = this.addHelperFunction(this.jsHelper, context);
+        context.quote = this.addHelperFunction(this.quoteHelper, context);
+        context.shortentext = this.addHelperFunction(this.shortenTextHelper, context);
+        context.userdate = this.addHelperFunction(this.userDateHelper, context);
         context.globals = {config: config};
         context.currentTheme = themeName;
     };
index 65c2c6a..5226f2b 100644 (file)
@@ -197,27 +197,7 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
                     return $context->getSession()->getPage()->findAll($args['selector'], $args['locator']);
                 }
 
-                // For nodes contained in other nodes we can not use the basic named selectors
-                // as they include unions and they would look for matches in the DOM root.
-                $elementxpath = $context->getSession()->getSelectorsHandler()->selectorToXpath($args['selector'], $args['locator']);
-
-                // Split the xpath in unions and prefix them with the container xpath.
-                $unions = explode('|', $elementxpath);
-                foreach ($unions as $key => $union) {
-                    $union = trim($union);
-
-                    // We are in the container node.
-                    if (strpos($union, '.') === 0) {
-                        $union = substr($union, 1);
-                    } else if (strpos($union, '/') !== 0) {
-                        // Adding the path separator in case it is not there.
-                        $union = '/' . $union;
-                    }
-                    $unions[$key] = $args['node']->getXpath() . $union;
-                }
-
-                // We can not use usual Element::find() as it prefixes with DOM root.
-                return $context->getSession()->getDriver()->find(implode('|', $unions));
+                return $args['node']->findAll($args['selector'], $args['locator']);
             },
             $params,
             $timeout,
index 75a0508..2a1434d 100644 (file)
@@ -167,6 +167,8 @@ class api {
     /**
      * Calls WS function hub_get_courses
      *
+     * @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
+     *
      * Parameter $options may have any of these fields:
      * [
      *     'ids' => new external_multiple_structure(new external_value(PARAM_INTEGER, 'id of a course in the hub course
@@ -255,43 +257,8 @@ class api {
      * @throws moodle_exception
      */
     public static function get_courses($search, $downloadable, $enrollable, $options) {
-        static $availableoptions = ['ids', 'sitecourseids', 'coverage', 'licenceshortname', 'subject', 'audience',
-            'educationallevel', 'language', 'orderby', 'givememore', 'allsitecourses'];
-
-        if (empty($options)) {
-            $options = [];
-        } else if (is_object($options)) {
-            $options = (array)$options;
-        } else if (!is_array($options)) {
-            throw new \coding_exception('Parameter $options is invalid');
-        }
-
-        if ($unknownkeys = array_diff(array_keys($options), $availableoptions)) {
-            throw new \coding_exception('Unknown option(s): ' . join(', ', $unknownkeys));
-        }
-
-        $params = [
-            'search' => $search,
-            'downloadable' => (int)(bool)$downloadable,
-            'enrollable' => (int)(bool)$enrollable,
-            'options' => $options
-        ];
-        $result = self::call('hub_get_courses', $params, true);
-        $courses = $result['courses'];
-        $coursetotal = $result['coursetotal'];
-
-        foreach ($courses as $idx => $course) {
-            $courses[$idx]['screenshotbaseurl'] = null;
-            if (!empty($course['screenshots'])) {
-                $courses[$idx]['screenshotbaseurl'] = new moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/webservice/download.php',
-                    array('courseid' => $course['id'],
-                        'filetype' => self::HUB_SCREENSHOT_FILE_TYPE));
-            }
-            $courses[$idx]['commenturl'] = new moodle_url(HUB_MOODLEORGHUBURL,
-                array('courseid' => $course['id'], 'mustbelogged' => true));
-        }
-
-        return [$courses, $coursetotal];
+        debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
+        return [[], 0];
     }
 
     /**
@@ -307,18 +274,20 @@ class api {
     /**
      * Unpublish courses
      *
+     * @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
+     *
      * @param int[]|int $courseids
      * @throws moodle_exception
      */
     public static function unregister_courses($courseids) {
-        $courseids = (array)$courseids;
-        $params = array('courseids' => $courseids);
-        self::call('hub_unregister_courses', $params);
+        debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
     }
 
     /**
      * Publish one course
      *
+     * @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
+     *
      * Expected contents of $courseinfo:
      * [
      *     'sitecourseid' => new external_value(PARAM_INT, 'the id of the course on the publishing site'),
@@ -360,70 +329,44 @@ class api {
      * @throws moodle_exception if communication to moodle.net failed or course could not be published
      */
     public static function register_course($courseinfo) {
-        $params = array('courses' => array($courseinfo));
-        $hubcourseids = self::call('hub_register_courses', $params);
-        if (count($hubcourseids) != 1) {
-            throw new moodle_exception('errorcoursewronglypublished', 'hub');
-        }
-        return $hubcourseids[0];
+        debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
+        throw new moodle_exception('errorcoursewronglypublished', 'hub');
     }
 
     /**
      * Uploads a screenshot for the published course
      *
+     * @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
+     *
      * @param int $hubcourseid id of the published course on moodle.net, it must be published from this site
      * @param \stored_file $file
      * @param int $screenshotnumber ordinal number of the screenshot
      */
     public static function add_screenshot($hubcourseid, \stored_file $file, $screenshotnumber) {
-        $curl = new \curl();
-        $params = array();
-        $params['filetype'] = self::HUB_SCREENSHOT_FILE_TYPE;
-        $params['file'] = $file;
-        $params['courseid'] = $hubcourseid;
-        $params['filename'] = $file->get_filename();
-        $params['screenshotnumber'] = $screenshotnumber;
-        $params['token'] = registration::get_token(MUST_EXIST);
-        $curl->post(HUB_MOODLEORGHUBURL . "/local/hub/webservice/upload.php", $params);
+        debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
     }
 
     /**
      * Downloads course backup
      *
+     * @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
+     *
      * @param int $hubcourseid id of the course on moodle.net
      * @param string $path local path (in tempdir) to save the downloaded backup to.
      */
     public static function download_course_backup($hubcourseid, $path) {
-        $fp = fopen($path, 'w');
-
-        $curlurl = new \moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/webservice/download.php',
-            ['filetype' => self::HUB_BACKUP_FILE_TYPE, 'courseid' => $hubcourseid]);
-
-        // Send an identification token if the site is registered.
-        if ($token = registration::get_token()) {
-            $curlurl->param('token', $token);
-        }
-
-        $ch = curl_init($curlurl->out(false));
-        curl_setopt($ch, CURLOPT_FILE, $fp);
-        curl_exec($ch);
-        curl_close($ch);
-        fclose($fp);
+        debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
     }
 
     /**
      * Uploads a course backup
      *
+     * @deprecated since Moodle 3.8. Moodle.net has been sunsetted making this function useless.
+     *
      * @param int $hubcourseid id of the published course on moodle.net, it must be published from this site
      * @param \stored_file $backupfile
      */
     public static function upload_course_backup($hubcourseid, \stored_file $backupfile) {
-        $curl = new \curl();
-        $params = array();
-        $params['filetype'] = self::HUB_BACKUP_FILE_TYPE;
-        $params['courseid'] = $hubcourseid;
-        $params['file'] = $backupfile;
-        $params['token'] = registration::get_token();
-        $curl->post(HUB_MOODLEORGHUBURL . '/local/hub/webservice/upload.php', $params);
+        debugging("This function has been deprecated as part of the Moodle.net sunsetting process.");
     }
 }
\ No newline at end of file
diff --git a/lib/classes/hub/course_publication_form.php b/lib/classes/hub/course_publication_form.php
deleted file mode 100644 (file)
index 498f087..0000000
+++ /dev/null
@@ -1,308 +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/>.
-
-/**
- * Class course_publication_form
- *
- * @package    core
- * @copyright  2017 Marina Glancy
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-namespace core\hub;
-defined('MOODLE_INTERNAL') || die();
-
-use stdClass;
-use license_manager;
-use moodle_url;
-use core_collator;
-
-global $CFG;
-require_once($CFG->libdir . '/formslib.php');
-require_once($CFG->libdir . '/licenselib.php');
-
-/**
- * The forms used for course publication
- *
- * @package    core
- * @copyright  2017 Marina Glancy
- * @author     Jerome Mouneyrac <jerome@mouneyrac.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class course_publication_form extends \moodleform {
-
-    /**
-     * Form definition
-     */
-    public function definition() {
-        global $CFG, $USER, $PAGE;
-
-        $strrequired = get_string('required');
-        $mform = & $this->_form;
-        $course = $this->_customdata['course'];
-        if (!empty($this->_customdata['publication'])) {
-            // We are editing existing publication.
-            $publication = $this->_customdata['publication'];
-            $advertise = $publication->enrollable;
-            $publishedcourse = publication::get_published_course($publication);
-        } else {
-            $publication = null;
-            $advertise = $this->_customdata['advertise'];
-        }
-        $share = !$advertise;
-
-        if (!empty($publishedcourse)) {
-            $hubcourseid = $publishedcourse['id'];
-            $defaultfullname = $publishedcourse['fullname'];
-            $defaultshortname = $publishedcourse['shortname'];
-            $defaultsummary = $publishedcourse['description'];
-            $defaultlanguage = $publishedcourse['language'];
-            $defaultpublishername = $publishedcourse['publishername'];
-            $defaultpublisheremail = $publishedcourse['publisheremail'];
-            $defaultcontributornames = $publishedcourse['contributornames'];
-            $defaultcoverage = $publishedcourse['coverage'];
-            $defaultcreatorname = $publishedcourse['creatorname'];
-            $defaultlicenceshortname = $publishedcourse['licenceshortname'];
-            $defaultsubject = $publishedcourse['subject'];
-            $defaultaudience = $publishedcourse['audience'];
-            $defaulteducationallevel = $publishedcourse['educationallevel'];
-            $defaultcreatornotes = $publishedcourse['creatornotes'];
-            $defaultcreatornotesformat = $publishedcourse['creatornotesformat'];
-            $screenshotsnumber = $publishedcourse['screenshots'];
-            $screenshotbaseurl = $publishedcourse['screenshotbaseurl'];
-            $privacy = $publishedcourse['privacy'];
-            if (($screenshotsnumber > 0) and !empty($privacy)) {
-                $PAGE->requires->yui_module('moodle-block_community-imagegallery',
-                    'M.blocks_community.init_imagegallery',
-                    array(array('imageids' => array($hubcourseid),
-                        'imagenumbers' => array($screenshotsnumber),
-                        'huburl' => HUB_MOODLEORGHUBURL)));
-            }
-        } else {
-            $defaultfullname = $course->fullname;
-            $defaultshortname = $course->shortname;
-            $defaultsummary = clean_param($course->summary, PARAM_TEXT);
-            if (empty($course->lang)) {
-                $language = get_site()->lang;
-                if (empty($language)) {
-                    $defaultlanguage = current_language();
-                } else {
-                    $defaultlanguage = $language;
-                }
-            } else {
-                $defaultlanguage = $course->lang;
-            }
-            $defaultpublishername = $USER->firstname . ' ' . $USER->lastname;
-            $defaultpublisheremail = $USER->email;
-            $defaultcontributornames = '';
-            $defaultcoverage = '';
-            $defaultcreatorname = $USER->firstname . ' ' . $USER->lastname;
-            $defaultlicenceshortname = 'cc';
-            $defaultsubject = 'none';
-            $defaultaudience = publication::HUB_AUDIENCE_STUDENTS;
-            $defaulteducationallevel = publication::HUB_EDULEVEL_TERTIARY;
-            $defaultcreatornotes = '';
-            $defaultcreatornotesformat = FORMAT_HTML;
-            $screenshotsnumber = 0;
-            $screenshotbaseurl = null;
-        }
-
-        // The input parameters.
-        $mform->addElement('header', 'moodle', get_string('publicationinfo', 'hub'));
-
-        $mform->addElement('text', 'name', get_string('coursename', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->addRule('name', $strrequired, 'required', null, 'client');
-        $mform->setType('name', PARAM_TEXT);
-        $mform->setDefault('name', $defaultfullname);
-        $mform->addHelpButton('name', 'name', 'hub');
-
-        $mform->addElement('hidden', 'id', $course->id);
-        $mform->setType('id', PARAM_INT);
-
-        $mform->addElement('hidden', 'publicationid', $publication ? $publication->id : null);
-        $mform->setType('publicationid', PARAM_INT);
-
-        if ($share) {
-            $buttonlabel = get_string('shareon', 'hub', 'Moodle.net');
-
-            $mform->addElement('hidden', 'share', $share);
-            $mform->setType('share', PARAM_BOOL);
-            $mform->addElement('text', 'demourl', get_string('demourl', 'hub'),
-                array('class' => 'metadatatext'));
-            $mform->setType('demourl', PARAM_URL);
-            $mform->setDefault('demourl', new moodle_url("/course/view.php?id=" . $course->id));
-            $mform->addHelpButton('demourl', 'demourl', 'hub');
-        }
-
-        if ($advertise) {
-            if (!$publication) {
-                $buttonlabel = get_string('advertiseon', 'hub', 'Moodle.net');
-            } else {
-                $buttonlabel = get_string('readvertiseon', 'hub', 'Moodle.net');
-            }
-            $mform->addElement('hidden', 'advertise', $advertise);
-            $mform->setType('advertise', PARAM_BOOL);
-            $mform->addElement('hidden', 'courseurl', $CFG->wwwroot . "/course/view.php?id=" . $course->id);
-            $mform->setType('courseurl', PARAM_URL);
-            $mform->addElement('static', 'courseurlstring', get_string('courseurl', 'hub'));
-            $mform->setDefault('courseurlstring', new moodle_url("/course/view.php?id=" . $course->id));
-            $mform->addHelpButton('courseurlstring', 'courseurl', 'hub');
-        }
-
-        $mform->addElement('text', 'courseshortname', get_string('courseshortname', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->setDefault('courseshortname', $defaultshortname);
-        $mform->addHelpButton('courseshortname', 'courseshortname', 'hub');
-        $mform->setType('courseshortname', PARAM_TEXT);
-        $mform->addElement('textarea', 'description', get_string('description', 'hub'), array('rows' => 10,
-            'cols' => 57));
-        $mform->addRule('description', $strrequired, 'required', null, 'client');
-        $mform->setDefault('description', $defaultsummary);
-        $mform->setType('description', PARAM_TEXT);
-        $mform->addHelpButton('description', 'description', 'hub');
-
-        $languages = get_string_manager()->get_list_of_languages();
-        core_collator::asort($languages);
-        $mform->addElement('select', 'language', get_string('language'), $languages);
-        $mform->setDefault('language', $defaultlanguage);
-        $mform->addHelpButton('language', 'language', 'hub');
-
-        $mform->addElement('text', 'publishername', get_string('publishername', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->setDefault('publishername', $defaultpublishername);
-        $mform->addRule('publishername', $strrequired, 'required', null, 'client');
-        $mform->addHelpButton('publishername', 'publishername', 'hub');
-        $mform->setType('publishername', PARAM_NOTAGS);
-
-        $mform->addElement('text', 'publisheremail', get_string('publisheremail', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->setDefault('publisheremail', $defaultpublisheremail);
-        $mform->addRule('publisheremail', $strrequired, 'required', null, 'client');
-        $mform->addHelpButton('publisheremail', 'publisheremail', 'hub');
-        $mform->setType('publisheremail', PARAM_EMAIL);
-
-        $mform->addElement('text', 'creatorname', get_string('creatorname', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->addRule('creatorname', $strrequired, 'required', null, 'client');
-        $mform->setType('creatorname', PARAM_NOTAGS);
-        $mform->setDefault('creatorname', $defaultcreatorname);
-        $mform->addHelpButton('creatorname', 'creatorname', 'hub');
-
-        $mform->addElement('text', 'contributornames', get_string('contributornames', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->setDefault('contributornames', $defaultcontributornames);
-        $mform->addHelpButton('contributornames', 'contributornames', 'hub');
-        $mform->setType('contributornames', PARAM_NOTAGS);
-
-        $mform->addElement('text', 'coverage', get_string('tags', 'hub'),
-            array('class' => 'metadatatext'));
-        $mform->setType('coverage', PARAM_TEXT);
-        $mform->setDefault('coverage', $defaultcoverage);
-        $mform->addHelpButton('coverage', 'tags', 'hub');
-
-        $licensemanager = new license_manager();
-        $licences = $licensemanager->get_licenses();
-        $options = array();
-        foreach ($licences as $license) {
-            $options[$license->shortname] = get_string($license->shortname, 'license');
-        }
-        $mform->addElement('select', 'licence', get_string('license'), $options);
-        $mform->setDefault('licence', $defaultlicenceshortname);
-        unset($options);
-        $mform->addHelpButton('licence', 'licence', 'hub');
-
-        $options = publication::get_sorted_subjects();
-
-        $mform->addElement('searchableselector', 'subject',
-            get_string('subject', 'hub'), $options);
-        unset($options);
-        $mform->addHelpButton('subject', 'subject', 'hub');
-        $mform->setDefault('subject', $defaultsubject);
-        $mform->addRule('subject', $strrequired, 'required', null, 'client');
-
-        $options = publication::audience_options();
-        $mform->addElement('select', 'audience', get_string('audience', 'hub'), $options);
-        $mform->setDefault('audience', $defaultaudience);
-        unset($options);
-        $mform->addHelpButton('audience', 'audience', 'hub');
-
-        $options = publication::educational_level_options();
-        $mform->addElement('select', 'educationallevel', get_string('educationallevel', 'hub'), $options);
-        $mform->setDefault('educationallevel', $defaulteducationallevel);
-        unset($options);
-        $mform->addHelpButton('educationallevel', 'educationallevel', 'hub');
-
-        $editoroptions = array('maxfiles' => 0, 'maxbytes' => 0, 'trusttext' => false, 'forcehttps' => false);
-        $mform->addElement('editor', 'creatornotes', get_string('creatornotes', 'hub'), '', $editoroptions);
-        $mform->addRule('creatornotes', $strrequired, 'required', null, 'client');
-        $mform->setType('creatornotes', PARAM_CLEANHTML);
-        $mform->addHelpButton('creatornotes', 'creatornotes', 'hub');
-
-        if ($advertise) {
-            if (!empty($screenshotsnumber)) {
-                if (!empty($privacy)) {
-                    $screenshothtml = \html_writer::empty_tag('img',
-                        array('src' => $screenshotbaseurl, 'alt' => $defaultfullname));
-                    $screenshothtml = \html_writer::tag('div', $screenshothtml,
-                        array('class' => 'coursescreenshot',
-                            'id' => 'image-' . $hubcourseid));
-                } else {
-                    $screenshothtml = get_string('existingscreenshotnumber', 'hub', $screenshotsnumber);
-                }
-                $mform->addElement('static', 'existingscreenshots', get_string('existingscreenshots', 'hub'), $screenshothtml);
-                $mform->addHelpButton('existingscreenshots', 'deletescreenshots', 'hub');
-                $mform->addElement('checkbox', 'deletescreenshots', '', ' ' . get_string('deletescreenshots', 'hub'));
-            }
-
-            $mform->addElement('hidden', 'existingscreenshotnumber', $screenshotsnumber);
-            $mform->setType('existingscreenshotnumber', PARAM_INT);
-        }
-
-        $mform->addElement('filemanager', 'screenshots', get_string('addscreenshots', 'hub'), null,
-            array('subdirs' => 0,
-                'maxbytes' => 1000000,
-                'maxfiles' => 3
-            ));
-        $mform->addHelpButton('screenshots', 'screenshots', 'hub');
-
-        $this->add_action_buttons(false, $buttonlabel);
-
-        // Set default value for creatornotes editor.
-        $data = new stdClass();
-        $data->creatornotes = array();
-        $data->creatornotes['text'] = $defaultcreatornotes;
-        $data->creatornotes['format'] = $defaultcreatornotesformat;
-        $this->set_data($data);
-    }
-
-    /**
-     * Custom form validation
-     *
-     * @param array $data
-     * @param array $files
-     * @return array
-     */
-    public function validation($data, $files) {
-        $errors = parent::validation($data, $files);
-
-        if ($this->_form->_submitValues['subject'] == 'none') {
-            $errors['subject'] = get_string('mustselectsubject', 'hub');
-        }
-
-        return $errors;
-    }
-}
diff --git a/lib/classes/hub/publication.php b/lib/classes/hub/publication.php
deleted file mode 100644 (file)
index f0f48d9..0000000
+++ /dev/null
@@ -1,409 +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/>.
-
-/**
- * Class publication
- *
- * @package    core
- * @copyright  2017 Marina Glancy
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-namespace core\hub;
-defined('MOODLE_INTERNAL') || die();
-
-use moodle_exception;
-use moodle_url;
-use context_user;
-use stdClass;
-use html_writer;
-
-/**
- * Methods to work with site registration on moodle.net
- *
- * @package    core
- * @copyright  2017 Marina Glancy
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class publication {
-
-    /** @var Audience: educators */
-    const HUB_AUDIENCE_EDUCATORS = 'educators';
-
-    /** @var Audience: students */
-    const HUB_AUDIENCE_STUDENTS = 'students';
-
-    /** @var Audience: admins */
-    const HUB_AUDIENCE_ADMINS = 'admins';
-
-    /** @var Educational level: primary */
-    const HUB_EDULEVEL_PRIMARY = 'primary';
-
-    /** @var Educational level: secondary */
-    const HUB_EDULEVEL_SECONDARY = 'secondary';
-
-    /** @var Educational level: tertiary */
-    const HUB_EDULEVEL_TERTIARY = 'tertiary';
-
-    /** @var Educational level: government */
-    const HUB_EDULEVEL_GOVERNMENT = 'government';
-
-    /** @var Educational level: association */
-    const HUB_EDULEVEL_ASSOCIATION = 'association';
-
-    /** @var Educational level: corporate */
-    const HUB_EDULEVEL_CORPORATE = 'corporate';
-
-    /** @var Educational level: other */
-    const HUB_EDULEVEL_OTHER = 'other';
-
-
-    /**
-     * Retrieve all the sorted course subjects
-     *
-     * @return array $subjects
-     */
-    public static function get_sorted_subjects() {
-        $subjects = get_string_manager()->load_component_strings('edufields', current_language());
-
-        // Sort the subjects.
-        $return  = [];
-        asort($subjects);
-        foreach ($subjects as $key => $option) {
-            $keylength = strlen($key);
-            if ($keylength == 12) {
-                $return[$key] = $option; // We want only selectable categories.
-            }
-        }
-        return $return;
-    }
-
-    /**
-     * Get all publication for a course
-     *
-     * @param int $courseid local course id
-     * @return array of publication
-     */
-    public static function get_course_publications($courseid) {
-        global $DB;
-        $sql = 'SELECT cp.id, cp.status, cp.timechecked, cp.timepublished, rh.hubname,
-                       rh.huburl, cp.courseid, cp.enrollable, cp.hubcourseid
-                FROM {course_published} cp, {registration_hubs} rh
-                WHERE cp.huburl = rh.huburl and cp.courseid = :courseid and rh.huburl = :huburl
-                ORDER BY cp.enrollable DESC, rh.hubname, cp.timepublished';
-        $params = array('courseid' => $courseid, 'huburl' => HUB_MOODLEORGHUBURL);
-        $records = $DB->get_records_sql($sql, $params);
-
-        // Add links for publications that are listed.
-        foreach ($records as $id => $record) {
-            if ($record->status) {
-                $records[$id]->link = new moodle_url(HUB_MOODLEORGHUBURL, ['courseid' => $record->hubcourseid]);
-            }
-        }
-        return $records;
-    }
-
-    /**
-     * Load publication information from local db
-     *
-     * @param int $id
-     * @param int $courseid if specified publication will be checked that it is in the current course
-     * @param int $strictness
-     * @return stdClass
-     */
-    public static function get_publication($id, $courseid = 0, $strictness = IGNORE_MISSING) {
-        global $DB;
-        if (!$id && $strictness != MUST_EXIST) {
-            return false;
-        }
-        $params = ['id' => $id, 'huburl' => HUB_MOODLEORGHUBURL];
-        if ($courseid) {
-            $params['courseid'] = $courseid;
-        }
-        return $DB->get_record('course_published', $params, '*', $strictness);
-    }
-
-    /**
-     * Update a course publication
-     * @param stdClass $publication
-     */
-    protected static function update_publication($publication) {
-        global $DB;
-        $DB->update_record('course_published', $publication);
-    }
-
-    /**
-     * Check all courses published from this site if they have been approved
-     */
-    public static function request_status_update() {
-        global $DB;
-
-        list($sitecourses, $coursetotal) = api::get_courses('', 1, 1, ['allsitecourses' => 1]);
-
-        // Update status for all these course.
-        foreach ($sitecourses as $sitecourse) {
-            // Get the publication from the hub course id.
-            $publication = $DB->get_record('course_published', ['hubcourseid' => $sitecourse['id']]);
-            if (!empty($publication)) {
-                $publication->status = $sitecourse['privacy'];
-                $publication->timechecked = time();
-                self::update_publication($publication);
-            } else {
-                $msgparams = new stdClass();
-                $msgparams->id = $sitecourse['id'];
-                $msgparams->hubname = html_writer::tag('a', 'Moodle.net', array('href' => HUB_MOODLEORGHUBURL));
-                \core\notification::add(get_string('detectednotexistingpublication', 'hub', $msgparams)); // TODO action?
-            }
-        }
-
-    }
-
-    /**
-     * Unpublish a course
-     *
-     * @param stdClass $publication
-     */
-    public static function unpublish($publication) {
-        global $DB;
-        // Unpublish the publication by web service.
-        api::unregister_courses($publication->hubcourseid);
-
-        // Delete the publication from the database.
-        $DB->delete_records('course_published', array('id' => $publication->id));
-
-        // Add confirmation message.
-        $course = get_course($publication->courseid);
-        $context = \context_course::instance($course->id);
-        $publication->courseshortname = format_string($course->shortname, true, ['context' => $context]);
-        $publication->hubname = 'Moodle.net';
-        \core\notification::add(get_string('courseunpublished', 'hub', $publication), \core\output\notification::NOTIFY_SUCCESS);
-    }
-
-    /**
-     * Publish a course
-     *
-     * @param \stdClass $courseinfo
-     * @param \stored_file[] $files
-     */
-    public static function publish_course($courseinfo, $files) {
-        global $DB;
-
-        // Register course and get id of the course on moodle.net ($hubcourseid).
-        $courseid = $courseinfo->sitecourseid;
-        try {
-            $hubcourseid = api::register_course($courseinfo);
-        } catch (Exception $e) {
-            throw new moodle_exception('errorcoursepublish', 'hub',
-                new moodle_url('/course/view.php', array('id' => $courseid)), $e->getMessage());
-        }
-
-        // Insert/update publication record in the local DB.
-        $publication = $DB->get_record('course_published', array('hubcourseid' => $hubcourseid, 'huburl' => HUB_MOODLEORGHUBURL));
-
-        if ($publication) {
-            $DB->update_record('course_published', ['id' => $publication->id, 'timepublished' => time()]);
-        } else {
-            $publication = new stdClass();
-            $publication->huburl = HUB_MOODLEORGHUBURL;
-            $publication->courseid = $courseid;
-            $publication->hubcourseid = $hubcourseid;
-            $publication->enrollable = (int)$courseinfo->enrollable;
-            $publication->timepublished = time();
-            $publication->id = $DB->insert_record('course_published', $publication);
-        }
-
-        // Send screenshots.
-        if ($files) {
-            $screenshotnumber = $courseinfo->screenshots - count($files);
-            foreach ($files as $file) {
-                $screenshotnumber++;
-                api::add_screenshot($hubcourseid, $file, $screenshotnumber);
-            }
-        }
-
-        return $hubcourseid;
-    }
-
-    /**
-     * Delete all publications
-     *
-     * @param int $advertised search for advertised courses
-     * @param int $shared search for shared courses
-     * @throws moodle_exception
-     */
-    public static function delete_all_publications($advertised = true, $shared = true) {
-        global $DB;
-
-        if (!$advertised && !$shared) {
-            // Nothing to do.
-            return true;
-        }
-
-        $params = ['huburl' => HUB_MOODLEORGHUBURL];
-        if (!$advertised || !$shared) {
-            // Retrieve ONLY advertised or ONLY shared.
-            $params['enrollable'] = $advertised ? 1 : 0;
-        }
-
-        if (!$publications = $DB->get_records('course_published', $params)) {
-            // Nothing to unpublish.
-            return true;
-        }
-
-        foreach ($publications as $publication) {
-            $hubcourseids[] = $publication->hubcourseid;
-        }
-
-        api::unregister_courses($hubcourseids);
-
-        // Delete the published courses from local db.
-        $DB->delete_records('course_published', $params);
-        return true;
-    }
-
-    /**
-     * Get an array of all block instances for a given context
-     * @param int $contextid a context id
-     * @return array of block instances.
-     */
-    public static function get_block_instances_by_context($contextid) {
-        global $DB;
-        return $DB->get_records('block_instances', array('parentcontextid' => $contextid), 'blockname');
-    }
-
-    /**
-     * List of available educational levels
-     *
-     * @param bool $any add option for "Any" (for search forms)
-     * @return array
-     */
-    public static function educational_level_options($any = false) {
-        $options = array();
-        if ($any) {
-            $options['all'] = get_string('any');
-        }
-        $options[self::HUB_EDULEVEL_PRIMARY] = get_string('edulevelprimary', 'hub');
-        $options[self::HUB_EDULEVEL_SECONDARY] = get_string('edulevelsecondary', 'hub');
-        $options[self::HUB_EDULEVEL_TERTIARY] = get_string('eduleveltertiary', 'hub');
-        $options[self::HUB_EDULEVEL_GOVERNMENT] = get_string('edulevelgovernment', 'hub');
-        $options[self::HUB_EDULEVEL_ASSOCIATION] = get_string('edulevelassociation', 'hub');
-        $options[self::HUB_EDULEVEL_CORPORATE] = get_string('edulevelcorporate', 'hub');
-        $options[self::HUB_EDULEVEL_OTHER] = get_string('edulevelother', 'hub');
-        return $options;
-    }
-
-    /**
-     * List of available audience options
-     *
-     * @param bool $any add option for "Any" (for search forms)
-     * @return array
-     */
-    public static function audience_options($any = false) {
-        $options = array();
-        if ($any) {
-            $options['all'] = get_string('any');
-        }
-        $options[self::HUB_AUDIENCE_EDUCATORS] = get_string('audienceeducators', 'hub');
-        $options[self::HUB_AUDIENCE_STUDENTS] = get_string('audiencestudents', 'hub');
-        $options[self::HUB_AUDIENCE_ADMINS] = get_string('audienceadmins', 'hub');
-        return $options;
-    }
-
-    /**
-     * Search for courses
-     *
-     * For the list of fields returned for each course see {@link communication::get_courses}
-     *
-     * @param string $search search string
-     * @param bool $downloadable true - return downloadable courses, false - return enrollable courses
-     * @param array|\stdClass $options other options from the list of allowed options:
-     *              'ids', 'sitecourseids', 'coverage', 'licenceshortname', 'subject', 'audience',
-     *              'educationallevel', 'language', 'orderby', 'givememore', 'allsitecourses'
-     * @return array of two elements: [$courses, $coursetotal]
-     */
-    public static function search($search, $downloadable, $options) {
-        try {
-            return api::get_courses($search, $downloadable, !$downloadable, $options);
-        } catch (moodle_exception $e) {
-            \core\notification::add(get_string('errorcourselisting', 'block_community', $e->getMessage()),
-                \core\output\notification::NOTIFY_ERROR);
-            return [[], 0];
-        }
-    }
-
-    /**
-     * Retrieves information about published course
-     *
-     * For the list of fields returned for the course see {@link communication::get_courses}
-     *
-     * @param stdClass $publication
-     * @return array|null
-     */
-    public static function get_published_course($publication) {
-        try {
-            list($courses, $unused) = api::get_courses('', !$publication->enrollable,
-                $publication->enrollable, ['ids' => [$publication->hubcourseid], 'allsitecourses' => 1]);
-            return reset($courses);
-        } catch (\Exception $e) {
-            \core\notification::add(get_string('errorcourseinfo', 'hub', $e->getMessage()),
-                \core\output\notification::NOTIFY_ERROR);
-        }
-        return null;
-    }
-
-    /**
-     * Downloads course backup and stores it in the user private files
-     *
-     * @param int $hubcourseid
-     * @param string $coursename
-     * @return array
-     */
-    public static function download_course_backup($hubcourseid, $coursename) {
-        global $CFG, $USER;
-        require_once($CFG->libdir . "/filelib.php");
-
-        $backuptempdir = make_backup_temp_directory('');
-        $filename = md5(time() . '-' . $hubcourseid . '-'. $USER->id . '-'. random_string(20));
-        $path = $backuptempdir.'/'.$filename.".mbz";
-
-        api::download_course_backup($hubcourseid, $path);
-
-        $fs = get_file_storage();
-        $record = new stdClass();
-        $record->contextid = context_user::instance($USER->id)->id;
-        $record->component = 'user';
-        $record->filearea = 'private';
-        $record->itemid = 0;
-        $record->filename = urlencode($coursename).'_'.time().".mbz";
-        $record->filepath = '/downloaded_backup/';
-        if (!$fs->file_exists($record->contextid, $record->component,
-            $record->filearea, 0, $record->filepath, $record->filename)) {
-            $fs->create_file_from_pathname($record, $path);
-        }
-
-        return [$record->filepath . $record->filename, $filename];
-    }
-
-    /**
-     * Uploads a course backup
-     *
-     * @param int $hubcourseid id of the published course on moodle.net, it must be published from this site
-     * @param \stored_file $backupfile
-     */
-    public static function upload_course_backup($hubcourseid, \stored_file $backupfile) {
-        api::upload_course_backup($hubcourseid, $backupfile);
-    }
-}
\ No newline at end of file
index 9865782..2586791 100644 (file)
@@ -418,19 +418,6 @@ class registration {
             return true;
         }
 
-        // Unpublish the courses.
-        try {
-            publication::delete_all_publications($unpublishalladvertisedcourses, $unpublishalluploadedcourses);
-        } catch (moodle_exception $e) {
-            $errormessage = $e->getMessage();
-            $errormessage .= \html_writer::empty_tag('br') .
-                get_string('errorunpublishcourses', 'hub');
-
-            \core\notification::add(get_string('unregistrationerror', 'hub', $errormessage),
-                \core\output\notification::NOTIFY_ERROR);
-            return false;
-        }
-
         // Course unpublish went ok, unregister the site now.
         try {
             api::unregister_site();
diff --git a/lib/classes/output/mustache_engine.php b/lib/classes/output/mustache_engine.php
new file mode 100644 (file)
index 0000000..4dd2b90
--- /dev/null
@@ -0,0 +1,77 @@
+<?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/>.
+
+/**
+ * Custom Moodle engine for mustache.
+ *
+ * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\output;
+
+/**
+ * Custom Moodle engine for mustache.
+ *
+ * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mustache_engine extends \Mustache_Engine {
+    /**
+     * @var mustache_helper_collection
+     */
+    private $helpers;
+
+    /**
+     * @var string[] Names of helpers that aren't allowed to be called within other helpers.
+     */
+    private $blacklistednestedhelpers = [];
+
+    /**
+     * Mustache engine constructor.
+     *
+     * This provides an additional option to the parent \Mustache_Engine implementation:
+     * $options = [
+     *      // A list of helpers (by name) to prevent from executing within the rendering
+     *      // of other helpers.
+     *      'blacklistednestedhelpers' => ['js']
+     * ];
+     * @param array $options [description]
+     */
+    public function __construct(array $options = []) {
+        if (isset($options['blacklistednestedhelpers'])) {
+            $this->blacklistednestedhelpers = $options['blacklistednestedhelpers'];
+        }
+
+        parent::__construct($options);
+    }
+
+    /**
+     * Get the current set of Mustache helpers.
+     *
+     * @see Mustache_Engine::setHelpers
+     *
+     * @return \Mustache_HelperCollection
+     */
+    public function getHelpers()
+    {
+        if (!isset($this->helpers)) {
+            $this->helpers = new mustache_helper_collection(null, $this->blacklistednestedhelpers);
+        }
+
+        return $this->helpers;
+    }
+}
diff --git a/lib/classes/output/mustache_helper_collection.php b/lib/classes/output/mustache_helper_collection.php
new file mode 100644 (file)
index 0000000..233d741
--- /dev/null
@@ -0,0 +1,176 @@
+<?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/>.
+
+/**
+ * Custom Moodle helper collection for mustache.
+ *
+ * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\output;
+
+/**
+ * Custom Moodle helper collection for mustache.
+ *
+ * @copyright  2019 Ryan Wyllie <ryan@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mustache_helper_collection extends \Mustache_HelperCollection {
+
+    /**
+     * @var string[] Names of helpers that aren't allowed to be called within other helpers.
+     */
+    private $blacklistednestedhelpers = [];
+
+    /**
+     * Helper Collection constructor.
+     *
+     * Optionally accepts an array (or Traversable) of `$name => $helper` pairs.
+     *
+     * @throws \Mustache_Exception_InvalidArgumentException if the $helpers argument isn't an array or Traversable
+     *
+     * @param array|\Traversable $helpers (default: null)
+     * @param string[] $blacklistednestedhelpers Names of helpers that aren't allowed to be called within other helpers.
+     */
+    public function __construct($helpers = null, array $blacklistednestedhelpers = []) {
+        $this->blacklistednestedhelpers = $blacklistednestedhelpers;
+        parent::__construct($helpers);
+    }
+
+    /**
+     * Add a helper to this collection.
+     *
+     * This function has overridden the parent implementation to provide blacklist
+     * functionality for certain helpers to prevent them being called from within
+     * other helpers. This is because the JavaScript helper can be used in a
+     * security exploit if it can be nested.
+     *
+     * The function will wrap callable helpers in an anonymous function that strips
+     * out the blacklisted helpers from the source string before giving it to the
+     * helper function. This prevents the blacklisted helper functions from being
+     * called by nested render functions from within other helpers.
+     *
+     * @see \Mustache_HelperCollection::add()
+     * @param string $name
+     * @param mixed  $helper
+     */
+    public function add($name, $helper)
+    {
+        $blacklist = $this->blacklistednestedhelpers;
+
+        if (is_callable($helper) && !empty($blacklist)) {
+            $helper = function($source, \Mustache_LambdaHelper $lambdahelper) use ($helper, $blacklist) {
+
+                // Temporarily override the blacklisted helpers to return nothing
+                // so that they can't be executed from within other helpers.
+                $disabledhelpers = $this->disable_helpers($blacklist);
+                // Call the original function with the modified sources.
+                $result = call_user_func($helper, $source, $lambdahelper);
+                // Restore the original blacklisted helper implementations now
+                // that this helper has finished executing so that the rest of
+                // the rendering process continues to work correctly.
+                $this->restore_helpers($disabledhelpers);
+                // Lastly parse the returned string to strip out any unwanted helper
+                // tags that were added through variable substitution (or other means).
+                // This is done because a secondary render is called on the result
+                // of a helper function if it still includes mustache tags. See
+                // the section function of Mustache_Compiler for details.
+                return $this->strip_blacklisted_helpers($blacklist, $result);
+            };
+        }
+
+        parent::add($name, $helper);
+    }
+
+    /**
+     * Disable a list of helpers (by name) by changing their implementation to
+     * simply return an empty string.
+     *
+     * @param  string[] $names List of helper names to disable
+     * @return \Closure[] The original helper functions indexed by name
+     */
+    private function disable_helpers($names) {
+        $disabledhelpers = [];
+
+        foreach ($names as $name) {
+            if ($this->has($name)) {
+                $function = $this->get($name);
+                // Null out the helper. Must call parent::add here to avoid
+                // a recursion problem.
+                parent::add($name, function() {
+                    return '';
+                });
+
+                $disabledhelpers[$name] = $function;
+            }
+        }
+
+        return $disabledhelpers;
+    }
+
+    /**
+     * Restore the original helper implementations. Typically used after disabling
+     * a helper.
+     *
+     * @param  \Closure[] $helpers The helper functions indexed by name
+     */
+    private function restore_helpers($helpers) {
+        foreach ($helpers as $name => $function) {
+            // Restore the helper functions. Must call parent::add here to avoid
+            // a recursion problem.
+            parent::add($name, $function);
+        }
+    }
+
+    /**
+     * Parse the given string and remove any reference to blacklisted helpers.
+     *
+     * E.g.
+     * $blacklist = ['js'];
+     * $string = "core, move, {{#js}} some nasty JS hack {{/js}}"
+     * result: "core, move, {{}}"
+     *
+     * @param  string[] $blacklist List of helper names to strip
+     * @param  string $string String to parse
+     * @return string Parsed string
+     */
+    public function strip_blacklisted_helpers($blacklist, $string) {
+        $starttoken = \Mustache_Tokenizer::T_SECTION;
+        $endtoken = \Mustache_Tokenizer::T_END_SECTION;
+        if ($endtoken == '/') {
+            $endtoken = '\/';
+        }
+
+        $regexes = array_map(function($name) use ($starttoken, $endtoken) {
+            // We only strip out the name of the helper (excluding delimiters)
+            // the user is able to change the delimeters on a per template
+            // basis so they may not be curly braces.
+            return '/\s*' . $starttoken . '\s*'. $name . '\W+.*' . $endtoken . '\s*' . $name . '\s*/';
+        }, $blacklist);
+
+        // This will strip out unwanted helpers from the $source string
+        // before providing it to the original helper function.
+        // E.g.
+        // Before:
+        // "core, move, {{#js}} some nasty JS hack {{/js}}"
+        // After:
+        // "core, move, {{}}"
+        return preg_replace_callback($regexes, function() {
+            return '';
+        }, $string);
+    }
+}
index 564bd9e..960cdf7 100644 (file)
@@ -1647,7 +1647,7 @@ class core_plugin_manager {
         $plugins = array(
             'qformat' => array('blackboard', 'learnwise'),
             'auth' => array('radius', 'fc', 'nntp', 'pam', 'pop3', 'imap'),
-            'block' => array('course_overview', 'messages'),
+            'block' => array('course_overview', 'messages', 'community'),
             'cachestore' => array('memcache'),
             'enrol' => array('authorize'),
             'report' => array('search'),
@@ -1714,7 +1714,7 @@ class core_plugin_manager {
             'block' => array(
                 'activity_modules', 'activity_results', 'admin_bookmarks', 'badges',
                 'blog_menu', 'blog_recent', 'blog_tags', 'calendar_month',
-                'calendar_upcoming', 'comments', 'community',
+                'calendar_upcoming', 'comments',
                 'completionstatus', 'course_list', 'course_summary',
                 'feedback', 'globalsearch', 'glossary_random', 'html',
                 'login', 'lp', 'mentees', 'mnet_hosts', 'myoverview', 'myprofile',
index 87d472e..4253f7d 100644 (file)
@@ -181,20 +181,6 @@ $capabilities = array(
         'clonepermissionsfrom' =>  'moodle/backup:backupcourse'
     ),
 
-    'moodle/backup:backuptargethub' => array(
-
-        'riskbitmask' => RISK_SPAM | RISK_PERSONAL | RISK_XSS,
-
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_COURSE,
-        'archetypes' => array(
-            'editingteacher' => CAP_ALLOW,
-            'manager' => CAP_ALLOW
-        ),
-
-        'clonepermissionsfrom' =>  'moodle/backup:backupcourse'
-    ),
-
     'moodle/backup:backuptargetimport' => array(
 
         'riskbitmask' => RISK_SPAM | RISK_PERSONAL | RISK_XSS,
@@ -311,20 +297,6 @@ $capabilities = array(
         ),
     ),
 
-    'moodle/restore:restoretargethub' => array(
-
-        'riskbitmask' => RISK_SPAM | RISK_PERSONAL | RISK_XSS,
-
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_COURSE,
-        'archetypes' => array(
-            'editingteacher' => CAP_ALLOW,
-            'manager' => CAP_ALLOW
-        ),
-
-        'clonepermissionsfrom' =>  'moodle/restore:restorecourse'
-    ),
-
     'moodle/restore:restoretargetimport' => array(
 
         'riskbitmask' => RISK_SPAM | RISK_PERSONAL | RISK_XSS,
@@ -1987,15 +1959,6 @@ $capabilities = array(
             'editingteacher' => CAP_ALLOW,
             'manager' => CAP_ALLOW
         )
-    ),
-     'moodle/course:publish' => array(
-
-        'captype' => 'write',
-        'riskbitmask' => RISK_SPAM | RISK_PERSONAL,
-        'contextlevel' => CONTEXT_SYSTEM,
-        'archetypes' => array(
-            'manager' => CAP_ALLOW
-        )
     ),
     'moodle/course:markcomplete' => array(
         'captype' => 'write',
@@ -2015,23 +1978,6 @@ $capabilities = array(
             'manager' => CAP_ALLOW
         )
     ),
-    'moodle/community:add' => array(
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_SYSTEM,
-        'archetypes' => array(
-            'manager' => CAP_ALLOW,
-            'teacher' => CAP_ALLOW,
-            'editingteacher' => CAP_ALLOW,
-        )
-    ),
-    'moodle/community:download' => array(
-        'captype' => 'write',
-        'contextlevel' => CONTEXT_SYSTEM,
-        'archetypes' => array(
-            'manager' => CAP_ALLOW,
-            'editingteacher' => CAP_ALLOW,
-        )
-    ),
 
     // Badges.
     'moodle/badges:manageglobalsettings' => array(
index 59cebd4..71f216e 100644 (file)
@@ -284,9 +284,10 @@ function xmldb_main_install() {
     set_role_contextlevels($guestrole,          get_default_contextlevels('guest'));
     set_role_contextlevels($userrole,           get_default_contextlevels('user'));
 
-    // Init theme and JS revisions
+    // Init theme, JS and template revisions.
     set_config('themerev', time());
     set_config('jsrev', time());
+    set_config('templaterev', time());
 
     // No admin setting for this any more, GD is now required, remove in Moodle 2.6.
     set_config('gdversion', 2);
index 16f2a29..1aa73b8 100644 (file)
@@ -3466,6 +3466,60 @@ function xmldb_main_upgrade($oldversion) {
     }
 
     if ($oldversion < 2019083000.01) {
+
+        // If block_community is no longer present, remove it.
+        if (!file_exists($CFG->dirroot . '/blocks/community/communitycourse.php')) {
+            // Drop table that is no longer needed.
+            $table = new xmldb_table('block_community');
+            if ($dbman->table_exists($table)) {
+                $dbman->drop_table($table);
+            }
+
+            // Delete instances.
+            $instances = $DB->get_records_list('block_instances', 'blockname', ['community']);
+            $instanceids = array_keys($instances);
+
+            if (!empty($instanceids)) {
+                $DB->delete_records_list('block_positions', 'blockinstanceid', $instanceids);
+                $DB->delete_records_list('block_instances', 'id', $instanceids);
+                list($sql, $params) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED);
+                $params['contextlevel'] = CONTEXT_BLOCK;
+                $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params);
+
+                $preferences = array();
+                foreach ($instances as $instanceid => $instance) {
+                    $preferences[] = 'block' . $instanceid . 'hidden';
+                    $preferences[] = 'docked_block_instance_' . $instanceid;
+                }
+                $DB->delete_records_list('user_preferences', 'name', $preferences);
+            }
+
+            // Delete the block from the block table.
+            $DB->delete_records('block', array('name' => 'community'));
+
+            // Remove capabilities.
+            capabilities_cleanup('block_community');
+            // Clean config.
+            unset_all_config_for_plugin('block_community');
+
+            // Remove Moodle-level community based capabilities.
+            $capabilitiestoberemoved = ['block/community:addinstance', 'block/community:myaddinstance'];
+            // Delete any role_capabilities for the old roles.
+            $DB->delete_records_list('role_capabilities', 'capability', $capabilitiestoberemoved);
+            // Delete the capability itself.
+            $DB->delete_records_list('capabilities', 'name', $capabilitiestoberemoved);
+        }
+
+        upgrade_main_savepoint(true, 2019083000.01);
+    }
+
+    if ($oldversion < 2019083000.02) {
+        // Remove unused config.
+        unset_config('enablecoursepublishing');
+        upgrade_main_savepoint(true, 2019083000.02);
+    }
+
+    if ($oldversion < 2019083000.04) {
         // Delete "orphaned" subscriptions.
         $sql = "SELECT DISTINCT es.userid
                   FROM {event_subscriptions} es
@@ -3479,7 +3533,7 @@ function xmldb_main_upgrade($oldversion) {
             $DB->execute("DELETE FROM {event_subscriptions} WHERE userid " . $sql, $params);
         }
 
-        upgrade_main_savepoint(true, 2019083000.01);
+        upgrade_main_savepoint(true, 2019083000.04);
     }
 
     return true;
index d894b36..f5d5690 100644 (file)
@@ -187,6 +187,17 @@ class pgsql_native_moodle_database extends moodle_database {
             throw new dml_connection_exception($dberr);
         }
 
+        if (!empty($this->dboptions['dbpersist'])) {
+            // There are rare situations (such as PHP out of memory errors) when open cursors may
+            // not be closed at the end of a connection. When using persistent connections, the
+            // cursors remain open and 'get in the way' of future connections. To avoid this
+            // problem, close all cursors here.
+            $result = pg_query($this->pgsql, 'CLOSE ALL');
+            if ($result) {
+                pg_free_result($result);
+            }
+        }
+
         if (!empty($this->dboptions['dbhandlesoptions'])) {
             /* We don't trust people who just set the dbhandlesoptions, this code checks up on them.
              * These functions do not talk to the server, they use the client library knowledge to determine state.
index ffe8c16..b01fda6 100644 (file)
@@ -36,7 +36,7 @@ $string['pluginname'] = 'Atto HTML editor';
 $string['subplugintype_atto'] = 'Atto plugin';
 $string['subplugintype_atto_plural'] = 'Atto plugins';
 $string['settings'] = 'Atto toolbar settings';
-$string['taskautosavecleanup'] = 'Delete expired autosave drafts from the database.';
+$string['taskautosavecleanup'] = 'Delete expired autosave drafts';
 $string['textrecovered'] = 'A draft version of this text was automatically restored.';
 $string['toolbarconfig'] = 'Toolbar config';
 $string['toolbarconfig_desc'] = 'The list of plugins and the order they are displayed can be configured here. The configuration consists of groups (one per line) followed by the ordered list of plugins for that group. The group is separated from the plugins with an equals sign and the plugins are separated with commas. The group names must be unique and should indicate what the buttons have in common. Button and group names should not be repeated and may only contain alphanumeric characters.';
diff --git a/lib/form/amd/build/submit.min.js b/lib/form/amd/build/submit.min.js
new file mode 100644 (file)
index 0000000..46f722e
Binary files /dev/null and b/lib/form/amd/build/submit.min.js differ
diff --git a/lib/form/amd/build/submit.min.js.map b/lib/form/amd/build/submit.min.js.map
new file mode 100644 (file)
index 0000000..afc8bae
Binary files /dev/null and b/lib/form/amd/build/submit.min.js.map differ
diff --git a/lib/form/amd/src/submit.js b/lib/form/amd/src/submit.js
new file mode 100644 (file)
index 0000000..1e4e7dd
--- /dev/null
@@ -0,0 +1,48 @@
+// 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/>.
+
+/**
+ * Submit button JavaScript. All submit buttons will be automatically disabled once the form is
+ * submitted, unless that submission results in an error/cancelling the submit.
+ *
+ * @module core_form/submit
+ * @package core_form
+ * @copyright 2019 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since 3.8
+ */
+
+/**
+ * Initialises submit buttons.
+ *
+ * @param {String} elementId Form element
+ */
+export const init = (elementId) => {
+    const button = document.getElementById(elementId);
+    button.form.addEventListener('submit', function() {
+        // Only disable it if the browser is really going to another page as a result of the
+        // submit.
+        const disableAction = function() {
+            button.disabled = true;
+        };
+        window.addEventListener('beforeunload', disableAction);
+        // If there is no beforeunload event as a result of this form submit, then the form
+        // submit must have been cancelled, so don't disable the button if the page is
+        // unloaded later.
+        setTimeout(function() {
+            window.removeEventListener('beforeunload', disableAction);
+        }, 0);
+    }, false);
+};
index 8c2c047..51b9700 100644 (file)
         {{/element.frozen}}
     {{/element}}
 {{/ core_form/element-template-inline }}
+{{# js }}
+    {{^element.frozen}}
+        require(['core_form/submit'], function(Submit) {
+            Submit.init("{{ element.id }}");
+        });
+    {{/element.frozen}}
+{{/ js }}
index 058e414..330c8be 100644 (file)
         {{/element.frozen}}
     {{/element}}
 {{/ core_form/element-template }}
+{{# js }}
+    {{^element.frozen}}
+        require(['core_form/submit'], function(Submit) {
+            Submit.init("{{ element.id }}");
+        });
+    {{/element.frozen}}
+{{/ js }}
index fa6bfe5..31cb592 100644 (file)
@@ -38,7 +38,7 @@ class processor implements  \core_analytics\classifier, \core_analytics\regresso
     /**
      * The required version of the python package that performs all calculations.
      */
-    const REQUIRED_PIP_PACKAGE_VERSION = '1.0.0';
+    const REQUIRED_PIP_PACKAGE_VERSION = '2.0.0';
 
     /**
      * The path to the Python bin.
index 76ae27f..7643051 100644 (file)
@@ -1648,7 +1648,7 @@ function purge_all_caches() {
  *        'other'  Purge all other caches?
  */
 function purge_caches($options = []) {
-    $defaults = array_fill_keys(['muc', 'theme', 'lang', 'js', 'filter', 'other'], false);
+    $defaults = array_fill_keys(['muc', 'theme', 'lang', 'js', 'template', 'filter', 'other'], false);
     if (empty(array_filter($options))) {
         $options = array_fill_keys(array_keys($defaults), true); // Set all options to true.
     } else {
@@ -1666,6 +1666,9 @@ function purge_caches($options = []) {
     if ($options['js']) {
         js_reset_all_caches();
     }
+    if ($options['template']) {</