diff --git a/backup/util/structure/base_nested_element.class.php b/backup/util/structure/base_nested_element.class.php
index 1cd23b032b7..b48defc8235 100644
--- a/backup/util/structure/base_nested_element.class.php
+++ b/backup/util/structure/base_nested_element.class.php
@@ -94,6 +94,10 @@ abstract class base_nested_element extends base_final_element {
}
protected function check_and_set_used($element) {
+ // First of all, check the element being added doesn't conflict with own final elements
+ if (array_key_exists($element->get_name(), $this->final_elements)) {
+ throw new base_element_struct_exception('baseelementchildnameconflict', $element->get_name());
+ }
$grandparent = $this->get_grandoptigroupelement_or_grandparent();
if ($existing = array_intersect($grandparent->get_used(), $element->get_used())) { // Check the element isn't being used already
throw new base_element_struct_exception('baseelementexisting', implode($existing));
diff --git a/backup/util/structure/simpletest/testbasenestedelement.php b/backup/util/structure/simpletest/testbasenestedelement.php
index 0f5ed645eed..206fab00e9c 100644
--- a/backup/util/structure/simpletest/testbasenestedelement.php
+++ b/backup/util/structure/simpletest/testbasenestedelement.php
@@ -393,5 +393,16 @@ class base_nested_element_test extends UnitTestCase {
$this->assertTrue($e instanceof base_element_parent_exception);
}
+ // Add child element already used by own final elements
+ $nested = new mock_base_nested_element('PARENT1', null, array('FINAL1', 'FINAL2'));
+ $child = new mock_base_nested_element('FINAL2', null, array('FINAL3', 'FINAL4'));
+ try {
+ $nested->add_child($child);
+ $this->fail("Expecting base_element_struct_exception exception, none occurred");
+ } catch (Exception $e) {
+ $this->assertTrue($e instanceof base_element_struct_exception);
+ $this->assertEqual($e->errorcode, 'baseelementchildnameconflict');
+ $this->assertEqual($e->a, 'FINAL2');
+ }
}
}
diff --git a/backup/util/xml/parser/processors/simplified_parser_processor.class.php b/backup/util/xml/parser/processors/simplified_parser_processor.class.php
index 9dbe9b8a0fc..e87ac9d556f 100644
--- a/backup/util/xml/parser/processors/simplified_parser_processor.class.php
+++ b/backup/util/xml/parser/processors/simplified_parser_processor.class.php
@@ -104,13 +104,18 @@ abstract class simplified_parser_processor extends progressive_parser_processor
$alltagswhitespace = false;
continue;
}
+
// If the path including the tag name matches another selected path
- // (registered or parent) delete it, another chunk will contain that info
+ // (registered or parent) and is null or begins with linefeed, we know it's part
+ // of another chunk, delete it, another chunk will contain that info
if ($this->path_is_selected($path . '/' . $key) ||
$this->path_is_selected_parent($path . '/' . $key)) {
- unset($data['tags'][$key]);
- continue;
+ if (!isset($value['cdata']) || substr($value['cdata'], 0, 1) === "\n") {
+ unset($data['tags'][$key]);
+ continue;
+ }
}
+
// Convert to simple name => value array
$data['tags'][$key] = isset($value['cdata']) ? $value['cdata'] : null;
diff --git a/backup/util/xml/parser/progressive_parser.class.php b/backup/util/xml/parser/progressive_parser.class.php
index 11f3c9c682e..91bc85fc4b2 100644
--- a/backup/util/xml/parser/progressive_parser.class.php
+++ b/backup/util/xml/parser/progressive_parser.class.php
@@ -201,7 +201,12 @@ class progressive_parser {
// Entering a new inner level, publish all the information available
if ($this->level > $this->prevlevel) {
if (!empty($this->currtag) && (!empty($this->currtag['attrs']) || !empty($this->currtag['cdata']))) {
- $this->topush['tags'][$this->currtag['name']] = $this->currtag;
+ // We always add the last not-empty repetition. Empty ones are ignored.
+ if (isset($this->topush['tags'][$this->currtag['name']]) && trim($this->currtag['cdata']) === '') {
+ // Do nothing, the tag already exists and the repetition is empty
+ } else {
+ $this->topush['tags'][$this->currtag['name']] = $this->currtag;
+ }
}
if (!empty($this->topush['tags'])) {
$this->publish($this->topush);
@@ -233,7 +238,12 @@ class progressive_parser {
// Ending rencently started tag, add value to current tag
if ($this->level == $this->prevlevel) {
$this->currtag['cdata'] = $this->postprocess_cdata($this->accum);
- $this->topush['tags'][$this->currtag['name']] = $this->currtag;
+ // We always add the last not-empty repetition. Empty ones are ignored.
+ if (isset($this->topush['tags'][$this->currtag['name']]) && trim($this->currtag['cdata']) === '') {
+ // Do nothing, the tag already exists and the repetition is empty
+ } else {
+ $this->topush['tags'][$this->currtag['name']] = $this->currtag;
+ }
$this->currtag = array();
}
diff --git a/backup/util/xml/parser/simpletest/fixtures/test4.xml b/backup/util/xml/parser/simpletest/fixtures/test4.xml
index f5865c47da9..4a4fa67416c 100755
--- a/backup/util/xml/parser/simpletest/fixtures/test4.xml
+++ b/backup/util/xml/parser/simpletest/fixtures/test4.xml
@@ -106,6 +106,9 @@
4
4
5
+
+
+
diff --git a/mod/lesson/backup/moodle2/backup_lesson_stepslib.php b/mod/lesson/backup/moodle2/backup_lesson_stepslib.php
index 0b90f423dea..c55bffe0a92 100644
--- a/mod/lesson/backup/moodle2/backup_lesson_stepslib.php
+++ b/mod/lesson/backup/moodle2/backup_lesson_stepslib.php
@@ -76,8 +76,11 @@ class backup_lesson_activity_structure_step extends backup_activity_structure_st
'minquestions','maxpages','timed','maxtime','retake','activitylink',
'mediafile','mediaheight','mediawidth','mediaclose','slideshow',
'width','height','bgcolor','displayleft','displayleftif','progressbar',
- 'highscores','maxhighscores','available','deadline','timemodified'
+ 'showhighscores','maxhighscores','available','deadline','timemodified'
));
+ // Tell the lesson element about the showhighscores elements mapping to the highscores
+ // database field.
+ $lesson->set_source_alias('highscores', 'showhighscores');
// The lesson_pages table
// Grouped within a `pages` element, important to note that page is relational
diff --git a/mod/lesson/backup/moodle2/restore_lesson_stepslib.php b/mod/lesson/backup/moodle2/restore_lesson_stepslib.php
index b716355b64c..00dc383f09d 100644
--- a/mod/lesson/backup/moodle2/restore_lesson_stepslib.php
+++ b/mod/lesson/backup/moodle2/restore_lesson_stepslib.php
@@ -62,6 +62,13 @@ class restore_lesson_activity_structure_step extends restore_activity_structure_
$data->deadline = $this->apply_date_offset($data->deadline);
$data->timemodified = $this->apply_date_offset($data->timemodified);
+ // lesson->highscores can come both in data->highscores and
+ // data->showhighscores, handle both. MDL-26229
+ if (isset($data->showhighscores)) {
+ $data->highscores = $data->showhighscores;
+ unset($data->showhighscores);
+ }
+
// insert the lesson record
$newitemid = $DB->insert_record('lesson', $data);
// immediately after inserting "activity" record, call this
diff --git a/mod/quiz/backup/moodle2/backup_quiz_stepslib.php b/mod/quiz/backup/moodle2/backup_quiz_stepslib.php
index 7a05c5a49c1..655cb5f8474 100644
--- a/mod/quiz/backup/moodle2/backup_quiz_stepslib.php
+++ b/mod/quiz/backup/moodle2/backup_quiz_stepslib.php
@@ -39,7 +39,7 @@ class backup_quiz_activity_structure_step extends backup_questions_activity_stru
// Define each element separated
$quiz = new backup_nested_element('quiz', array('id'), array(
'name', 'intro', 'introformat', 'timeopen',
- 'timeclose', 'optionflags', 'penaltyscheme', 'attempts',
+ 'timeclose', 'optionflags', 'penaltyscheme', 'attempts_number',
'attemptonlast', 'grademethod', 'decimalpoints', 'questiondecimalpoints',
'review', 'questionsperpage', 'shufflequestions', 'shuffleanswers',
'questions', 'sumgrades', 'grade', 'timecreated',
@@ -119,6 +119,7 @@ class backup_quiz_activity_structure_step extends backup_questions_activity_stru
}
// Define source alias
+ $quiz->set_source_alias('attempts', 'attempts_number');
$grade->set_source_alias('grade', 'gradeval');
$attempt->set_source_alias('attempt', 'attemptnum');
diff --git a/mod/quiz/backup/moodle2/restore_quiz_stepslib.php b/mod/quiz/backup/moodle2/restore_quiz_stepslib.php
index 30f8baa0ae2..72222419322 100644
--- a/mod/quiz/backup/moodle2/restore_quiz_stepslib.php
+++ b/mod/quiz/backup/moodle2/restore_quiz_stepslib.php
@@ -67,6 +67,13 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st
$data->questions = $this->questions_recode_layout($data->questions);
+ // quiz->attempts can come both in data->attempts and
+ // data->attempts_number, handle both. MDL-26229
+ if (isset($data->attempts_number)) {
+ $data->attempts = $data->attempts_number;
+ unset($data->attempts_number);
+ }
+
// insert the quiz record
$newitemid = $DB->insert_record('quiz', $data);
// immediately after inserting "activity" record, call this