mirror of
https://github.com/moodle/moodle.git
synced 2025-04-17 22:45:54 +02:00
MDL-75492 mod_data: Refactor code to get available importing information
This commit is contained in:
parent
5a880405bf
commit
b755cfa544
@ -36,6 +36,18 @@ abstract class preset_importer {
|
||||
/** @var string directory where to find the preset. */
|
||||
protected $directory;
|
||||
|
||||
/** @var array fields to remove. */
|
||||
public $fieldstoremove;
|
||||
|
||||
/** @var array fields to update. */
|
||||
public $fieldstoupdate;
|
||||
|
||||
/** @var array fields to create. */
|
||||
public $fieldstocreate;
|
||||
|
||||
/** @var array settings to be imported. */
|
||||
public $settings;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -45,6 +57,9 @@ abstract class preset_importer {
|
||||
public function __construct(manager $manager, string $directory) {
|
||||
$this->manager = $manager;
|
||||
$this->directory = $directory;
|
||||
|
||||
// Read the preset and saved result.
|
||||
$this->settings = $this->get_preset_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,22 +191,33 @@ abstract class preset_importer {
|
||||
}
|
||||
|
||||
// Now work out fields to user friendly array.
|
||||
$fieldsarray = $parsedxml['preset']['#']['field'];
|
||||
foreach ($fieldsarray as $field) {
|
||||
if (!is_array($field)) {
|
||||
continue;
|
||||
}
|
||||
$fieldstoimport = new StdClass();
|
||||
foreach ($field['#'] as $param => $value) {
|
||||
if (!is_array($value)) {
|
||||
if (
|
||||
array_key_exists('preset', $parsedxml) &&
|
||||
array_key_exists('#', $parsedxml['preset']) &&
|
||||
array_key_exists('field', $parsedxml['preset']['#'])) {
|
||||
$fieldsarray = $parsedxml['preset']['#']['field'];
|
||||
foreach ($fieldsarray as $field) {
|
||||
if (!is_array($field)) {
|
||||
continue;
|
||||
}
|
||||
$fieldstoimport->$param = $value[0]['#'];
|
||||
$fieldstoimport = new StdClass();
|
||||
foreach ($field['#'] as $param => $value) {
|
||||
if (!is_array($value)) {
|
||||
continue;
|
||||
}
|
||||
$fieldstoimport->$param = $value[0]['#'];
|
||||
}
|
||||
$fieldstoimport->dataid = $module->id;
|
||||
$fieldstoimport->type = clean_param($fieldstoimport->type, PARAM_ALPHA);
|
||||
$result->importfields[] = $fieldstoimport;
|
||||
}
|
||||
$fieldstoimport->dataid = $module->id;
|
||||
$fieldstoimport->type = clean_param($fieldstoimport->type, PARAM_ALPHA);
|
||||
$result->importfields[] = $fieldstoimport;
|
||||
}
|
||||
|
||||
// Calculate default mapping.
|
||||
if (is_null($this->fieldstoremove) && is_null($this->fieldstocreate) && is_null($this->fieldstoupdate)) {
|
||||
$this->set_affected_fields($result->importfields, $result->currentfields);
|
||||
}
|
||||
|
||||
// Now add the HTML templates to the settings array so we can update d.
|
||||
foreach (manager::TEMPLATES_LIST as $templatename => $templatefile) {
|
||||
$result->settings->$templatename = $this->get_file_contents(
|
||||
@ -215,63 +241,44 @@ abstract class preset_importer {
|
||||
public function import(bool $overwritesettings): bool {
|
||||
global $DB, $OUTPUT;
|
||||
|
||||
$params = $this->get_preset_settings();
|
||||
$settings = $params->settings;
|
||||
$newfields = $params->importfields;
|
||||
$currentfields = $params->currentfields;
|
||||
$preservedfields = [];
|
||||
$settings = $this->settings->settings;
|
||||
$currentfields = $this->settings->currentfields;
|
||||
$missingfieldtypes = [];
|
||||
$module = $this->manager->get_instance();
|
||||
|
||||
// Maps fields and makes new ones.
|
||||
if (!empty($newfields)) {
|
||||
// We require an injective mapping, and need to know what to protect.
|
||||
foreach ($newfields as $newid => $newfield) {
|
||||
$cid = optional_param("field_$newid", -1, PARAM_INT);
|
||||
if ($cid == -1) {
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($cid, $preservedfields)) {
|
||||
throw new \moodle_exception('notinjectivemap', 'data');
|
||||
} else {
|
||||
$preservedfields[$cid] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($newfields as $newid => $newfield) {
|
||||
$cid = optional_param("field_$newid", -1, PARAM_INT);
|
||||
|
||||
/* A mapping. Just need to change field params. Data kept. */
|
||||
if ($cid != -1 && isset($currentfields[$cid])) {
|
||||
$fieldobject = data_get_field_from_id($currentfields[$cid]->id, $module);
|
||||
foreach ($newfield as $param => $value) {
|
||||
if ($param != "id") {
|
||||
$fieldobject->field->$param = $value;
|
||||
}
|
||||
foreach ($this->fieldstoupdate as $currentid => $updatable) {
|
||||
if ($currentid != -1 && isset($currentfields[$currentid])) {
|
||||
$fieldobject = data_get_field_from_id($currentfields[$currentid]->id, $module);
|
||||
foreach ($updatable as $param => $value) {
|
||||
if ($param != "id") {
|
||||
$fieldobject->field->$param = $value;
|
||||
}
|
||||
unset($fieldobject->field->similarfield);
|
||||
$fieldobject->update_field();
|
||||
unset($fieldobject);
|
||||
} else {
|
||||
/* Make a new field */
|
||||
$filepath = "field/$newfield->type/field.class.php";
|
||||
if (!file_exists($filepath)) {
|
||||
$missingfieldtypes[] = $newfield->name;
|
||||
continue;
|
||||
}
|
||||
include_once($filepath);
|
||||
|
||||
if (!isset($newfield->description)) {
|
||||
$newfield->description = '';
|
||||
}
|
||||
$classname = 'data_field_'.$newfield->type;
|
||||
$fieldclass = new $classname($newfield, $module);
|
||||
$fieldclass->insert_field();
|
||||
unset($fieldclass);
|
||||
}
|
||||
unset($fieldobject->field->similarfield);
|
||||
$fieldobject->update_field();
|
||||
unset($fieldobject);
|
||||
}
|
||||
if (!empty($missingfieldtypes)) {
|
||||
echo $OUTPUT->notification(get_string('missingfieldtypeimport', 'data') . html_writer::alist($missingfieldtypes));
|
||||
}
|
||||
|
||||
foreach ($this->fieldstocreate as $newfield) {
|
||||
/* Make a new field */
|
||||
$filepath = "field/$newfield->type/field.class.php";
|
||||
if (!file_exists($filepath)) {
|
||||
$missingfieldtypes[] = $newfield->name;
|
||||
continue;
|
||||
}
|
||||
include_once($filepath);
|
||||
|
||||
if (!isset($newfield->description)) {
|
||||
$newfield->description = '';
|
||||
}
|
||||
$classname = 'data_field_' . $newfield->type;
|
||||
$fieldclass = new $classname($newfield, $module);
|
||||
$fieldclass->insert_field();
|
||||
unset($fieldclass);
|
||||
}
|
||||
if (!empty($missingfieldtypes)) {
|
||||
echo $OUTPUT->notification(get_string('missingfieldtypeimport', 'data') . html_writer::alist($missingfieldtypes));
|
||||
}
|
||||
|
||||
// Get rid of all old unused data.
|
||||
@ -328,6 +335,59 @@ abstract class preset_importer {
|
||||
return $this->cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the fields needs to be removed, updated or created.
|
||||
*
|
||||
* @param array $newfields Array of new fields to be applied.
|
||||
* @param array $currentfields Array of current fields on database activity.
|
||||
* @return void
|
||||
*/
|
||||
public function set_affected_fields(array $newfields = [], array $currentfields = []): void {
|
||||
$fieldstoremove = [];
|
||||
$fieldstocreate = [];
|
||||
$preservedfields = [];
|
||||
|
||||
// Maps fields and makes new ones.
|
||||
if (!empty($newfields)) {
|
||||
// We require an injective mapping, and need to know what to protect.
|
||||
foreach ($newfields as $newid => $newfield) {
|
||||
$preservedfieldid = optional_param("field_$newid", -1, PARAM_INT);
|
||||
|
||||
if (array_key_exists($preservedfieldid, $preservedfields)) {
|
||||
throw new \moodle_exception('notinjectivemap', 'data');
|
||||
}
|
||||
|
||||
if ($preservedfieldid == -1) {
|
||||
// Let's check if there is any field with same type and name that we could map to.
|
||||
foreach ($currentfields as $currentid => $currentfield) {
|
||||
if (($currentfield->type == $newfield->type) &&
|
||||
($currentfield->name == $newfield->name) && !array_key_exists($currentid, $preservedfields)) {
|
||||
// We found a possible default map.
|
||||
$preservedfieldid = $currentid;
|
||||
$preservedfields[$currentid] = $newfield;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($preservedfieldid == -1) {
|
||||
// We need to create a new field.
|
||||
$fieldstocreate[] = $newfield;
|
||||
} else {
|
||||
$preservedfields[$preservedfieldid] = $newfield;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($currentfields as $currentid => $currentfield) {
|
||||
if (!array_key_exists($currentid, $preservedfields)) {
|
||||
$fieldstoremove[] = $currentfield;
|
||||
}
|
||||
}
|
||||
|
||||
$this->fieldstocreate = $fieldstocreate;
|
||||
$this->fieldstoremove = $fieldstoremove;
|
||||
$this->fieldstoupdate = $preservedfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any clean up routines should go here
|
||||
*
|
||||
@ -343,7 +403,10 @@ abstract class preset_importer {
|
||||
* @return bool True if the current database needs to map the fields imported.
|
||||
*/
|
||||
public function needs_mapping(): bool {
|
||||
return $this->manager->has_fields();
|
||||
if (!$this->manager->has_fields()) {
|
||||
return false;
|
||||
}
|
||||
return (!empty($this->fieldstocreate) || !empty($this->fieldstoremove));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,7 +59,7 @@ class mod_data_renderer extends plugin_renderer_base {
|
||||
$strwarning = get_string('mappingwarning', 'data');
|
||||
$strfieldmappings = get_string('fieldmappings', 'data');
|
||||
|
||||
$params = $importer->get_preset_settings();
|
||||
$params = $importer->settings;
|
||||
$newfields = $params->importfields;
|
||||
$currentfields = $params->currentfields;
|
||||
|
||||
@ -94,10 +94,18 @@ class mod_data_renderer extends plugin_renderer_base {
|
||||
continue;
|
||||
}
|
||||
if ($currentfield->name == $newfield->name) {
|
||||
$row[1] .= html_writer::tag('option', get_string('mapexistingfield', 'data', $currentfield->name), array('value'=>$cid, 'selected'=>'selected'));
|
||||
$selected=true;
|
||||
$row[1] .= html_writer::tag(
|
||||
'option',
|
||||
get_string('mapexistingfield', 'data', $currentfield->name),
|
||||
['value' => $cid, 'selected' => 'selected']
|
||||
);
|
||||
$selected = true;
|
||||
} else {
|
||||
$row[1] .= html_writer::tag('option', get_string('mapexistingfield', 'data', $currentfield->name), array('value'=>$cid));
|
||||
$row[1] .= html_writer::tag(
|
||||
'option',
|
||||
get_string('mapexistingfield', 'data', $currentfield->name),
|
||||
['value' => $cid]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,16 +17,11 @@ Feature: Users can import presets
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| data | Mountain landscapes | n | C1 | data1 |
|
||||
And the following "mod_data > presets" exist:
|
||||
| database | name | description |
|
||||
| data1 | Saved preset 1 | The preset1 has description |
|
||||
| data1 | Saved preset 2 | |
|
||||
|
||||
Scenario: Teacher can import from preset page on an empty database
|
||||
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "Actions" "button"
|
||||
And I choose "Import preset" in the open action menu
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
Then I should not see "Field mappings"
|
||||
@ -38,8 +33,7 @@ Feature: Users can import presets
|
||||
| data1 | text | Test field name | Test field description |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "Actions" "button"
|
||||
And I choose "Import preset" in the open action menu
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
Then I should see "Field mappings"
|
||||
@ -62,8 +56,7 @@ Feature: Users can import presets
|
||||
| data1 | Student entry 1 |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "Actions" "button"
|
||||
And I choose "Import preset" in the open action menu
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
Then I should see "Field mappings"
|
||||
@ -86,13 +79,17 @@ Feature: Users can import presets
|
||||
| data1 | Student entry 1 |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "Actions" "button"
|
||||
And I choose "Import preset" in the open action menu
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
Then I should see "Field mappings"
|
||||
And I should see "image"
|
||||
And I should see "Create a new field" in the "image" "table_row"
|
||||
And I should see "title"
|
||||
And I should see "Create a new field" in the "title" "table_row"
|
||||
# We map existing field to keep the entry data
|
||||
And I set the field "id_title" to "Map to field1"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Database"
|
||||
And I should see "Student entry"
|
||||
|
||||
Scenario: Teacher can import from zero state page on an empty database
|
||||
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
@ -101,3 +98,72 @@ Feature: Users can import presets
|
||||
When I click on "Import preset and apply" "button"
|
||||
Then I should not see "Field mappings"
|
||||
And I should see "Image" in the "image" "table_row"
|
||||
|
||||
Scenario: Importing a preset could create new fields
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | title |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Fields"
|
||||
And I should see "title"
|
||||
And I should not see "Description"
|
||||
And I should not see "image"
|
||||
And I follow "Presets"
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
Then I should see "title"
|
||||
And I should see "description" in the "description" "table_row"
|
||||
And I should see "image" in the "image" "table_row"
|
||||
|
||||
Scenario: Importing a preset could create map fields
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | oldtitle |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Fields"
|
||||
And I should see "oldtitle"
|
||||
And I should not see "Description"
|
||||
And I should not see "image"
|
||||
And I follow "Presets"
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
# Let's map a field that is not mapped by default
|
||||
And I should see "Create a new field" in the "oldtitle" "table_row"
|
||||
And I set the field "id_title" to "Map to oldtitle"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
Then I should not see "oldtitle"
|
||||
And I should see "title"
|
||||
And I should see "description" in the "description" "table_row"
|
||||
And I should see "image" in the "image" "table_row"
|
||||
|
||||
Scenario: Importing same preset twice doesn't show mapping dialogue
|
||||
# Importing a preset on an empty database doesn't show the mapping dialogue, so we add a field for the database
|
||||
# not to be empty.
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | title |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
When I click on "Import preset and apply" "button"
|
||||
And I should see "Field mappings"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
And I follow "Presets"
|
||||
And I choose the "Import preset" item in the "Action" action menu
|
||||
And I upload "mod/data/tests/fixtures/image_gallery_preset.zip" file to "Preset file" filemanager
|
||||
And I click on "Import preset and apply" "button"
|
||||
Then I should not see "Field mappings"
|
||||
And I should see "The preset has been successfully applied"
|
||||
|
186
mod/data/tests/behat/use_presets.feature
Normal file
186
mod/data/tests/behat/use_presets.feature
Normal file
@ -0,0 +1,186 @@
|
||||
@mod @mod_data @javascript
|
||||
Feature: Users can use predefined presets
|
||||
In order to use presets
|
||||
As a user
|
||||
I need to select an existing preset
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| data | Mountain landscapes | introduction... | C1 | data1 |
|
||||
And the following "mod_data > fields" exist:
|
||||
| database | type | name | description |
|
||||
| data1 | text | Test field name | Test field description |
|
||||
Scenario: Using a preset on a non empty database could create new fields
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | title |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Fields"
|
||||
And I should see "title"
|
||||
And I should not see "Description"
|
||||
And I should not see "image"
|
||||
And I follow "Presets"
|
||||
And I click on "fullname" "radio" in the "Image gallery" "table_row"
|
||||
And I click on "Use this preset" "button"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
Then I should see "title"
|
||||
And I should see "description" in the "description" "table_row"
|
||||
And I should see "image" in the "image" "table_row"
|
||||
|
||||
Scenario: Using a preset on a non-empty database could show the option to map fields
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | oldtitle |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Fields"
|
||||
And I should see "oldtitle"
|
||||
And I should not see "Description"
|
||||
And I should not see "image"
|
||||
And I follow "Presets"
|
||||
And I click on "fullname" "radio" in the "Image gallery" "table_row"
|
||||
And I click on "Use this preset" "button"
|
||||
# Let's map a field that is not mapped by default
|
||||
And I should see "Create a new field" in the "oldtitle" "table_row"
|
||||
And I set the field "id_title" to "Map to oldtitle"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
Then I should not see "oldtitle"
|
||||
And I should see "title"
|
||||
And I should see "description" in the "description" "table_row"
|
||||
And I should see "image" in the "image" "table_row"
|
||||
|
||||
Scenario: Teacher can use a preset from presets page on a database with existing entries
|
||||
# Creating an entry to test use a preset feature with databases with entries.
|
||||
Given the following "mod_data > entries" exist:
|
||||
| database | Test field name |
|
||||
| data1 | Student entry 1 |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "fullname" "radio" in the "Image gallery" "table_row"
|
||||
And the "Use this preset" "button" should be enabled
|
||||
Then I click on "Use this preset" "button"
|
||||
Then I should see "Field mappings"
|
||||
And I should see "title"
|
||||
And I should see "Create a new field" in the "title" "table_row"
|
||||
# We map existing field to keep the entry data
|
||||
And I set the field "id_title" to "Map to Test field name"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I follow "Fields"
|
||||
And I should see "title"
|
||||
And I follow "Database"
|
||||
And I should see "Student entry 1"
|
||||
|
||||
Scenario: Using same preset twice doesn't show mapping dialogue and applies the preset directly
|
||||
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "fullname" "radio" in the "Image gallery" "table_row"
|
||||
When I click on "Use this preset" "button"
|
||||
And I should see "Field mappings"
|
||||
And I set the field "id_title" to "Map to Test field name"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Presets"
|
||||
And I click on "fullname" "radio" in the "Image gallery" "table_row"
|
||||
And I click on "Use this preset" "button"
|
||||
Then I should not see "Field mappings"
|
||||
And I should see "The preset has been successfully applied"
|
||||
|
||||
Scenario: Using a preset from preset preview page on a non empty database could create new fields
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | title |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Fields"
|
||||
And I should see "title"
|
||||
And I should not see "Description"
|
||||
And I should not see "image"
|
||||
And I follow "Presets"
|
||||
And I click on "Image gallery" "link"
|
||||
And I click on "Use this preset" "button"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
Then I should see "title"
|
||||
And I should see "description" in the "description" "table_row"
|
||||
And I should see "image" in the "image" "table_row"
|
||||
|
||||
Scenario: Using a preset from preset preview page on a non-empty database could show the option to map fields
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name |
|
||||
| data1 | text | oldtitle |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Fields"
|
||||
And I should see "oldtitle"
|
||||
And I should not see "Description"
|
||||
And I should not see "image"
|
||||
And I follow "Presets"
|
||||
And I click on "Image gallery" "link"
|
||||
And I click on "Use this preset" "button"
|
||||
# Let's map a field that is not mapped by default
|
||||
And I should see "Create a new field" in the "oldtitle" "table_row"
|
||||
And I set the field "id_title" to "Map to oldtitle"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Fields"
|
||||
Then I should not see "oldtitle"
|
||||
And I should see "title"
|
||||
And I should see "description" in the "description" "table_row"
|
||||
And I should see "image" in the "image" "table_row"
|
||||
|
||||
Scenario: Teacher can use a preset from preset preview page on a database with existing entries
|
||||
# Creating an entry to test use a preset feature with databases with entries.
|
||||
Given the following "mod_data > entries" exist:
|
||||
| database | Test field name |
|
||||
| data1 | Student entry 1 |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "Image gallery" "link"
|
||||
And the "Use this preset" "button" should be enabled
|
||||
Then I click on "Use this preset" "button"
|
||||
Then I should see "Field mappings"
|
||||
And I should see "title"
|
||||
And I should see "Create a new field" in the "title" "table_row"
|
||||
# We map existing field to keep the entry data
|
||||
And I set the field "id_title" to "Map to Test field name"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I follow "Fields"
|
||||
And I should see "title"
|
||||
And I follow "Database"
|
||||
And I should see "Student entry 1"
|
||||
|
||||
Scenario: Using same preset twice from preset preview page doesn't show mapping dialogue and applies the preset
|
||||
directly
|
||||
Given I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
And I click on "Image gallery" "link"
|
||||
When I click on "Use this preset" "button"
|
||||
And I should see "Field mappings"
|
||||
And I set the field "id_title" to "Map to Test field name"
|
||||
And I click on "Continue" "button"
|
||||
And I should see "The preset has been successfully applied"
|
||||
And I click on "Continue" "button"
|
||||
And I follow "Presets"
|
||||
And I click on "Image gallery" "link"
|
||||
And I click on "Use this preset" "button"
|
||||
Then I should not see "Field mappings"
|
||||
And I should see "The preset has been successfully applied"
|
@ -17,7 +17,6 @@
|
||||
namespace mod_data;
|
||||
|
||||
use mod_data\local\importer\preset_existing_importer;
|
||||
use mod_data\local\importer\preset_upload_importer;
|
||||
|
||||
/**
|
||||
* Preset importer tests class for mod_data.
|
||||
@ -30,65 +29,255 @@ use mod_data\local\importer\preset_upload_importer;
|
||||
*/
|
||||
class preset_importer_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Data provider for build providers for test_needs_mapping and test_set_affected_fields.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function preset_importer_provider(): array {
|
||||
// Image gallery preset is: ['title' => 'text', 'description' => 'textarea', 'image' => 'picture'];
|
||||
|
||||
$titlefield = new \stdClass();
|
||||
$titlefield->name = 'title';
|
||||
$titlefield->type = 'text';
|
||||
|
||||
$descfield = new \stdClass();
|
||||
$descfield->name = 'description';
|
||||
$descfield->type = 'textarea';
|
||||
|
||||
$imagefield = new \stdClass();
|
||||
$imagefield->name = 'image';
|
||||
$imagefield->type = 'picture';
|
||||
|
||||
$difffield = new \stdClass();
|
||||
$difffield->name = 'title';
|
||||
$difffield->type = 'textarea';
|
||||
|
||||
$newfield = new \stdClass();
|
||||
$newfield->name = 'number';
|
||||
$newfield->type = 'number';
|
||||
|
||||
return [
|
||||
'Empty database / Empty importer' => [
|
||||
'currentfields' => [],
|
||||
'newfields' => [],
|
||||
'pluginname' => '',
|
||||
],
|
||||
'Empty database / Importer with fields' => [
|
||||
'currentfields' => [],
|
||||
'newfields' => [$titlefield, $descfield, $imagefield],
|
||||
'pluginname' => 'imagegallery',
|
||||
],
|
||||
'Database with fields / Empty importer' => [
|
||||
'currentfields' => [$titlefield, $descfield, $imagefield],
|
||||
'newfields' => [],
|
||||
'pluginname' => '',
|
||||
],
|
||||
'Same fields' => [
|
||||
'currentfields' => [$titlefield, $descfield, $imagefield],
|
||||
'newfields' => [$titlefield, $descfield, $imagefield],
|
||||
'pluginname' => 'imagegallery',
|
||||
],
|
||||
'Fields to create' => [
|
||||
'currentfields' => [$titlefield, $descfield],
|
||||
'newfields' => [$titlefield, $descfield, $imagefield],
|
||||
'pluginname' => 'imagegallery',
|
||||
],
|
||||
'Fields to remove' => [
|
||||
'currentfields' => [$titlefield, $descfield, $imagefield, $difffield],
|
||||
'newfields' => [$titlefield, $descfield, $imagefield],
|
||||
'pluginname' => 'imagegallery',
|
||||
],
|
||||
'Fields to update' => [
|
||||
'currentfields' => [$difffield, $descfield, $imagefield],
|
||||
'newfields' => [$titlefield, $descfield, $imagefield],
|
||||
'pluginname' => 'imagegallery',
|
||||
],
|
||||
'Fields to create, remove and update' => [
|
||||
'currentfields' => [$titlefield, $descfield, $imagefield, $difffield],
|
||||
'newfields' => [$titlefield, $descfield, $newfield],
|
||||
'pluginname' => '',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for needs_mapping().
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function needs_mapping_provider(): array {
|
||||
$basedprovider = $this->preset_importer_provider();
|
||||
|
||||
$basedprovider['Empty database / Empty importer']['needsmapping'] = false;
|
||||
$basedprovider['Empty database / Importer with fields']['needsmapping'] = false;
|
||||
$basedprovider['Database with fields / Empty importer']['needsmapping'] = true;
|
||||
$basedprovider['Same fields']['needsmapping'] = false;
|
||||
$basedprovider['Fields to create']['needsmapping'] = true;
|
||||
$basedprovider['Fields to remove']['needsmapping'] = true;
|
||||
$basedprovider['Fields to update']['needsmapping'] = true;
|
||||
$basedprovider['Fields to create, remove and update']['needsmapping'] = true;
|
||||
|
||||
return $basedprovider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for needs_mapping method.
|
||||
*
|
||||
* @dataProvider needs_mapping_provider
|
||||
* @covers ::needs_mapping
|
||||
*
|
||||
* @param array $currentfields Fields of the current activity.
|
||||
* @param array $newfields Fields to be imported.
|
||||
* @param string $pluginname The plugin preset to be imported.
|
||||
* @param bool $expectedresult Expected exception.
|
||||
*/
|
||||
public function test_needs_mapping() {
|
||||
global $CFG, $USER;
|
||||
public function test_needs_mapping(
|
||||
array $currentfields,
|
||||
array $newfields,
|
||||
string $pluginname,
|
||||
bool $expectedresult
|
||||
) {
|
||||
|
||||
global $USER;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
|
||||
// Create a course and a database activity.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
// Add current fields to the activity.
|
||||
foreach ($currentfields as $field) {
|
||||
$plugingenerator->create_field($field, $activity);
|
||||
}
|
||||
$manager = manager::create_from_instance($activity);
|
||||
|
||||
// Create presets and importers.
|
||||
$pluginname = 'imagegallery';
|
||||
$plugin = preset::create_from_plugin(null, $pluginname);
|
||||
$pluginimporter = new preset_existing_importer($manager, '/' . $pluginname);
|
||||
$presetactivity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
// Add current fields to the activity.
|
||||
foreach ($newfields as $field) {
|
||||
$plugingenerator->create_field($field, $presetactivity);
|
||||
}
|
||||
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$record = (object) [
|
||||
'name' => 'Testing preset name',
|
||||
'description' => 'Testing preset description',
|
||||
];
|
||||
$saved = $plugingenerator->create_preset($activity, $record);
|
||||
$saved = $plugingenerator->create_preset($presetactivity, $record);
|
||||
$savedimporter = new preset_existing_importer($manager, $USER->id . '/Testing preset name');
|
||||
$this->assertEquals($savedimporter->needs_mapping(), $expectedresult);
|
||||
|
||||
$fixturepath = $CFG->dirroot . '/mod/data/tests/fixtures/image_gallery_preset.zip';
|
||||
// Create presets and importers.
|
||||
if ($pluginname) {
|
||||
$plugin = preset::create_from_plugin(null, $pluginname);
|
||||
$pluginimporter = new preset_existing_importer($manager, '/' . $pluginname);
|
||||
$this->assertEquals($pluginimporter->needs_mapping(), $expectedresult);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a storage file.
|
||||
$draftid = file_get_unused_draft_itemid();
|
||||
$filerecord = [
|
||||
'component' => 'user',
|
||||
'filearea' => 'draft',
|
||||
'contextid' => \context_user::instance($USER->id)->id,
|
||||
'itemid' => $draftid,
|
||||
'filename' => 'image_gallery_preset.zip',
|
||||
'filepath' => '/'
|
||||
/**
|
||||
* Data provider for test_set_affected_fields().
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function set_affected_provider(): array {
|
||||
$basedprovider = $this->preset_importer_provider();
|
||||
|
||||
$basedprovider['Empty database / Empty importer']['fieldstocreate'] = 0;
|
||||
$basedprovider['Empty database / Empty importer']['fieldstoremove'] = 0;
|
||||
$basedprovider['Empty database / Empty importer']['fieldstoupdate'] = 0;
|
||||
|
||||
$basedprovider['Empty database / Importer with fields']['fieldstocreate'] = 3;
|
||||
$basedprovider['Empty database / Importer with fields']['fieldstoremove'] = 0;
|
||||
$basedprovider['Empty database / Importer with fields']['fieldstoupdate'] = 0;
|
||||
|
||||
$basedprovider['Database with fields / Empty importer']['fieldstocreate'] = 0;
|
||||
$basedprovider['Database with fields / Empty importer']['fieldstoremove'] = 3;
|
||||
$basedprovider['Database with fields / Empty importer']['fieldstoupdate'] = 0;
|
||||
|
||||
$basedprovider['Same fields']['fieldstocreate'] = 0;
|
||||
$basedprovider['Same fields']['fieldstoremove'] = 0;
|
||||
$basedprovider['Same fields']['fieldstoupdate'] = 3;
|
||||
|
||||
$basedprovider['Fields to create']['fieldstocreate'] = 1;
|
||||
$basedprovider['Fields to create']['fieldstoremove'] = 0;
|
||||
$basedprovider['Fields to create']['fieldstoupdate'] = 2;
|
||||
|
||||
$basedprovider['Fields to remove']['fieldstocreate'] = 0;
|
||||
$basedprovider['Fields to remove']['fieldstoremove'] = 1;
|
||||
$basedprovider['Fields to remove']['fieldstoupdate'] = 3;
|
||||
|
||||
$basedprovider['Fields to update']['fieldstocreate'] = 1;
|
||||
$basedprovider['Fields to update']['fieldstoremove'] = 1;
|
||||
$basedprovider['Fields to update']['fieldstoupdate'] = 2;
|
||||
|
||||
$basedprovider['Fields to create, remove and update']['fieldstocreate'] = 1;
|
||||
$basedprovider['Fields to create, remove and update']['fieldstoremove'] = 2;
|
||||
$basedprovider['Fields to create, remove and update']['fieldstoupdate'] = 2;
|
||||
|
||||
return $basedprovider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for set_affected_fields method.
|
||||
*
|
||||
* @dataProvider set_affected_provider
|
||||
* @covers ::set_affected_fields
|
||||
*
|
||||
* @param array $currentfields Fields of the current activity.
|
||||
* @param array $newfields Fields to be imported.
|
||||
* @param string $pluginname The plugin preset to be imported.
|
||||
* @param int $fieldstocreate Expected number of fields on $fieldstocreate.
|
||||
* @param int $fieldstoremove Expected number of fields on $fieldstoremove.
|
||||
* @param int $fieldstoupdate Expected number of fields on $fieldstoupdate.
|
||||
*/
|
||||
public function test_set_affected_fields(
|
||||
array $currentfields,
|
||||
array $newfields,
|
||||
string $pluginname,
|
||||
int $fieldstocreate,
|
||||
int $fieldstoremove,
|
||||
int $fieldstoupdate
|
||||
) {
|
||||
global $USER;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
|
||||
// Create a course and a database activity.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
// Add current fields to the activity.
|
||||
foreach ($currentfields as $field) {
|
||||
$plugingenerator->create_field($field, $activity);
|
||||
}
|
||||
$manager = manager::create_from_instance($activity);
|
||||
|
||||
$presetactivity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
// Add current fields to the activity.
|
||||
foreach ($newfields as $field) {
|
||||
$plugingenerator->create_field($field, $presetactivity);
|
||||
}
|
||||
|
||||
$record = (object) [
|
||||
'name' => 'Testing preset name',
|
||||
'description' => 'Testing preset description',
|
||||
];
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->create_file_from_pathname($filerecord, $fixturepath);
|
||||
$uploadedimporter = new preset_upload_importer($manager, $file->get_filepath());
|
||||
$saved = $plugingenerator->create_preset($presetactivity, $record);
|
||||
$savedimporter = new preset_existing_importer($manager, $USER->id . '/Testing preset name');
|
||||
$this->assertEquals(count($savedimporter->fieldstoremove), $fieldstoremove);
|
||||
$this->assertEquals(count($savedimporter->fieldstocreate), $fieldstocreate);
|
||||
$this->assertEquals(count($savedimporter->fieldstoupdate), $fieldstoupdate);
|
||||
|
||||
// Needs mapping returns false for empty databases.
|
||||
$this->assertFalse($pluginimporter->needs_mapping());
|
||||
$this->assertFalse($savedimporter->needs_mapping());
|
||||
$this->assertFalse($uploadedimporter->needs_mapping());
|
||||
|
||||
// Add a field to the database.
|
||||
$fieldrecord = new \stdClass();
|
||||
$fieldrecord->name = 'field1';
|
||||
$fieldrecord->type = 'text';
|
||||
$plugingenerator->create_field($fieldrecord, $activity);
|
||||
|
||||
// Needs mapping returns true for non-empty databases.
|
||||
$this->assertTrue($pluginimporter->needs_mapping());
|
||||
$this->assertTrue($savedimporter->needs_mapping());
|
||||
$this->assertTrue($uploadedimporter->needs_mapping());
|
||||
// Create presets and importers.
|
||||
if ($pluginname) {
|
||||
$plugin = preset::create_from_plugin(null, $pluginname);
|
||||
$pluginimporter = new preset_existing_importer($manager, '/' . $pluginname);
|
||||
$this->assertEquals(count($pluginimporter->fieldstoremove), $fieldstoremove);
|
||||
$this->assertEquals(count($pluginimporter->fieldstocreate), $fieldstocreate);
|
||||
$this->assertEquals(count($pluginimporter->fieldstoupdate), $fieldstoupdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user