Merge branch 'MDL-84291-main-v03' of https://github.com/ferranrecio/moodle
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
issueNumber: MDL-84291
|
||||
notes:
|
||||
core_courseformat:
|
||||
- message: >-
|
||||
The maxsections setting is now considered deprecated and will be removed
|
||||
in Moodle 6.0. Consider implementing your own setting in your format
|
||||
plugin if needed.
|
||||
type: deprecated
|
||||
@@ -0,0 +1,8 @@
|
||||
issueNumber: MDL-84291
|
||||
notes:
|
||||
format_weeks:
|
||||
- message: >-
|
||||
The weekly sections format now has a system setting called Maximum
|
||||
initial number of weeks that replaced the old "Max sections" when
|
||||
creating a new course
|
||||
type: improved
|
||||
@@ -0,0 +1,8 @@
|
||||
issueNumber: MDL-84291
|
||||
notes:
|
||||
format_topics:
|
||||
- message: >-
|
||||
Now the custom sections format won't ask for initial sections on the
|
||||
creation form. Instead it will use the system number of sections
|
||||
settings directly.
|
||||
type: improved
|
||||
@@ -0,0 +1,8 @@
|
||||
issueNumber: MDL-84291
|
||||
notes:
|
||||
core_courseformat:
|
||||
- message: >-
|
||||
The param $maxsections of get_num_sections_data in addsection output is
|
||||
not used anymore. If your format overrides this method, you should add
|
||||
a default value 0 to be consistent with the new implementation.
|
||||
type: changed
|
||||
@@ -0,0 +1,7 @@
|
||||
issueNumber: MDL-84291
|
||||
notes:
|
||||
core_courseformat:
|
||||
- message: >-
|
||||
The format base method get_max_sections has been deprecated, as the
|
||||
maxsections setting is also deprecated and no longer in use.
|
||||
type: deprecated
|
||||
@@ -93,6 +93,7 @@ class manager {
|
||||
'adminpresets_admin_settings_country_select' => 'adminpresets_admin_setting_configmultiselect_with_loader',
|
||||
'adminpresets_admin_settings_coursecat_select' => 'adminpresets_admin_setting_configmultiselect_with_loader',
|
||||
'adminpresets_admin_settings_h5plib_handler_select' => 'adminpresets_admin_setting_configselect',
|
||||
// TODO: remove adminpresets_admin_settings_num_course_sections in Moodle 6.0 (MDL-85272).
|
||||
'adminpresets_admin_settings_num_course_sections' => 'adminpresets_admin_setting_configmultiselect_with_loader',
|
||||
'adminpresets_admin_settings_sitepolicy_handler_select' => 'adminpresets_admin_setting_configselect',
|
||||
'adminpresets_antivirus_clamav_pathtounixsocket_setting' => 'adminpresets_admin_setting_configtext',
|
||||
|
||||
@@ -157,11 +157,17 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/format', new lang_string('format'), new lang_string('coursehelpformat'),
|
||||
'topics', $formcourseformats));
|
||||
|
||||
// TODO: remove this setting in Moodle 6.0 (MDL-85272).
|
||||
$temp->add(new admin_setting_configtext('moodlecourse/maxsections', new lang_string('maxnumberweeks'),
|
||||
new lang_string('maxnumberweeks_desc'), 52));
|
||||
|
||||
$temp->add(new admin_settings_num_course_sections('moodlecourse/numsections', new lang_string('numberweeks'),
|
||||
new lang_string('coursehelpnumberweeks'), 4));
|
||||
$temp->add(new admin_setting_configtext(
|
||||
name: 'moodlecourse/numsections',
|
||||
visiblename: new lang_string('numberweeks'),
|
||||
description: new lang_string('coursehelpnumberweeks'),
|
||||
defaultsetting: 4,
|
||||
paramtype: PARAM_INT,
|
||||
));
|
||||
|
||||
$choices = array();
|
||||
$choices['0'] = new lang_string('hiddensectionscollapsed');
|
||||
|
||||
@@ -48,7 +48,6 @@ require_sesskey();
|
||||
$desirednumsections = 0;
|
||||
$courseformat = course_get_format($course);
|
||||
$lastsectionnumber = $courseformat->get_last_section_number();
|
||||
$maxsections = $courseformat->get_max_sections();
|
||||
|
||||
if (isset($courseformatoptions['numsections']) && $increase !== null) {
|
||||
$desirednumsections = $courseformatoptions['numsections'] + 1;
|
||||
@@ -57,18 +56,6 @@ if (isset($courseformatoptions['numsections']) && $increase !== null) {
|
||||
$desirednumsections = $lastsectionnumber + $numsections;
|
||||
}
|
||||
|
||||
if ($desirednumsections > $maxsections) {
|
||||
// Increase in number of sections is not allowed.
|
||||
\core\notification::warning(get_string('maxsectionslimit', 'moodle', $maxsections));
|
||||
$increase = null;
|
||||
$insertsection = null;
|
||||
$numsections = 0;
|
||||
|
||||
if (!$returnurl) {
|
||||
$returnurl = course_get_url($course);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($courseformatoptions['numsections']) && $increase !== null) {
|
||||
if ($increase) {
|
||||
// Add an additional section.
|
||||
|
||||
@@ -277,11 +277,8 @@ class content_item_service {
|
||||
return course_allowed_module($course, explode('_', $parents[$contentitem->get_component_name()])[1], $user);
|
||||
});
|
||||
|
||||
$format = course_get_format($course);
|
||||
$maxsectionsreached = ($format->get_last_section_number() >= $format->get_max_sections());
|
||||
|
||||
// Now, check there is no delegated section into a delegated section.
|
||||
if (is_null($sectioninfo) || $sectioninfo->is_delegated() || $maxsectionsreached) {
|
||||
if (is_null($sectioninfo) || $sectioninfo->is_delegated()) {
|
||||
$availablecontentitems = array_filter($availablecontentitems, function($contentitem){
|
||||
return !sectiondelegate::has_delegate_class($contentitem->get_component_name());
|
||||
});
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -39,11 +39,8 @@ import {prefetchStrings} from 'core/prefetch';
|
||||
import {getString} from 'core/str';
|
||||
import {getFirst} from 'core/normalise';
|
||||
import {toggleBulkSelectionAction} from 'core_courseformat/local/content/actions/bulkselection';
|
||||
import * as CourseEvents from 'core_course/events';
|
||||
import Pending from 'core/pending';
|
||||
import ContentTree from 'core_courseformat/local/courseeditor/contenttree';
|
||||
// The jQuery module is only used for interacting with Boostrap 4. It can we removed when MDL-71979 is integrated.
|
||||
import Notification from "core/notification";
|
||||
|
||||
// Load global strings.
|
||||
prefetchStrings('core', ['movecoursesection', 'movecoursemodule', 'confirm', 'delete']);
|
||||
@@ -87,7 +84,6 @@ export default class extends BaseComponent {
|
||||
// Availability modal selectors.
|
||||
OPTIONSRADIO: `[type='radio']`,
|
||||
COURSEADDSECTION: `#course-addsection`,
|
||||
MAXSECTIONSWARNING: `[data-region='max-sections-warning']`,
|
||||
ADDSECTIONREGION: `[data-region='section-addsection']`,
|
||||
};
|
||||
// Component css classes.
|
||||
@@ -114,25 +110,14 @@ export default class extends BaseComponent {
|
||||
|
||||
/**
|
||||
* Initial state ready method.
|
||||
*
|
||||
* @param {Object} state the state data.
|
||||
*
|
||||
*/
|
||||
stateReady(state) {
|
||||
stateReady() {
|
||||
// Delegate dispatch clicks.
|
||||
this.addEventListener(
|
||||
this.element,
|
||||
'click',
|
||||
this._dispatchClick
|
||||
);
|
||||
// Check section limit.
|
||||
this._checkSectionlist({state});
|
||||
// Add an Event listener to recalculate limits it if a section HTML is altered.
|
||||
this.addEventListener(
|
||||
this.element,
|
||||
CourseEvents.sectionRefreshed,
|
||||
() => this._checkSectionlist({state})
|
||||
);
|
||||
// Any inplace editable update needs state refresh.
|
||||
this.addEventListener(
|
||||
this.element,
|
||||
@@ -141,18 +126,6 @@ export default class extends BaseComponent {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the component watchers.
|
||||
*
|
||||
* @returns {Array} of watchers
|
||||
*/
|
||||
getWatchers() {
|
||||
return [
|
||||
// Check section limit.
|
||||
{watch: `course.sectionlist:updated`, handler: this._checkSectionlist},
|
||||
];
|
||||
}
|
||||
|
||||
_dispatchClick(event) {
|
||||
const target = event.target.closest(this.selectors.ACTIONLINK);
|
||||
if (!target) {
|
||||
@@ -188,17 +161,6 @@ export default class extends BaseComponent {
|
||||
return `_request${requestName}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the section list and disable some options if needed.
|
||||
*
|
||||
* @param {Object} detail the update details.
|
||||
* @param {Object} detail.state the state object.
|
||||
*/
|
||||
_checkSectionlist({state}) {
|
||||
// Disable "add section" actions if the course max sections has been exceeded.
|
||||
this._setAddSectionLocked(state.course.sectionlist.length > state.course.maxsections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle inplace editable updates.
|
||||
*
|
||||
@@ -813,38 +775,6 @@ export default class extends BaseComponent {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all add sections actions.
|
||||
*
|
||||
* @param {boolean} locked the new locked value.
|
||||
*/
|
||||
_setAddSectionLocked(locked) {
|
||||
const targets = this.getElements(this.selectors.ADDSECTIONREGION);
|
||||
targets.forEach(element => {
|
||||
element.classList.toggle(this.classes.DISABLED, locked);
|
||||
const addSectionElement = element.querySelector(this.selectors.ADDSECTION);
|
||||
addSectionElement.classList.toggle(this.classes.DISABLED, locked);
|
||||
this.setElementLocked(addSectionElement, locked);
|
||||
// We tweak the element to show a tooltip as a title attribute.
|
||||
if (locked) {
|
||||
getString('sectionaddmax', 'core_courseformat')
|
||||
.then((text) => addSectionElement.setAttribute('title', text))
|
||||
.catch(Notification.exception);
|
||||
addSectionElement.style.pointerEvents = null; // Unlocks the pointer events.
|
||||
addSectionElement.style.userSelect = null; // Unlocks the pointer events.
|
||||
} else {
|
||||
addSectionElement.setAttribute('title', addSectionElement.dataset.addSections);
|
||||
}
|
||||
});
|
||||
const courseAddSection = this.getElement(this.selectors.COURSEADDSECTION);
|
||||
if (courseAddSection) {
|
||||
const addSection = courseAddSection.querySelector(this.selectors.ADDSECTION);
|
||||
addSection.classList.toggle(this.classes.DISPLAYNONE, locked);
|
||||
const noMoreSections = courseAddSection.querySelector(this.selectors.MAXSECTIONSWARNING);
|
||||
noMoreSections.classList.toggle(this.classes.DISPLAYNONE, !locked);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace an element with a copy with a different tag name.
|
||||
*
|
||||
|
||||
@@ -448,9 +448,19 @@ abstract class base {
|
||||
|
||||
/**
|
||||
* Method used to get the maximum number of sections for this course format.
|
||||
*
|
||||
* @deprecated Since 5.1 the setting is removed.
|
||||
* @todo Remove this method in Moodle 6.0 (MDL-85272).
|
||||
* @return int
|
||||
*/
|
||||
#[\core\attribute\deprecated(
|
||||
replacement: null,
|
||||
reason: 'The maxsection setting is removed.',
|
||||
since: '5.1',
|
||||
mdl: 'MDL-84291',
|
||||
)]
|
||||
public function get_max_sections() {
|
||||
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
|
||||
$maxsections = get_config('moodlecourse', 'maxsections');
|
||||
if (!isset($maxsections) || !is_numeric($maxsections)) {
|
||||
$maxsections = 52;
|
||||
|
||||
@@ -72,16 +72,15 @@ class addsection implements named_templatable, renderable {
|
||||
$options = $format->get_format_options();
|
||||
|
||||
$lastsection = $format->get_last_section_number();
|
||||
$maxsections = $format->get_max_sections();
|
||||
|
||||
// Component based formats handle add section button in the frontend.
|
||||
$show = ($lastsection < $maxsections) || $format->supports_components();
|
||||
$show = $format->supports_components();
|
||||
|
||||
$supportsnumsections = array_key_exists('numsections', $options);
|
||||
if ($supportsnumsections) {
|
||||
$data = $this->get_num_sections_data($output, $lastsection, $maxsections);
|
||||
$data = $this->get_num_sections_data($output, $lastsection);
|
||||
} else if (course_get_format($course)->uses_sections() && $show) {
|
||||
$data = $this->get_add_section_data($output, $lastsection, $maxsections);
|
||||
$data = $this->get_add_section_data($output, $lastsection);
|
||||
}
|
||||
|
||||
if (count((array)$data)) {
|
||||
@@ -99,22 +98,20 @@ class addsection implements named_templatable, renderable {
|
||||
*
|
||||
* @param \renderer_base $output typically, the renderer that's calling this function
|
||||
* @param int $lastsection the last section number
|
||||
* @param int $maxsections the maximum number of sections
|
||||
* @param int $maxsections unused (max sections is not needed anymore)
|
||||
* @return stdClass data context for a mustache template
|
||||
*/
|
||||
protected function get_num_sections_data(\renderer_base $output, int $lastsection, int $maxsections): stdClass {
|
||||
protected function get_num_sections_data(\renderer_base $output, int $lastsection, int $maxsections = 0): stdClass {
|
||||
$format = $this->format;
|
||||
$course = $format->get_course();
|
||||
$data = new stdClass();
|
||||
|
||||
if ($lastsection < $maxsections) {
|
||||
$data->increase = (object) [
|
||||
'url' => new moodle_url(
|
||||
'/course/changenumsections.php',
|
||||
['courseid' => $course->id, 'increase' => true, 'sesskey' => sesskey()]
|
||||
),
|
||||
];
|
||||
}
|
||||
$data->increase = (object) [
|
||||
'url' => new moodle_url(
|
||||
'/course/changenumsections.php',
|
||||
['courseid' => $course->id, 'increase' => true, 'sesskey' => sesskey()]
|
||||
),
|
||||
];
|
||||
|
||||
if ($course->numsections > 0) {
|
||||
$data->decrease = (object) [
|
||||
@@ -137,10 +134,10 @@ class addsection implements named_templatable, renderable {
|
||||
*
|
||||
* @param \renderer_base $output typically, the renderer that's calling this function
|
||||
* @param int $lastsection the last section number
|
||||
* @param int $maxsections the maximum number of sections
|
||||
* @param int $maxsections unused (max sections is not needed anymore)
|
||||
* @return stdClass data context for a mustache template
|
||||
*/
|
||||
protected function get_add_section_data(\renderer_base $output, int $lastsection, int $maxsections): stdClass {
|
||||
protected function get_add_section_data(\renderer_base $output, int $lastsection, int $maxsections = 0): stdClass {
|
||||
$format = $this->format;
|
||||
$course = $format->get_course();
|
||||
$data = new stdClass();
|
||||
@@ -156,8 +153,8 @@ class addsection implements named_templatable, renderable {
|
||||
$data->addsections = (object) [
|
||||
'url' => new moodle_url('/course/changenumsections.php', $params),
|
||||
'title' => $addstring,
|
||||
'newsection' => $maxsections - $lastsection,
|
||||
'canaddsection' => $lastsection < $maxsections,
|
||||
'newsection' => $lastsection + 1,
|
||||
'canaddsection' => true,
|
||||
];
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ class course implements renderable {
|
||||
'sectionlist' => [],
|
||||
'editmode' => $format->show_editor(),
|
||||
'highlighted' => $format->get_section_highlighted_name(),
|
||||
'maxsections' => $format->get_max_sections(),
|
||||
'baseurl' => $url->out(),
|
||||
'statekey' => course_format::session_cache($course),
|
||||
'maxbytes' => $maxbytes,
|
||||
|
||||
@@ -267,15 +267,6 @@ class stateactions {
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
require_capability('moodle/course:update', $coursecontext);
|
||||
|
||||
// Get course format settings.
|
||||
$format = course_get_format($course->id);
|
||||
$lastsectionnumber = $format->get_last_section_number();
|
||||
$maxsections = $format->get_max_sections();
|
||||
|
||||
if ($lastsectionnumber >= $maxsections) {
|
||||
throw new moodle_exception('maxsectionslimit', 'moodle', '', $maxsections);
|
||||
}
|
||||
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
|
||||
// Get target section.
|
||||
|
||||
@@ -61,14 +61,6 @@
|
||||
{{#pix}} t/add, core {{/pix}}
|
||||
{{title}}
|
||||
</a>
|
||||
<div class="d-none p-3 max-section-alert" data-region="max-sections-warning">
|
||||
<div class="w-100 text-center">
|
||||
{{#pix}}t/block, moodle{{/pix}}
|
||||
</div>
|
||||
<div class="w-100 fst-italic text-center">
|
||||
{{#str}}maxsectionaddmessage, core_courseformat{{/str}}
|
||||
</div>
|
||||
</div>
|
||||
{{/addsections}}
|
||||
</div>
|
||||
{{/showaddsection}}
|
||||
|
||||
@@ -381,17 +381,3 @@ Feature: Course index depending on role
|
||||
And I turn editing mode on
|
||||
When I set the field "Edit section name" in the "page-header" "region" to "Custom section name"
|
||||
Then I should see "Custom section name" in the "courseindex-content" "region"
|
||||
|
||||
@javascript
|
||||
Scenario: We cannot add a section when the number of section reaches maxsections but as soon as we reach under the limit we can add a section again.
|
||||
Given the following config values are set as admin:
|
||||
| maxsections | 4 | moodlecourse|
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
Then I should see "Section 1" in the "courseindex-content" "region"
|
||||
And ".disabled" "css_element" should exist in the "[data-action='addSection']" "css_element"
|
||||
And I should see "You have reached the maximum number of sections allowed for a course."
|
||||
And I delete section "4"
|
||||
And I click on "Delete" "button" in the ".modal" "css_element"
|
||||
And ".disabled" "css_element" should not exist in the "[data-action='addSection']" "css_element"
|
||||
And I should not see "You have reached the maximum number of sections allowed for a course."
|
||||
|
||||
@@ -285,17 +285,11 @@ class format_topics extends core_courseformat\base {
|
||||
$elements = parent::create_edit_form_elements($mform, $forsection);
|
||||
|
||||
if (!$forsection && (empty($COURSE->id) || $COURSE->id == SITEID)) {
|
||||
// Add "numsections" element to the create course form - it will force new course to be prepopulated
|
||||
// with empty sections.
|
||||
// The "Number of sections" option is no longer available when editing course, instead teachers should
|
||||
// delete and add sections when needed.
|
||||
// Custom sections are always created with the default number of sections.
|
||||
$courseconfig = get_config('moodlecourse');
|
||||
$max = (int)$courseconfig->maxsections;
|
||||
$element = $mform->addElement('select', 'numsections', get_string('numberweeks'), range(0, $max ?: 52));
|
||||
$element = $mform->addElement('hidden', 'numsections');
|
||||
$mform->setType('numsections', PARAM_INT);
|
||||
if (is_null($mform->getElementValue('numsections'))) {
|
||||
$mform->setDefault('numsections', $courseconfig->numsections);
|
||||
}
|
||||
$mform->setDefault('numsections', $courseconfig->numsections);
|
||||
array_unshift($elements, $element);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
@format @format_topics
|
||||
Feature: Custom sections are created with the system default number of sections
|
||||
In order to create courses
|
||||
As a course creator
|
||||
I need my courses to be created as the system default number of sections
|
||||
|
||||
@javascript
|
||||
Scenario: Default number of sections in course creation
|
||||
Given the following config values are set as admin:
|
||||
| numsections | 5 | moodlecourse |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Courses > Manage courses and categories" in site administration
|
||||
And I click on "Create new course" "link"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Course full name" to "Course 1"
|
||||
And I set the field "Course short name" to "C1"
|
||||
And I set the field "Format" to "Custom sections"
|
||||
Then I should not see "Number of sections"
|
||||
And I click on "Save and display" "button"
|
||||
And "[data-for='section'][data-number='1']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='2']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='3']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='4']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='5']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='6']" "css_element" should not exist
|
||||
@@ -46,5 +46,19 @@ function xmldb_format_weeks_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v5.0.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2025052600) {
|
||||
$config = get_config('format_weeks');
|
||||
// Crerate the default maxinitialsections setting if is not set.
|
||||
if (!isset($config->maxinitialsections)) {
|
||||
// The system may have some maxsections defined. We will keep the same value.
|
||||
$courseconfig = get_config('moodlecourse');
|
||||
$max = (int) $courseconfig->maxsections;
|
||||
$config->maxinitialsections = $max ?: 52;
|
||||
set_config('maxinitialsections', $config->maxinitialsections, 'format_weeks');
|
||||
}
|
||||
|
||||
upgrade_plugin_savepoint(true, 2025052600, 'format', 'weeks');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ $string['automaticenddate'] = 'Calculate the end date from the number of section
|
||||
$string['automaticenddate_help'] = 'If enabled, the end date for the course will be automatically calculated from the number of sections and the course start date.';
|
||||
$string['currentsection'] = 'Current week';
|
||||
$string['hidefromothers'] = 'Hide';
|
||||
$string['maxinitialsections'] = 'Maximum number of weeks at course creation';
|
||||
$string['maxinitialsections_help'] = 'Sets the maximum number of weeks that can be assigned to a course at the time of creation. This limit helps prevent accidental creation of overly long courses. It does not restrict teachers from adding more weeks later during course editing.';
|
||||
$string['page-course-view-weeks'] = 'Any course main page in weekly sections format';
|
||||
$string['page-course-view-weeks-x'] = 'Any course page in weekly sections format';
|
||||
$string['pluginname'] = 'Weekly sections';
|
||||
|
||||
@@ -319,7 +319,8 @@ class format_weeks extends core_courseformat\base {
|
||||
// The "Number of sections" option is no longer available when editing course, instead teachers should
|
||||
// delete and add sections when needed.
|
||||
$courseconfig = get_config('moodlecourse');
|
||||
$max = (int)$courseconfig->maxsections;
|
||||
$weeksconfig = get_config('format_weeks');
|
||||
$max = (int)$weeksconfig->maxinitialsections;
|
||||
$element = $mform->addElement('select', 'numsections', get_string('numberweeks'), range(0, $max ?: 52));
|
||||
$mform->setType('numsections', PARAM_INT);
|
||||
if (is_null($mform->getElementValue('numsections'))) {
|
||||
|
||||
@@ -33,4 +33,12 @@ if ($ADMIN->fulltree) {
|
||||
new lang_string('indentation_help', 'format_weeks').'<br />'.$link,
|
||||
1
|
||||
));
|
||||
|
||||
$settings->add(new admin_setting_configtext(
|
||||
name: 'format_weeks/maxinitialsections',
|
||||
visiblename: new lang_string('maxinitialsections', 'format_weeks'),
|
||||
description: new lang_string('maxinitialsections_help', 'format_weeks'),
|
||||
defaultsetting: 52,
|
||||
paramtype: PARAM_INT,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
@format @format_weeks
|
||||
Feature: Weeks format courses are created with the system default number of sections
|
||||
In order to create courses
|
||||
As a course creator
|
||||
I need my week courses to be created as the system default number of sections
|
||||
|
||||
@javascript
|
||||
Scenario: Weeks formats cannot be created with more sections than the format max
|
||||
Given the following config values are set as admin:
|
||||
| maxinitialsections | 5 | format_weeks |
|
||||
| numsections | 40 | moodlecourse |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Courses > Manage courses and categories" in site administration
|
||||
And I click on "Create new course" "link"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Course full name" to "Course 1"
|
||||
And I set the field "Course short name" to "C1"
|
||||
And I set the field "Format" to "Weekly sections"
|
||||
Then the "Number of sections" select box should contain "5"
|
||||
And the "Number of sections" select box should not contain "6"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Number of sections" to "5"
|
||||
And I click on "Save and display" "button"
|
||||
And "[data-for='section'][data-number='1']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='2']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='3']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='4']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='5']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='6']" "css_element" should not exist
|
||||
|
||||
@javascript
|
||||
Scenario: Weeks formats will be created with the system default
|
||||
Given the following config values are set as admin:
|
||||
| numsections | 5 | moodlecourse |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Courses > Manage courses and categories" in site administration
|
||||
And I click on "Create new course" "link"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Course full name" to "Course 1"
|
||||
And I set the field "Course short name" to "C1"
|
||||
And I set the field "Format" to "Weekly sections"
|
||||
Then the "Number of sections" select box should contain "52"
|
||||
And the "Number of sections" select box should not contain "53"
|
||||
And I click on "Save and display" "button"
|
||||
And "[data-for='section'][data-number='1']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='2']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='3']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='4']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='5']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='6']" "css_element" should not exist
|
||||
|
||||
@javascript
|
||||
Scenario: Weeks formats can be created with a specific number of sections
|
||||
Given the following config values are set as admin:
|
||||
| numsections | 4 | moodlecourse |
|
||||
| maxinitialsections | 10 | format_weeks |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Courses > Manage courses and categories" in site administration
|
||||
And I click on "Create new course" "link"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Course full name" to "Course 1"
|
||||
And I set the field "Course short name" to "C1"
|
||||
And I set the field "Format" to "Weekly sections"
|
||||
Then the "Number of sections" select box should contain "10"
|
||||
And the "Number of sections" select box should not contain "11"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Number of sections" to "5"
|
||||
And I click on "Save and display" "button"
|
||||
And "[data-for='section'][data-number='1']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='2']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='3']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='4']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='5']" "css_element" should exist
|
||||
And "[data-for='section'][data-number='6']" "css_element" should not exist
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2025041400; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2025052600; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2025040800; // Requires this Moodle version.
|
||||
$plugin->component = 'format_weeks'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -72,15 +72,6 @@ if (!empty($add)) {
|
||||
// will be the closest match we have.
|
||||
navigation_node::override_active_url(course_get_url($course, $section));
|
||||
|
||||
// MDL-69431 Validate that $section (url param) does not exceed the maximum for this course / format.
|
||||
// If too high (e.g. section *id* not number) non-sequential sections inserted in course_sections table.
|
||||
// Then on import, backup fills 'gap' with empty sections (see restore_rebuild_course_cache). Avoid this.
|
||||
$courseformat = course_get_format($course);
|
||||
$maxsections = $courseformat->get_max_sections();
|
||||
if ($section > $maxsections) {
|
||||
throw new \moodle_exception('maxsectionslimit', 'moodle', '', $maxsections);
|
||||
}
|
||||
|
||||
list($module, $context, $cw, $cm, $data) = prepare_new_moduleinfo_data($course, $add, $section);
|
||||
$data->return = 0;
|
||||
if (!is_null($sectionreturn)) {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
@core @core_course
|
||||
Feature: The maximum number of weeks/topics in a course can be configured
|
||||
In order to set boundaries to courses size
|
||||
As a manager
|
||||
I need to limit the number of weeks/topics a course can have
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| manager1 | Manager | 1 | manager1@example.com |
|
||||
And the following "system role assigns" exist:
|
||||
| user | course | role |
|
||||
| manager1 | Acceptance test site | manager |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Courses > Default settings > Course default settings" in site administration
|
||||
|
||||
@javascript
|
||||
Scenario: The number of sections can be increased and the limits are applied to courses
|
||||
Given I set the field "Maximum number of sections" to "100"
|
||||
When I press "Save changes"
|
||||
And the field "Maximum number of sections" matches value "100"
|
||||
And the "Number of sections" select box should contain "100"
|
||||
And I log out
|
||||
And I log in as "manager1"
|
||||
And the following "course" exists:
|
||||
| fullname | New course fullname |
|
||||
| shortname | New course shortname |
|
||||
| format | topics |
|
||||
| numsections | 90 |
|
||||
| initsections | 1 |
|
||||
And I am on the "New course fullname" course page
|
||||
Then I should see "Section 90"
|
||||
|
||||
@javascript
|
||||
Scenario: The number of sections can be reduced to 0 and the limits are applied to courses
|
||||
Given I set the field "Maximum number of sections" to "0"
|
||||
When I press "Save changes"
|
||||
And the field "Maximum number of sections" matches value "0"
|
||||
And the "Number of sections" select box should contain "0"
|
||||
And the "Number of sections" select box should not contain "52"
|
||||
And I log out
|
||||
And I log in as "manager1"
|
||||
And the following "course" exists:
|
||||
| fullname | New course fullname |
|
||||
| shortname | New course shortname |
|
||||
| format | topics |
|
||||
| numsections | 0 |
|
||||
| initsections | 1 |
|
||||
And I am on the "New course fullname" course page
|
||||
Then I should not see "Section 1"
|
||||
@@ -70,7 +70,6 @@ $string['cmsmove_title'] = 'Move selected activities';
|
||||
$string['cmsmove_info'] = 'Move {$a} activities after';
|
||||
$string['courseindex'] = 'Course index';
|
||||
$string['courseindexoptions'] = 'Course index options';
|
||||
$string['maxsectionaddmessage'] = 'You have reached the maximum number of sections allowed for a course.';
|
||||
$string['nobulkaction'] = 'No bulk actions available';
|
||||
$string['orphansectionwarning'] = 'This section and its content are not part of the course structure and are not visible to students. To use any of this content, move it to a different section.';
|
||||
$string['preference:coursesectionspreferences'] = 'Section user preferences for course {$a}';
|
||||
@@ -98,3 +97,6 @@ $string['sectionsmove_info'] = 'Move {$a} sections after';
|
||||
$string['sectionsmove_title'] = 'Move selected sections';
|
||||
$string['selectcm'] = 'Select activity {$a}';
|
||||
$string['selectsection'] = 'Select section {$a}';
|
||||
|
||||
// Deprecated since Moodle 5.1.
|
||||
$string['maxsectionaddmessage'] = 'You have reached the maximum number of sections allowed for a course.';
|
||||
|
||||
@@ -82,3 +82,5 @@ lockverbose,core_grades
|
||||
showverbose,core_grades
|
||||
unlockverbose,core_grades
|
||||
aiusagestats,core_hub
|
||||
maxsectionslimit,core
|
||||
maxsectionaddmessage,core_courseformat
|
||||
|
||||
+5
-3
@@ -1288,7 +1288,6 @@ $string['match'] = 'Match';
|
||||
$string['matchingsearchandrole'] = 'Matching \'{$a->search}\' and {$a->role}';
|
||||
$string['matchofthefollowing'] = 'of the following:';
|
||||
$string['maxareabytesreached'] = 'The file (or the total size of several files) is larger than the space remaining in this area.';
|
||||
$string['maxsectionslimit'] = 'Cannot create new section as it would exceed the maximum number of sections allowed for this course ({$a}).';
|
||||
$string['maxfilesize'] = 'Maximum size for new files: {$a}';
|
||||
$string['maxfilesreached'] = 'You are allowed to attach a maximum of {$a} file(s) to this item';
|
||||
$string['maximumchars'] = 'Maximum of {$a} characters';
|
||||
@@ -1297,8 +1296,8 @@ $string['maximumgradex'] = 'Maximum grade: {$a}';
|
||||
$string['maximumshort'] = 'Max';
|
||||
$string['maximumupload'] = 'Maximum upload size';
|
||||
$string['maximumupload_help'] = 'The maximum file size allowed for student uploads to the course. Additionally, you can further restrict the maximum upload size for each activity.';
|
||||
$string['maxnumberweeks'] = 'Maximum number of sections';
|
||||
$string['maxnumberweeks_desc'] = 'The maximum value in the number of sections drop-down menu (applies to certain course formats only).';
|
||||
$string['maxnumberweeks'] = 'Maximum number of sections (deprecated)';
|
||||
$string['maxnumberweeks_desc'] = 'The maximum value in the number of sections drop-down menu (applies to certain course formats only). This setting is deprecated and will be removed in a future version of Moodle. Please use the course format settings instead.';
|
||||
$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}';
|
||||
@@ -2488,3 +2487,6 @@ $string['registrationcontactyes'] = 'Yes, provide a form for other Moodlers to c
|
||||
|
||||
// Deprecated since Moodle 5.0.
|
||||
$string['failedtaskcontexturlname'] = 'Status report';
|
||||
|
||||
// Deprecated since Moodle 5.1.
|
||||
$string['maxsectionslimit'] = 'Cannot create new section as it would exceed the maximum number of sections allowed for this course ({$a}).';
|
||||
|
||||
@@ -5414,11 +5414,29 @@ class admin_settings_country_select extends admin_setting_configselect {
|
||||
* admin_setting_configselect for the default number of sections in a course,
|
||||
* simply so we can lazy-load the choices.
|
||||
*
|
||||
* @deprecated since Moodle 5.2.
|
||||
* @todo Remove this class in Moodle 6.0 (MDL-85272).
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_settings_num_course_sections extends admin_setting_configselect {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the setting
|
||||
* @param string $visiblename The visible name of the setting
|
||||
* @param string $description The description of the setting
|
||||
* @param int $defaultsetting The default setting value
|
||||
* @deprecated since Moodle 5.2
|
||||
* @todo Final deprecation in Moodle 6.0 (MDL-84291)
|
||||
*/
|
||||
#[\core\attribute\deprecated(
|
||||
replacement: 'admin_setting_configtext',
|
||||
since: '5.1',
|
||||
mdl: 'MDL-84291',
|
||||
)]
|
||||
public function __construct($name, $visiblename, $description, $defaultsetting) {
|
||||
\core\deprecation::emit_deprecation_if_present(__FUNCTION__);
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting, array());
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,6 @@ class permission {
|
||||
return false;
|
||||
}
|
||||
$format = course_get_format($section->course);
|
||||
if ($format->get_last_section_number() >= $format->get_max_sections()) {
|
||||
return false;
|
||||
}
|
||||
if (!$format->supports_components()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
@mod @mod_subsection
|
||||
Feature: Teacher can only add subsection when certain conditions are met
|
||||
In order to limit subsections
|
||||
As an teacher
|
||||
I need to create subsections only when possible
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category | numsections | initsections |
|
||||
| Course 1 | C1 | 0 | 5 | 1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@javascript
|
||||
Scenario: We cannot add subsections when maxsections is reached
|
||||
Given the following config values are set as admin:
|
||||
| maxsections | 10 | moodlecourse |
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I click on "Add content" "button" in the "Section 1" "section"
|
||||
And I click on "Subsection" "link" in the ".dropdown-menu.show" "css_element"
|
||||
When the following config values are set as admin:
|
||||
| maxsections | 4 | moodlecourse |
|
||||
And I am on "Course 1" course homepage
|
||||
And I should see "You have reached the maximum number of sections allowed for a course."
|
||||
@@ -37,7 +37,6 @@ final class permission_test extends advanced_testcase {
|
||||
* @param bool $ismoddisabled
|
||||
* @param bool $missingcapability
|
||||
* @param bool $isdelegated
|
||||
* @param bool $maxsectionsreached
|
||||
* @param string $format
|
||||
* @param bool $expected
|
||||
*
|
||||
@@ -47,7 +46,6 @@ final class permission_test extends advanced_testcase {
|
||||
bool $ismoddisabled,
|
||||
bool $missingcapability,
|
||||
bool $isdelegated,
|
||||
bool $maxsectionsreached,
|
||||
string $format,
|
||||
bool $expected
|
||||
): void {
|
||||
@@ -68,10 +66,6 @@ final class permission_test extends advanced_testcase {
|
||||
assign_capability('mod/subsection:addinstance', CAP_PROHIBIT, $userrole, context_course::instance($course->id));
|
||||
}
|
||||
|
||||
if ($maxsectionsreached) {
|
||||
set_config('maxsections', 5, 'moodlecourse');
|
||||
}
|
||||
|
||||
if ($isdelegated) {
|
||||
$this->getDataGenerator()->create_module('subsection', ['course' => $course->id, 'section' => 1]);
|
||||
$targetsection = $courseformat->get_modinfo()->get_section_info(6);
|
||||
@@ -92,7 +86,6 @@ final class permission_test extends advanced_testcase {
|
||||
'ismoddisabled' => true,
|
||||
'missingcapability' => false,
|
||||
'isdelegated' => false,
|
||||
'maxsectionsreached' => false,
|
||||
'format' => 'topics',
|
||||
'expected' => false,
|
||||
],
|
||||
@@ -100,15 +93,6 @@ final class permission_test extends advanced_testcase {
|
||||
'ismoddisabled' => false,
|
||||
'missingcapability' => true,
|
||||
'isdelegated' => false,
|
||||
'maxsectionsreached' => false,
|
||||
'format' => 'topics',
|
||||
'expected' => false,
|
||||
],
|
||||
'Max sections reached' => [
|
||||
'ismoddisabled' => false,
|
||||
'missingcapability' => false,
|
||||
'isdelegated' => false,
|
||||
'maxsectionsreached' => true,
|
||||
'format' => 'topics',
|
||||
'expected' => false,
|
||||
],
|
||||
@@ -116,7 +100,6 @@ final class permission_test extends advanced_testcase {
|
||||
'ismoddisabled' => false,
|
||||
'missingcapability' => false,
|
||||
'isdelegated' => true,
|
||||
'maxsectionsreached' => false,
|
||||
'format' => 'topics',
|
||||
'expected' => false,
|
||||
],
|
||||
@@ -124,15 +107,13 @@ final class permission_test extends advanced_testcase {
|
||||
'ismoddisabled' => false,
|
||||
'missingcapability' => false,
|
||||
'isdelegated' => false,
|
||||
'maxsectionsreached' => false,
|
||||
'format' => 'singleactivity',
|
||||
'expected' => false,
|
||||
],
|
||||
'Plugin enabled, with capability, max sections not reached, not inside a delegated section' => [
|
||||
'Plugin enabled, with capability, not inside a delegated section' => [
|
||||
'ismoddisabled' => false,
|
||||
'missingcapability' => false,
|
||||
'isdelegated' => false,
|
||||
'maxsectionsreached' => false,
|
||||
'format' => 'topics',
|
||||
'expected' => true,
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user