Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace mod_data;
  18  
  19  use context_module;
  20  use mod_data\local\exporter\csv_entries_exporter;
  21  use mod_data\local\exporter\ods_entries_exporter;
  22  use mod_data\local\exporter\utils;
  23  use mod_data\local\importer\csv_entries_importer;
  24  use zip_archive;
  25  
  26  /**
  27   * Unit tests for entries_importer and csv_entries_importer class.
  28   *
  29   * Also {@see entries_import_test} class which provides module tests for importing entries.
  30   *
  31   * @package    mod_data
  32   * @covers     \mod_data\local\importer\entries_importer
  33   * @covers     \mod_data\local\importer\csv_entries_importer
  34   * @copyright  2023 ISB Bayern
  35   * @author     Philipp Memmel
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class entries_importer_test extends \advanced_testcase {
  39  
  40      /**
  41       * Set up function.
  42       */
  43      protected function setUp(): void {
  44          parent::setUp();
  45  
  46          global $CFG;
  47          require_once($CFG->dirroot . '/mod/data/lib.php');
  48          require_once($CFG->dirroot . '/lib/datalib.php');
  49          require_once($CFG->dirroot . '/lib/csvlib.class.php');
  50          require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
  51          require_once($CFG->dirroot . '/mod/data/tests/generator/lib.php');
  52      }
  53  
  54      /**
  55       * Get the test data.
  56       * In this instance we are setting up database records to be used in the unit tests.
  57       *
  58       * @return array
  59       */
  60      protected function get_test_data(): array {
  61          $this->resetAfterTest(true);
  62  
  63          $generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
  64          $course = $this->getDataGenerator()->create_course();
  65          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
  66          $this->setUser($teacher);
  67          $student = $this->getDataGenerator()->create_and_enrol($course, 'student', array('username' => 'student'));
  68  
  69          $data = $generator->create_instance(array('course' => $course->id));
  70          $cm = get_coursemodule_from_instance('data', $data->id);
  71  
  72          // Add fields.
  73          $fieldrecord = new \stdClass();
  74          $fieldrecord->name = 'ID'; // Identifier of the records for testing.
  75          $fieldrecord->type = 'number';
  76          $generator->create_field($fieldrecord, $data);
  77  
  78          $fieldrecord->name = 'Param2';
  79          $fieldrecord->type = 'text';
  80          $generator->create_field($fieldrecord, $data);
  81  
  82          $fieldrecord->name = 'filefield';
  83          $fieldrecord->type = 'file';
  84          $generator->create_field($fieldrecord, $data);
  85  
  86          $fieldrecord->name = 'picturefield';
  87          $fieldrecord->type = 'picture';
  88          $generator->create_field($fieldrecord, $data);
  89  
  90          return [
  91              'teacher' => $teacher,
  92              'student' => $student,
  93              'data' => $data,
  94              'cm' => $cm,
  95          ];
  96      }
  97  
  98      /**
  99       * Test importing files from zip archive.
 100       *
 101       * @covers \mod_data\local\importer\entries_importer::get_file_content_from_zip
 102       * @covers \mod_data\local\importer\entries_importer::get_data_file_content
 103       * @dataProvider get_file_content_from_zip_provider
 104       * @param array $files array of filenames and filecontents to test
 105       * @param mixed $datafilecontent the expected result returned by the method which is being tested here
 106       */
 107      public function test_get_file_content_from_zip(array $files, mixed $datafilecontent): void {
 108          // First we need to create the zip file from the provided data.
 109          $tmpdir = make_request_directory();
 110          $zipfilepath = $tmpdir . '/entries_importer_test_tmp_' . time() . '.zip';
 111          $ziparchive = new zip_archive();
 112          $ziparchive->open($zipfilepath);
 113          foreach ($files as $file) {
 114              $localname = empty($file['subdir']) ? $file['filename'] : $file['subdir'] . '/' . $file['filename'];
 115              $ziparchive->add_file_from_string($localname, $file['filecontent']);
 116          }
 117          $ziparchive->close();
 118  
 119          // We now created a zip archive according to the data provider's data. We now can test the importer.
 120          $importer = new csv_entries_importer($zipfilepath, 'testzip.zip');
 121          foreach ($files as $file) {
 122              $subdir = empty($file['subdir']) ? '' : $file['subdir'];
 123              $this->assertEquals($file['filecontent'], $importer->get_file_content_from_zip($file['filename'], $subdir));
 124          }
 125  
 126          // Test the method to retrieve the datafile content.
 127          $this->assertEquals($datafilecontent, $importer->get_data_file_content());
 128          unlink($zipfilepath);
 129      }
 130  
 131      /**
 132       * Data provider method for self::test_get_file_content_from_zip.
 133       *
 134       * @return array data for testing
 135       */
 136      public function get_file_content_from_zip_provider(): array {
 137          return [
 138              'some files in the zip archive' => [
 139                  'files' => [
 140                      [
 141                          'filename' => 'datafile.csv',
 142                          'filecontent' => 'some,csv,data'
 143                      ],
 144                      [
 145                          'filename' => 'testfile.txt',
 146                          'filecontent' => 'somecontent',
 147                          'subdir' => 'files'
 148                      ],
 149                      [
 150                          'filename' => 'testfile2.txt',
 151                          'filecontent' => 'someothercontent',
 152                          'subdir' => 'testsubdir'
 153                      ]
 154                  ],
 155                  // Should be identical with filecontent of 'datafile.csv' above.
 156                  'datafilecontent' => 'some,csv,data'
 157              ],
 158              'wrongly placed data file' => [
 159                  'files' => [
 160                      [
 161                          'filename' => 'datafile.csv',
 162                          'filecontent' => 'some,csv,data',
 163                          'subdir' => 'wrongsubdir'
 164                      ],
 165                      [
 166                          'filename' => 'testfile.txt',
 167                          'filecontent' => 'somecontent',
 168                          'subdir' => 'files'
 169                      ],
 170                      [
 171                          'filename' => 'testfile2.txt',
 172                          'filecontent' => 'someothercontent',
 173                          'subdir' => 'testsubdir'
 174                      ]
 175                  ],
 176                  // Data file is not in the root directory, though no content should be retrieved.
 177                  'datafilecontent' => false
 178              ],
 179              'two data files where only one is allowed' => [
 180                  'files' => [
 181                      [
 182                          'filename' => 'datafile.csv',
 183                          'filecontent' => 'some,csv,data',
 184                      ],
 185                      [
 186                          'filename' => 'anothercsvfile.csv',
 187                          'filecontent' => 'some,other,csv,data',
 188                      ],
 189                      [
 190                          'filename' => 'testfile.txt',
 191                          'filecontent' => 'somecontent',
 192                          'subdir' => 'files'
 193                      ],
 194                      [
 195                          'filename' => 'testfile2.txt',
 196                          'filecontent' => 'someothercontent',
 197                          'subdir' => 'testsubdir'
 198                      ]
 199                  ],
 200                  // There are two data files in the zip root, so the data cannot be imported.
 201                  'datafilecontent' => false
 202              ],
 203          ];
 204      }
 205  }