mirror of
https://github.com/moodle/moodle.git
synced 2025-04-15 05:25:08 +02:00
Merge branch 'MDL-80191-main-v06' of https://github.com/ferranrecio/moodle
This commit is contained in:
commit
4fcea1f716
@ -38,6 +38,9 @@ abstract class backup_activity_task extends backup_task {
|
||||
|
||||
protected $moduleid;
|
||||
protected $sectionid;
|
||||
|
||||
/** @var stdClass the section object */
|
||||
protected $section;
|
||||
protected $modulename;
|
||||
protected $activityid;
|
||||
protected $contextid;
|
||||
@ -50,6 +53,7 @@ abstract class backup_activity_task extends backup_task {
|
||||
* @param backup_plan|null $plan the backup plan instance this task is part of
|
||||
*/
|
||||
public function __construct($name, $moduleid, $plan = null) {
|
||||
global $DB;
|
||||
|
||||
// Check moduleid exists
|
||||
if (!$coursemodule = get_coursemodule_from_id(false, $moduleid)) {
|
||||
@ -65,6 +69,7 @@ abstract class backup_activity_task extends backup_task {
|
||||
$this->modulename = $coursemodule->modname;
|
||||
$this->activityid = $coursemodule->instance;
|
||||
$this->contextid = context_module::instance($this->moduleid)->id;
|
||||
$this->section = $DB->get_record('course_sections', ['id' => $this->sectionid]);
|
||||
|
||||
parent::__construct($name, $plan);
|
||||
}
|
||||
@ -90,6 +95,16 @@ abstract class backup_activity_task extends backup_task {
|
||||
return $this->modulename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the activity is inside a subsection.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_in_subsection(): bool {
|
||||
return !empty($this->section->component);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int the id of the activity instance (id in the activity's instances table)
|
||||
*/
|
||||
@ -123,12 +138,12 @@ abstract class backup_activity_task extends backup_task {
|
||||
}
|
||||
|
||||
// Add some extra settings that related processors are going to need
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_MODID, base_setting::IS_INTEGER, $this->moduleid));
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_COURSEID, base_setting::IS_INTEGER, $this->get_courseid()));
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_SECTIONID, base_setting::IS_INTEGER, $this->sectionid));
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_MODNAME, base_setting::IS_FILENAME, $this->modulename));
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_ACTIVITYID, base_setting::IS_INTEGER, $this->activityid));
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_CONTEXTID, base_setting::IS_INTEGER, $this->contextid));
|
||||
$this->add_section_setting(backup::VAR_MODID, base_setting::IS_INTEGER, $this->moduleid);
|
||||
$this->add_section_setting(backup::VAR_COURSEID, base_setting::IS_INTEGER, $this->get_courseid());
|
||||
$this->add_section_setting(backup::VAR_SECTIONID, base_setting::IS_INTEGER, $this->sectionid);
|
||||
$this->add_section_setting(backup::VAR_MODNAME, base_setting::IS_FILENAME, $this->modulename);
|
||||
$this->add_section_setting(backup::VAR_ACTIVITYID, base_setting::IS_INTEGER, $this->activityid);
|
||||
$this->add_section_setting(backup::VAR_CONTEXTID, base_setting::IS_INTEGER, $this->contextid);
|
||||
|
||||
// Create the activity directory
|
||||
$this->add_step(new create_taskbasepath_directory('create_activity_directory'));
|
||||
@ -269,58 +284,111 @@ abstract class backup_activity_task extends backup_task {
|
||||
$settingprefix = $this->modulename . '_' . $this->moduleid . '_';
|
||||
|
||||
// All these are common settings to be shared by all activities.
|
||||
|
||||
// Define activity_include (to decide if the whole task must be really executed)
|
||||
// Dependent of:
|
||||
// - activities root setting.
|
||||
// - section_included setting (if exists).
|
||||
$settingname = $settingprefix . 'included';
|
||||
$activityincluded = new backup_activity_generic_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
$activityincluded->get_ui()->set_icon(new image_icon('monologo', get_string('pluginname', $this->modulename),
|
||||
$this->modulename, array('class' => 'iconlarge icon-post ml-1')));
|
||||
$this->add_setting($activityincluded);
|
||||
// Look for "activities" root setting.
|
||||
$activities = $this->plan->get_setting('activities');
|
||||
$activities->add_dependency($activityincluded);
|
||||
$activityincluded = $this->add_activity_included_setting($settingprefix);
|
||||
|
||||
if (question_module_uses_questions($this->modulename)) {
|
||||
$questionbank = $this->plan->get_setting('questionbank');
|
||||
$questionbank->add_dependency($activityincluded);
|
||||
}
|
||||
|
||||
$this->add_activity_userinfo_setting($settingprefix, $activityincluded);
|
||||
|
||||
// End of common activity settings, let's add the particular ones.
|
||||
$this->define_my_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a setting to the task. This method is used to add a setting to the task
|
||||
*
|
||||
* @param int|string $identifier the identifier of the setting
|
||||
* @param string $type the type of the setting
|
||||
* @param string|int $value the value of the setting
|
||||
* @return section_backup_setting the setting added
|
||||
*/
|
||||
protected function add_section_setting(int|string $identifier, string $type, string|int $value): activity_backup_setting {
|
||||
if ($this->is_in_subsection()) {
|
||||
$setting = new backup_subactivity_generic_setting($identifier, $type, $value);
|
||||
} else {
|
||||
$setting = new backup_activity_generic_setting($identifier, $type, $value);
|
||||
}
|
||||
$this->add_setting($setting);
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the section include setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @return activity_backup_setting the setting added
|
||||
*/
|
||||
protected function add_activity_included_setting(string $settingprefix): activity_backup_setting {
|
||||
// Define activity_include (to decide if the whole task must be really executed)
|
||||
// Dependent of:
|
||||
// - activities root setting.
|
||||
// - sectionincluded setting (if exists).
|
||||
$settingname = $settingprefix . 'included';
|
||||
if ($this->is_in_subsection()) {
|
||||
$activityincluded = new backup_subactivity_generic_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
} else {
|
||||
$activityincluded = new backup_activity_generic_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
}
|
||||
$activityincluded->get_ui()->set_icon(new image_icon('monologo', get_string('pluginname', $this->modulename),
|
||||
$this->modulename, array('class' => 'iconlarge icon-post ml-1')));
|
||||
$this->add_setting($activityincluded);
|
||||
|
||||
// Look for "activities" root setting.
|
||||
$activities = $this->plan->get_setting('activities');
|
||||
$activities->add_dependency($activityincluded);
|
||||
|
||||
// Look for "sectionincluded" section setting (if exists).
|
||||
$settingname = 'section_' . $this->sectionid . '_included';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$sectionincluded = $this->plan->get_setting($settingname);
|
||||
$sectionincluded->add_dependency($activityincluded);
|
||||
}
|
||||
return $activityincluded;
|
||||
}
|
||||
|
||||
// Define activityuserinfo. Dependent of:
|
||||
/**
|
||||
* Add the section userinfo setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @param activity_backup_setting $includefield the setting to depend on
|
||||
* @return activity_backup_setting the setting added
|
||||
*/
|
||||
protected function add_activity_userinfo_setting(
|
||||
string $settingprefix,
|
||||
activity_backup_setting $includefield
|
||||
): activity_backup_setting {
|
||||
// Define activity_userinfo. Dependent of:
|
||||
// - users root setting.
|
||||
// - sectionuserinfo setting (if exists).
|
||||
// - activityincluded setting.
|
||||
// - includefield setting.
|
||||
$settingname = $settingprefix . 'userinfo';
|
||||
$activityuserinfo = new backup_activity_userinfo_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
if ($this->is_in_subsection()) {
|
||||
$activityuserinfo = new backup_subactivity_userinfo_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
} else {
|
||||
$activityuserinfo = new backup_activity_userinfo_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
}
|
||||
|
||||
$activityuserinfo->get_ui()->set_label('-');
|
||||
$activityuserinfo->get_ui()->set_visually_hidden_label(
|
||||
get_string('includeuserinfo_instance', 'core_backup', $this->name)
|
||||
);
|
||||
$this->add_setting($activityuserinfo);
|
||||
|
||||
// Look for "users" root setting.
|
||||
$users = $this->plan->get_setting('users');
|
||||
$users->add_dependency($activityuserinfo);
|
||||
|
||||
// Look for "sectionuserinfo" section setting (if exists).
|
||||
$settingname = 'section_' . $this->sectionid . '_userinfo';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$sectionuserinfo = $this->plan->get_setting($settingname);
|
||||
$sectionuserinfo->add_dependency($activityuserinfo);
|
||||
}
|
||||
// Look for "activityincluded" setting.
|
||||
$activityincluded->add_dependency($activityuserinfo);
|
||||
|
||||
// End of common activity settings, let's add the particular ones.
|
||||
$this->define_my_settings();
|
||||
$includefield->add_dependency($activityuserinfo);
|
||||
return $activityuserinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,6 +133,9 @@ abstract class backup_plan_builder {
|
||||
try {
|
||||
$plan->add_task(backup_factory::get_backup_activity_task($controller->get_format(), $id));
|
||||
|
||||
// Some activities may have delegated section integrations.
|
||||
self::build_delegated_section_plan($controller, $id);
|
||||
|
||||
// For the given activity, add as many block tasks as necessary
|
||||
$blockids = backup_plan_dbops::get_blockids_from_moduleid($id);
|
||||
foreach ($blockids as $blockid) {
|
||||
@ -150,6 +153,44 @@ abstract class backup_plan_builder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a course module delegated section backup plan.
|
||||
* @param backup_controller $controller
|
||||
* @param int $cmid the parent course module id.
|
||||
*/
|
||||
protected static function build_delegated_section_plan($controller, $cmid) {
|
||||
global $CFG, $DB;
|
||||
|
||||
// Check moduleid exists.
|
||||
if (!$coursemodule = get_coursemodule_from_id(false, $cmid)) {
|
||||
$controller->log(get_string('error_course_module_not_found', 'backup', $cmid), backup::LOG_WARNING);
|
||||
}
|
||||
$classname = 'mod_' . $coursemodule->modname . '\courseformat\sectiondelegate';
|
||||
if (!class_exists($classname)) {
|
||||
return;
|
||||
}
|
||||
$sectionid = null;
|
||||
try {
|
||||
$sectionid = $classname::delegated_section_id($coursemodule);
|
||||
} catch (dml_exception $error) {
|
||||
$controller->log(get_string('error_delegate_section_not_found', 'backup', $cmid), backup::LOG_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
$plan = $controller->get_plan();
|
||||
$sectiontask = backup_factory::get_backup_section_task($controller->get_format(), $sectionid);
|
||||
$sectiontask->set_delegated_cm($cmid);
|
||||
$plan->add_task($sectiontask);
|
||||
|
||||
// For the given section, add as many activity tasks as necessary.
|
||||
$coursemodules = backup_plan_dbops::get_modules_from_sectionid($sectionid);
|
||||
foreach ($coursemodules as $coursemodule) {
|
||||
if (plugin_supports('mod', $coursemodule->modname, FEATURE_BACKUP_MOODLE2)) {
|
||||
self::build_activity_plan($controller, $coursemodule->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build one 1-section backup
|
||||
*/
|
||||
@ -185,8 +226,13 @@ abstract class backup_plan_builder {
|
||||
|
||||
// For the given course, add as many section tasks as necessary
|
||||
$sections = backup_plan_dbops::get_sections_from_courseid($id);
|
||||
foreach ($sections as $section) {
|
||||
self::build_section_plan($controller, $section);
|
||||
foreach ($sections as $sectionid) {
|
||||
// Delegated sections are not course responsability.
|
||||
$sectiondata = backup_plan_dbops::get_section_from_id($sectionid);
|
||||
if (!empty($sectiondata->component)) {
|
||||
continue;
|
||||
}
|
||||
self::build_section_plan($controller, $sectionid);
|
||||
}
|
||||
|
||||
// For the given course, add as many block tasks as necessary
|
||||
|
@ -37,6 +37,16 @@ class backup_section_task extends backup_task {
|
||||
|
||||
protected $sectionid;
|
||||
|
||||
/**
|
||||
* @var stdClass $section The database section object.
|
||||
*/
|
||||
protected stdClass $section;
|
||||
|
||||
/**
|
||||
* @var int|null $delegatedcmid the course module that is delegating this section (if any)
|
||||
*/
|
||||
protected ?int $delegatedcmid = null;
|
||||
|
||||
/**
|
||||
* Constructor - instantiates one object of this class
|
||||
*/
|
||||
@ -48,11 +58,45 @@ class backup_section_task extends backup_task {
|
||||
throw new backup_task_exception('section_task_section_not_found', $sectionid);
|
||||
}
|
||||
|
||||
$this->section = $section;
|
||||
$this->sectionid = $sectionid;
|
||||
|
||||
parent::__construct($name, $plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the course module that is delegating this section.
|
||||
*
|
||||
* Delegated section can belong to any kind of plugin. However, when a delegated
|
||||
* section belongs to a course module, the UI will present all settings according.
|
||||
*
|
||||
* @param int $cmid the course module id that is delegating this section
|
||||
*/
|
||||
public function set_delegated_cm(int $cmid) {
|
||||
$this->delegatedcmid = $cmid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the course module that is delegating this section.
|
||||
*
|
||||
* @return int|null the course module id that is delegating this section
|
||||
*/
|
||||
public function get_delegated_cm(): ?int {
|
||||
return $this->delegatedcmid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delegate activity modname (if any).
|
||||
*
|
||||
* @return string|null the modname of the delegated activity
|
||||
*/
|
||||
public function get_modname(): ?string {
|
||||
if (empty($this->section->component)) {
|
||||
return null;
|
||||
}
|
||||
return core_component::normalize_component($this->section->component)[1];
|
||||
}
|
||||
|
||||
public function get_sectionid() {
|
||||
return $this->sectionid;
|
||||
}
|
||||
@ -72,11 +116,11 @@ class backup_section_task extends backup_task {
|
||||
|
||||
// Set the backup::VAR_CONTEXTID setting to course context as far as next steps require that
|
||||
$coursectxid = context_course::instance($this->get_courseid())->id;
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_CONTEXTID, base_setting::IS_INTEGER, $coursectxid));
|
||||
$this->add_section_setting(backup::VAR_CONTEXTID, base_setting::IS_INTEGER, $coursectxid);
|
||||
|
||||
// Add some extra settings that related processors are going to need
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_SECTIONID, base_setting::IS_INTEGER, $this->sectionid));
|
||||
$this->add_setting(new backup_activity_generic_setting(backup::VAR_COURSEID, base_setting::IS_INTEGER, $this->get_courseid()));
|
||||
$this->add_section_setting(backup::VAR_SECTIONID, base_setting::IS_INTEGER, $this->sectionid);
|
||||
$this->add_section_setting(backup::VAR_COURSEID, base_setting::IS_INTEGER, $this->get_courseid());
|
||||
|
||||
// Create the section directory
|
||||
$this->add_step(new create_taskbasepath_directory('create_section_directory'));
|
||||
@ -145,32 +189,105 @@ class backup_section_task extends backup_task {
|
||||
// All the settings related to this activity will include this prefix.
|
||||
$settingprefix = 'section_' . $this->sectionid . '_';
|
||||
|
||||
// All these are common settings to be shared by all sections.
|
||||
$incudefield = $this->add_section_included_setting($settingprefix);
|
||||
$this->add_section_userinfo_setting($settingprefix, $incudefield);
|
||||
}
|
||||
|
||||
$section = $DB->get_record('course_sections', array('id' => $this->sectionid), '*', MUST_EXIST);
|
||||
$course = $DB->get_record('course', array('id' => $section->course), '*', MUST_EXIST);
|
||||
/**
|
||||
* Add a setting to the task. This method is used to add a setting to the task
|
||||
*
|
||||
* @param int|string $identifier the identifier of the setting
|
||||
* @param string $type the type of the setting
|
||||
* @param string|int $value the value of the setting
|
||||
* @return section_backup_setting the setting added
|
||||
*/
|
||||
protected function add_section_setting(int|string $identifier, string $type, string|int $value): section_backup_setting {
|
||||
if ($this->get_delegated_cm()) {
|
||||
$setting = new backup_subsection_generic_setting($identifier, $type, $value);
|
||||
} else {
|
||||
$setting = new backup_section_generic_setting($identifier, $type, $value);
|
||||
}
|
||||
$this->add_setting($setting);
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the section included setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @return section_backup_setting the setting added
|
||||
*/
|
||||
protected function add_section_included_setting(string $settingprefix): section_backup_setting {
|
||||
global $DB;
|
||||
$course = $DB->get_record('course', ['id' => $this->section->course], '*', MUST_EXIST);
|
||||
|
||||
// Define sectionincluded (to decide if the whole task must be really executed).
|
||||
$settingname = $settingprefix . 'included';
|
||||
$sectionincluded = new backup_section_included_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
$sectionincluded->get_ui()->set_label(get_section_name($course, $section));
|
||||
|
||||
$delegatedcmid = $this->get_delegated_cm();
|
||||
if ($delegatedcmid) {
|
||||
$sectionincluded = new backup_subsection_included_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
// Subsections depends on the parent activity included setting.
|
||||
$settingname = $this->get_modname() . '_' . $delegatedcmid . '_included';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$cmincluded = $this->plan->get_setting($settingname);
|
||||
$cmincluded->add_dependency(
|
||||
$sectionincluded,
|
||||
);
|
||||
}
|
||||
$sectionincluded->get_ui()->set_label(get_string('subsectioncontent', 'backup'));
|
||||
} else {
|
||||
$sectionincluded = new backup_section_included_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
$sectionincluded->get_ui()->set_label(get_section_name($course, $this->section));
|
||||
}
|
||||
|
||||
$this->add_setting($sectionincluded);
|
||||
|
||||
return $sectionincluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the section userinfo setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @param section_backup_setting $includefield the setting to depend on
|
||||
* @return section_backup_setting the setting added
|
||||
*/
|
||||
protected function add_section_userinfo_setting(
|
||||
string $settingprefix,
|
||||
section_backup_setting $includefield
|
||||
): section_backup_setting {
|
||||
// Define sectionuserinfo. Dependent of:
|
||||
// - users root setting.
|
||||
// - sectionincluded setting.
|
||||
// - section_included setting.
|
||||
$settingname = $settingprefix . 'userinfo';
|
||||
$sectionuserinfo = new backup_section_userinfo_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
|
||||
$delegatedcmid = $this->get_delegated_cm();
|
||||
if ($delegatedcmid) {
|
||||
$sectionuserinfo = new backup_subsection_userinfo_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
// Subsections depends on the parent activity included setting.
|
||||
$settingname = $this->get_modname() . '_' . $delegatedcmid . '_userinfo';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$cmincluded = $this->plan->get_setting($settingname);
|
||||
$cmincluded->add_dependency(
|
||||
$sectionuserinfo,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$sectionuserinfo = new backup_section_userinfo_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
}
|
||||
|
||||
$sectionuserinfo->get_ui()->set_label(get_string('includeuserinfo', 'backup'));
|
||||
$sectionuserinfo->get_ui()->set_visually_hidden_label(
|
||||
get_string('section_prefix', 'core_backup', $section->name ?: $section->section)
|
||||
get_string('section_prefix', 'core_backup', $this->section->name ?: $this->section->section)
|
||||
);
|
||||
$this->add_setting($sectionuserinfo);
|
||||
|
||||
// Look for "users" root setting.
|
||||
$users = $this->plan->get_setting('users');
|
||||
$users->add_dependency($sectionuserinfo);
|
||||
// Look for "section_included" section setting.
|
||||
$sectionincluded->add_dependency($sectionuserinfo);
|
||||
$includefield->add_dependency($sectionuserinfo);
|
||||
|
||||
return $sectionuserinfo;
|
||||
}
|
||||
}
|
||||
|
@ -185,6 +185,45 @@ class backup_section_included_setting extends section_backup_setting {}
|
||||
*/
|
||||
class backup_section_userinfo_setting extends section_backup_setting {}
|
||||
|
||||
/**
|
||||
* Subsection base class (section delegated to a course module).
|
||||
*/
|
||||
class subsection_backup_setting extends section_backup_setting {
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $name Name of the setting
|
||||
* @param string $vtype Type of the setting, for example base_setting::IS_TEXT
|
||||
* @param mixed $value Value of the setting
|
||||
* @param bool $visibility Is the setting visible in the UI, for example base_setting::VISIBLE
|
||||
* @param int $status Status of the setting with regards to the locking, for example base_setting::NOT_LOCKED
|
||||
*/
|
||||
public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) {
|
||||
parent::__construct($name, $vtype, $value, $visibility, $status);
|
||||
$this->level = self::SUBSECTION_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generic section setting to pass various settings between tasks and steps
|
||||
*/
|
||||
class backup_subsection_generic_setting extends subsection_backup_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting to define if one section is included or no. Activities _included
|
||||
* settings depend of them if available
|
||||
*/
|
||||
class backup_subsection_included_setting extends subsection_backup_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* section backup setting to control if section will include
|
||||
* user information or no, depends of @backup_users_setting
|
||||
*/
|
||||
class backup_subsection_userinfo_setting extends subsection_backup_setting {
|
||||
}
|
||||
|
||||
|
||||
// Activity backup settings
|
||||
|
||||
@ -206,6 +245,46 @@ class backup_activity_included_setting extends activity_backup_setting {}
|
||||
*/
|
||||
class backup_activity_userinfo_setting extends activity_backup_setting {}
|
||||
|
||||
/**
|
||||
* Subactivity base class (activity inside a delegated section).
|
||||
*/
|
||||
class subactivity_backup_setting extends activity_backup_setting {
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $name Name of the setting
|
||||
* @param string $vtype Type of the setting, for example base_setting::IS_TEXT
|
||||
* @param mixed $value Value of the setting
|
||||
* @param bool $visibility Is the setting visible in the UI, for example base_setting::VISIBLE
|
||||
* @param int $status Status of the setting with regards to the locking, for example base_setting::NOT_LOCKED
|
||||
*/
|
||||
public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) {
|
||||
parent::__construct($name, $vtype, $value, $visibility, $status);
|
||||
$this->level = self::SUBACTIVITY_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic subactivity (activity inside a delegated section) setting to pass various settings between tasks and steps
|
||||
*/
|
||||
class backup_subactivity_generic_setting extends subactivity_backup_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subactivity (activity inside a delegated section) backup setting to control if activity will
|
||||
* be included or no, depends of @backup_activities_setting and
|
||||
* optionally parent section included setting
|
||||
*/
|
||||
class backup_subactivity_included_setting extends subactivity_backup_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subactivity (activity inside a delegated section) backup setting to control if activity will include
|
||||
* user information or no, depends of @backup_users_setting
|
||||
*/
|
||||
class backup_subactivity_userinfo_setting extends subactivity_backup_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* Root setting to control if backup will include content bank content or no
|
||||
*/
|
||||
|
@ -119,6 +119,20 @@ abstract class backup_activity_structure_step extends backup_structure_step {
|
||||
// Return the root element (activity)
|
||||
return $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a delegate section itemid mapping.
|
||||
*
|
||||
* @param string $pluginname the name of the plugin that is delegating the section.
|
||||
* @param int $itemid the itemid of the section being delegated.
|
||||
*/
|
||||
protected function set_delegated_section_mapping(string $pluginname, int $itemid) {
|
||||
backup_structure_dbops::insert_backup_ids_record(
|
||||
$this->get_backupid(),
|
||||
"course_section::$pluginname::$itemid",
|
||||
$this->task->get_moduleid()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2122,14 +2136,19 @@ class backup_main_structure_step extends backup_structure_step {
|
||||
|
||||
$activities = new backup_nested_element('activities');
|
||||
|
||||
$activity = new backup_nested_element('activity', null, array(
|
||||
'moduleid', 'sectionid', 'modulename', 'title',
|
||||
'directory'));
|
||||
$activity = new backup_nested_element(
|
||||
'activity',
|
||||
null,
|
||||
['moduleid', 'sectionid', 'modulename', 'title', 'directory', 'insubsection']
|
||||
);
|
||||
|
||||
$sections = new backup_nested_element('sections');
|
||||
|
||||
$section = new backup_nested_element('section', null, array(
|
||||
'sectionid', 'title', 'directory'));
|
||||
$section = new backup_nested_element(
|
||||
'section',
|
||||
null,
|
||||
['sectionid', 'title', 'directory', 'parentcmid', 'modname']
|
||||
);
|
||||
|
||||
$course = new backup_nested_element('course', null, array(
|
||||
'courseid', 'title', 'directory'));
|
||||
|
@ -100,6 +100,15 @@ abstract class restore_activity_task extends restore_task {
|
||||
return $this->moduleid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the activity is inside a subsection.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_in_subsection(): bool {
|
||||
return !empty($this->info->insubsection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the old course module id (cmid of activity which will be restored)
|
||||
*
|
||||
@ -288,42 +297,79 @@ abstract class restore_activity_task extends restore_task {
|
||||
* Define the common setting that any restore activity will have
|
||||
*/
|
||||
protected function define_settings() {
|
||||
|
||||
// All the settings related to this activity will include this prefix
|
||||
$settingprefix = $this->info->modulename . '_' . $this->info->moduleid . '_';
|
||||
|
||||
// All these are common settings to be shared by all activities
|
||||
$activityincluded = $this->add_activity_included_setting($settingprefix);
|
||||
$this->add_activity_userinfo_setting($settingprefix, $activityincluded);
|
||||
|
||||
// Define activity_include (to decide if the whole task must be really executed)
|
||||
// End of common activity settings, let's add the particular ones.
|
||||
$this->define_my_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the activity included setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @return activity_backup_setting the setting added
|
||||
*/
|
||||
protected function add_activity_included_setting(string $settingprefix): activity_backup_setting {
|
||||
// Define activity_included (to decide if the whole task must be really executed)
|
||||
// Dependent of:
|
||||
// - activities root setting
|
||||
// - section_included setting (if exists)
|
||||
// - activities root setting.
|
||||
// - sectionincluded setting (if exists).
|
||||
$settingname = $settingprefix . 'included';
|
||||
$activity_included = new restore_activity_generic_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
$activity_included->get_ui()->set_icon(new image_icon('monologo', get_string('pluginname', $this->modulename),
|
||||
$this->modulename, array('class' => 'iconlarge icon-post ml-1')));
|
||||
$this->add_setting($activity_included);
|
||||
// Look for "activities" root setting
|
||||
$activities = $this->plan->get_setting('activities');
|
||||
$activities->add_dependency($activity_included);
|
||||
// Look for "section_included" section setting (if exists)
|
||||
$settingname = 'section_' . $this->info->sectionid . '_included';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$section_included = $this->plan->get_setting($settingname);
|
||||
$section_included->add_dependency($activity_included);
|
||||
|
||||
if ($this->is_in_subsection()) {
|
||||
$activityincluded = new restore_subactivity_generic_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
} else {
|
||||
$activityincluded = new restore_activity_generic_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
}
|
||||
|
||||
// Define activity_userinfo. Dependent of:
|
||||
// - users root setting
|
||||
// - section_userinfo setting (if exists)
|
||||
// - activity_included setting.
|
||||
$activityincluded->get_ui()->set_icon(new image_icon('monologo', get_string('pluginname', $this->modulename),
|
||||
$this->modulename, ['class' => 'iconlarge icon-post ml-1']));
|
||||
$this->add_setting($activityincluded);
|
||||
// Look for "activities" root setting.
|
||||
$activities = $this->plan->get_setting('activities');
|
||||
$activities->add_dependency($activityincluded);
|
||||
// Look for "sectionincluded" section setting (if exists).
|
||||
$settingname = 'section_' . $this->info->sectionid . '_included';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$sectionincluded = $this->plan->get_setting($settingname);
|
||||
$sectionincluded->add_dependency($activityincluded);
|
||||
}
|
||||
|
||||
return $activityincluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the activity userinfo setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @param activity_backup_setting $includefield the activity included setting
|
||||
* @return activity_backup_setting the setting added
|
||||
*/
|
||||
protected function add_activity_userinfo_setting(
|
||||
string $settingprefix,
|
||||
activity_backup_setting $includefield
|
||||
): activity_backup_setting {
|
||||
// Define activityuserinfo. Dependent of:
|
||||
// - users root setting.
|
||||
// - sectionuserinfo setting (if exists).
|
||||
// - activity included setting.
|
||||
$settingname = $settingprefix . 'userinfo';
|
||||
$defaultvalue = false;
|
||||
if (isset($this->info->settings[$settingname]) && $this->info->settings[$settingname]) { // Only enabled when available
|
||||
$defaultvalue = true;
|
||||
}
|
||||
|
||||
$activity_userinfo = new restore_activity_userinfo_setting($settingname, base_setting::IS_BOOLEAN, $defaultvalue);
|
||||
if ($this->is_in_subsection()) {
|
||||
$activityuserinfo = new restore_subactivity_userinfo_setting($settingname, base_setting::IS_BOOLEAN, $defaultvalue);
|
||||
} else {
|
||||
$activityuserinfo = new restore_activity_userinfo_setting($settingname, base_setting::IS_BOOLEAN, $defaultvalue);
|
||||
}
|
||||
|
||||
if (!$defaultvalue) {
|
||||
// This is a bit hacky, but if there is no user data to restore, then
|
||||
// we replace the standard check-box with a select menu with the
|
||||
@ -333,30 +379,34 @@ abstract class restore_activity_task extends restore_task {
|
||||
// It would probably be better design to have a special UI class
|
||||
// setting_ui_checkbox_or_no, rather than this hack, but I am not
|
||||
// going to do that today.
|
||||
$activity_userinfo->set_ui(new backup_setting_ui_select($activity_userinfo, '-',
|
||||
array(0 => get_string('no'))));
|
||||
$activityuserinfo->set_ui(
|
||||
new backup_setting_ui_select(
|
||||
$activityuserinfo,
|
||||
'-',
|
||||
[0 => get_string('no')]
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$activity_userinfo->get_ui()->set_label('-');
|
||||
$activityuserinfo->get_ui()->set_label('-');
|
||||
}
|
||||
|
||||
$this->add_setting($activity_userinfo);
|
||||
$this->add_setting($activityuserinfo);
|
||||
|
||||
// Look for "users" root setting
|
||||
// Look for "users" root setting.
|
||||
$users = $this->plan->get_setting('users');
|
||||
$users->add_dependency($activity_userinfo);
|
||||
$users->add_dependency($activityuserinfo);
|
||||
|
||||
// Look for "section_userinfo" section setting (if exists)
|
||||
// Look for "sectionuserinfo" section setting (if exists).
|
||||
$settingname = 'section_' . $this->info->sectionid . '_userinfo';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$section_userinfo = $this->plan->get_setting($settingname);
|
||||
$section_userinfo->add_dependency($activity_userinfo);
|
||||
$sectionuserinfo = $this->plan->get_setting($settingname);
|
||||
$sectionuserinfo->add_dependency($activityuserinfo);
|
||||
}
|
||||
|
||||
// Look for "activity_included" setting.
|
||||
$activity_included->add_dependency($activity_userinfo);
|
||||
// Look for "activity included" setting.
|
||||
$includefield->add_dependency($activityuserinfo);
|
||||
|
||||
// End of common activity settings, let's add the particular ones.
|
||||
$this->define_my_settings();
|
||||
return $activityuserinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,6 +144,9 @@ abstract class restore_plan_builder {
|
||||
$plan->add_task($task);
|
||||
$controller->get_progress()->progress();
|
||||
|
||||
// Some activities may have delegated section integrations.
|
||||
self::build_delegated_section_plan($controller, $infoactivity->moduleid);
|
||||
|
||||
// For the given activity path, add as many block tasks as necessary
|
||||
// TODO: Add blocks, we need to introspect xml here
|
||||
$blocks = backup_general_helper::get_blocks_from_path($task->get_taskbasepath());
|
||||
@ -161,6 +164,30 @@ abstract class restore_plan_builder {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a course module delegated section backup plan.
|
||||
* @param restore_controller $controller
|
||||
* @param int $cmid the parent course module id.
|
||||
*/
|
||||
protected static function build_delegated_section_plan($controller, $cmid) {
|
||||
$info = $controller->get_info();
|
||||
|
||||
// Find if some section depends on that course module.
|
||||
$delegatedsectionid = null;
|
||||
foreach ($info->sections as $sectionid => $section) {
|
||||
// Delegated sections are not course responsability.
|
||||
if (isset($section->parentcmid) && $section->parentcmid == $cmid) {
|
||||
$delegatedsectionid = $sectionid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$delegatedsectionid) {
|
||||
return;
|
||||
}
|
||||
self::build_section_plan($controller, $delegatedsectionid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore one 1-section backup
|
||||
*/
|
||||
@ -215,6 +242,10 @@ abstract class restore_plan_builder {
|
||||
|
||||
// For the given course, add as many section tasks as necessary
|
||||
foreach ($info->sections as $sectionid => $section) {
|
||||
// Delegated sections are not course responsability.
|
||||
if (isset($section->parentcmid) && !empty($section->parentcmid)) {
|
||||
continue;
|
||||
}
|
||||
self::build_section_plan($controller, $sectionid);
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,30 @@ class restore_section_task extends restore_task {
|
||||
return $this->get_basepath() . '/sections/section_' . $this->info->sectionid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the course module that is delegating this section.
|
||||
*
|
||||
* @return int|null the course module id that is delegating this section
|
||||
*/
|
||||
public function get_delegated_cm(): ?int {
|
||||
if (!isset($this->info->parentcmid) || empty($this->info->parentcmid)) {
|
||||
return null;
|
||||
}
|
||||
return intval($this->info->parentcmid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delegated activity modname if any.
|
||||
*
|
||||
* @return string|null the modname of the delegated activity
|
||||
*/
|
||||
public function get_modname(): ?string {
|
||||
if (!isset($this->info->modname) || empty($this->info->modname)) {
|
||||
return null;
|
||||
}
|
||||
return $this->info->modname;
|
||||
}
|
||||
|
||||
public function set_sectionid($sectionid) {
|
||||
$this->sectionid = $sectionid;
|
||||
}
|
||||
@ -150,36 +174,95 @@ class restore_section_task extends restore_task {
|
||||
* Define the common setting that any restore section will have
|
||||
*/
|
||||
protected function define_settings() {
|
||||
|
||||
// All the settings related to this activity will include this prefix
|
||||
$settingprefix = 'section_' . $this->info->sectionid . '_';
|
||||
|
||||
// All these are common settings to be shared by all sections
|
||||
// All these are common settings to be shared by all sections.
|
||||
$sectionincluded = $this->add_section_included_setting($settingprefix);
|
||||
$this->add_section_userinfo_setting($settingprefix, $sectionincluded);
|
||||
}
|
||||
|
||||
// Define section_included (to decide if the whole task must be really executed)
|
||||
/**
|
||||
* Add the section included setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @return section_backup_setting the setting added
|
||||
*/
|
||||
protected function add_section_included_setting(string $settingprefix): section_backup_setting {
|
||||
global $DB;
|
||||
// Define sectionincluded (to decide if the whole task must be really executed).
|
||||
$settingname = $settingprefix . 'included';
|
||||
$section_included = new restore_section_included_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
if (is_number($this->info->title)) {
|
||||
$label = get_string('includesection', 'backup', $this->info->title);
|
||||
} elseif (empty($this->info->title)) { // Don't throw error if title is empty, gracefully continue restore.
|
||||
$this->log('Section title missing in backup for section id '.$this->info->sectionid, backup::LOG_WARNING, $this->name);
|
||||
$label = get_string('unnamedsection', 'backup');
|
||||
} else {
|
||||
$label = $this->info->title;
|
||||
}
|
||||
$section_included->get_ui()->set_label($label);
|
||||
$this->add_setting($section_included);
|
||||
|
||||
// Define section_userinfo. Dependent of:
|
||||
// - users root setting
|
||||
// - section_included setting.
|
||||
$delegatedcmid = $this->get_delegated_cm();
|
||||
if ($delegatedcmid) {
|
||||
$sectionincluded = new restore_subsection_included_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
// Subsections depends on the parent activity included setting.
|
||||
$settingname = $this->get_modname() . '_' . $delegatedcmid . '_included';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$cmincluded = $this->plan->get_setting($settingname);
|
||||
$cmincluded->add_dependency(
|
||||
$sectionincluded,
|
||||
);
|
||||
}
|
||||
$label = get_string('subsectioncontent', 'backup');
|
||||
} else {
|
||||
$sectionincluded = new restore_section_included_setting($settingname, base_setting::IS_BOOLEAN, true);
|
||||
|
||||
if (is_number($this->info->title)) {
|
||||
$label = get_string('includesection', 'backup', $this->info->title);
|
||||
} else if (empty($this->info->title)) { // Don't throw error if title is empty, gracefully continue restore.
|
||||
$this->log(
|
||||
'Section title missing in backup for section id ' . $this->info->sectionid,
|
||||
backup::LOG_WARNING,
|
||||
$this->name
|
||||
);
|
||||
$label = get_string('unnamedsection', 'backup');
|
||||
} else {
|
||||
$label = $this->info->title;
|
||||
}
|
||||
}
|
||||
|
||||
$sectionincluded->get_ui()->set_label($label);
|
||||
$this->add_setting($sectionincluded);
|
||||
|
||||
return $sectionincluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the section userinfo setting to the task.
|
||||
*
|
||||
* @param string $settingprefix the identifier of the setting
|
||||
* @param section_backup_setting $includefield the section included setting
|
||||
* @return section_backup_setting the setting added
|
||||
*/
|
||||
protected function add_section_userinfo_setting(
|
||||
string $settingprefix,
|
||||
section_backup_setting $includefield
|
||||
): section_backup_setting {
|
||||
// Define sectionuserinfo. Dependent of:
|
||||
// - users root setting.
|
||||
// - sectionincluded setting.
|
||||
$settingname = $settingprefix . 'userinfo';
|
||||
$defaultvalue = false;
|
||||
if (isset($this->info->settings[$settingname]) && $this->info->settings[$settingname]) { // Only enabled when available
|
||||
$defaultvalue = true;
|
||||
}
|
||||
|
||||
$section_userinfo = new restore_section_userinfo_setting($settingname, base_setting::IS_BOOLEAN, $defaultvalue);
|
||||
$delegatedcmid = $this->get_delegated_cm();
|
||||
if ($delegatedcmid) {
|
||||
$sectionuserinfo = new restore_subsection_userinfo_setting($settingname, base_setting::IS_BOOLEAN, $defaultvalue);
|
||||
// Subsections depends on the parent activity included setting.
|
||||
$settingname = $this->get_modname() . '_' . $delegatedcmid . '_userinfo';
|
||||
if ($this->plan->setting_exists($settingname)) {
|
||||
$cmincluded = $this->plan->get_setting($settingname);
|
||||
$cmincluded->add_dependency(
|
||||
$sectionuserinfo,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$sectionuserinfo = new restore_section_userinfo_setting($settingname, base_setting::IS_BOOLEAN, $defaultvalue);
|
||||
}
|
||||
|
||||
if (!$defaultvalue) {
|
||||
// This is a bit hacky, but if there is no user data to restore, then
|
||||
// we replace the standard check-box with a select menu with the
|
||||
@ -189,19 +272,23 @@ class restore_section_task extends restore_task {
|
||||
// It would probably be better design to have a special UI class
|
||||
// setting_ui_checkbox_or_no, rather than this hack, but I am not
|
||||
// going to do that today.
|
||||
$section_userinfo->set_ui(new backup_setting_ui_select($section_userinfo, get_string('includeuserinfo','backup'),
|
||||
array(0 => get_string('no'))));
|
||||
$sectionuserinfo->set_ui(
|
||||
new backup_setting_ui_select($sectionuserinfo,
|
||||
get_string('includeuserinfo', 'backup'), [0 => get_string('no')])
|
||||
);
|
||||
} else {
|
||||
$section_userinfo->get_ui()->set_label(get_string('includeuserinfo','backup'));
|
||||
$sectionuserinfo->get_ui()->set_label(get_string('includeuserinfo', 'backup'));
|
||||
}
|
||||
|
||||
$this->add_setting($section_userinfo);
|
||||
$this->add_setting($sectionuserinfo);
|
||||
|
||||
// Look for "users" root setting.
|
||||
$users = $this->plan->get_setting('users');
|
||||
$users->add_dependency($section_userinfo);
|
||||
$users->add_dependency($sectionuserinfo);
|
||||
|
||||
// Look for "section_included" section setting.
|
||||
$section_included->add_dependency($section_userinfo);
|
||||
// Look for "section included" section setting.
|
||||
$includefield->add_dependency($sectionuserinfo);
|
||||
|
||||
return $sectionuserinfo;
|
||||
}
|
||||
}
|
||||
|
@ -222,6 +222,39 @@ class restore_section_included_setting extends restore_section_generic_setting {
|
||||
*/
|
||||
class restore_section_userinfo_setting extends restore_section_generic_setting {}
|
||||
|
||||
/**
|
||||
* Subsection base class (delegated section).
|
||||
*/
|
||||
class restore_subsection_generic_setting extends restore_section_generic_setting {
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $name Name of the setting
|
||||
* @param string $vtype Type of the setting, for example base_setting::IS_TEXT
|
||||
* @param mixed $value Value of the setting
|
||||
* @param bool $visibility Is the setting visible in the UI, for example base_setting::VISIBLE
|
||||
* @param int $status Status of the setting with regards to the locking, for example base_setting::NOT_LOCKED
|
||||
*/
|
||||
public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) {
|
||||
parent::__construct($name, $vtype, $value, $visibility, $status);
|
||||
$this->level = self::SUBSECTION_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting to define if one subsection is included or no.
|
||||
*
|
||||
* Activities _included settings depend of them if available.
|
||||
*/
|
||||
class restore_subsection_included_setting extends restore_subsection_generic_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subsection backup setting to control if section will include
|
||||
* user information or no, depends of @restore_users_setting.
|
||||
*/
|
||||
class restore_subsection_userinfo_setting extends restore_subsection_generic_setting {
|
||||
}
|
||||
|
||||
// Activity backup settings
|
||||
|
||||
@ -243,6 +276,41 @@ class restore_activity_included_setting extends restore_activity_generic_setting
|
||||
*/
|
||||
class restore_activity_userinfo_setting extends restore_activity_generic_setting {}
|
||||
|
||||
/**
|
||||
* Generic subactivity setting to pass various settings between tasks and steps
|
||||
*/
|
||||
class restore_subactivity_generic_setting extends restore_activity_generic_setting {
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $name Name of the setting
|
||||
* @param string $vtype Type of the setting, for example base_setting::IS_TEXT
|
||||
* @param mixed $value Value of the setting
|
||||
* @param bool $visibility Is the setting visible in the UI, for example base_setting::VISIBLE
|
||||
* @param int $status Status of the setting with regards to the locking, for example base_setting::NOT_LOCKED
|
||||
*/
|
||||
public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) {
|
||||
parent::__construct($name, $vtype, $value, $visibility, $status);
|
||||
$this->level = self::SUBACTIVITY_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subactivity backup setting to control if activity will be included or no.
|
||||
*
|
||||
* Depends of restore_activities_setting and optionally parent section included setting.
|
||||
*/
|
||||
class restore_subactivity_included_setting extends restore_subactivity_generic_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subactivity backup setting to control if activity will include user information.
|
||||
*
|
||||
* Depends of restore_users_setting.
|
||||
*/
|
||||
class restore_subactivity_userinfo_setting extends restore_subactivity_generic_setting {
|
||||
}
|
||||
|
||||
/**
|
||||
* root setting to control if restore will create content bank content or no
|
||||
*/
|
||||
|
@ -1612,8 +1612,28 @@ class restore_section_structure_step extends restore_structure_step {
|
||||
$section->course = $this->get_courseid();
|
||||
$section->section = $data->number;
|
||||
$section->timemodified = $data->timemodified ?? 0;
|
||||
$section->component = null;
|
||||
$section->itemid = null;
|
||||
|
||||
$secrec = $DB->get_record(
|
||||
'course_sections',
|
||||
['course' => $this->get_courseid(), 'section' => $data->number, 'component' => null]
|
||||
);
|
||||
$createsection = empty($secrec);
|
||||
|
||||
// Delegated sections are always restored as new sections.
|
||||
if (!empty($data->component)) {
|
||||
$section->itemid = $this->get_delegated_section_mapping($data->component, $data->itemid);
|
||||
// If the delegate component does not set the mapping id, the section must be converted
|
||||
// into a regular section. Otherwise, it won't be accessible.
|
||||
$createsection = $createsection || $section->itemid !== null;
|
||||
$section->component = ($section->itemid !== null) ? $data->component : null;
|
||||
// The section number will be always the last of the course, no matter the case.
|
||||
$section->section = $this->get_last_section_number($this->get_courseid()) + 1;
|
||||
|
||||
}
|
||||
// Section doesn't exist, create it with all the info from backup
|
||||
if (!$secrec = $DB->get_record('course_sections', ['course' => $this->get_courseid(), 'section' => $data->number])) {
|
||||
if ($createsection) {
|
||||
$section->name = $data->name;
|
||||
$section->summary = $data->summary;
|
||||
$section->summaryformat = $data->summaryformat;
|
||||
@ -1629,8 +1649,10 @@ class restore_section_structure_step extends restore_structure_step {
|
||||
$data, true);
|
||||
}
|
||||
}
|
||||
$section->component = $data->component ?? null;
|
||||
$section->itemid = $data->itemid ?? null;
|
||||
|
||||
// Delegated sections should be always after the normal sections.
|
||||
$this->displace_delegated_sections_after($section->section);
|
||||
|
||||
$newitemid = $DB->insert_record('course_sections', $section);
|
||||
$section->id = $newitemid;
|
||||
|
||||
@ -1802,6 +1824,57 @@ class restore_section_structure_step extends restore_structure_step {
|
||||
// Add section related files, with 'course_section' itemid to match
|
||||
$this->add_related_files('course', 'section', 'course_section');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a delegate section mapping.
|
||||
*
|
||||
* @param string $component the component name (frankenstyle)
|
||||
* @param int $oldsectionid The old section id.
|
||||
* @return int|null The new section id or null if not found.
|
||||
*/
|
||||
protected function get_delegated_section_mapping($component, $oldsectionid): ?int {
|
||||
$result = $this->get_mappingid("course_section::$component", $oldsectionid, null);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displace delegated sections after the given section number.
|
||||
*
|
||||
* @param int $sectionnum The section number.
|
||||
*/
|
||||
protected function displace_delegated_sections_after(int $sectionnum): void {
|
||||
global $DB;
|
||||
|
||||
$sectionstomove = $DB->get_records_select(
|
||||
'course_sections',
|
||||
'course = ? AND component IS NOT NULL',
|
||||
[$this->get_courseid()],
|
||||
'section DESC', 'id, section'
|
||||
);
|
||||
foreach ($sectionstomove as $section) {
|
||||
$sectionnum++;
|
||||
$section->section = $sectionnum;
|
||||
$DB->update_record('course_sections', $section);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last section number in the course.
|
||||
*
|
||||
* @param int $courseid The course id.
|
||||
* @param bool $includedelegated If true, include delegated sections in the count.
|
||||
* @return int The last section number.
|
||||
*/
|
||||
protected function get_last_section_number(int $courseid, bool $includedelegated = false): int {
|
||||
global $DB;
|
||||
|
||||
$delegtadefilter = $includedelegated ? '' : ' AND component IS NULL';
|
||||
|
||||
return (int) $DB->get_field_sql(
|
||||
'SELECT max(section) from {course_sections} WHERE course = ?' . $delegtadefilter,
|
||||
[$courseid]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4905,6 +4978,17 @@ abstract class restore_activity_structure_step extends restore_structure_step {
|
||||
$oldid = $this->task->get_old_activityid();
|
||||
$this->set_mapping($modulename, $oldid, $newitemid, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a delegate section mapping.
|
||||
*
|
||||
* @param string $component The component name (frankenstyle)
|
||||
* @param int $olditemid The old section id.
|
||||
* @param int $newitemid The new section id.
|
||||
*/
|
||||
protected function set_delegated_section_mapping($component, $olditemid, $newitemid) {
|
||||
$this->set_mapping("course_section::$component", $olditemid, $newitemid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,7 +103,7 @@ class restore_stepslib_test extends \advanced_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for the section structure step included elements.
|
||||
* Test for delegate section behaviour.
|
||||
*
|
||||
* @covers \restore_section_structure_step::process_section
|
||||
*/
|
||||
@ -114,7 +114,7 @@ class restore_stepslib_test extends \advanced_testcase {
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course(['numsections' => 2, 'format' => 'topics']);
|
||||
// Section 2 has an existing delegate class.
|
||||
// Section 2 has an existing delegate class for component that is not an activity.
|
||||
course_update_section(
|
||||
$course,
|
||||
$DB->get_record('course_sections', ['course' => $course->id, 'section' => 2]),
|
||||
@ -130,16 +130,18 @@ class restore_stepslib_test extends \advanced_testcase {
|
||||
$originalsections = get_fast_modinfo($course->id)->get_section_info_all();
|
||||
$restoredsections = get_fast_modinfo($newcourseid)->get_section_info_all();
|
||||
|
||||
$this->assertEquals(count($originalsections), count($restoredsections));
|
||||
// Delegated sections depends on the plugin to be backuped and restored.
|
||||
// In this case, the plugin is not backuped and restored, so the section is not restored.
|
||||
$this->assertEquals(3, count($originalsections));
|
||||
$this->assertEquals(2, count($restoredsections));
|
||||
|
||||
$validatefields = ['name', 'summary', 'summaryformat', 'visible', 'component', 'itemid'];
|
||||
|
||||
$this->assertEquals($originalsections[1]->name, $restoredsections[1]->name);
|
||||
|
||||
foreach ($validatefields as $field) {
|
||||
$this->assertEquals($originalsections[0]->$field, $restoredsections[0]->$field);
|
||||
$this->assertEquals($originalsections[1]->$field, $restoredsections[1]->$field);
|
||||
$this->assertEquals($originalsections[2]->$field, $restoredsections[2]->$field);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,9 @@ abstract class backup_controller_dbops extends backup_dbops {
|
||||
'sectionid' => $task->get_sectionid(),
|
||||
'modulename' => $task->get_modulename(),
|
||||
'title' => $task->get_name(),
|
||||
'directory' => 'activities/' . $task->get_modulename() . '_' . $task->get_moduleid());
|
||||
'directory' => 'activities/' . $task->get_modulename() . '_' . $task->get_moduleid(),
|
||||
'insubsection' => ($task->is_in_subsection()) ? 1 : '',
|
||||
);
|
||||
|
||||
// Now get activity settings
|
||||
// Calculate prefix to find valid settings
|
||||
@ -246,7 +248,7 @@ abstract class backup_controller_dbops extends backup_dbops {
|
||||
continue;
|
||||
}
|
||||
// Validate level is correct (activity)
|
||||
if ($setting->get_level() != backup_setting::ACTIVITY_LEVEL) {
|
||||
if (!in_array($setting->get_level(), [backup_setting::ACTIVITY_LEVEL, backup_setting::SUBACTIVITY_LEVEL])) {
|
||||
throw new backup_controller_exception('setting_not_activity_level', $setting);
|
||||
}
|
||||
$settinginfo = array(
|
||||
@ -268,7 +270,10 @@ abstract class backup_controller_dbops extends backup_dbops {
|
||||
$contentinfo = array(
|
||||
'sectionid' => $task->get_sectionid(),
|
||||
'title' => $task->get_name(),
|
||||
'directory' => 'sections/' . 'section_' . $task->get_sectionid());
|
||||
'directory' => 'sections/' . 'section_' . $task->get_sectionid(),
|
||||
'parentcmid' => $task->get_delegated_cm() ?? '',
|
||||
'modname' => $task->get_modname() ?? '',
|
||||
);
|
||||
|
||||
// Now get section settings
|
||||
// Calculate prefix to find valid settings
|
||||
@ -280,7 +285,7 @@ abstract class backup_controller_dbops extends backup_dbops {
|
||||
continue;
|
||||
}
|
||||
// Validate level is correct (section)
|
||||
if ($setting->get_level() != backup_setting::SECTION_LEVEL) {
|
||||
if (!in_array($setting->get_level(), [backup_setting::SECTION_LEVEL, backup_setting::SUBSECTION_LEVEL])) {
|
||||
throw new backup_controller_exception('setting_not_section_level', $setting);
|
||||
}
|
||||
$settinginfo = array(
|
||||
|
@ -120,6 +120,17 @@ abstract class backup_plan_dbops extends backup_dbops {
|
||||
return $sectionsarr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given one section id, returns the full section record.
|
||||
*
|
||||
* @param int $sectionid
|
||||
* @return stdClass
|
||||
*/
|
||||
public static function get_section_from_id($sectionid): stdClass {
|
||||
global $DB;
|
||||
return $DB->get_record('course_sections', ['id' => $sectionid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given one course id, return its format in DB
|
||||
*/
|
||||
|
@ -103,7 +103,20 @@ abstract class base_task implements checksumable, executable, loggable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a setting with the given name exists.
|
||||
*
|
||||
* This method find first in the current settings and then in the plan settings.
|
||||
*
|
||||
* @param string $name Setting name
|
||||
* @return bool
|
||||
*/
|
||||
public function setting_exists($name) {
|
||||
foreach ($this->settings as $setting) {
|
||||
if ($setting->get_name() == $name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $this->plan->setting_exists($name);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,12 @@ abstract class backup_setting extends base_setting implements checksumable {
|
||||
const SECTION_LEVEL = 9;
|
||||
const ACTIVITY_LEVEL = 13;
|
||||
|
||||
/** @var int the subsection level. */
|
||||
const SUBSECTION_LEVEL = 17;
|
||||
|
||||
/** @var int the activity inside a subsection level. */
|
||||
const SUBACTIVITY_LEVEL = 21;
|
||||
|
||||
/** @var int Level of the setting, eg {@link self::ROOT_LEVEL} */
|
||||
protected $level;
|
||||
|
||||
@ -96,7 +102,12 @@ abstract class backup_setting extends base_setting implements checksumable {
|
||||
}
|
||||
// Check the dependency level is >= current level
|
||||
if ($dependentsetting->get_level() < $this->level) {
|
||||
throw new backup_setting_exception('cannot_add_upper_level_dependency');
|
||||
throw new backup_setting_exception('cannot_add_upper_level_dependency', [
|
||||
$dependentsetting->get_level(),
|
||||
$dependentsetting->get_name(),
|
||||
$this->level,
|
||||
$this->get_name(),
|
||||
]);
|
||||
}
|
||||
parent::add_dependency($dependentsetting, $type, $options);
|
||||
}
|
||||
|
@ -256,9 +256,11 @@ abstract class backup_setting_ui extends base_setting_ui {
|
||||
$this->name = 'course_'.$setting->get_name();
|
||||
break;
|
||||
case backup_setting::SECTION_LEVEL :
|
||||
case backup_setting::SUBSECTION_LEVEL:
|
||||
$this->name = 'section_'.$setting->get_name();
|
||||
break;
|
||||
case backup_setting::ACTIVITY_LEVEL :
|
||||
case backup_setting::SUBACTIVITY_LEVEL:
|
||||
$this->name = 'activity_'.$setting->get_name();
|
||||
break;
|
||||
}
|
||||
@ -329,9 +331,10 @@ abstract class backup_setting_ui extends base_setting_ui {
|
||||
// If a task has been provided and the label is not already set meaningfully
|
||||
// we will attempt to improve it.
|
||||
if (!is_null($task) && $this->label == $this->setting->get_name() && strpos($this->setting->get_name(), '_include') !== false) {
|
||||
if ($this->setting->get_level() == backup_setting::SECTION_LEVEL) {
|
||||
$level = $this->setting->get_level();
|
||||
if ($level == backup_setting::SECTION_LEVEL || $level == backup_setting::SUBSECTION_LEVEL) {
|
||||
$this->label = get_string('includesection', 'backup', $task->get_name());
|
||||
} else if ($this->setting->get_level() == backup_setting::ACTIVITY_LEVEL) {
|
||||
} else if ($level == backup_setting::ACTIVITY_LEVEL || $level == backup_setting::SUBACTIVITY_LEVEL) {
|
||||
$this->label = $task->get_name();
|
||||
}
|
||||
}
|
||||
|
@ -48,22 +48,10 @@ abstract class base_moodleform extends moodleform {
|
||||
protected $uistage = null;
|
||||
|
||||
/**
|
||||
* True if we have a course div open, false otherwise
|
||||
* @var bool
|
||||
* Group stack to control open and closed div groups.
|
||||
* @var array
|
||||
*/
|
||||
protected $coursediv = false;
|
||||
|
||||
/**
|
||||
* True if we have a section div open, false otherwise
|
||||
* @var bool
|
||||
*/
|
||||
protected $sectiondiv = false;
|
||||
|
||||
/**
|
||||
* True if we have an activity div open, false otherwise
|
||||
* @var bool
|
||||
*/
|
||||
protected $activitydiv = false;
|
||||
protected array $groupstack = [];
|
||||
|
||||
/**
|
||||
* Creates the form
|
||||
@ -177,20 +165,12 @@ abstract class base_moodleform extends moodleform {
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes any open divs
|
||||
* Closes any open divs.
|
||||
*/
|
||||
public function close_task_divs() {
|
||||
if ($this->activitydiv) {
|
||||
while (!empty($this->groupstack)) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->activitydiv = false;
|
||||
}
|
||||
if ($this->sectiondiv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->sectiondiv = false;
|
||||
}
|
||||
if ($this->coursediv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->coursediv = false;
|
||||
array_pop($this->groupstack);
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,7 +224,7 @@ abstract class base_moodleform extends moodleform {
|
||||
list($identifier, $component) = $setting->get_help();
|
||||
$this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component);
|
||||
}
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->pop_group();
|
||||
}
|
||||
$this->_form->setDefaults($defaults);
|
||||
return true;
|
||||
@ -265,54 +245,42 @@ abstract class base_moodleform extends moodleform {
|
||||
* @param backup_setting $setting
|
||||
*/
|
||||
protected function add_html_formatting(backup_setting $setting) {
|
||||
$mform = $this->_form;
|
||||
$isincludesetting = (strpos($setting->get_name(), '_include') !== false);
|
||||
if ($isincludesetting && $setting->get_level() != backup_setting::ROOT_LEVEL) {
|
||||
switch ($setting->get_level()) {
|
||||
case backup_setting::COURSE_LEVEL:
|
||||
if ($this->activitydiv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->activitydiv = false;
|
||||
}
|
||||
if ($this->sectiondiv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->sectiondiv = false;
|
||||
}
|
||||
if ($this->coursediv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
}
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'grouped_settings course_level')));
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'include_setting course_level')));
|
||||
$this->coursediv = true;
|
||||
$this->pop_groups_to('course');
|
||||
$this->push_group_start('course', 'grouped_settings course_level');
|
||||
$this->push_group_start(null, 'include_setting course_level');
|
||||
break;
|
||||
case backup_setting::SECTION_LEVEL:
|
||||
if ($this->activitydiv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->activitydiv = false;
|
||||
}
|
||||
if ($this->sectiondiv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
}
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'grouped_settings section_level')));
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'include_setting section_level')));
|
||||
$this->sectiondiv = true;
|
||||
$this->pop_groups_to('course');
|
||||
$this->push_group_start('section', 'grouped_settings section_level');
|
||||
$this->push_group_start(null, 'include_setting section_level');
|
||||
break;
|
||||
case backup_setting::ACTIVITY_LEVEL:
|
||||
if ($this->activitydiv) {
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
}
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'grouped_settings activity_level')));
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'include_setting activity_level')));
|
||||
$this->activitydiv = true;
|
||||
$this->pop_groups_to('section');
|
||||
$this->push_group_start('activity', 'grouped_settings activity_level');
|
||||
$this->push_group_start(null, 'include_setting activity_level');
|
||||
break;
|
||||
case backup_setting::SUBSECTION_LEVEL:
|
||||
$this->pop_groups_to('section');
|
||||
$this->push_group_start('subsection', 'grouped_settings subsection_level');
|
||||
$this->push_group_start(null, 'normal_setting');
|
||||
break;
|
||||
case backup_setting::SUBACTIVITY_LEVEL:
|
||||
$this->pop_groups_to('subsection');
|
||||
$this->push_group_start('subactivity', 'grouped_settings activity_level');
|
||||
$this->push_group_start(null, 'include_setting activity_level');
|
||||
break;
|
||||
default:
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'normal_setting')));
|
||||
$this->push_group_start(null, 'normal_setting');
|
||||
break;
|
||||
}
|
||||
} else if ($setting->get_level() == backup_setting::ROOT_LEVEL) {
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'root_setting')));
|
||||
$this->push_group_start('root', 'root_setting');
|
||||
} else {
|
||||
$mform->addElement('html', html_writer::start_tag('div', array('class' => 'normal_setting')));
|
||||
$this->push_group_start(null, 'normal_setting');
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,12 +318,55 @@ abstract class base_moodleform extends moodleform {
|
||||
$label .= $OUTPUT->render($labelicon);
|
||||
}
|
||||
$this->_form->addElement('static', 'static_'.$settingui->get_name(), $label, $settingui->get_static_value().$icon);
|
||||
$this->_form->addElement('html', html_writer::end_tag('div'));
|
||||
$this->pop_group();
|
||||
}
|
||||
$this->_form->addElement('hidden', $settingui->get_name(), $settingui->get_value());
|
||||
$this->_form->setType($settingui->get_name(), $settingui->get_param_validation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a group start to the form.
|
||||
*
|
||||
* This method will create a new group div in the form and add it to the group stack.
|
||||
* The name can be used to close all stacked groups up to a certain group.
|
||||
*
|
||||
* @param string|null $name The name of the group, if any.
|
||||
* @param string $classes The classes to add to the div.
|
||||
*/
|
||||
protected function push_group_start(?string $name, string $classes) {
|
||||
$mform = $this->_form;
|
||||
$this->groupstack[] = $name;
|
||||
$mform->addElement('html', html_writer::start_tag('div', ['class' => $classes]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops groups from the stack until the given group name is reached.
|
||||
*
|
||||
* @param string $name The name of the group to pop to.
|
||||
*/
|
||||
protected function pop_groups_to(string $name) {
|
||||
if (empty($this->groupstack)) {
|
||||
return;
|
||||
}
|
||||
while (!empty($this->groupstack) && end($this->groupstack) !== $name) {
|
||||
$this->pop_group();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a group from the stack and closes the div.
|
||||
*
|
||||
* @return string|null The name of the group that was popped, or null if the stack is empty.
|
||||
*/
|
||||
protected function pop_group(): ?string {
|
||||
if (empty($this->groupstack)) {
|
||||
return null;
|
||||
}
|
||||
$mform = $this->_form;
|
||||
$mform->addElement('html', html_writer::end_tag('div'));
|
||||
return array_pop($this->groupstack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds dependencies to the form recursively
|
||||
*
|
||||
|
@ -52,6 +52,29 @@ abstract class sectiondelegatemodule extends sectiondelegate {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delegated section id controlled by a specific cm.
|
||||
*
|
||||
* This method is used when reverse search is needed bu we cannot access the database.
|
||||
* This happens mostly on backup and restore. Do NOT use for normal operations.
|
||||
*
|
||||
* @param stdClass|cm_info $cm a course module compatible data structure.
|
||||
* @return int the section id.
|
||||
*/
|
||||
public static function delegated_section_id(stdClass|cm_info $cm): int {
|
||||
global $DB;
|
||||
return $DB->get_field(
|
||||
'course_sections',
|
||||
'id',
|
||||
[
|
||||
'course' => $cm->course,
|
||||
'component' => explode('\\', static::class)[0],
|
||||
'itemid' => $cm->instance,
|
||||
],
|
||||
MUST_EXIST
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent section of the current delegated section.
|
||||
*
|
||||
|
@ -198,6 +198,7 @@ $string['enableasyncbackup_help'] = 'If enabled, backup and restore operations w
|
||||
$string['enterasearch'] = 'Enter a search';
|
||||
$string['error_block_for_module_not_found'] = 'Orphan block instance (id: {$a->bid}) for course module (id: {$a->mid}) found. This block will not be backed up';
|
||||
$string['error_course_module_not_found'] = 'Orphan course module (id: {$a}) found. This module will not be backed up.';
|
||||
$string['error_delegate_section_not_found'] = 'Missing delegate section form course module (id: {$a}. The section will not be backed up.';
|
||||
$string['errorcopyingbackupfile'] = "Failed to copy the backup file to the temporary folder before restoring.";
|
||||
$string['errorfilenamerequired'] = 'You must enter a valid filename for this backup';
|
||||
$string['errorfilenametoolong'] = 'The filename must be less than 255 characters in length.';
|
||||
@ -416,6 +417,7 @@ $string['skipmodifdayshelp'] = 'Choose to skip courses that have not been modifi
|
||||
$string['skipmodifprev'] = 'Skip courses not modified since previous backup';
|
||||
$string['skipmodifprevhelp'] = 'Choose whether to skip courses that have not been modified since the last automatic backup. This requires logging to be enabled.';
|
||||
$string['status'] = 'Status';
|
||||
$string['subsectioncontent'] = 'Subsection content';
|
||||
$string['successful'] = 'Backup successful';
|
||||
$string['successfulcopy'] = 'Copy successful';
|
||||
$string['successfulrestore'] = 'Restore successful';
|
||||
|
@ -12,6 +12,15 @@
|
||||
padding: $card-spacer-x;
|
||||
margin-bottom: $card-spacer-x;
|
||||
}
|
||||
|
||||
&.subsection_level {
|
||||
background-color: $card-bg;
|
||||
@include border-radius($card-border-radius);
|
||||
border: $card-border-width solid $card-border-color;
|
||||
@include clearfix;
|
||||
padding: $card-spacer-x;
|
||||
margin: 0 $card-spacer-x $card-spacer-x $card-spacer-x;
|
||||
}
|
||||
}
|
||||
|
||||
/* These are long labels with checkboxes on the right. */
|
||||
@ -202,4 +211,3 @@
|
||||
background: $backup-restore-state12-bg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34997,6 +34997,18 @@ img.userpicture {
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
.path-backup .mform .grouped_settings.subsection_level {
|
||||
background-color: #fff;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid rgba(0, 0, 0, 0.125);
|
||||
padding: 1.25rem;
|
||||
margin: 0 1.25rem 1.25rem 1.25rem;
|
||||
}
|
||||
.path-backup .mform .grouped_settings.subsection_level::after {
|
||||
display: block;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
.path-backup .mform .include_setting {
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
|
@ -34997,6 +34997,18 @@ img.userpicture {
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
.path-backup .mform .grouped_settings.subsection_level {
|
||||
background-color: #fff;
|
||||
border-radius: 0.25rem;
|
||||
border: 1px solid rgba(0, 0, 0, 0.125);
|
||||
padding: 1.25rem;
|
||||
margin: 0 1.25rem 1.25rem 1.25rem;
|
||||
}
|
||||
.path-backup .mform .grouped_settings.subsection_level::after {
|
||||
display: block;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
.path-backup .mform .include_setting {
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
|
Loading…
x
Reference in New Issue
Block a user