diff --git a/classes/ArchiveJob.php b/classes/ArchiveJob.php index c6a7fd7..2929b58 100644 --- a/classes/ArchiveJob.php +++ b/classes/ArchiveJob.php @@ -39,13 +39,13 @@ class ArchiveJob { /** @var string UUID of the job, as assigned by the archive worker */ protected string $jobid; /** @var int ID of the course this job is associated with */ - protected int $course_id; + protected int $courseid; /** @var int ID of the course module this job is associated with */ - protected int $cm_id; + protected int $cmid; /** @var int ID of the quiz this job is associated with */ - protected int $quiz_id; + protected int $quizid; /** @var int ID of the user that owns this job */ - protected int $user_id; + protected int $userid; /** @var int Unix timestamp of job creation */ protected int $timecreated; /** @var int|null Unix timestamp after which this jobs artifacts will be deleted automatically. Null indicates no deletion.*/ @@ -54,7 +54,7 @@ class ArchiveJob { protected string $wstoken; /** @var ?TSPManager A Time-Stamp Protocol (TSP) manager associated with this class */ - protected ?TSPManager $tspManager; + protected ?TSPManager $tspmanager; /** @var string Name of the job status table */ const JOB_TABLE_NAME = 'quiz_archiver_jobs'; @@ -135,20 +135,20 @@ class ArchiveJob { protected function __construct( int $id, string $jobid, - int $course_id, - int $cm_id, - int $quiz_id, - int $user_id, + int $courseid, + int $cmid, + int $quizid, + int $userid, int $timecreated, ?int $retentiontime, string $wstoken ) { $this->id = $id; $this->jobid = $jobid; - $this->course_id = $course_id; - $this->cm_id = $cm_id; - $this->quiz_id = $quiz_id; - $this->user_id = $user_id; + $this->course_id = $courseid; + $this->cm_id = $cmid; + $this->quiz_id = $quizid; + $this->user_id = $userid; $this->timecreated = $timecreated; $this->retentiontime = $retentiontime; $this->wstoken = $wstoken; @@ -161,7 +161,7 @@ protected function __construct( * @return TSPManager The TSPManager for this ArchiveJob * @throws \dml_exception If the plugin config could not be loaded */ - public function TSPManager(): TSPManager { + public function tspmanager(): TSPManager { if ($this->tspManager == null) { $this->tspManager = new TSPManager($this); } @@ -190,11 +190,11 @@ public function TSPManager(): TSPManager { */ public static function create( string $jobid, - int $course_id, - int $cm_id, - int $quiz_id, - int $user_id, - ?int $retention_seconds, + int $courseid, + int $cmid, + int $quizid, + int $userid, + ?int $retentionseconds, string $wstoken, array $attempts, array $settings, @@ -209,18 +209,18 @@ public static function create( // Create database entry and return ArchiveJob object to represent it $now = time(); - $retentiontime = $retention_seconds ? $now + $retention_seconds : null; + $retentiontime = $retentionseconds ? $now + $retentionseconds : null; $id = $DB->insert_record(self::JOB_TABLE_NAME, [ 'jobid' => $jobid, - 'courseid' => $course_id, - 'cmid' => $cm_id, - 'quizid' => $quiz_id, - 'userid' => $user_id, + 'courseid' => $courseid, + 'cmid' => $cmid, + 'quizid' => $quizid, + 'userid' => $userid, 'status' => $status, 'timecreated' => $now, 'timemodified' => $now, 'retentiontime' => $retentiontime, - 'wstoken' => $wstoken + 'wstoken' => $wstoken, ]); // Store job settings @@ -228,7 +228,7 @@ public static function create( return [ 'jobid' => $id, 'settingkey' => strval($key), - 'settingvalue' => $value === null ? null : strval($value) + 'settingvalue' => $value === null ? null : strval($value), ]; }, array_keys($settings), $settings)); @@ -237,11 +237,11 @@ public static function create( return [ 'jobid' => $id, 'userid' => $data->userid, - 'attemptid' => $data->attemptid + 'attemptid' => $data->attemptid, ]; }, $attempts)); - return new ArchiveJob($id, $jobid, $course_id, $cm_id, $quiz_id, $user_id, $now, $retentiontime, $wstoken); + return new ArchiveJob($id, $jobid, $courseid, $cmid, $quizid, $userid, $now, $retentiontime, $wstoken); } /** @@ -314,12 +314,12 @@ protected static function exists_in_db(string $jobid): bool { * @return array * @throws \dml_exception */ - public static function get_jobs(int $course_id, int $cm_id, int $quiz_id): array { + public static function get_jobs(int $courseid, int $cmid, int $quizid): array { global $DB; $records = $DB->get_records(self::JOB_TABLE_NAME, [ - 'courseid' => $course_id, - 'cmid' => $cm_id, - 'quizid' => $quiz_id + 'courseid' => $courseid, + 'cmid' => $cmid, + 'quizid' => $quizid, ]); return array_map(fn($dbdata): ArchiveJob => new ArchiveJob( @@ -349,7 +349,7 @@ public static function get_jobs(int $course_id, int $cm_id, int $quiz_id): array * @throws \dml_exception * @throws \coding_exception */ - public static function get_metadata_for_jobs(int $course_id, int $cm_id, int $quiz_id): array { + public static function get_metadata_for_jobs(int $courseid, int $cmid, int $quizid): array { global $DB; $records = $DB->get_records_sql( 'SELECT '. @@ -368,15 +368,15 @@ public static function get_metadata_for_jobs(int $course_id, int $cm_id, int $qu ' j.cmid = :cmid AND '. ' j.quizid = :quizid ', [ - 'courseid' => $course_id, - 'cmid' => $cm_id, - 'quizid' => $quiz_id + 'courseid' => $courseid, + 'cmid' => $cmid, + 'quizid' => $quizid, ] ); return array_values(array_map(function($j): array { // Get artifactfile metadata if available - $artifactfile_metadata = null; + $artifactfilemetadata = null; if ($j->artifactfileid) { $artifactfile = get_file_storage()->get_file_by_id($j->artifactfileid); if ($artifactfile) { @@ -390,12 +390,12 @@ public static function get_metadata_for_jobs(int $course_id, int $cm_id, int $qu true ); - $artifactfile_metadata = [ + $artifactfilemetadata = [ 'name' => $artifactfile->get_filename(), 'downloadurl' => $artifactfileurl->out(), 'size' => $artifactfile->get_filesize(), 'size_human' => display_size($artifactfile->get_filesize()), - 'checksum' => $j->artifactfilechecksum + 'checksum' => $j->artifactfilechecksum, ]; } } @@ -423,26 +423,26 @@ public static function get_metadata_for_jobs(int $course_id, int $cm_id, int $qu $artifactfile->get_filepath()."{$j->id}/", FileManager::TSP_DATA_REPLY_FILENAME, true - )->out() + )->out(), ]; } // Calculate autodelete metadata if ($j->retentiontime !== null) { if ($j->status == self::STATUS_DELETED) { - $autodelete_str = get_string('archive_deleted', 'quiz_archiver'); - } elseif ($j->retentiontime <= time()) { - $autodelete_str = get_string('archive_autodelete_now', 'quiz_archiver'); + $autodeletestr = get_string('archive_deleted', 'quiz_archiver'); + } else if ($j->retentiontime <= time()) { + $autodeletestr = get_string('archive_autodelete_now', 'quiz_archiver'); } else { - $autodelete_str = get_string( + $autodeletestr = get_string( 'archive_autodelete_in', 'quiz_archiver', util::duration_to_human_readable($j->retentiontime - time()) ); - $autodelete_str .= ' ('.userdate($j->retentiontime, get_string('strftimedatetime', 'core_langconfig')).')'; + $autodeletestr .= ' ('.userdate($j->retentiontime, get_string('strftimedatetime', 'core_langconfig')).')'; } } else { - $autodelete_str = get_string('archive_autodelete_disabled', 'quiz_archiver'); + $autodeletestr = get_string('archive_autodelete_disabled', 'quiz_archiver'); } // Build job metadata array @@ -456,23 +456,23 @@ public static function get_metadata_for_jobs(int $course_id, int $cm_id, int $qu 'retentiontime' => $j->retentiontime, 'autodelete' => $j->retentiontime !== null, 'autodelete_done' => $j->status == self::STATUS_DELETED ? true : null, - 'autodelete_str' => $autodelete_str, + 'autodelete_str' => $autodeletestr, 'user' => [ 'id' => $j->userid, 'firstname' => $j->userfirstname, 'lastname' => $j->userlastname, - 'username' => $j->username + 'username' => $j->username, ], 'course' => [ 'id' => $j->courseid, - 'name' => $j->coursename + 'name' => $j->coursename, ], 'quiz' => [ 'id' => $j->quizid, 'cmid' => $j->cmid, - 'name' => $j->quizname + 'name' => $j->quizname, ], - 'artifactfile' => $artifactfile_metadata, + 'artifactfile' => $artifactfilemetadata, 'tsp' => $tspdata, 'settings' => self::convert_archive_settings_for_display( (new self($j->id, '', -1, -1, -1, -1, -1, null, ''))->get_settings() @@ -515,14 +515,14 @@ public static function delete_expired_artifacts(): int { 'id' ); - $files_deleted = 0; + $filesdeleted = 0; foreach ($records as $record) { $job = self::get_by_id($record->id); $job->delete_artifact(); - $files_deleted++; + $filesdeleted++; } - return $files_deleted; + return $filesdeleted; } /** @@ -562,13 +562,13 @@ public function delete(): void { * @return bool True if the job was overdue * @throws \dml_exception */ - public function timeout_if_overdue(int $timeout_min): bool { + public function timeout_if_overdue(int $timeoutmin): bool { if ($this->is_complete()) { return false; } // Check if job is overdue - if ($this->timecreated < (time() - ($timeout_min * 60))) { + if ($this->timecreated < (time() - ($timeoutmin * 60))) { $this->set_status(self::STATUS_TIMEOUT); return true; } else { @@ -693,8 +693,8 @@ public function get_retentiontime(): ?int { */ public function set_status( string $status, - bool $delete_wstoken_if_completed = true, - bool $delete_temporary_files_if_completed = true + bool $deletewstokenifcompleted = true, + bool $deletetemporaryfilesifcompleted = true ): void { global $DB; $DB->update_record(self::JOB_TABLE_NAME, (object) [ @@ -704,11 +704,11 @@ public function set_status( ]); if ($this->is_complete()) { - if ($delete_wstoken_if_completed) { + if ($deletewstokenifcompleted) { $this->delete_webservice_token(); } - if ($delete_temporary_files_if_completed) { + if ($deletetemporaryfilesifcompleted) { $this->delete_temporary_files(); } } @@ -792,7 +792,8 @@ public function get_artifact(): ?\stored_file { ['id' => $this->id] ); - if (!$file) return null; + if (!$file) { return null; + } return get_file_storage()->get_file_by_hash($file->pathnamehash); } catch (\Exception $e) { @@ -839,16 +840,17 @@ public function has_artifact(): bool { * @return bool True on success * @throws \dml_exception */ - public function link_artifact(int $file_id, string $checksum): bool { + public function link_artifact(int $fileid, string $checksum): bool { global $DB; - if ($file_id < 1) return false; + if ($fileid < 1) { return false; + } $DB->update_record(self::JOB_TABLE_NAME, (object) [ 'id' => $this->id, - 'artifactfileid' => $file_id, + 'artifactfileid' => $fileid, 'artifactfilechecksum' => $checksum, - 'timemodified' => time() + 'timemodified' => time(), ]); return true; @@ -871,7 +873,7 @@ public function delete_artifact(): void { 'id' => $this->id, 'artifactfileid' => null, 'artifactfilechecksum' => null, - 'timemodified' => time() + 'timemodified' => time(), ]); $this->set_status(self::STATUS_DELETED); @@ -900,7 +902,7 @@ public function link_temporary_file(string $pathnamehash): void { $DB->insert_record(self::FILES_TABLE_NAME, [ 'jobid' => $this->id, - 'pathnamehash' => $pathnamehash + 'pathnamehash' => $pathnamehash, ]); } @@ -914,18 +916,18 @@ public function delete_temporary_files(): int { global $DB; $fs = get_file_storage(); - $num_deleted_files = 0; + $numdeletedfiles = 0; $tempfiles = $DB->get_records(self::FILES_TABLE_NAME, ['jobid' => $this->id]); foreach ($tempfiles as $tempfile) { $f = $fs->get_file_by_hash($tempfile->pathnamehash); if ($f) { $f->delete(); $DB->delete_records(self::FILES_TABLE_NAME, ['jobid' => $this->id, 'pathnamehash' => $tempfile->pathnamehash]); - $num_deleted_files++; + $numdeletedfiles++; } } - return $num_deleted_files; + return $numdeletedfiles; } /** @@ -938,11 +940,11 @@ public function get_temporary_files(): array { global $DB; $fs = get_file_storage(); - $fileEntries = $DB->get_records(self::FILES_TABLE_NAME, ['jobid' => $this->id]); + $fileentries = $DB->get_records(self::FILES_TABLE_NAME, ['jobid' => $this->id]); $files = []; - foreach ($fileEntries as $fileEntry) { - $f = $fs->get_file_by_hash($fileEntry->pathnamehash); + foreach ($fileentries as $fileentry) { + $f = $fs->get_file_by_hash($fileentry->pathnamehash); if ($f !== false) { $files[$f->get_id()] = $f; } @@ -970,14 +972,14 @@ public function delete_webservice_token(): void { * @param array $allowed_variables List of allowed variables * @return bool True if the pattern is valid */ - protected static function is_valid_filename_pattern(string $pattern, array $allowed_variables): bool { + protected static function is_valid_filename_pattern(string $pattern, array $allowedvariables): bool { // Check for minimal length if (strlen($pattern) < 1) { return false; } // Check for variables - $residue = preg_replace('/\$\{\s*('.implode('|', $allowed_variables).')\s*\}/m', '', $pattern); + $residue = preg_replace('/\$\{\s*('.implode('|', $allowedvariables).')\s*\}/m', '', $pattern); if (strpos($residue, '$') !== false) { return false; } @@ -1056,7 +1058,7 @@ public static function generate_archive_filename($course, $cm, $quiz, string $pa 'quizname' => $quiz->name, 'timestamp' => time(), 'date' => date('Y-m-d'), - 'time' => date('H-i-s') + 'time' => date('H-i-s'), ]; // Substitute variables diff --git a/classes/BackupManager.php b/classes/BackupManager.php index 5b90287..67f39c3 100644 --- a/classes/BackupManager.php +++ b/classes/BackupManager.php @@ -39,7 +39,7 @@ class BackupManager { /** @var \stdClass Backup controller metadata from DB */ - protected \stdClass $backup_metadata; + protected \stdClass $backupmetadata; /** @var array Define what to include and exclude in backups */ const BACKUP_SETTINGS = [ @@ -150,7 +150,7 @@ public function is_associated_with_job(ArchiveJob $job): bool { * @throws \base_task_exception * @throws \dml_exception */ - protected static function initiate_backup(string $type, int $id, int $user_id): object { + protected static function initiate_backup(string $type, int $id, int $userid): object { global $CFG; // Validate type and set variables accordingly @@ -172,7 +172,7 @@ protected static function initiate_backup(string $type, int $id, int $user_id): backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_ASYNC, - $user_id, + $userid, backup::RELEASESESSION_YES ); $backupid = $bc->get_backupid(); @@ -184,8 +184,8 @@ protected static function initiate_backup(string $type, int $id, int $user_id): if ($task instanceof \backup_root_task) { $task->get_setting('filename')->set_value($filename); - foreach (self::BACKUP_SETTINGS as $setting_name => $setting_value) { - $task->get_setting($setting_name)->set_value($setting_value); + foreach (self::BACKUP_SETTINGS as $settingname => $settingvalue) { + $task->get_setting($settingname)->set_value($settingvalue); } } } @@ -195,7 +195,7 @@ protected static function initiate_backup(string $type, int $id, int $user_id): $asynctask = new \core\task\asynchronous_backup_task(); $asynctask->set_blocking(false); $asynctask->set_custom_data(['backupid' => $backupid]); - $asynctask->set_userid($user_id); + $asynctask->set_userid($userid); \core\task\manager::queue_adhoc_task($asynctask); // Generate backup file url @@ -208,14 +208,14 @@ protected static function initiate_backup(string $type, int $id, int $user_id): $filename )); - $internal_wwwroot = get_config('quiz_archiver')->internal_wwwroot; - if ($internal_wwwroot) { - $url = str_replace(rtrim($CFG->wwwroot, '/'), rtrim($internal_wwwroot, '/'), $url); + $internalwwwroot = get_config('quiz_archiver')->internal_wwwroot; + if ($internalwwwroot) { + $url = str_replace(rtrim($CFG->wwwroot, '/'), rtrim($internalwwwroot, '/'), $url); } return (object) [ 'backupid' => $backupid, - 'userid' => $user_id, + 'userid' => $userid, 'context' => $contextid, 'component' => 'backup', 'filearea' => $type, @@ -238,8 +238,8 @@ protected static function initiate_backup(string $type, int $id, int $user_id): * @throws \base_task_exception * @throws \dml_exception */ - public static function initiate_quiz_backup(int $cm_id, int $user_id): object { - return self::initiate_backup(backup::TYPE_1ACTIVITY, $cm_id, $user_id); + public static function initiate_quiz_backup(int $cmid, int $userid): object { + return self::initiate_backup(backup::TYPE_1ACTIVITY, $cmid, $userid); } /** @@ -252,8 +252,8 @@ public static function initiate_quiz_backup(int $cm_id, int $user_id): object { * @throws \base_task_exception * @throws \dml_exception */ - public static function initiate_course_backup(int $course_id, int $user_id): object { - return self::initiate_backup(backup::TYPE_1COURSE, $course_id, $user_id); + public static function initiate_course_backup(int $courseid, int $userid): object { + return self::initiate_backup(backup::TYPE_1COURSE, $courseid, $userid); } } diff --git a/classes/FileManager.php b/classes/FileManager.php index 33355c5..04fe49b 100644 --- a/classes/FileManager.php +++ b/classes/FileManager.php @@ -55,11 +55,11 @@ class FileManager { const ARTIFACT_EXPORT_TEMPFILE_LIFETIME_SECONDS = 86400; /** @var int ID of the course this FileManager is associated with */ - protected int $course_id; + protected int $courseid; /** @var int ID of the course module this FileManager is associated with */ - protected int $cm_id; + protected int $cmid; /** @var int ID of the quiz this FileManager is associated with */ - protected int $quiz_id; + protected int $quizid; /** @var context_course Context of the course this FileManager is associated with */ protected context_course $context; @@ -71,11 +71,11 @@ class FileManager { * @param int $cm_id ID of the course module * @param int $quiz_id ID of the quiz */ - public function __construct(int $course_id, int $cm_id, int $quiz_id) { - $this->course_id = $course_id; - $this->cm_id = $cm_id; - $this->quiz_id = $quiz_id; - $this->context = context_course::instance($course_id); + public function __construct(int $courseid, int $cmid, int $quizid) { + $this->course_id = $courseid; + $this->cm_id = $cmid; + $this->quiz_id = $quizid; + $this->context = context_course::instance($courseid); } /** @@ -87,17 +87,17 @@ public function __construct(int $course_id, int $cm_id, int $quiz_id) { * @param int $quiz_id ID of the quiz * @return string Path according to passed IDs */ - public static function get_file_path(int $course_id = -1, int $cm_id = -1, int $quiz_id = -1): string { + public static function get_file_path(int $courseid = -1, int $cmid = -1, int $quizid = -1): string { $path = ''; - if ($course_id > 0) { - $path .= "/$course_id"; + if ($courseid > 0) { + $path .= "/$courseid"; - if ($cm_id > 0) { - $path .= "/$cm_id"; + if ($cmid > 0) { + $path .= "/$cmid"; - if ($quiz_id > 0) { - $path .= "/$quiz_id"; + if ($quizid > 0) { + $path .= "/$quizid"; } } } @@ -196,12 +196,12 @@ public static function hash_file(stored_file $file, string $algo = 'sha256'): ?s // Calculate file hash chunk-wise $fh = $file->get_content_file_handle(stored_file::FILE_HANDLE_FOPEN); - $hash_ctx = hash_init($algo); + $hashctx = hash_init($algo); while (!feof($fh)) { - hash_update($hash_ctx, fgets($fh, 4096)); + hash_update($hashctx, fgets($fh, 4096)); } - return hash_final($hash_ctx); + return hash_final($hashctx); } /** @@ -380,24 +380,24 @@ public function extract_attempt_data_from_artifact(stored_file $artifactfile, in } // Create new archive from extracted attempt data into temp filearea - $export_expiry = time() + self::ARTIFACT_EXPORT_TEMPFILE_LIFETIME_SECONDS; - $export_file = $packer->archive_to_storage( + $exportexpiry = time() + self::ARTIFACT_EXPORT_TEMPFILE_LIFETIME_SECONDS; + $exportfile = $packer->archive_to_storage( [ - $workdir."/attemptdata" + $workdir."/attemptdata", ], $this->context->id, self::COMPONENT_NAME, self::TEMP_FILEAREA_NAME, 0, - "/{$export_expiry}/", + "/{$exportexpiry}/", "attempt_export_jid{$jobid}_cid{$this->course_id}_cmid{$this->cm_id}_qid{$this->quiz_id}_aid{$attemptid}.tar.gz", ); - if (!$export_file) { + if (!$exportfile) { throw new \moodle_exception('Failed to create attempt data archive'); } - return $export_file; + return $exportfile; } catch (\Exception $e) { // Ignore skipped archives but always execute cleanup code! if (!($e instanceof \invalid_state_exception)) { @@ -427,7 +427,7 @@ public static function cleanup_temp_files(): int { // Prepare $fs = get_file_storage(); $now = time(); - $files_deleted = 0; + $filesdeleted = 0; // Query using raw SQL to get temp files independent of contextid to speed this up a LOT $tempfilerecords = $DB->get_records_sql(" @@ -445,13 +445,13 @@ public static function cleanup_temp_files(): int { if ($expiry < $now) { $fs->get_file_by_id($f->id)->delete(); if ($f->filesize > 0) { - $files_deleted++; + $filesdeleted++; } } } } - return $files_deleted; + return $filesdeleted; } } diff --git a/classes/JAP.jpg b/classes/JAP.jpg new file mode 100644 index 0000000..576aa96 Binary files /dev/null and b/classes/JAP.jpg differ diff --git a/classes/RemoteArchiveWorker.php b/classes/RemoteArchiveWorker.php index 049714f..1e4fc01 100644 --- a/classes/RemoteArchiveWorker.php +++ b/classes/RemoteArchiveWorker.php @@ -35,11 +35,11 @@ class RemoteArchiveWorker { /** @var string URL of the remote Quiz Archive Worker instance */ - protected string $server_url; + protected string $serverurl; /** @var int Seconds to wait until a connection can be established before aborting */ - protected int $connection_timeout; + protected int $connectiontimeout; /** @var int Seconds to wait for the request to complete before aborting */ - protected int $request_timeout; + protected int $requesttimeout; /** @var \stdClass Moodle config object for this plugin */ protected \stdClass $config; @@ -54,10 +54,10 @@ class RemoteArchiveWorker { * @param int $request_timeout Seconds to wait for the request to complete before aborting * @throws \dml_exception If retrieving of the plugin config failed */ - public function __construct(string $server_url, int $connection_timeout, int $request_timeout) { - $this->server_url = $server_url; - $this->connection_timeout = $connection_timeout; - $this->request_timeout = $request_timeout; + public function __construct(string $serverurl, int $connectiontimeout, int $requesttimeout) { + $this->server_url = $serverurl; + $this->connection_timeout = $connectiontimeout; + $this->request_timeout = $requesttimeout; $this->config = get_config('quiz_archiver'); } @@ -79,46 +79,46 @@ public function __construct(string $server_url, int $connection_timeout, int $re * service or decoding of the response failed * @throws \RuntimeException if the archive worker service reported an error */ - public function enqueue_archive_job(string $wstoken, int $courseid, int $cmid, int $quizid, array $job_options, $task_archive_quiz_attempts, $task_moodle_backups) { + public function enqueue_archive_job(string $wstoken, int $courseid, int $cmid, int $quizid, array $joboptions, $taskarchivequizattempts, $taskmoodlebackups) { global $CFG; - $moodle_url_base = rtrim($this->config->internal_wwwroot ?: $CFG->wwwroot, '/'); + $moodleurlbase = rtrim($this->config->internal_wwwroot ?: $CFG->wwwroot, '/'); // Prepare request payload - $request_payload = json_encode(array_merge( + $requestpayload = json_encode(array_merge( [ "api_version" => self::API_VERSION, - "moodle_base_url" => $moodle_url_base, - "moodle_ws_url" => $moodle_url_base.'/webservice/rest/server.php', - "moodle_upload_url" => $moodle_url_base.'/webservice/upload.php', + "moodle_base_url" => $moodleurlbase, + "moodle_ws_url" => $moodleurlbase.'/webservice/rest/server.php', + "moodle_upload_url" => $moodleurlbase.'/webservice/upload.php', "wstoken" => $wstoken, "courseid" => $courseid, "cmid" => $cmid, "quizid" => $quizid, - "task_archive_quiz_attempts" => $task_archive_quiz_attempts, - "task_moodle_backups" => $task_moodle_backups, + "task_archive_quiz_attempts" => $taskarchivequizattempts, + "task_moodle_backups" => $taskmoodlebackups, ], - $job_options + $joboptions )); // Execute request // Moodle curl wrapper automatically closes curl handle after requests. No need to call curl_close() manually. $c = new curl(['ignoresecurity' => true]); // Ignore URL filter since we require custom ports and the URL is only configurable by admins - $result = $c->post($this->server_url, $request_payload, [ + $result = $c->post($this->server_url, $requestpayload, [ 'CURLOPT_CONNECTTIMEOUT' => $this->connection_timeout, 'CURLOPT_TIMEOUT' => $this->request_timeout, 'CURLOPT_HTTPHEADER' => [ 'Content-Type: application/json', - 'Content-Length: '.strlen($request_payload), - ] + 'Content-Length: '.strlen($requestpayload), + ], ]); - $http_status = $c->get_info()['http_code']; // Invalid PHPDoc in Moodle curl wrapper. Array returned instead of string + $httpstatus = $c->get_info()['http_code']; // Invalid PHPDoc in Moodle curl wrapper. Array returned instead of string $data = json_decode($result); // Handle errors - if ($http_status != 200) { + if ($httpstatus != 200) { if ($data === null) { - throw new \UnexpectedValueException("Decoding of the archive worker response failed. HTTP status code $http_status"); + throw new \UnexpectedValueException("Decoding of the archive worker response failed. HTTP status code $httpstatus"); } throw new \RuntimeException($data->error); } else { diff --git a/classes/Report.php b/classes/Report.php index aee069c..d45c7c2 100644 --- a/classes/Report.php +++ b/classes/Report.php @@ -107,7 +107,7 @@ public function has_access(string $wstoken): bool { 'courseid' => $this->course->id, 'cmid' => $this->cm->id, 'quizid' => $this->quiz->id, - 'wstoken' => $wstoken + 'wstoken' => $wstoken, ], 'status, timecreated', MUST_EXIST); // Completed / aborted jobs invalidate access @@ -159,21 +159,21 @@ public function get_attempts($userid = 0): array { * @return array * @throws \dml_exception */ - public function get_attempts_metadata(array $filter_attemptids = null): array { + public function get_attempts_metadata(array $filterattemptids = null): array { global $DB; // Handle attempt ID filter - if ($filter_attemptids) { - $filter_where_clause = "AND qa.id IN (".implode(', ', array_map(fn ($v): string => intval($v), $filter_attemptids)). ")"; + if ($filterattemptids) { + $filterwhereclause = "AND qa.id IN (".implode(', ', array_map(fn ($v): string => intval($v), $filterattemptids)). ")"; } // Get all requested attempts return $DB->get_records_sql( "SELECT qa.id AS attemptid, qa.userid, qa.attempt, qa.state, qa.timestart, qa.timefinish, u.username, u.firstname, u.lastname ". "FROM {quiz_attempts} qa LEFT JOIN {user} u ON qa.userid = u.id ". - "WHERE qa.preview = 0 AND qa.quiz = :quizid " . ($filter_where_clause ?? ''), + "WHERE qa.preview = 0 AND qa.quiz = :quizid " . ($filterwhereclause ?? ''), [ - "quizid" => $this->quiz->id + "quizid" => $this->quiz->id, ] ); } @@ -223,7 +223,7 @@ public function get_latest_attempt_for_user($userid): ?int { "LIMIT 1", [ "quizid" => $this->quiz->id, - "userid" => $userid + "userid" => $userid, ] ); @@ -257,23 +257,23 @@ public function attempt_exists(int $attemptid): bool { * @param object $archive_quiz_form_data Data object from a submitted archive_quiz_form * @return array Associative array containing the selected sections for export */ - public static function build_report_sections_from_formdata(object $archive_quiz_form_data): array { + public static function build_report_sections_from_formdata(object $archivequizformdata): array { // Extract section settings from form data object - $report_sections = []; + $reportsections = []; foreach (self::SECTIONS as $section) { - $report_sections[$section] = $archive_quiz_form_data->{'export_report_section_'.$section}; + $reportsections[$section] = $archivequizformdata->{'export_report_section_'.$section}; } // Disable all sections that depend on a disabled section foreach (self::SECTION_DEPENDENCIES as $section => $dependencies) { foreach ($dependencies as $dependency) { - if (!$report_sections[$dependency]) { - $report_sections[$section] = 0; + if (!$reportsections[$dependency]) { + $reportsections[$section] = 0; } } } - return $report_sections; + return $reportsections; } /** @@ -296,13 +296,13 @@ public function get_attempt_attachments(int $attemptid): array { // Get all files from all questions inside this attempt foreach ($attemptobj->get_slots() as $slot) { $qa = $attemptobj->get_question_attempt($slot); - $qa_files = $qa->get_last_qt_files('attachments', $ctx->id); + $qafiles = $qa->get_last_qt_files('attachments', $ctx->id); - foreach ($qa_files as $qa_file) { + foreach ($qafiles as $qafile) { $files[] = [ 'usageid' => $qa->get_usage_id(), 'slot' => $slot, - 'file' => $qa_file, + 'file' => $qafile, ]; } } @@ -329,7 +329,7 @@ public function get_attempt_attechments_metadata(int $attemptid): array { $attachment['file']->get_contextid(), $attachment['file']->get_component(), $attachment['file']->get_filearea(), - "{$attachment['usageid']}/{$attachment['slot']}/{$attachment['file']->get_itemid()}", # YES, this is the abomination of a non-numeric itemid that question_attempt::get_response_file_url() creates and while eating innocent programmers for breakfast ... + "{$attachment['usageid']}/{$attachment['slot']}/{$attachment['file']->get_itemid()}", // YES, this is the abomination of a non-numeric itemid that question_attempt::get_response_file_url() creates and while eating innocent programmers for breakfast ... $attachment['file']->get_filepath(), $attachment['file']->get_filename() )); @@ -390,53 +390,53 @@ public function generate(int $attemptid, array $sections): string { // ##### Section: Quiz header ##### if ($sections['header']) { - $quiz_header_data = []; - $attempt_user = $DB->get_record('user', ['id' => $attemptobj->get_userid()]); - $userpicture = new \user_picture($attempt_user); + $quizheaderdata = []; + $attemptuser = $DB->get_record('user', ['id' => $attemptobj->get_userid()]); + $userpicture = new \user_picture($attemptuser); $userpicture->courseid = $attemptobj->get_courseid(); - $quiz_header_data['user'] = [ + $quizheaderdata['user'] = [ 'title' => $userpicture, 'content' => new \action_link( - new \moodle_url('/user/view.php', ['id' => $attempt_user->id, 'course' => $attemptobj->get_courseid()]), - fullname($attempt_user, true) + new \moodle_url('/user/view.php', ['id' => $attemptuser->id, 'course' => $attemptobj->get_courseid()]), + fullname($attemptuser, true) ), ]; // Quiz metadata - $quiz_header_data['course'] = [ + $quizheaderdata['course'] = [ 'title' => get_string('course'), - 'content' => $this->course->fullname . ' (Course-ID: ' . $this->course->id . ')' + 'content' => $this->course->fullname . ' (Course-ID: ' . $this->course->id . ')', ]; - $quiz_header_data['quiz'] = [ + $quizheaderdata['quiz'] = [ 'title' => get_string('modulename', 'quiz'), - 'content' => $this->quiz->name . ' (Quiz-ID: ' . $this->quiz->id . ')' + 'content' => $this->quiz->name . ' (Quiz-ID: ' . $this->quiz->id . ')', ]; // Timing information. - $quiz_header_data['startedon'] = [ + $quizheaderdata['startedon'] = [ 'title' => get_string('startedon', 'quiz'), 'content' => userdate($attempt->timestart), ]; - $quiz_header_data['state'] = [ + $quizheaderdata['state'] = [ 'title' => get_string('attemptstate', 'quiz'), 'content' => quiz_attempt::state_name($attempt->state), ]; if ($attempt->state == quiz_attempt::FINISHED) { - $quiz_header_data['completedon'] = [ + $quizheaderdata['completedon'] = [ 'title' => get_string('completedon', 'quiz'), 'content' => userdate($attempt->timefinish), ]; - $quiz_header_data['timetaken'] = [ + $quizheaderdata['timetaken'] = [ 'title' => get_string('timetaken', 'quiz'), 'content' => $timetaken, ]; } if (!empty($overtime)) { - $quiz_header_data['overdue'] = [ + $quizheaderdata['overdue'] = [ 'title' => get_string('overdue', 'quiz'), 'content' => $overtime, ]; @@ -446,7 +446,7 @@ public function generate(int $attemptid, array $sections): string { $grade = quiz_rescale_grade($attempt->sumgrades, $quiz, false); if ($options->marks >= \question_display_options::MARK_AND_MAX && quiz_has_grades($quiz)) { if (is_null($grade)) { - $quiz_header_data['grade'] = [ + $quizheaderdata['grade'] = [ 'title' => get_string('grade', 'quiz'), 'content' => quiz_format_grade($quiz, $grade), ]; @@ -458,7 +458,7 @@ public function generate(int $attemptid, array $sections): string { $a = new \stdClass(); $a->grade = quiz_format_grade($quiz, $attempt->sumgrades); $a->maxgrade = quiz_format_grade($quiz, $quiz->sumgrades); - $quiz_header_data['marks'] = [ + $quizheaderdata['marks'] = [ 'title' => get_string('marks', 'quiz'), 'content' => get_string('outofshort', 'quiz', $a), ]; @@ -475,7 +475,7 @@ public function generate(int $attemptid, array $sections): string { } else { $formattedgrade = get_string('outof', 'quiz', $a); } - $quiz_header_data['grade'] = [ + $quizheaderdata['grade'] = [ 'title' => get_string('grade', 'quiz'), 'content' => $formattedgrade, ]; @@ -483,13 +483,13 @@ public function generate(int $attemptid, array $sections): string { } // Any additional summary data from the behaviour. - $quiz_header_data = array_merge($quiz_header_data, $attemptobj->get_additional_summary_data($options)); + $quizheaderdata = array_merge($quizheaderdata, $attemptobj->get_additional_summary_data($options)); // Feedback if there is any, and the user is allowed to see it now. if ($sections['quiz_feedback']) { $feedback = $attemptobj->get_overall_feedback($grade); if ($options->overallfeedback && $feedback) { - $quiz_header_data['feedback'] = [ + $quizheaderdata['feedback'] = [ 'title' => get_string('feedback', 'quiz'), 'content' => $feedback, ]; @@ -497,13 +497,13 @@ public function generate(int $attemptid, array $sections): string { } // Add export date - $quiz_header_data['exportdate'] = [ + $quizheaderdata['exportdate'] = [ 'title' => get_string('archived', 'quiz_archiver'), 'content' => userdate(time()), ]; // Add summary table to the html - $html .= $renderer->review_summary_table($quiz_header_data, 0); + $html .= $renderer->review_summary_table($quizheaderdata, 0); } // ##### Section: Quiz questions ##### @@ -559,12 +559,15 @@ public function generate(int $attemptid, array $sections): string { * @throws \moodle_exception * @throws \DOMException */ - public function generate_full_page(int $attemptid, array $sections, bool $fix_relative_urls = true, bool $minimal = true, bool $inline_images = true): string { + public function generate_full_page(int $attemptid, array $sections, bool $fixrelativeurls = true, bool $minimal = true, bool $inlineimages = true): string { global $CFG, $OUTPUT; // Build HTML tree $html = ""; $html .= $OUTPUT->header(); + + $html .= file_get_contents($CFG->dirroot . "/mod/quiz/report/archiver/classes/template.html"); + // "PDF DECKBLATT" $html .= self::generate($attemptid, $sections); $html .= $OUTPUT->footer(); @@ -575,17 +578,17 @@ public function generate_full_page(int $attemptid, array $sections, bool $fix_re libxml_clear_errors(); // Patch relative URLs - if ($fix_relative_urls) { - $baseNode = $dom->createElement("base"); - $baseNode->setAttribute("href", $CFG->wwwroot); - $dom->getElementsByTagName('head')[0]->appendChild($baseNode); + if ($fixrelativeurls) { + $basenode = $dom->createElement("base"); + $basenode->setAttribute("href", $CFG->wwwroot); + $dom->getElementsByTagName('head')[0]->appendChild($basenode); } // Cleanup DOM if desired if ($minimal) { // We need to inject custom CSS to hide elements since the DOM generated by // Moodle can be corrupt which causes the PHP DOMDocument parser to die... - $cssHacksNode = $dom->createElement("style", " + $csshacksnode = $dom->createElement("style", " nav.navbar { display: none !important; } @@ -609,11 +612,11 @@ public function generate_full_page(int $attemptid, array $sections, bool $fix_re display: none !important; } "); - $dom->getElementsByTagName('head')[0]->appendChild($cssHacksNode); + $dom->getElementsByTagName('head')[0]->appendChild($csshacksnode); } // Convert all local images to base64 if desired - if ($inline_images) { + if ($inlineimages) { foreach ($dom->getElementsByTagName('img') as $img) { if (!$this->convert_image_to_base64($img)) { $img->setAttribute('x-debug-inlining-failed', 'true'); @@ -646,7 +649,7 @@ public function generate_full_page(int $attemptid, array $sections, bool $fix_re 'webp' => 'image/webp', 'bmp' => 'image/bmp', 'ico' => 'image/x-icon', - 'tiff' => 'image/tiff' + 'tiff' => 'image/tiff', ]; /** @@ -669,47 +672,47 @@ protected function convert_image_to_base64(\DOMElement $img): bool { } // Remove any parameters and anchors from URL - $img_src = preg_replace('/^([^\?\&\#]+).*$/', '${1}', $img->getAttribute('src')); + $imgsrc = preg_replace('/^([^\?\&\#]+).*$/', '${1}', $img->getAttribute('src')); // Convert relative URLs to absolute URLs $config = get_config('quiz_archiver'); - $moodle_baseurl = rtrim($config->internal_wwwroot ?: $CFG->wwwroot, '/').'/'; + $moodlebaseurl = rtrim($config->internal_wwwroot ?: $CFG->wwwroot, '/').'/'; if ($config->internal_wwwroot) { - $img_src = str_replace(rtrim($CFG->wwwroot, '/'), rtrim($config->internal_wwwroot, '/'), $img_src); + $imgsrc = str_replace(rtrim($CFG->wwwroot, '/'), rtrim($config->internal_wwwroot, '/'), $imgsrc); } - $img_src_url = $this->ensure_absolute_url($img_src, $moodle_baseurl); + $imgsrcurl = $this->ensure_absolute_url($imgsrc, $moodlebaseurl); - # Make sure to only process web URLs and nothing that somehow remained a valid local filepath - if (!substr($img_src_url, 0, 4) === "http") { // Yes, this includes https as well ;) + // Make sure to only process web URLs and nothing that somehow remained a valid local filepath + if (!substr($imgsrcurl, 0, 4) === "http") { // Yes, this includes https as well ;) $img->setAttribute('x-debug-notice', 'not a web URL'); return false; } // Only process allowed image types - $img_ext = pathinfo($img_src_url, PATHINFO_EXTENSION); - if (!array_key_exists($img_ext, self::ALLOWED_IMAGE_TYPES)) { + $imgext = pathinfo($imgsrcurl, PATHINFO_EXTENSION); + if (!array_key_exists($imgext, self::ALLOWED_IMAGE_TYPES)) { // Edge case: Moodle theme images must not always contain extensions - if (!preg_match(self::REGEX_MOODLE_URL_THEME_IMAGE, $img_src_url)) { + if (!preg_match(self::REGEX_MOODLE_URL_THEME_IMAGE, $imgsrcurl)) { $img->setAttribute('x-debug-notice', 'image type not allowed'); return false; } } // Try to get image content based on link type - $regex_matches = null; - $img_data = null; + $regexmatches = null; + $imgdata = null; // Handle special internal URLs first - $is_internal_url = substr($img_src_url, 0, strlen($moodle_baseurl)) === $moodle_baseurl; - if ($is_internal_url) { - if (preg_match(self::REGEX_MOODLE_URL_PLUGINFILE, $img_src_url, $regex_matches)) { + $isinternalurl = substr($imgsrcurl, 0, strlen($moodlebaseurl)) === $moodlebaseurl; + if ($isinternalurl) { + if (preg_match(self::REGEX_MOODLE_URL_PLUGINFILE, $imgsrcurl, $regexmatches)) { // ### Link type: Moodle pluginfile URL ### $img->setAttribute('x-url-type', 'MOODLE_URL_PLUGINFILE'); // Edge case detection: question / qtype files follow another pattern, inserting questionbank_id and question_slot after filearea ... - if ($regex_matches['component'] == 'question' || strpos($regex_matches['component'], 'qtype_') === 0) { - $regex_matches = null; - if (!preg_match(self::REGEX_MOODLE_URL_PLUGINFILE_QUESTION_AND_QTYPE, $img_src_url, $regex_matches)) { + if ($regexmatches['component'] == 'question' || strpos($regexmatches['component'], 'qtype_') === 0) { + $regexmatches = null; + if (!preg_match(self::REGEX_MOODLE_URL_PLUGINFILE_QUESTION_AND_QTYPE, $imgsrcurl, $regexmatches)) { $img->setAttribute('x-url-type', 'MOODLE_URL_PLUGINFILE_QUESTION_AND_QTYPE'); return false; } @@ -718,38 +721,38 @@ protected function convert_image_to_base64(\DOMElement $img): bool { // Get file content via Moodle File API $fs = get_file_storage(); $file = $fs->get_file( - $regex_matches['contextid'], - $regex_matches['component'], - $regex_matches['filearea'], - !empty($regex_matches['itemid']) ? $regex_matches['itemid'] : 0, + $regexmatches['contextid'], + $regexmatches['component'], + $regexmatches['filearea'], + !empty($regexmatches['itemid']) ? $regexmatches['itemid'] : 0, '/', // Dirty simplification but works for now *sigh* - $regex_matches['filename'] + $regexmatches['filename'] ); if (!$file) { $img->setAttribute('x-debug-notice', 'moodledata file not found'); return false; } - $img_data = $file->get_content(); - } else if (preg_match(self::REGEX_MOODLE_URL_STACKPLOT, $img_src_url, $regex_matches)) { + $imgdata = $file->get_content(); + } else if (preg_match(self::REGEX_MOODLE_URL_STACKPLOT, $imgsrcurl, $regexmatches)) { // ### Link type: qtype_stack plotfile ### $img->setAttribute('x-url-type', 'MOODLE_URL_STACKPLOT'); // Get STACK plot file from disk - $filename = $CFG->dataroot . '/stack/plots/' . clean_filename($regex_matches['filename']); + $filename = $CFG->dataroot . '/stack/plots/' . clean_filename($regexmatches['filename']); if (!is_readable($filename)) { $img->setAttribute('x-debug-notice', 'stack plot file not readable'); return false; } - $img_data = file_get_contents($filename); + $imgdata = file_get_contents($filename); } else { $img->setAttribute('x-debug-internal-url-without-handler', ''); } } // Fall back to generic URL handling if image data not already set by internal handling routines - if ($img_data === null) { - if (preg_match(self::REGEX_MOODLE_URL_THEME_IMAGE, $img_src_url)) { + if ($imgdata === null) { + if (preg_match(self::REGEX_MOODLE_URL_THEME_IMAGE, $imgsrcurl)) { // ### Link type: Moodle theme image ### // We should be able to download there images using a simple HTTP request // Accessing them directly from disk is a little more complicated due to caching and other logic (see: /theme/image.php). @@ -761,22 +764,22 @@ protected function convert_image_to_base64(\DOMElement $img): bool { } // No special local file access. Try to download via HTTP request - $c = new curl(['ignoresecurity' => $is_internal_url]); - $img_data = $c->get($img_src_url); // Curl handle automatically closed - if ($c->get_info()['http_code'] !== 200 || $img_data === false) { - $img->setAttribute('x-debug-more', $img_data); + $c = new curl(['ignoresecurity' => $isinternalurl]); + $imgdata = $c->get($imgsrcurl); // Curl handle automatically closed + if ($c->get_info()['http_code'] !== 200 || $imgdata === false) { + $img->setAttribute('x-debug-more', $imgdata); $img->setAttribute('x-debug-notice', 'HTTP request failed'); return false; } } // Encode and replace image if present - if (!$img_data) { + if (!$imgdata) { $img->setAttribute('x-debug-notice', 'no image data'); return false; } - $img_base64 = base64_encode($img_data); - $img->setAttribute('src', 'data:'.self::ALLOWED_IMAGE_TYPES[$img_ext].';base64,'.$img_base64); + $imgbase64 = base64_encode($imgdata); + $img->setAttribute('src', 'data:'.self::ALLOWED_IMAGE_TYPES[$imgext].';base64,'.$imgbase64); return true; } @@ -817,7 +820,8 @@ protected static function ensure_absolute_url(string $url, string $base): string /* replace '//' or '/./' or '/foo/../' with '/' */ $re = ['#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#']; - for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {} + for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) { + } /* absolute URL is ready! */ return $scheme.'://'.$abs; diff --git a/classes/TSPManager.php b/classes/TSPManager.php index c87de8a..123a349 100644 --- a/classes/TSPManager.php +++ b/classes/TSPManager.php @@ -55,7 +55,7 @@ public function __construct(ArchiveJob $job) { * * @return TimeStampProtocolClient A fresh TimeStampProtocolClient instance */ - protected function getTimestampProtocolClient(): TimeStampProtocolClient { + protected function gettimestampprotocolclient(): TimeStampProtocolClient { return new TimeStampProtocolClient($this->config->tsp_server_url); } @@ -86,11 +86,11 @@ public function wants_tsp_timestamp(): bool { public function has_tsp_timestamp(): bool { global $DB; - $num_tsp_records = $DB->count_records(self::TSP_TABLE_NAME, [ - 'jobid' => $this->job->get_id() + $numtsprecords = $DB->count_records(self::TSP_TABLE_NAME, [ + 'jobid' => $this->job->get_id(), ]); - return $num_tsp_records > 0; + return $numtsprecords > 0; } /** diff --git a/classes/TimeStampProtocolClient.php b/classes/TimeStampProtocolClient.php index ad3b71d..daee3c1 100644 --- a/classes/TimeStampProtocolClient.php +++ b/classes/TimeStampProtocolClient.php @@ -36,7 +36,7 @@ class TimeStampProtocolClient { /** @var string URL of the TSP server */ - private string $server_url; + private string $serverurl; /** @var string Content-Type header for TimeStampQuery */ const CONTENT_TYPE_TIMESTAMP_QUERY = 'application/timestamp-query'; @@ -49,8 +49,8 @@ class TimeStampProtocolClient { * * @param string $server_url URL of the TSP server */ - public function __construct(string $server_url) { - $this->server_url = $server_url; + public function __construct(string $serverurl) { + $this->server_url = $serverurl; } /** @@ -93,21 +93,21 @@ public function sign(string $sha256hash): array { if ($c->error) { // Moodle curl wrapper provides no getter for curl error message throw new \Exception(get_string('tsp_client_error_curl', 'quiz_archiver', $c->error)); } else { - $curl_info = $c->get_info(); + $curlinfo = $c->get_info(); } - if ($curl_info['http_code'] !== 200) { - throw new \Exception(get_string('tsp_client_error_http_code', 'quiz_archiver', $curl_info['http_code'])); + if ($curlinfo['http_code'] !== 200) { + throw new \Exception(get_string('tsp_client_error_http_code', 'quiz_archiver', $curlinfo['http_code'])); } - if ($curl_info['content_type'] !== self::CONTENT_TYPE_TIMESTAMP_REPLY) { - throw new \Exception(get_string('tsp_client_error_content_type', 'quiz_archiver', $curl_info['content_type'])); + if ($curlinfo['content_type'] !== self::CONTENT_TYPE_TIMESTAMP_REPLY) { + throw new \Exception(get_string('tsp_client_error_content_type', 'quiz_archiver', $curlinfo['content_type'])); } // Success return [ 'query' => $tsreq, - 'reply' => $tsresp + 'reply' => $tsresp, ]; } @@ -117,7 +117,7 @@ public function sign(string $sha256hash): array { * @return string 128-bit nonce * @throws \Exception If an appropriate source of randomness cannot be found. */ - public static function generateNonce(): string { + public static function generatenonce(): string { return random_bytes(16); } @@ -133,7 +133,7 @@ public static function generateNonce(): string { * @return string ASN.1 encoded TimeStampReq * @throws \ValueError If the SHA256 hash or nonce are invalid */ - protected static function createTimeStampReq(string $sha256hash, string $nonce, bool $requestTSAPublicKey = false): string { + protected static function createtimestampreq(string $sha256hash, string $nonce, bool $requesttsapublickey = false): string { // Validate input if (strlen($sha256hash) !== 64) { throw new \ValueError('Invalid hexadecimal SHA256 hash'); @@ -167,7 +167,7 @@ protected static function createTimeStampReq(string $sha256hash, string $nonce, $asn1[] = chr(0x02) . chr(0x10) . $nonce; // INTEGER + Length (16 bytes) + nonce value // -> certReq - if ($requestTSAPublicKey) { + if ($requesttsapublickey) { $asn1[] = chr(0x01) . chr(0x01) . chr(0xff); // BOOLEAN + Length + True } diff --git a/classes/external/generate_attempt_report.php b/classes/external/generate_attempt_report.php index 022f0af..9d2942d 100644 --- a/classes/external/generate_attempt_report.php +++ b/classes/external/generate_attempt_report.php @@ -64,7 +64,7 @@ public static function execute_parameters(): external_function_parameters { 'Sections to include in the report', VALUE_REQUIRED ), - 'attachments' => new external_value(PARAM_BOOL, 'Whether to check for attempts and include metadata if present', VALUE_REQUIRED) + 'attachments' => new external_value(PARAM_BOOL, 'Whether to check for attempts and include metadata if present', VALUE_REQUIRED), ]); } @@ -115,25 +115,25 @@ public static function execute_returns(): external_single_structure { * @throws \DOMException */ public static function execute( - int $courseid_raw, - int $cmid_raw, - int $quizid_raw, - int $attemptid_raw, - string $filenamepattern_raw, - array $sections_raw, - bool $attachments_raw + int $courseidraw, + int $cmidraw, + int $quizidraw, + int $attemptidraw, + string $filenamepatternraw, + array $sectionsraw, + bool $attachmentsraw ): array { global $DB; // Validate request $params = self::validate_parameters(self::execute_parameters(), [ - 'courseid' => $courseid_raw, - 'cmid' => $cmid_raw, - 'quizid' => $quizid_raw, - 'attemptid' => $attemptid_raw, - 'filenamepattern' => $filenamepattern_raw, - 'sections' => $sections_raw, - 'attachments' => $attachments_raw, + 'courseid' => $courseidraw, + 'cmid' => $cmidraw, + 'quizid' => $quizidraw, + 'attemptid' => $attemptidraw, + 'filenamepattern' => $filenamepatternraw, + 'sections' => $sectionsraw, + 'attachments' => $attachmentsraw, ]); // Check capabilities diff --git a/classes/external/get_attempts_metadata.php b/classes/external/get_attempts_metadata.php index 409f2b7..d8af19b 100644 --- a/classes/external/get_attempts_metadata.php +++ b/classes/external/get_attempts_metadata.php @@ -96,15 +96,15 @@ public static function execute_returns(): external_single_structure { * @throws \dml_transaction_exception * @throws \moodle_exception */ - public static function execute(int $courseid_raw, int $cmid_raw, int $quizid_raw, array $attemptids_raw): array { + public static function execute(int $courseidraw, int $cmidraw, int $quizidraw, array $attemptidsraw): array { global $DB; // Validate request $params = self::validate_parameters(self::execute_parameters(), [ - 'courseid' => $courseid_raw, - 'cmid' => $cmid_raw, - 'quizid' => $quizid_raw, - 'attemptids' => $attemptids_raw + 'courseid' => $courseidraw, + 'cmid' => $cmidraw, + 'quizid' => $quizidraw, + 'attemptids' => $attemptidsraw, ]); // Check capabilities @@ -126,17 +126,17 @@ public static function execute(int $courseid_raw, int $cmid_raw, int $quizid_raw $report = new Report($course, $cm, $quiz); if (!$report->has_access(optional_param('wstoken', null, PARAM_TEXT))) { return [ - 'status' => 'E_ACCESS_DENIED' + 'status' => 'E_ACCESS_DENIED', ]; } - $attempt_metadata = $report->get_attempts_metadata($params['attemptids']); + $attemptmetadata = $report->get_attempts_metadata($params['attemptids']); return [ 'courseid' => $params['courseid'], 'cmid' => $params['cmid'], 'quizid' => $params['quizid'], - 'attempts' => $attempt_metadata, - 'status' => 'OK' + 'attempts' => $attemptmetadata, + 'status' => 'OK', ]; } diff --git a/classes/external/get_backup_status.php b/classes/external/get_backup_status.php index 7e6859f..7311276 100644 --- a/classes/external/get_backup_status.php +++ b/classes/external/get_backup_status.php @@ -74,13 +74,13 @@ public static function execute_returns(): external_single_structure { * @throws \required_capability_exception */ public static function execute( - string $jobid_raw, - string $backupid_raw + string $jobidraw, + string $backupidraw ): array { // Validate request $params = self::validate_parameters(self::execute_parameters(), [ - 'jobid' => $jobid_raw, - 'backupid' => $backupid_raw, + 'jobid' => $jobidraw, + 'backupid' => $backupidraw, ]); // Validate that the jobid exists diff --git a/classes/external/process_uploaded_artifact.php b/classes/external/process_uploaded_artifact.php index bc729aa..9812b52 100644 --- a/classes/external/process_uploaded_artifact.php +++ b/classes/external/process_uploaded_artifact.php @@ -88,27 +88,27 @@ public static function execute_returns(): external_single_structure { * @throws \required_capability_exception */ public static function execute( - string $jobid_raw, - string $artifact_component_raw, - int $artifact_contextid_raw, - int $artifact_userid_raw, - string $artifact_filearea_raw, - string $artifact_filename_raw, - string $artifact_filepath_raw, - int $artifact_itemid_raw, - string $artifact_sha256sum_raw + string $jobidraw, + string $artifactcomponentraw, + int $artifactcontextidraw, + int $artifactuseridraw, + string $artifactfilearearaw, + string $artifactfilenameraw, + string $artifactfilepathraw, + int $artifactitemidraw, + string $artifactsha256sumraw ): array { // Validate request $params = self::validate_parameters(self::execute_parameters(), [ - 'jobid' => $jobid_raw, - 'artifact_component' => $artifact_component_raw, - 'artifact_contextid' => $artifact_contextid_raw, - 'artifact_userid' => $artifact_userid_raw, - 'artifact_filearea' => $artifact_filearea_raw, - 'artifact_filename' => $artifact_filename_raw, - 'artifact_filepath' => $artifact_filepath_raw, - 'artifact_itemid' => $artifact_itemid_raw, - 'artifact_sha256sum' => $artifact_sha256sum_raw, + 'jobid' => $jobidraw, + 'artifact_component' => $artifactcomponentraw, + 'artifact_contextid' => $artifactcontextidraw, + 'artifact_userid' => $artifactuseridraw, + 'artifact_filearea' => $artifactfilearearaw, + 'artifact_filename' => $artifactfilenameraw, + 'artifact_filepath' => $artifactfilepathraw, + 'artifact_itemid' => $artifactitemidraw, + 'artifact_sha256sum' => $artifactsha256sumraw, ]); // Validate that the jobid exists and no artifact was uploaded previously @@ -180,7 +180,7 @@ public static function execute( // TODO: Fail silently for now ... // $job->set_status(ArchiveJob::STATUS_FAILED); // return [ - // 'status' => 'E_TSP_TIMESTAMP_FAILED' + // 'status' => 'E_TSP_TIMESTAMP_FAILED' // ]; } } diff --git a/classes/external/update_job_status.php b/classes/external/update_job_status.php index fe522ad..4b35e51 100644 --- a/classes/external/update_job_status.php +++ b/classes/external/update_job_status.php @@ -72,13 +72,13 @@ public static function execute_returns(): external_single_structure { * @throws \coding_exception */ public static function execute( - string $jobid_raw, - string $status_raw + string $jobidraw, + string $statusraw ): array { // Validate request $params = self::validate_parameters(self::execute_parameters(), [ - 'jobid' => $jobid_raw, - 'status' => $status_raw, + 'jobid' => $jobidraw, + 'status' => $statusraw, ]); try { diff --git a/classes/form/archive_quiz_form.php b/classes/form/archive_quiz_form.php index 13c6ba4..dacb569 100644 --- a/classes/form/archive_quiz_form.php +++ b/classes/form/archive_quiz_form.php @@ -39,9 +39,9 @@ class archive_quiz_form extends \moodleform { /** @var string Name of the quiz to be exportet */ - protected string $quiz_name; + protected string $quizname; /** @var int Number of attempts to be exported */ - protected int $num_attempts; + protected int $numattempts; /** * Creates a new archive_quiz_form instance @@ -49,9 +49,9 @@ class archive_quiz_form extends \moodleform { * @param string $quiz_name Name of the quiz to be exported * @param int $num_attempts Number of attempts to be exported */ - public function __construct(string $quiz_name, int $num_attempts) { - $this->quiz_name = $quiz_name; - $this->num_attempts = $num_attempts; + public function __construct(string $quizname, int $numattempts) { + $this->quiz_name = $quizname; + $this->num_attempts = $numattempts; parent::__construct(); } @@ -130,10 +130,14 @@ public function definition() { $mform->addHelpButton('export_course_backup', 'export_course_backup', 'quiz_archiver'); $mform->setDefault('export_course_backup', $config->job_preset_export_course_backup); - // Advanced options - $mform->addElement('header', 'header_advanced_settings', get_string('advancedsettings')); + // PDF cover sheet. + $mform->addElement('header', 'header_advanced_settings', get_string('pdf_cover_sheet', 'quiz_archiver')); $mform->setExpanded('header_advanced_settings', false); + // Advanced options + $mform->addElement('header', 'header_pdf_cover_sheet_settings', get_string('advancedsettings')); + $mform->setExpanded('header_pdf_cover_sheet_settings', false); + $mform->addElement( 'select', 'export_attempts_paper_format', @@ -257,7 +261,7 @@ function validation($data, $files) { * @return \stdClass Cleared, submitted form data * @throws \dml_exception */ - public function get_data():\stdClass { + public function get_data():\stdClass { $data = parent::get_data(); $config = get_config('quiz_archiver'); diff --git a/classes/form/artifact_delete_form.php b/classes/form/artifact_delete_form.php index 35e864e..5cb8b5f 100644 --- a/classes/form/artifact_delete_form.php +++ b/classes/form/artifact_delete_form.php @@ -50,19 +50,19 @@ public function definition() { $artifactfile = $job->get_artifact(); // Generic warning message - $warn_head = get_string('delete_artifact', 'quiz_archiver'); + $warnhead = get_string('delete_artifact', 'quiz_archiver'); if ($artifactfile) { - $warn_msg = get_string('delete_artifact_warning', 'quiz_archiver'); - $warn_details = get_string('jobid', 'quiz_archiver').': '.$job->get_jobid(); - $warn_details .= '
'; - $warn_details .= get_string('quiz_archive', 'quiz_archiver').': ' .$artifactfile->get_filename().' ('.display_size($artifactfile->get_filesize()).')'; + $warnmsg = get_string('delete_artifact_warning', 'quiz_archiver'); + $warndetails = get_string('jobid', 'quiz_archiver').': '.$job->get_jobid(); + $warndetails .= '
'; + $warndetails .= get_string('quiz_archive', 'quiz_archiver').': ' .$artifactfile->get_filename().' ('.display_size($artifactfile->get_filesize()).')'; // Warn additionally if job is scheduled for automatic deletion if ($job->is_autodelete_enabled()) { if ($job->get_status() === ArchiveJob::STATUS_FINISHED) { - $warn_msg .= '

'; - $warn_msg .= get_string( + $warnmsg .= '

'; + $warnmsg .= get_string( 'delete_job_warning_retention', 'quiz_archiver', userdate($job->get_retentiontime(), get_string('strftimedatetime', 'langconfig')) @@ -70,17 +70,17 @@ public function definition() { } } } else { - $warn_msg = get_string('error').': '.get_string('quiz_archive_not_found', 'quiz_archiver', $job->get_jobid()); - $warn_details = get_string('jobid', 'quiz_archiver').': '.$job->get_jobid(); + $warnmsg = get_string('error').': '.get_string('quiz_archive_not_found', 'quiz_archiver', $job->get_jobid()); + $warndetails = get_string('jobid', 'quiz_archiver').': '.$job->get_jobid(); } // Print warning element $mform->addElement('html', << -

$warn_head

- $warn_msg +

$warnhead

+ $warnmsg
- $warn_details + $warndetails EOD); diff --git a/classes/form/job_delete_form.php b/classes/form/job_delete_form.php index 5ca71fd..e26f9ed 100644 --- a/classes/form/job_delete_form.php +++ b/classes/form/job_delete_form.php @@ -50,21 +50,21 @@ public function definition() { $artifactfile = $job->get_artifact(); // Generic warning message - $warn_head = get_string('delete_job', 'quiz_archiver'); - $warn_msg = get_string('delete_job_warning', 'quiz_archiver'); - $warn_details = get_string('jobid', 'quiz_archiver').': '.$job->get_jobid(); + $warnhead = get_string('delete_job', 'quiz_archiver'); + $warnmsg = get_string('delete_job_warning', 'quiz_archiver'); + $warndetails = get_string('jobid', 'quiz_archiver').': '.$job->get_jobid(); // Add artifact details if available if ($artifactfile) { - $warn_details .= '
'; - $warn_details .= get_string('quiz_archive', 'quiz_archiver').': ' .$artifactfile->get_filename().' ('.display_size($artifactfile->get_filesize()).')'; + $warndetails .= '
'; + $warndetails .= get_string('quiz_archive', 'quiz_archiver').': ' .$artifactfile->get_filename().' ('.display_size($artifactfile->get_filesize()).')'; } // Warn additionally if job is scheduled for automatic deletion if ($job->is_autodelete_enabled()) { if ($job->get_status() === ArchiveJob::STATUS_FINISHED) { - $warn_msg .= '

'; - $warn_msg .= get_string( + $warnmsg .= '

'; + $warnmsg .= get_string( 'delete_job_warning_retention', 'quiz_archiver', userdate($job->get_retentiontime(), get_string('strftimedatetime', 'langconfig')) @@ -75,10 +75,10 @@ public function definition() { // Print warning element $mform->addElement('html', << -

$warn_head

- $warn_msg +

$warnhead

+ $warnmsg
- $warn_details + $warndetails EOD); diff --git a/classes/form/job_sign_form.php b/classes/form/job_sign_form.php index 33aea4a..0d23244 100644 --- a/classes/form/job_sign_form.php +++ b/classes/form/job_sign_form.php @@ -43,15 +43,15 @@ public function definition() { $mform = $this->_form; // Warning message - $warn_head = get_string('areyousure', 'moodle'); - $warn_msg = get_string('sign_archive_warning', 'quiz_archiver', $this->optional_param('jobid', null, PARAM_TEXT)); - $warn_details = get_string('jobid', 'quiz_archiver').': '.$this->optional_param('jobid', null, PARAM_TEXT); + $warnhead = get_string('areyousure', 'moodle'); + $warnmsg = get_string('sign_archive_warning', 'quiz_archiver', $this->optional_param('jobid', null, PARAM_TEXT)); + $warndetails = get_string('jobid', 'quiz_archiver').': '.$this->optional_param('jobid', null, PARAM_TEXT); $mform->addElement('html', << -

$warn_head

- $warn_msg +

$warnhead

+ $warnmsg
- $warn_details + $warndetails EOD); diff --git a/classes/local/util.php b/classes/local/util.php index 9a07e97..f1d3706 100644 --- a/classes/local/util.php +++ b/classes/local/util.php @@ -88,4 +88,4 @@ public static function duration_to_unit(int $duration): array { return [$duration, get_string('seconds')]; } -} \ No newline at end of file +} diff --git a/classes/output/job_overview_table.php b/classes/output/job_overview_table.php index 3e21b71..bd23850 100644 --- a/classes/output/job_overview_table.php +++ b/classes/output/job_overview_table.php @@ -163,8 +163,8 @@ public function col_actions($values) { true, ); - $download_title = get_string('download').': '.$artifactfile->get_filename().' ('.get_string('size').': '.display_size($artifactfile->get_filesize()).')'; - $html .= ''; + $downloadtitle = get_string('download').': '.$artifactfile->get_filename().' ('.get_string('size').': '.display_size($artifactfile->get_filesize()).')'; + $html .= ''; } else { $html .= ''; } diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 6067029..9e28234 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -90,7 +90,7 @@ public static function get_contexts_for_userid(int $userid): contextlist { // Get all contexts where the user has a quiz archiver job // Note: The context stays the same across all entries for a single - // archive job. Hence, we only query the main job table. + // archive job. Hence, we only query the main job table. $contextlist->add_from_sql(" SELECT DISTINCT c.id FROM {context} c @@ -142,9 +142,9 @@ public static function export_user_data(approved_contextlist $contextlist) { $userid = $contextlist->get_user()->id; // Process all contexts - $subCtxBase = get_string('pluginname', 'quiz_archiver'); + $subctxbase = get_string('pluginname', 'quiz_archiver'); foreach ($contextlist->get_contexts() as $ctx) { - $ctxData = []; + $ctxdata = []; // Get existing jobs for current context $jobs = $DB->get_records_sql(" @@ -166,10 +166,10 @@ public static function export_user_data(approved_contextlist $contextlist) { // Export each job foreach ($jobs as $job) { // Set correct subcontext for the job - $subCtx = [$subCtxBase, "Job: {$job->jobid}"]; + $subctx = [$subctxbase, "Job: {$job->jobid}"]; // Get job settings - $job_settings = $DB->get_records( + $jobsettings = $DB->get_records( ArchiveJob::JOB_SETTINGS_TABLE_NAME, ['jobid' => $job->id], '', @@ -177,7 +177,7 @@ public static function export_user_data(approved_contextlist $contextlist) { ); // Get TSP data - $tsp_data = $DB->get_record( + $tspdata = $DB->get_record( TSPManager::TSP_TABLE_NAME, ['jobid' => $job->id], 'timecreated, server, timestampquery, timestampreply', @@ -185,26 +185,26 @@ public static function export_user_data(approved_contextlist $contextlist) { ); // Encode TSP data as base64 if present - if ($tsp_data) { - $tsp_data->timestampquery = base64_encode($tsp_data->timestampquery); - $tsp_data->timestampreply = base64_encode($tsp_data->timestampreply); + if ($tspdata) { + $tspdata->timestampquery = base64_encode($tspdata->timestampquery); + $tspdata->timestampreply = base64_encode($tspdata->timestampreply); } // Add job data to current context - writer::with_context($ctx)->export_data($subCtx, (object) [ + writer::with_context($ctx)->export_data($subctx, (object) [ 'courseid' => $job->courseid, 'cmid' => $job->cmid, 'quizid' => $job->quizid, 'userid' => $job->userid, 'timecreated' => $job->timecreated, 'timemodified' => $job->timemodified, - 'settings' => $job_settings, - 'tsp' => $tsp_data, + 'settings' => $jobsettings, + 'tsp' => $tspdata, ]); if ($job->artifactfileid) { writer::with_context($ctx)->export_file( - $subCtx, + $subctx, get_file_storage()->get_file_by_id($job->artifactfileid) ); } @@ -234,7 +234,7 @@ public static function export_user_data(approved_contextlist $contextlist) { $archive = $fm->extract_attempt_data_from_artifact($artifact, $row->jobid, $row->attemptid); if ($archive) { - writer::with_context($ctx)->export_file([$subCtxBase, "Attempts"], $archive); + writer::with_context($ctx)->export_file([$subctxbase, "Attempts"], $archive); } } } diff --git a/classes/task/autodelete_job_artifacts.php b/classes/task/autodelete_job_artifacts.php index cc6e1ac..cd23625 100644 --- a/classes/task/autodelete_job_artifacts.php +++ b/classes/task/autodelete_job_artifacts.php @@ -52,8 +52,8 @@ public function get_name(): string { */ public function execute(): void { echo get_string('task_autodelete_job_artifacts_start', 'quiz_archiver') . "\n"; - $files_deleted = ArchiveJob::delete_expired_artifacts(); - echo get_string('task_autodelete_job_artifacts_report', 'quiz_archiver', $files_deleted) . "\n"; + $filesdeleted = ArchiveJob::delete_expired_artifacts(); + echo get_string('task_autodelete_job_artifacts_report', 'quiz_archiver', $filesdeleted) . "\n"; } -} \ No newline at end of file +} diff --git a/classes/task/cleanup_temp_files.php b/classes/task/cleanup_temp_files.php index 5dd4b20..aed4111 100644 --- a/classes/task/cleanup_temp_files.php +++ b/classes/task/cleanup_temp_files.php @@ -51,8 +51,8 @@ public function get_name(): string { */ public function execute(): void { echo get_string('task_cleanup_temp_files_start', 'quiz_archiver') . "\n"; - $files_deleted = FileManager::cleanup_temp_files(); - echo get_string('task_cleanup_temp_files_report', 'quiz_archiver', $files_deleted) . "\n"; + $filesdeleted = FileManager::cleanup_temp_files(); + echo get_string('task_cleanup_temp_files_report', 'quiz_archiver', $filesdeleted) . "\n"; } -} \ No newline at end of file +} diff --git a/classes/template.html b/classes/template.html new file mode 100644 index 0000000..cd6bff9 --- /dev/null +++ b/classes/template.html @@ -0,0 +1,32 @@ + + +
+ +
+

Name:

+

Jahrgang:

+

Führungskraft:

+

Gruppenbetreuer:

+

Datum:

+
+ + +
diff --git a/db/tasks.php b/db/tasks.php index 053300e..33d56c8 100644 --- a/db/tasks.php +++ b/db/tasks.php @@ -41,4 +41,4 @@ 'month' => '*', 'dayofweek' => '*', ], -]; \ No newline at end of file +]; diff --git a/db/upgrade.php b/db/upgrade.php index b3be3d8..2d384f8 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -74,12 +74,12 @@ function xmldb_quiz_archiver_upgrade($oldversion) { if ($oldversion < 2023072700) { // Replace foreign-unique key with simple foreign key for userid in quiz_report_archiver_jobs. $table = new xmldb_table('quiz_report_archiver_jobs'); - $old_key = new xmldb_key('userid', XMLDB_KEY_FOREIGN_UNIQUE, ['userid'], 'user', ['id']); - $new_key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); + $oldkey = new xmldb_key('userid', XMLDB_KEY_FOREIGN_UNIQUE, ['userid'], 'user', ['id']); + $newkey = new xmldb_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); // Perform key exchange. - $dbman->drop_key($table, $old_key); - $dbman->add_key($table, $new_key); + $dbman->drop_key($table, $oldkey); + $dbman->add_key($table, $newkey); // Archiver savepoint reached. upgrade_plugin_savepoint(true, 2023072700, 'quiz', 'archiver'); @@ -212,6 +212,5 @@ function xmldb_quiz_archiver_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2024011000, 'quiz', 'archiver'); } - return true; } diff --git a/lang/de/quiz_archiver.php b/lang/de/quiz_archiver.php index bf9d518..893db90 100644 --- a/lang/de/quiz_archiver.php +++ b/lang/de/quiz_archiver.php @@ -83,6 +83,7 @@ $string['export_report_section_attachments_help'] = 'Alle Dateiabgaben (z.B. von Aufsätzen/Essay Aufgaben) im Archiv einschließen. Warnung: Dies kann die Archivgröße erheblich erhöhen.'; $string['job_overview'] = 'Testarchive'; $string['num_attempts'] = 'Anzahl Testversuche'; +$string['pdf_cover_sheet'] = 'PDF Deckblatt'; // Job creation form: Filename pattern $string['archive_filename_pattern'] = 'Archivname'; diff --git a/lang/en/quiz_archiver.php b/lang/en/quiz_archiver.php index 7385834..e0467a7 100644 --- a/lang/en/quiz_archiver.php +++ b/lang/en/quiz_archiver.php @@ -83,6 +83,7 @@ $string['export_report_section_attachments_help'] = 'Include all file attachments (e.g., essay file submissions) inside the archive. Warning: This can significantly increase the archive size.'; $string['job_overview'] = 'Archives'; $string['num_attempts'] = 'Number of attempts'; +$string['pdf_cover_sheet'] = 'PDF Cover Sheet'; // Job creation form: Filename pattern $string['archive_filename_pattern'] = 'Archive name'; diff --git a/report.php b/report.php index 7825a7d..6e0f859 100644 --- a/report.php +++ b/report.php @@ -90,109 +90,109 @@ public function display($quiz, $cm, $course): bool { // Start output. $this->print_header_and_tabs($cm, $course, $quiz, 'archiver'); - $tplCtx = [ + $tplctx = [ 'baseurl' => $this->base_url(), 'jobOverviewTable' => "", ]; // Handle job delete form if (optional_param('action', null, PARAM_TEXT) === 'delete_job') { - $job_delete_form = new job_delete_form(); + $jobdeleteform = new job_delete_form(); - if ($job_delete_form->is_cancelled()) { + if ($jobdeleteform->is_cancelled()) { redirect($this->base_url()); } - if ($job_delete_form->is_submitted()) { + if ($jobdeleteform->is_submitted()) { // Check permissions. require_capability('mod/quiz_archiver:delete', $this->context); // Execute deletion - $formdata = $job_delete_form->get_data(); + $formdata = $jobdeleteform->get_data(); ArchiveJob::get_by_jobid($formdata->jobid)->delete(); } else { - $job_delete_form->display(); + $jobdeleteform->display(); return true; } } // Handle artifact delete form if (optional_param('action', null, PARAM_TEXT) === 'delete_artifact') { - $arfifact_delete_form = new artifact_delete_form(); + $arfifactdeleteform = new artifact_delete_form(); - if ($arfifact_delete_form->is_cancelled()) { + if ($arfifactdeleteform->is_cancelled()) { redirect($this->base_url()); } - if ($arfifact_delete_form->is_submitted()) { + if ($arfifactdeleteform->is_submitted()) { // Check permissions. require_capability('mod/quiz_archiver:delete', $this->context); // Execute deletion - $formdata = $arfifact_delete_form->get_data(); + $formdata = $arfifactdeleteform->get_data(); ArchiveJob::get_by_jobid($formdata->jobid)->delete_artifact(); } else { - $arfifact_delete_form->display(); + $arfifactdeleteform->display(); return true; } } // Handle job sign form if (optional_param('action', null, PARAM_TEXT) === 'sign_job') { - $job_sign_form = new job_sign_form(); + $jobsignform = new job_sign_form(); - if ($job_sign_form->is_cancelled()) { + if ($jobsignform->is_cancelled()) { redirect($this->base_url()); } - if ($job_sign_form->is_submitted()) { + if ($jobsignform->is_submitted()) { // Check permissions. require_capability('mod/quiz_archiver:create', $this->context); // Execute signing - $formdata = $job_sign_form->get_data(); - $tspManager = ArchiveJob::get_by_jobid($formdata->jobid)->TSPManager(); - $jobid_log_str = ' ('.get_string('jobid', 'quiz_archiver').': '.$formdata->jobid.')'; - if ($tspManager->has_tsp_timestamp()) { - $tplCtx['jobInitiationStatusAlert'] = [ + $formdata = $jobsignform->get_data(); + $tspmanager = ArchiveJob::get_by_jobid($formdata->jobid)->TSPManager(); + $jobidlogstr = ' ('.get_string('jobid', 'quiz_archiver').': '.$formdata->jobid.')'; + if ($tspmanager->has_tsp_timestamp()) { + $tplctx['jobInitiationStatusAlert'] = [ "color" => "danger", "dismissible" => true, - "message" => get_string('archive_already_signed', 'quiz_archiver').$jobid_log_str, + "message" => get_string('archive_already_signed', 'quiz_archiver').$jobidlogstr, ]; } else { try { - $tspManager->timestamp(); - $tplCtx['jobInitiationStatusAlert'] = [ + $tspmanager->timestamp(); + $tplctx['jobInitiationStatusAlert'] = [ "color" => "success", "dismissible" => true, - "message" => get_string('archive_signed_successfully', 'quiz_archiver').$jobid_log_str, + "message" => get_string('archive_signed_successfully', 'quiz_archiver').$jobidlogstr, ]; } catch (RuntimeException $e) { - $tplCtx['jobInitiationStatusAlert'] = [ + $tplctx['jobInitiationStatusAlert'] = [ "color" => "danger", "dismissible" => true, - "message" => get_string('archive_signing_failed_no_artifact', 'quiz_archiver').$jobid_log_str, + "message" => get_string('archive_signing_failed_no_artifact', 'quiz_archiver').$jobidlogstr, ]; } catch (Exception $e) { - $tplCtx['jobInitiationStatusAlert'] = [ + $tplctx['jobInitiationStatusAlert'] = [ "color" => "danger", "dismissible" => true, - "message" => get_string('archive_signing_failed', 'quiz_archiver').': '.$e->getMessage().$jobid_log_str, + "message" => get_string('archive_signing_failed', 'quiz_archiver').': '.$e->getMessage().$jobidlogstr, ]; } } } else { - $job_sign_form->display(); + $jobsignform->display(); return true; } } // Determine page to display if (!quiz_has_questions($quiz->id)) { - $tplCtx['quizMissingSomethingWarning'] = quiz_no_questions_message($quiz, $cm, $this->context); + $tplctx['quizMissingSomethingWarning'] = quiz_no_questions_message($quiz, $cm, $this->context); } else { if (!quiz_has_attempts($quiz->id)) { - $tplCtx['quizMissingSomethingWarning'] = $OUTPUT->notification( + $tplctx['quizMissingSomethingWarning'] = $OUTPUT->notification( get_string('noattempts', 'quiz'), \core\output\notification::NOTIFY_ERROR, false @@ -201,19 +201,19 @@ public function display($quiz, $cm, $course): bool { } // Archive quiz form - if (!array_key_exists('quizMissingSomethingWarning', $tplCtx)) { - $archive_quiz_form = new archive_quiz_form( + if (!array_key_exists('quizMissingSomethingWarning', $tplctx)) { + $archivequizform = new archive_quiz_form( $this->quiz->name, count($this->report->get_attempts()) ); - if ($archive_quiz_form->is_submitted()) { + if ($archivequizform->is_submitted()) { $job = null; try { - if (!$archive_quiz_form->is_validated()) { + if (!$archivequizform->is_validated()) { throw new RuntimeException(get_string('error_archive_quiz_form_validation_failed', 'quiz_archiver')); } - $formdata = $archive_quiz_form->get_data(); + $formdata = $archivequizform->get_data(); $job = $this->initiate_archive_job( $formdata->export_attempts, Report::build_report_sections_from_formdata($formdata), @@ -225,13 +225,13 @@ public function display($quiz, $cm, $course): bool { $formdata->export_attempts_filename_pattern, $formdata->archive_autodelete ? $formdata->archive_retention_time : null, ); - $tplCtx['jobInitiationStatusAlert'] = [ + $tplctx['jobInitiationStatusAlert'] = [ "color" => "success", "message" => get_string('job_created_successfully', 'quiz_archiver', $job->get_jobid()), "returnMessage" => get_string('continue'), ]; } catch (RuntimeException $e) { - $tplCtx['jobInitiationStatusAlert'] = [ + $tplctx['jobInitiationStatusAlert'] = [ "color" => "danger", "message" => $e->getMessage(), "returnMessage" => get_string('retry'), @@ -240,26 +240,26 @@ public function display($quiz, $cm, $course): bool { // Do not print job overview table if job creation failed if ($job == null) { - unset($tplCtx['jobOverviewTable']); + unset($tplctx['jobOverviewTable']); } } else { - $tplCtx['jobInitiationForm'] = $archive_quiz_form->render(); + $tplctx['jobInitiationForm'] = $archivequizform->render(); } } // Job overview table - if (array_key_exists('jobOverviewTable', $tplCtx)) { + if (array_key_exists('jobOverviewTable', $tplctx)) { // Generate table $jobtbl = new job_overview_table('job_overview_table', $this->course->id, $this->cm->id, $this->quiz->id, $USER->id); $jobtbl->define_baseurl($this->base_url()); ob_start(); $jobtbl->out(10, true); - $jobtbl_html = ob_get_contents(); + $jobtblhtml = ob_get_contents(); ob_end_clean(); - $tplCtx['jobOverviewTable'] = $jobtbl_html; + $tplctx['jobOverviewTable'] = $jobtblhtml; // Prepare job metadata for job detail modals - $tplCtx['jobs'] = array_map(function($jm): array { + $tplctx['jobs'] = array_map(function($jm): array { // Generate action URLs $jm['action_urls'] = [ 'delete_job' => (new moodle_url($this->base_url(), [ @@ -307,7 +307,7 @@ public function display($quiz, $cm, $course): bool { } // Render output - echo $OUTPUT->render_from_template('quiz_archiver/overview', $tplCtx); + echo $OUTPUT->render_from_template('quiz_archiver/overview', $tplctx); return true; } @@ -333,15 +333,15 @@ public function display($quiz, $cm, $course): bool { * @throws RuntimeException Used to signal a soft failure to calling context */ protected function initiate_archive_job( - bool $export_attempts, - array $report_sections, - bool $report_keep_html_files, - string $paper_format, - bool $export_quiz_backup, - bool $export_course_backup, - string $archive_filename_pattern, - string $attempts_filename_pattern, - ?int $retention_seconds = null, + bool $exportattempts, + array $reportsections, + bool $reportkeephtmlfiles, + string $paperformat, + bool $exportquizbackup, + bool $exportcoursebackup, + string $archivefilenamepattern, + string $attemptsfilenamepattern, + ?int $retentionseconds = null, int $userid = 0 ): ?ArchiveJob { global $USER; @@ -384,80 +384,80 @@ protected function initiate_archive_job( $attempts = $this->report->get_attempts($userid); // Prepare task: Export quiz attempts - $task_archive_quiz_attempts = null; - if ($export_attempts) { - $task_archive_quiz_attempts = [ + $taskarchivequizattempts = null; + if ($exportattempts) { + $taskarchivequizattempts = [ 'attemptids' => array_values(array_keys($attempts)), 'fetch_metadata' => true, - 'sections' => $report_sections, - 'paper_format' => $paper_format, - 'keep_html_files' => $report_keep_html_files, - 'filename_pattern' => $attempts_filename_pattern, + 'sections' => $reportsections, + 'paper_format' => $paperformat, + 'keep_html_files' => $reportkeephtmlfiles, + 'filename_pattern' => $attemptsfilenamepattern, ]; } // Prepare task: Moodle backups - $task_moodle_backups = null; - if ($export_quiz_backup || $export_course_backup) { - $task_moodle_backups = []; + $taskmoodlebackups = null; + if ($exportquizbackup || $exportcoursebackup) { + $taskmoodlebackups = []; - if ($export_quiz_backup) { - $task_moodle_backups[] = BackupManager::initiate_quiz_backup($this->cm->id, $this->config->webservice_userid); + if ($exportquizbackup) { + $taskmoodlebackups[] = BackupManager::initiate_quiz_backup($this->cm->id, $this->config->webservice_userid); } - if ($export_course_backup) { - $task_moodle_backups[] = BackupManager::initiate_course_backup($this->course->id, $this->config->webservice_userid); + if ($exportcoursebackup) { + $taskmoodlebackups[] = BackupManager::initiate_course_backup($this->course->id, $this->config->webservice_userid); } } // Generate job settings array - $job_settings = []; - $job_settings['num_attempts'] = count($attempts); - $job_settings['export_attempts'] = $export_attempts; - if ($export_attempts) { - foreach ($report_sections as $section_name => $section_value) { - $job_settings["export_report_section_$section_name"] = $section_value; + $jobsettings = []; + $jobsettings['num_attempts'] = count($attempts); + $jobsettings['export_attempts'] = $exportattempts; + if ($exportattempts) { + foreach ($reportsections as $sectionname => $sectionvalue) { + $jobsettings["exportreportsection$sectionname"] = $sectionvalue; } } - $job_settings['export_quiz_backup'] = $export_quiz_backup ? '1' : '0'; - $job_settings['export_course_backup'] = $export_course_backup ? '1' : '0'; - $job_settings['archive_autodelete'] = $retention_seconds ? '1' : '0'; - if ($retention_seconds) { - $job_settings['archive_retention_time'] = util::duration_to_human_readable($retention_seconds); + $jobsettings['export_quiz_backup'] = $exportquizbackup ? '1' : '0'; + $jobsettings['export_course_backup'] = $exportcoursebackup ? '1' : '0'; + $jobsettings['archive_autodelete'] = $retentionseconds ? '1' : '0'; + if ($retentionseconds) { + $jobsettings['archive_retention_time'] = util::duration_to_human_readable($retentionseconds); } // Request archive worker $worker = new RemoteArchiveWorker(rtrim($this->config->worker_url, '/').'/archive', 10, 20); try { - $job_metadata = $worker->enqueue_archive_job( + $jobmetadata = $worker->enqueue_archive_job( $wstoken, $this->course->id, $this->cm->id, $this->quiz->id, [ - 'archive_filename' => ArchiveJob::generate_archive_filename($this->course, $this->cm, $this->quiz, $archive_filename_pattern), + 'archive_filename' => ArchiveJob::generate_archive_filename($this->course, $this->cm, $this->quiz, $archivefilenamepattern), ], - $task_archive_quiz_attempts, - $task_moodle_backups, + $taskarchivequizattempts, + $taskmoodlebackups, ); // Persist job in database $job = ArchiveJob::create( - $job_metadata->jobid, + $jobmetadata->jobid, $this->course->id, $this->cm->id, $this->quiz->id, $USER->id, - $retention_seconds, + $retentionseconds, $wstoken, $attempts, - $job_settings, - $job_metadata->status + $jobsettings, + $jobmetadata->status ); // Link all temporary files to be created, if present - if ($task_moodle_backups) { - foreach ($task_moodle_backups as $task) { + if ($taskmoodlebackups) { + foreach ($taskmoodlebackups as $task) { $job->link_temporary_file($task->pathnamehash); } } @@ -495,15 +495,15 @@ public function initiate_users_archive_job( object $cm, object $course, object $context, - bool $export_attempts, - array $report_sections, - bool $report_keep_html_files, - string $paper_format, - bool $export_quiz_backup, - bool $export_course_backup, - string $archive_filename_pattern, - string $attempts_filename_pattern, - ?int $retention_seconds = null, + bool $exportattempts, + array $reportsections, + bool $reportkeephtmlfiles, + string $paperformat, + bool $exportquizbackup, + bool $exportcoursebackup, + string $archivefilenamepattern, + string $attemptsfilenamepattern, + ?int $retentionseconds = null, int $userid = 0 ) { $this->context = $context; @@ -514,15 +514,15 @@ public function initiate_users_archive_job( $this->quiz = $quiz; $this->report = new Report($this->course, $this->cm, $this->quiz); return $this->initiate_archive_job( - $export_attempts, - $report_sections, - $report_keep_html_files, - $paper_format, - $export_quiz_backup, - $export_course_backup, - $archive_filename_pattern, - $attempts_filename_pattern, - $retention_seconds, + $exportattempts, + $reportsections, + $reportkeephtmlfiles, + $paperformat, + $exportquizbackup, + $exportcoursebackup, + $archivefilenamepattern, + $attemptsfilenamepattern, + $retentionseconds, $userid ); } diff --git a/tests/classes/ArchiveJob_test.php b/tests/classes/ArchiveJob_test.php index 74ee6ec..c49990d 100644 --- a/tests/classes/ArchiveJob_test.php +++ b/tests/classes/ArchiveJob_test.php @@ -37,7 +37,7 @@ class ArchiveJob_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -47,7 +47,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object) [ @@ -89,7 +89,7 @@ protected function generateMockQuiz(): \stdClass { * @throws \file_exception * @throws \stored_file_creation_exception */ - protected function generateArtifactFile(int $courseid, int $cmid, int $quizid, string $filename): \stored_file { + protected function generateartifactfile(int $courseid, int $cmid, int $quizid, string $filename): \stored_file { $this->resetAfterTest(); $ctx = context_course::instance($courseid); @@ -207,68 +207,68 @@ public function test_multiple_jobs_retrieval_and_metadata(): void { // Generate data $mocks = []; $jobs = []; - for ($quizIdx= 0; $quizIdx < 3; $quizIdx++) { - $mocks[$quizIdx] = $this->generateMockQuiz(); - for ($jobIdx = 0; $jobIdx < 3; $jobIdx++) { - $jobs[$quizIdx][$jobIdx] = ArchiveJob::create( - '30000000-1234-5678-abcd-'.$quizIdx.'0000000000'.$jobIdx, - $mocks[$quizIdx]->course->id, - $mocks[$quizIdx]->quiz->cmid, - $mocks[$quizIdx]->quiz->id, - $mocks[$quizIdx]->user->id, - 3600 + $jobIdx * $quizIdx * 100, + for ($quizidx = 0; $quizidx < 3; $quizidx++) { + $mocks[$quizidx] = $this->generateMockQuiz(); + for ($jobidx = 0; $jobidx < 3; $jobidx++) { + $jobs[$quizidx][$jobidx] = ArchiveJob::create( + '30000000-1234-5678-abcd-'.$quizidx.'0000000000'.$jobidx, + $mocks[$quizidx]->course->id, + $mocks[$quizidx]->quiz->cmid, + $mocks[$quizidx]->quiz->id, + $mocks[$quizidx]->user->id, + 3600 + $jobidx * $quizidx * 100, 'TEST-WS-TOKEN', - $mocks[$quizIdx]->attempts, - $mocks[$quizIdx]->settings + $mocks[$quizidx]->attempts, + $mocks[$quizidx]->settings ); } } // Find jobs in database - foreach ($mocks as $quizIdx => $mock) { + foreach ($mocks as $quizidx => $mock) { $this->assertEqualsCanonicalizing( - array_values($jobs[$quizIdx]), + array_values($jobs[$quizidx]), array_values(ArchiveJob::get_jobs($mock->course->id, $mock->quiz->cmid, $mock->quiz->id)), - 'Jobs for quiz '.$quizIdx.' were not returned properly by get_jobs()' + 'Jobs for quiz '.$quizidx.' were not returned properly by get_jobs()' ); } // Test metadata retrieval - foreach ($mocks as $quizIdx => $mock) { + foreach ($mocks as $quizidx => $mock) { $metadata = ArchiveJob::get_metadata_for_jobs($mock->course->id, $mock->quiz->cmid, $mock->quiz->id); // Check that the metadata array contains the correct number of jobs $this->assertSameSize( - $jobs[$quizIdx], + $jobs[$quizidx], $metadata, - 'Metadata for quiz '.$quizIdx.' does not contain the correct number of jobs' + 'Metadata for quiz '.$quizidx.' does not contain the correct number of jobs' ); // Check that the metadata array contains the correct data - foreach ($jobs[$quizIdx] as $jobIdx => $expectedJob) { + foreach ($jobs[$quizidx] as $jobidx => $expectedjob) { // Find job in metadata array - $actualJobs = array_filter($metadata, function ($metadata) use ($expectedJob) { - return $metadata['id'] == $expectedJob->get_id(); + $actualjobs = array_filter($metadata, function ($metadata) use ($expectedjob) { + return $metadata['id'] == $expectedjob->get_id(); }); // Assure that job was found $this->assertCount( 1, - $actualJobs, - 'Metadata for job '.$jobIdx.' of quiz '.$quizIdx.' could not uniquely be identified' + $actualjobs, + 'Metadata for job '.$jobidx.' of quiz '.$quizidx.' could not uniquely be identified' ); // Probe that the metadata contains the correct data - $actualJob = array_pop($actualJobs); - $this->assertEquals($expectedJob->get_jobid(), $actualJob['jobid'], 'Jobid was not returned correctly'); - $this->assertEquals($expectedJob->get_course_id(), $actualJob['course']['id'], 'Courseid was not returned correctly'); - $this->assertEquals($expectedJob->get_cm_id(), $actualJob['quiz']['cmid'], 'Course module id was not returned correctly'); - $this->assertEquals($expectedJob->get_quiz_id(), $actualJob['quiz']['id'], 'Quiz id was not returned correctly'); - $this->assertEquals($expectedJob->get_user_id(), $actualJob['user']['id'], 'User id was not returned correctly'); - $this->assertEquals($expectedJob->get_retentiontime(), $actualJob['retentiontime'], 'Retentiontime was not returned correctly'); - $this->assertSame($expectedJob->is_autodelete_enabled(), $actualJob['autodelete'], 'Autodelete was not detected as enabled'); - $this->assertArrayHasKey('autodelete_str', $actualJob, 'Autodelete string was not generated correctly'); - $this->assertSameSize($expectedJob->get_settings(), $actualJob['settings'], 'Settings were not returned correctly'); + $actualjob = array_pop($actualjobs); + $this->assertEquals($expectedjob->get_jobid(), $actualjob['jobid'], 'Jobid was not returned correctly'); + $this->assertEquals($expectedjob->get_course_id(), $actualjob['course']['id'], 'Courseid was not returned correctly'); + $this->assertEquals($expectedjob->get_cm_id(), $actualjob['quiz']['cmid'], 'Course module id was not returned correctly'); + $this->assertEquals($expectedjob->get_quiz_id(), $actualjob['quiz']['id'], 'Quiz id was not returned correctly'); + $this->assertEquals($expectedjob->get_user_id(), $actualjob['user']['id'], 'User id was not returned correctly'); + $this->assertEquals($expectedjob->get_retentiontime(), $actualjob['retentiontime'], 'Retentiontime was not returned correctly'); + $this->assertSame($expectedjob->is_autodelete_enabled(), $actualjob['autodelete'], 'Autodelete was not detected as enabled'); + $this->assertArrayHasKey('autodelete_str', $actualjob, 'Autodelete string was not generated correctly'); + $this->assertSameSize($expectedjob->get_settings(), $actualjob['settings'], 'Settings were not returned correctly'); } } } @@ -282,7 +282,7 @@ public function test_multiple_jobs_retrieval_and_metadata(): void { */ public function test_set_job_status(): void { // Job statuses to test and whether they should be considered completed - $statuses_and_completion = [ + $statusesandcompletion = [ ArchiveJob::STATUS_UNKNOWN => false, ArchiveJob::STATUS_UNINITIALIZED => false, ArchiveJob::STATUS_AWAITING_PROCESSING => false, @@ -295,7 +295,7 @@ public function test_set_job_status(): void { // Create test job $mocks = $this->generateMockQuiz(); - $expectedJob = ArchiveJob::create( + $expectedjob = ArchiveJob::create( '40000000-1234-5678-abcd-ef4242424242', $mocks->course->id, $mocks->quiz->cmid, @@ -316,11 +316,11 @@ public function test_set_job_status(): void { ); // Test status changes - foreach ($statuses_and_completion as $status => $completion) { - $expectedJob->set_status($status); - $actualJob = ArchiveJob::get_by_jobid('40000000-1234-5678-abcd-ef4242424242'); - $this->assertEquals($status, $actualJob->get_status(),'Job status was not set correctly to '.$status); - $this->assertEquals($completion, $actualJob->is_complete(), 'Job completion was not detected correctly'); + foreach ($statusesandcompletion as $status => $completion) { + $expectedjob->set_status($status); + $actualjob = ArchiveJob::get_by_jobid('40000000-1234-5678-abcd-ef4242424242'); + $this->assertEquals($status, $actualjob->get_status(), 'Job status was not set correctly to '.$status); + $this->assertEquals($completion, $actualjob->is_complete(), 'Job completion was not detected correctly'); } } @@ -546,7 +546,7 @@ public function test_artifact_checksum_non_existing(): void { public function test_temporary_file_linking(): void { // Generate data $mocks = $this->generateMockQuiz(); - $tmpFiles = [ + $tmpfiles = [ $this->generateArtifactFile($mocks->course->id, $mocks->quiz->cmid, $mocks->quiz->id, 'test1.tar.gz'), $this->generateArtifactFile($mocks->course->id, $mocks->quiz->cmid, $mocks->quiz->id, 'test2.tar.gz'), $this->generateArtifactFile($mocks->course->id, $mocks->quiz->cmid, $mocks->quiz->id, 'test3.tar.gz'), @@ -569,13 +569,13 @@ public function test_temporary_file_linking(): void { $this->assertEmpty($job->get_temporary_files(), 'Job returned temporary files before linking'); // Link files and check that they were linked correctly - foreach ($tmpFiles as $tmpFile) { - $job->link_temporary_file($tmpFile->get_pathnamehash()); + foreach ($tmpfiles as $tmpfile) { + $job->link_temporary_file($tmpfile->get_pathnamehash()); } - $actualTempFiles = $job->get_temporary_files(); - foreach ($tmpFiles as $tmpFile) { - $this->assertEquals($tmpFile, $actualTempFiles[$tmpFile->get_id()], 'Temporary file was not linked correctly'); + $actualtempfiles = $job->get_temporary_files(); + foreach ($tmpfiles as $tmpfile) { + $this->assertEquals($tmpfile, $actualtempfiles[$tmpfile->get_id()], 'Temporary file was not linked correctly'); } } @@ -591,7 +591,7 @@ public function test_temporary_file_linking(): void { public function test_temporary_file_deletion(): void { // Generate data $mocks = $this->generateMockQuiz(); - $tmpFiles = [ + $tmpfiles = [ $this->generateArtifactFile($mocks->course->id, $mocks->quiz->cmid, $mocks->quiz->id, 'test1.tar.gz'), $this->generateArtifactFile($mocks->course->id, $mocks->quiz->cmid, $mocks->quiz->id, 'test2.tar.gz'), $this->generateArtifactFile($mocks->course->id, $mocks->quiz->cmid, $mocks->quiz->id, 'test3.tar.gz'), @@ -609,8 +609,8 @@ public function test_temporary_file_deletion(): void { $mocks->attempts, $mocks->settings ); - foreach ($tmpFiles as $tmpFile) { - $job->link_temporary_file($tmpFile->get_pathnamehash()); + foreach ($tmpfiles as $tmpfile) { + $job->link_temporary_file($tmpfile->get_pathnamehash()); } // Ensure link state, delete and check @@ -618,8 +618,8 @@ public function test_temporary_file_deletion(): void { $job->delete_temporary_files(); $this->assertEmpty($job->get_temporary_files(), 'Job still has temporary files after deletion'); - foreach ($tmpFiles as $tmpFile) { - $this->assertFalse(get_file_storage()->get_file_by_id($tmpFile->get_id()), 'Temporary file was not deleted from file storage'); + foreach ($tmpfiles as $tmpfile) { + $this->assertFalse(get_file_storage()->get_file_by_id($tmpfile->get_id()), 'Temporary file was not deleted from file storage'); } } @@ -632,9 +632,9 @@ public function test_temporary_file_deletion(): void { * @param bool $isValid Expected result * @return void */ - public function test_archive_filename_pattern_validation(string $pattern, bool $isValid): void { + public function test_archive_filename_pattern_validation(string $pattern, bool $isvalid): void { $this->assertSame( - $isValid, + $isvalid, ArchiveJob::is_valid_archive_filename_pattern($pattern), 'Archive filename pattern validation failed for pattern "'.$pattern.'"' ); @@ -697,9 +697,9 @@ function ($carry, $item) { * @param bool $isValid Expected result * @return void */ - public function test_attempt_filename_pattern_validation(string $pattern, bool $isValid): void { + public function test_attempt_filename_pattern_validation(string $pattern, bool $isvalid): void { $this->assertSame( - $isValid, + $isvalid, ArchiveJob::is_valid_attempt_filename_pattern($pattern), 'Attempt filename pattern validation failed for pattern "'.$pattern.'"' ); @@ -753,4 +753,4 @@ function ($carry, $item) { ]; } -} \ No newline at end of file +} diff --git a/tests/classes/TSPManager_test.php b/tests/classes/TSPManager_test.php index 5c5d76c..9c2709f 100644 --- a/tests/classes/TSPManager_test.php +++ b/tests/classes/TSPManager_test.php @@ -37,7 +37,7 @@ class TSPManager_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -47,7 +47,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object) [ @@ -68,7 +68,7 @@ protected function generateMockQuiz(): \stdClass { * @throws \file_exception * @throws \stored_file_creation_exception */ - protected function generateArtifactFile(int $courseid, int $cmid, int $quizid, string $filename): \stored_file { + protected function generateartifactfile(int $courseid, int $cmid, int $quizid, string $filename): \stored_file { $this->resetAfterTest(); $ctx = context_course::instance($courseid); @@ -96,34 +96,34 @@ protected function generateArtifactFile(int $courseid, int $cmid, int $quizid, s * @param string $dummy_reply Dummy TSP reply data * @return TSPManager */ - protected function createMockTSPManager( + protected function createmocktspmanager( ArchiveJob $job, - string $dummy_server = 'localhost', - string $dummy_query = 'tsp-dummy-query', - string $dummy_reply = 'tsp-dummy-reply-0123456789abcdef' + string $dummyserver = 'localhost', + string $dummyquery = 'tsp-dummy-query', + string $dummyreply = 'tsp-dummy-reply-0123456789abcdef' ): TSPManager { // Prepare TimeStampProtocolClient that returns dummy data - $tspClientMock = $this->getMockBuilder(TimeStampProtocolClient::class) + $tspclientmock = $this->getMockBuilder(TimeStampProtocolClient::class) ->onlyMethods(['sign']) - ->setConstructorArgs([$dummy_server]) + ->setConstructorArgs([$dummyserver]) ->getMock(); - $tspClientMock->expects($this->any()) + $tspclientmock->expects($this->any()) ->method('sign') ->willReturn([ - 'query' => $dummy_query, - 'reply' => $dummy_reply, + 'query' => $dummyquery, + 'reply' => $dummyreply, ]); // Create TSPManager that uses the mocked TimeStampProtocolClient - $tspManager = $this->getMockBuilder(TSPManager::class) + $tspmanager = $this->getMockBuilder(TSPManager::class) ->onlyMethods(['getTimestampProtocolClient']) ->setConstructorArgs([$job]) ->getMock(); - $tspManager->expects($this->any()) + $tspmanager->expects($this->any()) ->method('getTimestampProtocolClient') - ->willReturn($tspClientMock); + ->willReturn($tspclientmock); - return $tspManager; + return $tspmanager; } /** @@ -163,14 +163,14 @@ public function test_tsp_timestamp(): void { $this->assertFalse($job->TSPManager()->has_tsp_timestamp(), 'Artifact was detected as signed without it being signed'); // Try signing the artifact using TSP - $tspManager = $this->createMockTSPManager($job); - $tspManager->timestamp(); - $this->assertTrue($tspManager->has_tsp_timestamp(), 'Artifact was not detected as signed after signing it'); + $tspmanager = $this->createMockTSPManager($job); + $tspmanager->timestamp(); + $this->assertTrue($tspmanager->has_tsp_timestamp(), 'Artifact was not detected as signed after signing it'); // Ensure that the TSP data was stored correctly - $this->assertEquals('tsp-dummy-query', $tspManager->get_tsp_data()->query, 'TSP query was not stored correctly'); - $this->assertEquals('tsp-dummy-reply-0123456789abcdef', $tspManager->get_tsp_data()->reply, 'TSP reply was not stored correctly'); - $this->assertEquals('localhost', $tspManager->get_tsp_data()->server, 'TSP server URL was not stored correctly'); + $this->assertEquals('tsp-dummy-query', $tspmanager->get_tsp_data()->query, 'TSP query was not stored correctly'); + $this->assertEquals('tsp-dummy-reply-0123456789abcdef', $tspmanager->get_tsp_data()->reply, 'TSP reply was not stored correctly'); + $this->assertEquals('localhost', $tspmanager->get_tsp_data()->server, 'TSP server URL was not stored correctly'); } /** @@ -207,13 +207,13 @@ public function test_delete_tsp_data(): void { $job->link_artifact($artifact->get_id(), $sha256dummy); // Sign the artifact using TSP - $tspManager = $this->createMockTSPManager($job); - $tspManager->timestamp(); - $this->assertTrue($tspManager->has_tsp_timestamp(), 'Artifact was not detected as signed after signing it'); + $tspmanager = $this->createMockTSPManager($job); + $tspmanager->timestamp(); + $this->assertTrue($tspmanager->has_tsp_timestamp(), 'Artifact was not detected as signed after signing it'); // Delete the TSP data - $tspManager->delete_tsp_data(); - $this->assertFalse($tspManager->has_tsp_timestamp(), 'Artifact was detected as signed after deleting the TSP data'); + $tspmanager->delete_tsp_data(); + $this->assertFalse($tspmanager->has_tsp_timestamp(), 'Artifact was detected as signed after deleting the TSP data'); } /** @@ -289,4 +289,4 @@ public function test_signing_disabled(): void { $this->createMockTSPManager($job)->timestamp(); } -} \ No newline at end of file +} diff --git a/tests/classes/external/generate_attempt_report_test.php b/tests/classes/external/generate_attempt_report_test.php index 7d35143..23e31c5 100644 --- a/tests/classes/external/generate_attempt_report_test.php +++ b/tests/classes/external/generate_attempt_report_test.php @@ -37,7 +37,7 @@ class generate_attempt_report_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -47,7 +47,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object)[ @@ -66,7 +66,7 @@ protected function generateMockQuiz(): \stdClass { * @param int $attemptid Attempt ID * @return array Valid request parameters */ - protected function generateValidRequest(int $courseid, int $cmid, int $quizid, int $attemptid): array { + protected function generatevalidrequest(int $courseid, int $cmid, int $quizid, int $attemptid): array { return [ 'courseid' => $courseid, 'cmid' => $cmid, @@ -129,15 +129,16 @@ public function test_parameter_validation( string $filenamepattern, array $sections, bool $attachments, - bool $shouldFail + bool $shouldfail ): void { - if ($shouldFail) { + if ($shouldfail) { $this->expectException(\invalid_parameter_exception::class); } try { generate_attempt_report::execute($courseid, $cmid, $quizid, $attemptid, $filenamepattern, $sections, $attachments); - } catch (\dml_missing_record_exception $e) {} + } catch (\dml_missing_record_exception $e) { + } } /** diff --git a/tests/classes/external/get_attempts_metadata_test.php b/tests/classes/external/get_attempts_metadata_test.php index 20c893d..fdd7a1e 100644 --- a/tests/classes/external/get_attempts_metadata_test.php +++ b/tests/classes/external/get_attempts_metadata_test.php @@ -37,7 +37,7 @@ class get_attempts_metadata_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -47,7 +47,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object)[ @@ -65,7 +65,7 @@ protected function generateMockQuiz(): \stdClass { * @param int $quizid Quiz ID * @return array Valid request parameters */ - protected function generateValidRequest(int $courseid, int $cmid, int $quizid): array { + protected function generatevalidrequest(int $courseid, int $cmid, int $quizid): array { return [ 'courseid' => $courseid, 'cmid' => $cmid, @@ -114,15 +114,16 @@ public function test_parameter_validation( int $cmid, int $quizid, array $attemptids, - bool $shouldFail + bool $shouldfail ): void { - if ($shouldFail) { + if ($shouldfail) { $this->expectException(\invalid_parameter_exception::class); } try { get_attempts_metadata::execute($courseid, $cmid, $quizid, $attemptids); - } catch (\dml_exception $e) {} + } catch (\dml_exception $e) { + } } /** diff --git a/tests/classes/external/get_backup_status_test.php b/tests/classes/external/get_backup_status_test.php index 7c60132..e84db9a 100644 --- a/tests/classes/external/get_backup_status_test.php +++ b/tests/classes/external/get_backup_status_test.php @@ -38,7 +38,7 @@ class get_backup_status_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -48,7 +48,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object)[ @@ -105,15 +105,16 @@ public function test_capability_requirement(): void { public function test_parameter_validation( string $jobid, string $backupid, - bool $shouldFail + bool $shouldfail ): void { - if ($shouldFail) { + if ($shouldfail) { $this->expectException(\invalid_parameter_exception::class); } try { get_backup_status::execute($jobid, $backupid); - } catch (\dml_exception $e) {} + } catch (\dml_exception $e) { + } } /** diff --git a/tests/classes/external/process_uploaded_artifact_test.php b/tests/classes/external/process_uploaded_artifact_test.php index df30392..a2fdb0b 100644 --- a/tests/classes/external/process_uploaded_artifact_test.php +++ b/tests/classes/external/process_uploaded_artifact_test.php @@ -39,7 +39,7 @@ class process_uploaded_artifact_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -49,7 +49,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object)[ @@ -67,7 +67,7 @@ protected function generateMockQuiz(): \stdClass { * @param int $userid User ID * @return array Valid request parameters */ - protected function generateValidRequest(string $jobid, int $cmid, int $userid): array { + protected function generatevalidrequest(string $jobid, int $cmid, int $userid): array { return [ 'jobid' => $jobid, 'artifact_component' => FileManager::COMPONENT_NAME, @@ -146,30 +146,30 @@ public function test_capability_requirement(): void { */ public function test_parameter_validation( string $jobid, - string $artifact_component, - int $artifact_contextid, - int $artifact_userid, - string $artifact_filearea, - string $artifact_filename, - string $artifact_filepath, - int $artifact_itemid, - string $artifact_sha256sum, - bool $shouldFail + string $artifactcomponent, + int $artifactcontextid, + int $artifactuserid, + string $artifactfilearea, + string $artifactfilename, + string $artifactfilepath, + int $artifactitemid, + string $artifactsha256sum, + bool $shouldfail ): void { - if ($shouldFail) { + if ($shouldfail) { $this->expectException(\invalid_parameter_exception::class); } process_uploaded_artifact::execute( $jobid, - $artifact_component, - $artifact_contextid, - $artifact_userid, - $artifact_filearea, - $artifact_filename, - $artifact_filepath, - $artifact_itemid, - $artifact_sha256sum + $artifactcomponent, + $artifactcontextid, + $artifactuserid, + $artifactfilearea, + $artifactfilename, + $artifactfilepath, + $artifactitemid, + $artifactsha256sum ); } diff --git a/tests/classes/external/update_job_status_test.php b/tests/classes/external/update_job_status_test.php index debcfc1..53a4d2d 100644 --- a/tests/classes/external/update_job_status_test.php +++ b/tests/classes/external/update_job_status_test.php @@ -37,7 +37,7 @@ class update_job_status_test extends \advanced_testcase { * * @return \stdClass Created mock objects */ - protected function generateMockQuiz(): \stdClass { + protected function generatemockquiz(): \stdClass { // Create course, course module and quiz $this->resetAfterTest(); @@ -47,7 +47,7 @@ protected function generateMockQuiz(): \stdClass { $quiz = $this->getDataGenerator()->create_module('quiz', [ 'course' => $course->id, 'grade' => 100.0, - 'sumgrades' => 100 + 'sumgrades' => 100, ]); return (object)[ @@ -144,8 +144,8 @@ public function test_wstoken_validation(): void { * @throws \invalid_parameter_exception * @throws \required_capability_exception */ - public function test_parameter_validation(string $jobid, string $status, bool $shouldFail): void { - if ($shouldFail) { + public function test_parameter_validation(string $jobid, string $status, bool $shouldfail): void { + if ($shouldfail) { $this->expectException(\invalid_parameter_exception::class); } @@ -181,7 +181,7 @@ public function parameter_data_provider(): array { * @throws \moodle_exception * @throws \required_capability_exception */ - public function test_update_job_status(string $originStatus, string $targetStatus, array $expected) { + public function test_update_job_status(string $originstatus, string $targetstatus, array $expected) { // Gain privileges $this->setAdminUser(); $_GET['wstoken'] = 'TEST-WS-TOKEN'; @@ -198,16 +198,16 @@ public function test_update_job_status(string $originStatus, string $targetStatu 'TEST-WS-TOKEN', [], [], - $originStatus + $originstatus ); // Ensure job is in the expected state - $this->assertSame($originStatus, $job->get_status()); + $this->assertSame($originstatus, $job->get_status()); // Execute the external function and check the result $result = update_job_status::execute( $job->get_jobid(), - $targetStatus + $targetstatus ); $this->assertSame($expected, $result, 'Invalid webservice answer'); } diff --git a/version.php b/version.php index c5c83a3..0acb131 100644 --- a/version.php +++ b/version.php @@ -29,5 +29,5 @@ $plugin->version = 2024021902; $plugin->requires = 2022112800; $plugin->supported = [401, 403]; -//$plugin->incompatible = 402; +// $plugin->incompatible = 402; $plugin->maturity = MATURITY_STABLE;