diff --git a/course/format/classes/base.php b/course/format/classes/base.php index ba63e27851f..644a8b5d72f 100644 --- a/course/format/classes/base.php +++ b/course/format/classes/base.php @@ -693,6 +693,7 @@ abstract class base { * @param array $options options for view URL. At the moment core uses: * 'navigation' (bool) if true and section has no separate page, the function returns null * 'sr' (int) used by multipage formats to specify to which section to return + * 'expanded' (bool) if true the section will be shown expanded, true by default * @return null|moodle_url */ public function get_view_url($section, $options = array()) { @@ -712,6 +713,14 @@ abstract class base { return null; } if ($this->uses_sections() && $sectionno !== null) { + // The url includes the parameter to expand the section by default. + if (!array_key_exists('expanded', $options)) { + $options['expanded'] = true; + } + if ($options['expanded']) { + // This parameter is being set by default. + $url->param('expandsection', $sectionno); + } $url->set_anchor('section-'.$sectionno); } return $url; diff --git a/course/format/classes/output/local/content/section.php b/course/format/classes/output/local/content/section.php index e47b21c8729..dcac5d6b982 100644 --- a/course/format/classes/output/local/content/section.php +++ b/course/format/classes/output/local/content/section.php @@ -318,14 +318,7 @@ class section implements named_templatable, renderable { $data->collapsemenu = true; } - $data->contentcollapsed = false; - $preferences = $format->get_sections_preferences(); - if (isset($preferences[$section->id])) { - $sectionpreferences = $preferences[$section->id]; - if (!empty($sectionpreferences->contentcollapsed)) { - $data->contentcollapsed = true; - } - } + $data->contentcollapsed = $this->is_section_collapsed(); if ($format->is_section_current($section)) { $data->iscurrent = true; @@ -335,4 +328,30 @@ class section implements named_templatable, renderable { } return true; } + + /** + * Returns true if the current section should be shown collapsed. + * + * @return bool + */ + protected function is_section_collapsed(): bool { + global $PAGE; + + $contentcollapsed = false; + $preferences = $this->format->get_sections_preferences(); + if (isset($preferences[$this->section->id])) { + $sectionpreferences = $preferences[$this->section->id]; + if (!empty($sectionpreferences->contentcollapsed)) { + $contentcollapsed = true; + } + } + + // No matter if the user's preference was to collapse the section or not: If the + // 'expandsection' parameter has been specified, it will be shown uncollapsed. + $expandsection = $PAGE->url->get_param('expandsection'); + if ($expandsection !== null && $this->section->section == $expandsection) { + $contentcollapsed = false; + } + return $contentcollapsed; + } } diff --git a/course/format/tests/base_test.php b/course/format/tests/base_test.php index d22422895c2..fccc7686d75 100644 --- a/course/format/tests/base_test.php +++ b/course/format/tests/base_test.php @@ -235,6 +235,26 @@ class base_test extends advanced_testcase { $CFG->linkcoursesections = 1; $this->assertNotEmpty($format->get_view_url(1, ['navigation' => 1])); $this->assertNotEmpty($format->get_view_url(0, ['navigation' => 1])); + + // Expand section. + // The current course format $format uses the format 'testformat' which does not use sections. + // Thus, the 'expanded' parameter does not do anything. + $viewurl = $format->get_view_url(1); + $this->assertNull($viewurl->get_param('expandsection')); + $viewurl = $format->get_view_url(1, ['expanded' => 1]); + $this->assertNull($viewurl->get_param('expandsection')); + $viewurl = $format->get_view_url(1, ['expanded' => 0]); + $this->assertNull($viewurl->get_param('expandsection')); + // We now use a course format which uses sections. + $course2 = $generator->create_course(['format' => 'testformatsections']); + course_create_sections_if_missing($course1, [0, 2]); + $formatwithsections = course_get_format($course2); + $viewurl = $formatwithsections->get_view_url(2); + $this->assertEquals(2, $viewurl->get_param('expandsection')); + $viewurl = $formatwithsections->get_view_url(2, ['expanded' => 1]); + $this->assertEquals(2, $viewurl->get_param('expandsection')); + $viewurl = $formatwithsections->get_view_url(2, ['expanded' => 0]); + $this->assertNull($viewurl->get_param('expandsection')); } /** @@ -479,6 +499,27 @@ class format_testformat extends core_courseformat\base { } } +/** + * Class format_testformatsections. + * + * A test class that simulates a course format with sections. + * + * @package core_courseformat + * @copyright 2023 ISB Bayern + * @author Philipp Memmel + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class format_testformatsections extends core_courseformat\base { + /** + * Returns if this course format uses sections. + * + * @return true + */ + public function uses_sections() { + return true; + } +} + /** * Class format_testlegacy. * diff --git a/course/format/upgrade.txt b/course/format/upgrade.txt index 77d4ef7dd8a..c10e69e1808 100644 --- a/course/format/upgrade.txt +++ b/course/format/upgrade.txt @@ -17,6 +17,14 @@ Overview of this plugin type at http://docs.moodle.org/dev/Course_formats - New overridable checkboxes: content/cm/bulkselect.mustache and content/section/bulkselect.mustache * Plugins can use the CSS class "bulk-hidden" to hide elements when the bulk editing is enabled. * New core_courseformat\base::duplicate_section method to duplicate course sections and their modules within a course. +* The section renderer will now respect the new course view parameter 'expandsection'. If the course's view page + is being called with this parameter set to a section number, this section will be shown expanded. +* core_courseformat\base::get_view_url() now by default returns a url for the *expanded* section. This can be + changed by adding ['expanded' => false] to the options parameter of get_view_url(). +* The newly introduced protected method core_courseformat\output\local\content\section::is_section_collapsed() now + should be used by format plugins to determine if a section should be rendered collapsed or expanded at first. + This method can also be overwritten by course formats, but should respect the new 'expandsection' parameter when + doing so. === 4.1 === * New \core_courseformat\stateupdates methods add_section_remove() and add_cm_remove() have been added to replace diff --git a/course/view.php b/course/view.php index 49890b39a88..ed3c46c61ba 100644 --- a/course/view.php +++ b/course/view.php @@ -17,6 +17,7 @@ $idnumber = optional_param('idnumber', '', PARAM_RAW); $sectionid = optional_param('sectionid', 0, PARAM_INT); $section = optional_param('section', 0, PARAM_INT); + $expandsection = optional_param('expandsection', -1, PARAM_INT); $move = optional_param('move', 0, PARAM_INT); $marker = optional_param('marker',-1 , PARAM_INT); $switchrole = optional_param('switchrole',-1, PARAM_INT); // Deprecated, use course/switchrole.php instead. @@ -44,6 +45,9 @@ if ($section) { $urlparams['section'] = $section; } + if ($expandsection !== -1) { + $urlparams['expandsection'] = $expandsection; + } $PAGE->set_url('/course/view.php', $urlparams); // Defined here to avoid notices on errors etc