Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-82877

Custom fields - Restore Course Backup Cannot Be Completed

XMLWordPrintable

    • MOODLE_403_STABLE, MOODLE_404_STABLE
    • MOODLE_404_STABLE, MOODLE_405_STABLE
    • MDL-82877-404
    • MDL-82877-405
    • Hide

      Setup

      1. Ensure testing is performed on a brand new site/installation
      2. Log in as admin
      3. Navigate to Courses > Asynchronous backup/restore in site administration
      4. Uncheck Enable asynchronous backups and save
      5. Navigate to Courses > Course custom fields in site administration
      6. Create a new category
      7. Create four new Short text custom fields:
        • Name: Field 0; Short name: field0; Visible to: Everyone
        • Name: Field 1; Short name: field1; Visible to: Everyone
        • Name: Field 2; Short name: field2; Visible to: Nobody
        • Name: Field 3; Short name: field3; Visible to: Teachers

      Test

      1. Navigate to Courses > Restore course in site administration
      2. Upload backup-moodle2-course-2-c1-20241015-1411-nu-nf.tar.gz and press Restore
      3. Use the wizard to Restore as a new course in the default course category
      4. Press Next to progress through wizard
      5. Press Restore course at last stage
      6. Confirm restore completes successfully without exceptions
      7. Navigate to restored course
      8. Go to Settings
      9. Confirm the content of the Other fields container:
        • Field 0:
        • Field 1: One
        • Field 2: Two
        • Field 3: Three
      Show
      Setup Ensure testing is performed on a brand new site/installation Log in as admin Navigate to Courses > Asynchronous backup/restore in site administration Uncheck Enable asynchronous backups and save Navigate to Courses > Course custom fields in site administration Create a new category Create four new Short text custom fields: Name: Field 0; Short name: field0; Visible to: Everyone Name: Field 1; Short name: field1; Visible to: Everyone Name: Field 2; Short name: field2; Visible to: Nobody Name: Field 3; Short name: field3; Visible to: Teachers Test Navigate to Courses > Restore course in site administration Upload backup-moodle2-course-2-c1-20241015-1411-nu-nf.tar.gz and press Restore Use the wizard to Restore as a new course in the default course category Press Next to progress through wizard Press Restore course at last stage Confirm restore completes successfully without exceptions Navigate to restored course Go to Settings Confirm the content of the Other fields container: Field 0: Field 1: One Field 2: Two Field 3: Three
    • Hide

      Code verified against automated checks.

      Checked MDL-82877 using repository: https://github.com/paulholden/moodle.git

      More information about this report

      Built on: Mon 04 Nov 2024 03:38:49 PM UTC

      Show
      Code verified against automated checks. Checked MDL-82877 using repository: https://github.com/paulholden/moodle.git MOODLE_404_STABLE (0 errors / 0 warnings) [branch: MDL-82877-404 | CI Job ] MOODLE_405_STABLE (0 errors / 0 warnings) [branch: MDL-82877-405 | CI Job ] main (0 errors / 0 warnings) [branch: MDL-82877 | CI Job ] More information about this report Built on: Mon 04 Nov 2024 03:38:49 PM UTC
    • Hide

      Launching automatic jobs for branch MDL-82877

      Built on: Mon Nov 4 03:34:54 PM UTC 2024

      Show
      Launching automatic jobs for branch MDL-82877 https://ci.moodle.org/view/Testing/job/DEV.02%20-%20Developer-requested%20PHPUnit/17224/ PHPUnit (sqlsrv / complete) https://ci.moodle.org/view/Testing/job/DEV.01%20-%20Developer-requested%20Behat/58663/ Behat (NonJS - boost and classic / complete) https://ci.moodle.org/view/Testing/job/DEV.01%20-%20Developer-requested%20Behat/58664/ Behat (Firefox - boost / complete) https://ci.moodle.org/view/Testing/job/DEV.01%20-%20Developer-requested%20Behat/58665/ Behat (Firefox - classic / complete) https://ci.moodle.org/view/Testing/job/DEV.01%20-%20Developer-requested%20Behat/58666/ App tests (stable app version) / complete) --> unrelated, reported to apps team. Built on: Mon Nov 4 03:34:54 PM UTC 2024

      Stumble upon this issue when using course reuse/restore to restore the backup into a new course. Existing backup course utilised the custom data fields. Backup is working as expected, however trying to restore the course throw some errors where the course is pending for restore.

      I tried to identify the problem. When choosing the restore options, I can see the course entry created in mdl_course table in the db.

      For example

      ID: 2903

      Fullname: Course restoration in progress copy 1

       

      All is well, until when i click "perform restore". The entry is delete from the mdl_course table. And then I get this error:

      dml_missing_record_exception
      Can't find data record in database table course. (SELECT id,category FROM {course} WHERE id = ? [array ( 0 => 8432, )])

      The ID 8432 seems out of place, as the created new course ID should have been 2903, as per the example above. Upon checking further 8432 seems to be the latest id for an entry in mdl_customfield_data. I am using 4 custom fields in my courses for various meta details. For some reason the backup tool is refering to the wrong ID. 

       

      Further drill down leads to line 2019, in this particular file backup\moodle2\restore_stepslib.php the function restore_instance_data_from_backup that is causing the issue.

      public function process_customfield($data) {
          $handler = core_course\customfield\course_handler::create();
          $newid = $handler->restore_instance_data_from_backup($this->task, $data);

          if ($newid)

      {         $handler->restore_define_structure($this, $newid, $data['id']);     }

      }

       

      The file course/classes/customfield/course_handler.php the function restore_instance_data_from_backup seems to return the first custom field data id straightaway as the course id.

      public function restore_instance_data_from_backup(\restore_task $task, array $data) {
              $courseid = $task->get_courseid();
              $context = $this->get_instance_context($courseid);
              $editablefields = $this->get_editable_fields($courseid);
              $records = api::get_instance_fields_data($editablefields, $courseid);
              $target = $task->get_target();
              $override = ($target != \backup::TARGET_CURRENT_ADDING && $target != \backup::TARGET_EXISTING_ADDING);

              foreach ($records as $d) {
                  $field = $d->get_field();
                  if ($field->get('shortname') === $data['shortname'] && $field->get('type') === $data['type']) {
                      if (!$d->get('id') || $override)

      {                     $d->set($d->datafield(), $data['value']);                     $d->set('value', $data['value']);                     $d->set('valueformat', $data['valueformat']);                     $d->set('valuetrust', !empty($data['valuetrust']));                     $d->set('contextid', $context->id);                     $d->save();                 }

                      return $d->get('id');
                  }
              }
          }
       

      Stack trace

      Can't find data record in database table course.
       
      More information about this error
      Debug info: SELECT id,category FROM {course} WHERE id = ?
      [array (
      0 => 3,
      )]
      Error code: invalidrecord
      Stack trace:
       
          line 1662 of /lib/dml/moodle_database.php: dml_missing_record_exception thrown
          line 1638 of /lib/dml/moodle_database.php: call to moodle_database->get_record_select()
          line 200 of /lib/classes/context/course.php: call to moodle_database->get_record()
          line 185 of /course/classes/customfield/course_handler.php: call to core\context\course::instance()
          line 127 of /course/classes/customfield/course_handler.php: call to core_course\customfield\course_handler->get_instance_context()
          line 785 of /customfield/classes/handler.php: call to core_course\customfield\course_handler->can_view()
          line ? of unknownfile: call to core_customfield\handler->core_customfield\{closure}()
          line 786 of /customfield/classes/handler.php: call to array_filter()
          line 377 of /customfield/classes/handler.php: call to core_customfield\handler->get_visible_fields()
          line 524 of /customfield/classes/handler.php: call to core_customfield\handler->get_instance_data()
          line 2104 of /backup/moodle2/restore_stepslib.php: call to core_customfield\handler->restore_define_structure()
          line 137 of /backup/util/plan/restore_structure_step.class.php: call to restore_course_structure_step->process_customfield()
          line 123 of /backup/util/helper/restore_structure_parser_processor.class.php: call to restore_structure_step->process()
          line 178 of /backup/util/xml/parser/processors/grouped_parser_processor.class.php: call to restore_structure_parser_processor->dispatch_chunk()
          line 111 of /backup/util/helper/restore_structure_parser_processor.class.php: call to grouped_parser_processor->postprocess_chunk()
          line 148 of /backup/util/xml/parser/processors/simplified_parser_processor.class.php: call to restore_structure_parser_processor->postprocess_chunk()
          line 92 of /backup/util/xml/parser/processors/progressive_parser_processor.class.php: call to simplified_parser_processor->process_chunk()
          line 189 of /backup/util/xml/parser/progressive_parser.class.php: call to progressive_parser_processor->receive_chunk()
          line 277 of /backup/util/xml/parser/progressive_parser.class.php: call to progressive_parser->publish()
          line ? of unknownfile: call to progressive_parser->end_tag()
          line 178 of /backup/util/xml/parser/progressive_parser.class.php: call to xml_parse()
          line 157 of /backup/util/xml/parser/progressive_parser.class.php: call to progressive_parser->parse()
          line 110 of /backup/util/plan/restore_structure_step.class.php: call to progressive_parser->process()
          line 199 of /backup/util/plan/base_task.class.php: call to restore_structure_step->execute()
          line 191 of /backup/util/plan/base_plan.class.php: call to base_task->execute()
          line 168 of /backup/util/plan/restore_plan.class.php: call to base_plan->execute()
          line 411 of /backup/controller/restore_controller.class.php: call to restore_plan->execute()
          line 219 of /backup/util/ui/restore_ui.class.php: call to restore_controller->execute_plan()
          line 146 of /backup/restore.php: call to restore_ui->execute()
      

            pholden Paul Holden
            euhuatan Eu Hua Tan
            Pedro Jordao Pedro Jordao
            Jun Pataleta Jun Pataleta
            Ron Carl Alfon Yu Ron Carl Alfon Yu
            Votes:
            4 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved:

                Estimated:
                Original Estimate - 0 minutes
                0m
                Remaining:
                Remaining Estimate - 0 minutes
                0m
                Logged:
                Time Spent - 3 hours, 19 minutes
                3h 19m

                  Error rendering 'clockify-timesheets-time-tracking-reports:timer-sidebar'. Please contact your Jira administrators.