From bb6d3d34545c46d6576a81b500ce93f0e18849fa Mon Sep 17 00:00:00 2001 From: skodak Date: Fri, 26 Jan 2007 13:11:06 +0000 Subject: [PATCH] MDL-8096 - refactored and cleanedup custom profiles, user edit form fixes TODO: fix comments and docs --- user/edit_form.php | 10 +- user/editadvanced.php | 53 +- user/editadvanced_form.php | 13 +- user/profile/definelib.php | 471 +++++++++++++++ user/profile/field/menu/define.class.php | 41 ++ user/profile/field/menu/field.class.php | 85 +-- user/profile/field/text/define.class.php | 21 + user/profile/field/text/field.class.php | 22 +- user/profile/index.php | 345 ++++------- user/profile/index_category_form.php | 11 +- user/profile/index_field_form.php | 56 +- user/profile/lib.php | 700 ++++------------------- 12 files changed, 854 insertions(+), 974 deletions(-) create mode 100644 user/profile/definelib.php create mode 100644 user/profile/field/menu/define.class.php create mode 100644 user/profile/field/text/define.class.php diff --git a/user/edit_form.php b/user/edit_form.php index 5f7b79ece7..38c888ebcd 100644 --- a/user/edit_form.php +++ b/user/edit_form.php @@ -29,6 +29,9 @@ class user_edit_form extends moodleform { $mform->removeElement('imagealt'); } + /// Next the customisable profile fields + profile_definition($mform); + $this->add_action_buttons(false, get_string('updatemyprofile')); } @@ -69,7 +72,9 @@ class user_edit_form extends moodleform { } $mform->hardFreeze($freezefields); } - /// TODO: add locking + + /// Next the customisable profile fields + profile_definition_after_data($mform); } @@ -91,6 +96,9 @@ class user_edit_form extends moodleform { $err['email'] = get_string('toomanybounces'); } + /// Next the customisable profile fields + $err += profile_validation($usernew); + if (count($err) == 0){ return true; } else { diff --git a/user/editadvanced.php b/user/editadvanced.php index f6788128f2..e1982df24c 100644 --- a/user/editadvanced.php +++ b/user/editadvanced.php @@ -50,7 +50,9 @@ $user->{'preference_'.$name} = $value; } } - //TODO: Load the custom profile fields + + //Load custom profile fields data + profile_load_data($user); //create form $userform = new user_editadvanced_form(); @@ -70,42 +72,44 @@ $usernew->timemodified = time(); if ($usernew->id == -1) { + //TODO check out that it makes sense to create account with this auth plugin and what to do with the password unset($usernew->id); $usernew->mnethostid = $CFG->mnet_localhost_id; // always local user $usernew->confirmed = 1; + $usernew->password = hash_internal_user_password($usernew->newpassword); if (!$usernew->id = insert_record('user', $usernew)) { error('Error creating user record'); } } else { - if (update_record('user', $usernew)) { - if (method_exists($authplugin, 'user_update')){ - // pass a true $userold here - if (! $authplugin->user_update($user, $userform->get_data(false))) { - // auth update failed, rollback for moodle - update_record('user', addslashes_object($user)); - error('Failed to update user data on external auth: '.$usernew->auth. - '. See the server logs for more details.'); - } - }; - } else { + if (!update_record('user', $usernew)) { error('Error updating user record'); } - } - - //set new password if specified - if (!empty($usernew->newpassword)) { - if ($authplugin->can_change_password()) { - if (method_exists($authplugin, 'user_update_password')){ - if (!$authplugin->user_update_password($user->username, $usernew->newpassword)){ - error('Failed to update password on external auth: ' . $usernew->auth . - '. See the server logs for more details.'); + if (method_exists($authplugin, 'user_update')){ + // pass a true $userold here + if (! $authplugin->user_update($user, $userform->get_data(false))) { + // auth update failed, rollback for moodle + update_record('user', addslashes_object($user)); + error('Failed to update user data on external auth: '.$usernew->auth. + '. See the server logs for more details.'); + } + }; + + //set new password if specified + if (!empty($usernew->newpassword)) { + if ($authplugin->can_change_password()) { + if (method_exists($authplugin, 'user_update_password')){ + if (!$authplugin->user_update_password($user->username, $usernew->newpassword)){ + error('Failed to update password on external auth: ' . $usernew->auth . + '. See the server logs for more details.'); + } + } else { + error('Your external authentication module is misconfigued!'); } - } else { - error('Your external authentication module is misconfigued!'); } } } + //update preferences $ua = (array)$usernew; foreach($ua as $key=>$value) { @@ -137,7 +141,8 @@ forum_tp_delete_read_records($usernew->id); } - //TODO: Save the custom profile fields + // save custom profile fields data + profile_save_data($usernew); if ($user->id == $USER->id) { // Override old $USER session variable diff --git a/user/editadvanced_form.php b/user/editadvanced_form.php index 6350b8b03e..896dc22a6b 100644 --- a/user/editadvanced_form.php +++ b/user/editadvanced_form.php @@ -5,7 +5,7 @@ require_once($CFG->dirroot.'/lib/formslib.php'); class user_editadvanced_form extends moodleform { // Define the form - function definition () { + function definition() { global $USER, $CFG, $COURSE; $mform =& $this->_form; @@ -41,6 +41,9 @@ class user_editadvanced_form extends moodleform { require('edit_form_common.php'); + /// Next the customisable profile fields + profile_definition($mform); + $this->add_action_buttons(false, get_string('updatemyprofile')); } @@ -81,9 +84,12 @@ class user_editadvanced_form extends moodleform { $image_el->setValue(get_string('none')); } } + + /// Next the customisable profile fields + profile_definition_after_data($mform); } - function validation ($usernew) { + function validation($usernew) { global $CFG; $usernew = (object)$usernew; @@ -116,6 +122,9 @@ class user_editadvanced_form extends moodleform { } } + /// Next the customisable profile fields + $err += profile_validation($usernew); + if (count($err) == 0){ return true; } else { diff --git a/user/profile/definelib.php b/user/profile/definelib.php new file mode 100644 index 0000000000..ec208263e4 --- /dev/null +++ b/user/profile/definelib.php @@ -0,0 +1,471 @@ +addElement('header', '_commonsettings', get_string('profilecommonsettings', 'admin')); + $this->define_form_common($form); + + $form->addElement('header', '_specificsettings', get_string('profilespecificsettings', 'admin')); + $this->define_form_specific($form); + } + + /** + * Prints out the form snippet for the part of creating or + * editing a profile field common to all data types + * @param object instance of the moodleform class + */ + function define_form_common(&$form) { + + $strrequired = get_string('required'); + + $form->addElement('text', 'shortname', get_string('profileshortname', 'admin'), 'maxlength="100" size="30"'); + $form->addRule('shortname', $strrequired, 'required', null, 'client'); + $form->setType('shortname', PARAM_ALPHANUM); + + $form->addElement('text', 'name', get_string('profilename', 'admin'), 'size="30"'); + $form->addRule('name', $strrequired, 'required', null, 'client'); + $form->setType('name', PARAM_MULTILANG); + + $form->addElement('htmleditor', 'description', get_string('profiledescription', 'admin')); + $form->setHelpButton('description', array('text', get_string('helptext'))); + $form->setType('description', PARAM_MULTILANG); + + $form->addElement('selectyesno', 'required', get_string('profilerequired', 'admin')); + + $form->addElement('selectyesno', 'locked', get_string('profilelocked', 'admin')); + + $choices = array(); + $choices[PROFILE_VISIBLE_NONE] = get_string('profilevisiblenone', 'admin'); + $choices[PROFILE_VISIBLE_PRIVATE] = get_string('profilevisibleprivate', 'admin'); + $choices[PROFILE_VISIBLE_ALL] = get_string('profilevisibleall', 'admin'); + $form->addElement('select', 'visible', get_string('profilevisible', 'admin'), $choices); + $form->setHelpButton('visible', array('profilevisible', get_string('profilevisible','admin'))); + $form->setDefault('visible', PROFILE_VISIBLE_ALL); + + $choices = profile_list_categories(); + $form->addElement('select', 'categoryid', get_string('profilecategory', 'admin'), $choices); + } + + /** + * Prints out the form snippet for the part of creating or + * editing a profile field specific to the current data type + * @param object instance of the moodleform class + */ + function define_form_specific(&$form) { + /// do nothing - overwrite if necessary + } + + /** + * Validate the data from the add/edit profile field form. + * Generally this method should not be overwritten by child + * classes. + * @param object data from the add/edit profile field form + * @return array associative array of error messages + */ + function define_validate($data) { + + $data = (object)$data; + $err = array(); + + $err += $this->define_validate_common($data); + $err += $this->define_validate_specific($data); + + if (count($err) == 0){ + return true; + } else { + return $err; + } + } + + /** + * Validate the data from the add/edit profile field form + * that is common to all data types. Generally this method + * should not be overwritten by child classes. + * @param object data from the add/edit profile field form + * @return array associative array of error messages + */ + function define_validate_common($data) { + $err = array(); + + /// Check the shortname is unique + if (($field = get_record('user_info_field', 'shortname', $data->shortname)) and ($field->id <> $data->id)) { + //if (record_exists_select('user_info_field', 'shortname='.$data->shortname.' AND id<>'.$data->id)) { + $err['shortname'] = get_string('profileshortnamenotunique', 'admin'); + } + + /// No further checks necessary as the form class will take care of it + + return $err; + } + + /** + * Validate the data from the add/edit profile field form + * that is specific to the current data type + * @param object data from the add/edit profile field form + * @return array associative array of error messages + */ + function define_validate_specific($data) { + /// do nothing - overwrite if necessary + return array(); + } + + /** + * Alter form based on submitted or existing data + * @param object form + */ + function define_after_data(&$mform) { + /// do nothing - overwrite if necessary + } + + /** + * Add a new profile field or save changes to current field + * @param object data from the add/edit profile field form + * @return boolean status of the insert/update record + */ + function define_save($data) { + + $data = $this->define_save_preprocess($data); /// hook for child classes + + $old = get_record('user_info_field', 'id', $data->id); + + /// check to see if the category has changed + if (!$old or $old->categoryid != $data->categoryid) { + $data->sortorder = count_records_select('user_info_field', 'categoryid='.$data->categoryid) + 1; + } + + + if (empty($data->id)) { + unset($data->id); + if (!$data->id = insert_record('user_info_field', $data)) { + error('Error creating new field'); + } + } else { + if (!update_record('user_info_field', $data)) { + error('Error updating field'); + } + } + } + + /** + * Preprocess data from the add/edit profile field form + * before it is saved. This method is a hook for the child + * classes to overwrite. + * @param object data from the add/edit profile field form + * @return object processed data object + */ + function define_save_preprocess($data) { + /// do nothing - overwrite if necessary + return $data; + } + +} + + + +/** + * Reorder the profile fields within a given category starting + * at the field at the given startorder + */ +function profile_reorder_fields() { + if ($categories = get_records_select('user_info_category')) { + $i = 1; + foreach ($categories as $category) { + if ($fields = get_records_select('user_info_field', 'categoryid='.$category->id, 'sortorder ASC')) { + foreach ($fields as $field) { + $f = new object(); + $f->if = $field->id; + $f->sortorder = $i++; + update_record('user_info_field', $f); + } + } + } + } +} + +/** + * Reorder the profile categoriess starting at the category + * at the given startorder + */ +function profile_reorder_categories() { + $i = 1; + if ($categories = get_records_select('user_info_category', '', 'sortorder ASC')) { + foreach ($categories as $cat) { + $c = new object(); + $c->id = $cat->id; + $c->sortorder = $i++; + update_record('user_info_category', $c); + } + } +} + +/** + * Delete a profile category + * @param integer id of the category to be deleted + * @return boolean success of operation + */ +function profile_delete_category($id) { + /// Retrieve the category + if (!$category = get_record('user_info_category', 'id', $id)) { + error('Incorrect category id'); + } + + if (!$categories = get_records_select('user_info_category', '', 'sortorder ASC')) { + error('Error no categories!?!?'); + } + + unset($categories[$category->id]); + + if (!count($categories)) { + return; //we can not delete the last category + } + + /// Does the category contain any fields + if (count_records('user_info_field', 'categoryid', $category->id)) { + if (array_key_exists($category->sortorder-1, $categories)) { + $newcategory = $categories[$category->sortorder-1]; + } else if (array_key_exists($category->sortorder+1, $categories)) { + $newcategory = $categories[$category->sortorder+1]; + } else { + $newcategory = reset($categories); // get first category if sortorder broken + } + + $sortorder = count_records('user_info_field', 'categoryid', $newcategory->id) + 1; + + if ($fields = get_records_select('user_info_field', 'categoryid='.$category->id, 'sortorder ASC')) { + foreach ($fields as $field) { + $f = new object(); + $f->id = $field->id; + $f->sortorder = $sortorder++; + $f->categoryid = $newcategory->id; + update_record('user_info_field', $f); + echo "
";var_dump($f);echo"
"; + } + } + } + + /// Finally we get to delete the category + if (!delete_records('user_info_category', 'id', $category->id)) { + error('Error while deliting category'); + } + profile_reorder_categories(); + return true; +} + + +function profile_delete_field($id) { + + /// Remove any user data associated with this field + if (!delete_records('user_info_data', 'fieldid', $id)) { + error('Error deleting custom field data'); + } + + /// Try to remove the record from the database + delete_records('user_info_field', 'id', $id); + + /// Reorder the remaining fields in the same category + profile_reorder_fields(); +} + +/** + * Change the sortorder of a field + * @param integer id of the field + * @param string direction of move + * @return boolean success of operation + */ +function profile_move_field ($id, $move) { + /// Get the field object + if (!$field = get_record('user_info_field', 'id', $id, '', '', '', '', 'id, sortorder, categoryid')) { + return false; + } + /// Count the number of fields in this category + $fieldcount = count_records_select('user_info_field', 'categoryid='.$field->categoryid); + + /// Calculate the new sortorder + if ( ($move == 'up') and ($field->sortorder > 1)) { + $neworder = $field->sortorder - 1; + } elseif ( ($move == 'down') and ($field->sortorder < $fieldcount)) { + $neworder = $field->sortorder + 1; + } else { + return false; + } + + /// Retrieve the field object that is currently residing in the new position + if ($swapfield = get_record('user_info_field', 'categoryid', $field->categoryid, 'sortorder', $neworder, '', '', 'id, sortorder')) { + + /// Swap the sortorders + $swapfield->sortorder = $field->sortorder; + $field->sortorder = $neworder; + + /// Update the field records + update_record('user_info_field', $field); + update_record('user_info_field', $swapfield); + } + + profile_reorder_fields(); +} + +/** + * Change the sortorder of a category + * @param integer id of the category + * @param string direction of move + * @return boolean success of operation + */ +function profile_move_category ($id, $move) { + /// Get the category object + if (!($category = get_record('user_info_category', 'id', $id, '', '', '', '', 'id, sortorder'))) { + return false; + } + + /// Count the number of categories + $categorycount = count_records('user_info_category'); + + /// Calculate the new sortorder + if ( ($move == 'up') and ($category->sortorder > 1)) { + $neworder = $category->sortorder - 1; + } elseif ( ($move == 'down') and ($category->sortorder < $categorycount)) { + $neworder = $category->sortorder + 1; + } else { + return false; + } + + /// Retrieve the category object that is currently residing in the new position + if ($swapcategory = get_record('user_info_category', 'sortorder', $neworder, '', '', '', '', 'id, sortorder')) { + + /// Swap the sortorders + $swapcategory->sortorder = $category->sortorder; + $category->sortorder = $neworder; + + /// Update the category records + if (update_record('user_info_category', $category) and update_record('user_info_category', $swapcategory)) { + return true; + } + } + + return false; +} + +/** + * Retrieve a list of all the available data types + * @return array a list of the datatypes suitable to use in a select statement + */ +function profile_list_datatypes() { + global $CFG; + + $datatypes = array(); + + if ($dirlist = get_directory_list($CFG->dirroot.'/user/profile/field', '', false, true, false)) { + foreach ($dirlist as $type) { + $datatypes[$type] = get_string('profilefieldtype'.$type, 'admin'); + } + } + return $datatypes; +} + +/** + * Retrieve a list of categories and ids suitable for use in a form + * @return array + */ +function profile_list_categories() { + if (!$categories = get_records_select_menu('user_info_category', '', 'sortorder ASC', 'id, name')) { + $categories = array(); + } + return $categories; +} + + +/// Are we adding or editing a cateogory? +function profile_edit_category($id, $redirect, $adminroot) { + global $CFG; + + require_once('index_category_form.php'); + $categoryform = new category_form(); + + if ($category = get_record('user_info_category', 'id', $id)) { + $categoryform->set_data($category); + } + + if ($categoryform->is_cancelled()) { + redirect($redirect); + } else { + if ($data = $categoryform->get_data()) { + if (empty($data->id)) { + unset($data->id); + $data->sortorder = count_records('user_info_category') + 1; + if (!insert_record('user_info_category', $data, false)) { + error('There was a problem adding the record to the database'); + } + } else { + if (!update_record('user_info_category', $data)) { + error('There was a problem updating the record in the database'); + } + } + profile_reorder_categories(); + redirect($redirect); + + } + + if (empty($id)) { + $strheading = get_string('profilecreatenewcategory', 'admin'); + } else { + $strheading = get_string('profileeditcategory', 'admin', $category->name); + } + + /// Print the page + admin_externalpage_print_header($adminroot); + print_heading($strheading); + $categoryform->display(); + admin_externalpage_print_footer($adminroot); + die; + } + +} + +function profile_edit_field($id, $datatype, $redirect, $adminroot) { + global $CFG; + + if (!$field = get_record('user_info_field', 'id', $id)) { + $field = new object(); + $field->datatype = $datatype; + } + + require_once('index_field_form.php'); + $fieldform = new field_form(null, $field->datatype); + $fieldform->set_data($field); + + if ($fieldform->is_cancelled()) { + redirect($redirect); + + } else { + if ($data = $fieldform->get_data()) { + require_once($CFG->dirroot.'/user/profile/field/'.$datatype.'/define.class.php'); + $newfield = 'profile_define_'.$datatype; + $formfield = new $newfield(); + $formfield->define_save($data); + profile_reorder_fields(); + profile_reorder_categories(); + redirect($redirect); + } + + $datatypes = profile_list_datatypes(); + + if (empty($id)) { + $strheading = get_string('profilecreatenewfield', 'admin', $datatypes[$datatype]); + } else { + $strheading = get_string('profileeditfield', 'admin', $field->name); + } + + /// Print the page + admin_externalpage_print_header($adminroot); + print_heading($strheading); + $fieldform->display(); + admin_externalpage_print_footer($adminroot); + die; + } +} + +?> \ No newline at end of file diff --git a/user/profile/field/menu/define.class.php b/user/profile/field/menu/define.class.php new file mode 100644 index 0000000000..126457a929 --- /dev/null +++ b/user/profile/field/menu/define.class.php @@ -0,0 +1,41 @@ +addElement('textarea', 'param1', get_string('profilemenuoptions', 'admin')); + $form->setType('param1', PARAM_MULTILANG); + + /// Default data + $form->addElement('text', 'defaultdata', get_string('profiledefaultdata', 'admin'), 'size="30"'); + $form->setType('defaultdata', PARAM_MULTILANG); + } + + function define_validate_specific($data) { + $err = array(); + + $data->param1 = str_replace("\r", '', $data->param1); + + /// Check that we have at least 2 options + if (($options = explode("\n", $data->param1)) === false) { + $err['param1'] = get_string('profilemenunooptions', 'admin'); + } elseif (count($options) < 2) { + $err['param1'] = get_string('profilemenutoofewoptions', 'admin'); + + /// Check the default data exists in the options + } elseif (!empty($data->defaultdata) and !in_array($data->defaultdata, $options)) { + $err['defaultdata'] = get_string('profilemenudefaultnotinoptions', 'admin'); + } + return $err; + } + + function define_save_preprocess($data) { + $data->param1 = str_replace("\r", '', $data->param1); + + return $data; + } + +} + +?> \ No newline at end of file diff --git a/user/profile/field/menu/field.class.php b/user/profile/field/menu/field.class.php index 72612ec726..c3b7a014e5 100644 --- a/user/profile/field/menu/field.class.php +++ b/user/profile/field/menu/field.class.php @@ -1,90 +1,31 @@ profile_field_base($fieldid); - function init() { /// Param 1 for menu type is the options - if (empty($this->field->param1)) { - $options = array(); - } else if (($options = explode("\n", $this->field->param1)) === false) { - $options = array(); + $options = explode("\n", $this->field->param1); + $this->options = array(); + foreach($options as $option) { + $this->options[] = format_string($option);//multilang formatting } - $this->options = $options; + } function display_field_add(&$form) { /// Create the form field - $form->addElement('select', $this->fieldname, $this->field->name, $this->options); - $form->setType($this->fieldname, PARAM_INT); + $form->addElement('select', $this->inputname, format_string($this->field->name), $this->options); } /// Override base class method function display_field_default(&$form) { - /// Default data is either what user has already set othewise the default value for the field othewise nothing - if (!($default = get_field('user_info_data', 'data', 'userid', $this->userid, 'fieldid', $this->field->id))) { - $default = (empty($this->field->defaultdata)) ? '' : $this->field->defaultdata; - } - if (($defaultkey = array_search($default, $this->options)) === NULL) { - $defaultkey = 0; - } - $form->setDefault($this->fieldname, $defaultkey); - } - - function set_data_type() { - $this->datatype = 'menu'; - } - - function validate_data($data) { - if ($data >= count($this->options)) { - return get_string('profileinvaliddata', 'admin'); - } else { - return ''; - } - } - - function save_data_preprocess($data) { - - if (!isset($this->options[$data])) { /// validate_data should already have caught this - return ''; - } else { - return $this->options[$data]; - } - } - - function edit_field_specific(&$form) { - /// Param 1 for menu type contains the options - $form->addElement('textarea', 'param1', get_string('profilemenuoptions', 'admin')); - $form->setType('param1', PARAM_MULTILANG); - - /// Default data - $form->addElement('text', 'defaultdata', get_string('profiledefaultdata', 'admin'), 'size="30"'); - $form->setType('defaultdata', PARAM_MULTILANG); - } - - function edit_validate_specific($data) { - $err = array(); - - $data->param1 = str_replace("\r", '', $data->param1); - - /// Check that we have at least 2 options - if (($options = explode("\n", $data->param1)) === false) { - $err['param1'] = get_string('profilemenunooptions', 'admin'); - } elseif (count($options) < 2) { - $err['param1'] = get_string('profilemenutoofewoptions', 'admin'); - - /// Check the default data exists in the options - } elseif (!empty($data->defaultdata) and !in_array($data->defaultdata, $options)) { - $err['defaultdata'] = get_string('profilemenudefaultnotinoptions', 'admin'); - } - return $err; - } - - function edit_save_preprocess($data) { - $data->param1 = str_replace("\r", '', $data->param1); - - return $data; + $defaultkey = (int)array_search($field->defaultdata, $this->options); + $form->setDefault($this->inputname, $defaultkey); } - } ?> diff --git a/user/profile/field/text/define.class.php b/user/profile/field/text/define.class.php new file mode 100644 index 0000000000..4c8c758b35 --- /dev/null +++ b/user/profile/field/text/define.class.php @@ -0,0 +1,21 @@ +addElement('text', 'defaultdata', get_string('profiledefaultdata', 'admin'), 'size="30"'); + $form->setType('defaultdata', PARAM_MULTILANG); + + /// Param 1 for text type is the size of the field + $form->addElement('text', 'param1', get_string('profilefieldsize', 'admin'), 'size="6"'); + $form->setType('param1', PARAM_INT); + + /// Param 2 for text type is the maxlength of the field + $form->addElement('text', 'param2', get_string('profilefieldmaxlength', 'admin'), 'size="6"'); + $form->setType('param2', PARAM_INT); + } + +} + +?> \ No newline at end of file diff --git a/user/profile/field/text/field.class.php b/user/profile/field/text/field.class.php index 8541db43c6..3a89efb340 100644 --- a/user/profile/field/text/field.class.php +++ b/user/profile/field/text/field.class.php @@ -10,26 +10,8 @@ class profile_field_text extends profile_field_base { $maxlength = (empty($this->field->param2)) ? '2048' : $this->field->param2; /// Create the form field - $form->addElement('text', $this->fieldname, $this->field->name, 'maxlength="'.$maxlength.'" size="'.$size.'" '); - $form->setType($this->fieldname, PARAM_MULTILANG); - } - - function set_data_type() { - $this->datatype = 'text'; - } - - function edit_field_specific(&$form) { - /// Default data - $form->addElement('text', 'defaultdata', get_string('profiledefaultdata', 'admin'), 'size="30"'); - $form->setType('defaultdata', PARAM_MULTILANG); - - /// Param 1 for text type is the size of the field - $form->addElement('text', 'param1', get_string('profilefieldsize', 'admin'), 'size="6"'); - $form->setType('param1', PARAM_INT); - - /// Param 2 for text type is the maxlength of the field - $form->addElement('text', 'param2', get_string('profilefieldmaxlength', 'admin'), 'size="6"'); - $form->setType('param2', PARAM_INT); + $form->addElement('text', $this->inputname, format_string($this->field->name), 'maxlength="'.$maxlength.'" size="'.$size.'" '); + $form->setType($this->inputname, PARAM_MULTILANG); } } diff --git a/user/profile/index.php b/user/profile/index.php index 76b4eefe33..9733825342 100644 --- a/user/profile/index.php +++ b/user/profile/index.php @@ -1,25 +1,16 @@ dirroot.'/user/profile/lib.php'); require_once($CFG->libdir.'/adminlib.php'); +require_once($CFG->dirroot.'/user/profile/lib.php'); +require_once($CFG->dirroot.'/user/profile/definelib.php'); $adminroot = admin_get_root(); admin_externalpage_setup('profilefields', $adminroot); -require_login(); - -require_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID)); - - -$id = optional_param('id', 0, PARAM_INT); $action = optional_param('action', '', PARAM_ALPHA); -$dir = optional_param('dir', '', PARAM_ALPHA); -$confirm = optional_param('confirm', 0, PARAM_BOOL); -$type = optional_param('type', '', PARAM_ALPHANUM); -$datatypes = profile_list_datatypes(); -$redirect = $CFG->wwwroot.'/user/profile/index.php'; +$redirect = $CFG->wwwroot.'/user/profile/index.php'; $strchangessaved = get_string('changessaved'); $strcancelled = get_string('cancelled'); @@ -32,254 +23,133 @@ $strcreatefield = get_string('profilecreatefield', 'admin'); switch ($action) { case 'movecategory': + $id = required_param('id', PARAM_INT); + $dir = required_param('dir', PARAM_ALPHA); + if (confirm_sesskey()) { profile_move_category($id, $dir); } redirect($redirect); - exit; - break; + break; case 'movefield': + $id = required_param('id', PARAM_INT); + $dir = required_param('dir', PARAM_ALPHA); + if (confirm_sesskey()) { profile_move_field($id, $dir); } redirect($redirect); - exit; break; case 'deletecategory': - if ($confirm and confirm_sesskey()) { - $categorycount = count_records('user_info_category'); - $fieldcount = count_records('user_info_field', 'categoryid', $id); - - /// Can only delete the last category if there are no fields in it - if ( ($categorycount > 1) or ($fieldcount == 0) ) { - profile_delete_category($id); - } + $id = required_param('id', PARAM_INT); + $confirm = optional_param('confirm', 0, PARAM_BOOL); + + if (data_submitted() and $confirm and confirm_sesskey()) { + profile_delete_category($id); redirect($redirect); - exit; } - break; + + //ask for confirmation + $fieldcount = count_records('user_info_field', 'categoryid', $id); + $optionsyes = array ('id'=>$id, 'confirm'=>1, 'action'=>'deletecategory', 'sesskey'=>sesskey()); + admin_externalpage_print_header($adminroot); + print_heading('profiledeletecategory', 'admin'); + notice_yesno(get_string('profileconfirmcategorydeletion', 'admin', $fieldcount), $redirect, $redirect, $optionsyes, null, 'post', 'get'); + admin_externalpage_print_footer($adminroot); + die; + break; case 'deletefield': - - if ($confirm and confirm_sesskey()) { - if ($field = get_record('user_info_field', 'id', $id)) { - require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); - $newfield = 'profile_field_'.$field->datatype; - $formfield = new $newfield($field->id); - $formfield->edit_remove_field(); - } + $id = required_param('id', PARAM_INT); + $confirm = optional_param('confirm', 0, PARAM_BOOL); + + if (data_submitted() and $confirm and confirm_sesskey()) { + profile_delete_field($id); redirect($redirect); - exit; } - + + //ask for confirmation + $datacount = count_records('user_info_data', 'fieldid', $id); + $optionsyes = array ('id'=>$id, 'confirm'=>1, 'action'=>'deletefield', 'sesskey'=>sesskey()); + admin_externalpage_print_header($adminroot); + print_heading('profiledeletefield', 'admin'); + notice_yesno(get_string('profileconfirmfielddeletion', 'admin', $datacount), $redirect, $redirect, $optionsyes, null, 'post', 'get'); + admin_externalpage_print_footer($adminroot); + die; break; case 'editfield': - unset($field); - if ($id == 0) { - if (!isset($datatypes[$type])) { - redirect($redirect); - exit; - } - $field->id = 0; - $field->datatype = $type; - $field->categoryid = 0; - } elseif (!($field = get_record('user_info_field', 'id', $id))) { - redirect($redirect); - exit; - } + $id = optional_param('id', 0, PARAM_INT); + $datatype = optional_param('datatype', '', PARAM_ALPHA); + + profile_edit_field($id, $datatype, $redirect, $adminroot); + die; break; case 'editcategory': - unset($category); - if ($id == 0) { - $category->id = 0; - $category->name = ''; - } elseif (!($category = get_record('user_info_category', 'id', $id))) { - redirect($redirect); - exit; - } + $id = optional_param('id', 0, PARAM_INT); + + profile_edit_category($id, $redirect, $adminroot); + die; break; default: + //normal form } +/// Print the header +admin_externalpage_print_header($adminroot); +print_heading(get_string('profilefields', 'admin')); + +/// Check that we have at least one category defined +if (count_records('user_info_category') == 0) { + $defaultcategory = new object(); + $defaultcategory->name = $strdefaultcategory; + $defaultcategory->sortorder = 1; + insert_record('user_info_category', $defaultcategory); + redirect($redirect); +} +/// Show all categories +$categories = get_records_select('user_info_category', '', 'sortorder ASC'); +foreach ($categories as $category) { + $table = new object(); + $table->head = array(get_string('profilefield', 'admin'), get_string('edit')); + $table->align = array('left', 'right'); + $table->width = '95%'; + $table->class = 'generaltable profilefield'; + $table->data = array(); - - -/// Are we adding or editing a cateogory? -if ( ($action == 'editcategory' )) { - - - require_once('index_category_form.php'); - $categoryform = new category_form(null); - $categoryform->set_data($category); - if ($categoryform->is_cancelled()) { - redirect($redirect); - exit; - } else { - if ($data = $categoryform->get_data()) { - if ($data->id == 0) { - unset($data->id); - $data->sortorder = count_records('user_info_category') + 1; - if (!insert_record('user_info_category', $data, false)) { - error('There was a problem adding the record to the database'); - exit; - } - } else { - if (!update_record('user_info_category', $data)) { - error('There was a problem updating the record in the database'); - exit; - } - } - redirect($redirect); - exit; - - } else { - - if ($id == 0) { - $strheading = get_string('profilecreatenewcategory', 'admin'); - } else { - $strheading = get_string('profileeditcategory', 'admin', $category->name); - } - - /// Print the header - admin_externalpage_print_header($adminroot); - - print_heading($strheading); - - $categoryform->display(); + if ($fields = get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) { + foreach ($fields as $field) { + $table->data[] = array($field->name, profile_field_icons($field)); } } -/// Are we adding or editing a field? -} elseif ( $action == 'editfield' ) { - - require_once('index_field_form.php'); - $fieldform = new field_form(null, $field->datatype); - $fieldform->set_data($field); - if ($fieldform->is_cancelled()) { - redirect($redirect); - exit; + print_heading($category->name.' '.profile_category_icons($category)); + if (count($table->data)) { + print_table($table); } else { - if ($data = $fieldform->get_data()) { - require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); - $newfield = 'profile_field_'.$field->datatype; - $formfield = new $newfield($field->id); - if (!$formfield->edit_save($data)) { - error('There was an error updating the database'); - } else { - redirect($redirect); - exit; - } - - } else { - - if ($id == 0) { - $strheading = get_string('profilecreatenewfield', 'admin', $datatypes[$type]); - } else { - $strheading = get_string('profileeditfield', 'admin', $field->name); - } - - /// Print the header - admin_externalpage_print_header($adminroot); - - print_heading($strheading); - - $fieldform->display(); - } - } - -/// Deleting a category that has fields in it, print confirm screen? -} elseif ( ($action == 'deletecategory') and !$confirm ) { - - /// Print the header - admin_externalpage_print_header($adminroot); - - print_heading('profiledeletecategory', 'admin'); - - $fieldcount = count_records('user_info_field', 'categoryid', $id); - echo '
'.get_string('profileconfirmcategorydeletion', 'admin', $fieldcount).'
'.get_string('yes').' '.get_string('no').'
'; - - -/// Deleting a field that has user data, print confirm screen -} elseif ( ($action == 'deletefield') and !$confirm ) { - - /// Print the header - admin_externalpage_print_header($adminroot); - - print_heading('profiledeletefield', 'admin'); - - $datacount = count_records('user_info_data', 'fieldid', $id); - echo '
'.get_string('profileconfirmfielddeletion', 'admin', $datacount).'
'.get_string('yes').' '.get_string('no').'
'; - - - -/// Print the table of categories and fields -} else { - - /// Print the header - admin_externalpage_print_header($adminroot); - - print_heading(get_string('profilefields', 'admin')); - - /// Check that we have at least one category defined - if (count_records('user_info_category') == 0) { - unset($defaultcategory); - $defaultcategory->name = $strdefaultcategory; - $defaultcategory->sortorder = 1; - insert_record('user_info_category', $defaultcategory); + notify($strnofields); } - /// We only displaying if there are fields defined or there is a category with a name different to the default name - if ( ( (count_records_select('user_info_category', "name<>'$strdefaultcategory'") > 0) or - (count_records('user_info_field') > 0) ) and - ( $categories = get_records_select('user_info_category', '', 'sortorder ASC')) ) { - - - foreach ($categories as $category) { - - unset ($table); - $table->head = array(get_string('profilefield','admin'),get_string('edit')); - $table->align = array('left','right'); - $table->width = '95%'; - $table->class = 'generaltable profilefield'; - $table->data = array(); - - if ($fields = get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) { - foreach ($fields as $field) { - - $table->data[] = array($field->name, profile_field_icons($field)); - - } /// End of $fields foreach - } /// End of $fields if - - print_heading($category->name.' '.profile_category_icons($category)); - print_table($table); - - } /// End of $categories foreach +} /// End of $categories foreach - } else { - notify($strnofields); - - } /// End of $categories if - echo '
'; - echo '
'; +echo '
'; +echo '
'; - /// Create a new field link - $options = profile_list_datatypes(); - popup_form($CFG->wwwroot.'/user/profile/index.php?id=0&action=editfield&type=', $options, 'newfieldform','','choose','','',false,'self',$strcreatefield); +/// Create a new field link +$options = profile_list_datatypes(); +popup_form($CFG->wwwroot.'/user/profile/index.php?id=0&action=editfield&datatype=', $options, 'newfieldform','','choose','','',false,'self',$strcreatefield); /// Create a new category link - $options = array('action'=>'editcategory', 'id'=>'0'); - print_single_button('index.php',$options,get_string('profilecreatecategory', 'admin')); +$options = array('action'=>'editcategory'); +print_single_button('index.php', $options, get_string('profilecreatecategory', 'admin')); - echo '
'; -} +echo '
'; admin_externalpage_print_footer($adminroot); - +die; /***** Some functions relevant to this script *****/ @@ -292,42 +162,39 @@ admin_externalpage_print_footer($adminroot); function profile_category_icons ($category) { global $CFG, $USER; - $str->delete = get_string("delete"); - $str->moveup = get_string("moveup"); - $str->movedown = get_string("movedown"); - $str->edit = get_string("edit"); + $strdelete = get_string('delete'); + $strmoveup = get_string('moveup'); + $strmovedown = get_string('movedown'); + $stredit = get_string('edit'); - $editstr = ''; $categorycount = count_records('user_info_category'); $fieldcount = count_records('user_info_field', 'categoryid', $category->id); /// Edit - $editstr .= '
'.$str->edit.' '; + $editstr = ''.$stredit.' '; /// Delete /// Can only delete the last category if there are no fields in it if ( ($categorycount > 1) or ($fieldcount == 0) ) { - $editstr .= ''.$str->delete.' '; + $editstr .= ''.$strdelete.' '; } else { $editstr .= ' '; } /// Move up if ($category->sortorder > 1) { - $editstr .= ''.$str->moveup.' '; + $editstr .= ''.$strmoveup.' '; } else { $editstr .= ' '; } /// Move down if ($category->sortorder < $categorycount) { - $editstr .= ''.$str->movedown.' '; + $editstr .= ''.$strmovedown.' '; } else { $editstr .= ' '; } - return $editstr; } @@ -341,34 +208,32 @@ function profile_field_icons ($field) { global $CFG, $USER; if (empty($str)) { - $str->delete = get_string("delete"); - $str->moveup = get_string("moveup"); - $str->movedown = get_string("movedown"); - $str->edit = get_string("edit"); + $strdelete = get_string('delete'); + $strmoveup = get_string('moveup'); + $strmovedown = get_string('movedown'); + $stredit = get_string('edit'); } - $editstr = ''; $fieldcount = count_records('user_info_field', 'categoryid',$field->categoryid); $datacount = count_records('user_info_data', 'fieldid', $field->id); /// Edit - $editstr .= ''.$str->edit.' '; + $editstr = ''.$stredit.' '; /// Delete - $editstr .= ''.$str->delete.' '; + $editstr .= ''.$strdelete.' '; /// Move up if ($field->sortorder > 1) { - $editstr .= ''.$str->moveup.' '; + $editstr .= ''.$strmoveup.' '; } else { $editstr .= ' '; } /// Move down if ($field->sortorder < $fieldcount) { - $editstr .= ''.$str->movedown.' '; + $editstr .= ''.$strmovedown.' '; } else { $editstr .= ' '; } diff --git a/user/profile/index_category_form.php b/user/profile/index_category_form.php index d636365efb..4264ebf9c1 100644 --- a/user/profile/index_category_form.php +++ b/user/profile/index_category_form.php @@ -1,6 +1,6 @@ dirroot/lib/formslib.php"); +require_once($CFG->dirroot.'/lib/formslib.php'); class category_form extends moodleform { @@ -9,7 +9,7 @@ class category_form extends moodleform { global $USER, $CFG; $mform =& $this->_form; - + $strrequired = get_string('required'); /// Add some extra hidden fields @@ -19,9 +19,8 @@ class category_form extends moodleform { $mform->addElement('text', 'name', get_string('profilecategoryname', 'admin'), 'maxlength="255" size="30"'); $mform->setType('name', PARAM_MULTILANG); $mform->addRule('name', $strrequired, 'required', null, 'client'); - - $this->add_action_buttons(true); + $this->add_action_buttons(true); } /// End of function @@ -31,8 +30,8 @@ class category_form extends moodleform { $data = (object)$data; $err = array(); - - $category = get_record('user_info_category', 'id', $data->id); + + $category = get_record('user_info_category', 'id', $data->id); /// Check the name is unique if ($category and ($category->name !== $data->name) and (record_exists('user_info_category', 'name', $data->name))) { diff --git a/user/profile/index_field_form.php b/user/profile/index_field_form.php index 4189a0366f..be49ff8eae 100644 --- a/user/profile/index_field_form.php +++ b/user/profile/index_field_form.php @@ -1,62 +1,46 @@ dirroot/lib/formslib.php"); +require_once($CFG->dirroot.'/lib/formslib.php'); class field_form extends moodleform { - // Define the form + var $field; + +/// Define the form function definition () { - global $USER, $CFG; + global $CFG; + + $mform =& $this->_form; + + /// Everything else is dependant on the data type + $datatype = $this->_customdata; + require_once($CFG->dirroot.'/user/profile/field/'.$datatype.'/define.class.php'); + $newfield = 'profile_define_'.$datatype; + $this->field = new $newfield(); - $mform =& $this->_form; - $fieldtype = $this->_customdata; - $strrequired = get_string('required'); /// Add some extra hidden fields $mform->addElement('hidden', 'id'); $mform->addElement('hidden', 'action', 'editfield'); - $mform->addElement('hidden', 'type', $fieldtype); - $mform->addElement('hidden', 'oldcategory'); - $mform->addElement('hidden', 'datatype'); - $mform->addElement('hidden', 'sesskey'); - + $mform->addElement('hidden', 'datatype', $datatype); - /// Everything else is dependant on the data type - require_once($CFG->dirroot.'/user/profile/field/'.$fieldtype.'/field.class.php'); - $newfield = 'profile_field_'.$fieldtype; - $formfield = new $newfield(); - $formfield->edit_field($mform); - + $this->field->define_form($mform); $this->add_action_buttons(true); + } - } /// End of function - +/// alter definition based on existing or submitted data function definition_after_data () { - /// nothing yet + $mform =& $this->_form; + $this->field->define_after_data($mform); } /// perform some moodle validation function validation ($data) { - global $CFG; - - $data = (object)$data; - $fieldtype = $this->_customdata; - - /// Everything else is dependant on the data type - require_once($CFG->dirroot.'/user/profile/field/'.$fieldtype.'/field.class.php'); - $newfield = 'profile_field_'.$fieldtype; - $formfield = new $newfield(); - $err = $formfield->edit_validate($data); - - if (count($err) == 0){ - return true; - } else { - return $err; - } + return $this->field->define_validate($data); } } diff --git a/user/profile/lib.php b/user/profile/lib.php index ae7895efa3..820a86ec5e 100644 --- a/user/profile/lib.php +++ b/user/profile/lib.php @@ -2,405 +2,149 @@ /// Some constants -define ('PROFILE_REQUIRED_YES', '1'); -define ('PROFILE_REQUIRED_NO', '0'); - -define ('PROFILE_VISIBLE_ALL', '2'); -define ('PROFILE_VISIBLE_PRIVATE', '1'); -define ('PROFILE_VISIBLE_NONE', '0'); - -define ('PROFILE_LOCKED_YES', '1'); -define ('PROFILE_LOCKED_NO', '0'); - +define ('PROFILE_VISIBLE_ALL', '2'); // only visible for users with moodle/user:update capability +define ('PROFILE_VISIBLE_PRIVATE', '1'); // either we are viewing our own profile or we have moodle/user:update capability +define ('PROFILE_VISIBLE_NONE', '0'); // only visible for moodle/user:update capability /** * Base class for the cusomisable profile fields. */ class profile_field_base { - var $datatype = ''; /// data type of this field - var $fieldid = 0; /// id from user_info_field table - var $dataid = 0; /// id from user_info_data table - var $userid = 0; /// id from the user table - var $field = null; /// a copy of the field information - var $fieldname = ''; /// form name of the field + var $field; + var $inputname; /** * Constructor method. * @param integer id of the profile from the user_info_field table * @param integer id of the user for whom we are displaying data */ - function profile_field_base($fieldid=0, $userid=0) { - global $USER; - - /// Set the various properties for this class /// - - $this->fieldid = $fieldid; - - /// If $userid is empty, assume the current user - $this->userid = (empty($userid)) ? $USER->id : $userid; - - /// Set $field - if ( empty($fieldid) or (($field = get_record('user_info_field', 'id', $fieldid)) === false) ) { - $field = null; + function profile_field_base($fieldid) { + if (!$field = get_record('user_info_field', 'id', $fieldid)) { + error('Incorrect profile field id!'); } - $this->field = $field; - - $this->set_data_type(); - - /// If the child class hasn't implemented it's own set_data_type method - /// then we can get the type from the $field object if it exists - if (!empty($field) and ($this->datatype == 'unknown')) { - $this->datatype = $field->datatype; - } - - if ($field) { - $this->fieldname = $field->shortname; - } else { /// we are creating a new profile field - $this->fieldname = 'new_'.$this->datatype; - } - - /// We can set $dataid from $fieldid and $userid (if it exists) - if (!empty($fieldid) and !empty($userid)) { - if (($dataid = get_field('user_info_data', 'id', 'fieldid', $fieldid, 'userid', $userid)) === false) { - $dataid = 0; - } - } else { - $dataid = 0; - } - $this->dataid = $dataid; - - /// End of setting the properties /// - - - /// Post setup processing - $this->init(); + $this->field = $field; + $this->inputname = 'profile_field_'.$field->shortname; } - - /***** The following methods must be overwritten in the child classes *****/ - /** - * Set the data type for this profile field + * Check if the current field is visible to the current user + * @return boolean */ - function set_data_type() { - $this->datatype = 'unknown'; - } + function is_visible_for($userid) { + global $USER; - /** - * Adds the profile field to the moodle form class - * @param form instance of the moodleform class - */ - function display_field_add(&$form) { - /// Add the element to the form class - /// By default we add a static field - $form->addElement('static', $this->fieldname, $this->field->name, ''); - } - - /** - * Validate the form field from profile page - * @return string contains error message otherwise NULL - **/ - function validate_profile_field ($data) { - return NULL; + switch ($this->field->visible) { + case PROFILE_VISIBLE_ALL: + return true; + case PROFILE_VISIBLE_PRIVATE: + return ($userid == $USER->id); + default: + return has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID)); + } } - - /***** The following methods may be overwritten by child classes *****/ - /** * Print out the form field in the profile page * @param object instance of the moodleform class * $return boolean */ - function display_field (&$form) { - if (empty($this->field)) { - return false; - } - - /// Check that this field is visible to current user - if (!$this->_is_visible()) { - return false; - } + function display_field(&$form) { - $this->display_field_add($form); - $this->display_field_lock($form); - $this->display_field_default($form); - $this->display_field_required($form); + if ($this->field->visible != PROFILE_VISIBLE_NONE + or has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID))) { - return true; - } - - /** - * Locks (disables) the field if required in the form object - * @param object instance of the moodleform class - */ - function display_field_lock (&$form) { - if ($this->_is_locked()) { - $form->freeze($this->fieldname, false); + $this->display_field_add($form); + $this->display_field_set_default($form); + $this->display_field_set_required($form); + $this->display_field_set_locked($form); } } /** - * Sets the default data for the field in the form object - * @param object instance of the moodleform class - */ - function display_field_default(&$form) { - if (!($default = get_field('user_info_data', 'data', 'userid', $this->userid, 'fieldid', $this->field->id))) { - $default = $this->field->defaultdata; - } - if (!empty($default)) { - $form->setDefault($this->fieldname, $default); - } - } - - /** - * Sets the required flag for the field in the form object - * @param object instance of the moodleform class + * Saves the data coming from form + * @param mixed data coming from the form + * @return mixed returns data id if success of db insert/update, false on fail, 0 if not permitted */ - function display_field_required(&$form) { - if ( $this->_is_required() and !$this->_is_locked() ) { - $form->addRule($this->fieldname, get_string('required'), 'required', null, 'client'); - } - } + function save_data($usernew) { - /** - * Hook for child classes to perform any post-setup processes - */ - function init() { - /// do nothing - overwrite if necessary - } + $usernew = $this->save_data_preprocess($usernew); + if (!isset($usernew->{$this->inputname})) { + // field not present in form, probably locked and incisible - skip it! + return; + } - /** - * Prints out the form snippet for creating or editing a profile field - * @param object instance of the moodleform class - */ - function edit_field (&$form) { - $form->addElement('header', '_commonsettings', get_string('profilecommonsettings', 'admin')); - $this->edit_field_common($form); - - $form->addElement('header', '_specificsettings', get_string('profilespecificsettings', 'admin')); - $this->edit_field_specific($form); - } + $data = new object(); + $data->userid = $usernew->id; + $data->fieldid = $this->field->id; + $data->data = $usernew->{$this->inputname}; - /** - * Prints out the form snippet for the part of creating or - * editing a profile field common to all data types - * @param object instance of the moodleform class - */ - function edit_field_common (&$form) { - - $strrequired = get_string('required'); - - $form->addElement('text', 'shortname', get_string('profileshortname', 'admin'), 'maxlength="100" size="30"'); - $form->setType('shortname', PARAM_ALPHANUM); - $form->addRule('shortname', $strrequired, 'required', null, 'client'); - - $form->addElement('text', 'name', get_string('profilename', 'admin'), 'size="30"'); - $form->setType('name', PARAM_MULTILANG); - $form->addRule('name', $strrequired, 'required', null, 'client'); - - $form->addElement('htmleditor', 'description', get_string('profiledescription', 'admin')); - $form->setType('description', PARAM_MULTILANG); - $form->setHelpButton('description', array('text', get_string('helptext'))); - - $form->addElement('selectyesno', 'required', get_string('profilerequired', 'admin')); - $form->setType('required', PARAM_BOOL); - - $form->addElement('selectyesno', 'locked', get_string('profilelocked', 'admin')); - $form->setType('locked', PARAM_BOOL); - - $choices = array(); - $choices[0] = get_string('profilevisiblenone', 'admin'); - $choices[1] = get_string('profilevisibleprivate', 'admin'); - $choices[2] = get_string('profilevisibleall', 'admin'); - $form->addElement('select', 'visible', get_string('profilevisible', 'admin'), $choices); - $form->setType('visible', PARAM_INT); - $form->setDefault('visible', 2); - $form->setHelpButton('visible', array('profilevisible', get_string('profilevisible','admin'))); - - $choices = array(); - $choices = profile_list_categories(); - $form->addElement('select', 'categoryid', get_string('profilecategory', 'admin'), $choices); - $form->setType('categoryid', PARAM_INT); - } - - /** - * Prints out the form snippet for the part of creating or - * editing a profile field specific to the current data type - * @param object instance of the moodleform class - */ - function edit_field_specific (&$form) { - /// do nothing - overwrite if necessary + if ($dataid = get_field('user_info_data', 'id', 'userid', $data->userid, 'fieldid', $data->fieldid)) { + $data->id = $dataid; + if (!update_record('user_info_data', $data)) { + error('Error updating custom profile field!'); + } + } else { + insert_record('user_info_data', $data); + } } - /** - * Validate the data from the add/edit profile field form. - * Generally this method should not be overwritten by child - * classes. - * @param object data from the add/edit profile field form - * @return array associative array of error messages - */ - function edit_validate ($data) { - - $data = (object)$data; - $err = array(); - - $err += $this->edit_validate_common($data); - $err += $this->edit_validate_specific($data); - - return $err; - } + /***** The following methods may be overwritten by child classes *****/ /** - * Validate the data from the add/edit profile field form - * that is common to all data types. Generally this method - * should not be overwritten by child classes. - * @param object data from the add/edit profile field form - * @return array associative array of error messages + * Adds the profile field to the moodle form class + * @param form instance of the moodleform class */ - function edit_validate_common ($data) { - $err = array(); - - /// Check the shortname is unique - if (($field = get_record('user_info_field', 'shortname', $data->shortname)) and ($field->id <> $data->id)) { - //if (record_exists_select('user_info_field', 'shortname='.$data->shortname.' AND id<>'.$data->id)) { - $err['shortname'] = get_string('profileshortnamenotunique', 'admin'); - } - - /// No further checks necessary as the form class will take care of it - - return $err; + function display_field_add(&$form) { + error('This abstract method must be overriden'); } /** - * Validate the data from the add/edit profile field form - * that is specific to the current data type - * @param object data from the add/edit profile field form - * @return array associative array of error messages - */ - function edit_validate_specific ($data) { - $err = array(); - - /// do nothing - overwrite if necessary - - return $err; + * Validate the form field from profile page + * @return string contains error message otherwise NULL + **/ + function validate_field($usernew) { + //no errors by default + return array(); } - /** - * Add a new profile field or save changes to current field - * @param object data from the add/edit profile field form - * @return boolean status of the insert/update record - */ - function edit_save ($data) { - /// check to see if the category has changed - if ( (isset($this->field->categoryid) and ($this->field->categoryid != $data->categoryid)) or ($data->id == 0)) { - /// Set the sortorder for the field in the new category - $data->sortorder = count_records_select('user_info_field', 'categoryid='.$data->categoryid) + 1; + function load_data(&$user) { + if ($data = get_field('user_info_data', 'data', 'userid', $user->id, 'fieldid', $this->field->id)) { + $user->{$this->inputname} = $data; } - - $data = $this->edit_save_preprocess($data); /// hook for child classes - - if ($data->id == 0) { - unset($data->id); - if ($success = insert_record('user_info_field', $data)) { - $data->id = $success; - $success = true; - } else { - $success = false; - } - } else { - $success = update_record('user_info_field', $data); - } - - /// Store the new information in this objects properties - if ($success) { - if (isset($this->field->categoryid) and ($this->field->categoryid != $data->categoryid)) { - /// Change the sortorder of the other fields in the old category - profile_reorder_fields($this->field->categoryid, $this->field->sortorder); - } - - $this->field = $data; - $this->fieldid = $data->id; - - } - return $success; } /** - * Preprocess data from the add/edit profile field form - * before it is saved. This method is a hook for the child - * classes to overwrite. - * @param object data from the add/edit profile field form - * @return object processed data object - */ - function edit_save_preprocess ($data) { - /// do nothing - overwrite if necessary - return $data; - } - - /** - * Removes a profile field and all the user data associated with it + * Sets the default data for the field in the form object + * @param object instance of the moodleform class */ - function edit_remove_field () { - - if (!empty($this->field->id)) { - /// Remove the record from the database - delete_records('user_info_field', 'id', $this->field->id); - - /// Reorder the remaining fields in the same category - profile_reorder_fields($this->field->categoryid, $this->field->sortorder); - - /// Remove any user data associated with this field - delete_records('user_info_data', 'fieldid', $this->field->id); - } + function display_field_set_default(&$form) { + if (!empty($default)) { + $form->setDefault($this->inputname, $this->field->defaultdata); + } } /** - * Validates the data coming from form - * @param mixed data from the form - * @return string error message + * Sets the required flag for the field in the form object + * @param object instance of the moodleform class */ - function validate_data ($data) { - return ''; + function display_field_set_required(&$form) { + if ($this->field->required and !has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID))) { + $form->addRule($this->inputname, get_string('required'), 'required', null, 'client'); + } } /** - * Saves the data coming from form - * @param mixed data coming from the form - * @return mixed returns data id if success of db insert/update, false on fail, 0 if not permitted + * HardFreeze the field if locked. + * @param object instance of the moodleform class */ - function save_data ($data) { - if ($this->_is_visible() and !$this->_is_locked()) { /// check that we have permission - - $data = $this->save_data_preprocess($data); - - unset($datarecord); - $datarecord->userid = $this->userid; - $datarecord->fieldid = $this->fieldid; - $datarecord->data = $data; - - if ($this->dataid == 0) { /// inserting a new record - if ($ret = insert_record('user_info_data', $datarecord)) { - $this->dataid = $ret; - } - } else { - $datarecord->id = $this->dataid; - if (update_record('user_info_data', $datarecord)) { - $ret = $this->dataid; - } else { - $ret = false; - } - } - - } else { - $ret = 0; + function display_field_set_locked(&$form) { + if ($this->field->locked and !has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID))) { + $form->hardFreeze($this->inputname); } - - return $ret; } /** @@ -411,283 +155,93 @@ class profile_field_base { function save_data_preprocess($data) { return $data; } - - /***** The following methods should never be overwritten *****/ - - /** - * Check if the current field is visible to the current user - * @return boolean - */ - function _is_visible() { - global $USER; - /* Can we see this field? Choices are: - 1 - VISIBLE ALL; - 2 - VISIBLE PRIVATE - either we are viewing our own profile or we have required capability; - 3 - VISIBLE NONE - we have the required capability - */ - return ( ($this->field->visible === PROFILE_VISIBLE_ALL) - or ( ($this->field->visible === PROFILE_VISIBLE_PRIVATE) - and ($this->userid == $USER->id) ) - or has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID)) ); - } - - /** - * Check if the field is locked to the current user - * @return boolean - */ - function _is_locked() { - return ( ($this->field->locked == PROFILE_LOCKED_YES) - and !has_capability('moodle/user:update', get_context_instance(CONTEXT_SYSTEM, SITEID))); - } - - /** - * Check if the field is required - * @return boolean - */ - function _is_required() { - return ($this->field->required == PROFILE_REQUIRED_YES); - } - } /// End of class definition /***** General purpose functions for customisable user profiles *****/ +function profile_load_data(&$user) { + global $CFG; + + if ($fields = get_records_select('user_info_field')) { + foreach ($fields as $field) { + require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); + $newfield = 'profile_field_'.$field->datatype; + $formfield = new $newfield($field->id); + $formfield->load_data($user); + } + } +} + /** * Print out the customisable categories and fields for a users profile * @param object instance of the moodleform class - * @param integer id of the user - * @return nothing */ -function profile_print_custom_fields(&$form, $userid=0) { - global $USER, $CFG; - - if ($userid == 0) $userid = $USER->id; +function profile_definition(&$form) { + global $CFG; if ($categories = get_records_select('user_info_category', '', 'sortorder ASC')) { foreach ($categories as $category) { if ($fields = get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) { - $form->addElement('header', 'category_'.$category->id, $category->name); - foreach ($fields as $field) { - require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); $newfield = 'profile_field_'.$field->datatype; - $formfield = new $newfield($field->id,$user->id); + $formfield = new $newfield($field->id); $formfield->display_field($form); - unset($formfield); } - } /// End of $fields if - } /// End of $categories foreach - } /// End of $categories if -} - - -/** - * Retrieve a list of all the available data types - * @return array a list of the datatypes suitable to use in a select statement - */ -function profile_list_datatypes() { - global $CFG; - - $datatypes = array(); - - if ($dirlist = get_directory_list($CFG->dirroot.'/user/profile/field', '', false, true, false)) { - foreach ($dirlist as $type) { - $datatypes[$type] = get_string('profilefieldtype'.$type, 'admin'); + } } } - return $datatypes; -// return get_directory_list($CFG->dirroot.'/user/profile/field', '', false, true, false); } -/** - * Change the sortorder of a field - * @param integer id of the field - * @param string direction of move - * @return boolean success of operation - */ -function profile_move_field ($id, $move='down') { - /// Get the field object - if (!($field = get_record('user_info_field', 'id', $id))) { - return false; - } - /// Count the number of fields in this category - $fieldcount = count_records_select('user_info_field', 'categoryid='.$field->categoryid); - - /// Calculate the new sortorder - if ( ($move == 'up') and ($field->sortorder > 1)) { - $neworder = $field->sortorder - 1; - } elseif ( ($move == 'down') and ($field->sortorder < $fieldcount)) { - $neworder = $field->sortorder + 1; - } else { - return false; - } - - /// Retrieve the field object that is currently residing in the new position - if ($swapfield = get_record('user_info_field', 'categoryid', $field->categoryid, 'sortorder', $neworder)) { - - /// Swap the sortorders - $swapfield->sortorder = $field->sortorder; - $field->sortorder = $neworder; +function profile_definition_after_data(&$mform) { + global $CFG; +/* + if ($fields = get_records('user_info_field')) { + foreach ($fields as $field) { + require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); + $newfield = 'profile_field_'.$field->datatype; + $formfield = new $newfield($field->id); +//TODO add: method into field class - /// Update the field records - if (update_record('user_info_field', $field) and update_record('user_info_field', $swapfield)) { - return true; } - } - - return false; + }*/ } -/** - * Change the sortorder of a category - * @param integer id of the category - * @param string direction of move - * @return boolean success of operation - */ -function profile_move_category ($id, $move='down') { - /// Get the category object - if (!($category = get_record('user_info_category', 'id', $id))) { - return false; - } - - /// Count the number of categories - $categorycount = count_records('user_info_category'); - - /// Calculate the new sortorder - if ( ($move == 'up') and ($category->sortorder > 1)) { - $neworder = $category->sortorder - 1; - } elseif ( ($move == 'down') and ($category->sortorder < $categorycount)) { - $neworder = $category->sortorder + 1; - } else { - return false; - } - - /// Retrieve the category object that is currently residing in the new position - if ($swapcategory = get_record('user_info_category', 'sortorder', $neworder)) { - - /// Swap the sortorders - $swapcategory->sortorder = $category->sortorder; - $category->sortorder = $neworder; +function profile_validation($usernew) { + global $CFG; - /// Update the category records - if (update_record('user_info_category', $category) and update_record('user_info_category', $swapcategory)) { - return true; + $err = array(); + if ($fields = get_records('user_info_field')) { + foreach ($fields as $field) { + require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); + $newfield = 'profile_field_'.$field->datatype; + $formfield = new $newfield($field->id); + $err += $formfield->validate_field($usernew); } } - - return false; + return $err; } +function profile_save_data($usernew) { + global $CFG; -/** - * Retrieve a list of categories and ids suitable for use in a form - * @return array - */ -function profile_list_categories() { - if ( !($categories = get_records_select_menu('user_info_category', '', 'sortorder ASC', 'id, name')) ) { - $categories = array(); + if ($fields = get_records_select('user_info_field')) { + foreach ($fields as $field) { + require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php'); + $newfield = 'profile_field_'.$field->datatype; + $formfield = new $newfield($field->id); + $formfield->save_data($usernew); + } } - return $categories; } -/** - * Delete a profile category - * @param integer id of the category to be deleted - * @return boolean success of operation - */ -function profile_delete_category ($id) { - /// Retrieve the category - if (!($category = get_record('user_info_category', 'id', $id))) { - return false; - } - - /// Retrieve the next category up - if ( !($newcategory = get_record('user_info_category', 'sortorder', ($category->sortorder - 1))) ) { - /// Retrieve the next category down - if (!($newcategory = get_record('user_info_category', 'sortorder', ($category->sortorder + 1))) ) { - - if (count_records('user_info_field', 'categoryid', $category->id) > 0) { - - /// We cannot find any other categories next to current one so either: - /// 1. The sortorder values are incongruous which means a bug somewhere - /// 2. We are the only category but there are fields => cannot delete this category! - - return false; - } - } - } - - /// Does the category contain any fields - if (count_records('user_info_field', 'categoryid', $category->id) > 0) { - /// Move fields to the new category - $sortorder = count_records('user_info_field', 'categoryid', $newcategory->id); - - if ($fields = get_records('user_info_field', 'categoryid', $category->id)) { - foreach ($fields as $field) { - $sortorder++; - $field->sortorder = $sortorder; - $field->categoryid = $newcategory->id; - update_record('user_info_field', $field); - } - } - } - /// Finally we get to delete the category - if (delete_records('user_info_category', 'id', $category->id) !== false) { - profile_reorder_categories(); - return true; - } else { - return false; - } -} -/** - * Reorder the profile fields within a given category starting - * at the field at the given startorder - * @param integer id of the category - * @param integer starting order - * @return integer number of fields reordered - */ -function profile_reorder_fields($categoryid, $startorder=1) { - $count = 0; - $sortorder = $startorder; - - if ($fields = get_records_select('user_info_field', 'categoryid='.$categoryid.' AND sortorder>='.$startorder, 'sortorder ASC')) { - foreach ($fields as $field) { - $field->sortorder = $sortorder; - update_record('user_info_field', $field); - $sortorder++; - $count++; - } - } - return $count; -} -/** - * Reorder the profile categoriess starting at the category - * at the given startorder - * @param integer starting order - * @return integer number of categories reordered - */ -function profile_reorder_categories($startorder=1) { - $count = 0; - $sortorder = $startorder; - - if ($categories = get_records_select('user_info_category', 'sortorder>='.$startorder, 'sortorder ASC')) { - foreach ($categories as $cat) { - $cat->sortorder = $sortorder; - update_record('user_info_category', $cat); - $sortorder++; - $count++; - } - } - return $count; -} ?> -- 2.39.5