diff --git a/enrol/meta/lib.php b/enrol/meta/lib.php
index 5659d9fa21a..4695835d17b 100644
--- a/enrol/meta/lib.php
+++ b/enrol/meta/lib.php
@@ -132,21 +132,30 @@ class enrol_meta_plugin extends enrol_plugin {
* Add new instance of enrol plugin.
* @param object $course
* @param array $fields instance fields
- * @return int id of new instance, null if can not be created
+ * @return int id of last instance, null if can not be created
*/
public function add_instance($course, array $fields = null) {
global $CFG;
require_once("$CFG->dirroot/enrol/meta/locallib.php");
- if (!empty($fields['customint2']) && $fields['customint2'] == ENROL_META_CREATE_GROUP) {
- $context = context_course::instance($course->id);
- require_capability('moodle/course:managegroups', $context);
- $groupid = enrol_meta_create_new_group($course->id, $fields['customint1']);
- $fields['customint2'] = $groupid;
+ // Support creating multiple at once.
+ if (is_array($fields['customint1'])) {
+ $courses = array_unique($fields['customint1']);
+ } else {
+ $courses = array($fields['customint1']);
}
+ foreach ($courses as $courseid) {
+ if (!empty($fields['customint2']) && $fields['customint2'] == ENROL_META_CREATE_GROUP) {
+ $context = context_course::instance($course->id);
+ require_capability('moodle/course:managegroups', $context);
+ $groupid = enrol_meta_create_new_group($course->id, $courseid);
+ $fields['customint2'] = $groupid;
+ }
- $result = parent::add_instance($course, $fields);
+ $fields['customint1'] = $courseid;
+ $result = parent::add_instance($course, $fields);
+ }
enrol_meta_sync($course->id);
@@ -258,7 +267,7 @@ class enrol_meta_plugin extends enrol_plugin {
}
// TODO: this has to be done via ajax or else it will fail very badly on large sites!
- $courses = array('' => get_string('choosedots'));
+ $courses = array();
$select = ', ' . context_helper::get_preload_record_columns_sql('ctx');
$join = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
@@ -313,10 +322,14 @@ class enrol_meta_plugin extends enrol_plugin {
public function edit_instance_form($instance, MoodleQuickForm $mform, $coursecontext) {
global $DB;
- $courses = $this->get_course_options($instance, $coursecontext);
$groups = $this->get_group_options($coursecontext);
- $mform->addElement('select', 'customint1', get_string('linkedcourse', 'enrol_meta'), $courses);
+ $options = array(
+ 'requiredcapabilities' => array('enrol/meta:selectaslinked'),
+ 'multiple' => true,
+ 'excludecourseid' => $coursecontext->instanceid
+ );
+ $mform->addElement('course', 'customint1', get_string('linkedcourse', 'enrol_meta'), $options);
$mform->addRule('customint1', get_string('required'), 'required', null, 'client');
if (!empty($instance->id)) {
$mform->freeze('customint1');
@@ -343,28 +356,25 @@ class enrol_meta_plugin extends enrol_plugin {
$c = false;
if (!empty($data['customint1'])) {
- $c = $DB->get_record('course', array('id' => $data['customint1']));
- }
-
- if (!$c) {
- $errors['customint1'] = get_string('required');
- } else {
- $coursecontext = context_course::instance($c->id);
- $existing = $DB->get_records('enrol', array('enrol' => 'meta', 'courseid' => $thiscourseid), '', 'customint1, id');
- if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
- $errors['customint1'] = get_string('error');
- } else if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
- $errors['customint1'] = get_string('error');
- } else if ($c->id == SITEID or $c->id == $thiscourseid or isset($existing[$c->id])) {
- $errors['customint1'] = get_string('error');
+ foreach ($data['customint1'] as $courseid) {
+ $c = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
+ $coursecontext = context_course::instance($c->id);
+ $existing = $DB->get_records('enrol', array('enrol' => 'meta', 'courseid' => $thiscourseid), '', 'customint1, id');
+ if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
+ $errors['customint1'] = get_string('error');
+ } else if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
+ $errors['customint1'] = get_string('error');
+ } else if ($c->id == SITEID or $c->id == $thiscourseid or isset($existing[$c->id])) {
+ $errors['customint1'] = get_string('error');
+ }
}
+ } else {
+ $errors['customint1'] = get_string('required');
}
- $validcourses = array_keys($this->get_course_options($instance, $context));
$validgroups = array_keys($this->get_group_options($context));
$tovalidate = array(
- 'customint1' => $validcourses,
'customint2' => $validgroups
);
$typeerrors = $this->validate_param_types($data, $tovalidate);
diff --git a/enrol/meta/tests/behat/enrol_meta.feature b/enrol/meta/tests/behat/enrol_meta.feature
index 9a07371da69..c5df107038e 100644
--- a/enrol/meta/tests/behat/enrol_meta.feature
+++ b/enrol/meta/tests/behat/enrol_meta.feature
@@ -1,4 +1,4 @@
-@enrol @enrol_meta
+@enrol @enrol_meta @javascript
Feature: Enrolments are synchronised with meta courses
In order to simplify enrolments in parent courses
As a teacher
@@ -13,21 +13,21 @@ Feature: Enrolments are synchronised with meta courses
| student4 | Student | 4 | student4@asd.com |
And the following "courses" exist:
| fullname | shortname |
- | Course 1 | C1 |
- | Course 2 | C2 |
- | Course 3 | C3 |
+ | Course 1 | C1C1 |
+ | Course 2 | C2C2 |
+ | Course 3 | C3C3 |
And the following "groups" exist:
| name | course | idnumber |
- | Groupcourse 1 | C3 | G1 |
- | Groupcourse 2 | C3 | G2 |
+ | Groupcourse 1 | C3C3 | G1 |
+ | Groupcourse 2 | C3C3 | G2 |
And the following "course enrolments" exist:
| user | course | role |
- | student1 | C1 | student |
- | student2 | C1 | student |
- | student3 | C1 | student |
- | student4 | C1 | student |
- | student1 | C2 | student |
- | student2 | C2 | student |
+ | student1 | C1C1 | student |
+ | student2 | C1C1 | student |
+ | student3 | C1C1 | student |
+ | student4 | C1C1 | student |
+ | student1 | C2C2 | student |
+ | student2 | C2C2 | student |
And I log in as "admin"
And I navigate to "Manage enrol plugins" node in "Site administration > Plugins > Enrolments"
And I click on "Enable" "link" in the "Course meta link" "table_row"
@@ -37,7 +37,7 @@ Feature: Enrolments are synchronised with meta courses
Scenario: Add meta enrolment instance without groups
When I follow "Course 3"
And I add "Course meta link" enrolment method with:
- | Link course | Course 1 |
+ | Link course | C1C1 |
And I navigate to "Enrolled users" node in "Course administration > Users"
Then I should see "Student 1"
And I should see "Student 4"
@@ -45,18 +45,13 @@ Feature: Enrolments are synchronised with meta courses
Scenario: Add meta enrolment instance with groups
When I follow "Course 3"
- And I navigate to "Enrolment methods" node in "Course administration > Users"
- And I select "Course meta link" from the "Add method" singleselect
- And I set the following fields to these values:
- | Link course | Course 1 |
+ And I add "Course meta link" enrolment method with:
+ | Link course | C1C1 |
| Add to group | Groupcourse 1 |
- And I press "Add method"
- And I set the field "Add method" to "Course meta link"
- And I press "Go"
- And I set the following fields to these values:
- | Link course | Course 2 |
+ And I follow "Course 3"
+ And I add "Course meta link" enrolment method with:
+ | Link course | C2C2 |
| Add to group | Groupcourse 2 |
- And I press "Add method"
And I navigate to "Enrolled users" node in "Course administration > Users"
Then I should see "Groupcourse 1" in the "Student 1" "table_row"
And I should see "Groupcourse 1" in the "Student 2" "table_row"
@@ -69,13 +64,9 @@ Feature: Enrolments are synchronised with meta courses
Scenario: Add meta enrolment instance with auto-created groups
When I follow "Course 3"
- And I navigate to "Enrolment methods" node in "Course administration > Users"
- And I set the field "Add method" to "Course meta link"
- And I press "Go"
- And I set the following fields to these values:
- | Link course | Course 1 |
+ And I add "Course meta link" enrolment method with:
+ | Link course | C1C1 |
| Add to group | Create new group |
- And I press "Add method"
And I navigate to "Enrolled users" node in "Course administration > Users"
Then I should see "Course 1 course" in the "Student 1" "table_row"
And I should see "Course 1 course" in the "Student 2" "table_row"
@@ -86,17 +77,12 @@ Feature: Enrolments are synchronised with meta courses
Scenario: Backup and restore of meta enrolment instance
When I follow "Course 3"
- And I navigate to "Enrolment methods" node in "Course administration > Users"
- And I set the field "Add method" to "Course meta link"
- And I press "Go"
- And I set the following fields to these values:
- | Link course | Course 1 |
+ And I add "Course meta link" enrolment method with:
+ | Link course | C1C1 |
| Add to group | Groupcourse 1 |
- And I press "Add method"
- And I select "Course meta link" from the "Add method" singleselect
- And I set the following fields to these values:
- | Link course | Course 2 |
- And I press "Add method"
+ And I follow "Course 3"
+ And I add "Course meta link" enrolment method with:
+ | Link course | C2C2 |
When I backup "Course 3" course using this options:
| Confirmation | Filename | test_backup.mbz |
And I click on "Restore" "link" in the "test_backup.mbz" "table_row"
diff --git a/lib/amd/build/form-autocomplete.min.js b/lib/amd/build/form-autocomplete.min.js
index f6f5d3e15e5..d024ddb7a1a 100644
--- a/lib/amd/build/form-autocomplete.min.js
+++ b/lib/amd/build/form-autocomplete.min.js
@@ -1 +1 @@
-define(["jquery","core/log","core/str","core/templates","core/notification"],function(a,b,c,d,e){var f={DOWN:40,ENTER:13,SPACE:32,ESCAPE:27,COMMA:188,UP:38},g=function(b,c){var d=a(document.getElementById(c.selectionId)),e=d.children("[aria-selected=true]").length;for(b%=e;0>b;)b+=e;var f=a(d.children("[aria-selected=true]").get(b)),g=c.selectionId+"-"+b;d.children().attr("data-active-selection",!1).attr("id",""),f.attr("data-active-selection",!0).attr("id",g),d.attr("aria-activedescendant",g)},h=function(b,c,f){var h=[],i=a(document.getElementById(c.selectionId)),j=i.attr("aria-activedescendant"),k=!1;j&&(k=a(document.getElementById(j)).attr("data-value")),f.children("option").each(function(b,c){a(c).prop("selected")&&h.push({label:a(c).html(),value:a(c).attr("value")})});var l=a.extend({items:h},b,c);d.render("core/form_autocomplete_selection",l).done(function(b){i.empty().append(a(b).html()),k!==!1&&i.children("[aria-selected=true]").each(function(b,d){a(d).attr("data-value")===k&&g(b,c)})}).fail(e.exception),f.change()},i=function(b,c,d,e){var f=a(d).attr("data-value");b.multiple&&e.children("option").each(function(b,c){a(c).attr("value")==f&&(a(c).prop("selected",!1),a(c).attr("data-iscustom")&&a(c).remove())}),h(b,c,e)},j=function(b,c){var d=a(document.getElementById(c.inputId)),e=a(document.getElementById(c.suggestionsId)),f=e.children("[aria-hidden=false]").length;for(b%=f;0>b;)b+=f;var g=a(e.children("[aria-hidden=false]").get(b)),h=a(e.children("[role=option]")).index(g),i=c.suggestionsId+"-"+h;e.children().attr("aria-selected",!1).attr("id",""),g.attr("aria-selected",!0).attr("id",i),d.attr("aria-activedescendant",i);var j=g.offset().top-e.offset().top+e.scrollTop()-e.height()/2;e.animate({scrollTop:j},100)},k=function(b){var c=a(document.getElementById(b.suggestionsId)),d=c.children("[aria-selected=true]"),e=c.children("[aria-hidden=false]").index(d);j(e+1,b)},l=function(b){var c=a(document.getElementById(b.selectionId)),d=c.children("[data-active-selection=true]");if(!d)return void g(0,b);var e=c.children("[aria-selected=true]").index(d);g(e-1,b)},m=function(b){var c=a(document.getElementById(b.selectionId)),d=c.children("[data-active-selection=true]");if(!d)return void g(0,b);var e=c.children("[aria-selected=true]").index(d);g(e+1,b)},n=function(b){var c=a(document.getElementById(b.suggestionsId)),d=c.children("[aria-selected=true]"),e=c.children("[aria-hidden=false]").index(d);j(e-1,b)},o=function(b){var c=a(document.getElementById(b.inputId)),d=a(document.getElementById(b.suggestionsId));c.attr("aria-expanded",!1).attr("aria-activedescendant",b.selectionId),d.hide().attr("aria-hidden",!0)},p=function(b,f,g,h){var i=a(document.getElementById(f.inputId)),k=a(document.getElementById(f.suggestionsId)),l=!1,m=[];h.children("option").each(function(b,c){a(c).prop("selected")!==!0&&(m[m.length]={label:c.innerHTML,value:a(c).attr("value")})});var n=f.caseSensitive?g:g.toLocaleLowerCase(),o=a.extend({options:m},b,f);d.render("core/form_autocomplete_suggestions",o).done(function(d){k.replaceWith(d),k=a(document.getElementById(f.suggestionsId)),k.show().attr("aria-hidden",!1),k.children().each(function(c,d){d=a(d),b.caseSensitive&&d.text().indexOf(n)>-1||!b.caseSensitive&&d.text().toLocaleLowerCase().indexOf(n)>-1?(d.show().attr("aria-hidden",!1),l=!0):d.hide().attr("aria-hidden",!0)}),i.attr("aria-expanded",!0),l?b.tags||j(0,f):c.get_string("nosuggestions","form").done(function(a){k.html(a)})}).fail(e.exception)},q=function(b,c,d){var e=a(document.getElementById(c.inputId)),f=e.val(),g=f.split(","),i=!1;a.each(g,function(c,e){if(e=e.trim(),""!==e&&(b.multiple||d.children("option").prop("selected",!1),d.children("option").each(function(b,c){a(c).attr("value")==e&&(i=!0,a(c).prop("selected",!0))}),!i)){var f=a("