Skip to content

Commit 18c994d

Browse files
committed
Merge branch 'master' into moodle_500_update_the_section_visibility_badge
2 parents 20ae871 + 9e9d7a7 commit 18c994d

13 files changed

Lines changed: 207 additions & 173 deletions

File tree

.github/workflows/moodle-ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111

1212
services:
1313
postgres:
14-
image: postgres:14 # Moodle 5.0
14+
image: postgres:15 # Moodle 5.1
1515
env:
1616
POSTGRES_USER: 'postgres'
1717
POSTGRES_HOST_AUTH_METHOD: 'trust'
@@ -42,13 +42,13 @@ jobs:
4242
plugin-ci: ^4
4343
# extensions: xmlrpc-beta
4444
# Moodle 5.1, PHP 8.3, MariaDB
45-
- php: '8.3'
45+
- php: '8.3' # 8.2-8.4
4646
moodle-branch: 'main'
4747
database: mariadb
4848
plugin-ci: ^4
4949
# extensions: xmlrpc-beta
5050
# Moodle 5.1, PHP 8.4, PostgresSQL
51-
- php: '8.4'
51+
- php: '8.4' # 8.2-8.4
5252
moodle-branch: 'main'
5353
database: pgsql
5454
plugin-ci: ^4

_course_changenumsections.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
* @since Moodle 2.3
3030
*/
3131

32+
use core_courseformat\formatactions; // ADDED.
33+
3234
require_once(__DIR__.'/../../../config.php'); // CHANGED.
3335
require_once($CFG->dirroot.'/course/lib.php');
34-
require_once(__DIR__.'/locallib.php');
35-
// ADDED LINE ABOVE: For function format_multitopic_course_create_section .
3636

3737
$courseid = required_param('courseid', PARAM_INT);
3838
$increase = optional_param('increase', null, PARAM_BOOL);
@@ -114,7 +114,7 @@
114114
}
115115
$sections = [];
116116
for ($i = 0; $i < max($numsections, 1); $i ++) {
117-
$sections[] = format_multitopic_course_create_section($course, $insertsection);
117+
$sections[] = formatactions::section($course)->fmt_create_from_object($insertsection);
118118
// CHANGED LINE ABOVE: Use custom method, and send section info, not section number.
119119
}
120120
$returnurl = course_get_url($course, $sections[0], []);

amd/build/courseformat/content.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/build/courseformat/content.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

