Skip to content

Commit

Permalink
MDL-57769 format_topics: remove numsections option
Browse files Browse the repository at this point in the history
  • Loading branch information
marinaglancy committed Mar 30, 2017
1 parent 89b909f commit af0698c
Show file tree
Hide file tree
Showing 11 changed files with 323 additions and 128 deletions.
7 changes: 4 additions & 3 deletions backup/util/ui/tests/behat/restore_moodle2_courses.feature
Expand Up @@ -41,11 +41,11 @@ Feature: Restore Moodle 2 course backups
Then I should see "Course 1 restored in a new course"
And I should see "Community finder" in the "Community finder" "block"
And I should see "Test forum name"
And I should see "Topic 15"
And I should not see "Topic 16"
And I navigate to "Edit settings" node in "Course administration"
And I expand all fieldsets
And the field "id_format" matches value "Topics format"
And the field "Number of sections" matches value "15"
And the field "Course layout" matches value "Show one section per page"
And I press "Cancel"

@javascript
Expand Down Expand Up @@ -122,11 +122,12 @@ Feature: Restore Moodle 2 course backups
And I navigate to "Edit settings" node in "Course administration"
And I expand all fieldsets
Then the field "id_format" matches value "Topics format"
And the field "Number of sections" matches value "15"
And the field "Course layout" matches value "Show one section per page"
And I press "Cancel"
And section "3" should be hidden
And section "7" should be hidden
And section "15" should be visible
And I should see "Topic 15"
And I should not see "Topic 16"
And I should see "Test URL name" in the "Topic 3" "section"
And I should see "Test forum name" in the "Topic 1" "section"
47 changes: 47 additions & 0 deletions course/format/topics/db/upgrade.php
@@ -0,0 +1,47 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Upgrade scripts for course format "Topics"
*
* @package format_topics
* @copyright 2017 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

/**
* Upgrade script for format_topics
*
* @param int $oldversion the version we are upgrading from
* @return bool result
*/
function xmldb_format_topics_upgrade($oldversion) {
global $CFG, $DB;

require_once($CFG->dirroot . '/course/format/topics/db/upgradelib.php');

if ($oldversion < 2017020200) {

// Remove 'numsections' option and hide or delete orphaned sections.
format_topics_upgrade_remove_numsections();

upgrade_plugin_savepoint(true, 2017020200, 'format', 'topics');
}

return true;
}
117 changes: 117 additions & 0 deletions course/format/topics/db/upgradelib.php
@@ -0,0 +1,117 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Upgrade scripts for course format "Topics"
*
* @package format_topics
* @copyright 2017 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

/**
* This method finds all courses in 'topics' format that have actual number of sections
* bigger than their 'numsections' course format option.
* For each such course we call {@link format_topics_upgrade_hide_extra_sections()} and
* either delete or hide "orphaned" sections.
*/
function format_topics_upgrade_remove_numsections() {
global $DB;

$sql1 = "SELECT c.id, max(cs.section) AS sectionsactual
FROM {course} c
JOIN {course_sections} cs ON cs.course = c.id
WHERE c.format = :format1
GROUP BY c.id";

$sql2 = "SELECT c.id, n.value AS numsections
FROM {course} c
JOIN {course_format_options} n ON n.courseid = c.id AND n.format = :format1 AND n.name = :numsections AND n.sectionid = 0
WHERE c.format = :format2";

$params = ['format1' => 'topics', 'format2' => 'topics', 'numsections' => 'numsections'];

$actual = $DB->get_records_sql_menu($sql1, $params);
$numsections = $DB->get_records_sql_menu($sql2, $params);
$needfixing = [];

$defaultnumsections = get_config('moodlecourse', 'numsections');

foreach ($actual as $courseid => $sectionsactual) {
if (array_key_exists($courseid, $numsections)) {
$n = (int)$numsections[$courseid];
} else {
$n = $defaultnumsections;
}
if ($sectionsactual > $n) {
$needfixing[$courseid] = $n;
}
}
unset($actual);
unset($numsections);

foreach ($needfixing as $courseid => $numsections) {
format_topics_upgrade_hide_extra_sections($courseid, $numsections);
}

$DB->delete_records('course_format_options', ['format' => 'topics', 'sectionid' => 0, 'name' => 'numsections']);
}

