MDL-29538 core_condition: changed the logic in the code so that it works with the new database structure as well as tidying up parts of the code

This commit is contained in:
Mark Nelson 2012-05-09 01:32:45 +08:00
parent 92fb7dd3a5
commit cb4492c200
5 changed files with 203 additions and 163 deletions

View file

@ -523,10 +523,12 @@ class restore_process_course_modules_availability extends restore_execution_step
foreach($rs as $availrec) { foreach($rs as $availrec) {
$allmatchesok = true; $allmatchesok = true;
// Get the complete availabilityobject // Get the complete availabilityobject
$availability = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'module_availability', $availrec->itemid)->info; $availability = restore_dbops::get_backup_ids_record($this->get_restoreid(),
'module_availability', $availrec->itemid)->info;
// Map the sourcecmid if needed and possible // Map the sourcecmid if needed and possible
if (!empty($availability->sourcecmid)) { if (!empty($availability->sourcecmid)) {
$newcm = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'course_module', $availability->sourcecmid); $newcm = restore_dbops::get_backup_ids_record($this->get_restoreid(),
'course_module', $availability->sourcecmid);
if ($newcm) { if ($newcm) {
$availability->sourcecmid = $newcm->newitemid; $availability->sourcecmid = $newcm->newitemid;
} else { } else {
@ -535,7 +537,8 @@ class restore_process_course_modules_availability extends restore_execution_step
} }
// Map the gradeitemid if needed and possible // Map the gradeitemid if needed and possible
if (!empty($availability->gradeitemid)) { if (!empty($availability->gradeitemid)) {
$newgi = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'grade_item', $availability->gradeitemid); $newgi = restore_dbops::get_backup_ids_record($this->get_restoreid(),
'grade_item', $availability->gradeitemid);
if ($newgi) { if ($newgi) {
$availability->gradeitemid = $newgi->newitemid; $availability->gradeitemid = $newgi->newitemid;
} else { } else {
@ -551,7 +554,8 @@ class restore_process_course_modules_availability extends restore_execution_step
$params = array('backupid' => $this->get_restoreid(), 'itemname' => 'module_availability_field'); $params = array('backupid' => $this->get_restoreid(), 'itemname' => 'module_availability_field');
$rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid'); $rs = $DB->get_recordset('backup_ids_temp', $params, '', 'itemid');
foreach($rs as $availrec) { foreach($rs as $availrec) {
$availability = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'module_availability_field', $availrec->itemid)->info; $availability = restore_dbops::get_backup_ids_record($this->get_restoreid(),
'module_availability_field', $availrec->itemid)->info;
$DB->insert_record('course_modules_avail_fields', $availability); $DB->insert_record('course_modules_avail_fields', $availability);
} }
$rs->close(); $rs->close();

View file

@ -263,8 +263,8 @@ abstract class moodleform_mod extends moodleform {
foreach($fullcm->conditionsfield as $field=>$details) { foreach($fullcm->conditionsfield as $field=>$details) {
$groupelements=$mform->getElement('conditionfieldgroup['.$num.']')->getElements(); $groupelements=$mform->getElement('conditionfieldgroup['.$num.']')->getElements();
$groupelements[0]->setValue($field); $groupelements[0]->setValue($field);
$groupelements[1]->setValue(is_null($details->operator)?'':$details->operator); $groupelements[1]->setValue(is_null($details->operator) ? '' : $details->operator);
$groupelements[2]->setValue(is_null($details->value)?'':($details->value)); $groupelements[2]->setValue(is_null($details->value) ? '' : $details->value);
$num++; $num++;
} }
@ -533,7 +533,7 @@ abstract class moodleform_mod extends moodleform {
$ci = new condition_info($this->_cm, CONDITION_MISSING_EXTRATABLE); $ci = new condition_info($this->_cm, CONDITION_MISSING_EXTRATABLE);
$this->_cm = $ci->get_full_course_module(); $this->_cm = $ci->get_full_course_module();
$count = count($this->_cm->conditionsgrade)+1; $count = count($this->_cm->conditionsgrade)+1;
$fieldcount = count($this->_cm->conditionsfield)+1; $fieldcount = count($this->_cm->conditionsfield) + 1;
} else { } else {
$count = 1; $count = 1;
$fieldcount = 1; $fieldcount = 1;
@ -575,7 +575,7 @@ abstract class moodleform_mod extends moodleform {
} }
} }
asort($completionoptions); asort($completionoptions);
$completionoptions = array(0=>$strnone)+$completionoptions; $completionoptions = array(0=>$strnone) + $completionoptions;
$completionvalues=array( $completionvalues=array(
COMPLETION_COMPLETE=>get_string('completion_complete','condition'), COMPLETION_COMPLETE=>get_string('completion_complete','condition'),

View file

@ -75,7 +75,7 @@ $string['requires_grade_any'] = 'Not available until you have a grade in <strong
$string['requires_grade_max'] = 'Not available unless you get an appropriate score in <strong>{$a}</strong>.'; $string['requires_grade_max'] = 'Not available unless you get an appropriate score in <strong>{$a}</strong>.';
$string['requires_grade_min'] = 'Not available until you achieve a required score in <strong>{$a}</strong>.'; $string['requires_grade_min'] = 'Not available until you achieve a required score in <strong>{$a}</strong>.';
$string['requires_grade_range'] = 'Not available unless you get a particular score in <strong>{$a}</strong>.'; $string['requires_grade_range'] = 'Not available unless you get a particular score in <strong>{$a}</strong>.';
$string['requires_user_field_restriction'] = 'Only available to users who\'s user field \'{$a->field}\' {$a->operator} \'{$a->value}\'.'; $string['requires_user_field_restriction'] = 'Not available unless your <strong>{$a->field}</strong> {$a->operator} <strong>{$a->value}</strong>.';
$string['showavailability'] = 'Before activity can be accessed'; $string['showavailability'] = 'Before activity can be accessed';
$string['showavailabilitysection'] = 'Before section can be accessed'; $string['showavailabilitysection'] = 'Before section can be accessed';
$string['showavailability_hide'] = 'Hide activity entirely'; $string['showavailability_hide'] = 'Hide activity entirely';
@ -83,7 +83,7 @@ $string['showavailability_show'] = 'Show activity greyed-out, with restriction i
$string['showavailabilitysection_hide'] = 'Hide section entirely'; $string['showavailabilitysection_hide'] = 'Hide section entirely';
$string['showavailabilitysection_show'] = 'Show section greyed-out, with restriction information'; $string['showavailabilitysection_show'] = 'Show section greyed-out, with restriction information';
$string['userfield'] = 'User field'; $string['userfield'] = 'User field';
$string['userfield_help'] = 'This is an attribute associated with each individual user'; $string['userfield_help'] = 'You can restrict access based on any field from the user&rsquo;s profile.';
$string['userrestriction_hidden'] = 'Restricted (completely hidden, no message): &lsquo;{$a}&rsquo;'; $string['userrestriction_hidden'] = 'Restricted (completely hidden, no message): &lsquo;{$a}&rsquo;';
$string['userrestriction_visible'] = 'Restricted: &lsquo;{$a}&rsquo;'; $string['userrestriction_visible'] = 'Restricted: &lsquo;{$a}&rsquo;';
$string['groupingnoaccess'] = 'You do not currently belong to a group which has access to this section. '; $string['groupingnoaccess'] = 'You do not currently belong to a group which has access to this section. ';

View file

@ -50,6 +50,36 @@ define('CONDITION_MISSING_EXTRATABLE', 1);
*/ */
define('CONDITION_MISSING_EVERYTHING', 2); define('CONDITION_MISSING_EVERYTHING', 2);
/**
* OP_CONTAINS - comparison operator that determines whether a specified user field contains
* a provided variable
*/
define('OP_CONTAINS', get_string('contains', 'filters'));
/**
* OP_DOES_NOT_CONTAIN - comparison operator that determines whether a specified user field does not
* contain a provided variable
*/
define('OP_DOES_NOT_CONTAIN', get_string('doesnotcontain', 'filters'));
/**
* OP_IS_EQUAL_TO - comparison operator that determines whether a specified user field is equal to
* a provided variable
*/
define('OP_IS_EQUAL_TO', get_string('isequalto', 'filters'));
/**
* OP_STARTS_WITH - comparison operator that determines whether a specified user field starts with
* a provided variable
*/
define('OP_STARTS_WITH', get_string('startswith', 'filters'));
/**
* OP_ENDS_WITH - comparison operator that determines whether a specified user field ends with
* a provided variable
*/
define('OP_ENDS_WITH', get_string('endswith', 'filters'));
/**
* OP_IS_EMPTY - comparison operator that determines whether a specified user field is empty
*/
define('OP_IS_EMPTY', get_string('isempty', 'filters'));
require_once($CFG->libdir.'/completionlib.php'); require_once($CFG->libdir.'/completionlib.php');
/** /**
@ -474,30 +504,32 @@ abstract class condition_info_base {
} }
} }
// For user fields // For user fields
$conditions = $DB->get_records_sql($sql=" $sql = "SELECT cma.id as cmaid, cma.*, uf.*
SELECT FROM {course_modules_avail_fields} cma
cma.* LEFT JOIN {user_info_field} uf
FROM ON cma.customfieldid = uf.id
{course_modules_avail_fields} cma WHERE coursemoduleid= :cmid";
WHERE if ($conditions = $DB->get_records_sql($sql, array('cmid'=>$cm->id))) {
coursemoduleid=?",array($cm->id));
foreach ($conditions as $condition) { foreach ($conditions as $condition) {
// If the condition field is numeric, check // If the condition field is numeric, check
// the user profile field is available // the user profile field is available
if (is_numeric($condition->field)) { if (!empty($condition->customfieldid)) {
if ($field = $DB->get_record('user_info_field', array('id'=>$condition->field))) { $field = $condition->customfieldid;
$fieldname = $field->name; if (!empty($condition->name)) {
$fieldname = $condition->name;
} else { } else {
$fieldname = '!missing'; $fieldname = '!missing';
} }
} else { } else {
$fieldname = $condition->field; $field = $condition->userfield;
$fieldname = $condition->userfield;
} }
$details = new stdClass; $details = new stdClass;
$details->fieldname = $fieldname; $details->fieldname = $fieldname;
$details->operator = $condition->operator; $details->operator = $condition->operator;
$details->value = $condition->value; $details->value = $condition->value;
$cm->conditionsfield[$condition->field] = $details; $cm->conditionsfield[$field] = $details;
}
} }
} }
} }
@ -536,16 +568,16 @@ WHERE
* The operators that provide the relationship * The operators that provide the relationship
* between a field and a value. * between a field and a value.
* *
* @return array * @return array Associative array from operator constant to display name
*/ */
public function get_condition_user_field_operators() { public static function get_condition_user_field_operators() {
return array( return array(
0 => get_string('contains', 'filters'), OP_CONTAINS => OP_CONTAINS,
1 => get_string('doesnotcontain','filters'), OP_DOES_NOT_CONTAIN => OP_DOES_NOT_CONTAIN,
2 => get_string('isequalto','filters'), OP_IS_EQUAL_TO => OP_IS_EQUAL_TO,
3 => get_string('startswith','filters'), OP_STARTS_WITH => OP_STARTS_WITH,
4 => get_string('endswith','filters'), OP_ENDS_WITH => OP_ENDS_WITH,
5 => get_string('isempty','filters') OP_IS_EMPTY => OP_IS_EMPTY
); );
} }
@ -553,30 +585,30 @@ WHERE
* The user fields we can compare * The user fields we can compare
* *
* @global $DB * @global $DB
* @return array * @return array Associative array from user field constants to display name
*/ */
public function get_condition_user_fields() { public static function get_condition_user_fields() {
global $DB; global $DB;
$userfields = array( $userfields = array(
'firstname' => get_string('firstname'), 'firstname' => get_user_field_name('firstname'),
'lastname' => get_string('lastname'), 'lastname' => get_user_field_name('lastname'),
'email' => get_string('email'), 'email' => get_user_field_name('email'),
'city' => get_string('city'), 'city' => get_user_field_name('city'),
'country' => get_string('country'), 'country' => get_user_field_name('country'),
'interests' => get_string('interests'), 'interests' => get_user_field_name('interests'),
'url' => get_string('webpage'), 'url' => get_user_field_name('url'),
'icq' => get_string('icqnumber'), 'icq' => get_user_field_name('icq'),
'skype' => get_string('skypeid'), 'skype' => get_user_field_name('skype'),
'aim' => get_string('aimid'), 'aim' => get_user_field_name('aim'),
'yahoo' => get_string('yahooid'), 'yahoo' => get_user_field_name('yahoo'),
'msn' => get_string('msnid'), 'msn' => get_user_field_name('msn'),
'idnumber' => get_string('idnumber'), 'idnumber' => get_user_field_name('idnumber'),
'institution' => get_string('institution'), 'institution' => get_user_field_name('institution'),
'department' => get_string('department'), 'department' => get_user_field_name('department'),
'phone' => get_string('phone'), 'phone' => get_user_field_name('phone'),
'phone2' => get_string('phone2'), 'phone2' => get_user_field_name('phone2'),
'address' => get_string('address') 'address' => get_user_field_name('address')
); );
// Go through the custom profile fields now // Go through the custom profile fields now
@ -620,11 +652,17 @@ WHERE
public function add_user_field_condition($field, $operator, $value) { public function add_user_field_condition($field, $operator, $value) {
// Add to DB // Add to DB
global $DB; global $DB;
$DB->insert_record('course_modules_avail_fields',
(object)array('coursemoduleid'=>$this->cm->id, $objavailfield = new stdClass;
'field'=>$field,'operator'=>$operator, $objavailfield->coursemoduleid = $this->cm->id;
'value'=>$value), if (is_numeric($field)) { // If the condition field is numeric then it is a custom profile field
false); $objavailfield->customfieldid = $field;
} else {
$objavailfield->userfield = $field;
}
$objavailfield->operator = $operator;
$objavailfield->value = $value;
$DB->insert_record('course_modules_avail_fields', $objavailfield, false);
// Store in memory too // Store in memory too
$this->cm->conditionsfield[$field] = (object)array( $this->cm->conditionsfield[$field] = (object)array(
@ -746,11 +784,10 @@ WHERE
// User field conditions // User field conditions
if (count($this->cm->conditionsfield)>0) { if (count($this->cm->conditionsfield)>0) {
// Need the array of operators // Need the array of operators
$arroperators = $this->get_condition_user_field_operators();
foreach ($this->cm->conditionsfield as $field=>$details) { foreach ($this->cm->conditionsfield as $field=>$details) {
$a = new stdclass; $a = new stdclass;
$a->field = $details->fieldname; $a->field = $details->fieldname;
$a->operator = $arroperators[$details->operator]; $a->operator = $details->operator;
$a->value = $details->value; $a->value = $details->value;
$information .= get_string('requires_user_field_restriction', 'condition', $a); $information .= get_string('requires_user_field_restriction', 'condition', $a);
} }
@ -950,59 +987,17 @@ WHERE
// Check if user field condition // Check if user field condition
if (count($this->cm->conditionsfield)>0) { if (count($this->cm->conditionsfield)>0) {
$arroperators = $this->get_condition_user_field_operators();
foreach ($this->cm->conditionsfield as $field=>$details) { foreach ($this->cm->conditionsfield as $field=>$details) {
// Need the array of operators // Need the array of operators
$operator = $details->operator; $operator = $details->operator;
$value = $details->value; $value = $details->value;
$uservalue = $this->get_cached_user_profile_field($userid, $field, $grabthelot); $uservalue = $this->get_cached_user_profile_field($userid, $field, $grabthelot);
// Assume that it passed if (!$fieldconditionmet = $this->field_condition_met($operator, $uservalue, $value)) {
$fieldconditionmet = true;
switch($operator) {
case 0: // contains
$pos = strpos($uservalue, $value);
if ($pos === false) {
$fieldconditionmet = false;
}
break;
case 1: // does not contain
if (!empty($value)) {
$pos = strpos($uservalue, $value);
if ($pos !== false) {
$fieldconditionmet = false;
}
}
break;
case 2: // equal to
if ($value !== $uservalue) {
$fieldconditionmet = false;
}
break;
case 3: // starts with
$length = strlen($value);
if ((substr($uservalue, 0, $length) !== $value)) {
$fieldconditionmet = false;
}
break;
case 4: // ends with
$length = strlen($value);
$start = $length * -1; //negative
if (substr($uservalue, $start) !== $value) {
$fieldconditionmet = false;
}
break;
case 5: // empty
if (!empty($uservalue)) {
$fieldconditionmet = false;
}
break;
}
if (!$fieldconditionmet) {
// Set available to false // Set available to false
$available = false; $available = false;
$a = new stdClass(); $a = new stdClass();
$a->field = $details->fieldname; $a->field = $details->fieldname;
$a->operator = $arroperators[$operator]; $a->operator = $operator;
$a->value = $details->value; $a->value = $details->value;
$information .= get_string('requires_user_field_restriction', 'condition', $a).' '; $information .= get_string('requires_user_field_restriction', 'condition', $a).' ';
} }
@ -1170,18 +1165,67 @@ WHERE
} }
} }
/**
* Returns true if a field meets the required conditions, false otherwise.
*
* @param char $operator the requirement/condition
* @param char $uservalue the user's value
* @param char $value the value required
* @return boolean
*/
private function field_condition_met($operator, $uservalue, $value) {
$fieldconditionmet = true;
switch($operator) {
case OP_CONTAINS: // contains
$pos = strpos($uservalue, $value);
if ($pos === false) {
$fieldconditionmet = false;
}
break;
case OP_DOES_NOT_CONTAIN: // does not contain
if (!empty($value)) {
$pos = strpos($uservalue, $value);
if ($pos !== false) {
$fieldconditionmet = false;
}
}
break;
case OP_IS_EQUAL_TO: // equal to
if ($value !== $uservalue) {
$fieldconditionmet = false;
}
break;
case OP_STARTS_WITH: // starts with
$length = strlen($value);
if ((substr($uservalue, 0, $length) !== $value)) {
$fieldconditionmet = false;
}
break;
case OP_ENDS_WITH: // ends with
$length = strlen($value);
$start = $length * -1; //negative
if (substr($uservalue, $start) !== $value) {
$fieldconditionmet = false;
}
break;
case OP_IS_EMPTY: // is empty
if (!empty($uservalue)) {
$fieldconditionmet = false;
}
break;
}
return $fieldconditionmet;
}
/** /**
* Return the value for a user's profile field * Return the value for a user's profile field
* *
* @global object * @param int $userid set if requesting grade for a different user (does
* @global object
* @global object
* @param int $userid Set if requesting grade for a different user (does
* not use cache) * not use cache)
* @param int $fieldid the user profile field id * @param int $fieldid the user profile field id
* @param bool $grabthelot If true, grabs all the user profile fields for * @param bool $grabthelot If true, grabs all the user profile fields for
* current user on this course, so that later ones come from cache * current user on this course, so that later ones come from cache
* @return string the user value * @return string the user value, or false if user does not have a user field value yet
*/ */
private function get_cached_user_profile_field($userid, $fieldid, $grabthelot) { private function get_cached_user_profile_field($userid, $fieldid, $grabthelot) {
global $USER, $DB, $SESSION; global $USER, $DB, $SESSION;
@ -1197,67 +1241,53 @@ WHERE
if (!array_key_exists($fieldid, $SESSION->userfieldcache)) { if (!array_key_exists($fieldid, $SESSION->userfieldcache)) {
if ($grabthelot) { if ($grabthelot) {
// Get all custom profile field values for user // Get all custom profile field values for user
$rs = $DB->get_recordset_sql(" $sql = "SELECT uf.id, ud.data
SELECT FROM {user_info_field} uf
uf.id, ud.data
FROM
{user_info_field} uf
LEFT JOIN {user_info_data} ud LEFT JOIN {user_info_data} ud
ON uf.id = ud.fieldid ON uf.id = ud.fieldid
WHERE WHERE ud.userid = :userid";
ud.userid=?", array($USER->id)); if ($records = $DB->get_records_sql($sql, array('userid'=>$USER->id))) {
foreach ($rs as $record) { foreach ($records as $r) {
$SESSION->userfieldcache[$record->id] = $record->data; $SESSION->userfieldcache[$r->id] = $r->data;
} }
$rs->close();
// And if it's still not set, well it doesn't exist (eg
// the user may have no entry for the profile field)
if (!array_key_exists($fieldid, $SESSION->userfieldcache)) {
$SESSION->userfieldcache[$fieldid] = false;
} }
} else { } else {
// Just get specified user field // Just get specified user field
if ($record = $DB->get_record_sql(" $sql = "SELECT ud.data
SELECT FROM {user_info_data} ud
ud.data
FROM
{user_info_data} ud
INNER JOIN {user_info_field} uf INNER JOIN {user_info_field} uf
ON ud.fieldid = uf.id ON ud.fieldid = uf.id
WHERE WHERE uf.id = :fieldid
uf.id = ? AND ud.userid = :userid";
AND if ($record = $DB->get_record_sql($sql, array('fieldid'=>$fieldid, 'userid'=>$USER->id))) {
ud.userid = ?", array($fieldid, $USER->id))) {
$field = $record->data; $field = $record->data;
} else { } else {
$field = false; $field = false;
} }
$SESSION->userfieldcache[$fieldid]=$field; $SESSION->userfieldcache[$fieldid] = $field;
} }
} }
if (!empty($SESSION->userfieldcache[$fieldid])) {
return $SESSION->userfieldcache[$fieldid]; return $SESSION->userfieldcache[$fieldid];
} else {
return false;
}
} else { } else {
return $USER->$fieldid; return $USER->$fieldid;
} }
} else { } else {
if ($iscustomprofilefield) { if ($iscustomprofilefield) {
if ($record = $DB->get_record_sql(" $sql = "SELECT ud.data
SELECT FROM {user_info_data} ud
ud.data
FROM
{user_info_data} ud
INNER JOIN {user_info_field} uf INNER JOIN {user_info_field} uf
ON ud.fieldid = uf.id ON ud.fieldid = uf.id
WHERE WHERE uf.id = :fieldid
uf.id = ? AND ud.userid = :userid";
AND if ($record = $DB->get_record_sql($sql, array('fieldid'=>$fieldid, 'userid'=>$userid))) {
ud.userid = ?", array($fieldid, $userid))) {
return $record->data; return $record->data;
} }
} else { } else {
if ($user = $DB->get_record('user', array('id' => $userid), $fieldid)) { return $DB->get_field('user', $fieldid, array('id'=>$userid), MUST_EXIST);
return $user->$fieldid;
}
} }
// If it reaches here, then no matches found // If it reaches here, then no matches found
return false; return false;

View file

@ -3581,6 +3581,12 @@ function get_user_field_name($field) {
// Some fields have language strings which are not the same as field name // Some fields have language strings which are not the same as field name
switch ($field) { switch ($field) {
case 'phone1' : return get_string('phone'); case 'phone1' : return get_string('phone');
case 'url' : return get_string('webpage');
case 'icq' : return get_string('icqnumber');
case 'skype' : return get_string('skypeid');
case 'aim' : return get_string('aimid');
case 'yahoo' : return get_string('yahooid');
case 'msn' : return get_string('msnid');
} }
// Otherwise just use the same lang string // Otherwise just use the same lang string
return get_string($field); return get_string($field);