Browse Source

Fix problems on backup/restore

MOODLE_20_STABLE
bdaloukas 8 years ago
parent
commit
2ab98c29c6
  1. 67
      backup/moodle2/backup_game_stepslib.php
  2. 133
      backup/moodle2/restore_game_activity_task.class.php
  3. 76
      backup/moodle2/restore_game_stepslib.php
  4. 4
      version.php

67
backup/moodle2/backup_game_stepslib.php

@ -88,39 +88,24 @@ class backup_game_activity_structure_step extends backup_activity_structure_step
'questiontext', 'score', 'timelastattempt', 'studentanswer', 'col', 'row', 'questiontext', 'score', 'timelastattempt', 'studentanswer', 'col', 'row',
'horizontal', 'answertext', 'correct', 'attachment', 'answerid', 'tries')); 'horizontal', 'answertext', 'correct', 'attachment', 'answerid', 'tries'));
$bookquizs = new backup_nested_element('game_bookquizs');
$bookquiz = new backup_nested_element('game_bookquiz', array('id'), array('lastchapterid'));
$bookquizchapters = new backup_nested_element('game_bookquiz_chapters');
$bookquizchapter = new backup_nested_element('game_bookquiz_chapter', array('id'), array( 'chapterid'));
$bookquizquestions = new backup_nested_element('game_bookquiz_questions'); $bookquizquestions = new backup_nested_element('game_bookquiz_questions');
$bookquizquestion = new backup_nested_element('game_bookquiz_question', array('id'), array( $bookquizquestion = new backup_nested_element('game_bookquiz_question', array('id'), array(
'chapterid', 'questioncategoryid')); 'chapterid', 'questioncategoryid'));
$crosss = new backup_nested_element('game_crosss'); // The games attemtps.
$bookquiz = new backup_nested_element('game_bookquiz', array('id'), array('lastchapterid'));
$bookquizchapters = new backup_nested_element('game_bookquiz_chapters');
$bookquizchapter = new backup_nested_element('game_bookquiz_chapter', array('id'), array( 'chapterid'));
$cross = new backup_nested_element('game_cross', array('id'), array( $cross = new backup_nested_element('game_cross', array('id'), array(
'usedcols', 'usedrows', 'words', 'wordsall', 'createscore', 'createtries', 'usedcols', 'usedrows', 'words', 'wordsall', 'createscore', 'createtries',
'createtimelimit', 'createconnectors', 'createfilleds', 'createspaces', 'triesplay')); 'createtimelimit', 'createconnectors', 'createfilleds', 'createspaces', 'triesplay'));
$cryptexs = new backup_nested_element('game_cryptexs');
$cryptex = new backup_nested_element('game_cryptex', array('id'), array('letters')); $cryptex = new backup_nested_element('game_cryptex', array('id'), array('letters'));
$hangmans = new backup_nested_element('game_hangmans');
$hangman = new backup_nested_element('game_hangman', array('id'), array( $hangman = new backup_nested_element('game_hangman', array('id'), array(
'queryid', 'letters', 'allletters', 'try', 'maxtries', 'finishedword', 'queryid', 'letters', 'allletters', 'try', 'maxtries', 'finishedword',
'corrects', 'iscorrect')); 'corrects', 'iscorrect'));
$hiddenpictures = new backup_nested_element('game_hiddenpictures');
$hiddenpicture = new backup_nested_element('game_hiddenpicture', array('id'), array('correct', 'wrong', 'found')); $hiddenpicture = new backup_nested_element('game_hiddenpicture', array('id'), array('correct', 'wrong', 'found'));
$millionaires = new backup_nested_element('game_millionaires');
$millionaire = new backup_nested_element('game_millionaire', array('id'), array('queryid', 'state', 'level')); $millionaire = new backup_nested_element('game_millionaire', array('id'), array('queryid', 'state', 'level'));
$snakes = new backup_nested_element('game_snakes');
$snake = new backup_nested_element('game_snake', array('id'), array('snakesdatabaseid', 'position', 'queryid', 'dice')); $snake = new backup_nested_element('game_snake', array('id'), array('snakesdatabaseid', 'position', 'queryid', 'dice'));
$sudokus = new backup_nested_element('game_sudokus');
$sudoku = new backup_nested_element('game_sudoku', array('id'), array('level', 'data', 'opened', 'guess')); $sudoku = new backup_nested_element('game_sudoku', array('id'), array('level', 'data', 'opened', 'guess'));
// Build the tree. // Build the tree.
@ -133,46 +118,31 @@ class backup_game_activity_structure_step extends backup_activity_structure_step
$game->add_child( $exportjavames); $game->add_child( $exportjavames);
$exportjavames->add_child( $exportjavame); $exportjavames->add_child( $exportjavame);
// All these source definitions only happen if we are including user info.
if ($userinfo) {
$game->add_child( $grades); $game->add_child( $grades);
$grades->add_child( $grade); $grades->add_child( $grade);
$game->add_child( $repetitions); $game->add_child( $repetitions);
$repetitions->add_child( $repetition); $repetitions->add_child( $repetition);
// All these source definitions only happen if we are including user info.
if ($userinfo) {
$game->add_child( $attempts); $game->add_child( $attempts);
$attempts->add_child( $attempt); $attempts->add_child( $attempt);
$attempts->add_child( $querys); $attempt->add_child( $querys);
$querys->add_child( $query); $querys->add_child( $query);
$attempts->add_child( $bookquizs); // All games.
$bookquizs->add_child( $bookquiz); $attempt->add_child( $bookquiz);
$attempt->add_child( $bookquizchapters);
$game->add_child( $bookquizchapters);
$bookquizchapters->add_child($bookquizchapter); $bookquizchapters->add_child($bookquizchapter);
$attempt->add_child( $cross);
$attempts->add_child( $crosss); $attempt->add_child( $cryptex);
$crosss->add_child( $cross); $attempt->add_child( $hangman);
$attempt->add_child( $hiddenpicture);
$attempts->add_child( $cryptexs); $attempt->add_child( $millionaire);
$cryptexs->add_child( $cryptex); $attempt->add_child( $snake);
$attempt->add_child( $sudoku);
$attempts->add_child( $hangmans);
$hangmans->add_child( $hangman);
$attempts->add_child( $hiddenpictures);
$hiddenpictures->add_child( $hiddenpicture);
$attempts->add_child( $millionaires);
$millionaires->add_child( $millionaire);
$attempts->add_child( $snakes);
$snakes->add_child( $snake);
$attempts->add_child( $sudokus);
$sudokus->add_child( $sudoku);
} }
// Define sources. // Define sources.
@ -200,6 +170,7 @@ class backup_game_activity_structure_step extends backup_activity_structure_step
$snake->set_source_table('game_snakes', array( 'id' => backup::VAR_PARENTID)); $snake->set_source_table('game_snakes', array( 'id' => backup::VAR_PARENTID));
$sudoku->set_source_table('game_sudoku', array( 'id' => backup::VAR_PARENTID)); $sudoku->set_source_table('game_sudoku', array( 'id' => backup::VAR_PARENTID));
} }
// Define id annotations. // Define id annotations.
$attempt->annotate_ids('user', 'userid'); $attempt->annotate_ids('user', 'userid');
$grade->annotate_ids('user', 'userid'); $grade->annotate_ids('user', 'userid');
@ -214,8 +185,6 @@ class backup_game_activity_structure_step extends backup_activity_structure_step
$bookquizquestion->annotate_ids('book_chapter', 'chapterid'); $bookquizquestion->annotate_ids('book_chapter', 'chapterid');
$bookquizquestion->annotate_ids('question_category', 'questioncategoryid'); $bookquizquestion->annotate_ids('question_category', 'questioncategoryid');
$bookquizchapter->annotate_ids('book_chapter', 'chapterid'); $bookquizchapter->annotate_ids('book_chapter', 'chapterid');
$hangman->annotate_ids('game_query', 'queryid');
$millionaire->annotate_ids('game_query', 'queryid');
// Define file annotations. // Define file annotations.
$game->annotate_files('mod_game', 'snakes_file', null); // This file area hasn't itemid. $game->annotate_files('mod_game', 'snakes_file', null); // This file area hasn't itemid.

