on-demand release 4.0dev+
[moodle.git] / contentbank / tests / content_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  * Test for content bank contenttype class.
19  *
20  * @package    core_contentbank
21  * @category   test
22  * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 namespace core_contentbank;
28 use stdClass;
29 use context_system;
30 use contenttype_testable\contenttype as contenttype;
32 /**
33  * Test for content bank contenttype class.
34  *
35  * @package    core_contentbank
36  * @category   test
37  * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
38  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  * @coversDefaultClass \core_contentbank\content
40  *
41  */
42 class core_contenttype_content_testcase extends \advanced_testcase {
44     /**
45      * Setup to ensure that fixtures are loaded.
46      */
47     public static function setupBeforeClass(): void {
48         global $CFG;
50         require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
51         require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
52     }
54     /**
55      * Tests for behaviour of get_name().
56      *
57      * @covers ::get_name
58      */
59     public function test_get_name() {
60         $this->resetAfterTest();
62         // Create content.
63         $record = new stdClass();
64         $record->name = 'Test content';
65         $record->configdata = '';
67         $contenttype = new contenttype(context_system::instance());
68         $content = $contenttype->create_content($record);
69         $this->assertEquals($record->name, $content->get_name());
70     }
72     /**
73      * Data provider for test_set_name.
74      *
75      * @return  array
76      */
77     public function set_name_provider() {
78         return [
79             'Standard name' => ['New name', 'New name'],
80             'Name with digits' => ['Today is 17/04/2017', 'Today is 17/04/2017'],
81             'Name with symbols' => ['Follow us: @moodle', 'Follow us: @moodle'],
82             'Name with tags' => ['This is <b>bold</b>', 'This is bold'],
83             'Long name' => [str_repeat('a', 100), str_repeat('a', 100)],
84             'Too long name' => [str_repeat('a', 300), str_repeat('a', 255)],
85             'Empty name' => ['', 'Old name'],
86             'Blanks only' => ['  ', 'Old name'],
87         ];
88     }
90     /**
91      * Tests for 'set_name' behaviour.
92      *
93      * @dataProvider    set_name_provider
94      * @param   string  $newname    The name to set
95      * @param   string   $expected   The name result
96      *
97      * @covers ::set_name
98      */
99     public function test_set_name(string $newname, string $expected) {
100         global $DB;
102         $this->resetAfterTest();
103         $this->setAdminUser();
105         $oldname = "Old name";
106         $context = context_system::instance();
108         // Create content.
109         $record = new stdClass();
110         $record->name = $oldname;
112         $contenttype = new contenttype($context);
113         $content = $contenttype->create_content($record);
114         $this->assertEquals($oldname, $content->get_name());
116         $content->set_name($newname);
117         $this->assertEquals($expected, $content->get_name());
119         $record = $DB->get_record('contentbank_content', ['id' => $content->get_id()]);
120         $this->assertEquals($expected, $record->name);
121     }
123     /**
124      * Tests for behaviour of get_content_type().
125      *
126      * @covers ::get_content_type
127      */
128     public function test_get_content_type() {
129         $this->resetAfterTest();
131         // Create content.
132         $record = new stdClass();
133         $record->name = 'Test content';
134         $record->configdata = '';
136         $contenttype = new contenttype(context_system::instance());
137         $content = $contenttype->create_content($record);
138         $this->assertEquals('contenttype_testable', $content->get_content_type());
139     }
141     /**
142      * Tests for 'configdata' behaviour.
143      *
144      * @covers ::set_configdata
145      */
146     public function test_configdata_changes() {
147         $this->resetAfterTest();
149         $configdata = "{img: 'icon.svg'}";
151         // Create content.
152         $record = new stdClass();
153         $record->configdata = $configdata;
155         $contenttype = new contenttype(context_system::instance());
156         $content = $contenttype->create_content($record);
157         $this->assertEquals($configdata, $content->get_configdata());
159         $configdata = "{alt: 'Name'}";
160         $content->set_configdata($configdata);
161         $this->assertEquals($configdata, $content->get_configdata());
162     }
164     /**
165      * Tests for 'set_contextid' behaviour.
166      *
167      * @covers ::set_contextid
168      */
169     public function test_set_contextid() {
170         $this->resetAfterTest();
171         $this->setAdminUser();
172         $context = context_system::instance();
173         $course = $this->getDataGenerator()->create_course();
174         $newcontext = \context_course::instance($course->id);
176         // Add some content to the content bank.
177         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
178         $contents = $generator->generate_contentbank_data('contenttype_testable', 3, 0, $context);
179         $content = reset($contents);
181         $oldcontextid = $content->get_contextid();
183         $file = $content->get_file();
184         $this->assertEquals($oldcontextid, $file->get_contextid());
185         $this->assertEquals($context->id, $oldcontextid);
186         $this->assertNotEquals($newcontext->id, $oldcontextid);
188         $content->set_contextid($newcontext->id);
189         $file = $content->get_file();
191         $this->assertEquals($newcontext->id, $content->get_contextid());
192         $this->assertEquals($newcontext->id, $file->get_contextid());
193     }
195     /**
196      * Tests for set_visibility behaviour
197      *
198      * @covers ::set_visibility
199      */
200     public function test_set_visibility() {
201         $this->resetAfterTest();
202         $this->setAdminUser();
203         $context = context_system::instance();
204         $oldvisibility = content::VISIBILITY_PUBLIC;
205         $newvisibility = content::VISIBILITY_UNLISTED;
206         $illegalvisibility = -1;
208         $record = new stdClass();
209         $record->visibility = $oldvisibility;
210         $contenttype = new contenttype($context);
211         $content = $contenttype->create_content($record);
213         $this->assertEquals($oldvisibility, $content->get_visibility());
215         $content->set_visibility($newvisibility);
217         $this->assertEquals($newvisibility, $content->get_visibility());
219         $content->set_visibility($illegalvisibility);
221         $this->assertEquals($newvisibility, $content->get_visibility());
222     }
224     /**
225      * Tests for 'import_file' behaviour when replacing a file.
226      *
227      * @covers ::import_file
228      */
229     public function test_import_file_replace(): void {
230         global $USER;
231         $this->resetAfterTest();
232         $this->setAdminUser();
233         $context = context_system::instance();
235         // Add some content to the content bank.
236         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
237         $contents = $generator->generate_contentbank_data('contenttype_testable', 3, 0, $context);
238         $content = reset($contents);
240         $originalfile = $content->get_file();
242         // Create a dummy file.
243         $filerecord = array(
244             'contextid' => $context->id,
245             'component' => 'contentbank',
246             'filearea' => 'draft',
247             'itemid' => $content->get_id(),
248             'filepath' => '/',
249             'filename' => 'example.txt'
250         );
251         $fs = get_file_storage();
252         $file = $fs->create_file_from_string($filerecord, 'Dummy content ');
254         $importedfile = $content->import_file($file);
256         $this->assertEquals($originalfile->get_filename(), $importedfile->get_filename());
257         $this->assertEquals($originalfile->get_filearea(), $importedfile->get_filearea());
258         $this->assertEquals($originalfile->get_filepath(), $importedfile->get_filepath());
259         $this->assertEquals($originalfile->get_mimetype(), $importedfile->get_mimetype());
261         $this->assertEquals($file->get_userid(), $importedfile->get_userid());
262         $this->assertEquals($file->get_contenthash(), $importedfile->get_contenthash());
263     }
265     /**
266      * Tests for 'import_file' behaviour when uploading a new file.
267      *
268      * @covers ::import_file
269      */
270     public function test_import_file_upload(): void {
271         global $USER;
272         $this->resetAfterTest();
273         $this->setAdminUser();
274         $context = context_system::instance();
276         $type = new contenttype($context);
277         $record = (object)[
278             'name' => 'content name',
279             'usercreated' => $USER->id,
280         ];
281         $content = $type->create_content($record);
283         // Create a dummy file.
284         $filerecord = array(
285             'contextid' => $context->id,
286             'component' => 'contentbank',
287             'filearea' => 'draft',
288             'itemid' => $content->get_id(),
289             'filepath' => '/',
290             'filename' => 'example.txt'
291         );
292         $fs = get_file_storage();
293         $file = $fs->create_file_from_string($filerecord, 'Dummy content ');
295         $importedfile = $content->import_file($file);
297         $this->assertEquals($file->get_filename(), $importedfile->get_filename());
298         $this->assertEquals($file->get_userid(), $importedfile->get_userid());
299         $this->assertEquals($file->get_mimetype(), $importedfile->get_mimetype());
300         $this->assertEquals($file->get_contenthash(), $importedfile->get_contenthash());
301         $this->assertEquals('public', $importedfile->get_filearea());
302         $this->assertEquals('/', $importedfile->get_filepath());
304         $contentfile = $content->get_file($file);
305         $this->assertEquals($importedfile->get_id(), $contentfile->get_id());
306     }
308     /**
309      * Tests for 'get_content_type_instance'
310      *
311      * @covers ::get_content_type_instance
312      */
313     public function test_get_content_type_instance(): void {
314         global $USER;
315         $this->resetAfterTest();
316         $this->setAdminUser();
317         $context = context_system::instance();
319         $type = new contenttype($context);
320         $record = (object)[
321             'name' => 'content name',
322             'usercreated' => $USER->id,
323         ];
324         $content = $type->create_content($record);
326         $contenttype = $content->get_content_type_instance();
328         $this->assertInstanceOf(get_class($type), $contenttype);
329     }
331     /**
332      * Tests for 'is_view_allowed'.
333      *
334      * @covers ::is_view_allowed
335      */
336     public function test_is_view_allowed() {
337         $this->resetAfterTest();
338         $this->setAdminUser();
339         $context = context_system::instance();
341         $userauthor = $this->getDataGenerator()->create_user();
342         $userother = $this->getDataGenerator()->create_user();
344         $contenttype = new contenttype($context);
346         $unlistedrecord = new stdClass();
347         $unlistedrecord->visibility = content::VISIBILITY_UNLISTED;
348         $unlistedrecord->usercreated = $userauthor->id;
349         $unlistedcontent = $contenttype->create_content($unlistedrecord);
351         $publicrecord = new stdClass();
352         $publicrecord->visibility = content::VISIBILITY_PUBLIC;
353         $publicrecord->usercreated = $userauthor->id;
354         $publiccontent = $contenttype->create_content($publicrecord);
356         $this->setUser($userother);
357         $this->assertFalse($unlistedcontent->is_view_allowed());
358         $this->assertTrue($publiccontent->is_view_allowed());
360         $this->setUser($userauthor);
361         $this->assertTrue($unlistedcontent->is_view_allowed());
362         $this->assertTrue($publiccontent->is_view_allowed());
364         $this->setAdminUser();
365         $this->assertTrue($unlistedcontent->is_view_allowed());
366         $this->assertTrue($publiccontent->is_view_allowed());
367     }
369     /**
370      * Tests for 'get_uses' behaviour.
371      *
372      * @covers ::get_uses
373      */
374     public function test_get_uses() {
375         $this->resetAfterTest();
376         $this->setAdminUser();
377         $context = context_system::instance();
379         // Add some content to the content bank.
380         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
381         $contents = $generator->generate_contentbank_data('contenttype_testable', 3, 0, $context);
382         $content1 = array_shift($contents);
384         // Check content has no references for now.
385         $this->assertCount(0, $content1->get_uses());
387         // Add a link to the previous content.
388         $cbfile = $content1->get_file();
389         $cbrecord = array(
390             'contextid' => $cbfile->get_contextid(),
391             'component' => $cbfile->get_component(),
392             'filearea'  => $cbfile->get_filearea(),
393             'itemid'    => $cbfile->get_itemid(),
394             'filepath'  => $cbfile->get_filepath(),
395             'filename'  => $cbfile->get_filename(),
396         );
397         $fs = get_file_storage();
398         $ref = $fs->pack_reference($cbrecord);
400         $aliasrecord = new stdClass();
401         $aliasrecord->contextid = $context->id;
402         $aliasrecord->component = 'core';
403         $aliasrecord->filearea = 'phpunit';
404         $aliasrecord->filepath = '/foo/';
405         $aliasrecord->filename = 'one.txt';
406         $aliasrecord->itemid = 0;
408         $repos = \repository::get_instances(['type' => 'contentbank']);
409         $cbrepo = reset($repos);
410         $this->assertInstanceOf('repository', $cbrepo);
412         $alias = $fs->create_file_from_reference($aliasrecord, $cbrepo->id, $ref);
414         // Check content now has one reference (the previous alias).
415         $contentuses1 = $content1->get_uses();
416         $this->assertCount(1, $contentuses1);
417         $reffile = reset($contentuses1);
418         $this->assertEquals($alias, $reffile);
420         // Check a different content hasn't any reference.
421         $content2 = array_shift($contents);
422         $this->assertCount(0, $content2->get_uses());
423     }