diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index ca36f446382..dceb84e1250 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -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'); diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 27afd285df9..c601b9ab64b 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -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); + } } } diff --git a/course/editsection.php b/course/editsection.php index ecd905b2868..d67b1797604 100644 --- a/course/editsection.php +++ b/course/editsection.php @@ -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, diff --git a/course/editsection_form.php b/course/editsection_form.php index 9f33f8332d9..dcfa9f6917c 100644 --- a/course/editsection_form.php +++ b/course/editsection_form.php @@ -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; } } diff --git a/lib/conditionlib.php b/lib/conditionlib.php index 68e34dcbe94..18d14f953a4 100644 --- a/lib/conditionlib.php +++ b/lib/conditionlib.php @@ -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 diff --git a/lib/db/install.xml b/lib/db/install.xml index 24576c21352..cc3751287bc 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -400,7 +400,7 @@ - +
@@ -417,7 +417,21 @@
- +
+ + + + + + + + + + + + +
+ diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index af8e3603b6d..2ac8e4f60b1 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -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); } diff --git a/lib/modinfolib.php b/lib/modinfolib.php index 114fbd42db3..46aadd924b9 100644 --- a/lib/modinfolib.php +++ b/lib/modinfolib.php @@ -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;