MDL-29538 core_condition: Integrated with the latest code, can now place user field conditions on sections as well
This commit is contained in:
@@ -376,11 +376,15 @@ class backup_section_structure_step extends backup_structure_step {
|
||||
// Add nested elements for _availability table
|
||||
$avail = new backup_nested_element('availability', array('id'), array(
|
||||
'sourcecmid', 'requiredcompletion', 'gradeitemid', 'grademin', 'grademax'));
|
||||
$avail_field = new backup_nested_element('availability_field', array('id'), array(
|
||||
'userfield', 'customfieldid', 'operator', 'value'));
|
||||
$section->add_child($avail);
|
||||
$section->add_child($avail_field);
|
||||
|
||||
// Define sources
|
||||
$section->set_source_table('course_sections', array('id' => backup::VAR_SECTIONID));
|
||||
$avail->set_source_table('course_sections_availability', array('coursesectionid' => backup::VAR_SECTIONID));
|
||||
$avail_field->set_source_table('course_sections_avail_fields', array('coursesectionid' => backup::VAR_SECTIONID));
|
||||
|
||||
// Aliases
|
||||
$section->set_source_alias('section', 'number');
|
||||
|
||||
@@ -547,13 +547,6 @@ class restore_process_course_modules_availability extends restore_execution_step
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to do it for conditional field availability
|
||||
$params = array('backupid' => $this->get_restoreid(), 'itemname' => 'module_availability_field');
|
||||
$rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid');
|
||||
foreach($rs as $availrec) {
|
||||
$availability = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'module_availability_field', $availrec->itemid)->info;
|
||||
$DB->insert_record('course_modules_avail_fields', $availability);
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
}
|
||||
@@ -1038,6 +1031,7 @@ class restore_section_structure_step extends restore_structure_step {
|
||||
$paths[] = $section;
|
||||
if ($CFG->enableavailability) {
|
||||
$paths[] = new restore_path_element('availability', '/section/availability');
|
||||
$paths[] = new restore_path_element('availability_field', '/section/availability_field');
|
||||
}
|
||||
|
||||
// Apply for 'format' plugins optional paths at section level
|
||||
@@ -1141,6 +1135,29 @@ class restore_section_structure_step extends restore_structure_step {
|
||||
$this->set_mapping('course_sections_availability', $newid, $newid);
|
||||
}
|
||||
|
||||
public function process_availability_field($data) {
|
||||
global $DB;
|
||||
$data = (object)$data;
|
||||
// Mark it is as passed by default
|
||||
$passed = true;
|
||||
// Ok, if it is a profile field we need to check it exists
|
||||
if (!is_null($data->customfieldid)) {
|
||||
if (!$DB->record_exists('user_info_field', array('id' => $data->customfieldid))) {
|
||||
$passed = false;
|
||||
}
|
||||
}
|
||||
if ($passed) {
|
||||
// Create the object to insert into the database
|
||||
$avail_field = new stdClass();
|
||||
$avail_field->coursesectionid = $this->task->get_sectionid();
|
||||
$avail_field->userfield = $data->userfield;
|
||||
$avail_field->customfieldid = $data->customfieldid;
|
||||
$avail_field->operator = $data->operator;
|
||||
$avail_field->value = $data->value;
|
||||
$DB->insert_record('course_sections_avail_fields', $avail_field);
|
||||
}
|
||||
}
|
||||
|
||||
protected function after_execute() {
|
||||
// Add section related files, with 'course_section' itemid to match
|
||||
$this->add_related_files('course', 'section', 'course_section');
|
||||
@@ -2547,7 +2564,7 @@ class restore_module_structure_step extends restore_structure_step {
|
||||
$paths[] = $module;
|
||||
if ($CFG->enableavailability) {
|
||||
$paths[] = new restore_path_element('availability', '/module/availability_info/availability');
|
||||
$paths[] = new restore_path_element('availability_fields', '/module/availability_info/availability_field');
|
||||
$paths[] = new restore_path_element('availability_field', '/module/availability_info/availability_field');
|
||||
}
|
||||
|
||||
// Apply for 'format' plugins optional paths at module level
|
||||
@@ -2650,19 +2667,28 @@ class restore_module_structure_step extends restore_structure_step {
|
||||
restore_dbops::set_backup_ids_record($this->get_restoreid(), 'module_availability', $data->id, 0, null, $data);
|
||||
}
|
||||
|
||||
protected function process_availability_fields($data) {
|
||||
protected function process_availability_field($data) {
|
||||
global $DB;
|
||||
|
||||
$data = (object)$data;
|
||||
// Create the object to insert into the database
|
||||
$avail_field = new stdClass();
|
||||
$avail_field->coursemoduleid = $this->task->get_moduleid(); // Lets add the availability cmid
|
||||
$avail_field->userfield = $data->userfield;
|
||||
$avail_field->customfieldid = $data->customfieldid;
|
||||
$avail_field->operator = $data->operator;
|
||||
$avail_field->value = $data->value;
|
||||
// Insert into the database
|
||||
$DB->insert_record('course_modules_avail_fields', $avail_field);
|
||||
// Mark it is as passed by default
|
||||
$passed = true;
|
||||
// Ok, if it is a profile field we need to check it exists
|
||||
if (!is_null($data->customfieldid)) {
|
||||
if (!$DB->record_exists('user_info_field', array('id' => $data->customfieldid))) {
|
||||
$passed = false;
|
||||
}
|
||||
}
|
||||
if ($passed) {
|
||||
// Create the object to insert into the database
|
||||
$avail_field = new stdClass();
|
||||
$avail_field->coursemoduleid = $this->task->get_moduleid(); // Lets add the availability cmid
|
||||
$avail_field->userfield = $data->userfield;
|
||||
$avail_field->customfieldid = $data->customfieldid;
|
||||
$avail_field->operator = $data->operator;
|
||||
$avail_field->value = $data->value;
|
||||
// Insert into the database
|
||||
$DB->insert_record('course_modules_avail_fields', $avail_field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ if (!empty($CFG->enableavailability)) {
|
||||
$sectioninfo = $modinfo->get_section_info($section->section);
|
||||
$section->conditionsgrade = $sectioninfo->conditionsgrade;
|
||||
$section->conditionscompletion = $sectioninfo->conditionscompletion;
|
||||
$section->conditionsfield = $sectioninfo->conditionsfield;
|
||||
}
|
||||
|
||||
$mform = new editsection_form($PAGE->url, array('course' => $course, 'editoroptions' => $editoroptions,
|
||||
|
||||
@@ -38,6 +38,8 @@ class editsection_form extends moodleform {
|
||||
$course = $this->_customdata['course'];
|
||||
|
||||
if (!empty($CFG->enableavailability)) {
|
||||
// String used by conditions more than once
|
||||
$strcondnone = get_string('none', 'condition');
|
||||
// Grouping conditions - only if grouping is enabled at site level
|
||||
if (!empty($CFG->enablegroupmembersonly)) {
|
||||
$options = array();
|
||||
@@ -68,7 +70,7 @@ class editsection_form extends moodleform {
|
||||
$gradeoptions[$id] = $item->get_name();
|
||||
}
|
||||
asort($gradeoptions);
|
||||
$gradeoptions = array(0 => get_string('none', 'condition')) + $gradeoptions;
|
||||
$gradeoptions = array(0 => $strcondnone) + $gradeoptions;
|
||||
|
||||
$grouparray = array();
|
||||
$grouparray[] = $mform->createElement('select', 'conditiongradeitemid', '', $gradeoptions);
|
||||
@@ -92,6 +94,25 @@ class editsection_form extends moodleform {
|
||||
'conditiongradeadds', 2, get_string('addgrades', 'condition'), true);
|
||||
$mform->addHelpButton('conditiongradegroup[0]', 'gradecondition', 'condition');
|
||||
|
||||
// Conditions based on user fields
|
||||
$operators = condition_info::get_condition_user_field_operators();
|
||||
$useroptions = condition_info::get_condition_user_fields();
|
||||
asort($useroptions);
|
||||
|
||||
$useroptions = array(0 => $strcondnone) + $useroptions;
|
||||
$grouparray = array();
|
||||
$grouparray[] =& $mform->createElement('select', 'conditionfield', '', $useroptions);
|
||||
$grouparray[] =& $mform->createElement('select', 'conditionfieldoperator', '', $operators);
|
||||
$grouparray[] =& $mform->createElement('text', 'conditionfieldvalue');
|
||||
$mform->setType('conditionfieldvalue', PARAM_RAW);
|
||||
$group = $mform->createElement('group', 'conditionfieldgroup', get_string('userfield', 'condition'), $grouparray);
|
||||
|
||||
$fieldcount = count($fullcs->conditionsfield) + 1;
|
||||
|
||||
$this->repeat_elements(array($group), $fieldcount, array(), 'conditionfieldrepeats', 'conditionfieldadds', 2,
|
||||
get_string('adduserfields', 'condition'), true);
|
||||
$mform->addHelpButton('conditionfieldgroup[0]', 'userfield', 'condition');
|
||||
|
||||
// Conditions based on completion
|
||||
$completion = new completion_info($course);
|
||||
if ($completion->is_enabled()) {
|
||||
@@ -106,7 +127,7 @@ class editsection_form extends moodleform {
|
||||
}
|
||||
}
|
||||
asort($completionoptions);
|
||||
$completionoptions = array(0 => get_string('none', 'condition')) +
|
||||
$completionoptions = array(0 => $strcondnone) +
|
||||
$completionoptions;
|
||||
|
||||
$completionvalues = array(
|
||||
@@ -145,6 +166,18 @@ class editsection_form extends moodleform {
|
||||
$num++;
|
||||
}
|
||||
|
||||
$num = 0;
|
||||
foreach ($fullcs->conditionsfield as $fieldid => $data) {
|
||||
$groupelements = $mform->getElement(
|
||||
'conditionfieldgroup[' . $num . ']')->getElements();
|
||||
$groupelements[0]->setValue($fieldid);
|
||||
$groupelements[1]->setValue(is_null($data->operator) ? '' :
|
||||
$data->operator);
|
||||
$groupelements[2]->setValue(is_null($data->value) ? '' :
|
||||
$data->operator);
|
||||
$num++;
|
||||
}
|
||||
|
||||
if ($completion->is_enabled()) {
|
||||
$num = 0;
|
||||
foreach ($fullcs->conditionscompletion as $othercmid => $state) {
|
||||
@@ -178,6 +211,25 @@ class editsection_form extends moodleform {
|
||||
$errors['availablefrom'] = get_string('badavailabledates', 'condition');
|
||||
}
|
||||
|
||||
// Conditions: Verify that the user profile field has not been declared more than once
|
||||
if (array_key_exists('conditionfieldgroup', $data)) {
|
||||
// Array to store the existing fields
|
||||
$arrcurrentfields = array();
|
||||
// Error message displayed if any condition is declared more than once. We use lang string because
|
||||
// this way we don't actually generate the string unless there is an error.
|
||||
$stralreadydeclaredwarning = new lang_string('fielddeclaredmultipletimes', 'condition');
|
||||
foreach ($data['conditionfieldgroup'] as $i => $fielddata) {
|
||||
if ($fielddata['conditionfield'] == 0) { // Don't need to bother if none is selected
|
||||
continue;
|
||||
}
|
||||
if (in_array($fielddata['conditionfield'], $arrcurrentfields)) {
|
||||
$errors["conditionfieldgroup[{$i}]"] = $stralreadydeclaredwarning->out();
|
||||
}
|
||||
// Add the field to the array
|
||||
$arrcurrentfields[] = $fielddata['conditionfield'];
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
|
||||
+22
-16
@@ -364,7 +364,7 @@ class condition_info_section extends condition_info_base {
|
||||
*/
|
||||
abstract class condition_info_base {
|
||||
/** @var object, bool, string, string, array */
|
||||
protected $item, $gotdata, $availtable, $idfieldname, $usergroupings;
|
||||
protected $item, $gotdata, $availtable, $availfieldtable, $idfieldname, $usergroupings;
|
||||
|
||||
/**
|
||||
* Constructs with item details.
|
||||
@@ -403,6 +403,9 @@ abstract class condition_info_base {
|
||||
// DB table to store availability conditions
|
||||
$this->availtable = $tableprefix . '_availability';
|
||||
|
||||
// DB table to store availability conditions for user fields
|
||||
$this->availfieldtable = $tableprefix . '_avail_fields';
|
||||
|
||||
// Name of module/section ID field in DB
|
||||
$this->idfieldname = $idfield;
|
||||
|
||||
@@ -503,13 +506,14 @@ abstract class condition_info_base {
|
||||
$item->conditionsgrade[$condition->gradeitemid] = $minmax;
|
||||
}
|
||||
}
|
||||
|
||||
// For user fields
|
||||
$sql = "SELECT cma.id as cmaid, cma.*, uf.*
|
||||
FROM {course_modules_avail_fields} cma
|
||||
$sql = "SELECT a.id as cmaid, a.*, uf.*
|
||||
FROM {" . $tableprefix . "_avail_fields} a
|
||||
LEFT JOIN {user_info_field} uf
|
||||
ON cma.customfieldid = uf.id
|
||||
WHERE coursemoduleid = :cmid";
|
||||
if ($conditions = $DB->get_records_sql($sql, array('cmid' => $cm->id))) {
|
||||
ON a.customfieldid = uf.id
|
||||
WHERE " . $idfield . " = :itemid";
|
||||
if ($conditions = $DB->get_records_sql($sql, array('itemid' => $item->id))) {
|
||||
foreach ($conditions as $condition) {
|
||||
// If the custom field is not empty, then
|
||||
// we have a custom profile field
|
||||
@@ -531,7 +535,7 @@ abstract class condition_info_base {
|
||||
$details->fieldname = $fieldname;
|
||||
$details->operator = $condition->operator;
|
||||
$details->value = $condition->value;
|
||||
$cm->conditionsfield[$field] = $details;
|
||||
$item->conditionsfield[$field] = $details;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -654,8 +658,11 @@ abstract class condition_info_base {
|
||||
public function add_user_field_condition($field, $operator, $value) {
|
||||
global $DB;
|
||||
|
||||
// Get the field name
|
||||
$idfieldname = $this->idfieldname;
|
||||
|
||||
$objavailfield = new stdClass;
|
||||
$objavailfield->coursemoduleid = $this->cm->id;
|
||||
$objavailfield->$idfieldname = $this->item->id;
|
||||
if (is_numeric($field)) { // If the condition field is numeric then it is a custom profile field
|
||||
// Need to get the field name so we can add it to the cache
|
||||
$ufield = $DB->get_field('user_info_field', 'name', array('id' => $field));
|
||||
@@ -667,10 +674,10 @@ abstract class condition_info_base {
|
||||
}
|
||||
$objavailfield->operator = $operator;
|
||||
$objavailfield->value = $value;
|
||||
$DB->insert_record('course_modules_avail_fields', $objavailfield, false);
|
||||
$DB->insert_record($this->availfieldtable, $objavailfield, false);
|
||||
|
||||
// Store in memory too
|
||||
$this->cm->conditionsfield[$field] = $objavailfield;
|
||||
$this->item->conditionsfield[$field] = $objavailfield;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -718,8 +725,7 @@ abstract class condition_info_base {
|
||||
global $DB;
|
||||
|
||||
$DB->delete_records($this->availtable, array($this->idfieldname => $this->item->id));
|
||||
$DB->delete_records('course_modules_avail_fields',
|
||||
array('coursemoduleid' => $this->cm->id));
|
||||
$DB->delete_records($this->availfieldtable, array($this->idfieldname => $this->item->id));
|
||||
|
||||
// And from memory
|
||||
$this->item->conditionsgrade = array();
|
||||
@@ -786,9 +792,9 @@ abstract class condition_info_base {
|
||||
}
|
||||
|
||||
// User field conditions
|
||||
if (count($this->cm->conditionsfield) > 0) {
|
||||
if (count($this->item->conditionsfield) > 0) {
|
||||
// Need the array of operators
|
||||
foreach ($this->cm->conditionsfield as $field => $details) {
|
||||
foreach ($this->item->conditionsfield as $field => $details) {
|
||||
$a = new stdclass;
|
||||
$a->field = $details->fieldname;
|
||||
$a->operator = get_string($details->operator, 'filters');
|
||||
@@ -990,8 +996,8 @@ abstract class condition_info_base {
|
||||
}
|
||||
|
||||
// Check if user field condition
|
||||
if (count($this->cm->conditionsfield) > 0) {
|
||||
foreach ($this->cm->conditionsfield as $field => $details) {
|
||||
if (count($this->item->conditionsfield) > 0) {
|
||||
foreach ($this->item->conditionsfield as $field => $details) {
|
||||
$uservalue = $this->get_cached_user_profile_field($userid, $field, $grabthelot);
|
||||
if (!$fieldconditionmet = $this->is_field_condition_met($details->operator, $uservalue, $details->value)) {
|
||||
// Set available to false
|
||||
|
||||
+16
-2
@@ -400,7 +400,7 @@
|
||||
<INDEX NAME="course_section" UNIQUE="true" FIELDS="course, section"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="course_sections_availability" COMMENT="Completion or grade conditions that affect if a section is currently available to students." PREVIOUS="course_sections" NEXT="course_request">
|
||||
<TABLE NAME="course_sections_availability" COMMENT="Completion or grade conditions that affect if a section is currently available to students." PREVIOUS="course_sections" NEXT="course_sections_avail_fields">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="coursesectionid"/>
|
||||
<FIELD NAME="coursesectionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the section whose availability is being restricted by this condition." PREVIOUS="id" NEXT="sourcecmid"/>
|
||||
@@ -417,7 +417,21 @@
|
||||
<KEY NAME="gradeitemid" TYPE="foreign" FIELDS="gradeitemid" REFTABLE="grade_items" REFFIELDS="id" PREVIOUS="sourcecmid"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="course_request" COMMENT="course requests" PREVIOUS="course_sections_availability" NEXT="filter_active">
|
||||
<TABLE NAME="course_sections_avail_fields" COMMENT="Stores user field conditions that affect whether an activity is currently available to students." PREVIOUS="course_sections_availability" NEXT="course_request">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="coursesectionid"/>
|
||||
<FIELD NAME="coursesectionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the section whose availability is being restricted by this condition." PREVIOUS="id" NEXT="userfield"/>
|
||||
<FIELD NAME="userfield" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false" COMMENT="The user profile field this record relates to if it is not a custom profile field" PREVIOUS="coursesectionid" NEXT="customfieldid"/>
|
||||
<FIELD NAME="customfieldid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="ID for the custom field if this relates to one" PREVIOUS="userfield" NEXT="operator"/>
|
||||
<FIELD NAME="operator" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" COMMENT="The operator, such as less than or equal to, between the field and the value" PREVIOUS="customfieldid" NEXT="value"/>
|
||||
<FIELD NAME="value" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The required value of the field" PREVIOUS="operator"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="coursesectionid"/>
|
||||
<KEY NAME="coursesectionid" TYPE="foreign" FIELDS="coursesectionid" REFTABLE="course_sections" REFFIELDS="id" PREVIOUS="primary"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="course_request" COMMENT="course requests" PREVIOUS="course_sections_avail_fields" NEXT="filter_active">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="fullname"/>
|
||||
<FIELD NAME="fullname" TYPE="char" LENGTH="254" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="shortname"/>
|
||||
|
||||
@@ -611,6 +611,26 @@ function xmldb_main_upgrade($oldversion) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Define table section_modules_avail_fields to be created
|
||||
$table = new xmldb_table('course_sections_avail_fields');
|
||||
|
||||
// Adding fields to table course_modules_section_fields
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('coursesectionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('userfield', XMLDB_TYPE_CHAR, '50', null, null, null, null);
|
||||
$table->add_field('customfieldid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
|
||||
$table->add_field('operator', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('value', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
// Adding keys to table course_modules_avail_fields
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('coursesectionid', XMLDB_KEY_FOREIGN, array('coursesectionid'), 'course_sections', array('id'));
|
||||
|
||||
// Conditionally launch create table for section_modules_avail_fields
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Main savepoint reached
|
||||
upgrade_main_savepoint(true, 2012051700.02);
|
||||
}
|
||||
|
||||
@@ -1497,6 +1497,8 @@ class section_info extends stdClass {
|
||||
? $data->conditionscompletion : array();
|
||||
$this->conditionsgrade = isset($data->conditionsgrade)
|
||||
? $data->conditionsgrade : array();
|
||||
$this->conditionsfield = isset($data->conditionsfield)
|
||||
? $data->conditionsfield : array();
|
||||
|
||||
// Other data from other places
|
||||
$this->course = $courseid;
|
||||
|
||||
Reference in New Issue
Block a user