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("