diff --git a/admin/tool/brickfield/classes/local/areas/core_course/base.php b/admin/tool/brickfield/classes/local/areas/core_course/base.php
index 8367df6c369..3afb2733216 100644
--- a/admin/tool/brickfield/classes/local/areas/core_course/base.php
+++ b/admin/tool/brickfield/classes/local/areas/core_course/base.php
@@ -108,7 +108,7 @@ abstract class base extends area_base {
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
if ($componentinfo->tablename == 'course_sections') {
- return new \moodle_url('/course/editsection.php', ['id' => $componentinfo->itemid, 'sr' => '']);
+ return new \moodle_url('/course/editsection.php', ['id' => $componentinfo->itemid]);
} else if ($componentinfo->tablename == 'course_categories') {
return new \moodle_url('/course/editcategory.php', ['id' => $componentinfo->itemid]);
} else {
diff --git a/admin/tool/brickfield/classes/local/areas/module_area_base.php b/admin/tool/brickfield/classes/local/areas/module_area_base.php
index 71673d16aca..edfc956712b 100644
--- a/admin/tool/brickfield/classes/local/areas/module_area_base.php
+++ b/admin/tool/brickfield/classes/local/areas/module_area_base.php
@@ -108,6 +108,6 @@ abstract class module_area_base extends area_base {
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
- return new \moodle_url('/course/mod.php', ['update' => $componentinfo->cmid, 'sr' => 0, 'sesskey' => sesskey()]);
+ return new \moodle_url('/course/mod.php', ['update' => $componentinfo->cmid, 'sr' => null, 'sesskey' => sesskey()]);
}
}
diff --git a/availability/condition/completion/tests/behat/availability_completion_previous.feature b/availability/condition/completion/tests/behat/availability_completion_previous.feature
index f70eb6b1a73..8dff21f5336 100644
--- a/availability/condition/completion/tests/behat/availability_completion_previous.feature
+++ b/availability/condition/completion/tests/behat/availability_completion_previous.feature
@@ -121,7 +121,7 @@ Feature: Confirm that availability_completion works with previous activity setti
Then I should see "Not available unless: The activity Page2 is marked complete" in the "region-main" "region"
# Remove Page 2 and check Section 4 depends now on Page1.
- When I turn editing mode on
+ When I am on "Course 1" course homepage with editing mode on
And I change window size to "large"
And I delete "Page2" activity
And I turn editing mode off
@@ -175,11 +175,11 @@ Feature: Confirm that availability_completion works with previous activity setti
And I press "Save changes"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
- When I turn editing mode off
- Then I should see "Not available unless: The activity Page1 is marked complete" in the "region-main" "region"
+ And I turn editing mode off
+ And I should see "Not available unless: The activity Page1 is marked complete" in the "region-main" "region"
# Set section 5 restriction to Previous Activity with completion.
- When I turn editing mode on
+ And I am on "Course 1" course homepage with editing mode on
And I edit the section "5"
And I expand all fieldsets
And I click on "Add restriction..." "button"
@@ -187,18 +187,18 @@ Feature: Confirm that availability_completion works with previous activity setti
And I click on "Displayed if student doesn't meet this condition • Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
- Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
+ And I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
- When I turn editing mode off
+ And I turn editing mode off
Then I should see "Not available unless: The activity Page3 is marked complete" in the "region-main" "region"
# Test if I disable completion tracking on Page3 section 5 depends on Page2.
- When I turn editing mode on
+ And I am on "Course 1" course homepage with editing mode on
And I open "Page3" actions menu
And I click on "Edit settings" "link" in the "Page3" activity
And I set the following fields to these values:
| None | 1 |
And I press "Save and return to course"
- When I turn editing mode off
- Then I should see "Not available unless: The activity Page2 is marked complete" in the "region-main" "region"
+ And I turn editing mode off
+ And I should see "Not available unless: The activity Page2 is marked complete" in the "region-main" "region"
diff --git a/availability/tests/behat/display_availability.feature b/availability/tests/behat/display_availability.feature
index 3ea2a02f49b..38d17e4e92b 100644
--- a/availability/tests/behat/display_availability.feature
+++ b/availability/tests/behat/display_availability.feature
@@ -126,7 +126,8 @@ Feature: display_availability
And I press "Save changes"
# Section 2 is the same but hidden from students
- When I edit the section "2"
+ And I am on "Course 1" course homepage
+ And I edit the section "2"
And I expand all fieldsets
And I press "Add restriction..."
And I click on "Date" "button" in the "Add restriction..." "dialogue"
diff --git a/course/amd/build/actions.min.js b/course/amd/build/actions.min.js
index 512f61b7f6c..83f0b11c331 100644
--- a/course/amd/build/actions.min.js
+++ b/course/amd/build/actions.min.js
@@ -6,6 +6,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.3
*/
-define("core_course/actions",["jquery","core/ajax","core/templates","core/notification","core/str","core/url","core/yui","core/modal_copy_to_clipboard","core/modal_save_cancel","core/modal_events","core/key_codes","core/log","core_courseformat/courseeditor","core/event_dispatcher","core_course/events"],(function($,ajax,templates,notification,str,url,Y,ModalCopyToClipboard,ModalSaveCancel,ModalEvents,KeyCodes,log,editor,EventDispatcher,CourseEvents){const componentActions=["moveSection","moveCm","addSection","deleteSection","cmDelete","cmDuplicate","sectionHide","sectionShow","cmHide","cmShow","cmStealth","sectionHighlight","sectionUnhighlight","cmMoveRight","cmMoveLeft","cmNoGroups","cmVisibleGroups","cmSeparateGroups"],courseeditor=editor.getCurrentCourseEditor();let formatname;var CSS_EDITINPROGRESS="editinprogress",CSS_EDITINGMOVE="editing_move",SELECTOR={ACTIVITYLI:"li.activity",ACTIONAREA:".actions",ACTIVITYACTION:"a.cm-edit-action",MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",TOGGLE:".toggle-display,.dropdown-toggle",SECTIONLI:"li.section",SECTIONACTIONMENU:".section_action_menu",SECTIONITEM:'[data-for="section_title"]',ADDSECTIONS:".changenumsections [data-add-sections]",SECTIONBADGES:'[data-region="sectionbadges"]'};Y.use("moodle-course-coursebase",(function(){var courseformatselector=M.course.format.get_section_selector();courseformatselector&&(SELECTOR.SECTIONLI=courseformatselector)}));const dispatchEvent=function(eventName,detail,container,options){return container instanceof Element||void 0===container.get||(container=container.get(0)),EventDispatcher.dispatchEvent(eventName,detail,container,options)};var getModuleId=function(element){const item=element.get(0);if(item.dataset.id)return item.dataset.id;let id;return Y.use("moodle-course-util",(function(Y){id=Y.Moodle.core_course.util.cm.getId(Y.Node(item))})),id},addActivitySpinner=function(activity){activity.addClass(CSS_EDITINPROGRESS);var actionarea=activity.find(SELECTOR.ACTIONAREA).get(0);if(actionarea){var spinner=M.util.add_spinner(Y,Y.Node(actionarea));return spinner.show(),void 0!==activity.data("id")&&courseeditor.dispatch("cmLock",[activity.data("id")],!0),spinner}return null},addSectionSpinner=function(sectionelement){sectionelement.addClass(CSS_EDITINPROGRESS);var actionarea=sectionelement.find(SELECTOR.SECTIONACTIONMENU).get(0);if(actionarea){var spinner=M.util.add_spinner(Y,Y.Node(actionarea));return spinner.show(),void 0!==sectionelement.data("id")&&courseeditor.dispatch("sectionLock",[sectionelement.data("id")],!0),spinner}return null},addSectionLightbox=function(sectionelement){const item=sectionelement.get(0);var lightbox=M.util.add_lightbox(Y,Y.Node(item));return"section"==item.dataset.for&&item.dataset.id&&(courseeditor.dispatch("sectionLock",[item.dataset.id],!0),lightbox.setAttribute("data-state","section"),lightbox.setAttribute("data-state-id",item.dataset.id)),lightbox.show(),lightbox},removeSpinner=function(element,spinner,delay){window.setTimeout((function(){if(element.removeClass(CSS_EDITINPROGRESS),spinner&&spinner.hide(),void 0!==element.data("id")){const mutation="section"===element.data("for")?"sectionLock":"cmLock";courseeditor.dispatch(mutation,[element.data("id")],!1)}}),delay)},removeLightbox=function(lightbox,delay){lightbox&&window.setTimeout((function(){lightbox.hide(),lightbox.getAttribute("data-state")&&courseeditor.dispatch("".concat(lightbox.getAttribute("data-state"),"Lock"),[lightbox.getAttribute("data-state-id")],!1)}),delay)},initActionMenu=function(elementid){Y.use("moodle-course-coursebase",(function(){M.course.coursebase.invoke_function("setup_for_resource","#"+elementid)})),M.core.actionmenu&&M.core.actionmenu.newDOMNode&&M.core.actionmenu.newDOMNode(Y.one("#"+elementid))},editModule=function(moduleElement,cmid,target){var lightbox,action=target.attr("data-action"),spinner=addActivitySpinner(moduleElement),promises=ajax.call([{methodname:"core_course_edit_module",args:{id:cmid,action:action,sectionreturn:target.attr("data-sectionreturn")?target.attr("data-sectionreturn"):0}}],!0);"duplicate"===action&&(lightbox=addSectionLightbox(target.closest(SELECTOR.SECTIONLI))),$.when.apply($,promises).done((function(data){var mainElement,tabables,isInside,foundElement,elementToFocus=(mainElement=moduleElement,tabables=$("a:visible"),isInside=!1,foundElement=null,tabables.each((function(){if($.contains(mainElement[0],this))isInside=!0;else if(isInside)return foundElement=this,!1;return!0})),foundElement);moduleElement.replaceWith(data);let affectedids=[];$("
"+data+"
").find(SELECTOR.ACTIVITYLI).each((function(index){initActionMenu($(this).attr("id")),0===index&&(!function(elementId,action){var mainelement=$("#"+elementId),selector="[data-action="+action+"]";"groupsseparate"!==action&&"groupsvisible"!==action&&"groupsnone"!==action||(selector="[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]"),mainelement.find(selector).is(":visible")?mainelement.find(selector).focus():mainelement.find(SELECTOR.MENU).find(SELECTOR.TOGGLE).focus()}($(this).attr("id"),action),elementToFocus=null),affectedids.push(getModuleId($(this)))})),elementToFocus&&elementToFocus.focus(),removeSpinner(moduleElement,spinner,400),removeLightbox(lightbox,400),moduleElement.trigger($.Event("coursemoduleedited",{ajaxreturn:data,action:action})),courseeditor.dispatch("legacyActivityAction",action,cmid,affectedids)})).fail((function(ex){removeSpinner(moduleElement,spinner),removeLightbox(lightbox);var e=$.Event("coursemoduleeditfailed",{exception:ex,action:action});moduleElement.trigger(e),e.isDefaultPrevented()||notification.exception(ex)}))},refreshModule=function(element,cmid,sectionreturn){void 0===sectionreturn&&(sectionreturn=courseeditor.sectionReturn);const activityElement=$(element);var spinner=addActivitySpinner(activityElement),promises=ajax.call([{methodname:"core_course_get_module",args:{id:cmid,sectionreturn:sectionreturn}}],!0);return new Promise(((resolve,reject)=>{$.when.apply($,promises).done((function(data){removeSpinner(activityElement,spinner,400),replaceActivityHtmlWith(data),resolve(data)})).fail((function(){removeSpinner(activityElement,spinner),reject()}))}))},confirmDeleteModule=function(mainelement,onconfirm){var modtypename=mainelement.attr("class").match(/modtype_([^\s]*)/)[1],modulename=function(element){var name;Y.use("moodle-course-util",(function(Y){name=Y.Moodle.core_course.util.cm.getName(Y.Node(element.get(0)))}));const state=courseeditor.state,cmid=getModuleId(element);var _state$cm$get;return!name&&state&&cmid&&(name=null===(_state$cm$get=state.cm.get(cmid))||void 0===_state$cm$get?void 0:_state$cm$get.name),name}(mainelement);str.get_string("pluginname",modtypename).done((function(pluginname){var plugindata={type:pluginname,name:modulename};str.get_strings([{key:"confirm",component:"core"},{key:null===modulename?"deletechecktype":"deletechecktypename",param:plugindata},{key:"yes"},{key:"no"}]).done((function(s){notification.confirm(s[0],s[1],s[2],s[3],onconfirm)}))}))},replaceActionItem=function(actionitem,image,stringname,stringcomponent,newaction){var stringRequests=[{key:stringname,component:stringcomponent}];return str.get_strings(stringRequests).then((function(strings){return actionitem.find("span.menu-action-text").html(strings[0]),templates.renderPix(image,"core")})).then((function(pixhtml){actionitem.find(".icon").replaceWith(pixhtml),actionitem.attr("data-action",newaction)})).catch(notification.exception)},defaultEditSectionHandler=function(sectionElement,actionItem,data,courseformat,sectionid){var action=actionItem.attr("data-action");if("hide"===action||"show"===action){if("hide"===action?(sectionElement.addClass("hidden"),setSectionBadge(sectionElement[0],"hiddenfromstudents",!0,!1),replaceActionItem(actionItem,"i/show","showfromothers","format_"+courseformat,"show")):(setSectionBadge(sectionElement[0],"hiddenfromstudents",!1,!1),sectionElement.removeClass("hidden"),replaceActionItem(actionItem,"i/hide","hidefromothers","format_"+courseformat,"hide")),void 0!==data.modules)for(var i in data.modules)replaceActivityHtmlWith(data.modules[i]);void 0!==data.section_availability&§ionElement.find(".section_availability").first().replaceWith(data.section_availability);void 0!==courseeditor.state.section.get(sectionid)&&courseeditor.dispatch("sectionState",[sectionid])}else if("setmarker"===action){var oldmarker=$(SELECTOR.SECTIONLI+".current"),oldActionItem=oldmarker.find(SELECTOR.SECTIONACTIONMENU+" a[data-action=removemarker]");oldmarker.removeClass("current"),replaceActionItem(oldActionItem,"i/marker","highlight","core","setmarker"),sectionElement.addClass("current"),replaceActionItem(actionItem,"i/marked","highlightoff","core","removemarker"),courseeditor.dispatch("legacySectionAction",action,sectionid),setSectionBadge(sectionElement[0],"iscurrent",!0,!0)}else"removemarker"===action&&(sectionElement.removeClass("current"),replaceActionItem(actionItem,"i/marker","highlight","core","setmarker"),courseeditor.dispatch("legacySectionAction",action,sectionid),setSectionBadge(sectionElement[0],"iscurrent",!1,!0))};var replaceActivityHtmlWith=function(activityHTML){$("
');return modalBody.find("label").html(strNumberSections),modalBody.html()})).then((body=>ModalSaveCancel.create({body:body,title:modalTitle}))).then((function(modal){var numSections=$(modal.getBody()).find("#add_section_numsections"),addSections=function(){""+parseInt(numSections.val())===numSections.val()&&parseInt(numSections.val())>=1&&(document.location=trigger.attr("href")+"&numsections="+parseInt(numSections.val()))};return modal.setSaveButtonText(modalTitle),modal.getRoot().on(ModalEvents.shown,(function(){numSections.focus().select().on("keydown",(function(e){e.keyCode===KeyCodes.enter&&addSections()}))})),modal.getRoot().on(ModalEvents.save,(function(e){e.preventDefault(),addSections()})),trigger.on("click",(e=>{e.preventDefault(),modal.show()})),modal})).catch(notification.exception)},replaceSectionActionItem:function(sectionelement,selector,image,stringname,stringcomponent,newaction){log.debug("replaceSectionActionItem() is deprecated and will be removed.");var actionitem=sectionelement.find(SELECTOR.SECTIONACTIONMENU+" "+selector);replaceActionItem(actionitem,image,stringname,stringcomponent,newaction)},refreshModule:refreshModule,refreshSection:function(element,sectionid,sectionreturn){void 0===sectionreturn&&(sectionreturn=courseeditor.sectionReturn);const sectionElement=$(element),promises=ajax.call([{methodname:"core_course_edit_section",args:{id:sectionid,action:"refresh",sectionreturn:sectionreturn}}],!0);var spinner=addSectionSpinner(sectionElement);return new Promise(((resolve,reject)=>{$.when.apply($,promises).done((dataencoded=>{removeSpinner(sectionElement,spinner);const data=$.parseJSON(dataencoded),newSectionElement=$(data.content);sectionElement.replaceWith(newSectionElement),$("".concat(SELECTOR.SECTIONLI,"#").concat(sectionid," ").concat(SELECTOR.ACTIVITYLI)).each(((index,activity)=>{initActionMenu(activity.data("id"))}));dispatchEvent(CourseEvents.sectionRefreshed,{ajaxreturn:data,action:"refresh",newSectionElement:newSectionElement.get(0)},newSectionElement).defaultPrevented||defaultEditSectionHandler(newSectionElement,$(SELECTOR.SECTIONLI+"#"+sectionid),data,formatname,sectionid),resolve(data)})).fail((ex=>{dispatchEvent("coursesectionrefreshfailed",{exception:ex,action:"refresh"},sectionElement).defaultPrevented||notification.exception(ex),reject()}))}))}}}));
//# sourceMappingURL=actions.min.js.map
\ No newline at end of file
diff --git a/course/amd/build/actions.min.js.map b/course/amd/build/actions.min.js.map
index 5a2abddf29e..a68b4bae2de 100644
--- a/course/amd/build/actions.min.js.map
+++ b/course/amd/build/actions.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"actions.min.js","sources":["../src/actions.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Various actions on modules and sections in the editing mode - hiding, duplicating, deleting, etc.\n *\n * @module core_course/actions\n * @copyright 2016 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.3\n */\ndefine(\n [\n 'jquery',\n 'core/ajax',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/url',\n 'core/yui',\n 'core/modal_copy_to_clipboard',\n 'core/modal_save_cancel',\n 'core/modal_events',\n 'core/key_codes',\n 'core/log',\n 'core_courseformat/courseeditor',\n 'core/event_dispatcher',\n 'core_course/events'\n ],\n function(\n $,\n ajax,\n templates,\n notification,\n str,\n url,\n Y,\n ModalCopyToClipboard,\n ModalSaveCancel,\n ModalEvents,\n KeyCodes,\n log,\n editor,\n EventDispatcher,\n CourseEvents\n ) {\n\n // Eventually, core_courseformat/local/content/actions will handle all actions for\n // component compatible formats and the default actions.js won't be necessary anymore.\n // Meanwhile, we filter the migrated actions.\n const componentActions = [\n 'moveSection', 'moveCm', 'addSection', 'deleteSection', 'cmDelete', 'cmDuplicate', 'sectionHide', 'sectionShow',\n 'cmHide', 'cmShow', 'cmStealth', 'sectionHighlight', 'sectionUnhighlight', 'cmMoveRight', 'cmMoveLeft',\n 'cmNoGroups', 'cmVisibleGroups', 'cmSeparateGroups',\n ];\n\n // The course reactive instance.\n const courseeditor = editor.getCurrentCourseEditor();\n\n // The current course format name (loaded on init).\n let formatname;\n\n var CSS = {\n EDITINPROGRESS: 'editinprogress',\n SECTIONDRAGGABLE: 'sectiondraggable',\n EDITINGMOVE: 'editing_move'\n };\n var SELECTOR = {\n ACTIVITYLI: 'li.activity',\n ACTIONAREA: '.actions',\n ACTIVITYACTION: 'a.cm-edit-action',\n MENU: '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',\n TOGGLE: '.toggle-display,.dropdown-toggle',\n SECTIONLI: 'li.section',\n SECTIONACTIONMENU: '.section_action_menu',\n SECTIONITEM: '[data-for=\"section_title\"]',\n ADDSECTIONS: '.changenumsections [data-add-sections]',\n SECTIONBADGES: '[data-region=\"sectionbadges\"]',\n };\n\n Y.use('moodle-course-coursebase', function() {\n var courseformatselector = M.course.format.get_section_selector();\n if (courseformatselector) {\n SELECTOR.SECTIONLI = courseformatselector;\n }\n });\n\n /**\n * Dispatch event wrapper.\n *\n * Old jQuery events will be replaced by native events gradually.\n *\n * @method dispatchEvent\n * @param {String} eventName The name of the event\n * @param {Object} detail Any additional details to pass into the eveent\n * @param {Node|HTMLElement} container The point at which to dispatch the event\n * @param {Object} options\n * @param {Boolean} options.bubbles Whether to bubble up the DOM\n * @param {Boolean} options.cancelable Whether preventDefault() can be called\n * @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM boundary\n * @returns {CustomEvent}\n */\n const dispatchEvent = function(eventName, detail, container, options) {\n // Most actions still uses jQuery node instead of regular HTMLElement.\n if (!(container instanceof Element) && container.get !== undefined) {\n container = container.get(0);\n }\n return EventDispatcher.dispatchEvent(eventName, detail, container, options);\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getId\n *\n * @param {JQuery} element\n * @returns {Integer}\n */\n var getModuleId = function(element) {\n // Check if we have a data-id first.\n const item = element.get(0);\n if (item.dataset.id) {\n return item.dataset.id;\n }\n // Use YUI way if data-id is not present.\n let id;\n Y.use('moodle-course-util', function(Y) {\n id = Y.Moodle.core_course.util.cm.getId(Y.Node(item));\n });\n return id;\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getName\n *\n * @param {JQuery} element\n * @returns {String}\n */\n var getModuleName = function(element) {\n var name;\n Y.use('moodle-course-util', function(Y) {\n name = Y.Moodle.core_course.util.cm.getName(Y.Node(element.get(0)));\n });\n // Check if we have the name in the course state.\n const state = courseeditor.state;\n const cmid = getModuleId(element);\n if (!name && state && cmid) {\n name = state.cm.get(cmid)?.name;\n }\n return name;\n };\n\n /**\n * Wrapper for M.util.add_spinner for an activity\n *\n * @param {JQuery} activity\n * @returns {Node}\n */\n var addActivitySpinner = function(activity) {\n activity.addClass(CSS.EDITINPROGRESS);\n var actionarea = activity.find(SELECTOR.ACTIONAREA).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the activity state element.\n if (activity.data('id') !== undefined) {\n courseeditor.dispatch('cmLock', [activity.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_spinner for a section\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionSpinner = function(sectionelement) {\n sectionelement.addClass(CSS.EDITINPROGRESS);\n var actionarea = sectionelement.find(SELECTOR.SECTIONACTIONMENU).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the section state element.\n if (sectionelement.data('id') !== undefined) {\n courseeditor.dispatch('sectionLock', [sectionelement.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_lightbox\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionLightbox = function(sectionelement) {\n const item = sectionelement.get(0);\n var lightbox = M.util.add_lightbox(Y, Y.Node(item));\n if (item.dataset.for == 'section' && item.dataset.id) {\n courseeditor.dispatch('sectionLock', [item.dataset.id], true);\n lightbox.setAttribute('data-state', 'section');\n lightbox.setAttribute('data-state-id', item.dataset.id);\n }\n lightbox.show();\n return lightbox;\n };\n\n /**\n * Removes the spinner element\n *\n * @param {JQuery} element\n * @param {Node} spinner\n * @param {Number} delay\n */\n var removeSpinner = function(element, spinner, delay) {\n window.setTimeout(function() {\n element.removeClass(CSS.EDITINPROGRESS);\n if (spinner) {\n spinner.hide();\n }\n // Unlock the state element.\n if (element.data('id') !== undefined) {\n const mutation = (element.data('for') === 'section') ? 'sectionLock' : 'cmLock';\n courseeditor.dispatch(mutation, [element.data('id')], false);\n }\n }, delay);\n };\n\n /**\n * Removes the lightbox element\n *\n * @param {Node} lightbox lighbox YUI element returned by addSectionLightbox\n * @param {Number} delay\n */\n var removeLightbox = function(lightbox, delay) {\n if (lightbox) {\n window.setTimeout(function() {\n lightbox.hide();\n // Unlock state if necessary.\n if (lightbox.getAttribute('data-state')) {\n courseeditor.dispatch(\n `${lightbox.getAttribute('data-state')}Lock`,\n [lightbox.getAttribute('data-state-id')],\n false\n );\n }\n }, delay);\n }\n };\n\n /**\n * Initialise action menu for the element (section or module)\n *\n * @param {String} elementid CSS id attribute of the element\n */\n var initActionMenu = function(elementid) {\n // Initialise action menu in the new activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.invoke_function('setup_for_resource', '#' + elementid);\n });\n if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {\n M.core.actionmenu.newDOMNode(Y.one('#' + elementid));\n }\n };\n\n /**\n * Returns focus to the element that was clicked or \"Edit\" link if element is no longer visible.\n *\n * @param {String} elementId CSS id attribute of the element\n * @param {String} action data-action property of the element that was clicked\n */\n var focusActionItem = function(elementId, action) {\n var mainelement = $('#' + elementId);\n var selector = '[data-action=' + action + ']';\n if (action === 'groupsseparate' || action === 'groupsvisible' || action === 'groupsnone') {\n // New element will have different data-action.\n selector = '[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]';\n }\n if (mainelement.find(selector).is(':visible')) {\n mainelement.find(selector).focus();\n } else {\n // Element not visible, focus the \"Edit\" link.\n mainelement.find(SELECTOR.MENU).find(SELECTOR.TOGGLE).focus();\n }\n };\n\n /**\n * Find next after the element\n *\n * @param {JQuery} mainElement element that is about to be deleted\n * @returns {JQuery}\n */\n var findNextFocusable = function(mainElement) {\n var tabables = $(\"a:visible\");\n var isInside = false;\n var foundElement = null;\n tabables.each(function() {\n if ($.contains(mainElement[0], this)) {\n isInside = true;\n } else if (isInside) {\n foundElement = this;\n return false; // Returning false in .each() is equivalent to \"break;\" inside the loop in php.\n }\n return true;\n });\n return foundElement;\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} moduleElement activity element we perform action on\n * @param {Number} cmid\n * @param {JQuery} target the element (menu item) that was clicked\n */\n var editModule = function(moduleElement, cmid, target) {\n var action = target.attr('data-action');\n var spinner = addActivitySpinner(moduleElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_module',\n args: {id: cmid,\n action: action,\n sectionreturn: target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0\n }\n }], true);\n\n var lightbox;\n if (action === 'duplicate') {\n lightbox = addSectionLightbox(target.closest(SELECTOR.SECTIONLI));\n }\n $.when.apply($, promises)\n .done(function(data) {\n var elementToFocus = findNextFocusable(moduleElement);\n moduleElement.replaceWith(data);\n let affectedids = [];\n // Initialise action menu for activity(ies) added as a result of this.\n $('
+ {{/displayonesection}}
{{/collapsemenu}}
{{#controlmenu}}
{{$ core_courseformat/local/content/section/controlmenu }}
diff --git a/course/format/tests/base_test.php b/course/format/tests/base_test.php
index 6852286d097..56a9a32b4fa 100644
--- a/course/format/tests/base_test.php
+++ b/course/format/tests/base_test.php
@@ -770,6 +770,109 @@ class base_test extends advanced_testcase {
$format = course_get_format($course);
$this->assertEmpty($format->get_required_jsfiles());
}
+
+ /**
+ * Test set_sectionid().
+ *
+ * @covers ::set_sectionid
+ * @covers ::get_sectionid
+ * @covers ::get_sectionnum
+ */
+ public function test_set_sectionid(): void {
+ $this->resetAfterTest();
+
+ $generator = $this->getDataGenerator();
+ $course = $generator->create_course(['numsections' => 2]);
+ $format = course_get_format($course);
+
+ // No section.
+ $this->assertNull($format->get_sectionid());
+ $this->assertNull($format->get_sectionnum());
+
+ // Valid section.
+ $sectionnum = 1;
+ $modinfo = get_fast_modinfo($course);
+ $sectioninfo = $modinfo->get_section_info($sectionnum);
+ $sectionid = $sectioninfo->id;
+ $format->set_sectionid($sectionid);
+ $this->assertEquals($sectionid, $format->get_sectionid());
+ $this->assertEquals($sectionnum, $format->get_sectionnum());
+
+ // Null section.
+ $format->set_sectionid(null);
+ $this->assertNull($format->get_sectionid());
+ $this->assertNull($format->get_sectionnum());
+
+ // Invalid section.
+ $this->expectException(\coding_exception::class);
+ $format->set_sectionid(-1);
+ }
+
+ /**
+ * Test set_sectionnum().
+ *
+ * @dataProvider set_sectionnum_provider
+ * @covers ::set_sectionnum
+ * @param int|null $sectionnum The section number
+ * @param bool $nullexpected If null is expected
+ * @param bool $exceptionexpected If an exception is expected
+ */
+ public function test_set_sectionnum(?int $sectionnum, bool $nullexpected = false, bool $exceptionexpected = false): void {
+ $this->resetAfterTest();
+
+ $generator = $this->getDataGenerator();
+ $course = $generator->create_course(['numsections' => 2]);
+ $format = course_get_format($course);
+
+ if ($exceptionexpected) {
+ $this->expectException(\coding_exception::class);
+ }
+ $format->set_sectionnum($sectionnum);
+ if ($nullexpected) {
+ $this->assertNull($format->get_sectionid());
+ $this->assertNull($format->get_sectionnum());
+ } else {
+ $this->assertNotNull($format->get_sectionid());
+ $this->assertNotNull($format->get_sectionnum());
+ }
+ }
+
+ /**
+ * Data provider for test_set_sectionnum.
+ *
+ * @return array The testing scenarios
+ */
+ public static function set_sectionnum_provider(): array {
+ return [
+ 'General sectionnumber' => [
+ 'sectionnum' => 0,
+ 'nullexpected' => false,
+ ],
+ 'Existing sectionnumber' => [
+ 'sectionnum' => 1,
+ 'nullexpected' => false,
+ ],
+ 'Another existing sectionnumber' => [
+ 'sectionnum' => 2,
+ 'nullexpected' => false,
+ ],
+ 'Null sectionnumber' => [
+ 'sectionnum' => null,
+ 'nullexpected' => true,
+ ],
+ 'Invalid sectionnumber' => [
+ 'sectionnum' => 3,
+ 'nullexpected' => true,
+ 'exceptionexpected' => true,
+ ],
+ 'Another invalid sectionnumber' => [
+ 'sectionnum' => -1,
+ 'nullexpected' => true,
+ 'exceptionexpected' => true,
+ ],
+ ];
+ }
+
}
/**
diff --git a/course/format/tests/behat/section_page.feature b/course/format/tests/behat/section_page.feature
index 366bec94d72..96198bd22eb 100644
--- a/course/format/tests/behat/section_page.feature
+++ b/course/format/tests/behat/section_page.feature
@@ -39,7 +39,7 @@ Feature: Single section course page
Scenario: General section is not displayed in the single section page
When I click on "Topic 1" "link" in the "region-main" "region"
- Then I should not see "General" in the "region-main" "region"
+ Then I should not see "General" in the "#section-1" "css_element"
And I should not see "Activity sample 0.1" in the "region-main" "region"
And I should see "Activity sample 1.1"
And I should see "Activity sample 1.2"
@@ -52,7 +52,7 @@ Feature: Single section course page
Given I turn editing mode on
And I open section "1" edit menu
When I click on "View" "link" in the "Topic 1" "section"
- Then I should not see "General" in the "region-main" "region"
+ Then I should not see "General" in the "#section-1" "css_element"
And I should not see "Activity sample 0.1" in the "region-main" "region"
And I should see "Activity sample 1.1"
And I should see "Activity sample 1.2"
@@ -62,21 +62,21 @@ Feature: Single section course page
And I am on "Course 1" course homepage
And I open section "2" edit menu
And I click on "View" "link" in the "Topic 2" "section"
- And I should not see "General" in the "region-main" "region"
+ And I should not see "General" in the "#section-2" "css_element"
And I should not see "Activity sample 0.1" in the "region-main" "region"
And I should not see "Activity sample 1.1"
And I should not see "Activity sample 1.2"
And I should not see "Activity sample 1.3"
And I should see "Activity sample 2.1" in the "region-main" "region"
And I should see "Activity sample 2.1" in the "region-main" "region"
- # The following steps will need to be changed in MDL-80248, when the General section will be displayed in isolation.
+ # The General section is also displayed in isolation.
But I am on "Course 1" course homepage
And I open section "0" edit menu
And I click on "View" "link" in the "General" "section"
And I should see "General" in the "region-main" "region"
And I should see "Activity sample 0.1" in the "region-main" "region"
- And I should see "Activity sample 1.1"
- And I should see "Activity sample 1.2"
- And I should see "Activity sample 1.3"
- And I should see "Activity sample 2.1" in the "region-main" "region"
- And I should see "Activity sample 2.1" in the "region-main" "region"
+ And I should not see "Activity sample 1.1" in the "region-main" "region"
+ And I should not see "Activity sample 1.2" in the "region-main" "region"
+ And I should not see "Activity sample 1.3" in the "region-main" "region"
+ And I should not see "Activity sample 2.1" in the "region-main" "region"
+ And I should not see "Activity sample 2.1" in the "region-main" "region"
diff --git a/course/format/topics/classes/output/courseformat/content/section.php b/course/format/topics/classes/output/courseformat/content/section.php
index c4a8ac1a23b..ca41d215527 100644
--- a/course/format/topics/classes/output/courseformat/content/section.php
+++ b/course/format/topics/classes/output/courseformat/content/section.php
@@ -45,7 +45,7 @@ class section extends section_base {
$data = parent::export_for_template($output);
- if (!$this->format->get_section_number()) {
+ if (!$this->format->get_sectionnum()) {
$addsectionclass = $format->get_output_classname('content\\addsection');
$addsection = new $addsectionclass($format);
$data->numsections = $addsection->export_for_template($output);
diff --git a/course/format/topics/classes/output/courseformat/content/section/controlmenu.php b/course/format/topics/classes/output/courseformat/content/section/controlmenu.php
index d554e84a69e..263247ffc0a 100644
--- a/course/format/topics/classes/output/courseformat/content/section/controlmenu.php
+++ b/course/format/topics/classes/output/courseformat/content/section/controlmenu.php
@@ -90,7 +90,7 @@ class controlmenu extends controlmenu_base {
$format = $this->format;
$section = $this->section;
$course = $format->get_course();
- $sectionreturn = $format->get_section_number();
+ $sectionreturn = $format->get_sectionnum();
if ($sectionreturn) {
$url = course_get_url($course, $section->section);
diff --git a/course/format/topics/format.php b/course/format/topics/format.php
index 03cef340939..9a7f9d55b6b 100644
--- a/course/format/topics/format.php
+++ b/course/format/topics/format.php
@@ -52,8 +52,8 @@ course_create_sections_if_missing($course, 0);
$renderer = $PAGE->get_renderer('format_topics');
-if (!empty($displaysection)) {
- $format->set_section_number($displaysection);
+if (!is_null($displaysection)) {
+ $format->set_sectionnum($displaysection);
}
$outputclass = $format->get_output_classname('content');
$widget = new $outputclass($format);
diff --git a/course/format/topics/lib.php b/course/format/topics/lib.php
index 096b3a2e2ab..3595950b1cb 100644
--- a/course/format/topics/lib.php
+++ b/course/format/topics/lib.php
@@ -114,7 +114,7 @@ class format_topics extends core_courseformat\base {
*/
public function get_view_url($section, $options = []) {
$course = $this->get_course();
- if (array_key_exists('sr', $options)) {
+ if (array_key_exists('sr', $options) && !is_null($options['sr'])) {
$sectionno = $options['sr'];
} else if (is_object($section)) {
$sectionno = $section->section;
diff --git a/course/format/upgrade.txt b/course/format/upgrade.txt
index 121afc8c2d3..873c1107812 100644
--- a/course/format/upgrade.txt
+++ b/course/format/upgrade.txt
@@ -47,6 +47,9 @@ always linked because a new page, section.php, has been created to display any s
- course/format/topics/renderer.php
- course/format/weeks/renderer.php
* New core_courseformat\sectiondelegate class. The class can be extended by plugins to take control of a course section.
+* The methods core_courseformat\base::set_section_number() and core_courseformat\base:: get_section_number() have been deprecated
+and replaced by core_courseformat\base::set_sectionnum() and core_courseformat\base::get_sectionnum(). The new methods use the null
+value when all the sections must be displayed (instead of 0). That way, section 0 (General), can be displayed on a single page too.
=== 4.3 ===
* New core_courseformat\output\activitybadge class that can be extended by any module to display content near the activity name.
diff --git a/course/format/weeks/format.php b/course/format/weeks/format.php
index 8a603c880d0..523ccbc638b 100644
--- a/course/format/weeks/format.php
+++ b/course/format/weeks/format.php
@@ -44,8 +44,8 @@ course_create_sections_if_missing($format->get_course(), 0);
$renderer = $PAGE->get_renderer('format_weeks');
-if (!empty($displaysection)) {
- $format->set_section_number($displaysection);
+if (!is_null($displaysection)) {
+ $format->set_sectionnum($displaysection);
}
$outputclass = $format->get_output_classname('content');
diff --git a/course/format/weeks/lib.php b/course/format/weeks/lib.php
index d54e0cf82ee..042445c9f5a 100644
--- a/course/format/weeks/lib.php
+++ b/course/format/weeks/lib.php
@@ -124,7 +124,7 @@ class format_weeks extends core_courseformat\base {
*/
public function get_view_url($section, $options = array()) {
$course = $this->get_course();
- if (array_key_exists('sr', $options)) {
+ if (array_key_exists('sr', $options) && !is_null($options['sr'])) {
$sectionno = $options['sr'];
} else if (is_object($section)) {
$sectionno = $section->section;
diff --git a/course/mod.php b/course/mod.php
index 3fc5647df94..dd433c8da0d 100644
--- a/course/mod.php
+++ b/course/mod.php
@@ -51,7 +51,15 @@ foreach (compact('indent','update','hide','show','copy','moveto','movetosection'
$url->param($key, $value);
}
}
-$url->param('sr', $sectionreturn);
+// Force it to be null if it's not a valid section number.
+if ($sectionreturn < 0) {
+ $sectionreturn = null;
+}
+$urloptions = [];
+if (!is_null($sectionreturn)) {
+ $url->param('sr', $sectionreturn);
+ $urloptions['sr'] = $sectionreturn;
+}
if ($add !== '') {
$url->param('add', $add);
}
@@ -73,26 +81,42 @@ if (!empty($add)) {
$returntomod = optional_param('return', 0, PARAM_BOOL);
$beforemod = optional_param('beforemod', 0, PARAM_INT);
+ $params = [
+ 'add' => $add,
+ 'type' => $type,
+ 'course' => $id,
+ 'section' => $section,
+ 'return' => $returntomod,
+ 'beforemod' => $beforemod,
+ ];
+ if (!is_null($sectionreturn)) {
+ $params['sr'] = $sectionreturn;
+ }
+
redirect(
new moodle_url(
'/course/modedit.php',
- [
- 'add' => $add,
- 'type' => $type,
- 'course' => $id,
- 'section' => $section,
- 'return' => $returntomod,
- 'sr' => $sectionreturn,
- 'beforemod' => $beforemod,
- ]
+ $params,
)
);
} else if (!empty($update)) {
$cm = get_coursemodule_from_id('', $update, 0, true, MUST_EXIST);
$returntomod = optional_param('return', 0, PARAM_BOOL);
- redirect("$CFG->wwwroot/course/modedit.php?update=$update&return=$returntomod&sr=$sectionreturn");
+ $params = [
+ 'update' => $update,
+ 'return' => $returntomod,
+ ];
+ if (!is_null($sectionreturn)) {
+ $params['sr'] = $sectionreturn;
+ }
+ redirect(
+ new moodle_url(
+ '/course/modedit.php',
+ $params,
+ )
+ );
} else if (!empty($duplicate) and confirm_sesskey()) {
$cm = get_coursemodule_from_id('', $duplicate, 0, true, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
@@ -101,9 +125,9 @@ if (!empty($add)) {
$modcontext = context_module::instance($cm->id);
require_capability('moodle/course:manageactivities', $modcontext);
- // Duplicate the module.
- $newcm = duplicate_module($course, $cm);
- redirect(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn)));
+ // Duplicate the module.
+ $newcm = duplicate_module($course, $cm);
+ redirect(course_get_url($course, $cm->sectionnum, $urloptions));
} else if (!empty($delete)) {
$cm = get_coursemodule_from_id('', $delete, 0, true, MUST_EXIST);
@@ -113,13 +137,19 @@ if (!empty($add)) {
$modcontext = context_module::instance($cm->id);
require_capability('moodle/course:manageactivities', $modcontext);
- $return = course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn));
+ $return = course_get_url($course, $cm->sectionnum, $urloptions);
if (!$confirm or !confirm_sesskey()) {
$fullmodulename = get_string('modulename', $cm->modname);
- $optionsyes = array('confirm'=>1, 'delete'=>$cm->id, 'sesskey'=>sesskey(), 'sr' => $sectionreturn);
-
+ $optionsyes = [
+ 'confirm' => 1,
+ 'delete' => $cm->id,
+ 'sesskey' => sesskey(),
+ ];
+ if (!is_null($sectionreturn)) {
+ $optionsyes['sr'] = $sectionreturn;
+ }
$strdeletecheck = get_string('deletecheck', '', $fullmodulename);
$strparams = (object)array('type' => $fullmodulename, 'name' => $cm->name);
$strdeletechecktypename = get_string('deletechecktypename', '', $strparams);
@@ -183,7 +213,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
unset($USER->activitycopyname);
unset($USER->activitycopysectionreturn);
- redirect(course_get_url($course, $section->section, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $section->section, $urloptions));
} else if (!empty($indent) and confirm_sesskey()) {
$id = required_param('id', PARAM_INT);
@@ -208,7 +238,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
// Rebuild invalidated module cache.
rebuild_course_cache($cm->course, false, true);
- redirect(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $cm->sectionnum, $urloptions));
} else if (!empty($hide) and confirm_sesskey()) {
$cm = get_coursemodule_from_id('', $hide, 0, true, MUST_EXIST);
@@ -222,7 +252,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
if (set_coursemodule_visible($cm->id, 0)) {
\core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
}
- redirect(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $cm->sectionnum, $urloptions));
} else if (!empty($stealth) and confirm_sesskey()) {
list($course, $cm) = get_course_and_cm_from_cmid($stealth);
@@ -243,7 +273,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
if (set_coursemodule_visible($cm->id, 1)) {
\core\event\course_module_updated::create_from_cm($cm)->trigger();
}
- redirect(course_get_url($course, $section->section, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $section->section, $urloptions));
} else if ($groupmode > -1 and confirm_sesskey()) {
$id = required_param('id', PARAM_INT);
@@ -258,7 +288,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
set_coursemodule_groupmode($cm->id, $groupmode);
\core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
- redirect(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $cm->sectionnum, $urloptions));
} else if (!empty($copy) and confirm_sesskey()) { // value = course module
$cm = get_coursemodule_from_id('', $copy, 0, true, MUST_EXIST);
@@ -276,7 +306,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
$USER->activitycopyname = $cm->name;
$USER->activitycopysectionreturn = $sectionreturn;
- redirect(course_get_url($course, $section->section, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $section->section, $urloptions));
} else if (!empty($cancelcopy) and confirm_sesskey()) { // value = course module
@@ -289,7 +319,7 @@ if ((!empty($movetosection) or !empty($moveto)) and confirm_sesskey()) {
unset($USER->activitycopycourse);
unset($USER->activitycopyname);
unset($USER->activitycopysectionreturn);
- redirect(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn)));
+ redirect(course_get_url($course, $cm->sectionnum, $urloptions));
} else {
throw new \moodle_exception('unknowaction');
}
diff --git a/course/modedit.php b/course/modedit.php
index 82a4eed3e65..84c2666916b 100644
--- a/course/modedit.php
+++ b/course/modedit.php
@@ -39,8 +39,15 @@ $sectionreturn = optional_param('sr', null, PARAM_INT);
$beforemod = optional_param('beforemod', 0, PARAM_INT);
$showonly = optional_param('showonly', '', PARAM_TAGLIST); // Settings group to show expanded and hide the rest.
+// Force it to be null if it's not a valid section number.
+if ($sectionreturn < 0) {
+ $sectionreturn = null;
+}
+
$url = new moodle_url('/course/modedit.php');
-$url->param('sr', $sectionreturn);
+if (!is_null($sectionreturn)) {
+ $url->param('sr', $sectionreturn);
+}
if (!empty($return)) {
$url->param('return', $return);
}
@@ -76,7 +83,9 @@ if (!empty($add)) {
list($module, $context, $cw, $cm, $data) = prepare_new_moduleinfo_data($course, $add, $section);
$data->return = 0;
- $data->sr = $sectionreturn;
+ if (!is_null($sectionreturn)) {
+ $data->sr = $sectionreturn;
+ }
$data->add = $add;
$data->beforemod = $beforemod;
if (!empty($type)) { //TODO: hopefully will be removed in 2.0
@@ -115,7 +124,9 @@ if (!empty($add)) {
list($cm, $context, $module, $data, $cw) = get_moduleinfo_data($cm, $course);
$data->return = $return;
- $data->sr = $sectionreturn;
+ if (!is_null($sectionreturn)) {
+ $data->sr = $sectionreturn;
+ }
$data->update = $update;
if (!empty($showonly)) {
$data->showonly = $showonly;
@@ -173,7 +184,11 @@ if ($mform->is_cancelled()) {
$activityurl = new moodle_url("/mod/$module->name/view.php", $urlparams);
redirect($activityurl);
} else {
- redirect(course_get_url($course, $cw->section, array('sr' => $sectionreturn)));
+ $options = [];
+ if (!is_null($sectionreturn)) {
+ $options['sr'] = $sectionreturn;
+ }
+ redirect(course_get_url($course, $cw->section, $options));
}
} else if ($fromform = $mform->get_data()) {
// Mark that this is happening in the front-end UI. This is used to indicate that we are able to
@@ -193,7 +208,11 @@ if ($mform->is_cancelled()) {
$url = $fromform->gradingman->get_management_url($url);
}
} else {
- $url = course_get_url($course, $cw->section, array('sr' => $sectionreturn));
+ $options = [];
+ if (!is_null($sectionreturn)) {
+ $options['sr'] = $sectionreturn;
+ }
+ $url = course_get_url($course, $cw->section, $options);
}
// If we need to regrade the course with a progress bar as a result of updating this module,
diff --git a/course/moodleform_mod.php b/course/moodleform_mod.php
index 5924ff6bf45..bb7483809f5 100644
--- a/course/moodleform_mod.php
+++ b/course/moodleform_mod.php
@@ -868,7 +868,9 @@ abstract class moodleform_mod extends moodleform {
$mform->addElement('hidden', 'return', 0);
$mform->setType('return', PARAM_BOOL);
- $mform->addElement('hidden', 'sr', 0);
+ // The section number where to return: -1 means no section (0 can't be used because it is a valid section number and
+ // null can't be used because it's converted to 0).
+ $mform->addElement('hidden', 'sr', -1);
$mform->setType('sr', PARAM_INT);
$mform->addElement('hidden', 'beforemod', 0);
diff --git a/course/section.php b/course/section.php
index 01e1aba09ea..f6b8ab5e3fe 100644
--- a/course/section.php
+++ b/course/section.php
@@ -168,7 +168,7 @@ echo $renderer->container_start('course-content');
// Include course AJAX.
include_course_ajax($course, $modinfo->get_used_module_names());
-$format->set_section_number($section->section);
+$format->set_sectionid($section->id);
$outputclass = $format->get_output_classname('content');
$widget = new $outputclass($format);
echo $renderer->render($widget);
diff --git a/course/templates/activitychooserbutton.mustache b/course/templates/activitychooserbutton.mustache
index 91615f7065f..9ebe9b7d0c2 100644
--- a/course/templates/activitychooserbutton.mustache
+++ b/course/templates/activitychooserbutton.mustache
@@ -30,7 +30,9 @@
}
}}