From ab71fb7eb42fdacb1260652d74491679e0206097 Mon Sep 17 00:00:00 2001 From: kateeht Date: Thu, 9 Jul 2026 11:53:26 +0200 Subject: [PATCH] [PIMDEV-882] - fix backup and codechecker --- .../backup_format_softcourse_plugin.class.php | 52 +++++++ ...restore_format_softcourse_plugin.class.php | 54 ++++--- classes/output/courseformat/content.php | 2 - .../output/courseformat/content/section.php | 147 +++++++++--------- classes/output/renderer.php | 20 ++- classes/privacy/provider.php | 1 - db/upgrade.php | 3 - externallib.php | 1 - format.php | 4 +- lib.php | 40 ++--- version.php | 4 +- 11 files changed, 193 insertions(+), 135 deletions(-) create mode 100644 backup/moodle2/backup_format_softcourse_plugin.class.php diff --git a/backup/moodle2/backup_format_softcourse_plugin.class.php b/backup/moodle2/backup_format_softcourse_plugin.class.php new file mode 100644 index 0000000..fab4026 --- /dev/null +++ b/backup/moodle2/backup_format_softcourse_plugin.class.php @@ -0,0 +1,52 @@ +. + +/** + * format_softcourse course format. + * Provides the information to backup grid course format + * + * @package format_softcourse + * @copyright 2026 Pimenko . + * @category backup + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_format_softcourse_plugin extends backup_format_plugin { + /** + * Returns the format information to attach to section element + */ + protected function define_course_plugin_structure() { + + // Define the virtual plugin element with the condition to fulfill. + $plugin = $this->get_plugin_element( + null, + '/course/format', + 'softcourse', + ); + + // Create one standard named plugin element (the visible container). + $pluginwrapper = new backup_nested_element($this->get_recommended_name()); + + $plugin->add_child($pluginwrapper); + + // Introduction. + $pluginwrapper->annotate_files('format_softcourse', 'introduction', null); + + // Section image. + $pluginwrapper->annotate_files('format_softcourse', 'sectionimage', null); + + return $plugin; + } +} diff --git a/backup/moodle2/restore_format_softcourse_plugin.class.php b/backup/moodle2/restore_format_softcourse_plugin.class.php index 18ea62f..0212551 100644 --- a/backup/moodle2/restore_format_softcourse_plugin.class.php +++ b/backup/moodle2/restore_format_softcourse_plugin.class.php @@ -15,16 +15,7 @@ // along with Moodle. If not, see . /** - * Specialised restore for format_softcourse - * - * @package format_softcourse - * @category backup - * @copyright 2021 Pimenko - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Specialised restore for format_softcourse + * Specialised restore for format_softcourse. * * Processes 'numsections' from the old backup files and hides sections that used to be "orphaned" * @@ -34,7 +25,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class restore_format_softcourse_plugin extends restore_format_plugin { - /** @var int */ protected $originalnumsections = 0; @@ -61,11 +51,14 @@ public function define_course_plugin_structure() { // Since this method is executed before the restore we can do some pre-checks here. // In case of merging backup into existing course find the current number of sections. $target = $this->step->get_task()->get_target(); - if (($target == backup::TARGET_CURRENT_ADDING || $target == backup::TARGET_EXISTING_ADDING) && - $this->need_restore_numsections()) { + if ( + ($target == backup::TARGET_CURRENT_ADDING || $target == backup::TARGET_EXISTING_ADDING) && + $this->need_restore_numsections() + ) { $maxsection = $DB->get_field_sql( 'SELECT max(section) FROM {course_sections} WHERE course = ?', - [$this->step->get_task()->get_courseid()]); + [$this->step->get_task()->get_courseid()] + ); $this->originalnumsections = (int)$maxsection; } @@ -77,7 +70,6 @@ public function define_course_plugin_structure() { * Dummy process method */ public function process_dummy_course() { - } /** @@ -86,7 +78,31 @@ public function process_dummy_course() { * This method is only executed if course configuration was overridden */ public function after_restore_course() { - global $DB; + global $DB, $CFG; + + $this->add_related_files('format_softcourse', 'introduction', null); + $this->add_related_files('format_softcourse', 'sectionimage', null); + + $courseid = $this->step->get_task()->get_courseid(); + $newcontext = \context_course::instance($courseid); + + $record = $DB->get_record('course_format_options', [ + 'courseid' => $courseid, + 'format' => 'softcourse', + 'name' => 'introduction', + ]); + + if ($record && !empty($record->value)) { + $newvalue = preg_replace( + '/\$@PLUGINFILEBYCONTEXT\*\d+@\$/', + $CFG->wwwroot . '/pluginfile.php/' . $newcontext->id, + $record->value + ); + if ($newvalue !== $record->value) { + $record->value = $newvalue; + $DB->update_record('course_format_options', $record); + } + } if (!$this->need_restore_numsections()) { // Backup file was made in Moodle 3.3 or later, we don't need to process 'numsecitons'. @@ -110,8 +126,10 @@ public function after_restore_course() { if ($this->step->get_task()->get_setting_value($key . '_included')) { $sectionnum = (int)$section->title; if ($sectionnum > $numsections && $sectionnum > $this->originalnumsections) { - $DB->execute("UPDATE {course_sections} SET visible = 0 WHERE course = ? AND section = ?", - [$this->step->get_task()->get_courseid(), $sectionnum]); + $DB->execute( + "UPDATE {course_sections} SET visible = 0 WHERE course = ? AND section = ?", + [$this->step->get_task()->get_courseid(), $sectionnum] + ); } } } diff --git a/classes/output/courseformat/content.php b/classes/output/courseformat/content.php index 568a359..10c1a06 100644 --- a/classes/output/courseformat/content.php +++ b/classes/output/courseformat/content.php @@ -34,12 +34,10 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class content extends content_base { - /** * @var bool Topic format has add section after each topic. * * The responsible for the buttons is core_courseformat\output\local\content\section. */ protected $hasaddsection = true; - } diff --git a/classes/output/courseformat/content/section.php b/classes/output/courseformat/content/section.php index 5791856..656791c 100644 --- a/classes/output/courseformat/content/section.php +++ b/classes/output/courseformat/content/section.php @@ -38,7 +38,6 @@ * @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; @@ -71,7 +70,6 @@ public function export_for_template(\renderer_base $output): stdClass { $data->insertafter = true; } return $data; - } // Prepare some cm_info we will need further. @@ -99,25 +97,31 @@ public function export_for_template(\renderer_base $output): stdClass { // We check case where section are hidden. // We check case where section have only one hidden activity. - if ((isset($data->visible) && $data->visible == 0) || (isset($data->uservisible) && $data->uservisible == false) || - (isset($data->available) && $data->available == false)) { + if ( + (isset($data->visible) && $data->visible == 0) || (isset($data->uservisible) && $data->uservisible == false) || + (isset($data->available) && $data->available == false) + ) { $data->skip = true; return $data; - } else if (isset($data->cmlist) && count($data->cmlist->cms) == 1 && - ((isset($data->cmlist->cms[0]->cminfo->visible) && $data->cmlist->cms[0]->cminfo->visible == 0) || - (isset($data->cmlist->cms[0]->cminfo->visibleoncoursepage) && - $data->cmlist->cms[0]->cminfo->visibleoncoursepage == 0) || - (isset($data->cmlist->cms[0]->cminfo->uservisible) && $data->cmlist->cms[0]->cminfo->uservisible == false) || - (isset($data->cmlist->cms[0]->cminfo->available) && $data->cmlist->cms[0]->cminfo->available == false))) { + } else if ( + isset($data->cmlist) && count($data->cmlist->cms) == 1 && + ( + (isset($data->cmlist->cms[0]->cminfo->visible) && $data->cmlist->cms[0]->cminfo->visible == 0) || + (isset($data->cmlist->cms[0]->cminfo->visibleoncoursepage) && + $data->cmlist->cms[0]->cminfo->visibleoncoursepage == 0) || + (isset($data->cmlist->cms[0]->cminfo->uservisible) && $data->cmlist->cms[0]->cminfo->uservisible == false) || + (isset($data->cmlist->cms[0]->cminfo->available) && $data->cmlist->cms[0]->cminfo->available == false) + ) + ) { $data->skip = true; return $data; } if (isset($data->name)) { $data->name = format_string( - $data->name, - true, - ['context' => context_course::instance($course->id)], + $data->name, + true, + ['context' => context_course::instance($course->id)], ); } @@ -126,50 +130,52 @@ public function export_for_template(\renderer_base $output): stdClass { $options->noclean = true; $options->overflowdiv = true; $data->summary->summarytext = format_text( - $data->summary->summarytext, - 1, - $options, + $data->summary->summarytext, + 1, + $options, ); $data->countactivitiestooltip = get_string( - 'countactivities', - 'format_softcourse', + 'countactivities', + 'format_softcourse', ); $data->countactivities = 0; // Check capability to edit/delete softcourse section picture. - if (has_capability( + if ( + has_capability( 'moodle/course:update', $context, - )) { + ) + ) { $data->update_img = get_string( - 'update_img', - 'format_softcourse', + 'update_img', + 'format_softcourse', ); $data->delete_img = get_string( - 'delete_img', - 'format_softcourse', + 'delete_img', + 'format_softcourse', ); } // Render the iamge section. $fs = get_file_storage(); $file = $fs->get_area_files( - $context->id, - 'format_softcourse', - 'sectionimage', - $data->num, - "itemid, filepath, filename", - false, + $context->id, + 'format_softcourse', + 'sectionimage', + $data->num, + "itemid, filepath, filename", + false, ); if ($file) { $data->urlimg = \moodle_url::make_pluginfile_url( - end($file)->get_contextid(), - end($file)->get_component(), - end($file)->get_filearea(), - end($file)->get_itemid(), - end($file)->get_filepath(), - end($file)->get_filename(), + end($file)->get_contextid(), + end($file)->get_component(), + end($file)->get_filearea(), + end($file)->get_itemid(), + end($file)->get_filepath(), + end($file)->get_filename(), ); } @@ -180,40 +186,38 @@ public function export_for_template(\renderer_base $output): stdClass { // Get completion of cms. foreach ($data->cmlist->cms as $cm) { - - // Check if $cm is a subsection + // Check if $cm is a subsection. if ($cm->cminfo->modname == 'subsection') { - // Loop through modules in the subsection + // Loop through modules in the subsection. $sectionid = $cm->cminfo->get_custom_data()['sectionid']; $sectionnum = get_fast_modinfo($course->id)->get_section_info_by_id($sectionid); $sectionmods = $sectionnum->get_sequence_cm_infos(); foreach ($sectionmods as $subsecmodule) { - - // Assuming $module, $data, $completioninfo, $nbcompletion, $nbcomplete are already defined + // Assuming $module, $data, $completioninfo, $nbcompletion, $nbcomplete are already defined. [ - $data, - $nbcompletion, - $nbcomplete - ] = $this->get_completion( - $subsecmodule, - $data, - $completioninfo, - $nbcompletion, - $nbcomplete, - ); - } - } else { - // Assuming $cm, $data, $completioninfo, $nbcompletion, $nbcomplete are already defined - [ $data, $nbcompletion, $nbcomplete - ] = $this->get_completion( - $cm, + ] = $this->get_completion( + $subsecmodule, $data, $completioninfo, $nbcompletion, $nbcomplete, + ); + } + } else { + // Assuming $cm, $data, $completioninfo, $nbcompletion, $nbcomplete are already defined. + [ + $data, + $nbcompletion, + $nbcomplete + ] = $this->get_completion( + $cm, + $data, + $completioninfo, + $nbcompletion, + $nbcomplete, ); } } @@ -221,8 +225,8 @@ public function export_for_template(\renderer_base $output): stdClass { // Count the percent of cm complete. if ($nbcompletion != 0) { $data->progression = get_string( - 'progression', - 'format_softcourse', + 'progression', + 'format_softcourse', ); $percentcomplete = $nbcomplete * 100 / $nbcompletion; $data->progression_percent = intval($percentcomplete); @@ -231,8 +235,8 @@ public function export_for_template(\renderer_base $output): stdClass { if ($data->start_url == null) { $data->disabledStart = 'true'; } - - //This is to add an add section(if you want to search go to /course/format/topics/classes/output/courseformat/content/section.php) + // This is to add an add section(if you want to search go to + // /course/format/topics/classes/output/courseformat/content/section.php). if (!$this->format->get_sectionnum()) { $addsectionclass = $format->get_output_classname('content\\addsection'); $addsection = new $addsectionclass($format); @@ -254,16 +258,16 @@ public function export_for_template(\renderer_base $output): stdClass { * * @return array An array containing updated data object, total completions, and total completed modules */ - function get_completion($cm, $data, $completioninfo, $nbcompletion, $nbcomplete) { - - // Determine if the desired information is in $cm or $cm->cminfo + public function get_completion($cm, $data, $completioninfo, $nbcompletion, $nbcomplete) { + // Determine if the desired information is in $cm or $cm->cminfo. $cminfo = property_exists($cm, 'cminfo') ? $cm->cminfo : false; if ($cminfo !== false) { - - if ((isset($cminfo->available) && $cminfo->available) && + if ( + (isset($cminfo->available) && $cminfo->available) && (($cminfo->uservisible && !$cminfo->is_stealth() && $cminfo->modname != 'label') || !empty($cm->url)) && - $data->first_cm_url == '') { + $data->first_cm_url == '' + ) { if ($cminfo->modname == 'resource') { $cminfo->url->param('forceview', 1); } @@ -279,9 +283,10 @@ function get_completion($cm, $data, $completioninfo, $nbcompletion, $nbcomplete) if (isset($cminfo)) { $nbcomplete += $completioninfo->get_data($cminfo, true)->completionstate; - - if ($cminfo->deletioninprogress == 0 && $cminfo->visible == 1 && $cminfo->modname != "label" && - $cminfo->visibleoncoursepage == 1 && $cminfo->uservisible && $cminfo->available == true) { + if ( + $cminfo->deletioninprogress == 0 && $cminfo->visible == 1 && $cminfo->modname != "label" && + $cminfo->visibleoncoursepage == 1 && $cminfo->uservisible && $cminfo->available == true + ) { $data->countactivities += 1; } } @@ -289,7 +294,7 @@ function get_completion($cm, $data, $completioninfo, $nbcompletion, $nbcomplete) return [ $data, $nbcompletion, - $nbcomplete + $nbcomplete, ]; } } diff --git a/classes/output/renderer.php b/classes/output/renderer.php index 4d67e85..81a7510 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -38,7 +38,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class renderer extends section_renderer { - /** * @var stdClass Course */ @@ -114,10 +113,12 @@ public function render_content($widget) { $context = context_course::instance($this->course->id); $data = $widget->export_for_template($this); - if ($this->page->user_is_editing() && has_capability( + if ( + $this->page->user_is_editing() && has_capability( 'moodle/course:update', $context, - )) { + ) + ) { // Base template. return $this->render_from_template( 'core_courseformat/local/content', @@ -143,7 +144,6 @@ public function render_content($widget) { } if ($this->courseformat->get_format_options()['hideallsections'] == 1) { - if (!$data->start_url) { foreach ($data->sections as $section) { if ($section->skip != true && $section->start_url != null) { @@ -153,7 +153,6 @@ public function render_content($widget) { } } $data->sections = false; - } else { if (!$data->start_url) { foreach ($data->sections as $section) { @@ -231,10 +230,12 @@ protected function section_edit_control_items($course, $section, $onsectionpage ); $controls = []; - if ($section->section && has_capability( + if ( + $section->section && has_capability( 'moodle/course:setcurrentsection', $coursecontext, - )) { + ) + ) { if ($course->marker == $section->section) { // Show the "light globe" on/off. $url->param( 'marker', @@ -287,10 +288,7 @@ protected function section_edit_control_items($course, $section, $onsectionpage ); // If the edit key exists, we are going to insert our controls after it. - if (array_key_exists( - "edit", - $parentcontrols, - )) { + if (array_key_exists("edit", $parentcontrols)) { $merged = []; // We can't use splice because we are using associative arrays. // Step through the array and merge the arrays. diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index b7c8f17..178cfe5 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -30,7 +30,6 @@ * @package YourPackageName */ class provider implements \core_privacy\local\metadata\null_provider { - /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. diff --git a/db/upgrade.php b/db/upgrade.php index f13483e..64e3680 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -34,7 +34,6 @@ function xmldb_format_softcourse_upgrade($oldversion) { require_once($CFG->dirroot . '/course/format/softcourse/db/upgradelib.php'); if ($oldversion < 2017020200) { - // Remove 'numsections' option and hide or delete orphaned sections. format_softcourse_upgrade_remove_numsections(); @@ -48,7 +47,6 @@ function xmldb_format_softcourse_upgrade($oldversion) { // Put any upgrade step following this. if ($oldversion < 2018030900) { - // During upgrade to Moodle 3.3 it could happen that general section (section 0) became 'invisible'. // It should always be visible. $DB->execute("UPDATE {course_sections} SET visible=1 WHERE visible=0 AND section=0 AND course IN @@ -57,7 +55,6 @@ function xmldb_format_softcourse_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2018030900, 'format', 'softcourse'); } if ($oldversion < 2019103100) { - // Get all sections 0 of courses having softcourse course format. $sectionsrequest = 'SELECT s.id, s.course, s.summary FROM {course_sections} s diff --git a/externallib.php b/externallib.php index 403fcf7..b1d8537 100644 --- a/externallib.php +++ b/externallib.php @@ -37,7 +37,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class format_softcourse_external extends external_api { - /** * Updates the section image for a given course section. * diff --git a/format.php b/format.php index 7088a51..69eef06 100644 --- a/format.php +++ b/format.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/filelib.php'); -require_once($CFG->libdir.'/completionlib.php'); +require_once($CFG->libdir . '/filelib.php'); +require_once($CFG->libdir . '/completionlib.php'); $context = context_course::instance($course->id); // Retrieve course format option fields and add them to the $course object. diff --git a/lib.php b/lib.php index 6ae1528..1959b35 100644 --- a/lib.php +++ b/lib.php @@ -36,7 +36,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class format_softcourse extends core_courseformat\base { - /** * Returns true if this course format uses sections. * @@ -123,10 +122,9 @@ public function get_view_url($section, $options = []) { [ 'id' => $course->id ], ); - if (array_key_exists( - 'sr', - $options, - ) && !is_null($options['sr'])) { + if ( + array_key_exists('sr', $options) && !is_null($options['sr']) + ) { $sectionno = $options['sr']; } else if (is_object($section)) { $sectionno = $section->section; @@ -134,12 +132,11 @@ public function get_view_url($section, $options = []) { $sectionno = $section; } - if ($this->uses_sections() && $sectionno !== null) { + if ( + $this->uses_sections() && $sectionno !== null + ) { // The url includes the parameter to expand the section by default. - if (!array_key_exists( - 'expanded', - $options, - )) { + if (!array_key_exists('expanded', $options)) { $options['expanded'] = true; } if ($options['expanded']) { @@ -244,10 +241,12 @@ public function extend_course_navigation($navigation, navigation_node $node) { null, PARAM_INT, ); - if ($selectedsection !== null && (!defined('AJAX_SCRIPT') || AJAX_SCRIPT == '0') && $PAGE->url->compare( + if ( + $selectedsection !== null && (!defined('AJAX_SCRIPT') || AJAX_SCRIPT == '0') && $PAGE->url->compare( new moodle_url('/course/view.php'), URL_MATCH_BASE, - )) { + ) + ) { $navigation->includesectionnum = $selectedsection; } } @@ -292,14 +291,8 @@ public function update_course_format_options($data, $oldcourse = null) { $oldcourse = (array) $oldcourse; $options = $this->course_format_options(); foreach ($options as $key => $unused) { - if (!array_key_exists( - $key, - $data, - )) { - if (array_key_exists( - $key, - $oldcourse, - )) { + if (!array_key_exists($key, $data)) { + if (array_key_exists($key, $oldcourse)) { $data[$key] = $oldcourse[$key]; } } @@ -592,10 +585,9 @@ protected function validate_format_options(array $rawdata, int $sectionid = null ); } - if ($option['element_type'] === 'select' && !array_key_exists( - $data[$key], - $option['element_attributes'][0], - )) { + if ( + $option['element_type'] === 'select' && !array_key_exists($data[$key], $option['element_attributes'][0]) + ) { // Value invalid for select element, skip. unset($data[$key]); } diff --git a/version.php b/version.php index d717a89..6701dff 100644 --- a/version.php +++ b/version.php @@ -24,8 +24,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2025011400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2026070900; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2022032200; // Requires this Moodle version. $plugin->component = 'format_softcourse'; // Full name of the plugin (used for diagnostics). -$plugin->release = '4.05.1'; +$plugin->release = '4.05.2'; $plugin->maturity = MATURITY_STABLE;