See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
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/>. 16 17 /** 18 * Database module external API 19 * 20 * @package mod_data 21 * @category external 22 * @copyright 2015 Juan Leyva <juan@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 * @since Moodle 2.9 25 */ 26 27 defined('MOODLE_INTERNAL') || die; 28 29 require_once("$CFG->libdir/externallib.php"); 30 require_once($CFG->dirroot . "/mod/data/locallib.php"); 31 32 use mod_data\external\database_summary_exporter; 33 use mod_data\external\record_exporter; 34 use mod_data\external\content_exporter; 35 use mod_data\external\field_exporter; 36 use mod_data\manager; 37 38 /** 39 * Database module external functions 40 * 41 * @package mod_data 42 * @category external 43 * @copyright 2015 Juan Leyva <juan@moodle.com> 44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 45 * @since Moodle 2.9 46 */ 47 class mod_data_external extends external_api { 48 49 /** 50 * Describes the parameters for get_databases_by_courses. 51 * 52 * @return external_function_parameters 53 * @since Moodle 2.9 54 */ 55 public static function get_databases_by_courses_parameters() { 56 return new external_function_parameters ( 57 array( 58 'courseids' => new external_multiple_structure( 59 new external_value(PARAM_INT, 'course id', VALUE_REQUIRED), 60 'Array of course ids', VALUE_DEFAULT, array() 61 ), 62 ) 63 ); 64 } 65 66 /** 67 * Returns a list of databases in a provided list of courses, 68 * if no list is provided all databases that the user can view will be returned. 69 * 70 * @param array $courseids the course ids 71 * @return array the database details 72 * @since Moodle 2.9 73 */ 74 public static function get_databases_by_courses($courseids = array()) { 75 global $PAGE; 76 77 $params = self::validate_parameters(self::get_databases_by_courses_parameters(), array('courseids' => $courseids)); 78 $warnings = array(); 79 80 $mycourses = array(); 81 if (empty($params['courseids'])) { 82 $mycourses = enrol_get_my_courses(); 83 $params['courseids'] = array_keys($mycourses); 84 } 85 86 // Array to store the databases to return. 87 $arrdatabases = array(); 88 89 // Ensure there are courseids to loop through. 90 if (!empty($params['courseids'])) { 91 92 list($dbcourses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses); 93 94 // Get the databases in this course, this function checks users visibility permissions. 95 // We can avoid then additional validate_context calls. 96 $databases = get_all_instances_in_courses("data", $dbcourses); 97 98 foreach ($databases as $database) { 99 100 $context = context_module::instance($database->coursemodule); 101 // Remove fields added by get_all_instances_in_courses. 102 unset($database->coursemodule, $database->section, $database->visible, $database->groupmode, $database->groupingid); 103 104 // This information should be only available if the user can see the database entries. 105 if (!has_capability('mod/data:viewentry', $context)) { 106 $fields = array('comments', 'timeavailablefrom', 'timeavailableto', 'timeviewfrom', 107 'timeviewto', 'requiredentries', 'requiredentriestoview', 'maxentries', 'rssarticles', 108 'singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter', 'addtemplate', 109 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate', 'asearchtemplate', 'approval', 110 'manageapproved', 'defaultsort', 'defaultsortdir'); 111 112 foreach ($fields as $field) { 113 unset($database->{$field}); 114 } 115 } 116 117 // Check additional permissions for returning optional private settings. 118 // I avoid intentionally to use can_[add|update]_moduleinfo. 119 if (!has_capability('moodle/course:manageactivities', $context)) { 120 121 $fields = array('scale', 'assessed', 'assesstimestart', 'assesstimefinish', 'editany', 'notification', 122 'timemodified'); 123 124 foreach ($fields as $field) { 125 unset($database->{$field}); 126 } 127 } 128 $exporter = new database_summary_exporter($database, array('context' => $context)); 129 $data = $exporter->export($PAGE->get_renderer('core')); 130 $data->name = external_format_string($data->name, $context); 131 $arrdatabases[] = $data; 132 } 133 } 134 135 $result = array(); 136 $result['databases'] = $arrdatabases; 137 $result['warnings'] = $warnings; 138 return $result; 139 } 140 141 /** 142 * Describes the get_databases_by_courses return value. 143 * 144 * @return external_single_structure 145 * @since Moodle 2.9 146 */ 147 public static function get_databases_by_courses_returns() { 148 149 return new external_single_structure( 150 array( 151 'databases' => new external_multiple_structure( 152 database_summary_exporter::get_read_structure() 153 ), 154 'warnings' => new external_warnings(), 155 ) 156 ); 157 } 158 159 /** 160 * Utility function for validating a database. 161 * 162 * @param int $databaseid database instance id 163 * @return array array containing the database object, course, context and course module objects 164 * @since Moodle 3.3 165 */ 166 protected static function validate_database($databaseid) { 167 global $DB; 168 169 // Request and permission validation. 170 $database = $DB->get_record('data', array('id' => $databaseid), '*', MUST_EXIST); 171 list($course, $cm) = get_course_and_cm_from_instance($database, 'data'); 172 173 $context = context_module::instance($cm->id); 174 self::validate_context($context); 175 require_capability('mod/data:viewentry', $context); 176 177 return array($database, $course, $cm, $context); 178 } 179 180 /** 181 * Returns description of method parameters 182 * 183 * @return external_function_parameters 184 * @since Moodle 3.3 185 */ 186 public static function view_database_parameters() { 187 return new external_function_parameters( 188 array( 189 'databaseid' => new external_value(PARAM_INT, 'data instance id') 190 ) 191 ); 192 } 193 194 /** 195 * Simulate the data/view.php web interface page: trigger events, completion, etc... 196 * 197 * @param int $databaseid the data instance id 198 * @return array of warnings and status result 199 * @since Moodle 3.3 200 * @throws moodle_exception 201 */ 202 public static function view_database($databaseid) { 203 204 $params = self::validate_parameters(self::view_database_parameters(), array('databaseid' => $databaseid)); 205 $warnings = array(); 206 207 list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); 208 209 // Call the data/lib API. 210 $manager = manager::create_from_coursemodule($cm); 211 $manager->set_module_viewed($course); 212 213 $result = [ 214 'status' => true, 215 'warnings' => $warnings, 216 ]; 217 return $result; 218 } 219 220 /** 221 * Returns description of method result value 222 * 223 * @return external_description 224 * @since Moodle 3.3 225 */ 226 public static function view_database_returns() { 227 return new external_single_structure( 228 array( 229 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 230 'warnings' => new external_warnings() 231 ) 232 ); 233 } 234 235 /** 236 * Returns description of method parameters. 237 * 238 * @return external_function_parameters 239 * @since Moodle 3.3 240 */ 241 public static function get_data_access_information_parameters() { 242 return new external_function_parameters( 243 array( 244 'databaseid' => new external_value(PARAM_INT, 'Database instance id.'), 245 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group.', 246 VALUE_DEFAULT, 0), 247 ) 248 ); 249 } 250 251 /** 252 * Return access information for a given database. 253 * 254 * @param int $databaseid the database instance id 255 * @param int $groupid (optional) group id, 0 means that the function will determine the user group 256 * @return array of warnings and access information 257 * @since Moodle 3.3 258 * @throws moodle_exception 259 */ 260 public static function get_data_access_information($databaseid, $groupid = 0) { 261 262 $params = array('databaseid' => $databaseid, 'groupid' => $groupid); 263 $params = self::validate_parameters(self::get_data_access_information_parameters(), $params); 264 $warnings = array(); 265 266 list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); 267 268 $result = array( 269 'warnings' => $warnings 270 ); 271 272 $groupmode = groups_get_activity_groupmode($cm); 273 if (!empty($params['groupid'])) { 274 $groupid = $params['groupid']; 275 // Determine is the group is visible to user. 276 if (!groups_group_visible($groupid, $course, $cm)) { 277 throw new moodle_exception('notingroup'); 278 } 279 } else { 280 // Check to see if groups are being used here. 281 if ($groupmode) { 282 $groupid = groups_get_activity_group($cm); 283 } else { 284 $groupid = 0; 285 } 286 } 287 // Group related information. 288 $result['groupid'] = $groupid; 289 $result['canaddentry'] = data_user_can_add_entry($database, $groupid, $groupmode, $context); 290 291 // Now capabilities. 292 $result['canmanageentries'] = has_capability('mod/data:manageentries', $context); 293 $result['canapprove'] = has_capability('mod/data:approve', $context); 294 295 // Now time access restrictions. 296 list($result['timeavailable'], $warnings) = data_get_time_availability_status($database, $result['canmanageentries']); 297 298 // Other information. 299 $result['numentries'] = data_numentries($database); 300 $result['entrieslefttoadd'] = data_get_entries_left_to_add($database, $result['numentries'], $result['canmanageentries']); 301 $result['entrieslefttoview'] = data_get_entries_left_to_view($database, $result['numentries'], $result['canmanageentries']); 302 $result['inreadonlyperiod'] = data_in_readonly_period($database); 303 304 return $result; 305 } 306 307 /** 308 * Returns description of method result value. 309 * 310 * @return external_description 311 * @since Moodle 3.3 312 */ 313 public static function get_data_access_information_returns() { 314 return new external_single_structure( 315 array( 316 'groupid' => new external_value(PARAM_INT, 'User current group id (calculated)'), 317 'canaddentry' => new external_value(PARAM_BOOL, 'Whether the user can add entries or not.'), 318 'canmanageentries' => new external_value(PARAM_BOOL, 'Whether the user can manage entries or not.'), 319 'canapprove' => new external_value(PARAM_BOOL, 'Whether the user can approve entries or not.'), 320 'timeavailable' => new external_value(PARAM_BOOL, 'Whether the database is available or not by time restrictions.'), 321 'inreadonlyperiod' => new external_value(PARAM_BOOL, 'Whether the database is in read mode only.'), 322 'numentries' => new external_value(PARAM_INT, 'The number of entries the current user added.'), 323 'entrieslefttoadd' => new external_value(PARAM_INT, 'The number of entries left to complete the activity.'), 324 'entrieslefttoview' => new external_value(PARAM_INT, 'The number of entries left to view other users entries.'), 325 'warnings' => new external_warnings() 326 ) 327 ); 328 } 329 330 /** 331 * Returns description of method parameters 332 * 333 * @return external_function_parameters 334 * @since Moodle 3.3 335 */ 336 public static function get_entries_parameters() { 337 return new external_function_parameters( 338 array( 339 'databaseid' => new external_value(PARAM_INT, 'data instance id'), 340 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group', 341 VALUE_DEFAULT, 0), 342 'returncontents' => new external_value(PARAM_BOOL, 'Whether to return contents or not. This will return each entry 343 raw contents and the complete list view (using the template).', 344 VALUE_DEFAULT, false), 345 'sort' => new external_value(PARAM_INT, 'Sort the records by this field id, reserved ids are: 346 0: timeadded 347 -1: firstname 348 -2: lastname 349 -3: approved 350 -4: timemodified. 351 Empty for using the default database setting.', VALUE_DEFAULT, null), 352 'order' => new external_value(PARAM_ALPHA, 'The direction of the sorting: \'ASC\' or \'DESC\'. 353 Empty for using the default database setting.', VALUE_DEFAULT, null), 354 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0), 355 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page', VALUE_DEFAULT, 0), 356 ) 357 ); 358 } 359 360 /** 361 * Return access information for a given feedback 362 * 363 * @param int $databaseid the data instance id 364 * @param int $groupid (optional) group id, 0 means that the function will determine the user group 365 * @param bool $returncontents Whether to return the entries contents or not 366 * @param str $sort sort by this field 367 * @param int $order the direction of the sorting 368 * @param int $page page of records to return 369 * @param int $perpage number of records to return per page 370 * @return array of warnings and the entries 371 * @since Moodle 3.3 372 * @throws moodle_exception 373 */ 374 public static function get_entries($databaseid, $groupid = 0, $returncontents = false, $sort = null, $order = null, 375 $page = 0, $perpage = 0) { 376 global $PAGE, $DB; 377 378 $params = array('databaseid' => $databaseid, 'groupid' => $groupid, 'returncontents' => $returncontents , 379 'sort' => $sort, 'order' => $order, 'page' => $page, 'perpage' => $perpage); 380 $params = self::validate_parameters(self::get_entries_parameters(), $params); 381 $warnings = array(); 382 383 if (!empty($params['order'])) { 384 $params['order'] = strtoupper($params['order']); 385 if ($params['order'] != 'ASC' && $params['order'] != 'DESC') { 386 throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $params['order'] . ')'); 387 } 388 } 389 390 list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); 391 // Check database is open in time. 392 data_require_time_available($database, null, $context); 393 394 if (!empty($params['groupid'])) { 395 $groupid = $params['groupid']; 396 // Determine is the group is visible to user. 397 if (!groups_group_visible($groupid, $course, $cm)) { 398 throw new moodle_exception('notingroup'); 399 } 400 } else { 401 // Check to see if groups are being used here. 402 if ($groupmode = groups_get_activity_groupmode($cm)) { 403 // We don't need to validate a possible groupid = 0 since it would be handled by data_search_entries. 404 $groupid = groups_get_activity_group($cm); 405 } else { 406 $groupid = 0; 407 } 408 } 409 410 $manager = manager::create_from_instance($database); 411 412 list($records, $maxcount, $totalcount, $page, $nowperpage, $sort, $mode) = 413 data_search_entries($database, $cm, $context, 'list', $groupid, '', $params['sort'], $params['order'], 414 $params['page'], $params['perpage']); 415 416 $entries = []; 417 $contentsids = []; // Store here the content ids of the records returned. 418 foreach ($records as $record) { 419 $user = user_picture::unalias($record, null, 'userid'); 420 $related = array('context' => $context, 'database' => $database, 'user' => $user); 421 422 $contents = $DB->get_records('data_content', array('recordid' => $record->id)); 423 $contentsids = array_merge($contentsids, array_keys($contents)); 424 if ($params['returncontents']) { 425 $related['contents'] = $contents; 426 } else { 427 $related['contents'] = null; 428 } 429 430 $exporter = new record_exporter($record, $related); 431 $entries[] = $exporter->export($PAGE->get_renderer('core')); 432 } 433 434 // Retrieve total files size for the records retrieved. 435 $totalfilesize = 0; 436 $fs = get_file_storage(); 437 $files = $fs->get_area_files($context->id, 'mod_data', 'content'); 438 foreach ($files as $file) { 439 if ($file->is_directory() || !in_array($file->get_itemid(), $contentsids)) { 440 continue; 441 } 442 $totalfilesize += $file->get_filesize(); 443 } 444 445 $result = array( 446 'entries' => $entries, 447 'totalcount' => $totalcount, 448 'totalfilesize' => $totalfilesize, 449 'warnings' => $warnings 450 ); 451 452 // Check if we should return the list rendered. 453 if ($params['returncontents']) { 454 $parser = $manager->get_template('listtemplate', ['page' => $page]); 455 $result['listviewcontents'] = $parser->parse_entries($records); 456 } 457 458 return $result; 459 } 460 461 /** 462 * Returns description of method result value 463 * 464 * @return external_description 465 * @since Moodle 3.3 466 */ 467 public static function get_entries_returns() { 468 return new external_single_structure( 469 array( 470 'entries' => new external_multiple_structure( 471 record_exporter::get_read_structure() 472 ), 473 'totalcount' => new external_value(PARAM_INT, 'Total count of records.'), 474 'totalfilesize' => new external_value(PARAM_INT, 'Total size (bytes) of the files included in the records.'), 475 'listviewcontents' => new external_value(PARAM_RAW, 'The list view contents as is rendered in the site.', 476 VALUE_OPTIONAL), 477 'warnings' => new external_warnings() 478 ) 479 ); 480 } 481 482 /** 483 * Returns description of method parameters 484 * 485 * @return external_function_parameters 486 * @since Moodle 3.3 487 */ 488 public static function get_entry_parameters() { 489 return new external_function_parameters( 490 array( 491 'entryid' => new external_value(PARAM_INT, 'record entry id'), 492 'returncontents' => new external_value(PARAM_BOOL, 'Whether to return contents or not.', VALUE_DEFAULT, false), 493 ) 494 ); 495 } 496 497 /** 498 * Return one entry record from the database, including contents optionally. 499 * 500 * @param int $entryid the record entry id id 501 * @param bool $returncontents whether to return the entries contents or not 502 * @return array of warnings and the entries 503 * @since Moodle 3.3 504 * @throws moodle_exception 505 */ 506 public static function get_entry($entryid, $returncontents = false) { 507 global $PAGE, $DB; 508 509 $params = array('entryid' => $entryid, 'returncontents' => $returncontents); 510 $params = self::validate_parameters(self::get_entry_parameters(), $params); 511 $warnings = array(); 512 513 $record = $DB->get_record('data_records', array('id' => $params['entryid']), '*', MUST_EXIST); 514 list($database, $course, $cm, $context) = self::validate_database($record->dataid); 515 516 // Check database is open in time. 517 $canmanageentries = has_capability('mod/data:manageentries', $context); 518 data_require_time_available($database, $canmanageentries); 519 520 $manager = manager::create_from_instance($database); 521 522 if ($record->groupid != 0) { 523 if (!groups_group_visible($record->groupid, $course, $cm)) { 524 throw new moodle_exception('notingroup'); 525 } 526 } 527 528 // Check correct record entry. Group check was done before. 529 if (!data_can_view_record($database, $record, $record->groupid, $canmanageentries)) { 530 throw new moodle_exception('notapprovederror', 'data'); 531 } 532 533 $related = array('context' => $context, 'database' => $database, 'user' => null); 534 if ($params['returncontents']) { 535 $related['contents'] = $DB->get_records('data_content', array('recordid' => $record->id)); 536 } else { 537 $related['contents'] = null; 538 } 539 $exporter = new record_exporter($record, $related); 540 $entry = $exporter->export($PAGE->get_renderer('core')); 541 542 $result = array( 543 'entry' => $entry, 544 'ratinginfo' => \core_rating\external\util::get_rating_info($database, $context, 'mod_data', 'entry', array($record)), 545 'warnings' => $warnings 546 ); 547 // Check if we should return the entry rendered. 548 if ($params['returncontents']) { 549 $records = [$record]; 550 $parser = $manager->get_template('singletemplate'); 551 $result['entryviewcontents'] = $parser->parse_entries($records); 552 } 553 554 return $result; 555 } 556 557 /** 558 * Returns description of method result value 559 * 560 * @return external_description 561 * @since Moodle 3.3 562 */ 563 public static function get_entry_returns() { 564 return new external_single_structure( 565 array( 566 'entry' => record_exporter::get_read_structure(), 567 'entryviewcontents' => new external_value(PARAM_RAW, 'The entry as is rendered in the site.', VALUE_OPTIONAL), 568 'ratinginfo' => \core_rating\external\util::external_ratings_structure(), 569 'warnings' => new external_warnings() 570 ) 571 ); 572 } 573 574 /** 575 * Returns description of method parameters 576 * 577 * @return external_function_parameters 578 * @since Moodle 3.3 579 */ 580 public static function get_fields_parameters() { 581 return new external_function_parameters( 582 array( 583 'databaseid' => new external_value(PARAM_INT, 'Database instance id.'), 584 ) 585 ); 586 } 587 588 /** 589 * Return the list of configured fields for the given database. 590 * 591 * @param int $databaseid the database id 592 * @return array of warnings and the fields 593 * @since Moodle 3.3 594 * @throws moodle_exception 595 */ 596 public static function get_fields($databaseid) { 597 global $PAGE; 598 599 $params = array('databaseid' => $databaseid); 600 $params = self::validate_parameters(self::get_fields_parameters(), $params); 601 $fields = $warnings = array(); 602 603 list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); 604 605 // Check database is open in time. 606 $canmanageentries = has_capability('mod/data:manageentries', $context); 607 data_require_time_available($database, $canmanageentries); 608 609 $fieldinstances = data_get_field_instances($database); 610 611 foreach ($fieldinstances as $fieldinstance) { 612 $record = $fieldinstance->field; 613 // Now get the configs the user can see with his current permissions. 614 $configs = $fieldinstance->get_config_for_external(); 615 foreach ($configs as $name => $value) { 616 // Overwrite. 617 $record->{$name} = $value; 618 } 619 620 $exporter = new field_exporter($record, array('context' => $context)); 621 $fields[] = $exporter->export($PAGE->get_renderer('core')); 622 } 623 624 $result = array( 625 'fields' => $fields, 626 'warnings' => $warnings 627 ); 628 return $result; 629 } 630 631 /** 632 * Returns description of method result value 633 * 634 * @return external_description 635 * @since Moodle 3.3 636 */ 637 public static function get_fields_returns() { 638 return new external_single_structure( 639 array( 640 'fields' => new external_multiple_structure( 641 field_exporter::get_read_structure() 642 ), 643 'warnings' => new external_warnings() 644 ) 645 ); 646 } 647 648 /** 649 * Returns description of method parameters 650 * 651 * @return external_function_parameters 652 * @since Moodle 3.3 653 */ 654 public static function search_entries_parameters() { 655 return new external_function_parameters( 656 array( 657 'databaseid' => new external_value(PARAM_INT, 'data instance id'), 658 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group', 659 VALUE_DEFAULT, 0), 660 'returncontents' => new external_value(PARAM_BOOL, 'Whether to return contents or not.', VALUE_DEFAULT, false), 661 'search' => new external_value(PARAM_NOTAGS, 'search string (empty when using advanced)', VALUE_DEFAULT, ''), 662 'advsearch' => new external_multiple_structure( 663 new external_single_structure( 664 array( 665 'name' => new external_value(PARAM_ALPHANUMEXT, 'Field key for search. 666 Use fn or ln for first or last name'), 667 'value' => new external_value(PARAM_RAW, 'JSON encoded value for search'), 668 ) 669 ), 'Advanced search', VALUE_DEFAULT, array() 670 ), 671 'sort' => new external_value(PARAM_INT, 'Sort the records by this field id, reserved ids are: 672 0: timeadded 673 -1: firstname 674 -2: lastname 675 -3: approved 676 -4: timemodified. 677 Empty for using the default database setting.', VALUE_DEFAULT, null), 678 'order' => new external_value(PARAM_ALPHA, 'The direction of the sorting: \'ASC\' or \'DESC\'. 679 Empty for using the default database setting.', VALUE_DEFAULT, null), 680 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0), 681 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page', VALUE_DEFAULT, 0), 682 ) 683 ); 684 } 685 686 /** 687 * Return access information for a given feedback 688 * 689 * @param int $databaseid the data instance id 690 * @param int $groupid (optional) group id, 0 means that the function will determine the user group 691 * @param bool $returncontents whether to return contents or not 692 * @param str $search search text 693 * @param array $advsearch advanced search data 694 * @param str $sort sort by this field 695 * @param int $order the direction of the sorting 696 * @param int $page page of records to return 697 * @param int $perpage number of records to return per page 698 * @return array of warnings and the entries 699 * @since Moodle 3.3 700 * @throws moodle_exception 701 */ 702 public static function search_entries($databaseid, $groupid = 0, $returncontents = false, $search = '', $advsearch = [], 703 $sort = null, $order = null, $page = 0, $perpage = 0) { 704 global $PAGE, $DB; 705 706 $params = array('databaseid' => $databaseid, 'groupid' => $groupid, 'returncontents' => $returncontents, 'search' => $search, 707 'advsearch' => $advsearch, 'sort' => $sort, 'order' => $order, 'page' => $page, 'perpage' => $perpage); 708 $params = self::validate_parameters(self::search_entries_parameters(), $params); 709 $warnings = array(); 710 711 if (!empty($params['order'])) { 712 $params['order'] = strtoupper($params['order']); 713 if ($params['order'] != 'ASC' && $params['order'] != 'DESC') { 714 throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $params['order'] . ')'); 715 } 716 } 717 718 list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); 719 // Check database is open in time. 720 data_require_time_available($database, null, $context); 721 722 $manager = manager::create_from_instance($database); 723 724 if (!empty($params['groupid'])) { 725 $groupid = $params['groupid']; 726 // Determine is the group is visible to user. 727 if (!groups_group_visible($groupid, $course, $cm)) { 728 throw new moodle_exception('notingroup'); 729 } 730 } else { 731 // Check to see if groups are being used here. 732 if ($groupmode = groups_get_activity_groupmode($cm)) { 733 // We don't need to validate a possible groupid = 0 since it would be handled by data_search_entries. 734 $groupid = groups_get_activity_group($cm); 735 } else { 736 $groupid = 0; 737 } 738 } 739 740 if (!empty($params['advsearch'])) { 741 $advanced = true; 742 $defaults = []; 743 $fn = $ln = ''; // Defaults for first and last name. 744 // Force defaults for advanced search. 745 foreach ($params['advsearch'] as $adv) { 746 if ($adv['name'] == 'fn') { 747 $fn = json_decode($adv['value']); 748 continue; 749 } 750 if ($adv['name'] == 'ln') { 751 $ln = json_decode($adv['value']); 752 continue; 753 } 754 $defaults[$adv['name']] = json_decode($adv['value']); 755 } 756 list($searcharray, $params['search']) = data_build_search_array($database, false, [], $defaults, $fn, $ln); 757 } else { 758 $advanced = null; 759 $searcharray = null; 760 } 761 762 list($records, $maxcount, $totalcount, $page, $nowperpage, $sort, $mode) = 763 data_search_entries($database, $cm, $context, 'list', $groupid, $params['search'], $params['sort'], $params['order'], 764 $params['page'], $params['perpage'], $advanced, $searcharray); 765 766 $entries = []; 767 foreach ($records as $record) { 768 $user = user_picture::unalias($record, null, 'userid'); 769 $related = array('context' => $context, 'database' => $database, 'user' => $user); 770 if ($params['returncontents']) { 771 $related['contents'] = $DB->get_records('data_content', array('recordid' => $record->id)); 772 } else { 773 $related['contents'] = null; 774 } 775 776 $exporter = new record_exporter($record, $related); 777 $entries[] = $exporter->export($PAGE->get_renderer('core')); 778 } 779 780 $result = array( 781 'entries' => $entries, 782 'totalcount' => $totalcount, 783 'maxcount' => $maxcount, 784 'warnings' => $warnings 785 ); 786 787 // Check if we should return the list rendered. 788 if ($params['returncontents']) { 789 $parser = $manager->get_template('listtemplate', ['page' => $page]); 790 $result['listviewcontents'] = $parser->parse_entries($records); 791 } 792 793 return $result; 794 } 795 796 /** 797 * Returns description of method result value 798 * 799 * @return external_description 800 * @since Moodle 3.3 801 */ 802 public static function search_entries_returns() { 803 return new external_single_structure( 804 array( 805 'entries' => new external_multiple_structure( 806 record_exporter::get_read_structure() 807 ), 808 'totalcount' => new external_value(PARAM_INT, 'Total count of records returned by the search.'), 809 'maxcount' => new external_value(PARAM_INT, 'Total count of records that the user could see in the database 810 (if all the search criterias were removed).', VALUE_OPTIONAL), 811 'listviewcontents' => new external_value(PARAM_RAW, 'The list view contents as is rendered in the site.', 812 VALUE_OPTIONAL), 813 'warnings' => new external_warnings() 814 ) 815 ); 816 } 817 818 /** 819 * Returns description of method parameters 820 * 821 * @return external_function_parameters 822 * @since Moodle 3.3 823 */ 824 public static function approve_entry_parameters() { 825 return new external_function_parameters( 826 array( 827 'entryid' => new external_value(PARAM_INT, 'Record entry id.'), 828 'approve' => new external_value(PARAM_BOOL, 'Whether to approve (true) or unapprove the entry.', 829 VALUE_DEFAULT, true), 830 ) 831 ); 832 } 833 834 /** 835 * Approves or unapproves an entry. 836 * 837 * @param int $entryid the record entry id id 838 * @param bool $approve whether to approve (true) or unapprove the entry 839 * @return array of warnings and the entries 840 * @since Moodle 3.3 841 * @throws moodle_exception 842 */ 843 public static function approve_entry($entryid, $approve = true) { 844 global $PAGE, $DB; 845 846 $params = array('entryid' => $entryid, 'approve' => $approve); 847 $params = self::validate_parameters(self::approve_entry_parameters(), $params); 848 $warnings = array(); 849 850 $record = $DB->get_record('data_records', array('id' => $params['entryid']), '*', MUST_EXIST); 851 list($database, $course, $cm, $context) = self::validate_database($record->dataid); 852 // Check database is open in time. 853 data_require_time_available($database, null, $context); 854 // Check specific capabilities. 855 require_capability('mod/data:approve', $context); 856 857 data_approve_entry($record->id, $params['approve']); 858 859 $result = array( 860 'status' => true, 861 'warnings' => $warnings 862 ); 863 return $result; 864 } 865 866 /** 867 * Returns description of method result value 868 * 869 * @return external_description 870 * @since Moodle 3.3 871 */ 872 public static function approve_entry_returns() { 873 return new external_single_structure( 874 array( 875 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 876 'warnings' => new external_warnings() 877 ) 878 ); 879 } 880 881 /** 882 * Returns description of method parameters 883 * 884 * @return external_function_parameters 885 * @since Moodle 3.3 886 */ 887 public static function delete_entry_parameters() { 888 return new external_function_parameters( 889 array( 890 'entryid' => new external_value(PARAM_INT, 'Record entry id.'), 891 ) 892 ); 893 } 894 895 /** 896 * Deletes an entry. 897 * 898 * @param int $entryid the record entry id 899 * @return array of warnings success status 900 * @since Moodle 3.3 901 * @throws moodle_exception 902 */ 903 public static function delete_entry($entryid) { 904 global $PAGE, $DB; 905 906 $params = array('entryid' => $entryid); 907 $params = self::validate_parameters(self::delete_entry_parameters(), $params); 908 $warnings = array(); 909 910 $record = $DB->get_record('data_records', array('id' => $params['entryid']), '*', MUST_EXIST); 911 list($database, $course, $cm, $context) = self::validate_database($record->dataid); 912 913 if (data_user_can_manage_entry($record, $database, $context)) { 914 data_delete_record($record->id, $database, $course->id, $cm->id); 915 } else { 916 throw new moodle_exception('noaccess', 'data'); 917 } 918 919 $result = array( 920 'status' => true, 921 'warnings' => $warnings 922 ); 923 return $result; 924 } 925 926 /** 927 * Returns description of method result value 928 * 929 * @return external_description 930 * @since Moodle 3.3 931 */ 932 public static function delete_entry_returns() { 933 return new external_single_structure( 934 array( 935 'status' => new external_value(PARAM_BOOL, 'Always true. If we see this field it means that the entry was deleted.'), 936 'warnings' => new external_warnings() 937 ) 938 ); 939 } 940 941 /** 942 * Returns description of method parameters 943 * 944 * @return external_function_parameters 945 * @since Moodle 3.3 946 */ 947 public static function add_entry_parameters() { 948 return new external_function_parameters( 949 array( 950 'databaseid' => new external_value(PARAM_INT, 'data instance id'), 951 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group', 952 VALUE_DEFAULT, 0), 953 'data' => new external_multiple_structure( 954 new external_single_structure( 955 array( 956 'fieldid' => new external_value(PARAM_INT, 'The field id.'), 957 'subfield' => new external_value(PARAM_NOTAGS, 'The subfield name (if required).', VALUE_DEFAULT, ''), 958 'value' => new external_value(PARAM_RAW, 'The contents for the field always JSON encoded.'), 959 ) 960 ), 'The fields data to be created' 961 ), 962 ) 963 ); 964 } 965 966 /** 967 * Adds a new entry to a database 968 * 969 * @param int $databaseid the data instance id 970 * @param int $groupid (optional) group id, 0 means that the function will determine the user group 971 * @param array $data the fields data to be created 972 * @return array of warnings and status result 973 * @since Moodle 3.3 974 * @throws moodle_exception 975 */ 976 public static function add_entry($databaseid, $groupid, $data) { 977 global $DB; 978 979 $params = array('databaseid' => $databaseid, 'groupid' => $groupid, 'data' => $data); 980 $params = self::validate_parameters(self::add_entry_parameters(), $params); 981 $warnings = array(); 982 $fieldnotifications = array(); 983 984 list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); 985 986 $fields = $DB->get_records('data_fields', ['dataid' => $database->id]); 987 if (empty($fields)) { 988 throw new moodle_exception('nofieldindatabase', 'data'); 989 } 990 991 // Check database is open in time. 992 data_require_time_available($database, null, $context); 993 994 $groupmode = groups_get_activity_groupmode($cm); 995 // Determine default group. 996 if (empty($params['groupid'])) { 997 // Check to see if groups are being used here. 998 if ($groupmode) { 999 $groupid = groups_get_activity_group($cm); 1000 } else { 1001 $groupid = 0; 1002 } 1003 } 1004 1005 // Group is validated inside the function. 1006 if (!data_user_can_add_entry($database, $groupid, $groupmode, $context)) { 1007 throw new moodle_exception('noaccess', 'data'); 1008 } 1009 1010 // Prepare the data as is expected by the API. 1011 $datarecord = new stdClass; 1012 foreach ($params['data'] as $data) { 1013 $subfield = ($data['subfield'] !== '') ? '_' . $data['subfield'] : ''; 1014 // We ask for JSON encoded values because of multiple choice forms or checkboxes that use array parameters. 1015 $datarecord->{'field_' . $data['fieldid'] . $subfield} = json_decode($data['value']); 1016 } 1017 // Validate to ensure that enough data was submitted. 1018 $processeddata = data_process_submission($database, $fields, $datarecord); 1019 1020 // Format notifications. 1021 if (!empty($processeddata->fieldnotifications)) { 1022 foreach ($processeddata->fieldnotifications as $field => $notififications) { 1023 foreach ($notififications as $notif) { 1024 $fieldnotifications[] = [ 1025 'fieldname' => $field, 1026 'notification' => $notif, 1027 ]; 1028 } 1029 } 1030 } 1031 1032 // Create a new (empty) record. 1033 $newentryid = 0; 1034 if ($processeddata->validated && $recordid = data_add_record($database, $groupid)) { 1035 $newentryid = $recordid; 1036 // Now populate the fields contents of the new record. 1037 data_add_fields_contents_to_new_record($database, $context, $recordid, $fields, $datarecord, $processeddata); 1038 } 1039 1040 $result = array( 1041 'newentryid' => $newentryid, 1042 'generalnotifications' => $processeddata->generalnotifications, 1043 'fieldnotifications' => $fieldnotifications, 1044 ); 1045 return $result; 1046 } 1047 1048 /** 1049 * Returns description of method result value 1050 * 1051 * @return external_description 1052 * @since Moodle 3.3 1053 */ 1054 public static function add_entry_returns() { 1055 return new external_single_structure( 1056 array( 1057 'newentryid' => new external_value(PARAM_INT, 'True new created entry id. 0 if the entry was not created.'), 1058 'generalnotifications' => new external_multiple_structure( 1059 new external_value(PARAM_RAW, 'General notifications') 1060 ), 1061 'fieldnotifications' => new external_multiple_structure( 1062 new external_single_structure( 1063 array( 1064 'fieldname' => new external_value(PARAM_TEXT, 'The field name.'), 1065 'notification' => new external_value(PARAM_RAW, 'The notification for the field.'), 1066 ) 1067 ) 1068 ), 1069 'warnings' => new external_warnings() 1070 ) 1071 ); 1072 } 1073 1074 /** 1075 * Returns description of method parameters 1076 * 1077 * @return external_function_parameters 1078 * @since Moodle 3.3 1079 */ 1080 public static function update_entry_parameters() { 1081 return new external_function_parameters( 1082 array( 1083 'entryid' => new external_value(PARAM_INT, 'The entry record id.'), 1084 'data' => new external_multiple_structure( 1085 new external_single_structure( 1086 array( 1087 'fieldid' => new external_value(PARAM_INT, 'The field id.'), 1088 'subfield' => new external_value(PARAM_NOTAGS, 'The subfield name (if required).', VALUE_DEFAULT, null), 1089 'value' => new external_value(PARAM_RAW, 'The new contents for the field always JSON encoded.'), 1090 ) 1091 ), 'The fields data to be updated' 1092 ), 1093 ) 1094 ); 1095 } 1096 1097 /** 1098 * Updates an existing entry. 1099 * 1100 * @param int $entryid the data instance id 1101 * @param array $data the fields data to be created 1102 * @return array of warnings and status result 1103 * @since Moodle 3.3 1104 * @throws moodle_exception 1105 */ 1106 public static function update_entry($entryid, $data) { 1107 global $DB; 1108 1109 $params = array('entryid' => $entryid, 'data' => $data); 1110 $params = self::validate_parameters(self::update_entry_parameters(), $params); 1111 $warnings = array(); 1112 $fieldnotifications = array(); 1113 $updated = false; 1114 1115 $record = $DB->get_record('data_records', array('id' => $params['entryid']), '*', MUST_EXIST); 1116 list($database, $course, $cm, $context) = self::validate_database($record->dataid); 1117 // Check database is open in time. 1118 data_require_time_available($database, null, $context); 1119 1120 if (!data_user_can_manage_entry($record, $database, $context)) { 1121 throw new moodle_exception('noaccess', 'data'); 1122 } 1123 1124 // Prepare the data as is expected by the API. 1125 $datarecord = new stdClass; 1126 foreach ($params['data'] as $data) { 1127 $subfield = ($data['subfield'] !== '') ? '_' . $data['subfield'] : ''; 1128 // We ask for JSON encoded values because of multiple choice forms or checkboxes that use array parameters. 1129 $datarecord->{'field_' . $data['fieldid'] . $subfield} = json_decode($data['value']); 1130 } 1131 // Validate to ensure that enough data was submitted. 1132 $fields = $DB->get_records('data_fields', array('dataid' => $database->id)); 1133 $processeddata = data_process_submission($database, $fields, $datarecord); 1134 1135 // Format notifications. 1136 if (!empty($processeddata->fieldnotifications)) { 1137 foreach ($processeddata->fieldnotifications as $field => $notififications) { 1138 foreach ($notififications as $notif) { 1139 $fieldnotifications[] = [ 1140 'fieldname' => $field, 1141 'notification' => $notif, 1142 ]; 1143 } 1144 } 1145 } 1146 1147 if ($processeddata->validated) { 1148 // Now update the fields contents. 1149 data_update_record_fields_contents($database, $record, $context, $datarecord, $processeddata); 1150 $updated = true; 1151 } 1152 1153 $result = array( 1154 'updated' => $updated, 1155 'generalnotifications' => $processeddata->generalnotifications, 1156 'fieldnotifications' => $fieldnotifications, 1157 'warnings' => $warnings, 1158 ); 1159 return $result; 1160 } 1161 1162 /** 1163 * Returns description of method result value 1164 * 1165 * @return external_description 1166 * @since Moodle 3.3 1167 */ 1168 public static function update_entry_returns() { 1169 return new external_single_structure( 1170 array( 1171 'updated' => new external_value(PARAM_BOOL, 'True if the entry was successfully updated, false other wise.'), 1172 'generalnotifications' => new external_multiple_structure( 1173 new external_value(PARAM_RAW, 'General notifications') 1174 ), 1175 'fieldnotifications' => new external_multiple_structure( 1176 new external_single_structure( 1177 array( 1178 'fieldname' => new external_value(PARAM_TEXT, 'The field name.'), 1179 'notification' => new external_value(PARAM_RAW, 'The notification for the field.'), 1180 ) 1181 ) 1182 ), 1183 'warnings' => new external_warnings() 1184 ) 1185 ); 1186 } 1187 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body