Merge branch 'MDL-75497-master4' of https://github.com/raortegar/moodle

This commit is contained in:
Jun Pataleta 2022-10-20 17:29:11 +08:00
commit de11a92ed0
8 changed files with 157 additions and 37 deletions

View File

@ -19,6 +19,7 @@ namespace mod_data\local\importer;
use mod_data\manager; use mod_data\manager;
use mod_data\preset; use mod_data\preset;
use stdClass; use stdClass;
use html_writer;
/** /**
* Abstract class used for data preset importers * Abstract class used for data preset importers
@ -212,7 +213,7 @@ abstract class preset_importer {
* @return bool Wether the importing has been successful. * @return bool Wether the importing has been successful.
*/ */
public function import(bool $overwritesettings): bool { public function import(bool $overwritesettings): bool {
global $DB; global $DB, $OUTPUT;
$params = $this->get_preset_settings(); $params = $this->get_preset_settings();
$settings = $params->settings; $settings = $params->settings;
@ -252,7 +253,12 @@ abstract class preset_importer {
unset($fieldobject); unset($fieldobject);
} else { } else {
/* Make a new field */ /* Make a new field */
include_once("field/$newfield->type/field.class.php"); $filepath = "field/$newfield->type/field.class.php";
if (!file_exists($filepath)) {
$missingfieldtypes[] = $newfield->name;
continue;
}
include_once($filepath);
if (!isset($newfield->description)) { if (!isset($newfield->description)) {
$newfield->description = ''; $newfield->description = '';
@ -263,6 +269,9 @@ abstract class preset_importer {
unset($fieldclass); unset($fieldclass);
} }
} }
if (!empty($missingfieldtypes)) {
echo $OUTPUT->notification(get_string('missingfieldtypeimport', 'data') . html_writer::alist($missingfieldtypes));
}
} }
// Get rid of all old unused data. // Get rid of all old unused data.

View File

@ -84,6 +84,9 @@ class template_editor_tools implements templatable, renderable {
$taglist = []; $taglist = [];
$fields = $this->manager->get_fields(); $fields = $this->manager->get_fields();
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field->type === 'unknown') {
continue;
}
$fieldname = $field->get_name(); $fieldname = $field->get_name();
$taglist["[[$fieldname]]"] = $fieldname; $taglist["[[$fieldname]]"] = $fieldname;
} }
@ -105,6 +108,9 @@ class template_editor_tools implements templatable, renderable {
// Field IDs. // Field IDs.
$fields = $this->manager->get_fields(); $fields = $this->manager->get_fields();
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field->type === 'unknown') {
continue;
}
$fieldname = $field->get_name(); $fieldname = $field->get_name();
$taglist["[[$fieldname#id]]"] = "$fieldname id"; $taglist["[[$fieldname#id]]"] = "$fieldname id";
} }

View File

@ -299,6 +299,10 @@ class entry extends \core_search\base_mod {
foreach ($filteredcontents as $content) { foreach ($filteredcontents as $content) {
$classname = $this->get_field_class_name($content->fieldtype); $classname = $this->get_field_class_name($content->fieldtype);
if (!$classname) {
$content->addtemplateposition = -1;
continue;
}
$content->priority = $classname::get_priority(); $content->priority = $classname::get_priority();
$content->addtemplateposition = strpos($template, '[['.$content->fldname.']]'); $content->addtemplateposition = strpos($template, '[['.$content->fldname.']]');
} }
@ -346,16 +350,22 @@ class entry extends \core_search\base_mod {
} }
/** /**
* Returns the class name for that field type and includes it. * Returns the class name for the given field type and includes it.
* *
* @param string $fieldtype * @param string $fieldtype
* @return string * @return string|null It will return the class name or null if the field type is not available.
*/ */
protected function get_field_class_name($fieldtype) { protected function get_field_class_name($fieldtype) {
global $CFG; global $CFG;
$fieldtype = trim($fieldtype); $fieldtype = trim($fieldtype);
require_once($CFG->dirroot . '/mod/data/field/' . $fieldtype . '/field.class.php');
$fieldpath = $CFG->dirroot . '/mod/data/field/' . $fieldtype . '/field.class.php';
if (!file_exists($fieldpath)) {
return null;
}
require_once($fieldpath);
return 'data_field_' . $fieldtype; return 'data_field_' . $fieldtype;
} }

