diff --git a/enrol/tests/behat/add_to_group.feature b/enrol/tests/behat/add_to_group.feature
index 0324747e141..c5fdca1ab48 100644
--- a/enrol/tests/behat/add_to_group.feature
+++ b/enrol/tests/behat/add_to_group.feature
@@ -1,4 +1,4 @@
-@core_enrol @core_group @doit
+@core_enrol @core_group
Feature: Users can be added to multiple groups at once
In order to manage group membership effectively
As a user
diff --git a/group/classes/output/user_groups_editable.php b/group/classes/output/user_groups_editable.php
index 12c8c5749f2..f21be027eb0 100644
--- a/group/classes/output/user_groups_editable.php
+++ b/group/classes/output/user_groups_editable.php
@@ -24,11 +24,12 @@
namespace core_group\output;
-use context_system;
use context_course;
use core_user;
use core_external;
-use moodle_exception;
+use coding_exception;
+
+defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/group/lib.php');
@@ -49,7 +50,11 @@ class user_groups_editable extends \core\output\inplace_editable {
/**
* Constructor.
*
- * @param \stdClass|core_tag_tag $tag
+ * @param \stdClass $course The current course
+ * @param \context $context The course context
+ * @param \stdClass $user The current user
+ * @param \stdClass[] $coursegroups The list of course groups from groups_get_all_groups with membership.
+ * @param string $value JSON Encoded list of group ids.
*/
public function __construct($course, $context, $user, $coursegroups, $value) {
// Check capabilities to get editable value.
@@ -83,7 +88,7 @@ class user_groups_editable extends \core\output\inplace_editable {
* Export this data so it can be used as the context for a mustache template.
*
* @param \renderer_base $output
- * @return \stdClass
+ * @return array
*/
public function export_for_template(\renderer_base $output) {
$listofgroups = [];
diff --git a/group/lib.php b/group/lib.php
index 67d04ddfbf9..5df273b81fc 100644
--- a/group/lib.php
+++ b/group/lib.php
@@ -1097,6 +1097,14 @@ function groups_sync_with_enrolment($enrolname, $courseid = 0, $gidfield = 'cust
return $affectedusers;
}
+/**
+ * Callback for inplace editable API.
+ *
+ * @param string $itemtype - Only user_groups is supported.
+ * @param string $itemid - Userid and groupid separated by a :
+ * @param string $newvalue - json encoded list of groupids.
+ * @return \core\output\inplace_editable
+ */
function core_group_inplace_editable($itemtype, $itemid, $newvalue) {
if ($itemtype === 'user_groups') {
return \core_group\output\user_groups_editable::update($itemid, $newvalue);
diff --git a/lib/amd/build/form-autocomplete.min.js b/lib/amd/build/form-autocomplete.min.js
index 7e9a903f0ba..05b38d0145d 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:44,UP:38},g=function(b,c){var d=a(document.getElementById(c.selectionId)),e=d.children("[aria-selected=true]").length;for(b%=e;b<0;)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)},i=function(a){"undefined"!=typeof M.core_formchangechecker&&M.core_formchangechecker.set_form_changed(),a.change()},j=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),i(e)},k=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;b<0;)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)},l=function(b){var c=a(document.getElementById(b.suggestionsId)),d=c.children("[aria-selected=true]"),e=c.children("[aria-hidden=false]").index(d);k(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.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)},o=function(b){var c=a(document.getElementById(b.suggestionsId)),d=c.children("[aria-selected=true]"),e=c.children("[aria-hidden=false]").index(d);k(e-1,b)},p=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)},q=function(b,f,g,h){var i=a(document.getElementById(f.inputId)),j=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){j.replaceWith(d),j=a(document.getElementById(f.suggestionsId)),j.show().attr("aria-hidden",!1),j.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||k(0,f):c.get_string("nosuggestions","form").done(function(a){j.html(a)})}).fail(e.exception)},r=function(b,c,d){var e=a(document.getElementById(c.inputId)),f=e.val(),g=f.split(","),j=!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&&(j=!0,a(c).prop("selected",!0))}),!j)){var f=a("