ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilTestArchiver.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
26 
39 {
40  #region Constants / Config
41 
42  public const DIR_SEP = '/';
43 
44  public const HTML_SUBMISSION_FILENAME = 'test_submission.html';
45  public const PASS_MATERIALS_PATH_COMPONENT = 'materials';
46  public const QUESTION_PATH_COMPONENT_PREFIX = 'q_';
47 
48  public const TEST_BEST_SOLUTION_PATH_COMPONENT = 'best_solution';
49  public const HTML_BEST_SOLUTION_FILENAME = 'best_solution.html';
50  public const TEST_MATERIALS_PATH_COMPONENT = 'materials';
51 
52  protected const TEST_RESULT_FILENAME = 'test_result.html';
53 
54  public const TEST_OVERVIEW_HTML_FILENAME = 'results_overview_html_v';
55  public const TEST_OVERVIEW_HTML_POSTFIX = '.html';
56 
57  public const LOG_DTSGROUP_FORMAT = 'D M j G:i:s T Y';
58  public const LOG_ADDITION_STRING = ' Adding ';
59  public const LOG_CREATION_STRING = ' Creating ';
60  public const LOG_UPDATE_STRING = ' Updating ';
61  public const LOG_DELETION_STRING = ' Deleting ';
62 
63  public const TEST_LOG_FILENAME = 'test.log';
64  public const DATA_INDEX_FILENAME = 'data_index.csv';
65  public const ARCHIVE_LOG = 'archive.log';
66 
67  public const EXPORT_DIRECTORY = 'archive_exports';
68 
69  #endregion
70 
71  /*
72  * Test-Archive Schema:
73  *
74  * <external directory>/<client>/tst_data/archive/tst_<obj_id>/
75  * - archive_data_index.dat
76  * - archive_log.log
77  *
78  * - test_log.log
79  *
80  * - test_results_v<n>.pdf
81  * - test_results_v<n>.csv
82  *
83  * -> best_solution/
84  * best_solution_v<n>.pdf
85  * -> /materials/q_<question_fi>/<n>_<filename>
86  *
87  * -> <year>/<month>/<day>/<ActiveFi>_<Pass>[_<Lastname>][_<Firstname>][_<Matriculation>]/
88  * -> test_submission.pdf
89  * -> test_submission.html
90  * -> test_submission.sig (et al)
91  * -> test_result_v<n>.pdf
92  * -> /materials_v<n>/<question_fi>/<n>_<filename>
93  */
94 
95  #region Properties
96 
98  protected $client_id;
99  protected $test_obj_id;
100  protected $test_ref_id;
102 
103  protected ilLanguage $lng;
104  protected ilDBInterface $db;
105  protected ilCtrl $ctrl;
106  protected ilObjUser $user;
107  protected ilTabsGUI $tabs;
112  protected ilAccess $access;
116 
118 
122  protected $participantData;
123 
124  private \ILIAS\ResourceStorage\Services $irss;
125 
126  #endregion
127 
128  public function __construct(int $test_obj_id, ?int $test_ref_id = null)
129  {
131  global $DIC;
132  $this->lng = $DIC['lng'];
133  $this->db = $DIC['ilDB'];
134  $this->ctrl = $DIC['ilCtrl'];
135  $this->user = $DIC['ilUser'];
136  $this->tabs = $DIC['ilTabs'];
137  $this->toolbar = $DIC['ilToolbar'];
138  $this->tpl = $DIC['tpl'];
139  $this->ui_factory = $DIC['ui.factory'];
140  $this->ui_renderer = $DIC['ui.renderer'];
141  $this->access = $DIC['ilAccess'];
142  $this->testrequest = $DIC->test()->internal()->request();
143  $this->http = $DIC->http();
144  $this->refinery = $DIC->refinery();
145  $this->irss = $DIC->resourceStorage();
146 
147  $ilias = $DIC['ilias'];
148 
149  $this->html_generator = new ilTestHTMLGenerator();
150 
151  $this->external_directory_path = $ilias->ini_ilias->readVariable('clients', 'datadir');
152  $this->client_id = $ilias->client_id;
153  $this->test_obj_id = $test_obj_id;
154  $this->test_ref_id = $test_ref_id;
155 
156  $this->archive_data_index = $this->readArchiveDataIndex();
157 
158  $this->participantData = null;
159  }
160 
165  {
166  return $this->participantData;
167  }
168 
173  {
174  $this->participantData = $participantData;
175  }
176 
177  #region API methods
178 
188  public function handInParticipantQuestionMaterial($active_fi, $pass, $question_fi, $original_filename, $file_path)
189  {
191  $this->ensurePassDataDirectoryIsAvailable($active_fi, $pass);
192 
193  $pass_question_directory = $this->getPassDataDirectory($active_fi, $pass)
194  . self::DIR_SEP . self::QUESTION_PATH_COMPONENT_PREFIX . $question_fi;
195  if (!is_dir($pass_question_directory)) {
196  mkdir($pass_question_directory, 0777, true);
197  }
198 
199  copy($file_path, $pass_question_directory . self::DIR_SEP . $original_filename);
200 
201  $this->logArchivingProcess(
202  date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING
203  . $pass_question_directory . self::DIR_SEP . $original_filename
204  );
205  }
206 
217  public function handInParticipantMisc($active_fi, $pass, $original_filename, $file_path)
218  {
220  $this->ensurePassDataDirectoryIsAvailable($active_fi, $pass);
221  $new_path = $this->getPassDataDirectory($active_fi, $pass) . self::DIR_SEP . $original_filename;
222  copy($file_path, $new_path);
223  $this->logArchivingProcess(date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING . $new_path);
224  }
225 
232  public function handInTestBestSolution($best_solution)
233  {
235 
236  $best_solution_path = $this->getTestArchive() . self::DIR_SEP . self::TEST_BEST_SOLUTION_PATH_COMPONENT;
237  if (!is_dir($best_solution_path)) {
238  mkdir($best_solution_path, 0777, true);
239  }
240 
241  $this->html_generator->generateHTML(
242  $best_solution,
243  $best_solution_path . self::DIR_SEP . self::HTML_BEST_SOLUTION_FILENAME
244  );
245 
246  $this->logArchivingProcess(
247  date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING
248  . $best_solution_path . self::DIR_SEP . self::HTML_BEST_SOLUTION_FILENAME
249  );
250 
251  $this->logArchivingProcess(
252  date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING . $best_solution_path
253  );
254  }
255 
261  public function handInParticipantUploadedResults($active_fi, $pass, $tst_obj){
262  $questions = $tst_obj->getQuestionsOfPass($active_fi, $pass);
263  foreach ($questions as $question) {
264  $question = $tst_obj->getQuestionDataset($question['question_fi']);
265  if ($question->type_tag === 'assFileUpload') {
267  $this->ensurePassDataDirectoryIsAvailable($active_fi, $pass);
268  $this->ensurePassMaterialsDirectoryIsAvailable($active_fi, $pass);
269  $pass_material_directory = $this->getPassMaterialsDirectory($active_fi, $pass);
270  $archive_folder = $pass_material_directory . self::DIR_SEP . $question->question_id . self::DIR_SEP;
271  if (!file_exists($archive_folder)) {
272  mkdir($archive_folder, 0777, true);
273  }
274  // TODO old Filesystem remove on ILIAS 10
275  $local_folder = CLIENT_WEB_DIR . '/assessment/tst_' . $tst_obj->test_id . self::DIR_SEP . $active_fi . self::DIR_SEP . $question->question_id . '/files/';
276  if (file_exists($local_folder)) {
277  $folder_content = scandir($local_folder);
278  $folder_content = array_diff($folder_content, array('.', '..'));
279  foreach ($folder_content as $file_name) {
280  if (preg_match('/file_(\d+)_(\d+)_(\d+)/', $file_name, $matches)){
281  if ($active_fi == intval($matches[1]) && $pass == $matches[2]){
282  $local_file= $local_folder . $file_name;
283  $target_destination = $archive_folder . $file_name;
284  copy($local_file, $target_destination);
285  $this->logArchivingProcess(date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING . $target_destination);
286  }
287  }
288  }
289  }
290  // IRSS
291  $resource_id = $tst_obj->getTextAnswer($active_fi, $question->question_id, $pass);
292  if ($resource_id == ''){
293  continue;
294  }
295  $irss_unique_id = $this->irss->manage()->find($resource_id);
296  if ($irss_unique_id != null){
297  $resource = $this->irss->manage()->getResource($irss_unique_id);
298  $information = $resource->getCurrentRevision()->getInformation();
299  $stream = $this->irss->consume()->stream($irss_unique_id);
300  // this feels unnecessary..
301  $file_stream = fopen($stream->getStream()->getMetadata('uri'), 'r');
302  $file_content = stream_get_contents($file_stream);
303  fclose($file_stream);
304  $target_destination = $archive_folder . $information->getTitle();
305  file_put_contents($target_destination, $file_content);
306  }
307  }
308  }
309  }
310 
318  public function handInBestSolutionQuestionMaterial($question_fi, $orginial_filename, $file_path)
319  {
321 
322  $best_solution_path = $this->getTestArchive() . self::DIR_SEP . self::TEST_BEST_SOLUTION_PATH_COMPONENT;
323  if (!is_dir($best_solution_path)) {
324  mkdir($best_solution_path, 0777, true);
325  }
326 
327  $materials_path = $best_solution_path . self::DIR_SEP . self::TEST_MATERIALS_PATH_COMPONENT;
328  if (!is_dir($materials_path)) {
329  mkdir($materials_path, 0777, true);
330  }
331 
332  $question_materials_path = $materials_path . self::DIR_SEP . self::QUESTION_PATH_COMPONENT_PREFIX . $question_fi;
333  if (!is_dir($question_materials_path)) {
334  mkdir($question_materials_path, 0777, true);
335  }
336 
337  copy($file_path, $question_materials_path . self::DIR_SEP . $orginial_filename);
338 
339  $this->logArchivingProcess(
340  date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING
341  . $question_materials_path . self::DIR_SEP . $orginial_filename
342  );
343  }
344 
354  public function handInTestResult($active_fi, $pass, $pdf_path)
355  {
357  $this->ensurePassDataDirectoryIsAvailable($active_fi, $pass);
358  $new_path = $this->getPassDataDirectory($active_fi, $pass) . self::DIR_SEP . self::TEST_RESULT_FILENAME;
359  copy($pdf_path, $new_path);
360  $this->logArchivingProcess(date(self::LOG_DTSGROUP_FORMAT) . self::LOG_ADDITION_STRING . $new_path);
361  }
362 
363  #endregion
364 
365  #region TestArchive
366  // The TestArchive lives here: <external directory>/<client>/tst_data/archive/tst_<obj_id>/
367 
373  protected function hasTestArchive(): bool
374  {
375  return is_dir($this->getTestArchive());
376  }
377 
381  protected function createArchiveForTest()
382  {
384  //mkdir( $this->getTestArchive(), 0777, true );
385  }
386 
392  protected function getTestArchive(): string
393  {
394  $test_archive_directory = $this->external_directory_path . self::DIR_SEP . $this->client_id . self::DIR_SEP . 'tst_data'
395  . self::DIR_SEP . 'archive' . self::DIR_SEP . 'tst_' . $this->test_obj_id;
396  return $test_archive_directory;
397  }
398 
406  protected function ensureTestArchiveIsAvailable()
407  {
408  if (!$this->hasTestArchive()) {
409  $this->createArchiveForTest();
410  }
411  return;
412  }
413 
419  public function updateTestArchive()
420  {
421  $query = 'SELECT * FROM ass_log WHERE obj_fi = ' . $this->db->quote($this->test_obj_id, 'integer');
422  $result = $this->db->query($query);
423 
424  $outfile_lines = '';
426  while ($row = $this->db->fetchAssoc($result)) {
427  $outfile_lines .= "\r\n" . implode("\t", $row);
428  }
429  file_put_contents($this->getTestArchive() . self::DIR_SEP . self::TEST_LOG_FILENAME, $outfile_lines);
430 
431  // Generate test pass overview
432  $test = new ilObjTest($this->test_obj_id, false);
433  if ($this->test_ref_id !== null) {
434  $test->setRefId($this->test_ref_id);
435  }
436 
437  $gui = new ilParticipantsTestResultsGUI(
438  $this->ctrl,
439  $this->lng,
440  $this->db,
441  $this->user,
442  $this->tabs,
443  $this->toolbar,
444  $this->tpl,
445  $this->ui_factory,
446  $this->ui_renderer,
448  $this->testrequest,
449  $this->http,
450  $this->refinery
451  );
452  $gui->setTestObj($test);
453 
454  $objectiveOrientedContainer = new ilTestObjectiveOrientedContainer();
455  $gui->setObjectiveParent($objectiveOrientedContainer);
456  $array_of_actives = array();
457  $participants = $test->getParticipants();
458 
459  foreach ($participants as $key => $value) {
460  $array_of_actives[] = $key;
461  }
462  $output_template = $gui->createUserResults(true, false, true, $array_of_actives);
463 
464  $filename = realpath($this->getTestArchive()) . self::DIR_SEP . 'participant_pass_overview.html';
465  $this->html_generator->generateHTML($output_template->get(), $filename);
466 
467  return;
468  }
469 
471  {
472  if (!$this->hasZipExportDirectory()) {
473  $this->createZipExportDirectory();
474  }
475  }
476 
482  public function hasZipExportDirectory(): bool
483  {
484  return is_dir($this->getZipExportDirectory());
485  }
486 
487  protected function createZipExportDirectory()
488  {
489  mkdir($this->getZipExportDirectory(), 0777, true);
490  }
491 
497  public function getZipExportDirectory(): string
498  {
499  return $this->external_directory_path . self::DIR_SEP . $this->client_id . self::DIR_SEP . 'tst_data'
500  . self::DIR_SEP . self::EXPORT_DIRECTORY . self::DIR_SEP . 'tst_' . $this->test_obj_id;
501  }
502 
508  public function compressTestArchive()
509  {
510  $this->updateTestArchive();
512 
513  $zip_output_path = $this->getZipExportDirectory();
514  $zip_output_filename = 'test_archive_obj_' . $this->test_obj_id . '_' . time() . '_.zip';
515 
516  ilFileUtils::zip($this->getTestArchive(), $zip_output_path . self::DIR_SEP . $zip_output_filename, true);
517  return;
518  }
519 
520  #endregion
521 
522  #region PassDataDirectory
523  // The pass data directory contains all data relevant for a participants pass.
524  // In addition to the test-archive-directory, this directory lives here:
525  // .../<year>/<month>/<day>/<ActiveFi>_<Pass>[_<Lastname>][_<Firstname>][_<Matriculation>]/
526  // Lastname, Firstname and Matriculation are not mandatory in the directory name.
527 
536  protected function hasPassDataDirectory($active_fi, $pass): bool
537  {
538  $pass_data_dir = $this->getPassDataDirectory($active_fi, $pass);
539  return is_dir($this->getPassDataDirectory($active_fi, $pass));
540  }
541 
550  protected function createPassDataDirectory($active_fi, $pass)
551  {
552  mkdir($this->getPassDataDirectory($active_fi, $pass), 0777, true);
553  return;
554  }
555 
556  private function buildPassDataDirectory($active_fi, $pass): ?string
557  {
558  foreach ($this->archive_data_index as $data_index_entry) {
559  if ($data_index_entry != null && $data_index_entry['identifier'] == $active_fi . '|' . $pass) {
560  array_shift($data_index_entry);
561  return $this->getTestArchive() . self::DIR_SEP . implode(self::DIR_SEP, $data_index_entry);
562  }
563  }
564 
565  return null;
566  }
567 
576  protected function getPassDataDirectory($active_fi, $pass): ?string
577  {
578  $pass_data_dir = $this->buildPassDataDirectory($active_fi, $pass);
579 
580  if ($pass_data_dir !== null) {
581  return $pass_data_dir;
582  }
583 
584  $test_obj = new ilObjTest($this->test_obj_id, false);
585  if ($test_obj->getAnonymity()) {
586  $firstname = 'anonym';
587  $lastname = '';
588  $matriculation = '0';
589  } else {
590  if ($this->getParticipantData()) {
591  $usr_data = $this->getParticipantData()->getUserDataByActiveId($active_fi);
592  $firstname = $usr_data['firstname'];
593  $lastname = $usr_data['lastname'];
594  $matriculation = $usr_data['matriculation'];
595  } else {
596 
597  $firstname = $this->user->getFirstname();
598  $lastname = $this->user->getLastname();
599  $matriculation = $this->user->getMatriculation();
600  }
601  }
602 
604  date(DATE_ISO8601),
605  $active_fi,
606  $pass,
607  $firstname,
608  $lastname,
609  $matriculation
610  );
611 
612  return $this->buildPassDataDirectory($active_fi, $pass);
613  }
614 
625  protected function ensurePassDataDirectoryIsAvailable($active_fi, $pass)
626  {
627  if (!$this->hasPassDataDirectory($active_fi, $pass)) {
628  $this->createPassDataDirectory($active_fi, $pass);
629  }
630  return;
631  }
632 
633  #endregion
634 
635  #region PassMaterialsDirectory
636 
645  protected function hasPassMaterialsDirectory($active_fi, $pass): bool
646  {
648  if (@is_dir($this->getPassMaterialsDirectory($active_fi, $pass))) {
649  return true;
650  }
651  return false;
652  }
653 
662  protected function createPassMaterialsDirectory($active_fi, $pass): string
663  {
664  // Data are taken from the current user as the implementation expects the first interaction of the pass
665  // takes place from the usage/behaviour of the current user.
666 
667  $user = $this->user;
668 
669  if ($this->getParticipantData()) {
670  $usrData = $this->getParticipantData()->getUserDataByActiveId($active_fi);
671  $user = new ilObjUser();
672  $user->setFirstname($usrData['firstname']);
673  $user->setLastname($usrData['lastname']);
674  $user->setMatriculation($usrData['matriculation']);
675  $user->setFirstname($usrData['firstname']);
676  }
677 
679  date('c'),
680  $active_fi,
681  $pass,
682  $user->getFirstname(),
683  $user->getLastname(),
684  $user->getMatriculation()
685  );
686  $material_directory = $this->getPassMaterialsDirectory($active_fi, $pass);
687  mkdir($material_directory, 0777, true);
688  return $material_directory;
689  }
690 
699  protected function getPassMaterialsDirectory($active_fi, $pass): string
700  {
701  $pass_data_directory = $this->getPassDataDirectory($active_fi, $pass);
702  return $pass_data_directory . self::DIR_SEP . self::PASS_MATERIALS_PATH_COMPONENT;
703  }
704 
714  protected function ensurePassMaterialsDirectoryIsAvailable($active_fi, $pass)
715  {
716  if (!$this->hasPassMaterialsDirectory($active_fi, $pass)) {
717  $this->createPassMaterialsDirectory($active_fi, $pass);
718  }
719  }
720 
721  #endregion
722 
728  protected function readArchiveDataIndex(): array
729  {
734  $data_index_file = $this->getTestArchive() . self::DIR_SEP . self::DATA_INDEX_FILENAME;
735 
736  $contents = array();
737 
739  if (@file_exists($data_index_file)) {
740  $lines = explode("\n", file_get_contents($data_index_file));
741  foreach ($lines as $line) {
742  if (strlen($line) === 0) {
743  continue;
744  }
745  $line_items = explode('|', $line);
746  $line_data = [];
747  $line_data['identifier'] = $line_items[0] . '|' . $line_items[1];
748  $line_data['yyyy'] = $line_items[2];
749  $line_data['mm'] = $line_items[3];
750  $line_data['dd'] = $line_items[4];
751  $line_data['directory'] = $line_items[5];
752  $contents[] = $line_data;
753  }
754  }
755  return $contents;
756  }
757 
770  protected function appendToArchiveDataIndex($date, $active_fi, $pass, $user_firstname, $user_lastname, $matriculation)
771  {
772  $line = $this->determinePassDataPath($date, $active_fi, $pass, $user_firstname, $user_lastname, $matriculation);
773 
774  $this->archive_data_index[] = $line;
775  $output_contents = '';
776 
777  foreach ($this->archive_data_index as $line_data) {
778  if ($line_data['identifier'] == "|") {
779  continue;
780  }
781  $output_contents .= implode('|', $line_data) . "\n";
782  }
783 
784  file_put_contents($this->getTestArchive() . self::DIR_SEP . self::DATA_INDEX_FILENAME, $output_contents);
785  $this->readArchiveDataIndex();
786  return;
787  }
788 
801  protected function determinePassDataPath($date, $active_fi, $pass, $user_firstname, $user_lastname, $matriculation): array
802  {
803  $date = date_create_from_format('Y-m-d\TH:i:sP', $date);
804  if (!$date) {
805  throw new Exception('Invalid date format. Expected ISO 8601 format.');
806  }
807 
808  $line = array(
809  'identifier' => $active_fi . '|' . $pass,
810  'yyyy' => date_format($date, 'Y'),
811  'mm' => date_format($date, 'm'),
812  'dd' => date_format($date, 'd'),
813  'directory' => $active_fi . '_' . $pass . '_' . $user_firstname . '_' . $user_lastname . '_' . $matriculation
814  );
815  return $line;
816  }
817 
825  protected function logArchivingProcess($message)
826  {
827  $archive = $this->getTestArchive() . self::DIR_SEP . self::ARCHIVE_LOG;
828  if (file_exists($archive)) {
829  $content = file_get_contents($archive) . "\n" . $message;
830  } else {
831  $content = $message;
832  }
833 
834  file_put_contents($archive, $content);
835  }
836 
845  protected function countFilesInDirectory($directory, $pattern = null): int
846  {
847  $filecount = 0;
848 
850  if ($handle = opendir($directory)) {
851  while (($file = readdir($handle)) !== false) {
852  if (!in_array($file, array( '.', '..' )) && !is_dir($directory . $file)) {
853  if ($pattern && strpos($file, $pattern) === 0) {
854  $filecount++;
855  }
856  }
857  }
858  }
859  return $filecount;
860  }
861 }
getPassDataDirectory($active_fi, $pass)
Returns the pass data directory.
Interface GlobalHttpState.
determinePassDataPath($date, $active_fi, $pass, $user_firstname, $user_lastname, $matriculation)
Determines the pass data path.
createArchiveForTest()
Creates the directory for the test archive.
ilParticipantsTestResultsGUI: ilTestEvaluationGUI ilParticipantsTestResultsGUI: ilAssQuestionPageGUI...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
GlobalHttpState $http
setMatriculation(string $a_str)
InternalRequestService $testrequest
createPassDataDirectory($active_fi, $pass)
Creates pass data directory.
countFilesInDirectory($directory, $pattern=null)
Returns the count of files in a directory, eventually matching the given, optional, pattern.
RefineryFactory $refinery
handInParticipantQuestionMaterial($active_fi, $pass, $question_fi, $original_filename, $file_path)
Hands in a particpants question material, such as an upload or other binary content.
getPassMaterialsDirectory($active_fi, $pass)
Returns the pass materials directory.
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
ilGlobalTemplateInterface $tpl
compressTestArchive()
Generate the test archive for download.
global $DIC
Definition: feed.php:28
readArchiveDataIndex()
Reads the archive data index.
static http()
Fetches the global http state from ILIAS.
__construct(VocabulariesInterface $vocabularies)
const QUESTION_PATH_COMPONENT_PREFIX
getZipExportDirectory()
Return the export directory, where zips are placed.
buildPassDataDirectory($active_fi, $pass)
appendToArchiveDataIndex($date, $active_fi, $pass, $user_firstname, $user_lastname, $matriculation)
Appends a line to the archive data index.
ensurePassDataDirectoryIsAvailable($active_fi, $pass)
Ensures the availability of the participant data directory.
string $key
Consumer key/client ID value.
Definition: System.php:193
handInBestSolutionQuestionMaterial($question_fi, $orginial_filename, $file_path)
Hands in a file related to a question in context of the best solution.
const CLIENT_WEB_DIR
Definition: constants.php:47
hasZipExportDirectory()
Returns if the export directory for zips exists.
handInParticipantUploadedResults($active_fi, $pass, $tst_obj)
hasTestArchive()
Returns if the archive directory structure for the test the object is created for exists...
$filename
Definition: buildRTE.php:78
Class that handles PDF generation for test and assessment.
setLastname(string $a_str)
Class ilTestArchiver.
getTestArchive()
Returns the (theoretical) path to the archive directory of the test, this object is created for...
ILIAS ResourceStorage Services $irss
hasPassDataDirectory($active_fi, $pass)
Checks if the directory for pass data is available.
hasPassMaterialsDirectory($active_fi, $pass)
Returns if the pass materials directory exists for a given pass.
createPassMaterialsDirectory($active_fi, $pass)
Creates pass materials directory.
static zip(string $a_dir, string $a_file, bool $compress_content=false)
const TEST_BEST_SOLUTION_PATH_COMPONENT
$message
Definition: xapiexit.php:32
ensurePassMaterialsDirectoryIsAvailable($active_fi, $pass)
Ensures the availability of the pass materials directory.
ensureTestArchiveIsAvailable()
Ensures the availability of the test archive directory.
handInTestBestSolution($best_solution)
Hands in the best solution for a test.
handInParticipantMisc($active_fi, $pass, $original_filename, $file_path)
Hands in a participants file, which is relevant for archiving but an unspecified type.
setFirstname(string $a_str)
ilTestHTMLGenerator $html_generator
setParticipantData($participantData)
logArchivingProcess($message)
Logs to the archive log.
updateTestArchive()
Replaces the test-log with the current one.
handInTestResult($active_fi, $pass, $pdf_path)
Hands in an individual test result for a pass.