133
backup/moodle2/restore_game_activity_task.class.php

@ -116,138 +116,5 @@ class restore_game_activity_task extends restore_activity_task {
* Do something at end of restore. * Do something at end of restore.
*/ */
public function after_restore() { public function after_restore() {
global $DB;
// Get the blockid.
$gameid = $this->get_activityid();
// Extract Game configdata and update it to point to the new glossary.
$rec = $DB->get_record_select( 'game', 'id='.$gameid,
null, 'id,quizid,glossaryid,glossarycategoryid,questioncategoryid,bookid,glossaryid2,glossarycategoryid2');
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'quiz', $rec->quizid);
if ($ret != false) {
$rec->quizid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary', $rec->glossaryid);
if ($ret != false) {
$rec->glossaryid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary_categories', $rec->glossarycategoryid);
if ($ret != false) {
$rec->glossarycategoryid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'question_categories', $rec->questioncategoryid);
if ($ret != false) {
$rec->questioncategoryid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'book', $rec->bookid);
if ($ret != false) {
$rec->bookid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary', $rec->glossaryid2);
if ($ret != false) {
$rec->glossaryid2 = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary_categories', $rec->glossarycategoryid);
if ($ret != false) {
$rec->glossarycategoryid = $ret->newitemid;
}
$DB->update_record( 'game', $rec);
// Read game_repetitions.
$recs = $DB->get_records_select( 'game_repetitions', 'gameid='.$gameid, null, '',
'id,questionid,glossaryentryid');
if ($recs != false) {
foreach ($recs as $rec) {
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'question', $rec->questionid);
if ($ret != false) {
$rec->questionid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary_entry', $rec->glossaryentryid);
if ($ret != false) {
$rec->glossaryentryid = $ret->newitemid;
}
$DB->update_record( 'game_repetitions', $rec);
}
}
// Read game_queries.
$recs = $DB->get_records_select( 'game_queries', 'gameid='.$gameid, null, '',
'id,questionid,glossaryentryid,answerid');
if ($recs != false) {
foreach ($recs as $rec) {
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'question', $rec->questionid);
if ($ret != false) {
$rec->questionid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary_entry', $rec->glossaryentryid);
if ($ret != false) {
$rec->glossaryentryid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'question_answers', $rec->glossaryentryid);
if ($ret != false) {
$rec->answerid = $ret->newitemid;
}
$DB->update_record( 'game_queries', $rec);
}
}
// Read bookquiz.
$recs = $DB->get_records_select( 'game_bookquiz', 'id='.$gameid, null, '', 'id,lastchapterid');
if ($recs != false) {
foreach ($recs as $rec) {
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'book_chapters', $rec->lastchapterid);
if ($ret != false) {
$rec->lastchapterid = $ret->newitemid;
}
$DB->update_record( 'game_bookquiz', $rec);
}
}
// Read bookquiz_chapters.
$sql = "SELECT gbc.* ".
"FROM {game_bookquiz_chapters} gbc LEFT JOIN {game_attempts} a ON gbc.attemptid = a.id".
" WHERE a.gameid=$gameid";
$recs = $DB->get_records_sql( $sql);
if ($recs != false) {
foreach ($recs as $rec) {
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'book_chapters', $rec->chapterid);
if ($ret != false) {
$rec->chapterid = $ret->newitemid;
}
$DB->update_record( 'game_bookquiz_chapter', $rec);
}
}
// Read bookquiz_questions.
$recs = $DB->get_records_select( 'game_bookquiz_questions', 'id='.$gameid, null, '', 'id,chapterid,questioncategoryid');
if ($recs != false) {
foreach ($recs as $rec) {
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'book_chapters', $rec->chapterid);
if ($ret != false) {
$rec->chapterid = $ret->newitemid;
}
$ret = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'book_chapters', $rec->questioncategoryid);
if ($ret != false) {
$rec->questioncategoryid = $ret->newitemid;
}
$DB->update_record( 'game_bookquiz_questions', $rec);
}
}
} }
} }

