MDL-64656 core_tag: New WebService core_tag_get_tagindex_per_area
[moodle.git] / tag / tests / external_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 WS in tags
19  *
20  * @package core_tag
21  * @category test
22  * @copyright 2015 Marina Glancy
23  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->libdir . '/externallib.php');
31 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
33 class core_tag_external_testcase extends externallib_advanced_testcase {
34     /**
35      * Test update_categories
36      */
37     public function test_update_tags() {
38         global $DB;
39         $this->resetAfterTest();
40         $context = context_system::instance();
42         $originaltag = array(
43             'isstandard' => 0,
44             'flag' => 1,
45             'rawname' => 'test',
46             'description' => 'desc'
47         );
48         $tag = $this->getDataGenerator()->create_tag($originaltag);
50         $updatetag = array(
51             'id' => $tag->id,
52             'description' => 'Trying to change tag description',
53             'rawname' => 'Trying to change tag name',
54             'flag' => 0,
55             'isstandard' => 1,
56         );
57         $gettag = array(
58             'id' => $tag->id,
59         );
61         // User without any caps can not change anything about a tag but can request [partial] tag data.
62         $this->setUser($this->getDataGenerator()->create_user());
63         $result = core_tag_external::update_tags(array($updatetag));
64         $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result);
65         $this->assertEquals($tag->id, $result['warnings'][0]['item']);
66         $this->assertEquals('nothingtoupdate', $result['warnings'][0]['warningcode']);
67         $this->assertEquals($originaltag['rawname'], $DB->get_field('tag', 'rawname',
68             array('id' => $tag->id)));
69         $this->assertEquals($originaltag['description'], $DB->get_field('tag', 'description',
70             array('id' => $tag->id)));
72         $result = core_tag_external::get_tags(array($gettag));
73         $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result);
74         $this->assertEquals($originaltag['rawname'], $result['tags'][0]['rawname']);
75         $this->assertEquals($originaltag['description'], $result['tags'][0]['description']);
76         $this->assertNotEmpty($result['tags'][0]['viewurl']);
77         $this->assertArrayNotHasKey('changetypeurl', $result['tags'][0]);
78         $this->assertArrayNotHasKey('changeflagurl', $result['tags'][0]);
79         $this->assertArrayNotHasKey('flag', $result['tags'][0]);
80         $this->assertArrayNotHasKey('official', $result['tags'][0]);
81         $this->assertArrayNotHasKey('isstandard', $result['tags'][0]);
83         // User with editing only capability can change description but not the tag name.
84         $roleid = $this->assignUserCapability('moodle/tag:edit', $context->id);
85         $result = core_tag_external::update_tags(array($updatetag));
86         $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result);
87         $this->assertEmpty($result['warnings']);
89         $result = core_tag_external::get_tags(array($gettag));
90         $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result);
91         $this->assertEquals($updatetag['id'], $result['tags'][0]['id']);
92         $this->assertEquals($updatetag['description'], $result['tags'][0]['description']);
93         $this->assertEquals($originaltag['rawname'], $result['tags'][0]['rawname']);
94         $this->assertArrayNotHasKey('flag', $result['tags'][0]); // 'Flag' is not available unless 'moodle/tag:manage' cap exists.
95         $this->assertEquals(0, $result['tags'][0]['official']);
96         $this->assertEquals(0, $result['tags'][0]['isstandard']);
97         $this->assertEquals($originaltag['rawname'], $DB->get_field('tag', 'rawname',
98                 array('id' => $tag->id)));
99         $this->assertEquals($updatetag['description'], $DB->get_field('tag', 'description',
100                 array('id' => $tag->id)));
102         // User with editing and manage cap can also change the tag name,
103         // make it standard and reset flag.
104         assign_capability('moodle/tag:manage', CAP_ALLOW, $roleid, $context->id);
105         $this->assertTrue(has_capability('moodle/tag:manage', $context));
106         $result = core_tag_external::update_tags(array($updatetag));
107         $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result);
108         $this->assertEmpty($result['warnings']);
110         $result = core_tag_external::get_tags(array($gettag));
111         $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result);
112         $this->assertEquals($updatetag['id'], $result['tags'][0]['id']);
113         $this->assertEquals($updatetag['rawname'], $result['tags'][0]['rawname']);
114         $this->assertEquals(core_text::strtolower($updatetag['rawname']), $result['tags'][0]['name']);
115         $this->assertEquals($updatetag['flag'], $result['tags'][0]['flag']);
116         $this->assertEquals($updatetag['isstandard'], $result['tags'][0]['official']);
117         $this->assertEquals($updatetag['isstandard'], $result['tags'][0]['isstandard']);
118         $this->assertEquals($updatetag['rawname'], $DB->get_field('tag', 'rawname',
119                 array('id' => $tag->id)));
120         $this->assertEquals(1, $DB->get_field('tag', 'isstandard', array('id' => $tag->id)));
122         // Updating and getting non-existing tag.
123         $nonexistingtag = array(
124             'id' => 123,
125             'description' => 'test'
126         );
127         $getnonexistingtag = array(
128             'id' => 123,
129         );
130         $result = core_tag_external::update_tags(array($nonexistingtag));
131         $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result);
132         $this->assertEquals(123, $result['warnings'][0]['item']);
133         $this->assertEquals('tagnotfound', $result['warnings'][0]['warningcode']);
135         $result = core_tag_external::get_tags(array($getnonexistingtag));
136         $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result);
137         $this->assertEmpty($result['tags']);
138         $this->assertEquals(123, $result['warnings'][0]['item']);
139         $this->assertEquals('tagnotfound', $result['warnings'][0]['warningcode']);
141         // Attempt to update a tag to the name that is reserved.
142         $anothertag = $this->getDataGenerator()->create_tag(array('rawname' => 'Mytag'));
143         $updatetag2 = array('id' => $tag->id, 'rawname' => 'MYTAG');
144         $result = core_tag_external::update_tags(array($updatetag2));
145         $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result);
146         $this->assertEquals($tag->id, $result['warnings'][0]['item']);
147         $this->assertEquals('namesalreadybeeingused', $result['warnings'][0]['warningcode']);
148     }
150     /**
151      * Test update_inplace_editable()
152      */
153     public function test_update_inplace_editable() {
154         global $CFG, $DB, $PAGE;
155         require_once($CFG->dirroot . '/lib/external/externallib.php');
157         $this->resetAfterTest(true);
158         $tag = $this->getDataGenerator()->create_tag();
159         $this->setUser($this->getDataGenerator()->create_user());
161         // Call service for core_tag component without necessary permissions.
162         try {
163             core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'new tag name');
164             $this->fail('Exception expected');
165         } catch (moodle_exception $e) {
166             $this->assertEquals('Sorry, but you do not currently have permissions to do that (Manage all tags).',
167                     $e->getMessage());
168         }
170         // Change to admin user and make sure that tag name can be updated using web service update_inplace_editable().
171         $this->setAdminUser();
172         $res = core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'New tag name');
173         $res = external_api::clean_returnvalue(core_external::update_inplace_editable_returns(), $res);
174         $this->assertEquals('New tag name', $res['value']);
175         $this->assertEquals('New tag name', $DB->get_field('tag', 'rawname', array('id' => $tag->id)));
177         // Call callback core_tag_inplace_editable() directly.
178         $tmpl = component_callback('core_tag', 'inplace_editable', array('tagname', $tag->id, 'Rename me again'));
179         $this->assertInstanceOf('core\output\inplace_editable', $tmpl);
180         $res = $tmpl->export_for_template($PAGE->get_renderer('core'));
181         $this->assertEquals('Rename me again', $res['value']);
182         $this->assertEquals('Rename me again', $DB->get_field('tag', 'rawname', array('id' => $tag->id)));
183     }
185     /**
186      * Test get_tagindex_per_area.
187      */
188     public function test_get_tagindex_per_area() {
189         global $USER;
190         $this->resetAfterTest(true);
192         // Create tags for two user profiles and one course.
193         $this->setAdminUser();
194         $context = context_user::instance($USER->id);
195         core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('test'));
197         $this->setUser($this->getDataGenerator()->create_user());
198         $context = context_user::instance($USER->id);
199         core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('test'));
201         $course = $this->getDataGenerator()->create_course();
202         $context = context_course::instance($course->id);
203         core_tag_tag::set_item_tags('core', 'course', $course->id, $context, array('test'));
205         $tag = core_tag_tag::get_by_name(0, 'test');
207         // First, search by id.
208         $result = core_tag_external::get_tagindex_per_area(array('id' => $tag->id));
209         $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result);
210         $this->assertCount(2, $result); // Two different areas: course and user.
211         $this->assertEquals($tag->id, $result[0]['tagid']);
212         $this->assertEquals('course', $result[0]['itemtype']);
213         $this->assertEquals($tag->id, $result[1]['tagid']);
214         $this->assertEquals('user', $result[1]['itemtype']);
216         // Now, search by name.
217         $result = core_tag_external::get_tagindex_per_area(array('tag' => 'test'));
218         $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result);
219         $this->assertCount(2, $result); // Two different areas: course and user.
220         $this->assertEquals($tag->id, $result[0]['tagid']);
221         $this->assertEquals('course', $result[0]['itemtype']);
222         $this->assertEquals($tag->id, $result[1]['tagid']);
223         $this->assertEquals('user', $result[1]['itemtype']);
225         // Filter by tag area.
226         $result = core_tag_external::get_tagindex_per_area(array('tag' => 'test', 'ta' => $result[0]['ta']));
227         $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result);
228         $this->assertCount(1, $result); // Just the given area.
229         $this->assertEquals($tag->id, $result[0]['tagid']);
230         $this->assertEquals('course', $result[0]['itemtype']);
232         // Now, search by tag collection (use default).
233         $result = core_tag_external::get_tagindex_per_area(array('id' => $tag->id, 'tc' => 1));
234         $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result);
235         $this->assertCount(2, $result); // Two different areas: course and user.
236     }