MDL-64702 badges: Add missing data to backup

Backup and restore of badges is missing data:
* related badges
* alignments
* endorsement

Also added to "clone" (duplicate a badge).
This commit is contained in:
Damyon Wiese
2019-01-25 15:47:49 +08:00
parent da59e61407
commit 748117eb47
11 changed files with 172 additions and 32 deletions
+27 -1
View File
@@ -794,12 +794,25 @@ class backup_badges_structure_step extends backup_structure_step {
$badge = new backup_nested_element('badge', array('id'), array('name', 'description',
'timecreated', 'timemodified', 'usercreated', 'usermodified', 'issuername',
'issuerurl', 'issuercontact', 'expiredate', 'expireperiod', 'type', 'courseid',
'message', 'messagesubject', 'attachment', 'notification', 'status', 'nextcron'));
'message', 'messagesubject', 'attachment', 'notification', 'status', 'nextcron',
'version', 'language', 'imageauthorname', 'imageauthoremail', 'imageauthorurl',
'imagecaption'));
$criteria = new backup_nested_element('criteria');
$criterion = new backup_nested_element('criterion', array('id'), array('badgeid',
'criteriatype', 'method', 'description', 'descriptionformat'));
$endorsement = new backup_nested_element('endorsement', array('id'), array('badgeid',
'issuername', 'issuerurl', 'issueremail', 'claimid', 'claimcomment', 'dateissued'));
$alignments = new backup_nested_element('alignments');
$alignment = new backup_nested_element('alignment', array('id'), array('badgeid',
'targetname', 'targeturl', 'targetdescription', 'targetframework', 'targetcode'));
$relatedbadges = new backup_nested_element('relatedbadges');
$relatedbadge = new backup_nested_element('relatedbadge', array('id'), array('badgeid',
'relatedbadgeid'));
$parameters = new backup_nested_element('parameters');
$parameter = new backup_nested_element('parameter', array('id'), array('critid',
'name', 'value', 'criteriatype'));
@@ -815,6 +828,11 @@ class backup_badges_structure_step extends backup_structure_step {
$criteria->add_child($criterion);
$criterion->add_child($parameters);
$parameters->add_child($parameter);
$badge->add_child($endorsement);
$badge->add_child($alignments);
$alignments->add_child($alignment);
$badge->add_child($relatedbadges);
$relatedbadges->add_child($relatedbadge);
$badge->add_child($manual_awards);
$manual_awards->add_child($manual_award);
@@ -822,6 +840,10 @@ class backup_badges_structure_step extends backup_structure_step {
$badge->set_source_table('badge', array('courseid' => backup::VAR_COURSEID));
$criterion->set_source_table('badge_criteria', array('badgeid' => backup::VAR_PARENTID));
$endorsement->set_source_table('badge_endorsement', array('badgeid' => backup::VAR_PARENTID));
$alignment->set_source_table('badge_competencies', array('badgeid' => backup::VAR_PARENTID));
$relatedbadge->set_source_table('badge_related', array('badgeid' => backup::VAR_PARENTID));
$parametersql = 'SELECT cp.*, c.criteriatype
FROM {badge_criteria_param} cp JOIN {badge_criteria} c
@@ -838,6 +860,10 @@ class backup_badges_structure_step extends backup_structure_step {
$badge->annotate_ids('user', 'usermodified');
$criterion->annotate_ids('badge', 'badgeid');
$parameter->annotate_ids('criterion', 'critid');
$endorsement->annotate_ids('badge', 'badgeid');
$alignment->annotate_ids('badge', 'badgeid');
$relatedbadge->annotate_ids('badge', 'badgeid');
$relatedbadge->annotate_ids('badge', 'relatedbadgeid');
$badge->annotate_files('badges', 'badgeimage', 'id');
$manual_award->annotate_ids('badge', 'badgeid');
$manual_award->annotate_ids('user', 'recipientid');
+109 -1
View File
@@ -2506,6 +2506,9 @@ class restore_badges_structure_step extends restore_structure_step {
$paths[] = new restore_path_element('badge', '/badges/badge');
$paths[] = new restore_path_element('criterion', '/badges/badge/criteria/criterion');
$paths[] = new restore_path_element('parameter', '/badges/badge/criteria/criterion/parameters/parameter');
$paths[] = new restore_path_element('endorsement', '/badges/badge/endorsement');
$paths[] = new restore_path_element('alignment', '/badges/badge/alignments/alignment');
$paths[] = new restore_path_element('relatedbadge', '/badges/badge/relatedbadges/relatedbadge');
$paths[] = new restore_path_element('manual_award', '/badges/badge/manual_awards/manual_award');
return $paths;
@@ -2550,13 +2553,87 @@ class restore_badges_structure_step extends restore_structure_step {
'attachment' => $data->attachment,
'notification' => $data->notification,
'status' => BADGE_STATUS_INACTIVE,
'nextcron' => $data->nextcron
'nextcron' => $data->nextcron,
'version' => $data->version,
'language' => $data->language,
'imageauthorname' => $data->imageauthorname,
'imageauthoremail' => $data->imageauthoremail,
'imageauthorurl' => $data->imageauthorurl,
'imagecaption' => $data->imagecaption
);
$newid = $DB->insert_record('badge', $params);
$this->set_mapping('badge', $data->id, $newid, $restorefiles);
}
/**
* Create an endorsement for a badge.
*
* @param mixed $data
* @return void
*/
public function process_endorsement($data) {
global $DB;
$data = (object)$data;
$params = array(
'badgeid' => $this->get_new_parentid('badge'),
'issuername' => $data->issuername,
'issuerurl' => $data->issuerurl,
'issueremail' => $data->issueremail,
'claimid' => $data->claimid,
'claimcomment' => $data->claimcomment,
'dateissued' => $this->apply_date_offset($data->dateissued)
);
$newid = $DB->insert_record('badge_endorsement', $params);
$this->set_mapping('endorsement', $data->id, $newid);
}
/**
* Link to related badges for a badge. This relies on post processing in after_execute().
*
* @param mixed $data
* @return void
*/
public function process_relatedbadge($data) {
global $DB;
$data = (object)$data;
$relatedbadgeid = $data->relatedbadgeid;
if ($relatedbadgeid) {
// Only backup and restore related badges if they are contained in the backup file.
$params = array(
'badgeid' => $this->get_new_parentid('badge'),
'relatedbadgeid' => $relatedbadgeid
);
$newid = $DB->insert_record('badge_related', $params);
}
}
/**
* Link to an alignment for a badge.
*
* @param mixed $data
* @return void
*/
public function process_alignment($data) {
global $DB;
$data = (object)$data;
$params = array(
'badgeid' => $this->get_new_parentid('badge'),
'targetname' => $data->targetname,
'targeturl' => $data->targeturl,
'targetdescription' => $data->targetdescription,
'targetframework' => $data->targetframework,
'targetcode' => $data->targetcode
);
$newid = $DB->insert_record('badge_competencies', $params);
$this->set_mapping('alignment', $data->id, $newid);
}
public function process_criterion($data) {
global $DB;
@@ -2569,6 +2646,7 @@ class restore_badges_structure_step extends restore_structure_step {
'description' => isset($data->description) ? $data->description : '',
'descriptionformat' => isset($data->descriptionformat) ? $data->descriptionformat : 0,
);
$newid = $DB->insert_record('badge_criteria', $params);
$this->set_mapping('criterion', $data->id, $newid);
}
@@ -2634,8 +2712,38 @@ class restore_badges_structure_step extends restore_structure_step {
}
protected function after_execute() {
global $DB;
// Add related files.
$this->add_related_files('badges', 'badgeimage', 'badge');
$badgeid = $this->get_new_parentid('badge');
// Remap any related badges.
// We do this in the DB directly because this is backup/restore it is not valid to call into
// the component API.
$params = array('badgeid' => $badgeid);
$query = "SELECT DISTINCT br.id, br.badgeid, br.relatedbadgeid
FROM {badge_related} br
WHERE (br.badgeid = :badgeid)";
$relatedbadges = $DB->get_records_sql($query, $params);
$newrelatedids = [];
foreach ($relatedbadges as $relatedbadge) {
$relatedid = $this->get_mappingid('badge', $relatedbadge->relatedbadgeid);
$params['relatedbadgeid'] = $relatedbadge->relatedbadgeid;
$DB->delete_records_select('badge_related', '(badgeid = :badgeid AND relatedbadgeid = :relatedbadgeid)', $params);
if ($relatedid) {
$newrelatedids[] = $relatedid;
}
}
if (!empty($newrelatedids)) {
$relatedbadges = [];
foreach ($newrelatedids as $relatedid) {
$relatedbadge = new stdClass();
$relatedbadge->badgeid = $badgeid;
$relatedbadge->relatedbadgeid = $relatedid;
$relatedbadges[] = $relatedbadge;
}
$DB->insert_records('badge_related', $relatedbadges);
}
}
}
+2 -2
View File
@@ -95,7 +95,7 @@ if ($badge->status != BADGE_STATUS_INACTIVE) {
$json['endorsement'] = $endorsementurl->out(false);
}
$competencies = $badge->get_alignment();
$competencies = $badge->get_alignments();
if (!empty($competencies)) {
foreach ($competencies as $item) {
$alignment = array('targetName' => $item->targetname, 'targetUrl' => $item->targeturl);
@@ -123,4 +123,4 @@ if ($badge->status != BADGE_STATUS_INACTIVE) {
$json['error'] = get_string('error:relatedbadgedoesntexist', 'badges');
}
echo $OUTPUT->header();
echo json_encode($json);
echo json_encode($json);
+1 -1
View File
@@ -150,7 +150,7 @@ class core_badges_external extends external_api {
// Create a badge instance to be able to get the endorsement and other info.
$badgeinstance = new badge($badge->id);
$endorsement = $badgeinstance->get_endorsement();
$competencies = $badgeinstance->get_alignment();
$competencies = $badgeinstance->get_alignments();
$relatedbadges = $badgeinstance->get_related_badges();
if (!$canconfiguredetails) {
+1 -18
View File
@@ -82,23 +82,6 @@ class provider implements
'datemet' => 'privacy:metadata:criteriamet:datemet',
], 'privacy:metadata:criteriamet');
$collection->add_database_table('badge_endorsement', [
'issuername' => 'privacy:metadata:endorsement:issuername',
'issuerurl' => 'privacy:metadata:endorsement:issuerurl',
'issueremail' => 'privacy:metadata:endorsement:issueremail',
'claimid' => 'privacy:metadata:endorsement:claimid',
'claimcomment' => 'privacy:metadata:endorsement:claimcomment',
'dateissued' => 'privacy:metadata:endorsement:dateissued',
], 'privacy:metadata:endorsement');
$collection->add_database_table('badge_competencies', [
'targetname' => 'privacy:metadata:alignment:targetname',
'targeturl' => 'privacy:metadata:alignment:targeturl',
'targetdescription' => 'privacy:metadata:alignment:targetdescription',
'targetframework' => 'privacy:metadata:alignment:targetframework',
'targetcode' => 'privacy:metadata:alignment:targetcode',
], 'privacy:metadata:alignment');
$collection->add_database_table('badge_manual_award', [
'recipientid' => 'privacy:metadata:manualaward:recipientid',
'issuerid' => 'privacy:metadata:manualaward:issuerid',
@@ -393,7 +376,7 @@ class provider implements
// Export the badges.
$uniqueid = $DB->sql_concat_join("'-'", ['b.id', 'COALESCE(bc.id, 0)', 'COALESCE(bi.id, 0)',
'COALESCE(bma.id, 0)', 'COALESCE(bcm.id, 0)', 'COALESCE(ba.id, 0)']);
'COALESCE(bma.id, 0)', 'COALESCE(bcm.id, 0)', 'COALESCE(brb.id, 0)', 'COALESCE(ba.id, 0)']);
$sql = "
SELECT $uniqueid AS uniqueid, b.id,
bi.id AS biid, bi.dateissued, bi.dateexpire, bi.uniquehash,
+1 -1
View File
@@ -97,7 +97,7 @@ if ($alignmentid || $action == 'add' || $action == 'edit') {
$urlbutton = new moodle_url('/badges/competency.php', array('id' => $badge->id, 'action' => 'add'));
echo $OUTPUT->box($OUTPUT->single_button($urlbutton, get_string('addalignment', 'badges')), 'clearfix mdl-align');
}
$alignment = $badge->get_alignment();
$alignment = $badge->get_alignments();
if (count($alignment) > 0) {
$renderrelated = new badge_competencies_alignment($alignment, $badgeid);
echo $output->render($renderrelated);
+2 -2
View File
@@ -428,7 +428,7 @@ class core_badges_renderer extends plugin_renderer_base {
}
$output .= html_writer::alist($items, array(), 'ul');
}
$competencies = $badge->get_alignment();
$competencies = $badge->get_alignments();
if (!empty($competencies)) {
$output .= $this->heading(get_string('alignment', 'badges'), 3);
$items = array();
@@ -1106,7 +1106,7 @@ class core_badges_renderer extends plugin_renderer_base {
protected function print_badge_competencies(badge $badge) {
$output = '';
$output .= $this->heading(get_string('alignment', 'badges'), 3);
$competencies = $badge->get_alignment();
$competencies = $badge->get_alignments();
if (!empty($competencies)) {
$items = array();
foreach ($competencies as $competency) {
+3 -3
View File
@@ -813,7 +813,7 @@ class core_badges_badgeslib_testcase extends advanced_testcase {
$competency2 = clone $competency1;
$newid1 = $badge->save_alignment($competency1);
$newid2 = $badge->save_alignment($competency2);
$competencies1 = $badge->get_alignment();
$competencies1 = $badge->get_alignments();
$this->assertCount(2, $competencies1);
$this->assertEquals($competency1->badgeid, $competencies1[$newid1]->badgeid);
@@ -826,12 +826,12 @@ class core_badges_badgeslib_testcase extends advanced_testcase {
// Update competency aligment.
$competencies1[$newid1]->targetname = 'CCSS.ELA-Literacy.RST.11-12.3 update';
$badge->save_alignment($competencies1[$newid1], $competencies1[$newid1]->id);
$competencies2 = $badge->get_alignment();
$competencies2 = $badge->get_alignments();
$this->assertEquals($competencies1[$newid1]->id, $competencies2[$newid1]->id);
$this->assertEquals($competencies1[$newid1]->targetname, $competencies2[$newid1]->targetname);
// Delete competency alignment.
$badge->delete_alignment($competencies1[$newid2]->id);
$this->assertCount(1, $badge->get_alignment());
$this->assertCount(1, $badge->get_alignments());
}
}
+1 -1
View File
@@ -165,7 +165,7 @@ class core_badges_external_testcase extends externallib_advanced_testcase {
// Get the endorsement, competencies and related badges.
$badgeinstance = new badge($badge->id);
$endorsement = $badgeinstance->get_endorsement();
$competencies = $badgeinstance->get_alignment();
$competencies = $badgeinstance->get_alignments();
$relatedbadges = $badgeinstance->get_related_badges();
$badge->competencies = array();
$badge->relatedbadges = array();
+2 -1
View File
@@ -650,7 +650,8 @@ class core_badges_privacy_testcase extends provider_testcase {
/**
* Relate a badge.
*
* @param array $params Parameters.
* @param int $badgeid The badge ID.
* @param int $relatedbadgeid The related badge ID.
* @return object
*/
protected function relate_badge(int $badgeid, int $relatedbadgeid) {
+23 -1
View File
@@ -315,6 +315,28 @@ class badge {
$crit->make_clone($new);
}
// Copy endorsement.
$endorsement = $this->get_endorsement();
if ($endorsement) {
unset($endorsement->id);
$endorsement->badgeid = $new;
$newbadge->save_endorsement($endorsement);
}
// Copy alignments.
$alignments = $this->get_alignments();
foreach ($alignments as $alignment) {
unset($alignment->id);
$alignment->badgeid = $new;
$newbadge->save_alignment($alignment);
}
// Copy related badges.
$related = $this->get_related_badges(true);
if (!empty($related)) {
$newbadge->add_related_badges(array_keys($related));
}
// Trigger event, badge duplicated.
$eventparams = array('objectid' => $new, 'context' => $PAGE->context);
$event = \core\event\badge_duplicated::create($eventparams);
@@ -838,7 +860,7 @@ class badge {
*
* @return array List content competencies.
*/
public function get_alignment() {
public function get_alignments() {
global $DB;
return $DB->get_records('badge_competencies', array('badgeid' => $this->id));
}