Skip to content

Commit

Permalink
quiz-data - Make quiz import/export easier. Catch Moodle instance mis…
Browse files Browse the repository at this point in the history
…match.
  • Loading branch information
EJMFarrow committed Dec 10, 2024
1 parent 42d99fc commit c93a91b
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 52 deletions.
8 changes: 8 additions & 0 deletions classes/create_repo.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ class create_repo {
* @var string
*/
public string $manifestpath;
/**
* Path to actual manifest file.
*
* @var string
*/
public string $nonquizmanifestpath;
/**
* Path to temporary manifest file.
*
Expand Down Expand Up @@ -134,6 +140,8 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
} else {
$this->directory = $arguments['rootdirectory'];
}
$this->nonquizmanifestpath = ($arguments['rootdirectory']) ?
$arguments['rootdirectory'] . '/' . $arguments['nonquizmanifestpath'] : $arguments['nonquizmanifestpath'];
$this->subcategory = ($arguments['subcategory']) ? $arguments['subcategory'] : 'top';
if (is_array($arguments['token'])) {
$token = $arguments['token'][$moodleinstance];
Expand Down
10 changes: 9 additions & 1 deletion classes/export_quiz.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
// Convert command line options into variables.
$arguments = $clihelper->get_arguments();
$moodleinstance = $arguments['moodleinstance'];
$this->moodleurl = $moodleinstances[$moodleinstance];
$rootdirectory = ($arguments['rootdirectory']) ? $arguments['rootdirectory'] . '/' : '';
$this->quizmanifestpath = ($arguments['quizmanifestpath']) ?
$rootdirectory . $arguments['quizmanifestpath'] : null;
Expand All @@ -115,6 +116,10 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
echo "\nUnable to access or parse manifest file: {$this->quizmanifestpath}\nAborting.\n";
$this->call_exit();
}
if ($this->quizmanifestcontents->context->moodleurl !== $this->moodleurl) {
echo "\nManifest file is for the wrong Moodle instance: {$this->quizmanifestpath}\nAborting.\n";
$this->call_exit();
}
$instanceid = $this->quizmanifestcontents->context->instanceid;
if ($arguments['nonquizmanifestpath']) {
$this->nonquizmanifestpath = ($arguments['nonquizmanifestpath']) ?
Expand All @@ -124,14 +129,17 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
echo "\nUnable to access or parse manifest file: {$this->nonquizmanifestpath}\nAborting.\n";
$this->call_exit();
}
if ($this->nonquizmanifestcontents->context->moodleurl !== $this->moodleurl) {
echo "\nManifest file is for the wrong Moodle instance: {$this->nonquizmanifestpath}\nAborting.\n";
$this->call_exit();
}
}
if (is_array($arguments['token'])) {
$token = $arguments['token'][$moodleinstance];
} else {
$token = $arguments['token'];
}

$this->moodleurl = $moodleinstances[$moodleinstance];
$wsurl = $this->moodleurl . '/webservice/rest/server.php';

$this->curlrequest = $this->get_curl_request($wsurl);
Expand Down
28 changes: 13 additions & 15 deletions classes/export_repo.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ class export_repo {
* @var string
*/
public string $manifestpath;
/**
* Full path to manifest file
*
* @var string
*/
public string $nonquizmanifestpath;
/**
* Path to temporary manifest file
*
Expand Down Expand Up @@ -120,6 +126,8 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
$defaultwarning = false;
$this->manifestpath = ($arguments['rootdirectory']) ? $arguments['rootdirectory'] . '/' . $arguments['manifestpath'] :
$arguments['manifestpath'];
$this->nonquizmanifestpath = ($arguments['rootdirectory']) ?
$arguments['rootdirectory'] . '/' . $arguments['nonquizmanifestpath'] : $arguments['nonquizmanifestpath'];
if (is_array($arguments['token'])) {
$token = $arguments['token'][$moodleinstance];
} else {
Expand All @@ -130,6 +138,11 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
echo "\nUnable to access or parse manifest file: {$this->manifestpath}\nAborting.\n";
$this->call_exit();
}
if ($this->manifestcontents->context->moodleurl !== $this->moodleurl) {
echo "\nManifest file is for the wrong Moodle instance: {$this->manifestcontents}\nAborting.\n";
$this->call_exit();
}

if ($arguments['subcategory']) {
$this->subcategory = $arguments['subcategory'];
$qcategoryid = null;
Expand Down Expand Up @@ -376,21 +389,6 @@ public function call_repo_creation(string $rootdirectory, string $moodleinstance
'" -l "module" -n ' . $instanceid . ' -t ' . $token . $ignorecat);
}

/**
* Separate out exec call for mocking.
*
* @param string $moodleinstance
* @param string $token
* @param string $quizmanifestpath
* @return string|null
*/
public function call_export_quiz(string $moodleinstance, string $token,
string $quizmanifestpath, string $scriptdirectory): ?string {
chdir($scriptdirectory);
return shell_exec('php exportquizstructurefrommoodle.php -u ' . $this->usegit . ' -w -r "" -i "' . $moodleinstance . '" -t '
. $token. ' -p "' . $this->manifestpath . '" -f "' . $quizmanifestpath . '"');
}

/**
* Separate out exec call for mocking.
*
Expand Down
3 changes: 2 additions & 1 deletion classes/export_trait.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,10 @@ public function export_quiz_structure($clihelper, $scriptdirectory) {
public function call_export_quiz(string $moodleinstance, string $token,
string $quizmanifestpath, string $scriptdirectory): ?string {
chdir($scriptdirectory);
$nonquiz = ($this->nonquizmanifestpath) ? ' -p "' . $this->nonquizmanifestpath . '"' : '';
return shell_exec('php exportquizstructurefrommoodle.php -u ' . $this->usegit .
' -w -r "" -i "' . $moodleinstance . '" -t "'
. $token. '" -p "' . $this->manifestpath . '" -f "' . $quizmanifestpath . '"');
. $token. '" -f "' . $quizmanifestpath . '"' . $nonquiz);
}

/**
Expand Down
23 changes: 16 additions & 7 deletions classes/import_quiz.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
$directoryprefix = ($directory) ? $directory . '/' : '';
$coursename = $arguments['coursename'];
$moodleinstance = $arguments['moodleinstance'];
$this->moodleurl = $moodleinstances[$moodleinstance];
$instanceid = $arguments['instanceid'];
$contextlevel = 50;
$this->usegit = $arguments['usegit'];
Expand All @@ -150,8 +151,11 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
if (!$this->quizmanifestcontents) {
echo "\nUnable to access or parse manifest file: {$this->quizmanifestpath}\nAborting.\n";
$this->call_exit();

} else {
if ($this->quizmanifestcontents->context->moodleurl !== $this->moodleurl) {
echo "\nManifest file is for the wrong Moodle instance: {$this->quizmanifestpath}\nAborting.\n";
$this->call_exit();
}
$this->cmid = $this->quizmanifestcontents->context->instanceid;
$this->quizdatapath = ($arguments['quizdatapath']) ? $directoryprefix . $arguments['quizdatapath']
: cli_helper::get_quiz_structure_path($this->quizmanifestcontents->context->modulename,
Expand Down Expand Up @@ -188,13 +192,17 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
}
}
if (!empty($arguments['nonquizmanifestpath'])) {
$this->nonquizmanifestpath = ($arguments['nonquizmanifestpath']) ?
$directoryprefix . $arguments['nonquizmanifestpath'] : null;
$this->nonquizmanifestpath = ($arguments['rootdirectory']) ?
$arguments['rootdirectory'] . '/' . $arguments['nonquizmanifestpath'] : $arguments['nonquizmanifestpath'];
$this->nonquizmanifestcontents = json_decode(file_get_contents($this->nonquizmanifestpath));
if (!$this->nonquizmanifestcontents) {
echo "\nUnable to access or parse manifest file: {$this->nonquizmanifestpath}\nAborting.\n";
$this->call_exit();
}
if ($this->nonquizmanifestcontents->context->moodleurl !== $this->moodleurl) {
echo "\nManifest file is for the wrong Moodle instance: {$this->nonquizmanifestpath}\nAborting.\n";
$this->call_exit();
}
if (!$instanceid && $this->nonquizmanifestcontents->context->contextlevel === cli_helper::get_context_level('course')) {
$instanceid = $this->nonquizmanifestcontents->context->instanceid;
}
Expand All @@ -216,7 +224,6 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
$token = $arguments['token'];
}

$this->moodleurl = $moodleinstances[$moodleinstance];
$wsurl = $this->moodleurl . '/webservice/rest/server.php';

$this->listcurlrequest = $this->get_curl_request($wsurl);
Expand Down Expand Up @@ -310,6 +317,8 @@ public function import_all($clihelper, $scriptdirectory): void {
} else {
$directory = $arguments['rootdirectory'];
}
$this->nonquizmanifestpath = ($arguments['rootdirectory']) ?
$arguments['rootdirectory'] . '/' . $arguments['nonquizmanifestpath'] : $arguments['nonquizmanifestpath'];
if (is_array($arguments['token'])) {
$token = $arguments['token'][$moodleinstance];
} else {
Expand Down Expand Up @@ -353,10 +362,10 @@ public function call_import_repo(string $rootdirectory, string $moodleinstance,
*/
public function call_import_quiz_data(string $moodleinstance, string $token, string $scriptdirectory): ?string {
chdir($scriptdirectory);
$nonquiz = ($this->nonquizmanifestpath) ? ' -p "' . $this->nonquizmanifestpath . '"' : '';
return shell_exec('php importquizstructuretomoodle.php -u ' . $this->usegit .
' -w -r "" -i "' . $moodleinstance . '" -t ' . $token. ' -p "' . $this->nonquizmanifestpath.
'" -a "' . $this->quizdatapath .
'" -f "' . $this->quizmanifestpath. '"');
' -w -r "" -i "' . $moodleinstance . '" -t ' . $token. ' -a "' . $this->quizdatapath .
'" -f "' . $this->quizmanifestpath. '"' . $nonquiz);
}

