/** * Helper function for creating a Moodle user profile field * * @param string $name Profile field shortname * @param string $datatype Profile field data type * @param int $categoryid Profile field category id * @return int The id of the created profile field */ private function create_profile_field($name, $datatype, $categoryid, $contextlevelname = 'user') { global $CFG; require_once $CFG->dirroot . '/local/eliscore/lib/data/customfield.class.php'; $file = get_plugin_directory('dhimport', 'version1elis') . '/lib.php'; require_once $file; $field = new field(array('categoryid' => $categoryid, 'shortname' => $name, 'name' => $name)); $field->save(); // Field contextlevel. $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevelname); $fieldcontextlevel = new field_contextlevel(array('fieldid' => $field->id, 'contextlevel' => $contextlevel)); $fieldcontextlevel->save(); return $field->id; }
/** * Test the migrate_contextlevels function. */ public function test_migrate_contextlevels() { global $DB; // Setup. $ctxoldnewmap = array(1001 => \local_eliscore\context\helper::get_level_from_name('curriculum'), 1002 => \local_eliscore\context\helper::get_level_from_name('track'), 1003 => \local_eliscore\context\helper::get_level_from_name('course'), 1004 => \local_eliscore\context\helper::get_level_from_name('class'), 1005 => \local_eliscore\context\helper::get_level_from_name('user'), 1006 => \local_eliscore\context\helper::get_level_from_name('cluster')); $createdrecs = array(); foreach ($ctxoldnewmap as $oldlevel => $newlevel) { $context = new \stdClass(); $context->contextlevel = $oldlevel; $context->instanceid = '1' . $oldlevel; $context->path = '/2/' . $oldlevel; $context->depth = 2; $context->id = $DB->insert_record('context', $context); $createdrecs['context'][$oldlevel] = $context->id; $fieldclevel = new \stdClass(); $fieldclevel->fieldid = '2' . $oldlevel; $fieldclevel->contextlevel = $oldlevel; $fieldclevel->id = $DB->insert_record('local_eliscore_field_clevels', $fieldclevel); $createdrecs['local_eliscore_field_clevels'][$oldlevel] = $fieldclevel->id; $catctx = new \stdClass(); $catctx->categoryid = '3' . $oldlevel; $catctx->contextlevel = $oldlevel; $catctx->id = $DB->insert_record('local_eliscore_fld_cat_ctx', $catctx); $createdrecs['local_eliscore_fld_cat_ctx'][$oldlevel] = $catctx->id; $rolectx = new \stdClass(); $rolectx->roleid = '3' . $oldlevel; $rolectx->contextlevel = $oldlevel; $rolectx->id = $DB->insert_record('role_context_levels', $rolectx); $createdrecs['role_context_levels'][$oldlevel] = $rolectx->id; } // Migrate. $migrator = new \local_elisprogram\install\migration\elis26(); $migrator->migrate_context_levels(); // Check records. foreach ($createdrecs as $table => $recs) { foreach ($recs as $oldlevel => $recid) { $newlevel = $ctxoldnewmap[$oldlevel]; $rec = $DB->get_record($table, array('id' => $recid)); $this->assertEquals($newlevel, $rec->contextlevel); } } }
public function validation($data, $files) { global $DB; $errors = array(); $level = required_param('level', PARAM_ACTION); $ctxlvl = \local_eliscore\context\helper::get_level_from_name($level); if (!empty($ctxlvl)) { $sql = 'SELECT cat.id FROM {local_eliscore_field_cats} cat JOIN {local_eliscore_fld_cat_ctx} ctx ON cat.id = ctx.categoryid WHERE ctx.contextlevel = ? AND cat.name=?'; $params = array($ctxlvl, $data['name']); $existing_catname = $DB->get_recordset_sql($sql, $params); if ($existing_catname->valid() === true) { $a = new stdClass(); $a->tablename = 'local_eliscore_field_cats'; $a->fields = 'name'; $errors['name'] = get_string('data_object_validation_unique', 'local_eliscore', $a); } unset($existing_catname); } return $errors; }
/** * Migrate context levels. */ public function migrate_context_levels() { global $DB; // Migrate old custom context levels. $ctxoldnewmap = array(1001 => \local_eliscore\context\helper::get_level_from_name('curriculum'), 1002 => \local_eliscore\context\helper::get_level_from_name('track'), 1003 => \local_eliscore\context\helper::get_level_from_name('course'), 1004 => \local_eliscore\context\helper::get_level_from_name('class'), 1005 => \local_eliscore\context\helper::get_level_from_name('user'), 1006 => \local_eliscore\context\helper::get_level_from_name('cluster')); foreach ($ctxoldnewmap as $oldctxlevel => $newctxlevel) { // Update context table. $sql = 'UPDATE {context} SET contextlevel = ? WHERE contextlevel = ?'; $params = array($newctxlevel, $oldctxlevel); $DB->execute($sql, $params); // Update role context levels. $sql = 'UPDATE {role_context_levels} SET contextlevel = ? WHERE contextlevel = ?'; $params = array($newctxlevel, $oldctxlevel); $DB->execute($sql, $params); // Update custom field context levels. $sql = 'UPDATE {local_eliscore_field_clevels} SET contextlevel = ? WHERE contextlevel = ?'; $params = array($newctxlevel, $oldctxlevel); $DB->execute($sql, $params); // Update custom field category context levels. $sql = 'UPDATE {local_eliscore_fld_cat_ctx} SET contextlevel = ? WHERE contextlevel = ?'; $params = array($newctxlevel, $oldctxlevel); $DB->execute($sql, $params); } }
/** * Displays the portion of the field editing form specific to a context level * * @param string $contextlevel_name The description of the context level, such * as 'course' or 'class' * @param string $field_header The display string used for the header above * the field value entry elements * @param string $button_text Text to display on the add button * @uses $CFG * @uses $DB */ private function display_for_context($contextlevel_name, $field_header, $button_text) { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/contexts.php'; $fields = field::get_for_context_level($contextlevel_name)->to_array(); $fields = $fields ? $fields : array(); // only retrieve fields for the specified context level $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevel_name); $questions = $DB->get_records('block_courserequest_fields', array('contextlevel' => $contextlevel)); print '<fieldset class="hidden">'; if (!empty($questions)) { print '<table cellpadding="2">'; print '<tr align="right">'; // print '<th><span style="margin-right:10px;">'.get_string('name_on_form', 'block_courserequest').'</span></th>'; print '<th><span style="margin-right:10px;">' . get_string('existing_fields', 'block_courserequest') . '</span></th>'; print '<th><span style="margin-right:10px;">' . $field_header . '</span></th>'; print '</tr>'; foreach ($questions as $question) { print '<tr>'; if ($question->fieldid) { $field = new field($question->fieldid); try { $fieldname = $field->name; } catch (dml_missing_record_exception $ex) { continue; // ELIS-4014: custom field deleted! } } else { $fieldname = 'select a field'; } // print "<td><input type="text" name=\"custom_name[]\" value=\"$value\" /></td>"; print "<td>{$fieldname}</td>"; print "<td><select name=\"field[{$question->id}]\" />"; // print '<option value="none">none</option>'; foreach ($fields as $f) { if ($f->id == $question->fieldid) { print '<option value="' . $f->id . '" selected="true">' . $f->name . '</option>'; $selected = true; } else { print '<option value="' . $f->id . '">' . $f->name . '</option>'; } } print "</select></td>"; print "<td><input type=\"submit\" name=\"delete[{$question->id}]\" value=\"" . get_string('delete', 'block_courserequest') . '" /></td>'; print '</tr>'; } print '</table>'; } $add_element_name = "add_field_{$contextlevel}"; print '<div style="margin-top:5px"><input type="submit" name="' . $add_element_name . '" value="' . $button_text . '" /></div>'; print '</fieldset>'; }
/** * Determines if standard and custom curriculum fields are included in the * details report. This function is needed in order to resolve the issues * described in EOPSS-70 * * @param array array of fields included with the report * @uses $DB * @return boolean - false if no custom curriculum fields are included */ protected function custom_fields_included($filters) { global $DB; $levels = array(); $no_custom_fields = true; foreach (array('curriculum', 'course', 'class') as $entity) { $level = \local_eliscore\context\helper::get_level_from_name($entity); if ($level) { $levels[] = $level; $no_custom_fields = false; } else { error_log("UCCDR::custom_fields_included(); NO custom field context level for '{$entity}'!"); } } if ($no_custom_fields) { return false; } foreach ($filters as $key => $filter) { foreach ($filter['value'] as $field_alias => $filter_value) { // If the filter_value is 0 then we don't need to worry about it if ($filter_value) { if (false !== ($pos = strpos($field_alias, '_'))) { // Determine whether this field has a 'custom' prefix $custom_field_name = substr($field_alias, 0, $pos); // Get the custom field id if (0 == strcmp($custom_field_name, 'custom')) { // Only get the last part of the field name as it contains the custom field id $custom_field_id = substr($field_alias, $pos + 1); //TBD: Check the custom field if ($DB->record_exists_select(field_contextlevel::TABLE, "fieldid = {$custom_field_id} AND contextlevel IN (" . implode(', ', $levels) . ')')) { //error_log("UCCDR::custom_fields_included(): fieldid {$custom_field_id} exists for an ELIS contextlevel!"); return true; } } else { if (0 == strcmp($field_alias, 'cur_name')) { return true; } } } } } } return false; }
/** * Returns an array of report columns related to the specified CM custom fields * @param array $cols List of columns/fields we are displaying * @param string $type The custom field type: curriculum, course, class ... * @return array Collection of appropriate table report columns */ function get_custom_field_columns($cols, $type) { global $DB; $columns = array(); if (!empty($cols)) { foreach ($cols as $field => $active) { if ($active && substr($field, 0, 7) == 'custom_') { $fieldid = substr($field, 7); //store the context level that's represented by this field $level = \local_eliscore\context\helper::get_level_from_name($type); if (!$DB->record_exists(field_contextlevel::TABLE, array('fieldid' => $fieldid, 'contextlevel' => $level))) { continue; } $this->_fielddatacontexts[$fieldid] = $type; $this->_customfieldids[] = $fieldid; $name = $DB->get_field(field::TABLE, 'name', array('id' => $fieldid)); $column = new table_report_column('customfielddata_' . $fieldid . '.data AS customfielddata_' . $fieldid, $name, 'field_' . $fieldid); $columns[] = $column; //store custom field information we need later $field = new field($fieldid); if (($default_value = $field->get_default()) !== false) { $this->_defaultfieldvalues[$fieldid] = $default_value; } //store the data type $this->_fielddatatypes[$fieldid] = $field->datatype; // ELIS-5862/ELIS-7409: keep track of datetime fields if (isset($field->owners['manual']) && ($manual = new field_owner($field->owners['manual'])) && $manual->param_control == 'datetime') { $this->_datetimefields[$fieldid] = !empty($manual->param_inctime); } } } } return $columns; }
/** * Create the test custom profile field and owner * * @param string $contextlevelname The name of the custom context level to create the field at * @param string $name PM custom field shortname * @param string $datatype The string identifier of the data type to use * @param string $uitype The string identifier of the UI / control type to use * @param int $categoryid PM custom field category id * @param string $options Extra parameter, used for select options * @param string $defaultdata Default value. * * @return int The id of the created field */ private function create_test_field($contextlevelname = 'user', $name = 'testfieldname', $datatype, $uitype, $categoryid, $options = null, $defaultdata = null) { global $CFG; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elis::lib('data/customfield.class.php'); // Category contextlevel. $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevelname); $fieldcategorycontextlevel = new field_category_contextlevel(array('categoryid' => $categoryid, 'contextlevel' => $contextlevel)); $fieldcategorycontextlevel->save(); // Field. $field = new field(array('shortname' => 'testfieldshortname', 'name' => $name, 'categoryid' => $categoryid, 'datatype' => $datatype)); $field->save(); // Field_data if a default value needs to be set. if ($defaultdata !== null) { $classname = 'field_data_' . $datatype; $fielddata = new $classname(array('fieldid' => $field->id, 'data' => $defaultdata)); $fielddata->save(); } // Field contextlevel. $fieldcontextlevel = new field_contextlevel(array('fieldid' => $field->id, 'contextlevel' => $contextlevel)); $fieldcontextlevel->save(); // Field owner. $ownerdata = array('control' => $uitype); if ($options !== null) { // Set options. $options = is_array($options) ? implode("\n", $options) : $options; $ownerdata['options'] = $options; } field_owner::ensure_field_owner_exists($field, 'manual', $ownerdata); return $field; }
function validate_custom_fields($data, $eliscontext) { $errors = array(); $contextlevel = \local_eliscore\context\helper::get_level_from_name($eliscontext); $fields = field::get_for_context_level($contextlevel); $fields = $fields ? $fields : array(); if (!empty($data['id'])) { $contextclass = \local_eliscore\context\helper::get_class_for_level($contextlevel); $context = $contextclass::instance($data['id']); $contextid = $context->id; } else { $contextid = 0; } foreach ($fields as $field) { $field = new field($field); $key = "field_{$field->shortname}"; if ($errstr = manual_field_validation(isset($data[$key]) ? $data[$key] : null, $field, $contextid)) { $errors[$key] = $errstr; } //error_log("cmform.class.php::validation(): contextid = {$contextid}, data[{$key}] = {$data[$key]}, errors[$key] = {$errstr}"); } return $errors; }
/** * Obtains the listing of fields that are available for the specified * entity type * * @param string $entitytype The type of entity */ function get_available_fields($entitytype) { global $CFG, $DB; require_once $CFG->dirroot . '/local/eliscore/lib/setup.php'; require_once $CFG->dirroot . '/local/elisprogram/accesslib.php'; require_once elis::lib('data/customfield.class.php'); if ($this->plugin_supports($entitytype) !== false) { $attribute = 'available_fields_' . $entitytype; $result = array_merge(array('action'), static::${$attribute}); // enrolments do not have custom fields if ($entitytype == 'enrolment') { return $result; } if (!is_numeric($entitytype)) { $entitytype = \local_eliscore\context\helper::get_level_from_name($entitytype); } // courses get all custom fields except user custom fields if ($entitytype == CONTEXT_ELIS_COURSE) { $contextsql = "ctx.contextlevel != " . CONTEXT_ELIS_USER; } else { if ($entitytype == CONTEXT_ELIS_USER) { $contextsql = "ctx.contextlevel = {$entitytype}"; } else { // unsupported entity type return $result; } } //add ELIS custom fields - get by context $sql = "SELECT field.shortname\n FROM {" . field::TABLE . "} field\n JOIN {" . field_contextlevel::TABLE . "} ctx ON ctx.fieldid = field.id AND " . $contextsql; if ($fields = $DB->get_recordset_sql($sql)) { foreach ($fields as $field) { $result[] = $field->shortname; } } // make sure there are no duplicate field shortnames returned return array_unique($result); } else { return false; } }
/** * Return a boolean to indicate whether or not this filter is displayed * depending upon whether any custom fields are found for this user * @param string $field_type type of custom field to check * @return boolean true if the filter is to show */ function check_for_custom_fields($field_type) { // Get custom course fields by context level $context = \local_eliscore\context\helper::get_level_from_name($field_type); $fields = field::get_for_context_level($context); $fields = $fields ? $fields : array(); $testfields = array(); foreach ($fields as $field) { //make sure the current user can access this field in at least one //course context if (!$this->field_accessible($field)) { continue; } return true; } return false; }
/** * Validate multi-valued custom field data update removes previous selection * * @dataProvider entity_type_provider * @param string $entitytype The type of entity we are running the import for * @param array $record The inport record to process * @param string $contextlevelname The name used to refer to the appropriate context level * @param string $fileidentifier The entity type represented by the input file * @param mixed $parententitytype The parent entity type, or null if none * @param mixed $parentrecord The parent data record, or null if none * @param mixed $parentreffield The field used to refer to the parent element, or null if none * @param mixed $ipparentreffield The field used to refer to the parent element in IP, or null if none */ public function test_multivalue_field_data_update_overwrites_previous_selection($entitytype, $record, $contextlevelname, $fileidentifier, $parententitytype = null, $parentrecord = null, $parentreffield = null, $ipparentreffield = null) { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elis::lib('data/customfield.class.php'); require_once elispm::lib('data/' . $entitytype . '.class.php'); // Set up the custom field, category, context association, and owner. $fieldid = $this->create_test_field($contextlevelname, 'int', 'menu', true, array('1', '2', '3', '4'), null, null); // Create parent entity if needed. if ($parentid = $this->create_parent_entity($parententitytype, $parentrecord, $parentreffield)) { $record[$parentreffield] = $parentid; } // Persist the entity. $entity = new $entitytype(); $entity->set_from_data((object) array_merge($record, array('field_testfieldshortname' => array('4')))); $entity->save(); $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevelname); $contextlevel = \local_eliscore\context\helper::get_class_for_level($contextlevel); $instance = $contextlevel::instance($entity->id); // Validate setup. $this->assertEquals(1, $DB->count_records(field_data_int::TABLE)); $this->assertTrue($DB->record_exists(field_data_int::TABLE, array('fieldid' => $fieldid, 'contextid' => $instance->id, 'data' => '4'))); $record['action'] = 'update'; $record['testfieldshortname'] = '1/2/3'; // Run the entity update action. $importplugin = rlip_dataplugin_factory::factory('dhimport_version1elis'); $importplugin->fslogger = new silent_fslogger(null); $importplugin->process_record($fileidentifier, (object) $record, 'bogus'); // Validation. $this->assert_field_values($contextlevelname, $entitytype::TABLE, field_data_int::TABLE, $fieldid, array('1', '2', '3')); }
/** * Check whether a field has view or edit capability on either Moodle or ELIS context(s). * * @param object $field the custom field we are viewing / editing * @param object $context Moodle context * @param string $contexteditcap The edit capability to check if the field owner * is set up to use the "edit this context" option for editing * @param string $contextviewcap The view capability to check if the field owner * is set up to use the "view this context" option for viewing * @param string $entity optional entity/context name * @param int $entityid The id of the entity. Required only if an entity is passed. * @return int MANUAL_FIELD_NO_VIEW_OR_EDIT (-1) if not viewable or editable * MANUAL_FIELD_VIEWABLE (0) if viewable * MANUAL_FIELD_EDITABLE (1) if editable (which implies viewable) */ function manual_field_is_view_or_editable($field, $context, $contexteditcap = NULL, $contextviewcap = NULL, $entity = 'system', $entityid = 0) { global $CFG, $USER; $canview = 0; $canedit = 0; if (!isset($field->owners['manual'])) { return MANUAL_FIELD_NO_VIEW_OR_EDIT; } $manual = new field_owner($field->owners['manual']); // Determine which exact capabilities we are checking $editcap = $manual->param_edit_capability; if ($editcap == '') { // Context-specific capability $editcap = $contexteditcap; } $viewcap = $manual->param_view_capability; if ($viewcap == '') { // Context-specific capability $viewcap = $contextviewcap; } if ($editcap == NULL || $viewcap == NULL) { // Capabilities for editing or viewing the context were not correctly specified return MANUAL_FIELD_NO_VIEW_OR_EDIT; } // Check if ELIS PM exists and if the given entity exists within PM if (file_exists($CFG->dirroot . '/local/elisprogram/lib/setup.php')) { if (empty($entityid)) { if ($entity !== 'system') { // Validate entity. \local_eliscore\context\helper::get_level_from_name($entity); $contextset = pm_context_set::for_user_with_capability($entity, $editcap, $USER->id); $canedit = !$contextset->is_empty(); $contextset = pm_context_set::for_user_with_capability($entity, $viewcap, $USER->id); $canview = !$contextset->is_empty(); } } else { // Validate entity. \local_eliscore\context\helper::get_level_from_name($entity); // Check ELIS contexts for the user's capability in an entity. $contextset = pm_context_set::for_user_with_capability($entity, $editcap, $USER->id); $canedit = $contextset->context_allowed($entityid, $entity); $contextset = pm_context_set::for_user_with_capability($entity, $viewcap, $USER->id); $canview = $contextset->context_allowed($entityid, $entity); } } if ($editcap == 'disabled' || !$canedit && !has_capability($editcap, $context)) { if (!$canview && !has_capability($viewcap, $context)) { // Do not have view or edit permissions return MANUAL_FIELD_NO_VIEW_OR_EDIT; } return MANUAL_FIELD_VIEWABLE; } return MANUAL_FIELD_EDITABLE; }
/** * Removes custom fields from the current form for a particular context level * * @param string $contextlevel_name Name of the context level for which we are removing fields * @uses $DB */ function remove_form_custom_fields($contextlevel_name) { global $DB; $mform =& $this->_form; $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevel_name); $fields = $DB->get_records('block_courserequest_fields', array('contextlevel' => $contextlevel)); $fields = $fields ? $fields : array(); foreach ($fields as $reqfield) { $field = new field($reqfield->fieldid); if (!$field->id || !isset($field->owners['manual'])) { // skip nonexistent fields, or fields without manual editing continue; } $manual = new field_owner($field->owners['manual']); if (empty($manual->param_edit_capability)) { // remove the field from the form $mform->removeElement("field_{$field->shortname}"); $mform->removeElement("fieldisrequired_field_{$field->shortname}_{$contextlevel_name}"); } } }
/** * Adds custom field data to a CM entity based on the data defined for * a particular class request (in-place) * * @param int $requestid The database record id of the class request * @param string $contextlevel_name Name of the context level we are adding fields for, * such as 'course' or 'class' * @param object $entity The CM entity to update with custom field data * @uses $CFG * @uses $DB */ function add_custom_fields($requestid, $contextlevel_name, &$entity) { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/contexts.php'; $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevel_name); $select = "requestid = ? AND contextlevel = ?"; // Add any custom field data from the request to this class now. if ($rs = $DB->get_recordset_select('block_courserequest_data', $select, array($requestid, $contextlevel))) { foreach ($rs as $fielddata) { // ^WAS: while ($fielddata = rs_fetch_next_record($rs)) { $field = new field($fielddata->fieldid); // Check for multiple values and unserialize if ($fielddata->multiple == '1') { $entity->{"field_{$field->shortname}"} = unserialize($fielddata->data); $entity->{"field_{$field->shortname}"}->multivalued = true; } else { $entity->{"field_{$field->shortname}"} = $fielddata->data; } } $rs->close(); } }
/** * Make field list * * @param array $groups A two dimensional array of groups => choices => values */ function make_field_list($groups) { // Force $groups to be an associative array foreach ($groups as $key => $choices) { if (!$this->is_assoc_array($choices)) { $groups[$key] = array_fill_keys($choices, ''); } } if (get_class($this) != 'generalized_filter_userprofilematch') { // UPM filter uses Moodle profile, we should obey 'extra' option // Generate a list of custom fields foreach ($this->sections as $group => $section) { $ctxtlvl = \local_eliscore\context\helper::get_level_from_name($section['name']); $this->sections[$group]['contextlevel'] = $ctxtlvl; // Add custom fields to array $extrafields = field::get_for_context_level($ctxtlvl); $this->get_custom_fields($group, $extrafields); } } // Generate the standard fields foreach ($groups as $group => $choices) { $custom_fields = isset($this->_fields[$group]) ? $this->_fields[$group] : array(); $this->_fields[$group] = array(); foreach ($choices as $name => $alias) { $label = $name; if (!empty($alias)) { $label = get_string($alias, $this->languagefile); } else { if (isset($this->labels[$group]) && array_key_exists($name, $this->labels[$group])) { $label = get_string($this->labels[$group][$name], $this->languagefile); } else { foreach ($this->sections as $section) { if (array_key_exists($name, $section['custom'])) { $label = $section['custom'][$name]; } } } } $this->_fields[$group][$name] = $label; } if (!empty($this->sections[$group]['custom'])) { $this->_fields[$group] = array_merge($this->_fields[$group], $this->sections[$group]['custom']); } if (!empty($custom_fields)) { $this->_fields[$group] = array_merge($this->_fields[$group], $custom_fields); } } }
/** * Fetch the contexts where the user has a given capability. This only works * with the CM context levels. * * Assumes that the user does not have "too many" role assignments. Assumes * the user has no "prevents"/"prohibits" roles. */ static function for_user_with_capability($contextlevel, $capability, $userid = null, $doanything = true) { global $USER, $DB; static $pm_context_parents = array('track' => array('curriculum'), 'course' => array('curriculum'), 'class' => array('course', 'track'), 'user' => array('cluster')); if ($userid === null) { $userid = $USER->id; } $obj = new pm_context_set(); $obj->contextlevel = $contextlevel; // if the user has the capability at the system level (or has the // manage master capability), we can stop here if (has_capability($capability, context_system::instance(), $userid, $doanything) || has_capability('local/elisprogram:manage', context_system::instance(), $userid, $doanything)) { $obj->contexts = array('system' => 1); return $obj; } $contexts = array($contextlevel => array()); // find all contexts at the given context level where the user has a direct // role assignment $ctxlevel = \local_eliscore\context\helper::get_level_from_name($contextlevel); $ctxclass = \local_eliscore\context\helper::get_class_for_level($ctxlevel); $sql = "SELECT c.id, c.instanceid\n FROM {role_assignments} ra\n JOIN {context} c ON ra.contextid = c.id\n WHERE ra.userid = {$userid}\n AND c.contextlevel = " . $ctxlevel; $possiblecontexts = $DB->get_recordset_sql($sql); foreach ($possiblecontexts as $c) { $context = $ctxclass::instance($c->instanceid); if (has_capability($capability, $context, $userid, $doanything)) { $contexts[$contextlevel][] = $context->__get('instanceid'); } } if (empty($contexts[$contextlevel])) { unset($contexts[$contextlevel]); } // look in the parent contexts if (isset($pm_context_parents[$contextlevel])) { foreach ($pm_context_parents[$contextlevel] as $parentlevel) { $parent = pm_context_set::for_user_with_capability($parentlevel, $capability, $userid, $doanything); $contexts = array_merge($contexts, $parent->contexts); } } $obj->contexts = $contexts; return $obj; }
/** * Constructor * * @param string $uniqueid Unique prefix for filters * @param string $label Filter label * @param array $options Filter options (see above) * @return array The sub-filters * @uses $PAGE */ function generalized_filter_curriculumclass($uniqueid, $label, $options = array()) { global $PAGE; parent::__construct($uniqueid, $label, $options); $this->_fields = array(); if (empty($options['help'])) { $options['help'] = array(); } // Get table aliases if (empty($options['tables'])) { $options['tables'] = array(); } $allfields = array(); foreach ($this->labels as $group => $labels) { foreach ($labels as $key => $val) { $this->record_short_field_name($group . '-' . $key); } } // Check for & assign table aliases foreach ($this->tables as $group => $tables) { if (!array_key_exists($group, $options['tables'])) { continue; } foreach ($tables as $key => $val) { if (!empty($options['tables'][$group][$key])) { // use defaults table aliases if not specified $this->tables[$group][$key] = $options['tables'][$group][$key]; } } } foreach ($this->sections as $group => $section) { $ctxtlvl = \local_eliscore\context\helper::get_level_from_name($section['name']); $this->sections[$group]['contextlevel'] = $ctxtlvl; // Add custom fields to array $extrafields = field::get_for_context_level($ctxtlvl); $this->get_custom_fields($group, $extrafields); } // Force $options['choices'] to be an associative array foreach ($options['choices'] as $key => $choices) { if (!$this->is_assoc_array($choices)) { $options['choices'][$key] = array_fill_keys($choices, ''); } } foreach ($options['choices'] as $group => $choices) { $allfields[$group] = array(); foreach ($choices as $name => $alias) { $label = $name; if (!empty($alias) && get_string_manager()->string_exists($alias, $this->languagefile)) { $label = get_string($alias, $this->languagefile); } else { if (array_key_exists($name, $this->defaultlabels[$group]) && get_string_manager()->string_exists($this->defaultlabels[$group][$name], $this->languagefile)) { $label = get_string($this->defaultlabels[$group][$name], $this->languagefile); } else { foreach ($this->sections as $section) { if (array_key_exists($name, $section['custom'])) { $label = $section['custom'][$name]; } } } } $allfields[$group][$name] = $label; } if (!empty($options['extra']) && !empty($this->sections[$group]['custom'])) { $allfields[$group] = array_merge($allfields[$group], $this->sections[$group]['custom']); } } foreach ($allfields as $group => $fields) { $this->_filters[$group] = array(); foreach ($fields as $name => $label) { // must setup select choices for specific fields $myoptions = $this->make_filter_options($group, $name, $options['help'], $options['tables']); if (!is_array($myoptions)) { continue; } $filterid = $this->_uniqueid . $group . '-' . substr($name, 0, MAX_FILTER_SUFFIX_LEN); $ftype = (string) $this->fieldtofiltermap[$group][$name]; $advanced = !empty($options['advanced'][$group]) && in_array($name, $options['advanced'][$group]) || !empty($options['notadvanced'][$group]) && !in_array($name, $options['notadvanced'][$group]); $this->_filters[$group][$name] = new generalized_filter_entry($filterid, $myoptions['talias'], $myoptions['dbfield'], $label, $advanced, $ftype, $myoptions); } } }
function display_editfield() { global $CFG, $DB; $level = $this->required_param('level', PARAM_ACTION); $ctxlvl = \local_eliscore\context\helper::get_level_from_name($level); if (!$ctxlvl) { print_error('invalid_context_level', 'local_elisprogram'); } $id = $this->optional_param('id', NULL, PARAM_INT); require_once elispm::file('form/customfieldform.class.php'); $tmppage = new customfieldpage(array('level' => $level, 'action' => 'editfield'), $this); $form = new customfieldform($tmppage->url, array('id' => $id, 'level' => $level, 'from' => optional_param('from', '', PARAM_CLEAN))); if ($form->is_cancelled()) { $tmppage = new customfieldpage(array('level' => $level)); redirect($tmppage->url, get_string('edit_cancelled', 'local_elisprogram')); } else { if ($data = $form->get_data()) { $src = !empty($data->manual_field_options_source) ? $data->manual_field_options_source : ''; // ELIS-8066: strip CRs "\r" from menu options & default data (below) if (!empty($data->manual_field_options)) { $data->manual_field_options = str_replace("\r", '', $data->manual_field_options); } switch ($data->manual_field_control) { case 'checkbox': if (!$data->multivalued && !empty($src)) { $elem = "defaultdata_radio_{$src}"; $data->defaultdata = isset($data->{$elem}) ? $data->{$elem} : ''; // radio buttons unset by default // error_log("/local/elisprogram/customfieldpage.class.php:: defaultdata->{$elem} = {$data->defaultdata}"); } else { if (!$data->multivalued && !empty($data->manual_field_options)) { $data->defaultdata = str_replace("\r", '', $data->defaultdata_radio); } else { $data->defaultdata = $data->defaultdata_checkbox; } } break; case 'menu': $elem = !empty($src) ? "defaultdata_menu_{$src}" : "defaultdata_menu"; $data->defaultdata = $data->{$elem}; if (empty($src)) { $data->defaultdata = str_replace("\r", '', $data->defaultdata); } break; case 'datetime': $data->defaultdata = $data->defaultdata_datetime; break; default: $data->defaultdata = $data->defaultdata_text; break; } $field = new field($data); if ($id) { $field->id = $id; $field->save(); } else { $field->save(); // assume each field only belongs to one context level (for now) $fieldcontext = new field_contextlevel(); $fieldcontext->fieldid = $field->id; $fieldcontext->contextlevel = $ctxlvl; $fieldcontext->save(); } //don't use !empty here because we might be storing a 0 or similar value if ($data->defaultdata != '') { // save the default value $defaultdata = $data->defaultdata; if ($field->multivalued && is_string($defaultdata)) { // parse as a CSV string // until we can use str_getcsv from PHP 5.3... $temp = fopen("php://memory", "rw"); fwrite($temp, $defaultdata); rewind($temp); $defaultdata = fgetcsv($temp); fclose($temp); } else { if (!$field->multivalued && is_array($defaultdata)) { foreach ($defaultdata as $val) { $defaultdata = $val; break; } } } field_data::set_for_context_and_field(NULL, $field, $defaultdata); } else { if ($field->multivalued) { field_data::set_for_context_and_field(NULL, $field, array()); } else { field_data::set_for_context_and_field(NULL, $field, NULL); } } $plugins = core_component::get_plugin_list('elisfields'); foreach ($plugins as $plugin => $dir) { if (is_readable($CFG->dirroot . '/local/eliscore/fields/' . $plugin . '/custom_fields.php')) { require_once elis::plugin_file('elisfields_' . $plugin, 'custom_fields.php'); if (function_exists("{$plugin}_field_save_form_data")) { call_user_func("{$plugin}_field_save_form_data", $form, $field, $data); } } } $tmppage = new customfieldpage(array('level' => $level)); redirect($tmppage->url, get_string('field_saved', 'local_elisprogram', $field)); } else { if (!empty($id)) { if ($this->optional_param('from', NULL, PARAM_CLEAN) == 'moodle' && $level == 'user') { $moodlefield = $DB->get_record('user_info_field', array('id' => $id)); if (!$moodlefield) { print_error('invalid_field_id', 'local_elisprogram'); } unset($moodlefield->id); $data = $moodlefield; $data_array = (array) $moodlefield; $data_array['datatype'] = 'text'; $data_array['manual_field_control'] = $moodlefield->datatype; switch ($moodlefield->datatype) { case field::CHECKBOX: $data_array['datatype'] = 'bool'; break; case field::DATETIME: $data_array['datatype'] = 'datetime'; $data_array['manual_field_startyear'] = $moodlefield->param1; $data_array['manual_field_stopyear'] = $moodlefield->param2; $data_array['manual_field_inctime'] = $moodlefield->param3; break; case field::MENU: $data_array['datatype'] = 'char'; $data_array['manual_field_options'] = $moodlefield->param1; break; case field::TEXTAREA: $data_array['manual_field_columns'] = $moodlefield->param1; $data_array['manual_field_rows'] = $moodlefield->param2; break; case field::TEXT: if ($moodlefield->param3) { $data_array['manual_field_control'] = 'password'; } $data_array['manual_field_columns'] = $moodlefield->param1; $data_array['manual_field_maxlength'] = $moodlefield->param2; break; } } else { $data = new field($id); $data->load(); $manual = new field_owner(!isset($field->owners) || !isset($field->owners['manual']) ? false : $field->owners['manual']); $menu_src = !empty($manual->options_source) ? $manual->options_source : 0; $data_array = $data->to_array(); $field_record = $DB->get_record(field::TABLE, array('id' => $id)); if (!empty($field_record)) { foreach ($field_record as $field_item => $field_value) { $data_array[$field_item] = $field_value; } } $defaultdata = field_data::get_for_context_and_field(NULL, $data); if (!empty($defaultdata)) { if ($data->multivalued) { $values = array(); foreach ($defaultdata as $defdata) { $values[] = $defdata->data; } $defaultdata = $values; } else { foreach ($defaultdata as $defdata) { $defaultdata = $defdata->data; break; } } } $field = new field(); // Format decimal numbers if ($data_array['datatype'] == 'num' && $manual->param_control != 'menu') { $defaultdata = $field->format_number($defaultdata); } if (!is_object($defaultdata)) { $data_array['defaultdata'] = $defaultdata; } $plugins = core_component::get_plugin_list('elisfields'); foreach ($plugins as $plugin => $dir) { if (is_readable($CFG->dirroot . '/local/eliscore/fields/' . $plugin . '/custom_fields.php')) { include_once $CFG->dirroot . '/local/eliscore/fields/' . $plugin . '/custom_fields.php'; if (function_exists("{$plugin}_field_get_form_data")) { $data_array += call_user_func("{$plugin}_field_get_form_data", $form, $data); } } } } if (isset($data_array['defaultdata'])) { // ELIS-6699 -- load the field to determine the data type used, $data may be a field_data_* or field object if (isset($data->fieldid)) { $field->id = $data->fieldid; $field->load(); } else { $field = $data; } $data_array['defaultdata_checkbox'] = !empty($data_array['defaultdata']); // ELIS-6699 -- If this is not a datetime field, then we can't use the default data value as a timestamp $data_array['defaultdata_datetime'] = $field->datatype == 'datetime' ? $data_array['defaultdata'] : time(); $data_array['defaultdata_text'] = strval($data_array['defaultdata']); $data_array[empty($menu_src) ? 'defaultdata_menu' : "defaultdata_menu_{$menu_src}"] = $data_array['defaultdata']; $data_array[empty($menu_src) ? 'defaultdata_radio' : "defaultdata_radio_{$menu_src}"] = $data_array['defaultdata']; } $form->set_data($data_array); } $form->display(); } } }
/** * Convenience function for use by data_object objects * * @param mixed $contextlevel the context level. Either a numeric value, * or the name of the context level from the ELIS Program Manager * @param object $record the data_object to fetch the field values from * @return bool true */ public static function set_for_context_from_datarecord($contextlevel, $record) { if (!is_numeric($contextlevel)) { $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextlevel); if (!$contextlevel) { // context levels not set up -- we must be in initial installation, // so no fields set up return true; } } $ctxclass = \local_eliscore\context\helper::get_class_for_level($contextlevel); $context = $ctxclass::instance($record->id); $fields = field::get_for_context_level($contextlevel); $fields = $fields ? $fields : array(); foreach ($fields as $field) { $fieldname = "field_{$field->shortname}"; if (isset($record->{$fieldname})) { self::set_for_context_and_field($context, $field, $record->{$fieldname}); } } return true; }
/** * Update environments and environment assignments to custom fields and * custom field data (run as a one-off during the elis program upgrade) * * If there are one or more entities (courses, classes) with environments * assigned to them, a new category and custom field is created, specific to the * appropriate context level. Then, that custom field is populated for each entity * that has and environment assigned (custom field is a single-select, where the options * are all the different environments on the site). */ function pm_migrate_environments() { global $DB; require_once elis::lib('data/customfield.class.php'); require_once elispm::lib('data/course.class.php'); require_once elispm::lib('data/pmclass.class.php'); //set up our contextlevel mapping $contextlevels = array(course::TABLE => 'course', pmclass::TABLE => 'class'); //lookup on all tags $environment_lookup = $DB->get_records('local_elisprogram_env', null, '', 'id, name'); foreach ($environment_lookup as $id => $environment) { $environment_lookup[$id] = $environment->name; } //go through each contextlevel and look for tags foreach ($contextlevels as $instancetable => $contextname) { //calculate the context level integer $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextname); //make sure one or more environments are used at the current context level $select = 'environmentid != 0'; if ($DB->record_exists_select($instancetable, $select)) { //used to reference the category name $category = new field_category(array('name' => get_string('misc_category', 'local_elisprogram'))); //make sure our field for storing environments is created $field = new field(array('shortname' => "_19upgrade_{$contextname}_environment", 'name' => get_string('environment', 'local_elisprogram'), 'datatype' => 'char')); $field = field::ensure_field_exists_for_context_level($field, $contextlevel, $category); //determine environment options $options = array(); if ($records = $DB->get_recordset('local_elisprogram_env', null, 'name', 'DISTINCT name')) { foreach ($records as $record) { $options[] = $record->name; } } $options = implode("\n", $options); //set up our field owner field_owner::ensure_field_owner_exists($field, 'manual', array('control' => 'menu', 'options' => $options, 'edit_capability' => '', 'view_capability' => '')); //set up data for all relevant entries $sql = "SELECT id, environmentid\n FROM {{$instancetable}}\n WHERE environmentid != 0"; if ($records = $DB->get_recordset_sql($sql)) { foreach ($records as $record) { $contextlevel = \local_eliscore\context\helper::get_level_from_name($contextname); $contextclass = \local_eliscore\context\helper::get_class_for_level($contextlevel); $context = $contextclass::instance($record->id); $environmentid = $environment_lookup[$record->environmentid]; field_data::set_for_context_and_field($context, $field, $environmentid); } } } } }
function validation($data, $files) { // copied from /user/profile/definelib.php global $CFG, $USER, $DB; $err = array(); $fid = $this->_customdata['id']; //ob_start(); //var_dump($this->defaultdata_menu); //$tmp = ob_get_contents(); //ob_end_clean(); //error_log("customfieldform::validation(); defaultdata_menu = {$tmp}"); if ($this->defaultdata_menu && $data['manual_field_control'] == 'menu' && empty($data['manual_field_options_source'])) { $menu_options = explode("\n", $data['manual_field_options']); array_walk($menu_options, array($this, 'trim_crlf')); $select_options = array(); foreach ($menu_options as $menu_option) { // ELIS-8066: Disallow blank/empty menu options if (empty($menu_option)) { $err['manual_field_options'] = get_string('no_blank_menuoption', 'local_elisprogram'); } $select_options[] = array('text' => $menu_option, 'attr' => array('value' => $menu_option)); } //ob_start(); //var_dump($this->defaultdata_menu->_options); //$tmp = ob_get_contents(); //ob_end_clean(); //error_log("customfieldform::validation(); defaultdata_menu->_options = {$tmp}"); $this->defaultdata_menu->_options = $select_options; } /// Check the shortname was not truncated by cleaning if (empty($data['shortname'])) { $err['shortname'] = get_string('required'); } else { // Check for duplicate shortnames $level = $this->_customdata['level']; $contextlevel = \local_eliscore\context\helper::get_level_from_name($level); if (!$contextlevel) { print_error('invalid_context_level', 'local_elisprogram'); } $editsql = ''; // We are in edit mode if (!empty($fid)) { $editsql = "AND ef.id != {$fid}"; } $sql = "SELECT ef.id\n FROM {" . field::TABLE . "} ef\n INNER JOIN {" . field_contextlevel::TABLE . "} cl ON ef.id = cl.fieldid\n WHERE ef.shortname = ?\n AND cl.contextlevel = ?\n {$editsql}"; $params = array($data['shortname'], $contextlevel); if ($DB->record_exists_sql($sql, $params)) { $err['shortname'] = get_string('profileshortnamenotunique', 'admin'); } } $plugins = core_component::get_plugin_list('elisfields'); foreach ($plugins as $plugin => $dir) { if (is_readable(elis::plugin_file("elisfields_{$plugin}", 'custom_fields.php'))) { include_once elis::plugin_file("elisfields_{$plugin}", 'custom_fields.php'); if (function_exists("{$plugin}_field_edit_form_validation")) { $err += call_user_func("{$plugin}_field_edit_form_validation", $this, $data, $files); } } } /// No further checks necessary as the form class will take care of it return $err; }