Merge branch 'MDL-64284-36_get_component_classes_cache' of https://github.com/tomdick...
[moodle.git] / mod / glossary / classes / external.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  * Glossary module external API.
19  *
20  * @package    mod_glossary
21  * @category   external
22  * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @since      Moodle 3.1
25  */
27 defined('MOODLE_INTERNAL') || die();
29 require_once($CFG->libdir . '/externallib.php');
30 require_once($CFG->dirroot . '/mod/glossary/lib.php');
32 /**
33  * Glossary module external functions.
34  *
35  * @package    mod_glossary
36  * @category   external
37  * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
38  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  * @since      Moodle 3.1
40  */
41 class mod_glossary_external extends external_api {
43     /**
44      * Get the browse modes from the display format.
45      *
46      * This returns some of the terms that can be used when reporting a glossary being viewed.
47      *
48      * @param  string $format The display format of the glossary.
49      * @return array Containing some of all of the following: letter, cat, date, author.
50      */
51     protected static function get_browse_modes_from_display_format($format) {
52         global $DB;
54         $formats = array();
55         $dp = $DB->get_record('glossary_formats', array('name' => $format), '*', IGNORE_MISSING);
56         if ($dp) {
57             $formats = glossary_get_visible_tabs($dp);
58         }
60         // Always add 'letter'.
61         $modes = array('letter');
63         if (in_array('category', $formats)) {
64             $modes[] = 'cat';
65         }
66         if (in_array('date', $formats)) {
67             $modes[] = 'date';
68         }
69         if (in_array('author', $formats)) {
70             $modes[] = 'author';
71         }
73         return $modes;
74     }
76     /**
77      * Get the return value of an entry.
78      *
79      * @param bool $includecat Whether the definition should include category info.
80      * @return external_definition
81      */
82     protected static function get_entry_return_structure($includecat = false) {
83         $params = array(
84             'id' => new external_value(PARAM_INT, 'The entry ID'),
85             'glossaryid' => new external_value(PARAM_INT, 'The glossary ID'),
86             'userid' => new external_value(PARAM_INT, 'Author ID'),
87             'userfullname' => new external_value(PARAM_NOTAGS, 'Author full name'),
88             'userpictureurl' => new external_value(PARAM_URL, 'Author picture'),
89             'concept' => new external_value(PARAM_RAW, 'The concept'),
90             'definition' => new external_value(PARAM_RAW, 'The definition'),
91             'definitionformat' => new external_format_value('definition'),
92             'definitiontrust' => new external_value(PARAM_BOOL, 'The definition trust flag'),
93             'definitioninlinefiles' => new external_files('entry definition inline files', VALUE_OPTIONAL),
94             'attachment' => new external_value(PARAM_BOOL, 'Whether or not the entry has attachments'),
95             'attachments' => new external_files('attachments', VALUE_OPTIONAL),
96             'timecreated' => new external_value(PARAM_INT, 'Time created'),
97             'timemodified' => new external_value(PARAM_INT, 'Time modified'),
98             'teacherentry' => new external_value(PARAM_BOOL, 'The entry was created by a teacher, or equivalent.'),
99             'sourceglossaryid' => new external_value(PARAM_INT, 'The source glossary ID'),
100             'usedynalink' => new external_value(PARAM_BOOL, 'Whether the concept should be automatically linked'),
101             'casesensitive' => new external_value(PARAM_BOOL, 'When true, the matching is case sensitive'),
102             'fullmatch' => new external_value(PARAM_BOOL, 'When true, the matching is done on full words only'),
103             'approved' => new external_value(PARAM_BOOL, 'Whether the entry was approved'),
104         );
106         if ($includecat) {
107             $params['categoryid'] = new external_value(PARAM_INT, 'The category ID. This may be' .
108                 ' \''. GLOSSARY_SHOW_NOT_CATEGORISED . '\' when the entry is not categorised', VALUE_DEFAULT,
109                 GLOSSARY_SHOW_NOT_CATEGORISED);
110             $params['categoryname'] = new external_value(PARAM_RAW, 'The category name. May be empty when the entry is' .
111                 ' not categorised, or the request was limited to one category.', VALUE_DEFAULT, '');
112         }
114         return new external_single_structure($params);
115     }
117     /**
118      * Fill in an entry object.
119      *
120      * This adds additional required fields for the external function to return.
121      *
122      * @param  stdClass $entry   The entry.
123      * @param  context  $context The context the entry belongs to.
124      * @return void
125      */
126     protected static function fill_entry_details($entry, $context) {
127         global $PAGE;
128         $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
130         // Format concept and definition.
131         $entry->concept = external_format_string($entry->concept, $context->id);
132         list($entry->definition, $entry->definitionformat) = external_format_text($entry->definition, $entry->definitionformat,
133             $context->id, 'mod_glossary', 'entry', $entry->id);
135         // Author details.
136         $user = mod_glossary_entry_query_builder::get_user_from_record($entry);
137         $userpicture = new user_picture($user);
138         $userpicture->size = 1;
139         $entry->userfullname = fullname($user, $canviewfullnames);
140         $entry->userpictureurl = $userpicture->get_url($PAGE)->out(false);
142         // Fetch attachments.
143         $entry->attachment = !empty($entry->attachment) ? 1 : 0;
144         $entry->attachments = array();
145         if ($entry->attachment) {
146             $entry->attachments = external_util::get_area_files($context->id, 'mod_glossary', 'attachment', $entry->id);
147         }
148         $definitioninlinefiles = external_util::get_area_files($context->id, 'mod_glossary', 'entry', $entry->id);
149         if (!empty($definitioninlinefiles)) {
150             $entry->definitioninlinefiles = $definitioninlinefiles;
151         }
152     }
154     /**
155      * Validate a glossary via ID.
156      *
157      * @param  int $id The glossary ID.
158      * @return array Contains glossary, context, course and cm.
159      */
160     protected static function validate_glossary($id) {
161         global $DB;
162         $glossary = $DB->get_record('glossary', array('id' => $id), '*', MUST_EXIST);
163         list($course, $cm) = get_course_and_cm_from_instance($glossary, 'glossary');
164         $context = context_module::instance($cm->id);
165         self::validate_context($context);
166         return array($glossary, $context, $course, $cm);
167     }
169     /**
170      * Describes the parameters for get_glossaries_by_courses.
171      *
172      * @return external_function_parameters
173      * @since Moodle 3.1
174      */
175     public static function get_glossaries_by_courses_parameters() {
176         return new external_function_parameters (
177             array(
178                 'courseids' => new external_multiple_structure(
179                     new external_value(PARAM_INT, 'course id'),
180                     'Array of course IDs', VALUE_DEFAULT, array()
181                 ),
182             )
183         );
184     }
186     /**
187      * Returns a list of glossaries in a provided list of courses.
188      *
189      * If no list is provided all glossaries that the user can view will be returned.
190      *
191      * @param array $courseids the course IDs.
192      * @return array of glossaries
193      * @since Moodle 3.1
194      */
195     public static function get_glossaries_by_courses($courseids = array()) {
196         $params = self::validate_parameters(self::get_glossaries_by_courses_parameters(), array('courseids' => $courseids));
198         $warnings = array();
199         $courses = array();
200         $courseids = $params['courseids'];
202         if (empty($courseids)) {
203             $courses = enrol_get_my_courses();
204             $courseids = array_keys($courses);
205         }
207         // Array to store the glossaries to return.
208         $glossaries = array();
209         $modes = array();
211         // Ensure there are courseids to loop through.
212         if (!empty($courseids)) {
213             list($courses, $warnings) = external_util::validate_courses($courseids, $courses);
215             // Get the glossaries in these courses, this function checks users visibility permissions.
216             $glossaries = get_all_instances_in_courses('glossary', $courses);
217             foreach ($glossaries as $glossary) {
218                 $context = context_module::instance($glossary->coursemodule);
219                 $glossary->name = external_format_string($glossary->name, $context->id);
220                 list($glossary->intro, $glossary->introformat) = external_format_text($glossary->intro, $glossary->introformat,
221                     $context->id, 'mod_glossary', 'intro', null);
222                 $glossary->introfiles = external_util::get_area_files($context->id, 'mod_glossary', 'intro', false, false);
224                 // Make sure we have a number of entries per page.
225                 if (!$glossary->entbypage) {
226                     $glossary->entbypage = $CFG->glossary_entbypage;
227                 }
229                 // Add the list of browsing modes.
230                 if (!isset($modes[$glossary->displayformat])) {
231                     $modes[$glossary->displayformat] = self::get_browse_modes_from_display_format($glossary->displayformat);
232                 }
233                 $glossary->browsemodes = $modes[$glossary->displayformat];
234                 $glossary->canaddentry = has_capability('mod/glossary:write', $context) ? 1 : 0;
235             }
236         }
238         $result = array();
239         $result['glossaries'] = $glossaries;
240         $result['warnings'] = $warnings;
241         return $result;
242     }
244     /**
245      * Describes the get_glossaries_by_courses return value.
246      *
247      * @return external_single_structure
248      * @since Moodle 3.1
249      */
250     public static function get_glossaries_by_courses_returns() {
251         return new external_single_structure(array(
252             'glossaries' => new external_multiple_structure(
253                 new external_single_structure(array(
254                     'id' => new external_value(PARAM_INT, 'Glossary id'),
255                     'coursemodule' => new external_value(PARAM_INT, 'Course module id'),
256                     'course' => new external_value(PARAM_INT, 'Course id'),
257                     'name' => new external_value(PARAM_RAW, 'Glossary name'),
258                     'intro' => new external_value(PARAM_RAW, 'The Glossary intro'),
259                     'introformat' => new external_format_value('intro'),
260                     'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
261                     'allowduplicatedentries' => new external_value(PARAM_INT, 'If enabled, multiple entries can have the' .
262                         ' same concept name'),
263                     'displayformat' => new external_value(PARAM_TEXT, 'Display format type'),
264                     'mainglossary' => new external_value(PARAM_INT, 'If enabled this glossary is a main glossary.'),
265                     'showspecial' => new external_value(PARAM_INT, 'If enabled, participants can browse the glossary by' .
266                         ' special characters, such as @ and #'),
267                     'showalphabet' => new external_value(PARAM_INT, 'If enabled, participants can browse the glossary by' .
268                         ' letters of the alphabet'),
269                     'showall' => new external_value(PARAM_INT, 'If enabled, participants can browse all entries at once'),
270                     'allowcomments' => new external_value(PARAM_INT, 'If enabled, all participants with permission to' .
271                         ' create comments will be able to add comments to glossary entries'),
272                     'allowprintview' => new external_value(PARAM_INT, 'If enabled, students are provided with a link to a' .
273                         ' printer-friendly version of the glossary. The link is always available to teachers'),
274                     'usedynalink' => new external_value(PARAM_INT, 'If site-wide glossary auto-linking has been enabled' .
275                         ' by an administrator and this checkbox is ticked, the entry will be automatically linked' .
276                         ' wherever the concept words and phrases appear throughout the rest of the course.'),
277                     'defaultapproval' => new external_value(PARAM_INT, 'If set to no, entries require approving by a' .
278                         ' teacher before they are viewable by everyone.'),
279                     'approvaldisplayformat' => new external_value(PARAM_TEXT, 'When approving glossary items you may wish' .
280                         ' to use a different display format'),
281                     'globalglossary' => new external_value(PARAM_INT, ''),
282                     'entbypage' => new external_value(PARAM_INT, 'Entries shown per page'),
283                     'editalways' => new external_value(PARAM_INT, 'Always allow editing'),
284                     'rsstype' => new external_value(PARAM_INT, 'To enable the RSS feed for this activity, select either' .
285                         ' concepts with author or concepts without author to be included in the feed'),
286                     'rssarticles' => new external_value(PARAM_INT, 'This setting specifies the number of glossary entry' .
287                         ' concepts to include in the RSS feed. Between 5 and 20 generally acceptable'),
288                     'assessed' => new external_value(PARAM_INT, 'Aggregate type'),
289                     'assesstimestart' => new external_value(PARAM_INT, 'Restrict rating to items created after this'),
290                     'assesstimefinish' => new external_value(PARAM_INT, 'Restrict rating to items created before this'),
291                     'scale' => new external_value(PARAM_INT, 'Scale ID'),
292                     'timecreated' => new external_value(PARAM_INT, 'Time created'),
293                     'timemodified' => new external_value(PARAM_INT, 'Time modified'),
294                     'completionentries' => new external_value(PARAM_INT, 'Number of entries to complete'),
295                     'section' => new external_value(PARAM_INT, 'Section'),
296                     'visible' => new external_value(PARAM_INT, 'Visible'),
297                     'groupmode' => new external_value(PARAM_INT, 'Group mode'),
298                     'groupingid' => new external_value(PARAM_INT, 'Grouping ID'),
299                     'browsemodes' => new external_multiple_structure(
300                         new external_value(PARAM_ALPHA, 'Modes of browsing allowed')
301                     ),
302                     'canaddentry' => new external_value(PARAM_INT, 'Whether the user can add a new entry', VALUE_OPTIONAL),
303                 ), 'Glossaries')
304             ),
305             'warnings' => new external_warnings())
306         );
307     }
309     /**
310      * Returns the description of the external function parameters.
311      *
312      * @return external_function_parameters
313      * @since Moodle 3.1
314      */
315     public static function view_glossary_parameters() {
316         return new external_function_parameters(array(
317             'id' => new external_value(PARAM_INT, 'Glossary instance ID'),
318             'mode' => new external_value(PARAM_ALPHA, 'The mode in which the glossary is viewed'),
319         ));
320     }
322     /**
323      * Notify that the course module was viewed.
324      *
325      * @param int $id The glossary instance ID.
326      * @param string $mode The view mode.
327      * @return array of warnings and status result
328      * @since Moodle 3.1
329      * @throws moodle_exception
330      */
331     public static function view_glossary($id, $mode) {
332         $params = self::validate_parameters(self::view_glossary_parameters(), array(
333             'id' => $id,
334             'mode' => $mode
335         ));
336         $id = $params['id'];
337         $mode = $params['mode'];
338         $warnings = array();
340         // Get and validate the glossary.
341         list($glossary, $context, $course, $cm) = self::validate_glossary($id);
343         // Trigger module viewed event.
344         glossary_view($glossary, $course, $cm, $context, $mode);
346         return array(
347             'status' => true,
348             'warnings' => $warnings
349         );
350     }
352     /**
353      * Returns the description of the external function return value.
354      *
355      * @return external_description
356      * @since Moodle 3.1
357      */
358     public static function view_glossary_returns() {
359         return new external_single_structure(array(
360             'status' => new external_value(PARAM_BOOL, 'True on success'),
361             'warnings' => new external_warnings()
362         ));
363     }
365     /**
366      * Returns the description of the external function parameters.
367      *
368      * @return external_function_parameters
369      * @since Moodle 3.1
370      */
371     public static function view_entry_parameters() {
372         return new external_function_parameters(array(
373             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
374         ));
375     }
377     /**
378      * Notify that the entry was viewed.
379      *
380      * @param int $id The entry ID.
381      * @return array of warnings and status result
382      * @since Moodle 3.1
383      * @throws moodle_exception
384      * @throws invalid_parameter_exception
385      */
386     public static function view_entry($id) {
387         global $DB, $USER;
389         $params = self::validate_parameters(self::view_entry_parameters(), array('id' => $id));
390         $id = $params['id'];
391         $warnings = array();
393         // Get and validate the glossary.
394         $entry = $DB->get_record('glossary_entries', array('id' => $id), '*', MUST_EXIST);
395         list($glossary, $context, $course, $cm) = self::validate_glossary($entry->glossaryid);
397         if (!glossary_can_view_entry($entry, $cm)) {
398             throw new invalid_parameter_exception('invalidentry');
399         }
401         // Trigger view.
402         glossary_entry_view($entry, $context);
404         return array(
405             'status' => true,
406             'warnings' => $warnings
407         );
408     }
410     /**
411      * Returns the description of the external function return value.
412      *
413      * @return external_description
414      * @since Moodle 3.1
415      */
416     public static function view_entry_returns() {
417         return new external_single_structure(array(
418             'status' => new external_value(PARAM_BOOL, 'True on success'),
419             'warnings' => new external_warnings()
420         ));
421     }
423     /**
424      * Returns the description of the external function parameters.
425      *
426      * @return external_function_parameters
427      * @since Moodle 3.1
428      */
429     public static function get_entries_by_letter_parameters() {
430         return new external_function_parameters(array(
431             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
432             'letter' => new external_value(PARAM_ALPHA, 'A letter, or either keywords: \'ALL\' or \'SPECIAL\'.'),
433             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
434             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
435             'options' => new external_single_structure(array(
436                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
437                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
438             ), 'An array of options', VALUE_DEFAULT, array())
439         ));
440     }
442     /**
443      * Browse a glossary entries by letter.
444      *
445      * @param int $id The glossary ID.
446      * @param string $letter A letter, or a special keyword.
447      * @param int $from Start returning records from here.
448      * @param int $limit Number of records to return.
449      * @param array $options Array of options.
450      * @return array Containing count, entries and warnings.
451      * @since Moodle 3.1
452      * @throws moodle_exception
453      * @throws invalid_parameter_exception
454      */
455     public static function get_entries_by_letter($id, $letter, $from, $limit, $options) {
456         $params = self::validate_parameters(self::get_entries_by_letter_parameters(), array(
457             'id' => $id,
458             'letter' => $letter,
459             'from' => $from,
460             'limit' => $limit,
461             'options' => $options,
462         ));
463         $id = $params['id'];
464         $letter = $params['letter'];
465         $from = $params['from'];
466         $limit = $params['limit'];
467         $options = $params['options'];
468         $warnings = array();
470         // Get and validate the glossary.
471         list($glossary, $context) = self::validate_glossary($id);
473         // Validate the mode.
474         $modes = self::get_browse_modes_from_display_format($glossary->displayformat);
475         if (!in_array('letter', $modes)) {
476             throw new invalid_parameter_exception('invalidbrowsemode');
477         }
479         $entries = array();
480         list($records, $count) = glossary_get_entries_by_letter($glossary, $context, $letter, $from, $limit, $options);
481         foreach ($records as $key => $record) {
482             self::fill_entry_details($record, $context);
483             $entries[] = $record;
484         }
486         return array(
487             'count' => $count,
488             'entries' => $entries,
489             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
490             'warnings' => $warnings
491         );
492     }
494     /**
495      * Returns the description of the external function return value.
496      *
497      * @return external_description
498      * @since Moodle 3.1
499      */
500     public static function get_entries_by_letter_returns() {
501         return new external_single_structure(array(
502             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
503             'entries' => new external_multiple_structure(
504                 self::get_entry_return_structure()
505             ),
506             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
507             'warnings' => new external_warnings()
508         ));
509     }
511     /**
512      * Returns the description of the external function parameters.
513      *
514      * @return external_function_parameters
515      * @since Moodle 3.1
516      */
517     public static function get_entries_by_date_parameters() {
518         return new external_function_parameters(array(
519             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
520             'order' => new external_value(PARAM_ALPHA, 'Order the records by: \'CREATION\' or \'UPDATE\'.',
521                 VALUE_DEFAULT, 'UPDATE'),
522             'sort' => new external_value(PARAM_ALPHA, 'The direction of the order: \'ASC\' or \'DESC\'', VALUE_DEFAULT, 'DESC'),
523             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
524             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
525             'options' => new external_single_structure(array(
526                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
527                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
528             ), 'An array of options', VALUE_DEFAULT, array())
529         ));
530     }
532     /**
533      * Browse a glossary entries by date.
534      *
535      * @param int $id The glossary ID.
536      * @param string $order The way to order the records.
537      * @param string $sort The direction of the order.
538      * @param int $from Start returning records from here.
539      * @param int $limit Number of records to return.
540      * @param array $options Array of options.
541      * @return array Containing count, entries and warnings.
542      * @since Moodle 3.1
543      * @throws moodle_exception
544      * @throws invalid_parameter_exception
545      */
546     public static function get_entries_by_date($id, $order, $sort, $from, $limit, $options) {
547         $params = self::validate_parameters(self::get_entries_by_date_parameters(), array(
548             'id' => $id,
549             'order' => core_text::strtoupper($order),
550             'sort' => core_text::strtoupper($sort),
551             'from' => $from,
552             'limit' => $limit,
553             'options' => $options,
554         ));
555         $id = $params['id'];
556         $order = $params['order'];
557         $sort = $params['sort'];
558         $from = $params['from'];
559         $limit = $params['limit'];
560         $options = $params['options'];
561         $warnings = array();
563         if (!in_array($order, array('CREATION', 'UPDATE'))) {
564             throw new invalid_parameter_exception('invalidorder');
565         } else if (!in_array($sort, array('ASC', 'DESC'))) {
566             throw new invalid_parameter_exception('invalidsort');
567         }
569         // Get and validate the glossary.
570         list($glossary, $context) = self::validate_glossary($id);
572         // Validate the mode.
573         $modes = self::get_browse_modes_from_display_format($glossary->displayformat);
574         if (!in_array('date', $modes)) {
575             throw new invalid_parameter_exception('invalidbrowsemode');
576         }
578         $entries = array();
579         list($records, $count) = glossary_get_entries_by_date($glossary, $context, $order, $sort, $from, $limit, $options);
580         foreach ($records as $key => $record) {
581             self::fill_entry_details($record, $context);
582             $entries[] = $record;
583         }
585         return array(
586             'count' => $count,
587             'entries' => $entries,
588             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
589             'warnings' => $warnings
590         );
591     }
593     /**
594      * Returns the description of the external function return value.
595      *
596      * @return external_description
597      * @since Moodle 3.1
598      */
599     public static function get_entries_by_date_returns() {
600         return new external_single_structure(array(
601             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
602             'entries' => new external_multiple_structure(
603                 self::get_entry_return_structure()
604             ),
605             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
606             'warnings' => new external_warnings()
607         ));
608     }
610     /**
611      * Returns the description of the external function parameters.
612      *
613      * @return external_function_parameters
614      * @since Moodle 3.1
615      */
616     public static function get_categories_parameters() {
617         return new external_function_parameters(array(
618             'id' => new external_value(PARAM_INT, 'The glossary ID'),
619             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
620             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20)
621         ));
622     }
624     /**
625      * Get the categories of a glossary.
626      *
627      * @param int $id The glossary ID.
628      * @param int $from Start returning records from here.
629      * @param int $limit Number of records to return.
630      * @return array Containing count, categories and warnings.
631      * @since Moodle 3.1
632      * @throws moodle_exception
633      */
634     public static function get_categories($id, $from, $limit) {
635         $params = self::validate_parameters(self::get_categories_parameters(), array(
636             'id' => $id,
637             'from' => $from,
638             'limit' => $limit
639         ));
640         $id = $params['id'];
641         $from = $params['from'];
642         $limit = $params['limit'];
643         $warnings = array();
645         // Get and validate the glossary.
646         list($glossary, $context) = self::validate_glossary($id);
648         // Fetch the categories.
649         $categories = array();
650         list($records, $count) = glossary_get_categories($glossary, $from, $limit);
651         foreach ($records as $category) {
652             $category->name = external_format_string($category->name, $context->id);
653             $categories[] = $category;
654         }
656         return array(
657             'count' => $count,
658             'categories' => $categories,
659             'warnings' => array(),
660         );
661     }
663     /**
664      * Returns the description of the external function return value.
665      *
666      * @return external_description
667      * @since Moodle 3.1
668      */
669     public static function get_categories_returns() {
670         return new external_single_structure(array(
671             'count' => new external_value(PARAM_INT, 'The total number of records.'),
672             'categories' => new external_multiple_structure(
673                 new external_single_structure(array(
674                     'id' => new external_value(PARAM_INT, 'The category ID'),
675                     'glossaryid' => new external_value(PARAM_INT, 'The glossary ID'),
676                     'name' => new external_value(PARAM_RAW, 'The name of the category'),
677                     'usedynalink' => new external_value(PARAM_BOOL, 'Whether the category is automatically linked'),
678                 ))
679             ),
680             'warnings' => new external_warnings()
681         ));
682     }
684     /**
685      * Returns the description of the external function parameters.
686      *
687      * @return external_function_parameters
688      * @since Moodle 3.1
689      */
690     public static function get_entries_by_category_parameters() {
691         return new external_function_parameters(array(
692             'id' => new external_value(PARAM_INT, 'The glossary ID.'),
693             'categoryid' => new external_value(PARAM_INT, 'The category ID. Use \'' . GLOSSARY_SHOW_ALL_CATEGORIES . '\' for all' .
694                 ' categories, or \'' . GLOSSARY_SHOW_NOT_CATEGORISED . '\' for uncategorised entries.'),
695             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
696             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
697             'options' => new external_single_structure(array(
698                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
699                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
700             ), 'An array of options', VALUE_DEFAULT, array())
701         ));
702     }
704     /**
705      * Browse a glossary entries by category.
706      *
707      * @param int $id The glossary ID.
708      * @param int $categoryid The category ID.
709      * @param int $from Start returning records from here.
710      * @param int $limit Number of records to return.
711      * @param array $options Array of options.
712      * @return array Containing count, entries and warnings.
713      * @since Moodle 3.1
714      * @throws moodle_exception
715      * @throws invalid_parameter_exception
716      */
717     public static function get_entries_by_category($id, $categoryid, $from, $limit, $options) {
718         global $DB;
720         $params = self::validate_parameters(self::get_entries_by_category_parameters(), array(
721             'id' => $id,
722             'categoryid' => $categoryid,
723             'from' => $from,
724             'limit' => $limit,
725             'options' => $options,
726         ));
727         $id = $params['id'];
728         $categoryid = $params['categoryid'];
729         $from = $params['from'];
730         $limit = $params['limit'];
731         $options = $params['options'];
732         $warnings = array();
734         // Get and validate the glossary.
735         list($glossary, $context) = self::validate_glossary($id);
737         // Validate the mode.
738         $modes = self::get_browse_modes_from_display_format($glossary->displayformat);
739         if (!in_array('cat', $modes)) {
740             throw new invalid_parameter_exception('invalidbrowsemode');
741         }
743         // Validate the category.
744         if (in_array($categoryid, array(GLOSSARY_SHOW_ALL_CATEGORIES, GLOSSARY_SHOW_NOT_CATEGORISED))) {
745             // All good.
746         } else if (!$DB->record_exists('glossary_categories', array('id' => $categoryid, 'glossaryid' => $id))) {
747             throw new invalid_parameter_exception('invalidcategory');
748         }
750         // Fetching the entries.
751         $entries = array();
752         list($records, $count) = glossary_get_entries_by_category($glossary, $context, $categoryid, $from, $limit, $options);
753         foreach ($records as $key => $record) {
754             self::fill_entry_details($record, $context);
755             if ($record->categoryid === null) {
756                 $record->categoryid = GLOSSARY_SHOW_NOT_CATEGORISED;
757             }
758             if (isset($record->categoryname)) {
759                 $record->categoryname = external_format_string($record->categoryname, $context->id);
760             }
761             $entries[] = $record;
762         }
764         return array(
765             'count' => $count,
766             'entries' => $entries,
767             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
768             'warnings' => $warnings
769         );
770     }
772     /**
773      * Returns the description of the external function return value.
774      *
775      * @return external_description
776      * @since Moodle 3.1
777      */
778     public static function get_entries_by_category_returns() {
779         return new external_single_structure(array(
780             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
781             'entries' => new external_multiple_structure(
782                 self::get_entry_return_structure(true)
783             ),
784             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
785             'warnings' => new external_warnings()
786         ));
787     }
789     /**
790      * Returns the description of the external function parameters.
791      *
792      * @return external_function_parameters
793      * @since Moodle 3.1
794      */
795     public static function get_authors_parameters() {
796         return new external_function_parameters(array(
797             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
798             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
799             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
800             'options' => new external_single_structure(array(
801                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes self even if all of their entries' .
802                     ' require approval. When true, also includes authors only having entries pending approval.', VALUE_DEFAULT, 0)
803             ), 'An array of options', VALUE_DEFAULT, array())
804         ));
805     }
807     /**
808      * Get the authors of a glossary.
809      *
810      * @param int $id The glossary ID.
811      * @param int $from Start returning records from here.
812      * @param int $limit Number of records to return.
813      * @param array $options Array of options.
814      * @return array Containing count, authors and warnings.
815      * @since Moodle 3.1
816      * @throws moodle_exception
817      */
818     public static function get_authors($id, $from, $limit, $options) {
819         global $PAGE;
821         $params = self::validate_parameters(self::get_authors_parameters(), array(
822             'id' => $id,
823             'from' => $from,
824             'limit' => $limit,
825             'options' => $options,
826         ));
827         $id = $params['id'];
828         $from = $params['from'];
829         $limit = $params['limit'];
830         $options = $params['options'];
831         $warnings = array();
833         // Get and validate the glossary.
834         list($glossary, $context) = self::validate_glossary($id);
836         // Fetching the entries.
837         list($users, $count) = glossary_get_authors($glossary, $context, $limit, $from, $options);
839         $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
840         foreach ($users as $user) {
841             $userpicture = new user_picture($user);
842             $userpicture->size = 1;
844             $author = new stdClass();
845             $author->id = $user->id;
846             $author->fullname = fullname($user, $canviewfullnames);
847             $author->pictureurl = $userpicture->get_url($PAGE)->out(false);
848             $authors[] = $author;
849         }
850         $users->close();
852         return array(
853             'count' => $count,
854             'authors' => $authors,
855             'warnings' => array(),
856         );
857     }
859     /**
860      * Returns the description of the external function return value.
861      *
862      * @return external_description
863      * @since Moodle 3.1
864      */
865     public static function get_authors_returns() {
866         return new external_single_structure(array(
867             'count' => new external_value(PARAM_INT, 'The total number of records.'),
868             'authors' => new external_multiple_structure(
869                 new external_single_structure(array(
870                     'id' => new external_value(PARAM_INT, 'The user ID'),
871                     'fullname' => new external_value(PARAM_NOTAGS, 'The fullname'),
872                     'pictureurl' => new external_value(PARAM_URL, 'The picture URL'),
873                 ))
874             ),
875             'warnings' => new external_warnings()
876         ));
877     }
879     /**
880      * Returns the description of the external function parameters.
881      *
882      * @return external_function_parameters
883      * @since Moodle 3.1
884      */
885     public static function get_entries_by_author_parameters() {
886         return new external_function_parameters(array(
887             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
888             'letter' => new external_value(PARAM_ALPHA, 'First letter of firstname or lastname, or either keywords:'
889                 . ' \'ALL\' or \'SPECIAL\'.'),
890             'field' => new external_value(PARAM_ALPHA, 'Search and order using: \'FIRSTNAME\' or \'LASTNAME\'', VALUE_DEFAULT,
891                 'LASTNAME'),
892             'sort' => new external_value(PARAM_ALPHA, 'The direction of the order: \'ASC\' or \'DESC\'', VALUE_DEFAULT, 'ASC'),
893             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
894             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
895             'options' => new external_single_structure(array(
896                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
897                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
898             ), 'An array of options', VALUE_DEFAULT, array())
899         ));
900     }
902     /**
903      * Browse a glossary entries by author.
904      *
905      * @param int $id The glossary ID.
906      * @param string $letter A letter, or a special keyword.
907      * @param string $field The field to search from.
908      * @param string $sort The direction of the order.
909      * @param int $from Start returning records from here.
910      * @param int $limit Number of records to return.
911      * @param array $options Array of options.
912      * @return array Containing count, entries and warnings.
913      * @since Moodle 3.1
914      * @throws moodle_exception
915      * @throws invalid_parameter_exception
916      */
917     public static function get_entries_by_author($id, $letter, $field, $sort, $from, $limit, $options) {
918         $params = self::validate_parameters(self::get_entries_by_author_parameters(), array(
919             'id' => $id,
920             'letter' => $letter,
921             'field' => core_text::strtoupper($field),
922             'sort' => core_text::strtoupper($sort),
923             'from' => $from,
924             'limit' => $limit,
925             'options' => $options,
926         ));
927         $id = $params['id'];
928         $letter = $params['letter'];
929         $field = $params['field'];
930         $sort = $params['sort'];
931         $from = $params['from'];
932         $limit = $params['limit'];
933         $options = $params['options'];
934         $warnings = array();
936         if (!in_array($field, array('FIRSTNAME', 'LASTNAME'))) {
937             throw new invalid_parameter_exception('invalidfield');
938         } else if (!in_array($sort, array('ASC', 'DESC'))) {
939             throw new invalid_parameter_exception('invalidsort');
940         }
942         // Get and validate the glossary.
943         list($glossary, $context) = self::validate_glossary($id);
945         // Validate the mode.
946         $modes = self::get_browse_modes_from_display_format($glossary->displayformat);
947         if (!in_array('author', $modes)) {
948             throw new invalid_parameter_exception('invalidbrowsemode');
949         }
951         // Fetching the entries.
952         $entries = array();
953         list($records, $count) = glossary_get_entries_by_author($glossary, $context, $letter, $field, $sort, $from, $limit,
954             $options);
955         foreach ($records as $key => $record) {
956             self::fill_entry_details($record, $context);
957             $entries[] = $record;
958         }
960         return array(
961             'count' => $count,
962             'entries' => $entries,
963             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
964             'warnings' => $warnings
965         );
966     }
968     /**
969      * Returns the description of the external function return value.
970      *
971      * @return external_description
972      * @since Moodle 3.1
973      */
974     public static function get_entries_by_author_returns() {
975         return new external_single_structure(array(
976             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
977             'entries' => new external_multiple_structure(
978                 self::get_entry_return_structure()
979             ),
980             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
981             'warnings' => new external_warnings()
982         ));
983     }
985     /**
986      * Returns the description of the external function parameters.
987      *
988      * @return external_function_parameters
989      * @since Moodle 3.1
990      */
991     public static function get_entries_by_author_id_parameters() {
992         return new external_function_parameters(array(
993             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
994             'authorid' => new external_value(PARAM_INT, 'The author ID'),
995             'order' => new external_value(PARAM_ALPHA, 'Order by: \'CONCEPT\', \'CREATION\' or \'UPDATE\'', VALUE_DEFAULT,
996                 'CONCEPT'),
997             'sort' => new external_value(PARAM_ALPHA, 'The direction of the order: \'ASC\' or \'DESC\'', VALUE_DEFAULT, 'ASC'),
998             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
999             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
1000             'options' => new external_single_structure(array(
1001                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
1002                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
1003             ), 'An array of options', VALUE_DEFAULT, array())
1004         ));
1005     }
1007     /**
1008      * Browse a glossary entries by author.
1009      *
1010      * @param int $id The glossary ID.
1011      * @param int $authorid The author ID.
1012      * @param string $order The way to order the results.
1013      * @param string $sort The direction of the order.
1014      * @param int $from Start returning records from here.
1015      * @param int $limit Number of records to return.
1016      * @param array $options Array of options.
1017      * @return array Containing count, entries and warnings.
1018      * @since Moodle 3.1
1019      * @throws moodle_exception
1020      * @throws invalid_parameter_exception
1021      */
1022     public static function get_entries_by_author_id($id, $authorid, $order, $sort, $from, $limit, $options) {
1023         $params = self::validate_parameters(self::get_entries_by_author_id_parameters(), array(
1024             'id' => $id,
1025             'authorid' => $authorid,
1026             'order' => core_text::strtoupper($order),
1027             'sort' => core_text::strtoupper($sort),
1028             'from' => $from,
1029             'limit' => $limit,
1030             'options' => $options,
1031         ));
1032         $id = $params['id'];
1033         $authorid = $params['authorid'];
1034         $order = $params['order'];
1035         $sort = $params['sort'];
1036         $from = $params['from'];
1037         $limit = $params['limit'];
1038         $options = $params['options'];
1039         $warnings = array();
1041         if (!in_array($order, array('CONCEPT', 'CREATION', 'UPDATE'))) {
1042             throw new invalid_parameter_exception('invalidorder');
1043         } else if (!in_array($sort, array('ASC', 'DESC'))) {
1044             throw new invalid_parameter_exception('invalidsort');
1045         }
1047         // Get and validate the glossary.
1048         list($glossary, $context) = self::validate_glossary($id);
1050         // Validate the mode.
1051         $modes = self::get_browse_modes_from_display_format($glossary->displayformat);
1052         if (!in_array('author', $modes)) {
1053             throw new invalid_parameter_exception('invalidbrowsemode');
1054         }
1056         // Fetching the entries.
1057         $entries = array();
1058         list($records, $count) = glossary_get_entries_by_author_id($glossary, $context, $authorid, $order, $sort, $from,
1059             $limit, $options);
1060         foreach ($records as $key => $record) {
1061             self::fill_entry_details($record, $context);
1062             $entries[] = $record;
1063         }
1065         return array(
1066             'count' => $count,
1067             'entries' => $entries,
1068             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
1069             'warnings' => $warnings
1070         );
1071     }
1073     /**
1074      * Returns the description of the external function return value.
1075      *
1076      * @return external_description
1077      * @since Moodle 3.1
1078      */
1079     public static function get_entries_by_author_id_returns() {
1080         return new external_single_structure(array(
1081             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
1082             'entries' => new external_multiple_structure(
1083                 self::get_entry_return_structure()
1084             ),
1085             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
1086             'warnings' => new external_warnings()
1087         ));
1088     }
1090     /**
1091      * Returns the description of the external function parameters.
1092      *
1093      * @return external_function_parameters
1094      * @since Moodle 3.1
1095      */
1096     public static function get_entries_by_search_parameters() {
1097         return new external_function_parameters(array(
1098             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
1099             'query' => new external_value(PARAM_NOTAGS, 'The query string'),
1100             'fullsearch' => new external_value(PARAM_BOOL, 'The query', VALUE_DEFAULT, 1),
1101             'order' => new external_value(PARAM_ALPHA, 'Order by: \'CONCEPT\', \'CREATION\' or \'UPDATE\'', VALUE_DEFAULT,
1102                 'CONCEPT'),
1103             'sort' => new external_value(PARAM_ALPHA, 'The direction of the order: \'ASC\' or \'DESC\'', VALUE_DEFAULT, 'ASC'),
1104             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
1105             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
1106             'options' => new external_single_structure(array(
1107                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
1108                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
1109             ), 'An array of options', VALUE_DEFAULT, array())
1110         ));
1111     }
1113     /**
1114      * Browse a glossary entries using the search.
1115      *
1116      * @param int $id The glossary ID.
1117      * @param string $query The search query.
1118      * @param bool $fullsearch Whether or not full search is required.
1119      * @param string $order The way to order the results.
1120      * @param string $sort The direction of the order.
1121      * @param int $from Start returning records from here.
1122      * @param int $limit Number of records to return.
1123      * @param array $options Array of options.
1124      * @return array Containing count, entries and warnings.
1125      * @since Moodle 3.1
1126      * @throws moodle_exception
1127      * @throws invalid_parameter_exception
1128      */
1129     public static function get_entries_by_search($id, $query, $fullsearch, $order, $sort, $from, $limit, $options) {
1130         $params = self::validate_parameters(self::get_entries_by_search_parameters(), array(
1131             'id' => $id,
1132             'query' => $query,
1133             'fullsearch' => $fullsearch,
1134             'order' => core_text::strtoupper($order),
1135             'sort' => core_text::strtoupper($sort),
1136             'from' => $from,
1137             'limit' => $limit,
1138             'options' => $options,
1139         ));
1140         $id = $params['id'];
1141         $query = $params['query'];
1142         $fullsearch = $params['fullsearch'];
1143         $order = $params['order'];
1144         $sort = $params['sort'];
1145         $from = $params['from'];
1146         $limit = $params['limit'];
1147         $options = $params['options'];
1148         $warnings = array();
1150         if (!in_array($order, array('CONCEPT', 'CREATION', 'UPDATE'))) {
1151             throw new invalid_parameter_exception('invalidorder');
1152         } else if (!in_array($sort, array('ASC', 'DESC'))) {
1153             throw new invalid_parameter_exception('invalidsort');
1154         }
1156         // Get and validate the glossary.
1157         list($glossary, $context) = self::validate_glossary($id);
1159         // Fetching the entries.
1160         $entries = array();
1161         list($records, $count) = glossary_get_entries_by_search($glossary, $context, $query, $fullsearch, $order, $sort, $from,
1162             $limit, $options);
1163         foreach ($records as $key => $record) {
1164             self::fill_entry_details($record, $context);
1165             $entries[] = $record;
1166         }
1168         return array(
1169             'count' => $count,
1170             'entries' => $entries,
1171             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
1172             'warnings' => $warnings
1173         );
1174     }
1176     /**
1177      * Returns the description of the external function return value.
1178      *
1179      * @return external_description
1180      * @since Moodle 3.1
1181      */
1182     public static function get_entries_by_search_returns() {
1183         return new external_single_structure(array(
1184             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
1185             'entries' => new external_multiple_structure(
1186                 self::get_entry_return_structure()
1187             ),
1188             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
1189             'warnings' => new external_warnings()
1190         ));
1191     }
1193     /**
1194      * Returns the description of the external function parameters.
1195      *
1196      * @return external_function_parameters
1197      * @since Moodle 3.1
1198      */
1199     public static function get_entries_by_term_parameters() {
1200         return new external_function_parameters(array(
1201             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
1202             'term' => new external_value(PARAM_NOTAGS, 'The entry concept, or alias'),
1203             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
1204             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
1205             'options' => new external_single_structure(array(
1206                 'includenotapproved' => new external_value(PARAM_BOOL, 'When false, includes the non-approved entries created by' .
1207                     ' the user. When true, also includes the ones that the user has the permission to approve.', VALUE_DEFAULT, 0)
1208             ), 'An array of options', VALUE_DEFAULT, array())
1209         ));
1210     }
1212     /**
1213      * Browse a glossary entries using a term matching the concept or alias.
1214      *
1215      * @param int $id The glossary ID.
1216      * @param string $term The term.
1217      * @param int $from Start returning records from here.
1218      * @param int $limit Number of records to return.
1219      * @param array $options Array of options.
1220      * @return array Containing count, entries and warnings.
1221      * @since Moodle 3.1
1222      * @throws moodle_exception
1223      */
1224     public static function get_entries_by_term($id, $term, $from, $limit, $options) {
1225         $params = self::validate_parameters(self::get_entries_by_term_parameters(), array(
1226             'id' => $id,
1227             'term' => $term,
1228             'from' => $from,
1229             'limit' => $limit,
1230             'options' => $options,
1231         ));
1232         $id = $params['id'];
1233         $term = $params['term'];
1234         $from = $params['from'];
1235         $limit = $params['limit'];
1236         $options = $params['options'];
1237         $warnings = array();
1239         // Get and validate the glossary.
1240         list($glossary, $context) = self::validate_glossary($id);
1242         // Fetching the entries.
1243         $entries = array();
1244         list($records, $count) = glossary_get_entries_by_term($glossary, $context, $term, $from, $limit, $options);
1245         foreach ($records as $key => $record) {
1246             self::fill_entry_details($record, $context);
1247             $entries[] = $record;
1248         }
1250         return array(
1251             'count' => $count,
1252             'entries' => $entries,
1253             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
1254             'warnings' => $warnings
1255         );
1256     }
1258     /**
1259      * Returns the description of the external function return value.
1260      *
1261      * @return external_description
1262      * @since Moodle 3.1
1263      */
1264     public static function get_entries_by_term_returns() {
1265         return new external_single_structure(array(
1266             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
1267             'entries' => new external_multiple_structure(
1268                 self::get_entry_return_structure()
1269             ),
1270             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
1271             'warnings' => new external_warnings()
1272         ));
1273     }
1275     /**
1276      * Returns the description of the external function parameters.
1277      *
1278      * @return external_function_parameters
1279      * @since Moodle 3.1
1280      */
1281     public static function get_entries_to_approve_parameters() {
1282         return new external_function_parameters(array(
1283             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
1284             'letter' => new external_value(PARAM_ALPHA, 'A letter, or either keywords: \'ALL\' or \'SPECIAL\'.'),
1285             'order' => new external_value(PARAM_ALPHA, 'Order by: \'CONCEPT\', \'CREATION\' or \'UPDATE\'', VALUE_DEFAULT,
1286                 'CONCEPT'),
1287             'sort' => new external_value(PARAM_ALPHA, 'The direction of the order: \'ASC\' or \'DESC\'', VALUE_DEFAULT, 'ASC'),
1288             'from' => new external_value(PARAM_INT, 'Start returning records from here', VALUE_DEFAULT, 0),
1289             'limit' => new external_value(PARAM_INT, 'Number of records to return', VALUE_DEFAULT, 20),
1290             'options' => new external_single_structure(array(), 'An array of options', VALUE_DEFAULT, array())
1291         ));
1292     }
1294     /**
1295      * Browse a glossary entries using a term matching the concept or alias.
1296      *
1297      * @param int $id The glossary ID.
1298      * @param string $letter A letter, or a special keyword.
1299      * @param string $order The way to order the records.
1300      * @param string $sort The direction of the order.
1301      * @param int $from Start returning records from here.
1302      * @param int $limit Number of records to return.
1303      * @return array Containing count, entries and warnings.
1304      * @since Moodle 3.1
1305      * @throws moodle_exception
1306      */
1307     public static function get_entries_to_approve($id, $letter, $order, $sort, $from, $limit) {
1308         $params = self::validate_parameters(self::get_entries_to_approve_parameters(), array(
1309             'id' => $id,
1310             'letter' => $letter,
1311             'order' => $order,
1312             'sort' => $sort,
1313             'from' => $from,
1314             'limit' => $limit
1315         ));
1316         $id = $params['id'];
1317         $letter = $params['letter'];
1318         $order = $params['order'];
1319         $sort = $params['sort'];
1320         $from = $params['from'];
1321         $limit = $params['limit'];
1322         $warnings = array();
1324         // Get and validate the glossary.
1325         list($glossary, $context) = self::validate_glossary($id);
1327         // Check the permissions.
1328         require_capability('mod/glossary:approve', $context);
1330         // Fetching the entries.
1331         $entries = array();
1332         list($records, $count) = glossary_get_entries_to_approve($glossary, $context, $letter, $order, $sort, $from, $limit);
1333         foreach ($records as $key => $record) {
1334             self::fill_entry_details($record, $context);
1335             $entries[] = $record;
1336         }
1338         return array(
1339             'count' => $count,
1340             'entries' => $entries,
1341             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry', $entries),
1342             'warnings' => $warnings
1343         );
1344     }
1346     /**
1347      * Returns the description of the external function return value.
1348      *
1349      * @return external_description
1350      * @since Moodle 3.1
1351      */
1352     public static function get_entries_to_approve_returns() {
1353         return new external_single_structure(array(
1354             'count' => new external_value(PARAM_INT, 'The total number of records matching the request.'),
1355             'entries' => new external_multiple_structure(
1356                 self::get_entry_return_structure()
1357             ),
1358             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
1359             'warnings' => new external_warnings()
1360         ));
1361     }
1363     /**
1364      * Returns the description of the external function parameters.
1365      *
1366      * @return external_function_parameters
1367      * @since Moodle 3.1
1368      */
1369     public static function get_entry_by_id_parameters() {
1370         return new external_function_parameters(array(
1371             'id' => new external_value(PARAM_INT, 'Glossary entry ID'),
1372         ));
1373     }
1375     /**
1376      * Get an entry.
1377      *
1378      * @param int $id The entry ID.
1379      * @return array Containing entry and warnings.
1380      * @since Moodle 3.1
1381      * @throws moodle_exception
1382      * @throws invalid_parameter_exception
1383      */
1384     public static function get_entry_by_id($id) {
1385         global $DB, $USER;
1387         $params = self::validate_parameters(self::get_entry_by_id_parameters(), array('id' => $id));
1388         $id = $params['id'];
1389         $warnings = array();
1391         // Get and validate the glossary.
1392         $entry = $DB->get_record('glossary_entries', array('id' => $id), '*', MUST_EXIST);
1393         list($glossary, $context) = self::validate_glossary($entry->glossaryid);
1395         if (empty($entry->approved) && $entry->userid != $USER->id && !has_capability('mod/glossary:approve', $context)) {
1396             throw new invalid_parameter_exception('invalidentry');
1397         }
1399         $entry = glossary_get_entry_by_id($id);
1400         self::fill_entry_details($entry, $context);
1402         return array(
1403             'entry' => $entry,
1404             'ratinginfo' => \core_rating\external\util::get_rating_info($glossary, $context, 'mod_glossary', 'entry',
1405                 array($entry)),
1406             'warnings' => $warnings
1407         );
1408     }
1410     /**
1411      * Returns the description of the external function return value.
1412      *
1413      * @return external_description
1414      * @since Moodle 3.1
1415      */
1416     public static function get_entry_by_id_returns() {
1417         return new external_single_structure(array(
1418             'entry' => self::get_entry_return_structure(),
1419             'ratinginfo' => \core_rating\external\util::external_ratings_structure(),
1420             'warnings' => new external_warnings()
1421         ));
1422     }
1424     /**
1425      * Returns the description of the external function parameters.
1426      *
1427      * @return external_function_parameters
1428      * @since Moodle 3.2
1429      */
1430     public static function add_entry_parameters() {
1431         return new external_function_parameters(array(
1432             'glossaryid' => new external_value(PARAM_INT, 'Glossary id'),
1433             'concept' => new external_value(PARAM_TEXT, 'Glossary concept'),
1434             'definition' => new external_value(PARAM_RAW, 'Glossary concept definition'),
1435             'definitionformat' => new external_format_value('definition'),
1436             'options' => new external_multiple_structure (
1437                 new external_single_structure(
1438                     array(
1439                         'name' => new external_value(PARAM_ALPHANUM,
1440                             'The allowed keys (value format) are:
1441                             inlineattachmentsid (int); the draft file area id for inline attachments
1442                             attachmentsid (int); the draft file area id for attachments
1443                             categories (comma separated int); comma separated category ids
1444                             aliases (comma separated str); comma separated aliases
1445                             usedynalink (bool); whether the entry should be automatically linked.
1446                             casesensitive (bool); whether the entry is case sensitive.
1447                             fullmatch (bool); whether to match whole words only.'),
1448                         'value' => new external_value(PARAM_RAW, 'the value of the option (validated inside the function)')
1449                     )
1450                 ), 'Optional settings', VALUE_DEFAULT, array()
1451             )
1452         ));
1453     }
1456     /**
1457      * Add a new entry to a given glossary.
1458      *
1459      * @param int $glossaryid the glosary id
1460      * @param string $concept    the glossary concept
1461      * @param string $definition the concept definition
1462      * @param int $definitionformat the concept definition format
1463      * @param array  $options    additional settings
1464      * @return array Containing entry and warnings.
1465      * @since Moodle 3.2
1466      * @throws moodle_exception
1467      * @throws invalid_parameter_exception
1468      */
1469     public static function add_entry($glossaryid, $concept, $definition, $definitionformat, $options = array()) {
1470         global $CFG;
1472         $params = self::validate_parameters(self::add_entry_parameters(), array(
1473             'glossaryid' => $glossaryid,
1474             'concept' => $concept,
1475             'definition' => $definition,
1476             'definitionformat' => $definitionformat,
1477             'options' => $options,
1478         ));
1479         $warnings = array();
1481         // Get and validate the glossary.
1482         list($glossary, $context, $course, $cm) = self::validate_glossary($params['glossaryid']);
1483         require_capability('mod/glossary:write', $context);
1485         if (!$glossary->allowduplicatedentries) {
1486             if (glossary_concept_exists($glossary, $params['concept'])) {
1487                 throw new moodle_exception('errconceptalreadyexists', 'glossary');
1488             }
1489         }
1491         // Prepare the entry object.
1492         $entry = new stdClass;
1493         $entry->id = null;
1494         $entry->aliases = '';
1495         $entry->usedynalink = $CFG->glossary_linkentries;
1496         $entry->casesensitive = $CFG->glossary_casesensitive;
1497         $entry->fullmatch = $CFG->glossary_fullmatch;
1498         $entry->concept = $params['concept'];
1499         $entry->definition_editor = array(
1500             'text' => $params['definition'],
1501             'format' => $params['definitionformat'],
1502         );
1503         // Options.
1504         foreach ($params['options'] as $option) {
1505             $name = trim($option['name']);
1506             switch ($name) {
1507                 case 'inlineattachmentsid':
1508                     $entry->definition_editor['itemid'] = clean_param($option['value'], PARAM_INT);
1509                     break;
1510                 case 'attachmentsid':
1511                     $entry->attachment_filemanager = clean_param($option['value'], PARAM_INT);
1512                     break;
1513                 case 'categories':
1514                     $entry->categories = clean_param($option['value'], PARAM_SEQUENCE);
1515                     $entry->categories = explode(',', $entry->categories);
1516                     break;
1517                 case 'aliases':
1518                     $entry->aliases = clean_param($option['value'], PARAM_NOTAGS);
1519                     // Convert to the expected format.
1520                     $entry->aliases = str_replace(",", "\n", $entry->aliases);
1521                     break;
1522                 case 'usedynalink':
1523                 case 'casesensitive':
1524                 case 'fullmatch':
1525                     // Only allow if linking is enabled.
1526                     if ($glossary->usedynalink) {
1527                         $entry->{$name} = clean_param($option['value'], PARAM_BOOL);
1528                     }
1529                     break;
1530                 default:
1531                     throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
1532             }
1533         }
1535         $entry = glossary_edit_entry($entry, $course, $cm, $glossary, $context);
1537         return array(
1538             'entryid' => $entry->id,
1539             'warnings' => $warnings
1540         );
1541     }
1543     /**
1544      * Returns the description of the external function return value.
1545      *
1546      * @return external_description
1547      * @since Moodle 3.2
1548      */
1549     public static function add_entry_returns() {
1550         return new external_single_structure(array(
1551             'entryid' => new external_value(PARAM_INT, 'New glossary entry ID'),
1552             'warnings' => new external_warnings()
1553         ));
1554     }