/**
Expand Down
6 changes: 5 additions & 1 deletion classes/import_repo.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ public function __construct(cli_helper $clihelper, array $moodleinstances) {
$this->manifestcontents->questions = [];
} else {
$this->manifestcontents = $manifestcontents;
if ($this->manifestcontents->context->moodleurl !== $this->moodleurl) {
echo "\nManifest file is for the wrong Moodle instance: {$this->manifestcontents}\nAborting.\n";
$this->call_exit();
}
}

if ($manifestpath) {
Expand Down Expand Up @@ -871,7 +875,7 @@ public function check_question_versions(): void {
}

/**
* Create/update quizzes.
* Create/update quizzes for whole course.
* @param object $clihelper
* @param string $scriptdirectory - directory of CLI scripts
* @return void
Expand Down
18 changes: 14 additions & 4 deletions cli/createrepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@
'variable' => 'instanceid',
'valuerequired' => true,
],
[
'longopt' => 'nonquizmanifestpath',
'shortopt' => 'p',
'description' => 'Filepath of non-quiz manifest file relative to root directory.',
'default' => null,
'variable' => 'nonquizmanifestpath',
'valuerequired' => true,
],
[
'longopt' => 'token',
'shortopt' => 't',
Expand Down Expand Up @@ -169,12 +177,14 @@
$createrepo->process();
$clihelper->commit_hash_setup($createrepo);
// If we're exporting a quiz then we try getting the structure as well.
// Skip if we're creating a whole cpurse repo or we'll do it twice!
// Skip if we're creating a whole course repo or we'll do it twice!
if ($createrepo->manifestcontents->context->contextlevel === 70 && !$clihelper->get_arguments()['subcall']) {
$scriptdirectory = dirname(__FILE__);
$createrepo->export_quiz_structure($clihelper, $scriptdirectory);
chdir(dirname($createrepo->manifestpath));
exec("git add --all");
exec('git commit -m "Initial Commit - Quiz structure"');
if ($clihelper->get_arguments()['usegit']) {
chdir(dirname($createrepo->manifestpath));
exec("git add --all");
exec('git commit -m "Initial Commit - Quiz structure"');
}
}

6 changes: 0 additions & 6 deletions cli/exportquizstructurefrommoodle.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,6 @@
}
$clihelper = new cli_helper($options);
$exportquiz = new export_quiz($clihelper, $moodleinstances);
if ($exportquiz->nonquizmanifestpath) {
if (empty($clihelper->get_arguments()['subcall'])) {
echo "Checking repo...\n";
}
$clihelper->check_for_changes($exportquiz->nonquizmanifestpath);
}
if ($exportquiz->quizmanifestpath) {
if (empty($clihelper->get_arguments()['subcall'])) {
echo "Checking quiz repo...\n";
Expand Down
8 changes: 8 additions & 0 deletions cli/exportrepofrommoodle.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@
'variable' => 'rootdirectory',
'valuerequired' => true,
],
[
'longopt' => 'nonquizmanifestpath',
'shortopt' => 'p',
'description' => 'Filepath of non-quiz manifest file relative to root directory.',
'default' => null,
'variable' => 'nonquizmanifestpath',
'valuerequired' => true,
],
[
'longopt' => 'manifestpath',
'shortopt' => 'f',
Expand Down
4 changes: 0 additions & 4 deletions cli/importquizstructuretomoodle.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,6 @@

$clihelper = new cli_helper($options);
$importquiz = new import_quiz($clihelper, $moodleinstances);
if ($importquiz->nonquizmanifestpath && empty($clihelper->get_arguments()['subcall'])) {
echo "Checking repo...\n";
$clihelper->check_for_changes($importquiz->nonquizmanifestpath);
}
if ($importquiz->quizmanifestpath && empty($clihelper->get_arguments()['subcall'])) {
echo "Checking quiz repo...\n";
$clihelper->check_for_changes($importquiz->quizmanifestpath);
Expand Down
8 changes: 8 additions & 0 deletions cli/importquiztomoodle.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@
'valuerequired' => true,
'hidden' => true,
],
[
'longopt' => 'nonquizmanifestpath',
'shortopt' => 'p',
'description' => 'Filepath of non-quiz manifest file relative to root directory.',
'default' => null,
'variable' => 'nonquizmanifestpath',
'valuerequired' => true,
],
[
'longopt' => 'quizdatapath',
'shortopt' => 'a',
Expand Down
2 changes: 1 addition & 1 deletion doc/importquiztomoodle.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Commit this update.
|-|-|-|
|i|moodleinstance|Key of Moodle instance in moodleinstances to use. Should match end of instance URL.|
|r|rootdirectory|Directory on user's computer containing repos.|
|f|manifestpath|Filepath of manifest file relative to root directory.|
|p|nonquizmanifestpath|Filepath of manifest file relative to root directory.|
|a|quizdatapath|Filepath of quiz data file relative to root directory.
|d|directory|Directory of repo on users computer containing "top" folder, relative to root directory.|
|s|subdirectory|Relative subdirectory of repo to actually import.|
Expand Down
20 changes: 8 additions & 12 deletions doc/usinggit.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,30 +174,26 @@ Import questions again after updates in the repo:
Create quiz and import into course with `id=2`:
`php importquiztomoodle.php -d 'quizexport' -n 2`

### To handle a quiz that only uses questions from another context
- `createrepo.php` will export the questions into the new repo but will not export the structure and will list the questions from other contexts.
- `exportrepofrommoodle.php` will update the questions in the repo.
- Use `exportquizstructurefrommoodle.php` to export the quiz structure from Moodle.
- Use `importquiztomoodle.php` for initial import of questions and structure into a Moodle instance. (Quiz will be created within a specified course.)
### To handle a quiz that uses questions from another context
- `createrepo.php` will export the questions into the new repo but will not export the structure and will list the questions from other contexts unless you also supply a manifest file containing the additional questions.
- `exportrepofrommoodle.php` will update the questions in the repo (and the quiz structure if you supply the manifest file again).
- Use `exportquizstructurefrommoodle.php` to export just the quiz structure from Moodle if needed.
- Use `importquiztomoodle.php` for initial import of questions and structure into a Moodle instance. (The quiz will be created within a specified course.)
- Use `importrepotomoodle.php` to update questions in Moodle.
- Manually update structure in Moodle.

Example:
Initialise repo for quiz:
`git init quizexport`
Export quiz with `cmid=50` into directory `quizexport` (assuming rootdirectory, token, moodleinstance, usegit, etc, all set in your config file.):
`php createrepo.php -d 'quizexport' -l module -n 50`
Export quiz structure by supplying quiz and course manifests:
`php exportquizstructurefrommoodle.php -f 'quizexport/instance1_module_course-1_mixed-quiz_question_manifest.json' -p 'course1/instance1_course_course-1_question_manifest.json'`
`php createrepo.php -d 'quizexport' -l module -n 49 -p 'course1/instance1_course_course-1_question_manifest.json'`
Export questions/structures again after updates in Moodle:
`php exportrepofrommoodle.php -f 'quizexport/instance1_module_course-1_quiz-only_question_manifest.json'`
`php exportquizstructurefrommoodle.php -f 'quizexport/instance1_module_course-1_mixed-quiz_question_manifest.json' -p 'course1/instance1_course_course-1_question_manifest.json'`
`php exportrepofrommoodle.php -f 'quizexport/instance1_module_course-1_mixed-quiz_question_manifest.json' -p 'course1/instance1_course_course-1_question_manifest.json'`
Import questions again after updates in the repo:
`php importrepotomoodle.php -f 'quizexport/instance1_module_course-1_quiz-only_question_manifest.json'`
`php importrepotomoodle.php -f 'quizexport/instance1_module_course-1_mixed-quiz_question_manifest.json'`
Create quiz and import into course with `id=2`:
`php importquiztomoodle.php -d 'quizexport' -n 2 -p 'course1/instance1_course_course-1_question_manifest.json'`


### To handle a course and its quizzes in a single repo
- `createwholecourserepo.php` will export a course context and associated quizzes in sibling directories. As long as the quizzes only use questions from the course and their own context, the quiz structures will be exported.
- `exportwholecoursefrommoodle.php` will update the questions and quiz structures in the repo.
Expand Down

0 comments on commit c93a91b

Please sign in to comment.