amd/src/courseformat/content.js

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ export default class Component extends BaseComponent {
163163
*/
164164
getWatchers() {
165165
return super.getWatchers().concat([
166+
{watch: `section.fmtispage:updated`, handler: this._reloadSection},
167+
{watch: `section.collapsible:updated`, handler: this._reloadSection},
166168
{watch: `section.parentvisiblesan:updated`, handler: this._reloadSection},
167169
]);
168170
}
@@ -210,50 +212,35 @@ export default class Component extends BaseComponent {
210212
}
211213

212214
/**
213-
* Update a course section when the section number changes.
215+
* Update a course section name on the whole page.
214216
*
215-
* The courseActions module used for most course section tools still depends on css classes and
216-
* section numbers (not id). To prevent inconsistencies when a section is moved, we need to refresh
217-
* the
218-
*
219-
* Course formats can override the section title rendering so the frontend depends heavily on backend
220-
* rendering. Luckily in edit mode we can trigger a title update using the inplace_editable module.
221-
*
222-
* @param {Object} param
217+
* @param {object} param
223218
* @param {Object} param.element details the update details.
224219
*/
225-
_refreshSectionNumber({element}) {
220+
_refreshSectionTitle(param) {
221+
super._refreshSectionTitle(param);
222+
const element = param.element;
223+
226224
// Find the element.
227225
const target = this.getElement(this.selectors.SECTION, element.id);
228226
if (!target) {
229227
// Job done. Nothing to refresh.
230228
return;
231229
}
232-
// Update section numbers in all data, css and YUI attributes.
233-
target.id = `section-${element.number}`;
234-
// YUI uses section number as section id in data-sectionid, in principle if a format use components
235-
// don't need this sectionid attribute anymore, but we keep the compatibility in case some plugin
236-
// use it for legacy purposes.
237-
target.dataset.sectionid = element.number;
238-
// The data-number is the attribute used by components to store the section number.
239-
target.dataset.number = element.number;
240230

241231
// Update title and title inplace editable, if any.
242232
const inplace = inplaceeditable.getInplaceEditable(target.querySelector(this.selectors.SECTION_ITEM));
243233
if (inplace) {
244234
// The course content HTML can be modified at any moment, so the function need to do some checkings
245235
// to make sure the inplace editable still represents the same itemid.
246-
const currentvalue = inplace.getValue();
247236
const currentitemid = inplace.getItemId();
248-
// Unnamed sections must be recalculated.
249-
if (inplace.getValue() === '' || element.timed) { // CHANGED.
250-
// The value to send can be an empty value if it is a default name.
251-
if (currentitemid == element.id
252-
&& (currentvalue != element.rawtitle || element.rawtitle == '' || element.timed)) { // CHANGED.
253-
inplace.setValue(element.rawtitle);
254-
}
237+
if (currentitemid == element.id) { // CHANGED.
238+
inplace.setValue(element.rawtitle);
255239
}
256240
}
241+
242+
// Update subtitle.
243+
target.querySelector(".section_subtitle").textContent = element.subtitle;
257244
}
258245

259246
/**
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
namespace format_multitopic\courseformat;
18+
19+
use stdClass;
20+
use core_courseformat\local\sectionactions as base_sectionactions;
21+
22+
/**
23+
* Section course format actions.
24+
*
25+
* @package format_multitopic
26+
* @copyright 2024 onwards James Calder and Otago Polytechnic
27+
* @copyright based on work by 2023 Ferran Recio <ferran@moodle.com>
28+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29+
*/
30+
class sectionactions extends base_sectionactions {
31+
32+
/**
33+
* Create a course section using a record object.
34+
*
35+
* If no position is specified, the section is added to the end of the course.
36+
*
37+
* @param stdClass $fields the fields to set on the section
38+
* @param bool $skipcheck the position check has already been made and we know it can be used
39+
* @return stdClass the created section record
40+
*/
41+
public function fmt_create_from_object(stdClass $fields, bool $skipcheck = false): stdClass {
42+
global $DB;
43+
require_once(__DIR__.'/../../locallib.php');
44+
45+
$skipcheck = $skipcheck && isset($fields->section);
46+
47+
// Determine the create position, and adapt fields for the move method, if necessary.
48+
if ($skipcheck) {
49+
$createnum = $fields->section;
50+
} else {
51+
$createnum = $DB->get_field_sql(
52+
'SELECT max(section) from {course_sections} WHERE course = ?',
53+
[$this->course->id]
54+
) + 1;
55+
if (!isset($fields->section) && !isset($fields->prevupid) && !isset($fields->nextupid) && !isset($fields->parentid)) {
56+
$fields->nextupid = null;
57+
}
58+
if (empty($fields->component) && !isset($fields->level)) {
59+
$fields->level = 2;
60+
}
61+
}
62+
63+
// First add section to the end.
64+
$sectionrecord = (object) [
65+
'course' => $this->course->id,
66+
'section' => $createnum,
67+
'summary' => $fields->summary ?? '',
68+
'summaryformat' => $fields->summaryformat ?? FORMAT_HTML,
69+
'sequence' => '',
70+
'name' => $fields->name ?? null,
71+
'visible' => $fields->visible ?? 1,
72+
'availability' => $fields->availability ?? null,
73+
'component' => $fields->component ?? null,
74+
'itemid' => $fields->itemid ?? null,
75+
'timemodified' => time(),
76+
];
77+
$sectionrecord->id = $DB->insert_record("course_sections", $sectionrecord);
78+
if (empty($fields->component) && !($skipcheck && ($fields->section > 0))) {
79+
$DB->insert_record("course_format_options", [
80+
'courseid' => $this->course->id,
81+
'format' => 'multitopic',
82+
'sectionid' => $sectionrecord->id,
83+
'name' => 'level',
84+
'value' => 0,
85+
]);
86+
}
87+
88+
// Now move it to the specified position, if necessary.
89+
$skipmove = $skipcheck || !empty($fields->component) && property_exists($fields, 'nextupid') && ($fields->nextupid == null);
90+
if (!$skipmove) {
91+
try {
92+
$movednews = format_multitopic_move_section_to(
93+
$this->course, [$sectionrecord], $fields, !empty($fields->component) ? 2 : 1
94+
);
95+
$sectionrecord->section = $movednews[$sectionrecord->id]->section;
96+
} catch (\moodle_exception $e) {
97+
$DB->delete_records('course_sections', ['id' => $sectionrecord->id]);
98+
throw $e;
99+
}
100+
}
101+
102+
\core\event\course_section_created::create_from_section($sectionrecord)->trigger();
103+
104+
rebuild_course_cache($this->course->id, true);
105+
return $sectionrecord;
106+
}
107+
108+
}

0 commit comments

Comments
 (0)