ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç home/smkb8269/public_html/lms.smk-almanshuriyah.sch.id/mod/data/tests/entries_export_test.php000064400000026512152267131660026354 0ustar00. namespace mod_data; use context_module; use mod_data\local\exporter\csv_entries_exporter; use mod_data\local\exporter\ods_entries_exporter; use mod_data\local\exporter\utils; /** * Unit tests for exporting entries. * * @package mod_data * @copyright 2023 ISB Bayern * @author Philipp Memmel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class entries_export_test extends \advanced_testcase { /** * Get the test data. * * In this instance we are setting up database records to be used in the unit tests. * * @return array of test instances */ protected function get_test_data(): array { $this->resetAfterTest(true); /** @var \mod_data_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); $course = $this->getDataGenerator()->create_course(); $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); $this->setUser($teacher); $student = $this->getDataGenerator()->create_and_enrol($course, 'student', ['username' => 'student']); $data = $generator->create_instance(['course' => $course->id]); $cm = get_coursemodule_from_instance('data', $data->id); // Add fields. $fieldrecord = new \stdClass(); $fieldrecord->name = 'numberfield'; // Identifier of the records for testing. $fieldrecord->type = 'number'; $numberfield = $generator->create_field($fieldrecord, $data); $fieldrecord->name = 'textfield'; $fieldrecord->type = 'text'; $textfield = $generator->create_field($fieldrecord, $data); $fieldrecord->name = 'filefield1'; $fieldrecord->type = 'file'; $filefield1 = $generator->create_field($fieldrecord, $data); $fieldrecord->name = 'filefield2'; $fieldrecord->type = 'file'; $filefield2 = $generator->create_field($fieldrecord, $data); $fieldrecord->name = 'picturefield'; $fieldrecord->type = 'picture'; $picturefield = $generator->create_field($fieldrecord, $data); $contents[$numberfield->field->id] = '3'; $contents[$textfield->field->id] = 'a simple text'; $contents[$filefield1->field->id] = 'samplefile.png'; $contents[$filefield2->field->id] = 'samplefile.png'; $contents[$picturefield->field->id] = ['picturefile.png', 'this picture shows something']; $generator->create_entry($data, $contents); return [ 'teacher' => $teacher, 'student' => $student, 'data' => $data, 'cm' => $cm, ]; } /** * Tests the exporting of the content of a mod_data instance by using the csv_entries_exporter. * * It also includes more general testing of the functionality of the entries_exporter the csv_entries_exporter * is inheriting from. * * @covers \mod_data\local\exporter\entries_exporter * @covers \mod_data\local\exporter\entries_exporter::get_records_count() * @covers \mod_data\local\exporter\entries_exporter::send_file() * @covers \mod_data\local\exporter\csv_entries_exporter * @covers \mod_data\local\exporter\utils::data_exportdata */ public function test_export_csv(): void { global $DB; [ 'data' => $data, 'cm' => $cm, ] = $this->get_test_data(); $exporter = new csv_entries_exporter(); $exporter->set_export_file_name('testexportfile'); $fieldrecords = $DB->get_records('data_fields', ['dataid' => $data->id], 'id'); $fields = []; foreach ($fieldrecords as $fieldrecord) { $fields[] = data_get_field($fieldrecord, $data); } // We select all fields. $selectedfields = array_map(fn($field) => $field->field->id, $fields); $currentgroup = groups_get_activity_group($cm); $context = context_module::instance($cm->id); $exportuser = false; $exporttime = false; $exportapproval = false; $tags = false; // We first test the export without exporting files. // This means file and picture fields will be exported, but only as text (which is the filename), // so we will receive a csv export file. $includefiles = false; utils::data_exportdata($data->id, $fields, $selectedfields, $exporter, $currentgroup, $context, $exportuser, $exporttime, $exportapproval, $tags, $includefiles); $this->assertEquals(file_get_contents(self::get_fixture_path(__NAMESPACE__, 'test_data_export_without_files.csv')), $exporter->send_file(false)); $this->assertEquals(1, $exporter->get_records_count()); // We now test the export including files. This will generate a zip archive. $includefiles = true; $exporter = new csv_entries_exporter(); $exporter->set_export_file_name('testexportfile'); utils::data_exportdata($data->id, $fields, $selectedfields, $exporter, $currentgroup, $context, $exportuser, $exporttime, $exportapproval, $tags, $includefiles); // We now write the zip archive temporary to disc to be able to parse it and assert it has the correct structure. $tmpdir = make_request_directory(); file_put_contents($tmpdir . '/testexportarchive.zip', $exporter->send_file(false)); $ziparchive = new \zip_archive(); $ziparchive->open($tmpdir . '/testexportarchive.zip'); $expectedfilecontents = [ // The test generator for mod_data uses a copy of field/picture/pix/sample.png as sample file content for the // file stored in a file and picture field. // So we expect that this file has to have the same content as sample.png. // Also, the default value for the subdirectory in the zip archive containing the files is 'files/'. 'files/samplefile.png' => 'mod/data/field/picture/pix/sample.png', 'files/samplefile_1.png' => 'mod/data/field/picture/pix/sample.png', 'files/picturefile.png' => 'mod/data/field/picture/pix/sample.png', // By checking that the content of the exported csv is identical to the fixture file it is verified // that the filenames in the csv file correspond to the names of the exported file. // It also verifies that files with identical file names in different fields (or records) will be numbered // automatically (samplefile.png, samplefile_1.png, ...). 'testexportfile.csv' => self::get_fixture_path(__NAMESPACE__, 'test_data_export_with_files.csv'), ]; for ($i = 0; $i < $ziparchive->count(); $i++) { // We here iterate over all files in the zip archive and check if their content is identical to the files // in the $expectedfilecontents array. $filestream = $ziparchive->get_stream($i); $fileinfo = $ziparchive->get_info($i); $filecontent = fread($filestream, $fileinfo->size); $this->assertEquals(file_get_contents($expectedfilecontents[$fileinfo->pathname]), $filecontent); fclose($filestream); } $ziparchive->close(); unlink($tmpdir . '/testexportarchive.zip'); } /** * Tests specific ODS exporting functionality. * * @covers \mod_data\local\exporter\ods_entries_exporter * @covers \mod_data\local\exporter\utils::data_exportdata */ public function test_export_ods(): void { global $DB; [ 'data' => $data, 'cm' => $cm, ] = $this->get_test_data(); $exporter = new ods_entries_exporter(); $exporter->set_export_file_name('testexportfile'); $fieldrecords = $DB->get_records('data_fields', ['dataid' => $data->id], 'id'); $fields = []; foreach ($fieldrecords as $fieldrecord) { $fields[] = data_get_field($fieldrecord, $data); } // We select all fields. $selectedfields = array_map(fn($field) => $field->field->id, $fields); $currentgroup = groups_get_activity_group($cm); $context = context_module::instance($cm->id); $exportuser = false; $exporttime = false; $exportapproval = false; $tags = false; // We first test the export without exporting files. // This means file and picture fields will be exported, but only as text (which is the filename), // so we will receive an ods export file. $includefiles = false; utils::data_exportdata($data->id, $fields, $selectedfields, $exporter, $currentgroup, $context, $exportuser, $exporttime, $exportapproval, $tags, $includefiles); $odsrows = $this->get_ods_rows_content($exporter->send_file(false)); // Check, if the headings match with the first row of the ods file. $i = 0; foreach ($fields as $field) { $this->assertEquals($field->field->name, $odsrows[0][$i]); $i++; } // Check, if the values match with the field values. $this->assertEquals('3', $odsrows[1][0]); $this->assertEquals('a simple text', $odsrows[1][1]); $this->assertEquals('samplefile.png', $odsrows[1][2]); $this->assertEquals('samplefile.png', $odsrows[1][3]); $this->assertEquals('picturefile.png', $odsrows[1][4]); // As the logic of renaming the files and building a zip archive is implemented in entries_exporter class, we do // not need to test this for the ods_entries_exporter, because entries_export_test::test_export_csv already does this. } /** * Helper function to extract the text data as row arrays from an ODS document. * * @param string $content the file content * @return array two-dimensional row/column array with the text content of the first spreadsheet */ private function get_ods_rows_content(string $content): array { $file = tempnam(make_request_directory(), 'ods_'); $filestream = fopen($file, "w"); fwrite($filestream, $content); $reader = new \OpenSpout\Reader\ODS\Reader(); $reader->open($file); /** @var \OpenSpout\Reader\ODS\Sheet[] $sheets */ $sheets = $reader->getSheetIterator(); $rowscellsvalues = []; foreach ($sheets as $sheet) { /** @var \OpenSpout\Common\Entity\Row[] $rows */ $rows = $sheet->getRowIterator(); foreach ($rows as $row) { $cellvalues = []; foreach ($row->getCells() as $cell) { $cellvalues[] = $cell->getValue(); } $rowscellsvalues[] = $cellvalues; } } return $rowscellsvalues; } }