mirror of
https://github.com/moodle/moodle.git
synced 2025-03-14 04:30:15 +01:00
MDL-57923 mod_data: New WS mod_data_add_entry
This commit is contained in:
parent
b376f55e59
commit
61c640c13a
@ -933,4 +933,140 @@ class mod_data_external extends external_api {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
public static function add_entry_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),
|
||||
'data' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'fieldid' => new external_value(PARAM_INT, 'The field id.'),
|
||||
'subfield' => new external_value(PARAM_NOTAGS, 'The subfield name (if required).', VALUE_DEFAULT, ''),
|
||||
'value' => new external_value(PARAM_RAW, 'The contents for the field always JSON encoded.'),
|
||||
)
|
||||
), 'The fields data to be created'
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new entry to a database
|
||||
*
|
||||
* @param int $databaseid the data instance id
|
||||
* @param int $groupid (optional) group id, 0 means that the function will determine the user group
|
||||
* @param array $data the fields data to be created
|
||||
* @return array of warnings and status result
|
||||
* @since Moodle 3.3
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function add_entry($databaseid, $groupid, $data) {
|
||||
global $DB;
|
||||
|
||||
$params = array('databaseid' => $databaseid, 'groupid' => $groupid, 'data' => $data);
|
||||
$params = self::validate_parameters(self::add_entry_parameters(), $params);
|
||||
$warnings = array();
|
||||
$fieldnotifications = array();
|
||||
|
||||
list($database, $course, $cm, $context) = self::validate_database($params['databaseid']);
|
||||
// Check database is open in time.
|
||||
data_require_time_available($database, null, $context);
|
||||
|
||||
$groupmode = groups_get_activity_groupmode($cm);
|
||||
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) {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data_user_can_add_entry($database, $groupid, $groupmode, $context)) {
|
||||
throw new moodle_exception('noaccess', 'data');
|
||||
}
|
||||
|
||||
// Prepare the data as is expected by the API.
|
||||
$datarecord = new stdClass;
|
||||
foreach ($params['data'] as $data) {
|
||||
$subfield = ($data['subfield'] !== '') ? '_' . $data['subfield'] : '';
|
||||
// We ask for JSON encoded values because of multiple choice forms or checkboxes that use array parameters.
|
||||
$datarecord->{'field_' . $data['fieldid'] . $subfield} = json_decode($data['value']);
|
||||
}
|
||||
// Validate to ensure that enough data was submitted.
|
||||
$fields = $DB->get_records('data_fields', array('dataid' => $database->id));
|
||||
$processeddata = data_process_submission($database, $fields, $datarecord);
|
||||
|
||||
// Format notifications.
|
||||
if (!empty($processeddata->fieldnotifications)) {
|
||||
foreach ($processeddata->fieldnotifications as $field => $notififications) {
|
||||
foreach ($notififications as $notif) {
|
||||
$fieldnotifications[] = [
|
||||
'fieldname' => $field,
|
||||
'notification' => $notif,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new (empty) record.
|
||||
$newentryid = 0;
|
||||
if ($processeddata->validated && $recordid = data_add_record($database, $groupid)) {
|
||||
$newentryid = $recordid;
|
||||
// Now populate the fields contents of the new record.
|
||||
data_add_fields_contents_to_new_record($database, $context, $recordid, $fields, $datarecord, $processeddata);
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'newentryid' => $newentryid,
|
||||
'generalnotifications' => $processeddata->generalnotifications,
|
||||
'fieldnotifications' => $fieldnotifications,
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
public static function add_entry_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'newentryid' => new external_value(PARAM_INT, 'True new created entry id. 0 if the entry was not created.'),
|
||||
'generalnotifications' => new external_multiple_structure(
|
||||
new external_value(PARAM_RAW, 'General notifications')
|
||||
),
|
||||
'fieldnotifications' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'fieldname' => new external_value(PARAM_TEXT, 'The field name.'),
|
||||
'notification' => new external_value(PARAM_RAW, 'The notification for the field.'),
|
||||
)
|
||||
)
|
||||
),
|
||||
'warnings' => new external_warnings()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -99,4 +99,12 @@ $functions = array(
|
||||
'capabilities' => 'mod/data:manageentries',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
'mod_data_add_entry' => array(
|
||||
'classname' => 'mod_data_external',
|
||||
'methodname' => 'add_entry',
|
||||
'description' => 'Adds a new entry.',
|
||||
'type' => 'write',
|
||||
'capabilities' => 'mod/data:writeentry',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
);
|
||||
|
@ -808,4 +808,189 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
|
||||
$this->expectException('moodle_exception');
|
||||
mod_data_external::delete_entry($entry21);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test add_entry.
|
||||
*/
|
||||
public function test_add_entry() {
|
||||
global $DB;
|
||||
// First create the record structure and add some entries.
|
||||
list($entry11, $entry12, $entry13, $entry21) = self::populate_database_with_entries();
|
||||
|
||||
$this->setUser($this->student1);
|
||||
$newentrydata = [];
|
||||
$fields = $DB->get_records('data_fields', array('dataid' => $this->data->id), 'id');
|
||||
// Prepare the new entry data.
|
||||
foreach ($fields as $field) {
|
||||
$subfield = $value = '';
|
||||
|
||||
switch ($field->type) {
|
||||
case 'checkbox':
|
||||
$value = ['opt1', 'opt2'];
|
||||
break;
|
||||
case 'date':
|
||||
// Add two extra.
|
||||
$newentrydata[] = [
|
||||
'fieldid' => $field->id,
|
||||
'subfield' => 'day',
|
||||
'value' => json_encode('5')
|
||||
];
|
||||
$newentrydata[] = [
|
||||
'fieldid' => $field->id,
|
||||
'subfield' => 'month',
|
||||
'value' => json_encode('1')
|
||||
];
|
||||
$subfield = 'year';
|
||||
$value = '1981';
|
||||
break;
|
||||
case 'menu':
|
||||
$value = 'menu1';
|
||||
break;
|
||||
case 'multimenu':
|
||||
$value = ['multimenu1', 'multimenu4'];
|
||||
break;
|
||||
case 'number':
|
||||
$value = 6;
|
||||
break;
|
||||
case 'radiobutton':
|
||||
$value = 'radioopt1';
|
||||
break;
|
||||
case 'text':
|
||||
$value = 'some text';
|
||||
break;
|
||||
case 'textarea':
|
||||
$newentrydata[] = [
|
||||
'fieldid' => $field->id,
|
||||
'subfield' => 'content1',
|
||||
'value' => json_encode(FORMAT_MOODLE)
|
||||
];
|
||||
$newentrydata[] = [
|
||||
'fieldid' => $field->id,
|
||||
'subfield' => 'itemid',
|
||||
'value' => json_encode(0)
|
||||
];
|
||||
$value = 'more text';
|
||||
break;
|
||||
case 'url':
|
||||
$value = 'https://moodle.org';
|
||||
$subfield = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
$newentrydata[] = [
|
||||
'fieldid' => $field->id,
|
||||
'subfield' => $subfield,
|
||||
'value' => json_encode($value)
|
||||
];
|
||||
}
|
||||
$result = mod_data_external::add_entry($this->data->id, 0, $newentrydata);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::add_entry_returns(), $result);
|
||||
|
||||
$newentryid = $result['newentryid'];
|
||||
$result = mod_data_external::get_entry($newentryid, 0, true);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::get_entry_returns(), $result);
|
||||
$this->assertEquals($this->student1->id, $result['entry']['userid']);
|
||||
$this->assertCount(9, $result['entry']['contents']);
|
||||
foreach ($result['entry']['contents'] as $content) {
|
||||
$field = $fields[$content['fieldid']];
|
||||
// Stored content same that the one retrieved by WS.
|
||||
$dbcontent = $DB->get_record('data_content', array('fieldid' => $field->id, 'recordid' => $newentryid));
|
||||
$this->assertEquals($dbcontent->content, $content['content']);
|
||||
|
||||
// Now double check everything stored is correct.
|
||||
if ($field->type == 'checkbox') {
|
||||
$this->assertEquals('opt1##opt2', $content['content']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'date') {
|
||||
$this->assertEquals(347500800, $content['content']); // Date in gregorian format.
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'menu') {
|
||||
$this->assertEquals('menu1', $content['content']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'multimenu') {
|
||||
$this->assertEquals('multimenu1##multimenu4', $content['content']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'number') {
|
||||
$this->assertEquals(6, $content['content']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'radiobutton') {
|
||||
$this->assertEquals('radioopt1', $content['content']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'text') {
|
||||
$this->assertEquals('some text', $content['content']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'textarea') {
|
||||
$this->assertEquals('more text', $content['content']);
|
||||
$this->assertEquals(FORMAT_MOODLE, $content['content1']);
|
||||
continue;
|
||||
}
|
||||
if ($field->type == 'url') {
|
||||
$this->assertEquals('https://moodle.org', $content['content']);
|
||||
continue;
|
||||
}
|
||||
$this->assertEquals('multimenu1##multimenu4', $content['content']);
|
||||
}
|
||||
|
||||
// Now, try to add another entry but removing some required data.
|
||||
unset($newentrydata[0]);
|
||||
$result = mod_data_external::add_entry($this->data->id, 0, $newentrydata);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::add_entry_returns(), $result);
|
||||
$this->assertEquals(0, $result['newentryid']);
|
||||
$this->assertCount(0, $result['generalnotifications']);
|
||||
$this->assertCount(1, $result['fieldnotifications']);
|
||||
$this->assertEquals('field-1', $result['fieldnotifications'][0]['fieldname']);
|
||||
$this->assertEquals(get_string('errormustsupplyvalue', 'data'), $result['fieldnotifications'][0]['notification']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test add_entry empty_form.
|
||||
*/
|
||||
public function test_add_entry_empty_form() {
|
||||
$result = mod_data_external::add_entry($this->data->id, 0, []);
|
||||
$result = external_api::clean_returnvalue(mod_data_external::add_entry_returns(), $result);
|
||||
$this->assertEquals(0, $result['newentryid']);
|
||||
$this->assertCount(1, $result['generalnotifications']);
|
||||
$this->assertCount(0, $result['fieldnotifications']);
|
||||
$this->assertEquals(get_string('emptyaddform', 'data'), $result['generalnotifications'][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test add_entry read_only_period.
|
||||
*/
|
||||
public function test_add_entry_read_only_period() {
|
||||
global $DB;
|
||||
list($entry11, $entry12, $entry13, $entry21) = self::populate_database_with_entries();
|
||||
// Set a time period.
|
||||
$this->data->timeviewfrom = time() - HOURSECS;
|
||||
$this->data->timeviewto = time() + HOURSECS;
|
||||
$DB->update_record('data', $this->data);
|
||||
|
||||
$this->setUser($this->student1);
|
||||
$this->expectExceptionMessage(get_string('noaccess', 'data'));
|
||||
$this->expectException('moodle_exception');
|
||||
mod_data_external::add_entry($this->data->id, 0, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test add_entry max_num_entries.
|
||||
*/
|
||||
public function test_add_entry_max_num_entries() {
|
||||
global $DB;
|
||||
list($entry11, $entry12, $entry13, $entry21) = self::populate_database_with_entries();
|
||||
// Set a time period.
|
||||
$this->data->maxentries = 1;
|
||||
$DB->update_record('data', $this->data);
|
||||
|
||||
$this->setUser($this->student1);
|
||||
$this->expectExceptionMessage(get_string('noaccess', 'data'));
|
||||
$this->expectException('moodle_exception');
|
||||
mod_data_external::add_entry($this->data->id, 0, []);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016120508; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2016120509; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016112900; // Requires this Moodle version
|
||||
$plugin->component = 'mod_data'; // Full name of the plugin (used for diagnostics)
|
||||
$plugin->cron = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user