From f9e1c2587a520ed486a169a3584b9e556bfa1e58 Mon Sep 17 00:00:00 2001 From: Bas Brands Date: Tue, 17 Nov 2020 19:43:49 +0100 Subject: [PATCH] MDL-28452 core_user: migrate social profile fields Create a new profile field type, move all existing content of the fields 'icq', 'skype', 'aim', 'yahoo', 'msn' and 'url' in the mdl_user table to theses new profile fields if needed. AMOS BEGIN MOV [aimid,core],[aimid,courseimage,profilefield_social] MOV [yahooid,core],[yahooid,profilefield_social] MOV [skypeid,core],[skypeid,profilefield_social] MOV [icqnumber,core],[icqnumber,profilefield_social] MOV [msnid,core],[msnid,profilefield_social] MOV [webpage,core],[webpage,profilefield_social] AMOS END --- admin/auth_config.php | 2 - admin/settings/users.php | 6 - admin/tool/uploaduser/classes/process.php | 5 +- admin/tool/uploaduser/user_form.php | 4 - admin/user/user_bulk_download.php | 6 - auth/mnet/classes/privacy/provider.php | 6 - auth/mnet/lang/en/auth_mnet.php | 16 +- auth/oauth2/classes/api.php | 2 - .../condition/profile/classes/frontend.php | 6 - backup/moodle2/backup_stepslib.php | 5 +- .../helper/backup_anonymizer_helper.class.php | 24 -- badges/criteria/award_criteria_profile.php | 4 +- badges/tests/badgeslib_test.php | 6 +- blocks/myprofile/classes/output/myprofile.php | 20 -- blocks/myprofile/edit_form.php | 35 -- blocks/myprofile/lang/en/block_myprofile.php | 12 +- blocks/myprofile/templates/myprofile.mustache | 40 --- .../tests/behat/block_myprofile.feature | 95 ------ enrol/externallib.php | 12 - lang/en/deprecated.txt | 15 + lang/en/moodle.php | 10 +- lib/authlib.php | 2 - lib/classes/oauth2/api.php | 214 ++++++++++++ .../oauth2/discovery/openidconnect.php | 1 - lib/classes/oauth2/service/facebook.php | 2 - lib/classes/user.php | 7 - lib/db/install.xml | 6 - lib/db/upgrade.php | 23 ++ lib/moodlelib.php | 2 - lib/myprofilelib.php | 43 --- lib/tests/datalib_test.php | 12 - lib/tests/myprofilelib_test.php | 8 +- .../classes/task/send_user_notifications.php | 1 - mod/forum/deprecatedlib.php | 1 - mod/url/locallib.php | 4 - .../analytics/indicator/user_profile_set.php | 2 +- user/classes/privacy/provider.php | 18 - user/editlib.php | 23 -- user/externallib.php | 18 - user/lib.php | 29 +- user/profile/field/social/classes/helper.php | 74 +++++ .../field/social/classes/privacy/provider.php | 214 ++++++++++++ user/profile/field/social/define.class.php | 95 ++++++ user/profile/field/social/field.class.php | 84 +++++ .../social/lang/en/profilefield_social.php | 39 +++ .../field/social/tests/privacy_test.php | 312 ++++++++++++++++++ user/profile/field/social/upgradelib.php | 187 +++++++++++ user/profile/field/social/version.php | 29 ++ user/profile/index.php | 8 +- user/profile/lib.php | 8 + user/tests/externallib_test.php | 60 ---- user/tests/privacy_test.php | 8 - user/tests/userlib_test.php | 8 +- version.php | 2 +- 54 files changed, 1338 insertions(+), 537 deletions(-) create mode 100644 user/profile/field/social/classes/helper.php create mode 100644 user/profile/field/social/classes/privacy/provider.php create mode 100644 user/profile/field/social/define.class.php create mode 100644 user/profile/field/social/field.class.php create mode 100644 user/profile/field/social/lang/en/profilefield_social.php create mode 100644 user/profile/field/social/tests/privacy_test.php create mode 100644 user/profile/field/social/upgradelib.php create mode 100644 user/profile/field/social/version.php diff --git a/admin/auth_config.php b/admin/auth_config.php index 3ee8ebc8c0f..503dd91cc1f 100644 --- a/admin/auth_config.php +++ b/admin/auth_config.php @@ -171,8 +171,6 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts, // limit for the setting name is 100. continue; } - } elseif ($fieldname == 'url') { - $fieldname = get_string('webpage'); } else { $fieldname = get_string($fieldname); } diff --git a/admin/settings/users.php b/admin/settings/users.php index 6e58d4cd89e..2f265ee7efd 100644 --- a/admin/settings/users.php +++ b/admin/settings/users.php @@ -196,12 +196,6 @@ if ($hassiteconfig 'country' => new lang_string('country'), 'moodlenetprofile' => new lang_string('moodlenetprofile', 'user'), 'timezone' => new lang_string('timezone'), - 'webpage' => new lang_string('webpage'), - 'icqnumber' => new lang_string('icqnumber'), - 'skypeid' => new lang_string('skypeid'), - 'yahooid' => new lang_string('yahooid'), - 'aimid' => new lang_string('aimid'), - 'msnid' => new lang_string('msnid'), 'firstaccess' => new lang_string('firstaccess'), 'lastaccess' => new lang_string('lastaccess'), 'lastip' => new lang_string('lastip'), diff --git a/admin/tool/uploaduser/classes/process.php b/admin/tool/uploaduser/classes/process.php index 4204c8b8ae5..cb56918a276 100644 --- a/admin/tool/uploaduser/classes/process.php +++ b/admin/tool/uploaduser/classes/process.php @@ -142,9 +142,8 @@ class process { $this->standardfields = array('id', 'username', 'email', 'emailstop', 'city', 'country', 'lang', 'timezone', 'mailformat', 'maildisplay', 'maildigest', 'htmleditor', 'autosubscribe', - 'institution', 'department', 'idnumber', 'skype', - 'msn', 'aim', 'yahoo', 'icq', 'phone1', 'phone2', 'address', - 'url', 'description', 'descriptionformat', 'password', + 'institution', 'department', 'idnumber', 'phone1', 'phone2', 'address', + 'description', 'descriptionformat', 'password', 'auth', // Watch out when changing auth type or using external auth plugins! 'oldusername', // Use when renaming users - this is the original username. 'suspended', // 1 means suspend user account, 0 means activate user account, nothing means keep as is. diff --git a/admin/tool/uploaduser/user_form.php b/admin/tool/uploaduser/user_form.php index 9e90d84eeb1..8dcf4ce76a2 100644 --- a/admin/tool/uploaduser/user_form.php +++ b/admin/tool/uploaduser/user_form.php @@ -300,10 +300,6 @@ class admin_uploaduser_form2 extends moodleform { $mform->addHelpButton('description', 'userdescription'); $mform->setAdvanced('description'); - $mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"'); - $mform->setType('url', PARAM_URL); - $mform->setAdvanced('url'); - $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"'); $mform->setType('idnumber', core_user::get_property_type('idnumber')); $mform->setForceLtr('idnumber'); diff --git a/admin/user/user_bulk_download.php b/admin/user/user_bulk_download.php index 4e5e8d37ae9..ffa3f2335b1 100644 --- a/admin/user/user_bulk_download.php +++ b/admin/user/user_bulk_download.php @@ -48,12 +48,6 @@ if ($dataformat) { 'phone1' => 'phone1', 'phone2' => 'phone2', 'city' => 'city', - 'url' => 'url', - 'icq' => 'icq', - 'skype' => 'skype', - 'aim' => 'aim', - 'yahoo' => 'yahoo', - 'msn' => 'msn', 'country' => 'country'); if ($extrafields = $DB->get_records('user_info_field')) { diff --git a/auth/mnet/classes/privacy/provider.php b/auth/mnet/classes/privacy/provider.php index c774de14573..c1a95c6f6f7 100644 --- a/auth/mnet/classes/privacy/provider.php +++ b/auth/mnet/classes/privacy/provider.php @@ -81,7 +81,6 @@ class provider implements $externalfields = [ 'address' => 'privacy:metadata:mnet_external:address', - 'aim' => 'privacy:metadata:mnet_external:aim', 'alternatename' => 'privacy:metadata:mnet_external:alternatename', 'autosubscribe' => 'privacy:metadata:mnet_external:autosubscribe', 'calendartype' => 'privacy:metadata:mnet_external:calendartype', @@ -95,7 +94,6 @@ class provider implements 'firstaccess' => 'privacy:metadata:mnet_external:firstaccess', 'firstname' => 'privacy:metadata:mnet_external:firstname', 'firstnamephonetic' => 'privacy:metadata:mnet_external:firstnamephonetic', - 'icq' => 'privacy:metadata:mnet_external:icq', 'id' => 'privacy:metadata:mnet_external:id', 'idnumber' => 'privacy:metadata:mnet_external:idnumber', 'imagealt' => 'privacy:metadata:mnet_external:imagealt', @@ -108,19 +106,15 @@ class provider implements 'maildigest' => 'privacy:metadata:mnet_external:maildigest', 'maildisplay' => 'privacy:metadata:mnet_external:maildisplay', 'middlename' => 'privacy:metadata:mnet_external:middlename', - 'msn' => 'privacy:metadata:mnet_external:msn', 'phone1' => 'privacy:metadata:mnet_external:phone1', 'pnone2' => 'privacy:metadata:mnet_external:phone2', 'picture' => 'privacy:metadata:mnet_external:picture', 'policyagreed' => 'privacy:metadata:mnet_external:policyagreed', - 'skype' => 'privacy:metadata:mnet_external:skype', 'suspended' => 'privacy:metadata:mnet_external:suspended', 'timezone' => 'privacy:metadata:mnet_external:timezone', 'trackforums' => 'privacy:metadata:mnet_external:trackforums', 'trustbitmask' => 'privacy:metadata:mnet_external:trustbitmask', - 'url' => 'privacy:metadata:mnet_external:url', 'username' => 'privacy:metadata:mnet_external:username', - 'yahoo' => 'privacy:metadata:mnet_external:yahoo', ]; $collection->add_external_location_link('moodle', $externalfields, 'privacy:metadata:external:moodle'); diff --git a/auth/mnet/lang/en/auth_mnet.php b/auth/mnet/lang/en/auth_mnet.php index 4836214200b..d07f3a65355 100644 --- a/auth/mnet/lang/en/auth_mnet.php +++ b/auth/mnet/lang/en/auth_mnet.php @@ -39,7 +39,6 @@ $string['pluginname'] = 'MNet authentication'; $string['privacy:metadata:external:mahara'] = 'This plugin can send data externally to a linked Mahara application.'; $string['privacy:metadata:external:moodle'] = 'This plugin can send data externally to a linked Moodle application.'; $string['privacy:metadata:mnet_external:address'] = 'The address of the user.'; -$string['privacy:metadata:mnet_external:aim'] = 'The AIM identifier of the user'; $string['privacy:metadata:mnet_external:alternatename'] = 'An alternative name for the user.'; $string['privacy:metadata:mnet_external:autosubscribe'] = 'A preference as to if the user should be auto-subscribed to forums the user posts in.'; $string['privacy:metadata:mnet_external:calendartype'] = 'A user preference for the type of calendar to use.'; @@ -53,7 +52,6 @@ $string['privacy:metadata:mnet_external:emailstop'] = 'A preference to stop emai $string['privacy:metadata:mnet_external:firstaccess'] = 'The time that this user first accessed the site.'; $string['privacy:metadata:mnet_external:firstname'] = 'The first name of the user.'; $string['privacy:metadata:mnet_external:firstnamephonetic'] = 'The phonetic details about the user\'s first name.'; -$string['privacy:metadata:mnet_external:icq'] = 'The ICQ number of the user.'; $string['privacy:metadata:mnet_external:id'] = 'The user ID'; $string['privacy:metadata:mnet_external:idnumber'] = 'An identification number given by the institution'; $string['privacy:metadata:mnet_external:imagealt'] = 'Alternative text for the user\'s image.'; @@ -66,19 +64,15 @@ $string['privacy:metadata:mnet_external:lastnamephonetic'] = 'The phonetic detai $string['privacy:metadata:mnet_external:maildigest'] = 'A setting for the mail digest for this user.'; $string['privacy:metadata:mnet_external:maildisplay'] = 'A preference for the user about displaying their email address to other users.'; $string['privacy:metadata:mnet_external:middlename'] = 'The middle name of the user'; -$string['privacy:metadata:mnet_external:msn'] = 'The MSN identifier of the user'; $string['privacy:metadata:mnet_external:phone1'] = 'A phone number for the user.'; $string['privacy:metadata:mnet_external:phone2'] = 'An additional phone number for the user.'; $string['privacy:metadata:mnet_external:picture'] = 'The picture details associated with this user.'; $string['privacy:metadata:mnet_external:policyagreed'] = 'A flag to determine if the user has agreed to the site policy.'; -$string['privacy:metadata:mnet_external:skype'] = 'The Skype identifier of the user'; $string['privacy:metadata:mnet_external:suspended'] = 'A flag to show if the user has been suspended on this system.'; $string['privacy:metadata:mnet_external:timezone'] = 'The timezone of the user'; $string['privacy:metadata:mnet_external:trackforums'] = 'A preference for forums and tracking them.'; $string['privacy:metadata:mnet_external:trustbitmask'] = 'The trust bit mask'; -$string['privacy:metadata:mnet_external:url'] = 'A URL related to this user.'; $string['privacy:metadata:mnet_external:username'] = 'The username for this user.'; -$string['privacy:metadata:mnet_external:yahoo'] = 'The Yahoo identifier of the user'; $string['privacy:metadata:mnet_log'] = 'Details of remote actions carried out by a local user logged in a remote system.'; $string['privacy:metadata:mnet_log:action'] = 'Action carried out by the user.'; $string['privacy:metadata:mnet_log:cmid'] = 'ID of the course module.'; @@ -99,4 +93,12 @@ $string['privacy:metadata:mnet_session:token'] = 'Unique session identifier'; $string['privacy:metadata:mnet_session:useragent'] = 'User agent used to access the remote system'; $string['privacy:metadata:mnet_session:userid'] = 'ID of the user jumping to remote system.'; $string['privacy:metadata:mnet_session:username'] = 'Username of the user jumping to remote system.'; -$string['unknownhost'] = 'Unknown host'; \ No newline at end of file +$string['unknownhost'] = 'Unknown host'; + +// Deprecated since Moodle 4.0. +$string['privacy:metadata:mnet_external:aim'] = 'The AIM identifier of the user'; +$string['privacy:metadata:mnet_external:icq'] = 'The ICQ number of the user.'; +$string['privacy:metadata:mnet_external:msn'] = 'The MSN identifier of the user'; +$string['privacy:metadata:mnet_external:skype'] = 'The Skype identifier of the user'; +$string['privacy:metadata:mnet_external:url'] = 'A URL related to this user.'; +$string['privacy:metadata:mnet_external:yahoo'] = 'The Yahoo identifier of the user'; diff --git a/auth/oauth2/classes/api.php b/auth/oauth2/classes/api.php index e5b0789b576..5c3545e1250 100644 --- a/auth/oauth2/classes/api.php +++ b/auth/oauth2/classes/api.php @@ -258,7 +258,6 @@ class api { $user->mnethostid = $CFG->mnet_localhost_id; $user->lastname = isset($userinfo['lastname']) ? $userinfo['lastname'] : ''; $user->firstname = isset($userinfo['firstname']) ? $userinfo['firstname'] : ''; - $user->url = isset($userinfo['url']) ? $userinfo['url'] : ''; $user->alternatename = isset($userinfo['alternatename']) ? $userinfo['alternatename'] : ''; $user->secret = random_string(15); @@ -307,7 +306,6 @@ class api { $user->mnethostid = $CFG->mnet_localhost_id; $user->lastname = isset($userinfo['lastname']) ? $userinfo['lastname'] : ''; $user->firstname = isset($userinfo['firstname']) ? $userinfo['firstname'] : ''; - $user->url = isset($userinfo['url']) ? $userinfo['url'] : ''; $user->alternatename = isset($userinfo['alternatename']) ? $userinfo['alternatename'] : ''; $user->secret = random_string(15); diff --git a/availability/condition/profile/classes/frontend.php b/availability/condition/profile/classes/frontend.php index 37fda5371f3..d6a311d9c14 100644 --- a/availability/condition/profile/classes/frontend.php +++ b/availability/condition/profile/classes/frontend.php @@ -49,12 +49,6 @@ class frontend extends \core_availability\frontend { 'email' => \core_user\fields::get_display_name('email'), 'city' => \core_user\fields::get_display_name('city'), 'country' => \core_user\fields::get_display_name('country'), - 'url' => \core_user\fields::get_display_name('url'), - 'icq' => \core_user\fields::get_display_name('icq'), - 'skype' => \core_user\fields::get_display_name('skype'), - 'aim' => \core_user\fields::get_display_name('aim'), - 'yahoo' => \core_user\fields::get_display_name('yahoo'), - 'msn' => \core_user\fields::get_display_name('msn'), 'idnumber' => \core_user\fields::get_display_name('idnumber'), 'institution' => \core_user\fields::get_display_name('institution'), 'department' => \core_user\fields::get_display_name('department'), diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index 4339b0c232d..d8f4e5aeaa3 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1360,11 +1360,10 @@ class backup_users_structure_step extends backup_structure_step { // Then, the fields potentially needing anonymization $anonfields = array( - 'username', 'idnumber', 'email', 'icq', 'skype', - 'yahoo', 'aim', 'msn', 'phone1', + 'username', 'idnumber', 'email', 'phone1', 'phone2', 'institution', 'department', 'address', 'city', 'country', 'lastip', 'picture', - 'url', 'description', 'descriptionformat', 'imagealt', 'auth'); + 'description', 'descriptionformat', 'imagealt', 'auth'); $anonfields = array_merge($anonfields, \core_user\fields::get_name_fields()); // Add anonymized fields to $userfields with custom final element diff --git a/backup/util/helper/backup_anonymizer_helper.class.php b/backup/util/helper/backup_anonymizer_helper.class.php index 9ccd8876141..74b73962d00 100644 --- a/backup/util/helper/backup_anonymizer_helper.class.php +++ b/backup/util/helper/backup_anonymizer_helper.class.php @@ -98,26 +98,6 @@ class backup_anonymizer_helper { return 'anon' . $counter . '@doesntexist.invalid'; // Just a counter. } - public static function process_user_icq($value) { - return ''; // Clean icq - } - - public static function process_user_skype($value) { - return ''; // Clean skype - } - - public static function process_user_yahoo($value) { - return ''; // Clean yahoo - } - - public static function process_user_aim($value) { - return ''; // Clean aim - } - - public static function process_user_msn($value) { - return ''; // Clean msn - } - public static function process_user_phone1($value) { return ''; // Clean phone1 } @@ -154,10 +134,6 @@ class backup_anonymizer_helper { return 0; // No picture } - public static function process_user_url($value) { - return ''; // No url - } - public static function process_user_description($value) { return ''; // No user description } diff --git a/badges/criteria/award_criteria_profile.php b/badges/criteria/award_criteria_profile.php index 6091b6281c2..9c02a19c6f4 100644 --- a/badges/criteria/award_criteria_profile.php +++ b/badges/criteria/award_criteria_profile.php @@ -51,8 +51,8 @@ class award_criteria_profile extends award_criteria { $missing = array(); // Note: cannot use user_get_default_fields() here because it is not possible to decide which fields user can modify. - $dfields = array('firstname', 'lastname', 'email', 'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo', - 'aim', 'msn', 'department', 'institution', 'description', 'picture', 'city', 'url', 'country'); + $dfields = array('firstname', 'lastname', 'email', 'address', 'phone1', 'phone2', + 'department', 'institution', 'description', 'picture', 'city', 'country'); $sql = "SELECT uf.id as fieldid, uf.name as name, ic.id as categoryid, ic.name as categoryname, uf.datatype FROM {user_info_field} uf diff --git a/badges/tests/badgeslib_test.php b/badges/tests/badgeslib_test.php index 3231db1628f..b44d2f59a52 100644 --- a/badges/tests/badgeslib_test.php +++ b/badges/tests/badgeslib_test.php @@ -602,8 +602,8 @@ class badgeslib_test extends advanced_testcase { $criteria_overall = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id)); $criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY)); $criteria_overall1 = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_PROFILE, 'badgeid' => $badge->id)); - $criteria_overall1->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ALL, 'field_address' => 'address', 'field_aim' => 'aim', - 'field_' . $customprofileid => $customprofileid)); + $criteria_overall1->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ALL, 'field_address' => 'address', + 'field_department' => 'department', 'field_' . $customprofileid => $customprofileid)); // Assert the badge will not be issued to the user as is. $badge = new badge($this->coursebadge); @@ -612,7 +612,7 @@ class badgeslib_test extends advanced_testcase { // Set the required fields and make sure the badge got issued. $this->user->address = 'Test address'; - $this->user->aim = '999999999'; + $this->user->department = 'sillywalks'; $sink = $this->redirectEmails(); profile_save_data((object)array('id' => $this->user->id, 'profile_field_newfield' => 'X')); user_update_user($this->user, false); diff --git a/blocks/myprofile/classes/output/myprofile.php b/blocks/myprofile/classes/output/myprofile.php index 714c9d01748..c604a37a67d 100644 --- a/blocks/myprofile/classes/output/myprofile.php +++ b/blocks/myprofile/classes/output/myprofile.php @@ -84,26 +84,6 @@ class myprofile implements renderable, templatable { $data->useremail = obfuscate_mailto($USER->email, ''); } - if (!empty($this->config->display_icq) && !empty($USER->icq)) { - $data->usericq = s($USER->icq); - } - - if (!empty($this->config->display_skype) && !empty($USER->skype)) { - $data->userskype = s($USER->skype); - } - - if (!empty($this->config->display_yahoo) && !empty($USER->yahoo)) { - $data->useryahoo = s($USER->yahoo); - } - - if (!empty($this->config->display_aim) && !empty($USER->aim)) { - $data->useraim = s($USER->aim); - } - - if (!empty($this->config->display_msn) && !empty($USER->msn)) { - $data->usermsn = s($USER->msn); - } - if (!empty($this->config->display_phone1) && !empty($USER->phone1)) { $data->userphone1 = s($USER->phone1); } diff --git a/blocks/myprofile/edit_form.php b/blocks/myprofile/edit_form.php index 0302647540c..6de49b23ddb 100644 --- a/blocks/myprofile/edit_form.php +++ b/blocks/myprofile/edit_form.php @@ -57,41 +57,6 @@ class block_myprofile_edit_form extends block_edit_form { $mform->setDefault('config_display_email', '1'); } - $mform->addElement('selectyesno', 'config_display_icq', get_string('display_icq', 'block_myprofile')); - if (isset($this->block->config->display_icq)) { - $mform->setDefault('config_display_icq', $this->block->config->display_icq); - } else { - $mform->setDefault('config_display_icq', '0'); - } - - $mform->addElement('selectyesno', 'config_display_skype', get_string('display_skype', 'block_myprofile')); - if (isset($this->block->config->display_skype)) { - $mform->setDefault('config_display_skype', $this->block->config->display_skype); - } else { - $mform->setDefault('config_display_skype', '0'); - } - - $mform->addElement('selectyesno', 'config_display_yahoo', get_string('display_yahoo', 'block_myprofile')); - if (isset($this->block->config->display_yahoo)) { - $mform->setDefault('config_display_yahoo', $this->block->config->display_yahoo); - } else { - $mform->setDefault('config_display_yahoo', '0'); - } - - $mform->addElement('selectyesno', 'config_display_aim', get_string('display_aim', 'block_myprofile')); - if (isset($this->block->config->display_aim)) { - $mform->setDefault('config_display_aim', $this->block->config->display_aim); - } else { - $mform->setDefault('config_display_aim', '0'); - } - - $mform->addElement('selectyesno', 'config_display_msn', get_string('display_msn', 'block_myprofile')); - if (isset($this->block->config->display_msn)) { - $mform->setDefault('config_display_msn', $this->block->config->display_msn); - } else { - $mform->setDefault('config_display_msn', '0'); - } - $mform->addElement('selectyesno', 'config_display_phone1', get_string('display_phone1', 'block_myprofile')); if (isset($this->block->config->display_phone1)) { $mform->setDefault('config_display_phone1', $this->block->config->display_phone1); diff --git a/blocks/myprofile/lang/en/block_myprofile.php b/blocks/myprofile/lang/en/block_myprofile.php index 5d886c2c078..e263d2c0846 100644 --- a/blocks/myprofile/lang/en/block_myprofile.php +++ b/blocks/myprofile/lang/en/block_myprofile.php @@ -28,11 +28,6 @@ $string['display_picture'] = 'Display picture'; $string['display_country'] = 'Display country'; $string['display_city'] = 'Display city'; $string['display_email'] = 'Display email'; -$string['display_icq'] = 'Display ICQ'; -$string['display_skype'] = 'Display Skype'; -$string['display_yahoo'] = 'Display Yahoo'; -$string['display_aim'] = 'Display AIM'; -$string['display_msn'] = 'Display MSN'; $string['display_phone1'] = 'Display phone'; $string['display_phone2'] = 'Display mobile phone'; $string['display_institution'] = 'Display institution'; @@ -46,3 +41,10 @@ $string['myprofile:myaddinstance'] = 'Add a new logged in user block to Dashboar $string['myprofile_settings'] = 'Visible user information'; $string['pluginname'] = 'Logged in user'; $string['privacy:metadata'] = 'The Logged in user block only shows information about the logged in user and does not store data itself.'; + +// Deprecated since Moodle 4.0. +$string['display_icq'] = 'Display ICQ'; +$string['display_skype'] = 'Display Skype'; +$string['display_yahoo'] = 'Display Yahoo'; +$string['display_aim'] = 'Display AIM'; +$string['display_msn'] = 'Display MSN'; \ No newline at end of file diff --git a/blocks/myprofile/templates/myprofile.mustache b/blocks/myprofile/templates/myprofile.mustache index e132b0d95d9..d9505e7f373 100644 --- a/blocks/myprofile/templates/myprofile.mustache +++ b/blocks/myprofile/templates/myprofile.mustache @@ -33,11 +33,6 @@ * usercountry * usercity * useremail - * usericq - * userskype - * useryahoo - * useraim - * usermsn * userphone1 * userphone2 * userinstitution @@ -54,11 +49,6 @@ "usercountry": "Australia", "usercity": "Perth", "useremail": "john.doe@example.com", - "usericq": "12345", - "userskype": "john.doe", - "useryahoo": "12345", - "useraim": "12345", - "usermsn": "12345", "userphone1": "123456789", "userphone2": "123456789", "userinstitution": "Institution", @@ -98,36 +88,6 @@ {{{ useremail }}} {{/useremail}} - {{#usericq}} -
- ICQ: - {{ usericq }} -
- {{/usericq}} - {{#userskype}} -
- Skype: - {{ userskype }} -
- {{/userskype}} - {{#useryahoo}} -
- Yahoo: - {{ useryahoo }} -
- {{/useryahoo}} - {{#useraim}} -
- AIM: - {{ useraim }} -
- {{/useraim}} - {{#usermsn}} -
- MSN: - {{ usermsn }} -
- {{/usermsn}} {{#userphone1}}
{{#str}} phone1 {{/str}}: diff --git a/blocks/myprofile/tests/behat/block_myprofile.feature b/blocks/myprofile/tests/behat/block_myprofile.feature index 8bd076c80c8..8801de340d9 100644 --- a/blocks/myprofile/tests/behat/block_myprofile.feature +++ b/blocks/myprofile/tests/behat/block_myprofile.feature @@ -61,101 +61,6 @@ Feature: The logged in user block allows users to view their profile information And I press "Save changes" And I should see "teacher1@example.com" in the "Logged in user" "block" - Scenario: Configure the logged in user block to show / hide the users ICQ - Given the following "users" exist: - | username | firstname | lastname | email | icq | - | teacher1 | Teacher | One | teacher1@example.com | myicq | - And I log in as "teacher1" - And I press "Customise this page" - When I add the "Logged in user" block - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display ICQ | No | - And I press "Save changes" - Then I should see "Teacher One" in the "Logged in user" "block" - And I should not see "myicq" in the "Logged in user" "block" - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display ICQ | Yes | - And I press "Save changes" - And I should see "myicq" in the "Logged in user" "block" - - Scenario: Configure the logged in user block to show / hide the users Skype - Given the following "users" exist: - | username | firstname | lastname | email | skype | - | teacher1 | Teacher | One | teacher1@example.com | myskype | - And I log in as "teacher1" - And I press "Customise this page" - When I add the "Logged in user" block - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display Skype | No | - And I press "Save changes" - Then I should see "Teacher One" in the "Logged in user" "block" - And I should not see "myskype" in the "Logged in user" "block" - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display Skype | Yes | - And I press "Save changes" - And I should see "myskype" in the "Logged in user" "block" - - Scenario: Configure the logged in user block to show / hide the users Yahoo - Given the following "users" exist: - | username | firstname | lastname | email | yahoo | - | teacher1 | Teacher | One | teacher1@example.com | myyahoo | - And I log in as "teacher1" - And I press "Customise this page" - When I add the "Logged in user" block - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display Yahoo | No | - And I press "Save changes" - Then I should see "Teacher One" in the "Logged in user" "block" - And I should not see "myyahoo" in the "Logged in user" "block" - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display Yahoo | Yes | - And I press "Save changes" - And I should see "myyahoo" in the "Logged in user" "block" - - Scenario: Configure the logged in user block to show / hide the users AIM - Given the following "users" exist: - | username | firstname | lastname | email | aim | - | teacher1 | Teacher | One | teacher1@example.com | myaim | - And I log in as "teacher1" - And I press "Customise this page" - When I add the "Logged in user" block - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display AIM | No | - And I press "Save changes" - Then I should see "Teacher One" in the "Logged in user" "block" - And I should not see "myaim" in the "Logged in user" "block" - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display AIM | Yes | - And I press "Save changes" - And I should see "myaim" in the "Logged in user" "block" - - Scenario: Configure the logged in user block to show / hide the users MSN - Given the following "users" exist: - | username | firstname | lastname | email | msn | - | teacher1 | Teacher | One | teacher1@example.com | mymsn | - And I log in as "teacher1" - And I press "Customise this page" - When I add the "Logged in user" block - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display MSN | No | - And I press "Save changes" - Then I should see "Teacher One" in the "Logged in user" "block" - And I should not see "mymsn" in the "Logged in user" "block" - And I configure the "Logged in user" block - And I set the following fields to these values: - | Display MSN | Yes | - And I press "Save changes" - And I should see "mymsn" in the "Logged in user" "block" - Scenario: Configure the logged in user block to show / hide the users phone Given the following "users" exist: | username | firstname | lastname | email | phone1 | diff --git a/enrol/externallib.php b/enrol/externallib.php index 116d1ff6d6a..0254bde5a4f 100644 --- a/enrol/externallib.php +++ b/enrol/externallib.php @@ -211,11 +211,6 @@ class core_enrol_external extends external_api { 'address' => new external_value(PARAM_MULTILANG, 'Postal address', VALUE_OPTIONAL), 'phone1' => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL), 'phone2' => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL), - 'icq' => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL), - 'skype' => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL), - 'yahoo' => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL), - 'aim' => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL), - 'msn' => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL), 'department' => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL), 'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL), 'interests' => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL), @@ -225,7 +220,6 @@ class core_enrol_external extends external_api { 'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL), 'descriptionformat' => new external_value(PARAM_INT, 'User profile description format', VALUE_OPTIONAL), 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), - 'url' => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL), 'country' => new external_value(PARAM_ALPHA, 'Country code of the user, such as AU or CZ', VALUE_OPTIONAL), 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small', VALUE_OPTIONAL), 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big', VALUE_OPTIONAL), @@ -908,11 +902,6 @@ class core_enrol_external extends external_api { 'address' => new external_value(PARAM_TEXT, 'Postal address', VALUE_OPTIONAL), 'phone1' => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL), 'phone2' => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL), - 'icq' => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL), - 'skype' => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL), - 'yahoo' => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL), - 'aim' => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL), - 'msn' => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL), 'department' => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL), 'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL), 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), @@ -923,7 +912,6 @@ class core_enrol_external extends external_api { 'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL), 'descriptionformat' => new external_format_value('description', VALUE_OPTIONAL), 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL), - 'url' => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL), 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version', VALUE_OPTIONAL), 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version', VALUE_OPTIONAL), diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt index 96968e97656..ea3ac6bbae9 100644 --- a/lang/en/deprecated.txt +++ b/lang/en/deprecated.txt @@ -134,3 +134,18 @@ usernameoridoccurenceerror,core_webservice addbackpack,core_badges error:backpacknotavailable,core_badges error:backpackproblem,core_badges +privacy:metadata:mnet_external:aim,auth_mnet +privacy:metadata:mnet_external:icq,auth_mnet +privacy:metadata:mnet_external:msn,auth_mnet +privacy:metadata:mnet_external:skype,auth_mnet +privacy:metadata:mnet_external:url,auth_mnet +privacy:metadata:mnet_external:yahoo,auth_mnet +display_icq,block_myprofile +display_skype,block_myprofile +display_yahoo,block_myprofile +display_aim,block_myprofile +display_msn,block_myprofile +aimid,core +yahooid,core +icqnumber,core +msnid,core diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 1090198974a..ea0e43b110f 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -123,7 +123,6 @@ $string['afterresource'] = 'After resource "{$a}"'; $string['aftersection'] = 'After section "{$a}"'; $string['again'] = 'again'; $string['agelocationverification'] = 'Age and location verification'; -$string['aimid'] = 'AIM ID'; $string['ajaxuse'] = 'AJAX and Javascript'; $string['all'] = 'All'; $string['allactions'] = 'All actions'; @@ -1049,7 +1048,6 @@ $string['eventcontentviewed'] = 'Content viewed'; $string['filter'] = 'Filter'; $string['filteroption'] = '{$a->criteria}: {$a->value}'; $string['filters'] = 'Filters'; -$string['icqnumber'] = 'ICQ number'; $string['icon'] = 'Icon'; $string['idnumber'] = 'ID number'; $string['idnumbercourse'] = 'Course ID number'; @@ -1356,7 +1354,6 @@ $string['moveselectedcategoriesto'] = 'Move selected categories to'; $string['moveselectedcoursesto'] = 'Move selected courses to...'; $string['movetoanotherfolder'] = 'Move to another folder'; $string['moveup'] = 'Move up'; -$string['msnid'] = 'MSN ID'; $string['mustconfirm'] = 'You need to confirm your account'; $string['mustchangepassword'] = 'The new password must be different than the current one'; $string['mycourses'] = 'My courses'; @@ -1972,7 +1969,6 @@ $string['skipped'] = 'Skipped'; $string['skiptocategorylisting'] = 'Skip to the category listings'; $string['skiptocourselisting'] = 'Skip to the course listings'; $string['skiptocoursedetails'] = 'Skip to the detailed course information'; -$string['skypeid'] = 'Skype ID'; $string['socialheadline'] = 'Social forum - latest topics'; $string['someallowguest'] = 'Some courses may allow guest access'; $string['someerrorswerefound'] = 'Some information was missing or incorrect. Look below for details.'; @@ -2298,7 +2294,6 @@ $string['writingmoduleinfo'] = 'Writing modules info'; $string['writingscalesinfo'] = 'Writing scales info'; $string['writinguserinfo'] = 'Writing users info'; $string['wrongpassword'] = 'Incorrect password for this username'; -$string['yahooid'] = 'Yahoo ID'; $string['year'] = 'year'; $string['years'] = 'years'; $string['yes'] = 'Yes'; @@ -2322,3 +2317,8 @@ $string['userfilterplaceholder'] = 'Search keyword or select filter'; // Deprecated since Moodle 3.11. $string['hidepicture'] = 'Hide picture'; +$string['aimid'] = 'AIM ID'; +$string['yahooid'] = 'Yahoo ID'; +$string['skypeid'] = 'Skype ID'; +$string['icqnumber'] = 'ICQ number'; +$string['msnid'] = 'MSN ID'; diff --git a/lib/authlib.php b/lib/authlib.php index 10be07e4e5e..b81c6ab4b5e 100644 --- a/lib/authlib.php +++ b/lib/authlib.php @@ -1200,8 +1200,6 @@ function display_auth_lock_options($settings, $auth, $userfields, $helptext, $ma // limit for the setting name is 100. $fieldnametoolong = true; } - } else if ($fieldname == 'url') { - $fieldname = get_string('webpage'); } else { $fieldname = get_string($fieldname); } diff --git a/lib/classes/oauth2/api.php b/lib/classes/oauth2/api.php index 6219c8dc98c..448928887f8 100644 --- a/lib/classes/oauth2/api.php +++ b/lib/classes/oauth2/api.php @@ -40,6 +40,220 @@ use moodle_exception; */ class api { + /** + * Build a facebook ready OAuth 2 service. + * @return \core\oauth2\issuer + */ + private static function init_facebook() { + // Facebook is a custom setup. + $record = (object) [ + 'name' => 'Facebook', + 'image' => 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png', + 'baseurl' => '', + 'loginscopes' => 'public_profile email', + 'loginscopesoffline' => 'public_profile email', + 'showonloginpage' => true, + 'servicetype' => 'facebook', + ]; + + $issuer = new issuer(0, $record); + return $issuer; + } + + /** + * Create endpoints for facebook issuers. + * @param issuer $issuer issuer the endpoints should be created for. + * @return mixed + * @throws \coding_exception + * @throws \core\invalid_persistent_exception + */ + private static function create_endpoints_for_facebook($issuer) { + // The Facebook API version. + $apiversion = '2.12'; + // The Graph API URL. + $graphurl = 'https://graph.facebook.com/v' . $apiversion; + // User information fields that we want to fetch. + $infofields = [ + 'id', + 'first_name', + 'last_name', + 'link', + 'picture.type(large)', + 'name', + 'email', + ]; + $endpoints = [ + 'authorization_endpoint' => sprintf('https://www.facebook.com/v%s/dialog/oauth', $apiversion), + 'token_endpoint' => $graphurl . '/oauth/access_token', + 'userinfo_endpoint' => $graphurl . '/me?fields=' . implode(',', $infofields) + ]; + + foreach ($endpoints as $name => $url) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'name' => $name, + 'url' => $url + ]; + $endpoint = new endpoint(0, $record); + $endpoint->create(); + } + + // Create the field mappings. + $mapping = [ + 'name' => 'alternatename', + 'last_name' => 'lastname', + 'email' => 'email', + 'first_name' => 'firstname', + 'picture-data-url' => 'picture', + ]; + foreach ($mapping as $external => $internal) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'externalfield' => $external, + 'internalfield' => $internal + ]; + $userfieldmapping = new user_field_mapping(0, $record); + $userfieldmapping->create(); + } + return $issuer; + } + + /** + * Build a microsoft ready OAuth 2 service. + * @return \core\oauth2\issuer + */ + private static function init_microsoft() { + // Microsoft is a custom setup. + $record = (object) [ + 'name' => 'Microsoft', + 'image' => 'https://www.microsoft.com/favicon.ico', + 'baseurl' => '', + 'loginscopes' => 'openid profile email user.read', + 'loginscopesoffline' => 'openid profile email user.read offline_access', + 'showonloginpage' => true, + 'servicetype' => 'microsoft', + ]; + + $issuer = new issuer(0, $record); + return $issuer; + } + + /** + * Create endpoints for microsoft issuers. + * @param issuer $issuer issuer the endpoints should be created for. + * @return mixed + * @throws \coding_exception + * @throws \core\invalid_persistent_exception + */ + private static function create_endpoints_for_microsoft($issuer) { + + $endpoints = [ + 'authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', + 'token_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token', + 'userinfo_endpoint' => 'https://graph.microsoft.com/v1.0/me/', + 'userpicture_endpoint' => 'https://graph.microsoft.com/v1.0/me/photo/$value', + ]; + + foreach ($endpoints as $name => $url) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'name' => $name, + 'url' => $url + ]; + $endpoint = new endpoint(0, $record); + $endpoint->create(); + } + + // Create the field mappings. + $mapping = [ + 'givenName' => 'firstname', + 'surname' => 'lastname', + 'userPrincipalName' => 'email', + 'displayName' => 'alternatename', + 'officeLocation' => 'address', + 'mobilePhone' => 'phone1', + 'preferredLanguage' => 'lang' + ]; + foreach ($mapping as $external => $internal) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'externalfield' => $external, + 'internalfield' => $internal + ]; + $userfieldmapping = new user_field_mapping(0, $record); + $userfieldmapping->create(); + } + return $issuer; + } + + /** + * Build a nextcloud ready OAuth 2 service. + * @return \core\oauth2\issuer + */ + private static function init_nextcloud() { + // Nextcloud has a custom baseurl. Thus, the creation of endpoints has to be done later. + $record = (object) [ + 'name' => 'Nextcloud', + 'image' => 'https://nextcloud.com/wp-content/themes/next/assets/img/common/favicon.png?x16328', + 'basicauth' => 1, + 'servicetype' => 'nextcloud', + ]; + + $issuer = new issuer(0, $record); + + return $issuer; + } + + /** + * Create endpoints for nextcloud issuers. + * @param issuer $issuer issuer the endpoints should be created for. + * @return mixed + * @throws \coding_exception + * @throws \core\invalid_persistent_exception + */ + private static function create_endpoints_for_nextcloud($issuer) { + $baseurl = $issuer->get('baseurl'); + // Add trailing slash to baseurl, if needed. + if (substr($baseurl, -1) !== '/') { + $baseurl .= '/'; + } + + $endpoints = [ + // Baseurl will be prepended later. + 'authorization_endpoint' => 'index.php/apps/oauth2/authorize', + 'token_endpoint' => 'index.php/apps/oauth2/api/v1/token', + 'userinfo_endpoint' => 'ocs/v2.php/cloud/user?format=json', + 'webdav_endpoint' => 'remote.php/webdav/', + 'ocs_endpoint' => 'ocs/v1.php/apps/files_sharing/api/v1/shares', + ]; + + foreach ($endpoints as $name => $url) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'name' => $name, + 'url' => $baseurl . $url, + ]; + $endpoint = new \core\oauth2\endpoint(0, $record); + $endpoint->create(); + } + + // Create the field mappings. + $mapping = [ + 'ocs-data-email' => 'email', + 'ocs-data-id' => 'username', + ]; + foreach ($mapping as $external => $internal) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'externalfield' => $external, + 'internalfield' => $internal + ]; + $userfieldmapping = new \core\oauth2\user_field_mapping(0, $record); + $userfieldmapping->create(); + } + return $issuer; + } + /** * Initializes a record for one of the standard issuers to be displayed in the settings. * The issuer is not yet created in the database. diff --git a/lib/classes/oauth2/discovery/openidconnect.php b/lib/classes/oauth2/discovery/openidconnect.php index f1c58631427..89a475327e3 100644 --- a/lib/classes/oauth2/discovery/openidconnect.php +++ b/lib/classes/oauth2/discovery/openidconnect.php @@ -93,7 +93,6 @@ class openidconnect extends base_definition { 'middle_name' => 'middlename', 'family_name' => 'lastname', 'email' => 'email', - 'website' => 'url', 'nickname' => 'alternatename', 'picture' => 'picture', 'address' => 'address', diff --git a/lib/classes/oauth2/service/facebook.php b/lib/classes/oauth2/service/facebook.php index 92ec1f513d2..9e1e49324bd 100644 --- a/lib/classes/oauth2/service/facebook.php +++ b/lib/classes/oauth2/service/facebook.php @@ -66,7 +66,6 @@ class facebook extends openidconnect implements issuer_interface { 'id', 'first_name', 'last_name', - 'link', 'picture.type(large)', 'name', 'email', @@ -94,7 +93,6 @@ class facebook extends openidconnect implements issuer_interface { 'email' => 'email', 'first_name' => 'firstname', 'picture-data-url' => 'picture', - 'link' => 'url', ]; foreach ($mapping as $external => $internal) { $record = (object) [ diff --git a/lib/classes/user.php b/lib/classes/user.php index 0cb5e4f8a7d..c6dddc67a6a 100644 --- a/lib/classes/user.php +++ b/lib/classes/user.php @@ -69,7 +69,6 @@ class core_user { 'country', 'lang', 'description', - 'url', 'idnumber', 'institution', 'department', @@ -669,11 +668,6 @@ class core_user { $fields['surname'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['email'] = array('type' => PARAM_RAW_TRIMMED, 'null' => NULL_NOT_ALLOWED); $fields['emailstop'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, 'default' => 0); - $fields['icq'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); - $fields['skype'] = array('type' => PARAM_NOTAGS, 'null' => NULL_ALLOWED); - $fields['aim'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); - $fields['yahoo'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); - $fields['msn'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['phone1'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['phone2'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['institution'] = array('type' => PARAM_TEXT, 'null' => NULL_NOT_ALLOWED); @@ -698,7 +692,6 @@ class core_user { $fields['lastip'] = array('type' => PARAM_NOTAGS, 'null' => NULL_NOT_ALLOWED); $fields['secret'] = array('type' => PARAM_ALPHANUM, 'null' => NULL_NOT_ALLOWED); $fields['picture'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); - $fields['url'] = array('type' => PARAM_URL, 'null' => NULL_NOT_ALLOWED); $fields['description'] = array('type' => PARAM_RAW, 'null' => NULL_ALLOWED); $fields['descriptionformat'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED); $fields['mailformat'] = array('type' => PARAM_INT, 'null' => NULL_NOT_ALLOWED, diff --git a/lib/db/install.xml b/lib/db/install.xml index fdeba8596f2..daaa8339731 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -837,11 +837,6 @@ - - - - - @@ -860,7 +855,6 @@ - diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index cb43328e0e0..ecdd8a8b833 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -2560,5 +2560,28 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2021052500.78); } + if ($oldversion < 2021052500.80) { + require_once($CFG->dirroot . '/user/profile/field/social/upgradelib.php'); + $table = new xmldb_table('user'); + $tablecolumns = ['icq', 'skype', 'aim', 'yahoo', 'msn', 'url']; + + foreach ($tablecolumns as $column) { + $field = new xmldb_field($column); + if ($dbman->field_exists($table, $field)) { + user_profile_social_moveto_profilefield($column); + $dbman->drop_field($table, $field); + } + } + + // Update all module availability if it relies on the old user fields. + user_profile_social_update_module_availability(); + + // Remove field mapping for oauth2. + $DB->delete_records('oauth2_user_field_mapping', array('internalfield' => 'url')); + + // Main savepoint reached. + upgrade_main_savepoint(true, 2021052500.80); + } + return true; } diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 6fc92dd9458..b6e9e2f2e63 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -4011,7 +4011,6 @@ function truncate_userinfo(array $info) { 'firstname' => 100, 'lastname' => 100, 'email' => 100, - 'icq' => 15, 'phone1' => 20, 'phone2' => 20, 'institution' => 255, @@ -4019,7 +4018,6 @@ function truncate_userinfo(array $info) { 'address' => 255, 'city' => 120, 'country' => 2, - 'url' => 255, ); // Apply where needed. diff --git a/lib/myprofilelib.php b/lib/myprofilelib.php index da370c899d6..bed91290310 100644 --- a/lib/myprofilelib.php +++ b/lib/myprofilelib.php @@ -219,17 +219,6 @@ function core_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $tree->add_node($node); } - if ($user->url && !isset($hiddenfields['webpage'])) { - $url = $user->url; - if (strpos($user->url, '://') === false) { - $url = 'http://'. $url; - } - $webpageurl = new moodle_url($url); - $node = new core_user\output\myprofile\node('contact', 'webpage', get_string('webpage'), null, null, - html_writer::link($url, $webpageurl)); - $tree->add_node($node); - } - // Printing tagged interests. We want this only for full profile. if (empty($course) && ($interests = core_tag_tag::get_item_tags('core', 'user', $user->id))) { $node = new core_user\output\myprofile\node('contact', 'interests', get_string('interests'), null, null, @@ -334,38 +323,6 @@ function core_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, } } - if ($user->icq && !isset($hiddenfields['icqnumber'])) { - $imurl = new moodle_url('https://web.icq.com/wwp', array('uin' => $user->icq) ); - $iconurl = new moodle_url('https://web.icq.com/whitepages/online', array('icq' => $user->icq, 'img' => '5')); - $statusicon = html_writer::tag('img', '', - array('src' => $iconurl, 'class' => 'icon icon-post', 'alt' => get_string('status'))); - $node = new core_user\output\myprofile\node('contact', 'icqnumber', get_string('icqnumber'), null, null, - html_writer::link($imurl, s($user->icq) . $statusicon)); - $tree->add_node($node); - } - - if ($user->skype && !isset($hiddenfields['skypeid'])) { - $imurl = 'skype:' . urlencode($user->skype) . '?call'; - $node = new core_user\output\myprofile\node('contact', 'skypeid', get_string('skypeid'), null, null, - html_writer::link($imurl, s($user->skype))); - $tree->add_node($node); - } - if ($user->yahoo && !isset($hiddenfields['yahooid'])) { - $node = new core_user\output\myprofile\node('contact', 'yahooid', get_string('yahooid'), null, null, - s($user->yahoo)); - $tree->add_node($node); - } - if ($user->aim && !isset($hiddenfields['aimid'])) { - $node = new core_user\output\myprofile\node('contact', 'aimid', get_string('aimid'), null, null, - s($user->aim)); - $tree->add_node($node); - } - if ($user->msn && !isset($hiddenfields['msnid'])) { - $node = new core_user\output\myprofile\node('contact', 'msnid', get_string('msnid'), null, null, - s($user->msn)); - $tree->add_node($node); - } - $categories = profile_get_user_fields_with_data_by_category($user->id); foreach ($categories as $categoryid => $fields) { foreach ($fields as $formfield) { diff --git a/lib/tests/datalib_test.php b/lib/tests/datalib_test.php index 9f786b6dd38..b81ddefdab6 100644 --- a/lib/tests/datalib_test.php +++ b/lib/tests/datalib_test.php @@ -60,17 +60,11 @@ class core_datalib_testcase extends advanced_testcase { 'address' => '2 Test Street Perth 6000 WA', 'phone1' => '01010101010', 'phone2' => '02020203', - 'icq' => 'testuser1', - 'skype' => 'testuser1', - 'yahoo' => 'testuser1', - 'aim' => 'testuser1', - 'msn' => 'testuser1', 'department' => 'Department of user 1', 'institution' => 'Institution of user 1', 'description' => 'This is a description for user 1', 'descriptionformat' => FORMAT_MOODLE, 'city' => 'Perth', - 'url' => 'http://moodle.org', 'country' => 'AU' ); $user1 = self::getDataGenerator()->create_user($user1); @@ -83,17 +77,11 @@ class core_datalib_testcase extends advanced_testcase { 'address' => '222 Test Street Perth 6000 WA', 'phone1' => '01010101010', 'phone2' => '02020203', - 'icq' => 'testuser1', - 'skype' => 'testuser1', - 'yahoo' => 'testuser1', - 'aim' => 'testuser1', - 'msn' => 'testuser1', 'department' => 'Department of user 2', 'institution' => 'Institution of user 2', 'description' => 'This is a description for user 2', 'descriptionformat' => FORMAT_MOODLE, 'city' => 'Perth', - 'url' => 'http://moodle.org', 'country' => 'AU' ); $user2 = self::getDataGenerator()->create_user($user2); diff --git a/lib/tests/myprofilelib_test.php b/lib/tests/myprofilelib_test.php index 20476c0d695..47cab7d4c37 100644 --- a/lib/tests/myprofilelib_test.php +++ b/lib/tests/myprofilelib_test.php @@ -169,7 +169,7 @@ class core_myprofilelib_testcase extends advanced_testcase { global $CFG; // User contact fields. - set_config("hiddenuserfields", "country,city,webpage,icqnumber,skypeid,yahooid,aimid,msnid"); + set_config("hiddenuserfields", "country,city"); set_config("showuseridentity", "email,address,phone1,phone2,institution,department,idnumber"); $hiddenfields = explode(',', $CFG->hiddenuserfields); $identityfields = explode(',', $CFG->showuseridentity); @@ -180,12 +180,6 @@ class core_myprofilelib_testcase extends advanced_testcase { $fields = array( 'country' => 'AU', 'city' => 'Silent hill', - 'url' => 'Ghosts', - 'icq' => 'Wth is ICQ?', - 'skype' => 'derp', - 'yahoo' => 'are you living in the 90\'s?', - 'aim' => 'are you for real?', - 'msn' => '...', 'email' => 'Rulelikeaboss@example.com', 'address' => 'Didn\'t I mention silent hill already ?', 'phone1' => '123', diff --git a/mod/forum/classes/task/send_user_notifications.php b/mod/forum/classes/task/send_user_notifications.php index d177f6e8a32..1e5efff06db 100644 --- a/mod/forum/classes/task/send_user_notifications.php +++ b/mod/forum/classes/task/send_user_notifications.php @@ -548,7 +548,6 @@ class send_user_notifications extends \core\task\adhoc_task { unset($user->department); unset($user->address); unset($user->city); - unset($user->url); unset($user->currentlogin); unset($user->description); unset($user->descriptionformat); diff --git a/mod/forum/deprecatedlib.php b/mod/forum/deprecatedlib.php index 29f2dc35be6..30345f69c6f 100644 --- a/mod/forum/deprecatedlib.php +++ b/mod/forum/deprecatedlib.php @@ -392,7 +392,6 @@ function forum_cron_minimise_user_record(stdClass $user) { unset($user->department); unset($user->address); unset($user->city); - unset($user->url); unset($user->currentlogin); unset($user->description); unset($user->descriptionformat); diff --git a/mod/url/locallib.php b/mod/url/locallib.php index 8ca4fd26c15..8209620868a 100644 --- a/mod/url/locallib.php +++ b/mod/url/locallib.php @@ -446,7 +446,6 @@ function url_get_variable_options($config) { 'userlastname' => get_string('lastname'), 'userfullname' => get_string('fullnameuser'), 'useremail' => get_string('email'), - 'usericq' => get_string('icqnumber'), 'userphone1' => get_string('phone1'), 'userphone2' => get_string('phone2'), 'userinstitution' => get_string('institution'), @@ -454,7 +453,6 @@ function url_get_variable_options($config) { 'useraddress' => get_string('address'), 'usercity' => get_string('city'), 'usertimezone' => get_string('timezone'), - 'userurl' => get_string('webpage'), ); if ($config->rolesinparams) { @@ -509,7 +507,6 @@ function url_get_variable_values($url, $cm, $course, $config) { $values['userlastname'] = $USER->lastname; $values['userfullname'] = fullname($USER); $values['useremail'] = $USER->email; - $values['usericq'] = $USER->icq; $values['userphone1'] = $USER->phone1; $values['userphone2'] = $USER->phone2; $values['userinstitution'] = $USER->institution; @@ -518,7 +515,6 @@ function url_get_variable_values($url, $cm, $course, $config) { $values['usercity'] = $USER->city; $now = new DateTime('now', core_date::get_user_timezone_object()); $values['usertimezone'] = $now->getOffset() / 3600.0; // Value in hours for BC. - $values['userurl'] = $USER->url; } // weak imitation of Single-Sign-On, for backwards compatibility only diff --git a/user/classes/analytics/indicator/user_profile_set.php b/user/classes/analytics/indicator/user_profile_set.php index 20639ac8417..eee75d3df7c 100644 --- a/user/classes/analytics/indicator/user_profile_set.php +++ b/user/classes/analytics/indicator/user_profile_set.php @@ -90,7 +90,7 @@ class user_profile_set extends \core_analytics\local\indicator\linear { } // 0.2 for any of the following fields being set (some of them may even be compulsory or have a default). - $fields = array('institution', 'department', 'address', 'city', 'country', 'url'); + $fields = array('institution', 'department', 'address', 'city', 'country'); foreach ($fields as $fieldname) { if ($user->{$fieldname} != '') { $calculatedvalue += 0.2; diff --git a/user/classes/privacy/provider.php b/user/classes/privacy/provider.php index 74b28a8bc3a..228142745e2 100644 --- a/user/classes/privacy/provider.php +++ b/user/classes/privacy/provider.php @@ -68,11 +68,6 @@ class provider implements 'lastname' => 'privacy:metadata:lastname', 'email' => 'privacy:metadata:email', 'emailstop' => 'privacy:metadata:emailstop', - 'icq' => 'privacy:metadata:icq', - 'skype' => 'privacy:metadata:skype', - 'yahoo' => 'privacy:metadata:yahoo', - 'aim' => 'privacy:metadata:aim', - 'msn' => 'privacy:metadata:msn', 'phone1' => 'privacy:metadata:phone', 'phone2' => 'privacy:metadata:phone', 'institution' => 'privacy:metadata:institution', @@ -91,7 +86,6 @@ class provider implements 'lastip' => 'privacy:metadata:lastip', 'secret' => 'privacy:metadata:secret', 'picture' => 'privacy:metadata:picture', - 'url' => 'privacy:metadata:url', 'description' => 'privacy:metadata:description', 'maildigest' => 'privacy:metadata:maildigest', 'maildisplay' => 'privacy:metadata:maildisplay', @@ -309,11 +303,6 @@ class provider implements $user->deleted = 1; $user->idnumber = ''; $user->emailstop = 0; - $user->icq = ''; - $user->skype = ''; - $user->yahoo = ''; - $user->aim = ''; - $user->msn = ''; $user->phone1 = ''; $user->phone2 = ''; $user->institution = ''; @@ -332,7 +321,6 @@ class provider implements $user->lastip = 0; $user->secret = ''; $user->picture = ''; - $user->url = ''; $user->description = ''; $user->descriptionformat = 0; $user->mailformat = 0; @@ -370,11 +358,6 @@ class provider implements 'lastname' => format_string($user->lastname, true, ['context' => $context]), 'email' => $user->email, 'emailstop' => transform::yesno($user->emailstop), - 'icq' => format_string($user->icq, true, ['context' => $context]), - 'skype' => format_string($user->skype, true, ['context' => $context]), - 'yahoo' => format_string($user->yahoo, true, ['context' => $context]), - 'aim' => format_string($user->aim, true, ['context' => $context]), - 'msn' => format_string($user->msn, true, ['context' => $context]), 'phone1' => format_string($user->phone1, true, ['context' => $context]), 'phone2' => format_string($user->phone2, true, ['context' => $context]), 'institution' => format_string($user->institution, true, ['context' => $context]), @@ -393,7 +376,6 @@ class provider implements 'lastip' => $user->lastip, 'secret' => $user->secret, 'picture' => $user->picture, - 'url' => $user->url, 'description' => format_text($user->description, $user->descriptionformat, ['context' => $context]), 'maildigest' => transform::yesno($user->maildigest), 'maildisplay' => $user->maildisplay, diff --git a/user/editlib.php b/user/editlib.php index 8d407d5859b..06940bf8ab0 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -394,29 +394,6 @@ function useredit_shared_definition(&$mform, $editoroptions, $filemanageroptions // Moodle optional fields. $mform->addElement('header', 'moodle_optional', get_string('optional', 'form')); - $mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"'); - $mform->setType('url', core_user::get_property_type('url')); - - $mform->addElement('text', 'icq', get_string('icqnumber'), 'maxlength="15" size="25"'); - $mform->setType('icq', core_user::get_property_type('icq')); - $mform->setForceLtr('icq'); - - $mform->addElement('text', 'skype', get_string('skypeid'), 'maxlength="50" size="25"'); - $mform->setType('skype', core_user::get_property_type('skype')); - $mform->setForceLtr('skype'); - - $mform->addElement('text', 'aim', get_string('aimid'), 'maxlength="50" size="25"'); - $mform->setType('aim', core_user::get_property_type('aim')); - $mform->setForceLtr('aim'); - - $mform->addElement('text', 'yahoo', get_string('yahooid'), 'maxlength="50" size="25"'); - $mform->setType('yahoo', core_user::get_property_type('yahoo')); - $mform->setForceLtr('yahoo'); - - $mform->addElement('text', 'msn', get_string('msnid'), 'maxlength="50" size="25"'); - $mform->setType('msn', core_user::get_property_type('msn')); - $mform->setForceLtr('msn'); - $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"'); $mform->setType('idnumber', core_user::get_property_type('idnumber')); diff --git a/user/externallib.php b/user/externallib.php index 90c9bd423db..86381b25fea 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -79,12 +79,6 @@ class core_user_external extends external_api { // Interests. 'interests' => new external_value(PARAM_TEXT, 'User interests (separated by commas)', VALUE_OPTIONAL), // Optional. - 'url' => new external_value(core_user::get_property_type('url'), 'User web page', VALUE_OPTIONAL), - 'icq' => new external_value(core_user::get_property_type('icq'), 'ICQ number', VALUE_OPTIONAL), - 'skype' => new external_value(core_user::get_property_type('skype'), 'Skype ID', VALUE_OPTIONAL), - 'aim' => new external_value(core_user::get_property_type('aim'), 'AIM ID', VALUE_OPTIONAL), - 'yahoo' => new external_value(core_user::get_property_type('yahoo'), 'Yahoo ID', VALUE_OPTIONAL), - 'msn' => new external_value(core_user::get_property_type('msn'), 'MSN ID', VALUE_OPTIONAL), 'idnumber' => new external_value(core_user::get_property_type('idnumber'), 'An arbitrary ID code number perhaps from the institution', VALUE_DEFAULT, ''), 'institution' => new external_value(core_user::get_property_type('institution'), 'institution', VALUE_OPTIONAL), @@ -503,12 +497,6 @@ class core_user_external extends external_api { // Interests. 'interests' => new external_value(PARAM_TEXT, 'User interests (separated by commas)', VALUE_OPTIONAL), // Optional. - 'url' => new external_value(core_user::get_property_type('url'), 'User web page', VALUE_OPTIONAL), - 'icq' => new external_value(core_user::get_property_type('icq'), 'ICQ number', VALUE_OPTIONAL), - 'skype' => new external_value(core_user::get_property_type('skype'), 'Skype ID', VALUE_OPTIONAL), - 'aim' => new external_value(core_user::get_property_type('aim'), 'AIM ID', VALUE_OPTIONAL), - 'yahoo' => new external_value(core_user::get_property_type('yahoo'), 'Yahoo ID', VALUE_OPTIONAL), - 'msn' => new external_value(core_user::get_property_type('msn'), 'MSN ID', VALUE_OPTIONAL), 'idnumber' => new external_value(core_user::get_property_type('idnumber'), 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), 'institution' => new external_value(core_user::get_property_type('institution'), 'Institution', VALUE_OPTIONAL), @@ -1093,11 +1081,6 @@ class core_user_external extends external_api { 'address' => new external_value(core_user::get_property_type('address'), 'Postal address', VALUE_OPTIONAL), 'phone1' => new external_value(core_user::get_property_type('phone1'), 'Phone 1', VALUE_OPTIONAL), 'phone2' => new external_value(core_user::get_property_type('phone2'), 'Phone 2', VALUE_OPTIONAL), - 'icq' => new external_value(core_user::get_property_type('icq'), 'icq number', VALUE_OPTIONAL), - 'skype' => new external_value(core_user::get_property_type('skype'), 'skype id', VALUE_OPTIONAL), - 'yahoo' => new external_value(core_user::get_property_type('yahoo'), 'yahoo id', VALUE_OPTIONAL), - 'aim' => new external_value(core_user::get_property_type('aim'), 'aim id', VALUE_OPTIONAL), - 'msn' => new external_value(core_user::get_property_type('msn'), 'msn number', VALUE_OPTIONAL), 'department' => new external_value(core_user::get_property_type('department'), 'department', VALUE_OPTIONAL), 'institution' => new external_value(core_user::get_property_type('institution'), 'institution', VALUE_OPTIONAL), 'idnumber' => new external_value(core_user::get_property_type('idnumber'), 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), @@ -1115,7 +1098,6 @@ class core_user_external extends external_api { 'description' => new external_value(core_user::get_property_type('description'), 'User profile description', VALUE_OPTIONAL), 'descriptionformat' => new external_format_value(core_user::get_property_type('descriptionformat'), VALUE_OPTIONAL), 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user', VALUE_OPTIONAL), - 'url' => new external_value(core_user::get_property_type('url'), 'URL of the user', VALUE_OPTIONAL), 'country' => new external_value(core_user::get_property_type('country'), 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'), 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'), diff --git a/user/lib.php b/user/lib.php index 3809b8170a3..6332648c790 100644 --- a/user/lib.php +++ b/user/lib.php @@ -242,10 +242,10 @@ function user_get_users_by_id($userids) { */ function user_get_default_fields() { return array( 'id', 'username', 'fullname', 'firstname', 'lastname', 'email', - 'address', 'phone1', 'phone2', 'icq', 'skype', 'yahoo', 'aim', 'msn', 'department', + 'address', 'phone1', 'phone2', 'department', 'institution', 'interests', 'firstaccess', 'lastaccess', 'auth', 'confirmed', 'idnumber', 'lang', 'theme', 'timezone', 'mailformat', 'description', 'descriptionformat', - 'city', 'url', 'country', 'profileimageurlsmall', 'profileimageurl', 'customfields', + 'city', 'country', 'profileimageurlsmall', 'profileimageurl', 'customfields', 'groups', 'roles', 'preferences', 'enrolledcourses', 'suspended', 'lastcourseaccess' ); } @@ -429,31 +429,6 @@ function user_get_user_details($user, $course = null, array $userfields = array( $userdetails['city'] = $user->city; } - if (in_array('url', $userfields) && $user->url && (!isset($hiddenfields['webpage']) or $isadmin)) { - $url = $user->url; - if (strpos($user->url, '://') === false) { - $url = 'http://'. $url; - } - $user->url = clean_param($user->url, PARAM_URL); - $userdetails['url'] = $user->url; - } - - if (in_array('icq', $userfields) && $user->icq && (!isset($hiddenfields['icqnumber']) or $isadmin)) { - $userdetails['icq'] = $user->icq; - } - - if (in_array('skype', $userfields) && $user->skype && (!isset($hiddenfields['skypeid']) or $isadmin)) { - $userdetails['skype'] = $user->skype; - } - if (in_array('yahoo', $userfields) && $user->yahoo && (!isset($hiddenfields['yahooid']) or $isadmin)) { - $userdetails['yahoo'] = $user->yahoo; - } - if (in_array('aim', $userfields) && $user->aim && (!isset($hiddenfields['aimid']) or $isadmin)) { - $userdetails['aim'] = $user->aim; - } - if (in_array('msn', $userfields) && $user->msn && (!isset($hiddenfields['msnid']) or $isadmin)) { - $userdetails['msn'] = $user->msn; - } if (in_array('suspended', $userfields) && (!isset($hiddenfields['suspended']) or $isadmin)) { $userdetails['suspended'] = (bool)$user->suspended; } diff --git a/user/profile/field/social/classes/helper.php b/user/profile/field/social/classes/helper.php new file mode 100644 index 00000000000..677e2eb2025 --- /dev/null +++ b/user/profile/field/social/classes/helper.php @@ -0,0 +1,74 @@ +. + +/** + * Contains class profilefield_social\networks + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace profilefield_social; + +/** + * helper class for social profile fields. + * + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class helper { + + /** + * Get the available social networks + * + * @return array list of social networks. + */ + public static function get_networks(): array { + return [ + 'icq' => get_string('icqnumber', 'profilefield_social'), + 'msn' => get_string('msnid', 'profilefield_social'), + 'aim' => get_string('aimid', 'profilefield_social'), + 'yahoo' => get_string('yahooid', 'profilefield_social'), + 'skype' => get_string('skypeid', 'profilefield_social'), + 'url' => get_string('webpage', 'profilefield_social'), + ]; + } + + /** + * Get the translated fieldname string for a network. + * + * @param string $fieldname Network short name. + * @return string network name. + */ + public static function get_fieldname(string $fieldname): string { + $networks = self::get_networks(); + return $networks[$fieldname]; + } + + /** + * Get the available network url formats. + * + * @return array list network url strings. + */ + public static function get_network_urls(): array { + return [ + 'skype' => '%%DATA%%', + 'icq' => '%%DATA%%', + 'url' => '%%DATA%%' + ]; + } +} diff --git a/user/profile/field/social/classes/privacy/provider.php b/user/profile/field/social/classes/privacy/provider.php new file mode 100644 index 00000000000..8c3c458c21a --- /dev/null +++ b/user/profile/field/social/classes/privacy/provider.php @@ -0,0 +1,214 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace profilefield_social\privacy; + +defined('MOODLE_INTERNAL') || die(); + +use \core_privacy\local\metadata\collection; +use \core_privacy\local\request\contextlist; +use \core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\userlist; +use core_privacy\local\request\approved_userlist; + +/** + * Privacy class for requesting user data. + * + * @copyright 2018 Mihail Geshoski + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements + \core_privacy\local\metadata\provider, + \core_privacy\local\request\core_userlist_provider, + \core_privacy\local\request\plugin\provider { + + /** + * Returns meta data about this system. + * + * @param collection $collection The initialised collection to add items to. + * @return collection A listing of user data stored through this system. + */ + public static function get_metadata(collection $collection) : collection { + return $collection->add_database_table('user_info_data', [ + 'userid' => 'privacy:metadata:profile_field_social:userid', + 'fieldid' => 'privacy:metadata:profile_field_social:fieldid', + 'data' => 'privacy:metadata:profile_field_social:data', + 'dataformat' => 'privacy:metadata:profile_field_social:dataformat' + ], 'privacy:metadata:profile_field_social:tableexplanation'); + } + + /** + * Get the list of contexts that contain user information for the specified user. + * + * @param int $userid The user to search. + * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. + */ + public static function get_contexts_for_userid(int $userid) : contextlist { + $sql = "SELECT ctx.id + FROM {user_info_data} uda + JOIN {user_info_field} uif ON uda.fieldid = uif.id + JOIN {context} ctx ON ctx.instanceid = uda.userid + AND ctx.contextlevel = :contextlevel + WHERE uda.userid = :userid + AND uif.datatype = :datatype"; + $params = [ + 'userid' => $userid, + 'contextlevel' => CONTEXT_USER, + 'datatype' => 'social' + ]; + $contextlist = new contextlist(); + $contextlist->add_from_sql($sql, $params); + + return $contextlist; + } + + /** + * Get the list of users within a specific context. + * + * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. + */ + public static function get_users_in_context(userlist $userlist) { + $context = $userlist->get_context(); + + if (!$context instanceof \context_user) { + return; + } + + $sql = "SELECT uda.userid + FROM {user_info_data} uda + JOIN {user_info_field} uif + ON uda.fieldid = uif.id + WHERE uda.userid = :userid + AND uif.datatype = :datatype"; + + $params = [ + 'userid' => $context->instanceid, + 'datatype' => 'social' + ]; + + $userlist->add_from_sql('userid', $sql, $params); + } + + /** + * Export all user data for the specified user, in the specified contexts. + * + * @param approved_contextlist $contextlist The approved contexts to export information for. + */ + public static function export_user_data(approved_contextlist $contextlist) { + $user = $contextlist->get_user(); + foreach ($contextlist->get_contexts() as $context) { + // Check if the context is a user context. + if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $user->id) { + $results = static::get_records($user->id); + foreach ($results as $result) { + $data = (object) [ + 'name' => $result->name, + 'description' => $result->description, + 'data' => $result->data + ]; + \core_privacy\local\request\writer::with_context($context)->export_data([ + get_string('pluginname', 'profilefield_social')], $data); + } + } + } + } + + /** + * Delete all user data which matches the specified context. + * + * @param context $context A user context. + */ + public static function delete_data_for_all_users_in_context(\context $context) { + // Delete data only for user context. + if ($context->contextlevel == CONTEXT_USER) { + static::delete_data($context->instanceid); + } + } + + /** + * Delete multiple users within a single context. + * + * @param approved_userlist $userlist The approved context and user information to delete information for. + */ + public static function delete_data_for_users(approved_userlist $userlist) { + $context = $userlist->get_context(); + + if ($context instanceof \context_user) { + static::delete_data($context->instanceid); + } + } + + /** + * Delete all user data for the specified user, in the specified contexts. + * + * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. + */ + public static function delete_data_for_user(approved_contextlist $contextlist) { + $user = $contextlist->get_user(); + foreach ($contextlist->get_contexts() as $context) { + // Check if the context is a user context. + if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $user->id) { + static::delete_data($context->instanceid); + } + } + } + + /** + * Delete data related to a userid. + * + * @param int $userid The user ID + */ + protected static function delete_data($userid) { + global $DB; + $params = [ + 'userid' => $userid, + 'datatype' => 'social' + ]; + + $DB->delete_records_select('user_info_data', "fieldid IN ( + SELECT id FROM {user_info_field} WHERE datatype = :datatype) + AND userid = :userid", $params); + } + + /** + * Get records related to this plugin and user. + * + * @param int $userid The user ID + * @return array An array of records. + */ + protected static function get_records($userid) { + global $DB; + $sql = "SELECT * + FROM {user_info_data} uda + JOIN {user_info_field} uif ON uda.fieldid = uif.id + WHERE uda.userid = :userid + AND uif.datatype = :datatype"; + $params = [ + 'userid' => $userid, + 'datatype' => 'social' + ]; + + return $DB->get_records_sql($sql, $params); + } +} diff --git a/user/profile/field/social/define.class.php b/user/profile/field/social/define.class.php new file mode 100644 index 00000000000..61a02fc4b8e --- /dev/null +++ b/user/profile/field/social/define.class.php @@ -0,0 +1,95 @@ +. + +/** + * Textarea profile field define. + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Class profile_define_social. + * + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class profile_define_social extends profile_define_base { + + /** + * Prints out the form snippet for the part of creating or editing a profile field common to all data types. + * + * @param moodleform $form instance of the moodleform class + */ + public function define_form_common(&$form) { + $availablenetworks = profilefield_social\helper::get_networks(); + $networks = array_merge(['0' => get_string('select')], $availablenetworks); + + $form->addElement('hidden', 'defaultdata', ''); + $form->setType('defaultdata', PARAM_TEXT); + + $form->addElement('select', 'param1', get_string('networktype', 'profilefield_social'), $networks); + $form->addRule('param1', get_string('required'), 'required', null, 'client'); + $form->setType('param1', PARAM_TEXT); + + parent::define_form_common($form); + $form->removeElement('name'); + } + + /** + * Alter form based on submitted or existing data. + * + * @param moodleform $form + */ + public function define_after_data(&$form) { + if (isset($form->_defaultValues['name'])) { + $form->setDefault('param1', $form->_defaultValues['name']); + } + } + + /** + * 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 stdClass|array $data from the add/edit profile field form + * @param array $files + * @return array associative array of error messages + */ + public function define_validate_common($data, $files) { + $err = parent::define_validate_common($data, $files); + + $networks = profilefield_social\helper::get_networks(); + if (empty($data->param1) || !array_key_exists($data->param1, $networks)) { + $err['param1'] = get_string('invalidnetwork', 'profilefield_social'); + } + return $err; + } + + /** + * 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 array|stdClass $data from the add/edit profile field form + * @return array|stdClass processed data object + */ + public function define_save_preprocess($data) { + $data->name = $data->param1; + return $data; + } +} diff --git a/user/profile/field/social/field.class.php b/user/profile/field/social/field.class.php new file mode 100644 index 00000000000..ad44f233e8d --- /dev/null +++ b/user/profile/field/social/field.class.php @@ -0,0 +1,84 @@ +. + +/** + * Social profile field define. + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Class profile_field_social. + * + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class profile_field_social extends profile_field_base { + + /** + * Adds elements for this field type to the edit form. + * @param moodleform $mform + */ + public function edit_field_add($mform) { + $mform->addElement('text', $this->inputname, $this->field->name, null, null); + if ($this->field->param1 === 'url') { + $mform->setType($this->inputname, PARAM_URL); + } else { + $mform->setType($this->inputname, PARAM_NOTAGS); + } + } + + /** + * alter the fieldname to be fetched from the language file. + * + * @param stdClass $field + */ + public function set_field($field) { + $networks = profilefield_social\helper::get_networks(); + $field->name = $networks[$field->name]; + parent::set_field($field); + } + + /** + * Display the data for this field + * @return string + */ + public function display_data() { + $network = $this->field->param1; + $networkurls = profilefield_social\helper::get_network_urls(); + + if (array_key_exists($network, $networkurls)) { + return str_replace('%%DATA%%', $this->data, $networkurls[$network]); + } + + return $this->data; + } + + /** + * Return the field type and null properties. + * This will be used for validating the data submitted by a user. + * + * @return array the param type and null property + * @since Moodle 3.2 + */ + public function get_field_properties() { + return array(PARAM_TEXT, NULL_NOT_ALLOWED); + } +} + + diff --git a/user/profile/field/social/lang/en/profilefield_social.php b/user/profile/field/social/lang/en/profilefield_social.php new file mode 100644 index 00000000000..8c90e6f5c86 --- /dev/null +++ b/user/profile/field/social/lang/en/profilefield_social.php @@ -0,0 +1,39 @@ +. + +/** + * Strings for component 'profilefield_social' + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['invalidnetwork'] = 'Invalid social network'; +$string['networkinuse'] = 'Social network has already been added'; +$string['pluginname'] = 'Social'; +$string['networktype'] = 'Networktype'; +$string['privacy:metadata:profile_field_social:data'] = 'Text area user profile field user data'; +$string['privacy:metadata:profile_field_social:dataformat'] = 'The format of Text area user profile field user data'; +$string['privacy:metadata:profile_field_social:fieldid'] = 'The ID of the profile field'; +$string['privacy:metadata:profile_field_social:tableexplanation'] = 'Additional profile data'; +$string['privacy:metadata:profile_field_social:userid'] = 'The ID of the user whose data is stored by the social user profile field'; +$string['aimid'] = 'AIM ID'; +$string['yahooid'] = 'Yahoo ID'; +$string['skypeid'] = 'Skype ID'; +$string['icqnumber'] = 'ICQ number'; +$string['msnid'] = 'MSN ID'; +$string['webpage'] = 'Web page'; diff --git a/user/profile/field/social/tests/privacy_test.php b/user/profile/field/social/tests/privacy_test.php new file mode 100644 index 00000000000..4c336f04b32 --- /dev/null +++ b/user/profile/field/social/tests/privacy_test.php @@ -0,0 +1,312 @@ +. + +/** + * Base class for unit tests for profilefield_social. + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use \core_privacy\tests\provider_testcase; +use profilefield_social\privacy\provider; +use core_privacy\local\request\approved_userlist; + +/** + * Unit tests for user\profile\field\social\classes\privacy\provider.php + * + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class profilefield_social_testcase extends provider_testcase { + + /** + * Basic setup for these tests. + */ + public function setUp(): void { + $this->resetAfterTest(true); + } + + /** + * Test getting the context for the user ID related to this plugin. + */ + public function test_get_contexts_for_userid() { + global $DB; + // Create profile category. + $categoryid = $this->add_profile_category(); + // Create profile field. + $profilefieldid = $this->add_profile_field($categoryid, 'social'); + // Create a user. + $user = $this->getDataGenerator()->create_user(); + $this->add_user_info_data($user->id, $profilefieldid, 'test data'); + // Get the field that was created. + $userfielddata = $DB->get_records('user_info_data', array('userid' => $user->id)); + // Confirm we got the right number of user field data. + $this->assertCount(1, $userfielddata); + $context = context_user::instance($user->id); + $contextlist = provider::get_contexts_for_userid($user->id); + $this->assertEquals($context, $contextlist->current()); + } + + /** + * Test that data is exported correctly for this plugin. + */ + public function test_export_user_data() { + // Create profile category. + $categoryid = $this->add_profile_category(); + // Create social profile field. + $socialprofilefieldid = $this->add_profile_field($categoryid, 'social'); + // Create checkbox profile field. + $checkboxprofilefieldid = $this->add_profile_field($categoryid, 'checkbox'); + // Create a user. + $user = $this->getDataGenerator()->create_user(); + $context = context_user::instance($user->id); + // Add social user info data. + $this->add_user_info_data($user->id, $socialprofilefieldid, '#icq-1294923'); + // Add checkbox user info data. + $this->add_user_info_data($user->id, $checkboxprofilefieldid, 'test data'); + $writer = \core_privacy\local\request\writer::with_context($context); + $this->assertFalse($writer->has_any_data()); + $this->export_context_data_for_user($user->id, $context, 'profilefield_social'); + $data = $writer->get_data([get_string('pluginname', 'profilefield_social')]); + $this->assertCount(3, (array) $data); + $this->assertEquals('icq', $data->name); + $this->assertEquals('', $data->description); + $this->assertEquals('#icq-1294923', $data->data); + } + + /** + * Test that user data is deleted using the context. + */ + public function test_delete_data_for_all_users_in_context() { + global $DB; + // Create profile category. + $categoryid = $this->add_profile_category(); + // Create social profile field. + $socialprofilefieldid = $this->add_profile_field($categoryid, 'social'); + // Create checkbox profile field. + $checkboxprofilefieldid = $this->add_profile_field($categoryid, 'checkbox'); + // Create a user. + $user = $this->getDataGenerator()->create_user(); + $context = context_user::instance($user->id); + // Add social user info data. + $this->add_user_info_data($user->id, $socialprofilefieldid, '#icq-1294923'); + // Add checkbox user info data. + $this->add_user_info_data($user->id, $checkboxprofilefieldid, 'test data'); + // Check that we have two entries. + $userinfodata = $DB->get_records('user_info_data', ['userid' => $user->id]); + $this->assertCount(2, $userinfodata); + provider::delete_data_for_all_users_in_context($context); + // Check that the correct profile field has been deleted. + $userinfodata = $DB->get_records('user_info_data', ['userid' => $user->id]); + $this->assertCount(1, $userinfodata); + $this->assertNotEquals('#icq-1294923', reset($userinfodata)->data); + } + + /** + * Test that user data is deleted for this user. + */ + public function test_delete_data_for_user() { + global $DB; + // Create profile category. + $categoryid = $this->add_profile_category(); + // Create social profile field. + $socialprofilefieldid = $this->add_profile_field($categoryid, 'social'); + // Create checkbox profile field. + $checkboxprofilefieldid = $this->add_profile_field($categoryid, 'checkbox'); + // Create a user. + $user = $this->getDataGenerator()->create_user(); + $context = context_user::instance($user->id); + // Add social user info data. + $this->add_user_info_data($user->id, $socialprofilefieldid, '#icq-1294923'); + // Add checkbox user info data. + $this->add_user_info_data($user->id, $checkboxprofilefieldid, 'test data'); + // Check that we have two entries. + $userinfodata = $DB->get_records('user_info_data', ['userid' => $user->id]); + $this->assertCount(2, $userinfodata); + $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'profilefield_social', + [$context->id]); + provider::delete_data_for_user($approvedlist); + // Check that the correct profile field has been deleted. + $userinfodata = $DB->get_records('user_info_data', ['userid' => $user->id]); + $this->assertCount(1, $userinfodata); + $this->assertNotEquals('#icq-1294923', reset($userinfodata)->data); + } + + /** + * Test that only users with a user context are fetched. + */ + public function test_get_users_in_context() { + $this->resetAfterTest(); + + $component = 'profilefield_social'; + // Create profile category. + $categoryid = $this->add_profile_category(); + // Create profile field. + $profilefieldid = $this->add_profile_field($categoryid, 'social'); + + // Create a user. + $user = $this->getDataGenerator()->create_user(); + $usercontext = context_user::instance($user->id); + // The list of users should not return anything yet (related data still haven't been created). + $userlist = new \core_privacy\local\request\userlist($usercontext, $component); + provider::get_users_in_context($userlist); + $this->assertCount(0, $userlist); + + $this->add_user_info_data($user->id, $profilefieldid, 'test data'); + + // The list of users for user context should return the user. + provider::get_users_in_context($userlist); + $this->assertCount(1, $userlist); + $expected = [$user->id]; + $actual = $userlist->get_userids(); + $this->assertEquals($expected, $actual); + + // The list of users for system context should not return any users. + $systemcontext = context_system::instance(); + $userlist = new \core_privacy\local\request\userlist($systemcontext, $component); + provider::get_users_in_context($userlist); + $this->assertCount(0, $userlist); + } + + /** + * Test that data for users in approved userlist is deleted. + */ + public function test_delete_data_for_users() { + $this->resetAfterTest(); + + $component = 'profilefield_social'; + // Create profile category. + $categoryid = $this->add_profile_category(); + // Create profile field. + $profilefieldid = $this->add_profile_field($categoryid, 'social'); + + // Create user1. + $user1 = $this->getDataGenerator()->create_user(); + $usercontext1 = context_user::instance($user1->id); + // Create user2. + $user2 = $this->getDataGenerator()->create_user(); + $usercontext2 = context_user::instance($user2->id); + + $this->add_user_info_data($user1->id, $profilefieldid, 'test data'); + $this->add_user_info_data($user2->id, $profilefieldid, 'test data'); + + // The list of users for usercontext1 should return user1. + $userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component); + provider::get_users_in_context($userlist1); + $this->assertCount(1, $userlist1); + $expected = [$user1->id]; + $actual = $userlist1->get_userids(); + $this->assertEquals($expected, $actual); + + // The list of users for usercontext2 should return user2. + $userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component); + provider::get_users_in_context($userlist2); + $this->assertCount(1, $userlist2); + $expected = [$user2->id]; + $actual = $userlist2->get_userids(); + $this->assertEquals($expected, $actual); + + // Add userlist1 to the approved user list. + $approvedlist = new approved_userlist($usercontext1, $component, $userlist1->get_userids()); + + // Delete user data using delete_data_for_user for usercontext1. + provider::delete_data_for_users($approvedlist); + + // Re-fetch users in usercontext1 - The user list should now be empty. + $userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component); + provider::get_users_in_context($userlist1); + $this->assertCount(0, $userlist1); + + // Re-fetch users in usercontext2 - The user list should not be empty (user2). + $userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component); + provider::get_users_in_context($userlist2); + $this->assertCount(1, $userlist2); + + // User data should be only removed in the user context. + $systemcontext = context_system::instance(); + // Add userlist2 to the approved user list in the system context. + $approvedlist = new approved_userlist($systemcontext, $component, $userlist2->get_userids()); + // Delete user1 data using delete_data_for_user. + provider::delete_data_for_users($approvedlist); + // Re-fetch users in usercontext2 - The user list should not be empty (user2). + $userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component); + provider::get_users_in_context($userlist1); + $this->assertCount(1, $userlist1); + } + + /** + * Add dummy user info data. + * + * @param int $userid The ID of the user + * @param int $fieldid The ID of the field + * @param string $data The data + */ + private function add_user_info_data($userid, $fieldid, $data) { + global $DB; + $userinfodata = array( + 'userid' => $userid, + 'fieldid' => $fieldid, + 'data' => $data, + 'dataformat' => 0 + ); + + $DB->insert_record('user_info_data', $userinfodata); + } + + /** + * Add dummy profile category. + * + * @return int The ID of the profile category + */ + private function add_profile_category() { + global $DB; + // Create a new profile category. + $cat = new stdClass(); + $cat->name = 'Test category'; + $cat->sortorder = 1; + + return $DB->insert_record('user_info_category', $cat); + } + + /** + * Add dummy profile field. + * + * @param int $categoryid The ID of the profile category + * @param string $datatype The datatype of the profile field + * @return int The ID of the profile field + */ + private function add_profile_field($categoryid, $datatype) { + global $DB; + // Create a new profile field. + $data = new stdClass(); + $data->datatype = $datatype; + $data->shortname = 'icq'; + $data->name = 'icq'; + $data->description = ''; + $data->required = false; + $data->locked = false; + $data->forceunique = false; + $data->signup = false; + $data->visible = '0'; + $data->categoryid = $categoryid; + + return $DB->insert_record('user_info_field', $data); + } +} diff --git a/user/profile/field/social/upgradelib.php b/user/profile/field/social/upgradelib.php new file mode 100644 index 00000000000..23387180ef8 --- /dev/null +++ b/user/profile/field/social/upgradelib.php @@ -0,0 +1,187 @@ +. + +/** + * Contains upgrade and install functions for the social profile fields. + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once("$CFG->dirroot/user/profile/definelib.php"); + +/** + * Create the default category for custom profile fields if it does not exist yet. + */ +function user_profile_social_create_info_category() { + global $DB; + + $categories = $DB->get_records('user_info_category', null, 'sortorder ASC'); + // Check that we have at least one category defined. + if (empty($categories)) { + $defaultcategory = (object) [ + 'name' => get_string('profiledefaultcategory', 'admin'), + 'sortorder' => 1 + ]; + $DB->insert_record('user_info_category', $defaultcategory); + } +} + +/** + * Called on upgrade to create new profile fields based on the old user table columns + * for icq, msn, aim, skype and url. + * + * @param string $social Social profile field. + */ +function user_profile_social_moveto_profilefield($social) { + global $DB; + + $users = $DB->get_records_select('user', "$social IS NOT NULL AND $social != ''"); + if (count($users)) { + $profilefield = user_profile_social_create_profilefield($social); + foreach ($users as $user) { + $userinfodata = [ + 'userid' => $user->id, + 'fieldid' => $profilefield->id, + 'data' => $user->$social, + 'dataformat' => 0 + ]; + $user->$social = ''; + $DB->update_record('user', $user); + $DB->insert_record('user_info_data', $userinfodata); + } + } +} + +/** + * Create an new custom social profile field if it does not exist + * + * @param string $social Social profile field. + * @return object DB record or social profield field. + */ +function user_profile_social_create_profilefield($social) { + global $DB, $CFG; + + $hiddenfields = explode(',', $CFG->hiddenuserfields); + $confignames = [ + 'url' => 'webpage', + 'icq' => 'icqnumber', + 'skype' => 'skypeid', + 'yahoo' => 'yahooid', + 'aim' => 'aimid', + 'msn' => 'msnid', + ]; + $visible = (in_array($confignames[$social], $hiddenfields)) ? 3 : 2; + + $newfield = (object)[ + 'shortname' => $social, + 'name' => $social, + 'datatype' => 'social', + 'description' => '', + 'descriptionformat' => 1, + 'categoryid' => 1, + 'required' => 0, + 'locked' => 0, + 'visible' => $visible, + 'forceunique' => 0, + 'signup' => 0, + 'defaultdata' => '', + 'defaultdataformat' => 0, + 'param1' => $social + ]; + + user_profile_social_create_info_category(); + + $profilefield = $DB->get_record_sql( + 'SELECT * FROM {user_info_field} WHERE datatype = :datatype AND ' . + $DB->sql_compare_text('param1') . ' = ' . $DB->sql_compare_text(':social', 40), + ['datatype' => 'social', 'social' => $social]); + + if (!$profilefield) { + + // Find a new unique shortname. + $count = 0; + $shortname = $newfield->shortname; + while ($field = $DB->get_record('user_info_field', array('shortname' => $shortname))) { + $count++; + $shortname = $newfield->shortname . '_' . $count; + } + $newfield->shortname = $shortname; + + $profileclass = new profile_define_base(); + $profileclass->define_save($newfield); + profile_reorder_fields(); + + $profilefield = $DB->get_record_sql( + 'SELECT * FROM {user_info_field} WHERE datatype = :datatype AND ' . + $DB->sql_compare_text('param1') . ' = ' . $DB->sql_compare_text(':social', 40), + ['datatype' => 'social', 'social' => $social]); + } + if (!$profilefield) { + throw new moodle_exception('upgradeerror', 'admin', 'could not create new social profile field'); + } + return $profilefield; +} + +/** + * Update the module availability configuration for all course modules + * + */ +function user_profile_social_update_module_availability() { + global $DB; + $modules = $DB->get_records('course_modules'); + foreach ($modules as $mod) { + if (isset($mod->availability)) { + $availability = json_decode($mod->availability); + if (!is_null($availability)) { + user_profile_social_update_availability_structure($availability); + $newavailability = json_encode($availability); + if ($newavailability !== $mod->availability) { + $mod->availability = json_encode($availability); + $DB->update_record('course_modules', $mod); + } + } + } + } +} + +/** + * Loop through the availability info and change all move standard profile + * fields for icq, skype, aim, yahoo, msn and url to be custom profile fields. + * @param mixed $structure The availability object. + */ +function user_profile_social_update_availability_structure(&$structure) { + if (is_array($structure)) { + foreach ($structure as $st) { + user_profile_social_update_availability_structure($st); + } + } + foreach ($structure as $key => $value) { + if ($key === 'c' && is_array($value)) { + user_profile_social_update_availability_structure($value); + } + if ($key === 'type' && $value === 'profile') { + if (isset($structure->sf) && in_array($structure->sf, + ['icq', 'skype', 'aim', 'yahoo', 'msn', 'url'])) { + $structure->cf = $structure->sf; + unset($structure->sf); + } + } + } +} \ No newline at end of file diff --git a/user/profile/field/social/version.php b/user/profile/field/social/version.php new file mode 100644 index 00000000000..1587c1388ff --- /dev/null +++ b/user/profile/field/social/version.php @@ -0,0 +1,29 @@ +. + +/** + * Version information for the social profile field. + * + * @package profilefield_social + * @copyright 2020 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2021052500; +$plugin->requires = 2021020400; +$plugin->component = 'profilefield_social'; diff --git a/user/profile/index.php b/user/profile/index.php index 799980c875f..ae55294ed12 100644 --- a/user/profile/index.php +++ b/user/profile/index.php @@ -134,7 +134,13 @@ foreach ($categories as $category) { if ($fields = $DB->get_records('user_info_field', array('categoryid' => $category->id), 'sortorder ASC')) { foreach ($fields as $field) { - $table->data[] = array(format_string($field->name), profile_field_icons($field)); + $fieldname = format_string($field->name); + $component = 'profilefield_' . $field->datatype; + $classname = "\\$component\\helper"; + if (class_exists($classname) && method_exists($classname, 'get_fieldname')) { + $fieldname = $classname::get_fieldname($field->name); + } + $table->data[] = array($fieldname, profile_field_icons($field)); } } diff --git a/user/profile/lib.php b/user/profile/lib.php index 33dc3c85b8b..6d9c1de6e0d 100644 --- a/user/profile/lib.php +++ b/user/profile/lib.php @@ -810,6 +810,14 @@ function profile_get_custom_fields($onlyinuserobject = false) { } } + foreach ($fields as $index => $field) { + $component = 'profilefield_' . $field->datatype; + $classname = "\\$component\\helper"; + if (class_exists($classname) && method_exists($classname, 'get_fieldname')) { + $fields[$index]->name = $classname::get_fieldname($field->name); + } + } + return $fields; } diff --git a/user/tests/externallib_test.php b/user/tests/externallib_test.php index 3c6b4de806d..f2a6176745c 100644 --- a/user/tests/externallib_test.php +++ b/user/tests/externallib_test.php @@ -53,17 +53,11 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { 'address' => '2 Test Street Perth 6000 WA', 'phone1' => '01010101010', 'phone2' => '02020203', - 'icq' => 'testuser1', - 'skype' => 'testuser1', - 'yahoo' => 'testuser1', - 'aim' => 'testuser1', - 'msn' => 'testuser1', 'department' => 'Department of user 1', 'institution' => 'Institution of user 1', 'description' => 'This is a description for user 1', 'descriptionformat' => FORMAT_MOODLE, 'city' => 'Perth', - 'url' => 'http://moodle.org', 'country' => 'AU' ); @@ -128,21 +122,6 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { if (!empty($generateduser->phone2)) { $this->assertEquals($generateduser->phone2, $returneduser['phone2']); } - if (!empty($generateduser->icq)) { - $this->assertEquals($generateduser->icq, $returneduser['icq']); - } - if (!empty($generateduser->skype)) { - $this->assertEquals($generateduser->skype, $returneduser['skype']); - } - if (!empty($generateduser->yahoo)) { - $this->assertEquals($generateduser->yahoo, $returneduser['yahoo']); - } - if (!empty($generateduser->aim)) { - $this->assertEquals($generateduser->aim, $returneduser['aim']); - } - if (!empty($generateduser->msn)) { - $this->assertEquals($generateduser->msn, $returneduser['msn']); - } if (!empty($generateduser->department)) { $this->assertEquals($generateduser->department, $returneduser['department']); } @@ -161,9 +140,6 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { if (!empty($generateduser->country)) { $this->assertEquals($generateduser->country, $returneduser['country']); } - if (!empty($generateduser->url)) { - $this->assertEquals($generateduser->url, $returneduser['url']); - } if (!empty($CFG->usetags) and !empty($generateduser->interests)) { $this->assertEquals(implode(', ', $generateduser->interests), $returneduser['interests']); } @@ -211,17 +187,11 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { 'address' => '2 Test Street Perth 6000 WA', 'phone1' => '01010101010', 'phone2' => '02020203', - 'icq' => 'testuser1', - 'skype' => 'testuser1', - 'yahoo' => 'testuser1', - 'aim' => 'testuser1', - 'msn' => 'testuser1', 'department' => 'Department of user 1', 'institution' => 'Institution of user 1', 'description' => 'This is a description for user 1', 'descriptionformat' => FORMAT_MOODLE, 'city' => 'Perth', - 'url' => 'http://moodle.org', 'country' => 'AU', ); $user1 = self::getDataGenerator()->create_user($user1); @@ -289,21 +259,6 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { if (!empty($generateduser->phone2)) { $this->assertEquals($generateduser->phone2, $returneduser['phone2']); } - if (!empty($generateduser->icq)) { - $this->assertEquals($generateduser->icq, $returneduser['icq']); - } - if (!empty($generateduser->skype)) { - $this->assertEquals($generateduser->skype, $returneduser['skype']); - } - if (!empty($generateduser->yahoo)) { - $this->assertEquals($generateduser->yahoo, $returneduser['yahoo']); - } - if (!empty($generateduser->aim)) { - $this->assertEquals($generateduser->aim, $returneduser['aim']); - } - if (!empty($generateduser->msn)) { - $this->assertEquals($generateduser->msn, $returneduser['msn']); - } if (!empty($generateduser->department)) { $this->assertEquals($generateduser->department, $returneduser['department']); } @@ -322,9 +277,6 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { if (!empty($generateduser->country)) { $this->assertEquals($generateduser->country, $returneduser['country']); } - if (!empty($generateduser->url)) { - $this->assertEquals($generateduser->url, $returneduser['url']); - } if (!empty($CFG->usetags) and !empty($generateduser->interests)) { $this->assertEquals(implode(', ', $generateduser->interests), $returneduser['interests']); } @@ -375,17 +327,11 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { 'address' => '2 Test Street Perth 6000 WA', 'phone1' => '01010101010', 'phone2' => '02020203', - 'icq' => 'testuser1', - 'skype' => 'testuser1', - 'yahoo' => 'testuser1', - 'aim' => 'testuser1', - 'msn' => 'testuser1', 'department' => 'Department of user 1', 'institution' => 'Institution of user 1', 'description' => 'This is a description for user 1', 'descriptionformat' => FORMAT_MOODLE, 'city' => 'Perth', - 'url' => 'http://moodle.org', 'country' => 'AU' ); $return->user1 = self::getDataGenerator()->create_user($return->user1); @@ -457,18 +403,12 @@ class core_user_externallib_testcase extends externallib_advanced_testcase { $this->assertEquals($data->user1->address, $enrolleduser['address']); $this->assertEquals($data->user1->phone1, $enrolleduser['phone1']); $this->assertEquals($data->user1->phone2, $enrolleduser['phone2']); - $this->assertEquals($data->user1->icq, $enrolleduser['icq']); - $this->assertEquals($data->user1->skype, $enrolleduser['skype']); - $this->assertEquals($data->user1->yahoo, $enrolleduser['yahoo']); - $this->assertEquals($data->user1->aim, $enrolleduser['aim']); - $this->assertEquals($data->user1->msn, $enrolleduser['msn']); $this->assertEquals($data->user1->department, $enrolleduser['department']); $this->assertEquals($data->user1->institution, $enrolleduser['institution']); $this->assertEquals($data->user1->description, $enrolleduser['description']); $this->assertEquals(FORMAT_HTML, $enrolleduser['descriptionformat']); $this->assertEquals($data->user1->city, $enrolleduser['city']); $this->assertEquals($data->user1->country, $enrolleduser['country']); - $this->assertEquals($data->user1->url, $enrolleduser['url']); if (!empty($CFG->usetags)) { $this->assertEquals(implode(', ', $data->user1->interests), $enrolleduser['interests']); } diff --git a/user/tests/privacy_test.php b/user/tests/privacy_test.php index cedc5658bd3..6e6e0bfed7a 100644 --- a/user/tests/privacy_test.php +++ b/user/tests/privacy_test.php @@ -146,7 +146,6 @@ class core_user_privacy_testcase extends provider_testcase { $user = $this->getDataGenerator()->create_user([ 'idnumber' => 'A0023', 'emailstop' => 1, - 'icq' => 'aksdjf98', 'phone1' => '555 3257', 'institution' => 'test', 'department' => 'Science', @@ -187,7 +186,6 @@ class core_user_privacy_testcase extends provider_testcase { $record = $DB->get_record('user', ['id' => $user->id]); $this->assertEmpty($record->idnumber); $this->assertEmpty($record->emailstop); - $this->assertEmpty($record->icq); $this->assertEmpty($record->phone1); $this->assertEmpty($record->institution); $this->assertEmpty($record->department); @@ -217,7 +215,6 @@ class core_user_privacy_testcase extends provider_testcase { $user = $this->getDataGenerator()->create_user([ 'idnumber' => 'A0023', 'emailstop' => 1, - 'icq' => 'aksdjf98', 'phone1' => '555 3257', 'institution' => 'test', 'department' => 'Science', @@ -262,7 +259,6 @@ class core_user_privacy_testcase extends provider_testcase { $record = $DB->get_record('user', ['id' => $user->id]); $this->assertEmpty($record->idnumber); $this->assertEmpty($record->emailstop); - $this->assertEmpty($record->icq); $this->assertEmpty($record->phone1); $this->assertEmpty($record->institution); $this->assertEmpty($record->department); @@ -323,7 +319,6 @@ class core_user_privacy_testcase extends provider_testcase { $user1 = $this->getDataGenerator()->create_user([ 'idnumber' => 'A0023', 'emailstop' => 1, - 'icq' => 'aksdjf98', 'phone1' => '555 3257', 'institution' => 'test', 'department' => 'Science', @@ -337,7 +332,6 @@ class core_user_privacy_testcase extends provider_testcase { $user2 = $this->getDataGenerator()->create_user([ 'idnumber' => 'A0024', 'emailstop' => 1, - 'icq' => 'aksdjf981', 'phone1' => '555 3258', 'institution' => 'test', 'department' => 'Science', @@ -363,7 +357,6 @@ class core_user_privacy_testcase extends provider_testcase { $record = $DB->get_record('user', ['id' => $user1->id]); $this->assertEmpty($record->idnumber); $this->assertEmpty($record->emailstop); - $this->assertEmpty($record->icq); $this->assertEmpty($record->phone1); $this->assertEmpty($record->institution); $this->assertEmpty($record->department); @@ -387,7 +380,6 @@ class core_user_privacy_testcase extends provider_testcase { $record = $DB->get_record('user', ['id' => $user2->id]); $this->assertNotEmpty($record->idnumber); $this->assertNotEmpty($record->emailstop); - $this->assertNotEmpty($record->icq); $this->assertNotEmpty($record->phone1); $this->assertNotEmpty($record->institution); $this->assertNotEmpty($record->department); diff --git a/user/tests/userlib_test.php b/user/tests/userlib_test.php index 51de4a67464..aaca2547d21 100644 --- a/user/tests/userlib_test.php +++ b/user/tests/userlib_test.php @@ -200,10 +200,9 @@ class core_userliblib_testcase extends advanced_testcase { $user->lang = 'xy'; $user->theme = 'somewrongthemename'; $user->timezone = '30.5'; - $user->url = 'wwww.somewrong@#$url.com.aus'; $debugmessages = $this->getDebuggingMessages(); user_update_user($user, true, false); - $this->assertDebuggingCalledCount(6, $debugmessages); + $this->assertDebuggingCalledCount(5, $debugmessages); // Now, with valid user data. $user->username = 'johndoe321'; @@ -212,7 +211,6 @@ class core_userliblib_testcase extends advanced_testcase { $user->lang = 'en'; $user->theme = 'classic'; $user->timezone = 'Australia/Perth'; - $user->url = 'www.moodle.org'; user_update_user($user, true, false); $this->assertDebuggingNotCalled(); } @@ -283,10 +281,9 @@ class core_userliblib_testcase extends advanced_testcase { $user['lang'] = 'xy'; $user['theme'] = 'somewrongthemename'; $user['timezone'] = '-30.5'; - $user['url'] = 'wwww.somewrong@#$url.com.aus'; $debugmessages = $this->getDebuggingMessages(); $user['id'] = user_create_user($user, true, false); - $this->assertDebuggingCalledCount(6, $debugmessages); + $this->assertDebuggingCalledCount(5, $debugmessages); $dbuser = $DB->get_record('user', array('id' => $user['id'])); $this->assertEquals($dbuser->country, 0); $this->assertEquals($dbuser->lang, 'en'); @@ -299,7 +296,6 @@ class core_userliblib_testcase extends advanced_testcase { $user['lang'] = 'en'; $user['theme'] = 'classic'; $user['timezone'] = 'Australia/Perth'; - $user['url'] = 'www.moodle.org'; user_create_user($user, true, false); $this->assertDebuggingNotCalled(); } diff --git a/version.php b/version.php index d14d637af70..8cdb4438328 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2021052500.79; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2021052500.80; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.0dev (Build: 20210416)'; // Human-friendly version name -- 2.43.0