From 5eac72f6d86af8a81a53801f0ab4069459ad148e Mon Sep 17 00:00:00 2001 From: Gareth Barnard <1058419+gjb2048@users.noreply.github.com> Date: Sun, 11 Jun 2023 12:47:41 +0100 Subject: [PATCH] Convert 'numsections' to 'gnumsections' to facilitate both a course setting and flexible section management when editing. --- Changes.md | 1 + .../restore_format_grid_plugin.class.php | 5 +- classes/courseformat/stateactions.php | 80 +++++++++++++++++++ classes/output/courseformat/content.php | 4 - .../output/courseformat/content/section.php | 63 +++++++++++++++ db/upgrade.php | 17 ++++ format.php | 2 +- lang/en/format_grid.php | 2 +- lib.php | 69 +++++++++++----- templates/local/content.mustache | 4 - 10 files changed, 215 insertions(+), 32 deletions(-) create mode 100644 classes/courseformat/stateactions.php create mode 100644 classes/output/courseformat/content/section.php diff --git a/Changes.md b/Changes.md index 7fe7e3f7..3c28ef6d 100644 --- a/Changes.md +++ b/Changes.md @@ -4,6 +4,7 @@ Version 402.1.1 - TBR ---------------------------- 1. Fix 'Previous/Next section arrows are incorrect for RTL languages' - #183. 2. Fix 'Last section not showing its image when editing'. +3. Convert 'numsections' to 'gnumsections' to facilitate both a course setting and flexible section management when editing. Version 402.1.0 - 11/05/2023 ---------------------------- diff --git a/backup/moodle2/restore_format_grid_plugin.class.php b/backup/moodle2/restore_format_grid_plugin.class.php index 66bcda80..a90fcf8c 100644 --- a/backup/moodle2/restore_format_grid_plugin.class.php +++ b/backup/moodle2/restore_format_grid_plugin.class.php @@ -152,8 +152,11 @@ public function after_restore_course() { $maxsection = $DB->get_field_sql('SELECT max(section) FROM {course_sections} WHERE course = ?', [$courseid]); - $courseformat->restore_numsections($maxsection); + $courseformat->restore_gnumsections($maxsection); return; + } else { + // The backup file contains 'numsections' so we need to set 'gnumsections' to this value. + $courseformat->restore_gnumsections($settings['numsections']); } foreach ($backupinfo->sections as $key => $section) { diff --git a/classes/courseformat/stateactions.php b/classes/courseformat/stateactions.php new file mode 100644 index 00000000..1276768c --- /dev/null +++ b/classes/courseformat/stateactions.php @@ -0,0 +1,80 @@ +. + +namespace format_grid\courseformat; + +use core_courseformat\stateupdates; +use core_courseformat\stateactions as stateactions_base; +use stdClass; + +/** + * Contains the core course state actions specific to grid format. + * + * @package format_grid + * @copyright 2022 Ferran Recio + * @copyright © 2023-onwards G J Barnard based upon work done by Ferran Recio. + * @author G J Barnard - {@link https://gjbarnard.co.uk} and + * {@link http://moodle.org/user/profile.php?id=442195} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class stateactions extends stateactions_base { + + /** + * Create a course section. + * + * This method follows the same logic as changenumsections.php. + * + * @param stateupdates $updates the affected course elements track + * @param stdClass $course the course object + * @param int[] $ids not used + * @param int $targetsectionid optional target section id (if not passed section will be appended) + * @param int $targetcmid not used + */ + public function section_add( + stateupdates $updates, + stdClass $course, + array $ids = [], + ?int $targetsectionid = null, + ?int $targetcmid = null + ): void { + parent::section_add($updates, $course, $ids, $targetsectionid, $targetcmid); + $format = course_get_format($course); + $format->section_added(); + } + + /** + * Delete course sections. + * + * This method follows the same logic as editsection.php. + * + * @param stateupdates $updates the affected course elements track + * @param stdClass $course the course object + * @param int[] $ids section ids + * @param int $targetsectionid not used + * @param int $targetcmid not used + */ + public function section_delete( + stateupdates $updates, + stdClass $course, + array $ids = [], + ?int $targetsectionid = null, + ?int $targetcmid = null + ): void { + parent::section_delete($updates, $course, $ids, $targetsectionid, $targetcmid); + $format = course_get_format($course); + $format->section_deleted(); + } +} diff --git a/classes/output/courseformat/content.php b/classes/output/courseformat/content.php index 51cdebd7..1b6c8c81 100644 --- a/classes/output/courseformat/content.php +++ b/classes/output/courseformat/content.php @@ -77,10 +77,6 @@ public function export_for_template(\renderer_base $output) { $course = $format->get_course(); $currentsectionid = 0; - if ($editing) { - $data->coursesettings = new \moodle_url('/course/edit.php', array('id' => $course->id)); - } - if (!empty($sections)) { // Most formats uses section 0 as a separate section so we remove from the list. $initialsection = array_shift($sections); diff --git a/classes/output/courseformat/content/section.php b/classes/output/courseformat/content/section.php new file mode 100644 index 00000000..49eb82f5 --- /dev/null +++ b/classes/output/courseformat/content/section.php @@ -0,0 +1,63 @@ +. + +/** + * Contains the default section controls output class. + * + * @package format_grid + * @copyright 2020 Ferran Recio + * @copyright © 2023-onwards G J Barnard based upon work done by Ferran Recio. + * @author G J Barnard - {@link https://gjbarnard.co.uk} and + * {@link http://moodle.org/user/profile.php?id=442195} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace format_grid\output\courseformat\content; + +use core_courseformat\base as course_format; +use core_courseformat\output\local\content\section as section_base; +use stdClass; + +/** + * Class to render a course section. + * + * @package format_grid + * @copyright 2020 Ferran Recio + * @copyright © 2023-onwards G J Barnard based upon work done by Ferran Recio. + * @author G J Barnard - {@link https://gjbarnard.co.uk} and + * {@link http://moodle.org/user/profile.php?id=442195} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class section extends section_base { + + /** @var course_format the course format */ + protected $format; + + public function export_for_template(\renderer_base $output): stdClass { + $format = $this->format; + + $data = parent::export_for_template($output); + + if (!$this->format->get_section_number()) { + $addsectionclass = $format->get_output_classname('content\\addsection'); + $addsection = new $addsectionclass($format); + $data->numsections = $addsection->export_for_template($output); + $data->insertafter = true; + } + + return $data; + } +} diff --git a/db/upgrade.php b/db/upgrade.php index 94d9b478..84a20356 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -167,6 +167,23 @@ function xmldb_format_grid_upgrade($oldversion = 0) { upgrade_plugin_savepoint(true, 2022072200, 'format', 'grid'); } + if ($oldversion < 2023051001) { + $records = $DB->get_records('course_format_options', + array( + 'format' => 'grid', + 'name' => 'numsections' + ), '', 'id' + ); + + $records = array_keys($records); + foreach ($records as $id) { + $DB->set_field('course_format_options', 'name', 'gnumsections', array('id' => $id)); + } + + // Grid savepoint reached. + upgrade_plugin_savepoint(true, 2023051001, 'format', 'grid'); + } + // Automatic 'Purge all caches'.... purge_all_caches(); diff --git a/format.php b/format.php index aa17e504..03f093c2 100755 --- a/format.php +++ b/format.php @@ -53,7 +53,7 @@ } // Make sure section 0 is created. -course_create_sections_if_missing($course, range(0, $course->numsections )); +course_create_sections_if_missing($course, 0); $renderer = $PAGE->get_renderer('format_grid'); diff --git a/lang/en/format_grid.php b/lang/en/format_grid.php index 4a11d2ee..4d90adef 100644 --- a/lang/en/format_grid.php +++ b/lang/en/format_grid.php @@ -39,6 +39,7 @@ $string['page-course-view-grid-x'] = 'Any course page in the grid format'; $string['addsection'] = 'Add section'; +$string['addsections'] = 'Add section'; $string['hidefromothers'] = 'Hide section'; // No longer used kept for legacy versions. $string['showfromothers'] = 'Show section'; // No longer used kept for legacy versions. $string['currentsection'] = 'This section'; // No longer used kept for legacy versions. @@ -124,7 +125,6 @@ $string['informationsettings'] = 'Information settings'; $string['informationsettingsdesc'] = 'Grid format information'; $string['informationchanges'] = 'Changes'; -$string['sectionchangecoursesettings'] = 'Change the number of sections in the course settings'; $string['settings'] = 'Settings'; $string['settingssettings'] = 'Settings settings'; $string['settingssettingsdesc'] = 'Grid format settings'; diff --git a/lib.php b/lib.php index b73070c5..1658fc19 100755 --- a/lib.php +++ b/lib.php @@ -315,7 +315,7 @@ public function course_format_options($foreditform = false) { WHERE course = ?', array($courseid)); } $courseformatoptions = array( - 'numsections' => array( + 'gnumsections' => array( 'default' => $defaultnumsections, 'type' => PARAM_INT, ), @@ -358,7 +358,7 @@ public function course_format_options($foreditform = false) { $sectionmenu[$i] = "$i"; } $courseformatoptionsedit = array( - 'numsections' => array( + 'gnumsections' => array( 'label' => new lang_string('numbersections', 'format_grid'), 'element_type' => 'select', 'element_attributes' => array($sectionmenu), @@ -515,10 +515,10 @@ public function create_edit_form_elements(&$mform, $forsection = false) { activities / resources. */ if (!$forsection) { $maxsections = get_config('moodlecourse', 'maxsections'); - $numsections = $mform->getElementValue('numsections'); + $numsections = $mform->getElementValue('gnumsections'); $numsections = $numsections[0]; if ($numsections > $maxsections) { - $element = $mform->getElement('numsections'); + $element = $mform->getElement('gnumsections'); for ($i = $maxsections + 1; $i <= $numsections; $i++) { $element->addOption("$i", $i); } @@ -553,14 +553,19 @@ public function update_course_format_options($data, $oldcourse = null) { if (!array_key_exists($key, $data)) { if (array_key_exists($key, $oldcourse)) { $data[$key] = $oldcourse[$key]; - } else if ($key === 'numsections') { - /* If previous format does not have the field 'numsections' and $data['numsections'] is not set, - we fill it with the maximum section number from the DB. */ - $maxsection = $DB->get_field_sql('SELECT max(section) from {course_sections} - WHERE course = ?', array($this->courseid)); - if ($maxsection) { - // If there are no sections, or just default 0-section, 'numsections' will be set to default. - $data['numsections'] = $maxsection; + } else if ($key === 'gnumsections') { + if (array_key_exists('numsections', $oldcourse)) { + // Transpose numsections to gnumsections. + $data[$key] = $oldcourse['numsections']; + } else { + /* The previous format does not have the field 'numsections' and $data['gnumsections'] is not set, + we fill it with the maximum section number from the DB. */ + $maxsection = $DB->get_field_sql('SELECT max(section) from {course_sections} + WHERE course = ?', array($this->courseid)); + if ($maxsection) { + // If there are no sections, or just default 0-section, 'gnumsections' will be set to default. + $data['gnumsections'] = $maxsection; + } } } } @@ -568,15 +573,21 @@ public function update_course_format_options($data, $oldcourse = null) { } $changes = $this->update_format_options($data); - if ($changes && array_key_exists('numsections', $data)) { - // If the numsections was decreased, try to completely delete the orphaned sections (unless they are not empty). - $numsections = (int)$data['numsections']; + if ($changes && array_key_exists('gnumsections', $data)) { + $numsections = (int)$data['gnumsections']; $maxsection = $DB->get_field_sql('SELECT max(section) from {course_sections} WHERE course = ?', array($this->courseid)); - for ($sectionnum = $maxsection; $sectionnum > $numsections; $sectionnum--) { - if (!$this->delete_section($sectionnum, false)) { - break; + if ($numsections < $maxsection) { + // The setting gnumsections has decreased, try to completely delete the orphaned sections (unless they are not empty). + for ($sectionnum = $maxsection; $sectionnum > $numsections; $sectionnum--) { + if (!$this->delete_section($sectionnum, false)) { + break; + } } + } else if ($numsections > $maxsection) { + // The setting gnumsections has increased then create the sections. + $course = $this->get_course(); + course_create_sections_if_missing($course, range(0, $numsections )); } } @@ -785,14 +796,30 @@ public function section_action($section, $action, $sr) { } /** - * Restores the numsections if was not in the backup. + * Restores the numsections if was not in the backup or if it was then transposes to gnumsections. * @param int $numsections The number of sections. */ - public function restore_numsections($numsections) { - $data = array('numsections' => $numsections); + public function restore_gnumsections($numsections) { + $data = array('gnumsections' => $numsections); $this->update_course_format_options($data); } + /** + * A section has been added. Should only be called from the state actions instance. + */ + public function section_added() { + $data = array('gnumsections' => $this->settings['gnumsections'] + 1); + $this->update_format_options($data); + } + + /** + * A section has been deleted. Should only be called from the state actions instance. + */ + public function section_deleted() { + $data = array('gnumsections' => $this->settings['gnumsections'] - 1); + $this->update_format_options($data); + } + /** * Return the plugin configs for external functions. * diff --git a/templates/local/content.mustache b/templates/local/content.mustache index a0692a92..50e2bc44 100644 --- a/templates/local/content.mustache +++ b/templates/local/content.mustache @@ -128,7 +128,6 @@ "selector": "" }, "sectionreturn": 1, - "coursesettings": "https://mymoodle/course/edit.php?id=4", "singlesection": { "num": 1, "id": 35, @@ -215,9 +214,6 @@ {{> core_courseformat/local/content/bulkedittools}} {{/ core_courseformat/local/content/bulkedittools}} {{/bulkedittools}} - {{#coursesettings}} - {{#str}}sectionchangecoursesettings, format_grid{{/str}} - {{/coursesettings}} {{#js}} require(['format_grid/local/content'], function(component) {