MDL-69549 core: Add context export API
[moodle.git] / lib / tests / content / export / exportable_items / exportable_stored_file_test.php
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/>.
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  */
26 declare(strict_types=1);
28 namespace core\content\export\exportable_items;
30 use advanced_testcase;
31 use context;
32 use context_system;
33 use core\content\export\zipwriter;
34 use stdClass;
35 use stored_file;
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 {
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         );
55         $this->assertIsArray($exportables);
56         $this->assertCount(0, $exportables);
57     }
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);
65         // Setup for test.
66         $user = $this->getDataGenerator()->create_user();
67         $context = context_system::instance();
68         $component = 'fake';
69         $filearea = 'myfirstfilearea';
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));
76         $exportables = exportable_stored_file::create_from_area_params($context, $component, $filearea, null);
78         $this->assertIsArray($exportables);
79         $this->assertCount(3, $exportables);
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];
86             $this->assertInstanceOf(exportable_stored_file::class, $exportable);
87             $this->assert_exportable_matches_file($component, $user, $context, $filearea, '', $file, $exportable);
88         }
90     }
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);
99         // Setup for test.
100         $user = $this->getDataGenerator()->create_user();
101         $context = context_system::instance();
102         $component = 'fake';
103         $filearea = 'myfirstfilearea';
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);
109         $exportables = exportable_stored_file::create_from_area_params($context, $component, $filearea, 2);
111         $this->assertIsArray($exportables);
112         $this->assertCount(1, $exportables);
114         // There is only one exportable.
115         $exportable = array_shift($exportables);
116         $this->assertInstanceOf(exportable_stored_file::class, $exportable);
118         $file2 = reset($files2);
119         $this->assert_exportable_matches_file($component, $user, $context, $filearea, '', $file2, $exportable);
120     }
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);
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';
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);
140         $exportables = exportable_stored_file::create_from_area_params($context, $component, $filearea, 2, 2, $subdir);
142         $this->assertIsArray($exportables);
143         $this->assertCount(1, $exportables);
145         // There is only one exportable.
146         $exportable = array_shift($exportables);
147         $this->assertInstanceOf(exportable_stored_file::class, $exportable);
149         $file2 = reset($files2);
150         $this->assert_exportable_matches_file($component, $user, $context, $filearea, $subdir, $file2, $exportable);
151     }
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();
166         $files = [];
167         for ($i = 0; $i < $count; $i++) {
169             $filepath = '/';
170             for ($j = 0; $j < $i; $j++) {
171                 $filepath .= "{$j}/";
172             }
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         }
187         return $files;
188     }
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();
217         $this->assertEquals($file->get_filepath() . $file->get_filename(), $exportable->get_user_visible_name());
219         $expectedfilepath = implode('/', array_filter([$subdir, $filearea, $file->get_filepath(), $file->get_filename()]));
220         $expectedfilepath = preg_replace('#/+#', '/', $expectedfilepath);
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             );
230         $exportable->add_to_archive($archive);
231     }