View File

@ -850,7 +850,17 @@ class template {
$errors .= $renderer->notification($notification); $errors .= $renderer->notification($notification);
} }
} }
$replacements[] = $errors . $field->display_add_field($entryid, $entrydata); $fielddisplay = '';
if ($field->type === 'unknown') {
if ($this->canmanageentries) { // Display notification for users that can manage entries.
$errors .= $renderer->notification(get_string('missingfieldtype', 'data',
(object)['name' => $field->field->name]));
}
} else {
$fielddisplay = $field->display_add_field($entryid, $entrydata);
}
$replacements[] = $errors . $fielddisplay;
} }
// Replace the field id tag. // Replace the field id tag.

View File

@ -260,9 +260,15 @@ switch ($mode) {
// Print confirmation message. // Print confirmation message.
$field = data_get_field_from_id($fid, $data); $field = data_get_field_from_id($fid, $data);
echo $OUTPUT->confirm('<strong>'.$field->name().': '.$field->field->name.'</strong><br /><br />'. get_string('confirmdeletefield','data'), if ($field->type === 'unknown') {
'field.php?d='.$data->id.'&mode=delete&fid='.$fid.'&confirm=1', $fieldtypename = get_string('unknown', 'data');
'field.php?d='.$data->id); } else {
$fieldtypename = $field->name();
}
echo $OUTPUT->confirm('<strong>'.$fieldtypename.': '.$field->field->name.'</strong><br /><br />'.
get_string('confirmdeletefield', 'data'),
'field.php?d='.$data->id.'&mode=delete&fid='.$fid.'&confirm=1',
'field.php?d='.$data->id);
echo $OUTPUT->footer(); echo $OUTPUT->footer();
exit; exit;
@ -317,6 +323,9 @@ $plugins = core_component::get_plugin_list('datafield');
$menufield = array(); $menufield = array();
foreach ($plugins as $plugin=>$fulldir){ foreach ($plugins as $plugin=>$fulldir){
if (!is_dir($fulldir)) {
continue;
}
$menufield[$plugin] = get_string('pluginname', 'datafield_'.$plugin); //get from language files $menufield[$plugin] = get_string('pluginname', 'datafield_'.$plugin); //get from language files
} }
asort($menufield); //sort in alphabetical order asort($menufield); //sort in alphabetical order
@ -360,6 +369,7 @@ if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
$table->wrap = array(false,false,false,false); $table->wrap = array(false,false,false,false);
if ($fff = $DB->get_records('data_fields', array('dataid'=>$data->id),'id')){ if ($fff = $DB->get_records('data_fields', array('dataid'=>$data->id),'id')){
$missingfieldtypes = [];
foreach ($fff as $ff) { foreach ($fff as $ff) {
$field = data_get_field($ff, $data); $field = data_get_field($ff, $data);
@ -378,15 +388,30 @@ if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
'mode' => 'delete', 'mode' => 'delete',
)); ));
$table->data[] = array( // It display a notification when the field type does not exist.
html_writer::link($displayurl, $field->field->name), $deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
$field->image() . '&nbsp;' . $field->name(), $editlink = html_writer::link($displayurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
if ($field->type === 'unknown') {
$missingfieldtypes[] = $field->field->name;
$fieldnamedata = $field->field->name;
$fieltypedata = $field->field->type;
$fieldlinkdata = $deletelink;
} else {
$fieldnamedata = html_writer::link($displayurl, $field->field->name);
$fieltypedata = $field->image() . '&nbsp;' . $field->name();
$fieldlinkdata = $editlink . '&nbsp;' . $deletelink;
}
$table->data[] = [
$fieldnamedata,
$fieltypedata,
$field->field->required ? get_string('yes') : get_string('no'), $field->field->required ? get_string('yes') : get_string('no'),
shorten_text($field->field->description, 30), shorten_text($field->field->description, 30),
html_writer::link($displayurl, $OUTPUT->pix_icon('t/edit', get_string('edit'))) . $fieldlinkdata
'&nbsp;' . ];
html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete'))), }
); if (!empty($missingfieldtypes)) {
echo $OUTPUT->notification(get_string('missingfieldtypes', 'data') . html_writer::alist($missingfieldtypes));
} }
} }
echo html_writer::table($table); echo html_writer::table($table);

