From ad07c084ac565bda85d9311000c112b14d7b1e2d Mon Sep 17 00:00:00 2001 From: James C <5689414+james-cnz@users.noreply.github.com> Date: Tue, 24 Mar 2026 21:40:11 +1300 Subject: [PATCH] Revamp get_view_url() --- changenumsections.php | 18 ++++--- classes/header.php | 7 +-- .../content/cm/delegatedcontrolmenu.php | 45 +++++++++++++++++ .../content/section/controlmenu.php | 10 ++-- .../courseformat/content/sectionselector.php | 6 +-- classes/tabs.php | 2 +- lib.php | 48 ++++++++++++------- 7 files changed, 92 insertions(+), 44 deletions(-) create mode 100644 classes/output/courseformat/content/cm/delegatedcontrolmenu.php diff --git a/changenumsections.php b/changenumsections.php index a4dea17..f8eeb28 100644 --- a/changenumsections.php +++ b/changenumsections.php @@ -37,6 +37,7 @@ $course = $DB->get_record('course', ['id' => $courseid], '*', MUST_EXIST); $courseformatoptions = course_get_format($course)->get_format_options(); +$anchortotabstree = get_config('format_onetopic', 'anchortotabstree'); $PAGE->set_url('/course/format/onetopic/changenumsections.php', ['courseid' => $courseid]); // Authorisation checks. @@ -64,7 +65,7 @@ $numsections = 0; if (!$returnurl) { - $returnurl = course_get_url($course); + $returnurl = course_get_url($course, null, ['anchortotabstree' => $anchortotabstree]); } } @@ -85,7 +86,7 @@ 'numsections' => $courseformatoptions['numsections'], ]); } if (!$returnurl) { - $returnurl = course_get_url($course); + $returnurl = course_get_url($course, null, ['anchortotabstree' => $anchortotabstree]); } } else if (course_get_format($course)->uses_sections() && $insertsection !== null) { if ($insertsection) { @@ -105,17 +106,14 @@ if (!$returnurl) { $returnurl = course_get_url( $course, - $sections[0]->section, - ($sectionreturn !== null) ? ['sr' => $sectionreturn] : [] + $sections[0], + array_merge( + ($sectionreturn !== null) ? ['sr' => $sectionreturn] : [], + ['anchortotabstree' => $anchortotabstree] + ) ); } } -$anchortotabstree = get_config('format_onetopic', 'anchortotabstree'); - -if ($anchortotabstree) { - $returnurl->set_anchor('tabs-tree-start'); -} - // Redirect to where we were.. redirect($returnurl); diff --git a/classes/header.php b/classes/header.php index ffaf2e9..da4ef1b 100644 --- a/classes/header.php +++ b/classes/header.php @@ -249,6 +249,7 @@ private function get_tabs(course_modinfo $modinfo, \core\output\renderer_base $o $sections = $modinfo->get_section_info_all(); $numsections = count($sections); $enablecustomstyles = get_config('format_onetopic', 'enablecustomstyles'); + $anchortotabstree = get_config('format_onetopic', 'anchortotabstree'); // Init custom tabs. $localsection = 0; @@ -416,11 +417,7 @@ private function get_tabs(course_modinfo $modinfo, \core\output\renderer_base $o } } - if ($localsection == 0) { - $url = new \core\url('/course/view.php', ['id' => $course->id, 'section' => 0]); - } else { - $url = course_get_url($course, $localsection); - } + $url = course_get_url($course, $localsection, ['anchortotabstree' => $anchortotabstree]); $specialclass = 'tab_position_' . $localsection . ' tab_level_' . $level; if ($course->marker == $localsection) { diff --git a/classes/output/courseformat/content/cm/delegatedcontrolmenu.php b/classes/output/courseformat/content/cm/delegatedcontrolmenu.php new file mode 100644 index 0000000..48dce55 --- /dev/null +++ b/classes/output/courseformat/content/cm/delegatedcontrolmenu.php @@ -0,0 +1,45 @@ +. + +namespace format_onetopic\output\courseformat\content\cm; + +use core\output\action_menu\link; +use core_courseformat\output\local\content\cm\delegatedcontrolmenu as delegatedcontrolmenubase; + +/** + * Class to render delegated section controls. + * + * @package format_onetopic + * @copyright 2026 James Calder and Otago Polytechnic + * @copyright based on work by 2024 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class delegatedcontrolmenu extends delegatedcontrolmenubase { + /** + * Retrieves the permalink item for the section control menu. + * + * @return link|null The menu item if applicable, otherwise null. + */ + protected function get_section_permalink_item(): ?link { + $link = parent::get_section_permalink_item(); + + if ($link) { + $link->url = $this->format->get_view_url($this->section, ['permalink' => true]); + } + + return $link; + } +} diff --git a/classes/output/courseformat/content/section/controlmenu.php b/classes/output/courseformat/content/section/controlmenu.php index 0ae9ff0..ad5634c 100644 --- a/classes/output/courseformat/content/section/controlmenu.php +++ b/classes/output/courseformat/content/section/controlmenu.php @@ -122,13 +122,9 @@ public function section_control_items() { // Create the permalink according to the Onetopic format. if (array_key_exists("permalink", $parentcontrols)) { - $sectionlink = new url( - '/course/view.php', - [ - 'id' => $course->id, - 'sectionid' => $section->id, - ], - 'tabs-tree-start' + $sectionlink = $format->get_view_url( + $section, + ['permalink' => true, 'anchortotabstree' => true] ); $parentcontrols['permalink'] = new link_secondary( diff --git a/classes/output/courseformat/content/sectionselector.php b/classes/output/courseformat/content/sectionselector.php index 90f3e01..c8f67b6 100644 --- a/classes/output/courseformat/content/sectionselector.php +++ b/classes/output/courseformat/content/sectionselector.php @@ -54,8 +54,6 @@ public function export_for_template(renderer_base $output): stdClass { $anchortotabstree = get_config('format_onetopic', 'anchortotabstree'); - $anchor = $anchortotabstree ? '#tabs-tree-start' : ''; - // Add the section selector. $sectionmenu = []; $section = ($course->realcoursedisplay == COURSE_DISPLAY_MULTIPAGE) ? 1 : 0; @@ -65,9 +63,9 @@ public function export_for_template(renderer_base $output): stdClass { $formatoptions = course_get_format($course)->get_format_options($thissection); $prefix = is_array($formatoptions) && $formatoptions['level'] > 0 ? '    ' : ''; - $url = course_get_url($course, $section); + $url = course_get_url($course, $section, ['anchortotabstree' => $anchortotabstree]); if ($thissection->uservisible && $url) { - $sectionmenu[$url->out(false) . $anchor] = $prefix . get_section_name($course, $section); + $sectionmenu[$url->out(false)] = $prefix . get_section_name($course, $section); } $section++; } diff --git a/classes/tabs.php b/classes/tabs.php index e07cac4..0a3e6e4 100644 --- a/classes/tabs.php +++ b/classes/tabs.php @@ -84,7 +84,7 @@ public function get_list(bool $assubtabs = false): array { } $newtab = new \stdClass(); - $newtab->link = $tab->link . ($anchortotabstree ? '#tabs-tree-start' : ''); + $newtab->link = $tab->link; $newtab->title = $tab->title; $newtab->text = $tab->content; $newtab->active = $tab->selected; diff --git a/lib.php b/lib.php index bba7e6e..d0fc2f8 100644 --- a/lib.php +++ b/lib.php @@ -420,35 +420,49 @@ public function page_title(): string { /** * The URL to use for the specified course (with section). * - * @param int|stdClass $section Section object from database or just field course_sections.section + * @param section_info|stdClass|int|null $section Section object from database or just field course_sections.section * if omitted the course view page is returned - * @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 + * @param array $options options for view URL. At the moment we use: * 'sr' (int) used by multipage formats to specify to which section to return + * 'permalink' (bool) if true, URL uses section IDs instead of section numbers + * 'anchortotabstree' (bool) if true, URL contains anchor for the tabs * @return null|\core\url */ - public function get_view_url($section, $options = []) { + public function get_view_url($section, $options = []): \core\url { $course = $this->get_course(); - $url = new \core\url('/course/view.php', ['id' => $course->id]); + $section = (is_null($section) || $section instanceof section_info) ? + $section + : $this->get_section($section, IGNORE_MISSING); + $permalink = $options['permalink'] ?? false; - $sr = null; if (array_key_exists('sr', $options)) { - $sr = $options['sr']; - } - if (is_object($section)) { - $sectionno = $section->section; + $pagesection = $this->get_section($options['sr'], IGNORE_MISSING); } else { - $sectionno = $section; + $pagesection = $section; + if ($pagesection && $pagesection->get_component_instance() && $pagesection->displaymode != 'summary') { + $pagesection = $pagesection->get_component_instance()->get_parent_section(); + } } - if ($sectionno !== null) { - if ($sr !== null) { - if ($sr) { - $sectionno = $sr; - } + + $url = new \core\url('/course/view.php', ['id' => $course->id]); + if ($pagesection) { + if ($permalink) { + $url->param('sectionid', $pagesection->id); + } else { + $url->param('section', $pagesection->section); } - $url->param('section', $sectionno); } + if ($section && $pagesection?->id != $section->id) { + if ($permalink) { + $url->set_anchor("sectionid-{$section->id}-title"); + } else { + $url->set_anchor("section-{$section->section}"); + } + } else if ($options['anchortotabstree'] ?? false) { + $url->set_anchor('tabs-tree-start'); + } + return $url; }