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