View File

@ -238,6 +238,11 @@ $string['invalidfieldid'] = 'Field ID is incorrect';
$string['invalidfieldname'] = 'Please choose another name for this field'; $string['invalidfieldname'] = 'Please choose another name for this field';
$string['invalidfieldtype'] = 'Field type is incorrect'; $string['invalidfieldtype'] = 'Field type is incorrect';
$string['invalidid'] = 'Incorrect data ID'; $string['invalidid'] = 'Incorrect data ID';
$string['missingfieldtype'] = 'Field type for {$a->name} not found';
$string['missingfieldtypes'] = 'The following fields do not have their corresponding field types installed and will not be included in the forms when adding or editing entries.
Their labels may still show on the form, so please update the "Add entry template" accordingly:';
$string['missingfieldtypeimport'] = 'The following fields were not imported because their corresponding field types are not installed:';
$string['unknown'] = 'Unknown field';
$string['invalidpreset'] = '{$a} is not a preset.'; $string['invalidpreset'] = '{$a} is not a preset.';
$string['invalidrecord'] = 'Incorrect record'; $string['invalidrecord'] = 'Incorrect record';
$string['invalidurl'] = 'The URL you just entered is not valid'; $string['invalidurl'] = 'The URL you just entered is not valid';

View File

@ -400,6 +400,12 @@ class data_field_base { // Base class for Database Field Types (see field/*/
if (empty($this->field)) { // No field has been defined yet, try and make one if (empty($this->field)) { // No field has been defined yet, try and make one
$this->define_default_field(); $this->define_default_field();
} }
// Throw an exception if field type doen't exist. Anyway user should never access to edit a field with an unknown fieldtype.
if ($this->type === 'unknown') {
throw new \moodle_exception(get_string('missingfieldtype', 'data', (object)['name' => $this->field->name]));
}
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide'); echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
echo '<form id="editfield" action="'.$CFG->wwwroot.'/mod/data/field.php" method="post">'."\n"; echo '<form id="editfield" action="'.$CFG->wwwroot.'/mod/data/field.php" method="post">'."\n";
@ -417,7 +423,14 @@ class data_field_base { // Base class for Database Field Types (see field/*/
echo $OUTPUT->heading($this->name(), 3); echo $OUTPUT->heading($this->name(), 3);
require_once($CFG->dirroot.'/mod/data/field/'.$this->type.'/mod.html');
$filepath = $CFG->dirroot.'/mod/data/field/'.$this->type.'/mod.html';
if (!file_exists($filepath)) {
throw new \moodle_exception(get_string('missingfieldtype', 'data', (object)['name' => $this->field->name]));
} else {
require_once($filepath);
}
echo html_writer::start_div('mt-3'); echo html_writer::start_div('mt-3');
echo html_writer::tag('input', null, array('type' => 'submit', 'value' => $savebutton, echo html_writer::tag('input', null, array('type' => 'submit', 'value' => $savebutton,
@ -916,7 +929,12 @@ function data_get_field_from_id($fieldid, $data){
function data_get_field_new($type, $data) { function data_get_field_new($type, $data) {
global $CFG; global $CFG;
require_once($CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php'); $filepath = $CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php';
// It should never access this method if the subfield class doesn't exist.
if (!file_exists($filepath)) {
throw new \moodle_exception('invalidfieldtype', 'data');
}
require_once($filepath);
$newfield = 'data_field_'.$type; $newfield = 'data_field_'.$type;
$newfield = new $newfield(0, $data); $newfield = new $newfield(0, $data);
return $newfield; return $newfield;
@ -928,20 +946,24 @@ function data_get_field_new($type, $data) {
* input: $param $field - record from db * input: $param $field - record from db
* *
* @global object * @global object
* @param object $field * @param stdClass $field the field record
* @param object $data * @param stdClass $data the data instance
* @param object $cm * @param stdClass|null $cm optional course module data
* @return data_field_base * @return data_field_base the field object instance or data_field_base if unkown type
*/ */
function data_get_field($field, $data, $cm=null) { function data_get_field($field, $data, $cm=null) {
global $CFG; global $CFG;
if (!isset($field->type)) {
if ($field) { return new data_field_base($field);
require_once('field/'.$field->type.'/field.class.php');
$newfield = 'data_field_'.$field->type;
$newfield = new $newfield($field, $data, $cm);
return $newfield;
} }
$filepath = $CFG->dirroot.'/mod/data/field/'.$field->type.'/field.class.php';
if (!file_exists($filepath)) {
return new data_field_base($field);
}
require_once($filepath);
$newfield = 'data_field_'.$field->type;
$newfield = new $newfield($field, $data, $cm);
return $newfield;
} }
@ -1764,6 +1786,10 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
$fieldname = preg_quote($fieldname, '/'); $fieldname = preg_quote($fieldname, '/');
$patterns[] = "/\[\[$fieldname\]\]/i"; $patterns[] = "/\[\[$fieldname\]\]/i";
$searchfield = data_get_field_from_id($field->field->id, $data); $searchfield = data_get_field_from_id($field->field->id, $data);
if ($searchfield->type === 'unknown') {
continue;
}
if (!empty($search_array[$field->field->id]->data)) { if (!empty($search_array[$field->field->id]->data)) {
$replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data); $replacement[] = $searchfield->display_search_field($search_array[$field->field->id]->data);
} else { } else {
@ -2450,7 +2476,7 @@ abstract class data_preset_importer {
* @return bool * @return bool
*/ */
function import($overwritesettings) { function import($overwritesettings) {
global $DB, $CFG; global $DB, $CFG, $OUTPUT;
$params = $this->get_preset_settings(); $params = $this->get_preset_settings();
$settings = $params->settings; $settings = $params->settings;
@ -2471,7 +2497,7 @@ abstract class data_preset_importer {
} }
else $preservedfields[$cid] = true; else $preservedfields[$cid] = true;
} }
$missingfieldtypes = [];
foreach ($newfields as $nid => $newfield) { foreach ($newfields as $nid => $newfield) {
$cid = optional_param("field_$nid", -1, PARAM_INT); $cid = optional_param("field_$nid", -1, PARAM_INT);
@ -2488,7 +2514,12 @@ abstract class data_preset_importer {
unset($fieldobject); unset($fieldobject);
} else { } else {
/* Make a new field */ /* Make a new field */
include_once("field/$newfield->type/field.class.php"); $filepath = "field/$newfield->type/field.class.php";
if (!file_exists($filepath)) {
$missingfieldtypes[] = $newfield->name;
continue;
}
include_once($filepath);
if (!isset($newfield->description)) { if (!isset($newfield->description)) {
$newfield->description = ''; $newfield->description = '';
@ -2499,6 +2530,9 @@ abstract class data_preset_importer {
unset($fieldclass); unset($fieldclass);
} }
} }
if (!empty($missingfieldtypes)) {
echo $OUTPUT->notification(get_string('missingfieldtypeimport', 'data') . html_writer::alist($missingfieldtypes));
}
} }
/* Get rid of all old unused data */ /* Get rid of all old unused data */
@ -2954,7 +2988,12 @@ function data_import_csv($cm, $data, &$csvdata, $encoding, $fielddelimiter) {
unset($fieldnames[$id]); // To ensure the user provided content fields remain in the array once flipped. unset($fieldnames[$id]); // To ensure the user provided content fields remain in the array once flipped.
} else { } else {
$field = $rawfields[$name]; $field = $rawfields[$name];
require_once("$CFG->dirroot/mod/data/field/$field->type/field.class.php"); $filepath = "$CFG->dirroot/mod/data/field/$field->type/field.class.php";
if (!file_exists($filepath)) {
$errorfield .= "'$name' ";
continue;
}
require_once($filepath);
$classname = 'data_field_' . $field->type; $classname = 'data_field_' . $field->type;
$fields[$name] = new $classname($field, $data, $cm); $fields[$name] = new $classname($field, $data, $cm);
} }

View File

@ -270,7 +270,11 @@ class data_portfolio_caller extends portfolio_module_caller_base {
return true; // too early yet return true; // too early yet
} }
foreach ($this->fieldtypes as $key => $field) { foreach ($this->fieldtypes as $key => $field) {
require_once($CFG->dirroot . '/mod/data/field/' . $field .'/field.class.php'); $filepath = $CFG->dirroot . '/mod/data/field/' . $field .'/field.class.php';
if (!file_exists($filepath)) {
continue;
}
require_once($filepath);
$this->fields[$key] = unserialize(serialize($this->fields[$key])); $this->fields[$key] = unserialize(serialize($this->fields[$key]));
} }
} }
@ -974,7 +978,11 @@ function data_get_tag_title_field($dataid) {
if ($field->addtemplateposition === false) { if ($field->addtemplateposition === false) {
continue; continue;
} }
require_once($CFG->dirroot . '/mod/data/field/' . $field->type . '/field.class.php'); $filepath = $CFG->dirroot . '/mod/data/field/' . $field->type . '/field.class.php';
if (!file_exists($filepath)) {
continue;
}
require_once($filepath);
$classname = 'data_field_' . $field->type; $classname = 'data_field_' . $field->type;
$field->priority = $classname::get_priority(); $field->priority = $classname::get_priority();
$filteredfields[] = $field; $filteredfields[] = $field;
@ -1005,11 +1013,19 @@ function data_get_tag_title_field($dataid) {
* *
* @param stdClass $field The field from the 'data_fields' table * @param stdClass $field The field from the 'data_fields' table
* @param stdClass $entry The entry from the 'data_records' table * @param stdClass $entry The entry from the 'data_records' table
* @return string The title of the entry * @return string|null It will return the title of the entry or null if the field type is not available.
*/ */
function data_get_tag_title_for_entry($field, $entry) { function data_get_tag_title_for_entry($field, $entry) {
global $CFG, $DB; global $CFG, $DB;
require_once($CFG->dirroot . '/mod/data/field/' . $field->type . '/field.class.php');
if (!isset($field->type)) {
return null;
}
$filepath = $CFG->dirroot . '/mod/data/field/' . $field->type . '/field.class.php';
if (!file_exists($filepath)) {
return null;
}
require_once($filepath);
$classname = 'data_field_' . $field->type; $classname = 'data_field_' . $field->type;
$sql = "SELECT dc.* $sql = "SELECT dc.*
@ -1339,7 +1355,7 @@ function data_build_search_array($data, $paging, $searcharray, $defaults = null,
$searchfield = data_get_field_from_id($field->id, $data); $searchfield = data_get_field_from_id($field->id, $data);
// Get field data to build search sql with. If paging is false, get from user. // Get field data to build search sql with. If paging is false, get from user.
// If paging is true, get data from $searcharray which is obtained from the $SESSION (see line 116). // If paging is true, get data from $searcharray which is obtained from the $SESSION (see line 116).
if (!$paging) { if (!$paging && $searchfield->type != 'unknown') {
$val = $searchfield->parse_search_field($defaults); $val = $searchfield->parse_search_field($defaults);
} else { } else {
// Set value from session if there is a value @ the required index. // Set value from session if there is a value @ the required index.