/**
* Find all sections in the course with sectionnum bigger than numsections.
* Either delete these sections or hide them
*
* We will only delete a section if it is completely empty and all sections below
* it are also empty
*
* @param int $courseid
* @param int $numsections
*/
function format_topics_upgrade_hide_extra_sections($courseid, $numsections) {
global $DB;
$sections = $DB->get_records_sql('SELECT id, name, summary, sequence, visible
FROM {course_sections}
WHERE course = ? AND section > ?
ORDER BY section DESC', [$courseid, $numsections]);
$candelete = true;
$tohide = [];
$todelete = [];
foreach ($sections as $section) {
if ($candelete && (!empty($section->summary) || !empty($section->sequence) || !empty($section->name))) {
$candelete = false;
}
if ($candelete) {
$todelete[] = $section->id;
} else if ($section->visible) {
$tohide[] = $section->id;
}
}
if ($todelete) {
// Delete empty sections in the end.
// This is an upgrade script - no events or cache resets are needed.
// We also know that these sections do not have any modules so it is safe to just delete records in the table.
$DB->delete_records_list('course_sections', 'id', $todelete);
}
if ($tohide) {
// Hide other orphaned sections.
// This is different from what set_section_visible() does but we want to preserve actual
// module visibility in this case.
list($sql, $params) = $DB->get_in_or_equal($tohide);
$DB->execute("UPDATE {course_sections} SET visible = 0 WHERE id " . $sql, $params);
}
}
7 changes: 4 additions & 3 deletions course/format/topics/format.php
Expand Up @@ -38,15 +38,16 @@
// End backwards-compatible aliasing..

$context = context_course::instance($course->id);
// Retrieve course format option fields and add them to the $course object.
$course = course_get_format($course)->get_course();

if (($marker >=0) && has_capability('moodle/course:setcurrentsection', $context) && confirm_sesskey()) {
$course->marker = $marker;
course_set_marker($course->id, $marker);
}

// make sure all sections are created
$course = course_get_format($course)->get_course();
course_create_sections_if_missing($course, range(0, $course->numsections));
// Make sure section 0 is created.
course_create_sections_if_missing($course, 0);

$renderer = $PAGE->get_renderer('format_topics');

Expand Down
1 change: 1 addition & 0 deletions course/format/topics/lang/en/format_topics.php
Expand Up @@ -23,6 +23,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

$string['addsection'] = 'Add topic';
$string['currentsection'] = 'This topic';
$string['editsection'] = 'Edit topic';
$string['editsectionname'] = 'Edit topic name';
Expand Down
80 changes: 18 additions & 62 deletions course/format/topics/lib.php
Expand Up @@ -214,7 +214,6 @@ public function get_default_blocks() {
*
* Topics format uses the following options:
* - coursedisplay
* - numsections
* - hiddensections
*
* @param bool $foreditform
Expand All @@ -225,10 +224,6 @@ public function course_format_options($foreditform = false) {
if ($courseformatoptions === false) {
$courseconfig = get_config('moodlecourse');
$courseformatoptions = array(
'numsections' => array(
'default' => $courseconfig->numsections,
'type' => PARAM_INT,
),
'hiddensections' => array(
'default' => $courseconfig->hiddensections,
'type' => PARAM_INT,
Expand All @@ -240,21 +235,7 @@ public function course_format_options($foreditform = false) {
);
}
if ($foreditform && !isset($courseformatoptions['coursedisplay']['label'])) {
$courseconfig = get_config('moodlecourse');
$max = $courseconfig->maxsections;
if (!isset($max) || !is_numeric($max)) {
$max = 52;
}
$sectionmenu = array();
for ($i = 0; $i <= $max; $i++) {
$sectionmenu[$i] = "$i";
}
$courseformatoptionsedit = array(
'numsections' => array(
'label' => new lang_string('numberweeks'),
'element_type' => 'select',
'element_attributes' => array($sectionmenu),
),
'hiddensections' => array(
'label' => new lang_string('hiddensections'),
'help' => 'hiddensections',
Expand Down Expand Up @@ -295,42 +276,39 @@ public function course_format_options($foreditform = false) {
* @return array array of references to the added form elements.
*/
public function create_edit_form_elements(&$mform, $forsection = false) {
global $COURSE;
$elements = parent::create_edit_form_elements($mform, $forsection);

// Increase the number of sections combo box values if the user has increased the number of sections
// using the icon on the course page beyond course 'maxsections' or course 'maxsections' has been
// reduced below the number of sections already set for the course on the site administration course
// defaults page. This is so that the number of sections is not reduced leaving unintended orphaned
// activities / resources.
if (!$forsection) {
$maxsections = get_config('moodlecourse', 'maxsections');
$numsections = $mform->getElementValue('numsections');
$numsections = $numsections[0];
if ($numsections > $maxsections) {
$element = $mform->getElement('numsections');
for ($i = $maxsections+1; $i <= $numsections; $i++) {
$element->addOption("$i", $i);
}
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.
$courseconfig = get_config('moodlecourse');
$max = (int)$courseconfig->maxsections;
$element = $mform->addElement('select', 'numsections', get_string('numberweeks'), range(0, $max ?: 52));
$mform->setType('numsections', PARAM_INT);
if (is_null($mform->getElementValue('numsections'))) {
$mform->setDefault('numsections', $courseconfig->numsections);
}
array_unshift($elements, $element);
}

return $elements;
}

/**
* Updates format options for a course
*
* In case if course format was changed to 'topics', we try to copy options
* 'coursedisplay', 'numsections' and 'hiddensections' from the previous format.
* If previous course format did not have 'numsections' option, we populate it with the
* current number of sections
* 'coursedisplay' and 'hiddensections' from the previous format.
*
* @param stdClass|array $data return value from {@link moodleform::get_data()} or array with data
* @param stdClass $oldcourse if this function is called from {@link update_course()}
* this object contains information about the course before update
* @return bool whether there were any changes to the options values
*/
public function update_course_format_options($data, $oldcourse = null) {
global $DB;
$data = (array)$data;
if ($oldcourse !== null) {
$oldcourse = (array)$oldcourse;
Expand All @@ -339,33 +317,11 @@ 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;
}
}
}
}
}
$changed = $this->update_format_options($data);
if ($changed && 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'];
$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;
}
}
}
return $changed;
return $this->update_format_options($data);
}

/**
Expand Down Expand Up @@ -420,8 +376,8 @@ public function supports_news() {
* @return bool
*/
public function allow_stealth_module_visibility($cm, $section) {
// Allow the third visibility state inside visible sections or in section 0, not allow in orphaned sections.
return !$section->section || ($section->visible && $section->section <= $this->get_course()->numsections);
// Allow the third visibility state inside visible sections or in section 0.
return !$section->section || $section->visible;
}

public function section_action($section, $action, $sr) {
Expand Down
3 changes: 1 addition & 2 deletions course/format/topics/renderer.php
Expand Up @@ -119,9 +119,8 @@ protected function section_edit_control_items($course, $section, $onsectionpage
}
$url->param('sesskey', sesskey());

$isstealth = $section->section > $course->numsections;
$controls = array();
if (!$isstealth && $section->section && has_capability('moodle/course:setcurrentsection', $coursecontext)) {
if ($section->section && has_capability('moodle/course:setcurrentsection', $coursecontext)) {
if ($course->marker == $section->section) { // Show the "light globe" on/off.
$url->param('marker', 0);
$markedthistopic = get_string('markedthistopic');
Expand Down

0 comments on commit af0698c

Please sign in to comment.