76
backup/moodle2/restore_game_stepslib.php

@ -25,6 +25,8 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/game/locallib.php');
/** /**
* Structure step to restore one game activity * Structure step to restore one game activity
* @copyright 2007 Vasilis Daloukas * @copyright 2007 Vasilis Daloukas
@ -52,17 +54,20 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$paths[] = new restore_path_element('game_grade', '/activity/game/game_grades/game_grade'); $paths[] = new restore_path_element('game_grade', '/activity/game/game_grades/game_grade');
$paths[] = new restore_path_element('game_repetition', '/activity/game/game_repetiotions/game_repetition'); $paths[] = new restore_path_element('game_repetition', '/activity/game/game_repetiotions/game_repetition');
$paths[] = new restore_path_element('game_attempt', '/activity/game/game_attempts/game_attempt'); $paths[] = new restore_path_element('game_attempt', '/activity/game/game_attempts/game_attempt');
$paths[] = new restore_path_element('game_query', '/activity/game/game_querys/game_query'); $paths[] = new restore_path_element('game_query', '/activity/game/game_attempts/game_attempt/game_querys/game_query');
$paths[] = new restore_path_element('game_bookquiz', '/activity/game/game_bookquizs/game_bookquiz');
// The games.
$paths[] = new restore_path_element('game_bookquiz', '/activity/game/game_attempts/game_attempt/game_bookquiz');
$paths[] = new restore_path_element('game_bookquiz_chapter', $paths[] = new restore_path_element('game_bookquiz_chapter',
'/activity/game/game_bookquiz_chapters/game_bookquiz_chapter'); '/activity/game/game_attempts/game_attempt/game_bookquiz_chapters/game_bookquiz_chapter');
$paths[] = new restore_path_element('game_cross', '/activity/game/game_crosss/game_cross'); $paths[] = new restore_path_element('game_cross', '/activity/game/game_attempts/game_attempt/game_cross');
$paths[] = new restore_path_element('game_cryptex', '/activity/game/game_cryptexs/game_cryptex'); $paths[] = new restore_path_element('game_cryptex', '/activity/game/game_attempts/game_attempt/game_cryptex');
$paths[] = new restore_path_element('game_hangman', '/activity/game/game_hangmans/game_hangman'); $paths[] = new restore_path_element('game_hangman', '/activity/game/game_attempts/game_attempt/game_hangman');
$paths[] = new restore_path_element('game_hiddenpicture', '/activity/game/game_hiddenpictures/game_hiddenpicture'); $paths[] = new restore_path_element('game_hiddenpicture',
$paths[] = new restore_path_element('game_millionaire', '/activity/game/game_millionaires/game_millionaire'); '/activity/game/game_attempts/game_attempt/game_hiddenpicture');
$paths[] = new restore_path_element('game_snake', '/activity/game/game_snakes/game_snake'); $paths[] = new restore_path_element('game_millionaire', '/activity/game/game_attempts/game_attempt/game_millionaire');
$paths[] = new restore_path_element('game_sudoku', '/activity/game/game_sudokus/game_sudoku'); $paths[] = new restore_path_element('game_snake', '/activity/game/game_attempts/game_attempt/game_snake');
$paths[] = new restore_path_element('game_sudoku', '/activity/game/game_attempts/game_attempt/game_sudoku');
} }
// Return the paths wrapped into standard activity structure. // Return the paths wrapped into standard activity structure.
@ -81,6 +86,13 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$oldid = $data->id; $oldid = $data->id;
$data->course = $this->get_courseid(); $data->course = $this->get_courseid();
$data->timemodified = $this->apply_date_offset($data->timemodified); $data->timemodified = $this->apply_date_offset($data->timemodified);
$data->quizid = $this->get_mappingid('quiz', $data->quizid);
$data->glossaryid = $this->get_mappingid('glossary', $data->glossaryid);
$data->glossarycategoryid = $this->get_mappingid('glossary_categories', $data->glossarycategoryid);
$data->questioncategoryid = $this->get_mappingid('question_categories', $data->questioncategoryid);
$data->bookid = $this->get_mappingid('book', $data->bookid);
$data->glossaryid2 = $this->get_mappingid('glossary', $data->glossaryid2);
$data->glossarycategoryid2 = $this->get_mappingid('glossary_categories', $data->glossarycategoryid2);
// Insert the game record. // Insert the game record.
$newitemid = $DB->insert_record('game', $data); $newitemid = $DB->insert_record('game', $data);
@ -153,6 +165,8 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data->gameid = $this->get_new_parentid('game'); $data->gameid = $this->get_new_parentid('game');
$data->userid = $this->get_mappingid('user', $data->userid); $data->userid = $this->get_mappingid('user', $data->userid);
$data->questionid = $this->get_mappingid('question', $data->questionid);
$data->glossaryentrydid = $this->get_mappingid('glossary_entries', $data->questionid);
$DB->insert_record('game_repetitions', $data); $DB->insert_record('game_repetitions', $data);
} }
@ -203,6 +217,9 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data->gameid = $this->get_new_parentid('game'); $data->gameid = $this->get_new_parentid('game');
$data->attemptid = get_mappingid('game_attempt', $data->attemptid); $data->attemptid = get_mappingid('game_attempt', $data->attemptid);
$data->userid = $this->get_mappingid('user', $data->userid); $data->userid = $this->get_mappingid('user', $data->userid);
$data->questionid = $this->get_mappingid('question', $data->questionid);
$data->glossaryentryid = $this->get_mappingid('glossary_entries', $data->glossaryentryid);
$data->answerid = $this->get_mappingid('question_answers', $data->answerid);
$newitemid = $DB->insert_record('game_queries', $data); $newitemid = $DB->insert_record('game_queries', $data);
$this->set_mapping('game_query', $oldid, $newitemid); $this->set_mapping('game_query', $oldid, $newitemid);
@ -219,6 +236,7 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game');
$data->lastchapterid = $this->get_mappingid('book_chapters', $data->lastchapterid);
$DB->insert_record('game_bookquiz', $data); $DB->insert_record('game_bookquiz', $data);
} }
@ -233,7 +251,8 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->gameid = $this->get_new_parentid('game'); $data->attemptid = $this->get_new_parentid('game_attempts');
$data->chapterid = $this->get_mappingid('book_chapters', $data->chapterid);
$DB->insert_record('game_bookquiz_chapters', $data); $DB->insert_record('game_bookquiz_chapters', $data);
} }
@ -249,6 +268,8 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->gameid = $this->get_new_parentid('game'); $data->gameid = $this->get_new_parentid('game');
$data->chapterid = $this->get_mappingid('book_chapters', $data->chapterid);
$data->questioncategoryid = $this->get_mappingid('question_categories', $data->questioncategoryid);
$DB->insert_record('game_bookquiz_questions', $data); $DB->insert_record('game_bookquiz_questions', $data);
} }
@ -263,9 +284,9 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game_attempt');
$DB->insert_record('game_cross', $data); game_insert_record( 'game_cross', $data);
} }
/** /**
@ -278,9 +299,9 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game_attempt');
$DB->insert_record('game_cryptex', $data); game_insert_record( 'game_cryptex', $data);
} }
/** /**
@ -293,10 +314,10 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game_attempt');
$data->queryid = $this->get_mappingid('game_query', $data->queryid); $data->queryid = $this->get_mappingid('game_query', $data->queryid);
$DB->insert_record('game_hangman', $data); game_insert_record( 'game_hangman', $data);
} }
/** /**
@ -309,9 +330,9 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game_attempt');
$DB->insert_record('game_hiddenpicture', $data); game_insert_record( 'game_hiddenpicture', $data);
} }
/** /**
@ -324,10 +345,10 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game_attempt');
$data->queryid = $this->get_mappingid('game_query', $data->queryid); $data->queryid = $this->get_mappingid('game_queries', $data->queryid);
$DB->insert_record('game_millionaire', $data); game_insert_record( 'game_millionaire', $data);
} }
/** /**
@ -340,10 +361,10 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_mappingid('game', $data->id); $data->id = $this->get_mappingid('game_attempt', $data->id);
$data->queryid = $this->get_mappingid('game_query', $data->queryid); $data->queryid = $this->get_mappingid('game_queries', $data->queryid);
$DB->insert_record('game_snakes', $data); game_insert_record( 'game_snakes', $data);
} }
/** /**
@ -356,9 +377,10 @@ class restore_game_activity_structure_step extends restore_activity_structure_st
$data = (object)$data; $data = (object)$data;
$data->id = $this->get_new_parentid('game'); $data->id = $this->get_new_parentid('game_attempt');
$data->queryid = $this->get_mappingid('game_queries', $data->queryid);
$DB->insert_record('game_sudoku', $data); game_insert_record( 'game_sudoku', $data);
} }
/** /**

4
version.php

@ -35,10 +35,10 @@ if (!isset( $plugin)) {
} }
$plugin->component = 'mod_game'; // Full name of the plugin (used for diagnostics). $plugin->component = 'mod_game'; // Full name of the plugin (used for diagnostics).
$plugin->version = 2017070403; // The current module version (Date: YYYYMMDDXX). $plugin->version = 2017070501; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2010112400; // Requires Moodle 2.0. $plugin->requires = 2010112400; // Requires Moodle 2.0.
$plugin->cron = 0; // Period for cron to check this module (secs). $plugin->cron = 0; // Period for cron to check this module (secs).
$plugin->release = '2017-07-04'; $plugin->release = '2017-07-05';
$plugin->maturity = MATURITY_STABLE; $plugin->maturity = MATURITY_STABLE;
if ($useplugin != 2) { if ($useplugin != 2) {

Loading…
Cancel
Save