diff --git a/mod/data/classes/external.php b/mod/data/classes/external.php index 9e65b35192f..4568cb7c76d 100644 --- a/mod/data/classes/external.php +++ b/mod/data/classes/external.php @@ -982,6 +982,12 @@ class mod_data_external extends external_api { $fieldnotifications = array(); list($database, $course, $cm, $context) = self::validate_database($params['databaseid']); + + $fields = $DB->get_records('data_fields', ['dataid' => $database->id]); + if (empty($fields)) { + throw new moodle_exception('nofieldindatabase', 'data'); + } + // Check database is open in time. data_require_time_available($database, null, $context); @@ -1009,7 +1015,6 @@ class mod_data_external extends external_api { $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. diff --git a/mod/data/lib.php b/mod/data/lib.php index a1820a6bc14..631869b7ab9 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -2139,7 +2139,12 @@ function data_print_header($course, $cm, $data, $currenttab='', string $actionba * @return bool */ function data_user_can_add_entry($data, $currentgroup, $groupmode, $context = null) { - global $USER; + global $DB; + + // Don't let add entry to a database that has no fields. + if (!$DB->record_exists('data_fields', ['dataid' => $data->id])) { + return false; + } if (empty($context)) { $cm = get_coursemodule_from_instance('data', $data->id, 0, false, MUST_EXIST); diff --git a/mod/data/tests/externallib_test.php b/mod/data/tests/externallib_test.php index d13618af310..98b43bdad26 100644 --- a/mod/data/tests/externallib_test.php +++ b/mod/data/tests/externallib_test.php @@ -113,6 +113,21 @@ class externallib_test extends externallib_advanced_testcase { groups_add_member($this->group2, $this->student3); } + /** + * Add a test field to the database activity instance to be used in the unit tests. + * + * @return \data_field_base + */ + protected function add_test_field(): \data_field_base { + $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); + + // Add fields. + $fieldrecord = new \stdClass(); + $fieldrecord->name = 'Test field'; // Identifier of the records for testing. + $fieldrecord->type = 'text'; + return $generator->create_field($fieldrecord, $this->database); + } + /** * Test get databases by courses */ @@ -321,6 +336,10 @@ class externallib_test extends externallib_advanced_testcase { */ public function test_get_data_access_information_student() { global $DB; + + // Add a field to database to let users add new entries. + $this->add_test_field(); + // Modify the database to add access restrictions. $this->database->timeavailablefrom = time() + DAYSECS; $this->database->requiredentries = 2; @@ -350,6 +369,10 @@ class externallib_test extends externallib_advanced_testcase { */ public function test_get_data_access_information_teacher() { global $DB; + + // Add a field to database to let users add new entries. + $this->add_test_field(); + // Modify the database to add access restrictions. $this->database->timeavailablefrom = time() + DAYSECS; $this->database->requiredentries = 2; @@ -380,6 +403,9 @@ class externallib_test extends externallib_advanced_testcase { public function test_get_data_access_information_groups() { global $DB; + // Add a field to database to let users add new entries. + $this->add_test_field(); + $DB->set_field('course', 'groupmode', VISIBLEGROUPS, ['id' => $this->course->id]); // Check I can see my group. @@ -1088,6 +1114,10 @@ class externallib_test extends externallib_advanced_testcase { * Test add_entry empty_form. */ public function test_add_entry_empty_form() { + + // Add a field to database to let users add new entries. + $this->add_test_field(); + $result = mod_data_external::add_entry($this->database->id, 0, []); $result = \external_api::clean_returnvalue(mod_data_external::add_entry_returns(), $result); $this->assertEquals(0, $result['newentryid']); @@ -1133,12 +1163,26 @@ class externallib_test extends externallib_advanced_testcase { * Test add_entry invalid group. */ public function test_add_entry_invalid_group() { + + // Add a field to database to let users add new entries. + $this->add_test_field(); + $this->setUser($this->student1); $this->expectExceptionMessage(get_string('noaccess', 'data')); $this->expectException('moodle_exception'); mod_data_external::add_entry($this->database->id, $this->group2->id, []); } + /** + * Test add_entry for an empty database (no fields). + * + * @covers \mod_data\mod_data_external::add_entry + */ + public function test_add_entry_empty_database() { + $this->expectException('moodle_exception'); + mod_data_external::add_entry($this->database->id, 0, []); + } + /** * Test update_entry. */ diff --git a/mod/data/upgrade.txt b/mod/data/upgrade.txt index c7659d1baea..f3e4bcabc0f 100644 --- a/mod/data/upgrade.txt +++ b/mod/data/upgrade.txt @@ -13,6 +13,8 @@ information provided here is intended especially for developers. - data_presets_generate_xml - data_presets_save - is_directory_a_preset +* mod_data_external::add_entry() function throws an error when trying to add an entry to a database with no field created. +* data_user_can_add_entry() function returns false for any user if there is no field created on the database. === 3.7 === * External functions get_entries, get_entry and search_entries now return an additional field "tags" containing the entry tags.