Skip to content

Commit

Permalink
allow changing order of last and first name (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippImhof authored Aug 20, 2024
1 parent ee4f8bf commit 3e7da9f
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 2 deletions.
11 changes: 11 additions & 0 deletions essaydownload_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ protected function standard_preference_fields(MoodleQuickForm $mform) {
$mform->addElement('advcheckbox', 'responsetext', get_string('includeresponsetext', 'quiz_essaydownload'));
$mform->addElement('advcheckbox', 'attachments', get_string('includeattachments', 'quiz_essaydownload'));

$mform->addElement(
'select',
'nameordering',
get_string('nameordering', 'quiz_essaydownload'),
[
'lastfirst' => get_string('lastfirst', 'quiz_essaydownload'),
'firstlast' => get_string('firstlast', 'quiz_essaydownload'),
]
);
$mform->setType('nameordering', PARAM_ALPHA);

$mform->addElement(
'advcheckbox',
'shortennames',
Expand Down
8 changes: 7 additions & 1 deletion essaydownload_options.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ class quiz_essaydownload_options extends quiz_essaydownload_options_parent_class
/** @var bool whether to include attachments (if there are) in the archive */
public $attachments = true;

/** @var bool whether to shorten file and path names to workaround a Windows issue */
/** @var string whether to shorten file and path names to workaround a Windows issue */
public $shortennames = false;

/** @var string how to organise the sub folders in the archive (by question or by attempt) */
public $groupby = 'byattempt';

/** @var string whether to have the last name or the first name first */
public $nameordering = 'lastfirst';

/**
* Constructor
*
Expand All @@ -86,6 +89,7 @@ public function get_initial_form_data() {
$toform->attachments = $this->attachments;
$toform->shortennames = $this->shortennames;
$toform->groupby = $this->groupby;
$toform->nameordering = $this->nameordering;

return $toform;
}
Expand All @@ -101,6 +105,7 @@ public function setup_from_form_data($fromform): void {
$this->attachments = $fromform->attachments;
$this->shortennames = $fromform->shortennames;
$this->groupby = $fromform->groupby;
$this->nameordering = $fromform->nameordering;
}

/**
Expand All @@ -112,6 +117,7 @@ public function setup_from_params() {
$this->attachments = optional_param('attachments', $this->attachments, PARAM_BOOL);
$this->shortennames = optional_param('shortennames', $this->shortennames, PARAM_BOOL);
$this->groupby = optional_param('groupby', $this->groupby, PARAM_ALPHA);
$this->nameordering = optional_param('nameordering', $this->nameordering, PARAM_ALPHA);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions lang/en/quiz_essaydownload.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@
$string['errorfilename'] = 'error-{$a}.txt';
$string['errormessage'] = 'An internal error occurred. The archive is probably incomplete. Please contact the developers of the Essay responses downloader plugin (quiz_essaydownload) and send them the details below:';
$string['essaydownload'] = 'Download essay responses';
$string['firstlast'] = 'First name - Last name';
$string['groupby'] = 'Group by';
$string['groupby_help'] = 'The archive can be structured by question or by attempt:<ul><li>If you group by question, the archive will have a folder for every question. Inside each folder, you will have a folder for every attempt.</li><li>If you group by attempt, the archive will have a folder for every attempt. Inside each folder, you will have a folder for every question.</li></ul>';
$string['includeattachments'] = 'Include attachments, if there are any';
$string['includequestiontext'] = 'Include question text';
$string['includeresponsetext'] = 'Include response text';
$string['lastfirst'] = 'Last name - First name';
$string['nameordering'] = 'Name format';
$string['noessayquestion'] = 'This quiz does not contain any essay questions.';
$string['nothingtodownload'] = 'Nothing to download';
$string['options'] = 'Options';
Expand Down
9 changes: 8 additions & 1 deletion report.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,15 @@ public function get_attempts_and_names(sql_join $joins): array {
$result->firstname = substr($result->firstname, 0, 40);
}

// The user can choose whether to start with the first name or the last name.
if ($this->options->nameordering === 'firstlast') {
$name = $result->firstname . '_' . $result->lastname;
} else {
$name = $result->lastname . '_' . $result->firstname;
}

// Build the path for this attempt: <name>_<attemptid>_<date/time finished>.
$path = $result->lastname . '_' . $result->firstname . '_' . $result->attemptid;
$path = $name . '_' . $result->attemptid;
$path = $path . '_' . date('Ymd_His', $result->timefinish);
$path = self::clean_filename($path);

Expand Down
57 changes: 57 additions & 0 deletions tests/report_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,63 @@ public function test_long_names_being_shortened(): void {
}
}

public function test_custom_name_order(): void {
$this->resetAfterTest();

// Create a course and a quiz with an essay question.
$generator = $this->getDataGenerator();
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
$course = $generator->create_course();
$quiz = $this->create_test_quiz($course);
$quiz->name = 'ThisQuizHasAnExtremelyLongTitleBecauseLongTitlesAreJustSoCoolToHave';
quiz_essaydownload_test_helper::add_essay_question($questiongenerator, $quiz);

// Add a student and an attempt.
$student = \phpunit_util::get_data_generator()->create_user(['firstname' => 'First', 'lastname' => 'Last']);
\phpunit_util::get_data_generator()->enrol_user($student->id, $course->id, 'student');
$attempt = $this->attempt_quiz($quiz, $student);

$cm = get_coursemodule_from_id('quiz', $quiz->cmid);
$report = new quiz_essaydownload_report();

list($currentgroup, $allstudentjoins, $groupstudentjoins, $allowedjoins) =
$report->init('essaydownload', 'quiz_essaydownload_form', $quiz, $cm, $course);

// Use reflection to force other name format.
$reflectedreport = new \ReflectionClass($report);
$reflectedoptions = $reflectedreport->getProperty('options');
$reflectedoptions->setAccessible(true);
$options = new quiz_essaydownload_options('essaydownload', $quiz, $cm, $course);
$options->nameordering = 'firstlast';
$reflectedoptions->setValue($report, $options);

// Fetch the attemps using the report's API.
$fetchedattempts = $report->get_attempts_and_names($groupstudentjoins);

// There should be exactly one attempt.
self::assertCount(1, $fetchedattempts);

$i = 0;
foreach ($fetchedattempts as $fetchedid => $fetchedname) {
// The attempt is stored in a somewhat obscure way.
$attemptobj = $attempt[2]->get_attempt();

$id = $attemptobj->id;
self::assertEquals($id, $fetchedid);

$firstname = clean_filename(str_replace(' ', '_', $student->firstname));
$lastname = clean_filename(str_replace(' ', '_', $student->lastname));

$name = $firstname . '_' . $lastname . '_' . $id . '_' . date('Ymd_His', $attemptobj->timefinish);

// We will not compare the minutes and seconds, because there might be a small difference and
// we don't really care. If the timestamp is correct up to the hours, we can safely assume the
// conversion worked.
self::assertStringStartsWith(substr($name, 0, -4), $fetchedname);
$i++;
}
}

public function test_get_attempts_and_names_without_groups(): void {
$this->resetAfterTest();

Expand Down

0 comments on commit 3e7da9f

Please sign in to comment.