MDL-49409 mod_data: New Web Service mod_data_get_entries
This commit is contained in:
@@ -30,6 +30,8 @@ require_once("$CFG->libdir/externallib.php");
|
||||
require_once($CFG->dirroot . "/mod/data/locallib.php");
|
||||
|
||||
use mod_data\external\database_summary_exporter;
|
||||
use mod_data\external\record_exporter;
|
||||
use mod_data\external\content_exporter;
|
||||
|
||||
/**
|
||||
* Database module external functions
|
||||
@@ -322,4 +324,160 @@ class mod_data_external extends external_api {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
public static function get_entries_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'databaseid' => new external_value(PARAM_INT, 'data instance id'),
|
||||
'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group',
|
||||
VALUE_DEFAULT, 0),
|
||||
'returncontents' => new external_value(PARAM_BOOL, 'Whether to return contents or not. This will return each entry
|
||||
raw contents and the complete list view (using the template).',
|
||||
VALUE_DEFAULT, false),
|
||||
'sort' => new external_value(PARAM_INT, 'Sort the records by this field id, reserved ids are:
|
||||
0: timeadded
|
||||
-1: firstname
|
||||
-2: lastname
|
||||
-3: approved
|
||||
-4: timemodified.
|
||||
Empty for using the default database setting.', VALUE_DEFAULT, null),
|
||||
'order' => new external_value(PARAM_ALPHA, 'The direction of the sorting: \'ASC\' or \'DESC\'.
|
||||
Empty for using the default database setting.', VALUE_DEFAULT, null),
|
||||
'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0),
|
||||
'perpage' => new external_value(PARAM_INT, 'The number of records to return per page', VALUE_DEFAULT, 0),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return access information for a given feedback
|
||||
*
|
||||
* @param int $databaseid the data instance id
|
||||
* @param int $groupid (optional) group id, 0 means that the function will determine the user group
|
||||
* @param bool $returncontents Whether to return the entries contents or not
|
||||
* @param str $sort sort by this field
|
||||
* @param int $order the direction of the sorting
|
||||
* @param int $page page of records to return
|
||||
* @param int $perpage number of records to return per page
|
||||
* @return array of warnings and the entries
|
||||
* @since Moodle 3.3
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function get_entries($databaseid, $groupid = 0, $returncontents = false, $sort = null, $order = null,
|
||||
$page = 0, $perpage = 0) {
|
||||
global $PAGE, $DB;
|
||||
|
||||
$params = array('databaseid' => $databaseid, 'groupid' => $groupid, 'returncontents' => $returncontents ,
|
||||
'sort' => $sort, 'order' => $order, 'page' => $page, 'perpage' => $perpage);
|
||||
$params = self::validate_parameters(self::get_entries_parameters(), $params);
|
||||
$warnings = array();
|
||||
|
||||
if (!empty($params['order'])) {
|
||||
$params['order'] = strtoupper($params['order']);
|
||||
if ($params['order'] != 'ASC' && $params['order'] != 'DESC') {
|
||||
throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $params['order'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
list($database, $course, $cm, $context) = self::validate_database($params['databaseid']);
|
||||
// Check database is open in time.
|
||||
data_require_time_available($database, null, $context);
|
||||
|
||||
if (!empty($params['groupid'])) {
|
||||
$groupid = $params['groupid'];
|
||||
// Determine is the group is visible to user.
|
||||
if (!groups_group_visible($groupid, $course, $cm)) {
|
||||
throw new moodle_exception('notingroup');
|
||||
}
|
||||
} else {
|
||||
// Check to see if groups are being used here.
|
||||
if ($groupmode = groups_get_activity_groupmode($cm)) {
|
||||
$groupid = groups_get_activity_group($cm);
|
||||
// Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
|
||||
if (!groups_group_visible($groupid, $course, $cm)) {
|
||||
throw new moodle_exception('notingroup');
|
||||
}
|
||||
} else {
|
||||
$groupid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
list($records, $maxcount, $totalcount, $page, $nowperpage, $sort, $mode) =
|
||||
data_search_entries($database, $cm, $context, 'list', $groupid, '', $params['sort'], $params['order'],
|
||||
$params['page'], $params['perpage']);
|
||||
|
||||
$entries = [];
|
||||
$contentsids = []; // Store here the content ids of the records returned.
|
||||
foreach ($records as $record) {
|
||||
$user = user_picture::unalias($record, null, 'userid');
|
||||
$related = array('context' => $context, 'database' => $database, 'user' => $user);
|
||||
|
||||
$contents = $DB->get_records('data_content', array('recordid' => $record->id));
|
||||
$contentsids = array_merge($contentsids, array_keys($contents));
|
||||
if ($params['returncontents']) {
|
||||
$related['contents'] = $contents;
|
||||
} else {
|
||||
$related['contents'] = null;
|
||||
}
|
||||
|
||||
$exporter = new record_exporter($record, $related);
|
||||
$entries[] = $exporter->export($PAGE->get_renderer('core'));
|
||||
}
|
||||
|
||||
// Retrieve total files size for the records retrieved.
|
||||
$totalfilesize = 0;
|
||||
$fs = get_file_storage();
|
||||
$files = $fs->get_area_files($context->id, 'mod_data', 'content');
|
||||
foreach ($files as $file) {
|
||||
if ($file->is_directory() || !in_array($file->get_itemid(), $contentsids)) {
|
||||
continue;
|
||||
}
|
||||
$totalfilesize += $file->get_filesize();
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'entries' => $entries,
|
||||
'totalcount' => $totalcount,
|
||||
'totalfilesize' => $totalfilesize,
|
||||
'warnings' => $warnings
|
||||
);
|
||||
|
||||
// Check if we should return the list rendered.
|
||||
if ($params['returncontents']) {
|
||||
ob_start();
|
||||
// The return parameter stops the execution after the first record.
|
||||
data_print_template('listtemplate', $records, $database, '', $page, false);
|
||||
$result['listviewcontents'] = ob_get_contents();
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
public static function get_entries_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'entries' => new external_multiple_structure(
|
||||
record_exporter::get_read_structure()
|
||||
),
|
||||
'totalcount' => new external_value(PARAM_INT, 'Total count of records.'),
|
||||
'totalfilesize' => new external_value(PARAM_INT, 'Total size (bytes) of the files included in the records.'),
|
||||
'listviewcontents' => new external_value(PARAM_RAW, 'The list view contents as is rendered in the site.',
|
||||
VALUE_OPTIONAL),
|
||||
'warnings' => new external_warnings()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,12 @@ $functions = array(
|
||||
'capabilities' => 'mod/data:viewentry',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
'mod_data_get_entries' => array(
|
||||
'classname' => 'mod_data_external',
|
||||
'methodname' => 'get_entries',
|
||||
'description' => 'Return the complete list of entries of the given database.',
|
||||
'type' => 'read',
|
||||
'capabilities' => 'mod/data:viewentry',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
);
|
||||
|
||||
@@ -50,7 +50,10 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
|
||||
$this->setAdminUser();
|
||||
|
||||
// Setup test data.
|
||||
$this->course = $this->getDataGenerator()->create_course();
|
||||
$course = new stdClass();
|
||||
$course->groupmode = SEPARATEGROUPS;
|
||||
$course->groupmodeforce = true;
|
||||
$this->course = $this->getDataGenerator()->create_course($course);
|
||||
$this->data = $this->getDataGenerator()->create_module('data', array('course' => $this->course->id));
|
||||
$this->context = context_module::instance($this->data->cmid);
|
||||
$this->cm = get_coursemodule_from_instance('data', $this->data->id);
|
||||
@@ -58,6 +61,7 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
|
||||
// Create users.
|
||||
$this->student1 = self::getDataGenerator()->create_user();
|
||||
$this->student2 = self::getDataGenerator()->create_user();
|
||||
$this->student3 = self::getDataGenerator()->create_user();
|
||||
$this->teacher = self::getDataGenerator()->create_user();
|
||||
|
||||
// Users enrolments.
|
||||
@@ -65,7 +69,14 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
|
||||
$this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
|
||||
$this->getDataGenerator()->enrol_user($this->student1->id, $this->course->id, $this->studentrole->id, 'manual');
|
||||
$this->getDataGenerator()->enrol_user($this->student2->id, $this->course->id, $this->studentrole->id, 'manual');
|
||||
$this->getDataGenerator()->enrol_user($this->student3->id, $this->course->id, $this->studentrole->id, 'manual');
|
||||
$this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
|
||||
|
||||
$this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
|
||||
$this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
|
||||
groups_add_member($this->group1, $this->student1);
|
||||
groups_add_member($this->group1, $this->student2);
|
||||
groups_add_member($this->group2, $this->student3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,7 +286,7 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
|
||||
$result = mod_data_external::get_data_access_information($this->data->id);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_data_access_information_returns(), $result);
|
||||
|
||||
$this->assertEquals(0, $result['groupid']);
|
||||
$this->assertEquals($this->group1->id, $result['groupid']);
|
||||
|
||||
$this->assertFalse($result['canmanageentries']);
|
||||
$this->assertFalse($result['canapprove']);
|
||||
@@ -315,4 +326,165 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
|
||||
$this->assertEquals(0, $result['entrieslefttoadd']);
|
||||
$this->assertEquals(0, $result['entrieslefttoview']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to populate the database with some entries.
|
||||
*
|
||||
* @return array the entry ids created
|
||||
*/
|
||||
public function populate_database_with_entries() {
|
||||
global $DB;
|
||||
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$fieldtypes = array('checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url');
|
||||
|
||||
$count = 1;
|
||||
// Creating test Fields with default parameter values.
|
||||
foreach ($fieldtypes as $fieldtype) {
|
||||
$fieldname = 'field-' . $count;
|
||||
$record = new StdClass();
|
||||
$record->name = $fieldname;
|
||||
$record->type = $fieldtype;
|
||||
$record->required = 1;
|
||||
|
||||
$generator->create_field($record, $this->data);
|
||||
$count++;
|
||||
}
|
||||
// Get all the fields created.
|
||||
$fields = $DB->get_records('data_fields', array('dataid' => $this->data->id), 'id');
|
||||
|
||||
// Populate with contents, creating a new entry.
|
||||
$contents = array();
|
||||
$contents[] = array('opt1', 'opt2', 'opt3', 'opt4');
|
||||
$contents[] = '01-01-2037'; // It should be lower than 2038, to avoid failing on 32-bit windows.
|
||||
$contents[] = 'menu1';
|
||||
$contents[] = array('multimenu1', 'multimenu2', 'multimenu3', 'multimenu4');
|
||||
$contents[] = '12345';
|
||||
$contents[] = 'radioopt1';
|
||||
$contents[] = 'text for testing';
|
||||
$contents[] = '<p>text area testing<br /></p>';
|
||||
$contents[] = array('example.url', 'sampleurl');
|
||||
$count = 0;
|
||||
$fieldcontents = array();
|
||||
foreach ($fields as $fieldrecord) {
|
||||
$fieldcontents[$fieldrecord->id] = $contents[$count++];
|
||||
}
|
||||
|
||||
$this->setUser($this->student1);
|
||||
$entry11 = $generator->create_entry($this->data, $fieldcontents, $this->group1->id);
|
||||
$this->setUser($this->student2);
|
||||
$entry12 = $generator->create_entry($this->data, $fieldcontents, $this->group1->id);
|
||||
|
||||
$this->setUser($this->student3);
|
||||
$entry21 = $generator->create_entry($this->data, $fieldcontents, $this->group2->id);
|
||||
return [$entry11, $entry12, $entry21];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_entries
|
||||
*/
|
||||
public function test_get_entries() {
|
||||
global $DB;
|
||||
list($entry11, $entry12, $entry21) = self::populate_database_with_entries();
|
||||
|
||||
// First of all, expect to see only my group entries (not other users in other groups ones).
|
||||
$this->setUser($this->student1);
|
||||
$result = mod_data_external::get_entries($this->data->id);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(2, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
$this->assertEquals($entry11, $result['entries'][0]['id']);
|
||||
$this->assertEquals($this->student1->id, $result['entries'][0]['userid']);
|
||||
$this->assertEquals($this->group1->id, $result['entries'][0]['groupid']);
|
||||
$this->assertEquals($this->data->id, $result['entries'][0]['dataid']);
|
||||
$this->assertEquals($entry12, $result['entries'][1]['id']);
|
||||
$this->assertEquals($this->student2->id, $result['entries'][1]['userid']);
|
||||
$this->assertEquals($this->group1->id, $result['entries'][1]['groupid']);
|
||||
$this->assertEquals($this->data->id, $result['entries'][1]['dataid']);
|
||||
// Other user in same group.
|
||||
$this->setUser($this->student2);
|
||||
$result = mod_data_external::get_entries($this->data->id);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(2, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
|
||||
// Now try with the user in the second group that must see only one entry.
|
||||
$this->setUser($this->student3);
|
||||
$result = mod_data_external::get_entries($this->data->id);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(1, $result['entries']);
|
||||
$this->assertEquals(1, $result['totalcount']);
|
||||
$this->assertEquals($entry21, $result['entries'][0]['id']);
|
||||
$this->assertEquals($this->student3->id, $result['entries'][0]['userid']);
|
||||
$this->assertEquals($this->group2->id, $result['entries'][0]['groupid']);
|
||||
$this->assertEquals($this->data->id, $result['entries'][0]['dataid']);
|
||||
|
||||
// Now, as teacher we should see all (we have permissions to view all groups).
|
||||
$this->setUser($this->teacher);
|
||||
$result = mod_data_external::get_entries($this->data->id);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(3, $result['entries']);
|
||||
$this->assertEquals(3, $result['totalcount']);
|
||||
|
||||
$entries = $DB->get_records('data_records', array('dataid' => $this->data->id), 'id');
|
||||
$this->assertCount(3, $entries);
|
||||
$count = 0;
|
||||
foreach ($entries as $entry) {
|
||||
$this->assertEquals($entry->id, $result['entries'][$count]['id']);
|
||||
$count++;
|
||||
}
|
||||
|
||||
// Basic test passing the parameter (instead having to calculate it).
|
||||
$this->setUser($this->student1);
|
||||
$result = mod_data_external::get_entries($this->data->id, $this->group1->id);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(2, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
|
||||
// Test ordering (reverse).
|
||||
$this->setUser($this->student1);
|
||||
$result = mod_data_external::get_entries($this->data->id, $this->group1->id, false, null, 'DESC');
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(2, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
$this->assertEquals($entry12, $result['entries'][0]['id']);
|
||||
|
||||
// Test pagination.
|
||||
$this->setUser($this->student1);
|
||||
$result = mod_data_external::get_entries($this->data->id, $this->group1->id, false, null, null, 0, 1);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(1, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
$this->assertEquals($entry11, $result['entries'][0]['id']);
|
||||
|
||||
$result = mod_data_external::get_entries($this->data->id, $this->group1->id, false, null, null, 1, 1);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(1, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
$this->assertEquals($entry12, $result['entries'][0]['id']);
|
||||
|
||||
// Now test the return contents.
|
||||
data_generate_default_template($this->data, 'listtemplate', 0, false, true); // Generate a default list template.
|
||||
$result = mod_data_external::get_entries($this->data->id, $this->group1->id, true, null, null, 0, 2);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entries_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertCount(2, $result['entries']);
|
||||
$this->assertEquals(2, $result['totalcount']);
|
||||
$this->assertCount(9, $result['entries'][0]['contents']);
|
||||
$this->assertCount(9, $result['entries'][1]['contents']);
|
||||
// Search for some content.
|
||||
$this->assertTrue(strpos($result['listviewcontents'], 'opt1') !== false);
|
||||
$this->assertTrue(strpos($result['listviewcontents'], 'January') !== false);
|
||||
$this->assertTrue(strpos($result['listviewcontents'], 'menu1') !== false);
|
||||
$this->assertTrue(strpos($result['listviewcontents'], 'text for testing') !== false);
|
||||
$this->assertTrue(strpos($result['listviewcontents'], 'sampleurl') !== false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user