Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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  /**
  18   * Unit tests for core\content\exportable_items\exportable_stored_file.
  19   *
  20   * @package     core
  21   * @category    test
  22   * @copyright   2020 Andrew Nicols <andrew@nicols.co.uk>
  23   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  declare(strict_types=1);
  27  
  28  namespace core\content\export\exportable_items;
  29  
  30  use advanced_testcase;
  31  use context;
  32  use context_system;
  33  use core\content\export\zipwriter;
  34  use stdClass;
  35  use stored_file;
  36  
  37  /**
  38   * Unit tests for the `exportable_stored_file` export item class.
  39   *
  40   * @coversDefaultClass \core\content\exportable_items\exportable_stored_file
  41   */
  42  class exportable_stored_file_test extends advanced_testcase {
  43  
  44      /**
  45       * Ensure that the create_from_area_params function returns an array.
  46       */
  47      public function test_create_from_area_params_no_files(): void {
  48          $exportables = exportable_stored_file::create_from_area_params(
  49              context_system::instance(),
  50              'fake',
  51              'filearea',
  52              null
  53          );
  54  
  55          $this->assertIsArray($exportables);
  56          $this->assertCount(0, $exportables);
  57      }
  58  
  59      /**
  60       * Ensure that the create_from_area_params function returns a set of exportable_stored_file items, for all itemids.
  61       */
  62      public function test_create_from_area_params_no_itemid(): void {
  63          $this->resetAfterTest(true);
  64  
  65          // Setup for test.
  66          $user = $this->getDataGenerator()->create_user();
  67          $context = context_system::instance();
  68          $component = 'fake';
  69          $filearea = 'myfirstfilearea';
  70  
  71          $files1 = $this->create_files(context_system::instance(), $component, $filearea, 1);
  72          $files2 = $this->create_files(context_system::instance(), $component, $filearea, 2);
  73          $files3 = $this->create_files(context_system::instance(), $component, $filearea, 3);
  74          $files = array_values(array_merge($files1, $files2, $files3));
  75  
  76          $exportables = exportable_stored_file::create_from_area_params($context, $component, $filearea, null);
  77  
  78          $this->assertIsArray($exportables);
  79          $this->assertCount(3, $exportables);
  80  
  81          // There should be three exportables. These are listed in order of itemid.
  82          for ($i = 0; $i < 3; $i++) {
  83              $exportable = $exportables[$i];
  84              $file = $files[$i];
  85  
  86              $this->assertInstanceOf(exportable_stored_file::class, $exportable);
  87              $this->assert_exportable_matches_file($component, $user, $context, $filearea, '', $file, $exportable);
  88          }
  89  
  90      }
  91  
  92      /**
  93       * Ensure that the create_from_area_params function returns a set of exportable_stored_file items, for the requested
  94       * itemid
  95       */
  96      public function test_create_from_area_params_specified_itemid(): void {
  97          $this->resetAfterTest(true);
  98  
  99          // Setup for test.
 100          $user = $this->getDataGenerator()->create_user();
 101          $context = context_system::instance();
 102          $component = 'fake';
 103          $filearea = 'myfirstfilearea';
 104  
 105          $files1 = $this->create_files(context_system::instance(), $component, $filearea, 1);
 106          $files2 = $this->create_files(context_system::instance(), $component, $filearea, 2);
 107          $files3 = $this->create_files(context_system::instance(), $component, $filearea, 3);
 108  
 109          $exportables = exportable_stored_file::create_from_area_params($context, $component, $filearea, 2);
 110  
 111          $this->assertIsArray($exportables);
 112          $this->assertCount(1, $exportables);
 113  
 114          // There is only one exportable.
 115          $exportable = array_shift($exportables);
 116          $this->assertInstanceOf(exportable_stored_file::class, $exportable);
 117  
 118          $file2 = reset($files2);
 119          $this->assert_exportable_matches_file($component, $user, $context, $filearea, '', $file2, $exportable);
 120      }
 121  
 122      /**
 123       * Ensure that the create_from_area_params function returns a set of exportable_stored_file items, for the requested
 124       * itemid
 125       */
 126      public function test_create_from_area_params_in_subdir(): void {
 127          $this->resetAfterTest(true);
 128  
 129          // Setup for test.
 130          $user = $this->getDataGenerator()->create_user();
 131          $context = context_system::instance();
 132          $component = 'fake';
 133          $filearea = 'myfirstfilearea';
 134          $subdir = 'a/path/to/my/subdir';
 135  
 136          $files1 = $this->create_files(context_system::instance(), $component, $filearea, 1);
 137          $files2 = $this->create_files(context_system::instance(), $component, $filearea, 2);
 138          $files3 = $this->create_files(context_system::instance(), $component, $filearea, 3);
 139  
 140          $exportables = exportable_stored_file::create_from_area_params($context, $component, $filearea, 2, 2, $subdir);
 141  
 142          $this->assertIsArray($exportables);
 143          $this->assertCount(1, $exportables);
 144  
 145          // There is only one exportable.
 146          $exportable = array_shift($exportables);
 147          $this->assertInstanceOf(exportable_stored_file::class, $exportable);
 148  
 149          $file2 = reset($files2);
 150          $this->assert_exportable_matches_file($component, $user, $context, $filearea, $subdir, $file2, $exportable);
 151      }
 152  
 153      /**
 154       * Create files for use in testing.
 155       *
 156       * @param   context $context
 157       * @param   string $component
 158       * @param   string $filearea
 159       * @param   int $itemid
 160       * @param   int $count
 161       * @return  stored_file[]
 162       */
 163      protected function create_files(context $context, string $component, string $filearea, int $itemid, int $count = 1): array {
 164          $fs = get_file_storage();
 165  
 166          $files = [];
 167          for ($i = 0; $i < $count; $i++) {
 168  
 169              $filepath = '/';
 170              for ($j = 0; $j < $i; $j++) {
 171                  $filepath .= "{$j}/";
 172              }
 173  
 174              $files[] = $fs->create_file_from_string(
 175                  (object) [
 176                      'contextid' => $context->id,
 177                      'component' => $component,
 178                      'filearea' => $filearea,
 179                      'filepath' => $filepath,
 180                      'filename' => "file.txt",
 181                      'itemid' => $itemid,
 182                  ],
 183                  "File content: {$i}"
 184              );
 185          }
 186  
 187          return $files;
 188      }
 189  
 190      /**
 191       * Assert that the supplied expotable matches the supplied file.
 192       *
 193       * @param   string $component
 194       * @param   stdClass $user
 195       * @param   context $context
 196       * @param   string $filearea
 197       * @param   string $subdir
 198       * @param   stored_file $file
 199       * @param   exportable_stored_file $exportable
 200       */
 201      protected function assert_exportable_matches_file(
 202          string $component,
 203          stdClass $user,
 204          context $context,
 205          string $filearea,
 206          string $subdir,
 207          stored_file $file,
 208          exportable_stored_file $exportable
 209      ): void {
 210          $archive = $this->getMockBuilder(zipwriter::class)
 211              ->setConstructorArgs([$this->getMockBuilder(\ZipStream\ZipStream::class)->getmock()])
 212              ->setMethods([
 213                  'add_file_from_stored_file',
 214              ])
 215              ->getMock();
 216  
 217          $this->assertEquals($file->get_filepath() . $file->get_filename(), $exportable->get_user_visible_name());
 218  
 219          $expectedfilepath = implode('/', array_filter([$subdir, $filearea, $file->get_filepath(), $file->get_filename()]));
 220          $expectedfilepath = preg_replace('#/+#', '/', $expectedfilepath);
 221  
 222          $archive->expects($this->once())
 223              ->method('add_file_from_stored_file')
 224              ->with(
 225                  $this->equalTo($context),
 226                  $this->equalTo($expectedfilepath),
 227                  $this->equalTo($file)
 228              );
 229  
 230          $exportable->add_to_archive($archive);
 231      }
 232  }