f1924fbf8ada779d7623592254f97a5cec648e7e
[moodle.git] / course / tests / services_content_item_service_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  * Contains the tests for the content_item_service class.
19  *
20  * @package    core
21  * @subpackage course
22  * @copyright  2020 Jake Dallimore <jrhdallimore@gmail.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
25 namespace tests\course;
27 defined('MOODLE_INTERNAL') || die();
29 use \core_course\local\service\content_item_service;
30 use \core_course\local\repository\content_item_readonly_repository;
32 /**
33  * The tests for the content_item_service class.
34  *
35  * @copyright  2020 Jake Dallimore <jrhdallimore@gmail.com>
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class services_content_item_service_testcase extends \advanced_testcase {
40     /**
41      * Test confirming that content items are returned by the service.
42      */
43     public function test_get_content_items_for_user_in_course_basic() {
44         $this->resetAfterTest();
46         // Create a user in a course.
47         $course = $this->getDataGenerator()->create_course();
48         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
50         $cis = new content_item_service(new content_item_readonly_repository());
51         $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
53         foreach ($contentitems as $key => $contentitem) {
54             $this->assertObjectHasAttribute('id', $contentitem);
55             $this->assertObjectHasAttribute('name', $contentitem);
56             $this->assertObjectHasAttribute('title', $contentitem);
57             $this->assertObjectHasAttribute('link', $contentitem);
58             $this->assertObjectHasAttribute('icon', $contentitem);
59             $this->assertObjectHasAttribute('help', $contentitem);
60             $this->assertObjectHasAttribute('archetype', $contentitem);
61             $this->assertObjectHasAttribute('componentname', $contentitem);
62         }
63     }
65     /**
66      * Test confirming that access control is performed when asking the service to return content items for a user in a course.
67      */
68     public function test_get_content_items_for_user_in_course_permissions() {
69         $this->resetAfterTest();
70         global $DB;
72         // Create a user in a course.
73         $course = $this->getDataGenerator()->create_course();
74         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
76         // No cap override, so assign should be returned.
77         $cis = new content_item_service(new content_item_readonly_repository());
78         $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
79         $this->assertContains('assign', array_column($contentitems, 'name'));
81         // Override the capability 'mod/assign:addinstance' for the 'editing teacher' role.
82         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
83         assign_capability('mod/assign:addinstance', CAP_PROHIBIT, $teacherrole->id, \context_course::instance($course->id));
85         $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
86         $this->assertArrayNotHasKey('assign', $contentitems);
87     }
89     /**
90      * Test confirming that params can be added to the content item's link.
91      */
92     public function test_get_content_item_for_user_in_course_link_params() {
93         $this->resetAfterTest();
95         // Create a user in a course.
96         $course = $this->getDataGenerator()->create_course();
97         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
99         $cis = new content_item_service(new content_item_readonly_repository());
100         $contentitems = $cis->get_content_items_for_user_in_course($user, $course, ['sr' => 7]);
102         foreach ($contentitems as $item) {
103             $this->assertStringContainsString('sr=7', $item->link);
104         }
105     }
107     /**
108      * Test confirming that all content items can be fetched irrespective of permissions.
109      */
110     public function test_get_all_content_items() {
111         $this->resetAfterTest();
112         global $DB;
114         // Create a user in a course.
115         $course = $this->getDataGenerator()->create_course();
116         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
118         $cis = new content_item_service(new content_item_readonly_repository());
119         $allcontentitems = $cis->get_all_content_items($user);
120         $coursecontentitems = $cis->get_content_items_for_user_in_course($user, $course);
122         // The call to get_all_content_items() should return the same items as for the course,
123         // given the user in an editing teacher and can add manual lti instances.
124         $this->assertEquals(array_column($allcontentitems, 'name'), array_column($coursecontentitems, 'name'));
126         // Now removing the cap 'mod/lti:addinstance'. This will restrict those items returned by the course-specific method.
127         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
128         assign_capability('mod/lti:addinstance', CAP_PROHIBIT, $teacherrole->id, \context_course::instance($course->id));
130         // Verify that all items, including lti, are still returned by the get_all_content_items() call.
131         $allcontentitems = $cis->get_all_content_items($user);
132         $coursecontentitems = $cis->get_content_items_for_user_in_course($user, $course);
133         $this->assertNotContains('lti', array_column($coursecontentitems, 'name'));
134         $this->assertContains('lti', array_column($allcontentitems, 'name'));
135     }
137     /**
138      * Test confirming that content items which title match a certain pattern can be fetched irrespective of permissions.
139      */
140     public function test_get_content_items_by_name_pattern() {
141         $this->resetAfterTest();
143         // Create a user in a course.
144         $course = $this->getDataGenerator()->create_course();
145         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
147         // Pattern that does exist.
148         $pattern1 = "assign";
149         // Pattern that does not exist.
150         $pattern2 = "random string";
152         $cis = new content_item_service(new content_item_readonly_repository());
153         $matchingcontentitems1 = $cis->get_content_items_by_name_pattern($user, $pattern1);
154         $matchingcontentitems2 = $cis->get_content_items_by_name_pattern($user, $pattern2);
156         // The pattern "assign" should return at least 1 content item (ex. "Assignment").
157         $this->assertGreaterThanOrEqual(1, count($matchingcontentitems1));
158         // Verify the pattern "assign" can be found in the title of each returned content item.
159         foreach ($matchingcontentitems1 as $contentitem) {
160             $this->assertEquals(1, preg_match("/$pattern1/i", $contentitem->title));
161         }
162         // The pattern "random string" should not return any content items.
163         $this->assertEmpty($matchingcontentitems2);
164     }
166     /**
167      * Test confirming that a content item can be added to a user's favourites.
168      */
169     public function test_add_to_user_favourites() {
170         $this->resetAfterTest();
172         // Create a user in a course.
173         $course = $this->getDataGenerator()->create_course();
174         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
175         $cis = new content_item_service(new content_item_readonly_repository());
177         // Grab a the assign content item, which we'll favourite for the user.
178         $items = $cis->get_all_content_items($user);
179         $assign = $items[array_search('assign', array_column($items, 'name'))];
180         $contentitem = $cis->add_to_user_favourites($user, 'mod_assign', $assign->id);
182         // Verify the exported result is marked as a favourite.
183         $this->assertEquals('assign', $contentitem->name);
184         $this->assertTrue($contentitem->favourite);
186         // Verify the item is marked as a favourite when returned from the other service methods.
187         $allitems = $cis->get_all_content_items($user);
188         $allitemsassign = $allitems[array_search('assign', array_column($allitems, 'name'))];
190         $courseitems = $cis->get_content_items_for_user_in_course($user, $course);
191         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
192         $this->assertTrue($allitemsassign->favourite);
193         $this->assertTrue($courseitemsassign->favourite);
194     }
196     /**
197      * Test verifying that content items can be removed from a user's favourites.
198      */
199     public function test_remove_from_user_favourites() {
200         $this->resetAfterTest();
202         // Create a user in a course.
203         $course = $this->getDataGenerator()->create_course();
204         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
205         $cis = new content_item_service(new content_item_readonly_repository());
207         // Grab a the assign content item, which we'll favourite for the user.
208         $items = $cis->get_all_content_items($user);
209         $assign = $items[array_search('assign', array_column($items, 'name'))];
210         $cis->add_to_user_favourites($user, 'mod_assign', $assign->id);
212         // Now, remove the favourite, and verify it.
213         $contentitem = $cis->remove_from_user_favourites($user, 'mod_assign', $assign->id);
215         // Verify the exported result is not marked as a favourite.
216         $this->assertEquals('assign', $contentitem->name);
217         $this->assertFalse($contentitem->favourite);
219         // Verify the item is not marked as a favourite when returned from the other service methods.
220         $allitems = $cis->get_all_content_items($user);
221         $allitemsassign = $allitems[array_search('assign', array_column($allitems, 'name'))];
222         $courseitems = $cis->get_content_items_for_user_in_course($user, $course);
223         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
224         $this->assertFalse($allitemsassign->favourite);
225         $this->assertFalse($courseitemsassign->favourite);
226     }
228     /**
229      * Test that toggling a recommendation works as anticipated.
230      */
231     public function test_toggle_recommendation() {
232         $this->resetAfterTest();
234         // Create a user in a course.
235         $course = $this->getDataGenerator()->create_course();
236         $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
237         $cis = new content_item_service(new content_item_readonly_repository());
239         // Grab a the assign content item, which we'll recommend for the user.
240         $items = $cis->get_all_content_items($user);
241         $assign = $items[array_search('assign', array_column($items, 'name'))];
242         $result = $cis->toggle_recommendation($assign->componentname, $assign->id);
243         $this->assertTrue($result);
245         $courseitems = $cis->get_all_content_items($user);
246         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
247         $this->assertTrue($courseitemsassign->recommended);
249         // Let's toggle the recommendation off.
250         $result = $cis->toggle_recommendation($assign->componentname, $assign->id);
251         $this->assertFalse($result);
253         $courseitems = $cis->get_all_content_items($user);
254         $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
255         $this->assertFalse($courseitemsassign->recommended);
256     }