| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 5 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 6 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 7 | // (at your option) any later version.
 | 
        
           |  |  | 8 | //
 | 
        
           |  |  | 9 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 12 | // GNU General Public License for more details.
 | 
        
           |  |  | 13 | //
 | 
        
           |  |  | 14 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 | namespace communication_matrix;
 | 
        
           |  |  | 18 |   | 
        
           |  |  | 19 | /**
 | 
        
           |  |  | 20 |  * class matrix_user_manager to handle specific actions.
 | 
        
           |  |  | 21 |  *
 | 
        
           |  |  | 22 |  * @package    communication_matrix
 | 
        
           |  |  | 23 |  * @copyright  2023 Stevani Andolo <stevani.andolo@moodle.com>
 | 
        
           |  |  | 24 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 25 |  */
 | 
        
           |  |  | 26 | class matrix_user_manager {
 | 
        
           |  |  | 27 |   | 
        
           |  |  | 28 |     /**
 | 
        
           |  |  | 29 |      * Prefix for Matrix usernames when they are detected as numeric.
 | 
        
           |  |  | 30 |      */
 | 
        
           |  |  | 31 |     const MATRIX_USER_PREFIX = 'user';
 | 
        
           |  |  | 32 |   | 
        
           |  |  | 33 |     /**
 | 
        
           |  |  | 34 |      * Gets matrix user id from moodle.
 | 
        
           |  |  | 35 |      *
 | 
        
           |  |  | 36 |      * @param int $userid Moodle user id
 | 
        
           |  |  | 37 |      * @return string|null
 | 
        
           |  |  | 38 |      */
 | 
        
           |  |  | 39 |     public static function get_matrixid_from_moodle(
 | 
        
           |  |  | 40 |         int $userid,
 | 
        
           |  |  | 41 |     ): ?string {
 | 
        
           |  |  | 42 |         self::load_requirements();
 | 
        
           |  |  | 43 |         $field = profile_user_record($userid);
 | 
        
           |  |  | 44 |         $matrixprofilefield = get_config('communication_matrix', 'matrixuserid_field');
 | 
        
           |  |  | 45 |   | 
        
           |  |  | 46 |         if ($matrixprofilefield === false) {
 | 
        
           |  |  | 47 |             return null;
 | 
        
           |  |  | 48 |         }
 | 
        
           |  |  | 49 |   | 
        
           |  |  | 50 |         return $field->{$matrixprofilefield} ?? null;
 | 
        
           |  |  | 51 |     }
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 |     /**
 | 
        
           |  |  | 54 |      * Get a qualified matrix user id based on a Moodle username.
 | 
        
           |  |  | 55 |      *
 | 
        
           |  |  | 56 |      * @param string $username The moodle username to turn into a Matrix username
 | 
        
           |  |  | 57 |      * @return string
 | 
        
           |  |  | 58 |      */
 | 
        
           |  |  | 59 |     public static function get_formatted_matrix_userid(
 | 
        
           |  |  | 60 |         string $username,
 | 
        
           |  |  | 61 |     ): string {
 | 
        
           |  |  | 62 |         $username = preg_replace('/[@#$%^&*()+{}|<>?!,]/i', '.', $username);
 | 
        
           |  |  | 63 |         $username = ltrim(rtrim($username, '.'), '.');
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 |         // Matrix/Synapse servers will not allow numeric usernames.
 | 
        
           |  |  | 66 |         if (is_numeric($username)) {
 | 
        
           |  |  | 67 |             $username = self::MATRIX_USER_PREFIX . $username;
 | 
        
           |  |  | 68 |         }
 | 
        
           |  |  | 69 |   | 
        
           | 1441 | ariadna | 70 |         $homeserver = get_config('communication_matrix', 'matrixhomeservername');
 | 
        
           | 1 | efrain | 71 |   | 
        
           | 1441 | ariadna | 72 |         // Fall back to homeserver URL if name not set.
 | 
        
           |  |  | 73 |         if (empty($homeserver)) {
 | 
        
           |  |  | 74 |             $homeserver = self::get_formatted_matrix_home_server();
 | 
        
           |  |  | 75 |         }
 | 
        
           |  |  | 76 |   | 
        
           | 1 | efrain | 77 |         return "@{$username}:{$homeserver}";
 | 
        
           |  |  | 78 |     }
 | 
        
           |  |  | 79 |   | 
        
           |  |  | 80 |     /**
 | 
        
           |  |  | 81 |      * Add user's Matrix user id.
 | 
        
           |  |  | 82 |      *
 | 
        
           |  |  | 83 |      * @param int $userid Moodle user id
 | 
        
           |  |  | 84 |      * @param string $matrixuserid Matrix user id
 | 
        
           |  |  | 85 |      */
 | 
        
           |  |  | 86 |     public static function set_matrix_userid_in_moodle(
 | 
        
           |  |  | 87 |         int $userid,
 | 
        
           |  |  | 88 |         string $matrixuserid,
 | 
        
           |  |  | 89 |     ): void {
 | 
        
           |  |  | 90 |         $matrixprofilefield = self::get_profile_field_name();
 | 
        
           |  |  | 91 |         $field = profile_get_custom_field_data_by_shortname($matrixprofilefield);
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |         if ($field === null) {
 | 
        
           |  |  | 94 |             return;
 | 
        
           |  |  | 95 |         }
 | 
        
           |  |  | 96 |         $userinfodata = (object) [
 | 
        
           |  |  | 97 |             'id' => $userid,
 | 
        
           |  |  | 98 |             'data' => $matrixuserid,
 | 
        
           |  |  | 99 |             'fieldid' => $field->id,
 | 
        
           |  |  | 100 |             "profile_field_{$matrixprofilefield}" => $matrixuserid,
 | 
        
           |  |  | 101 |         ];
 | 
        
           |  |  | 102 |         profile_save_data($userinfodata);
 | 
        
           |  |  | 103 |     }
 | 
        
           |  |  | 104 |   | 
        
           |  |  | 105 |     /**
 | 
        
           |  |  | 106 |      * Sets home server for user matrix id
 | 
        
           |  |  | 107 |      *
 | 
        
           |  |  | 108 |      * @return string
 | 
        
           |  |  | 109 |      */
 | 
        
           |  |  | 110 |     public static function get_formatted_matrix_home_server(): string {
 | 
        
           |  |  | 111 |         $homeserver = get_config('communication_matrix', 'matrixhomeserverurl');
 | 
        
           |  |  | 112 |         if ($homeserver === false) {
 | 
        
           |  |  | 113 |             throw new \moodle_exception('Unknown matrix homeserver url');
 | 
        
           |  |  | 114 |         }
 | 
        
           |  |  | 115 |   | 
        
           |  |  | 116 |         $homeserver = parse_url($homeserver)['host'];
 | 
        
           |  |  | 117 |   | 
        
           |  |  | 118 |         if (str_starts_with($homeserver, 'www.')) {
 | 
        
           |  |  | 119 |             $homeserver = str_replace('www.', '', $homeserver);
 | 
        
           |  |  | 120 |         }
 | 
        
           |  |  | 121 |   | 
        
           |  |  | 122 |         return $homeserver;
 | 
        
           |  |  | 123 |     }
 | 
        
           |  |  | 124 |   | 
        
           |  |  | 125 |     /**
 | 
        
           |  |  | 126 |      * Insert "Communication" category and "matrixuserid" field.
 | 
        
           |  |  | 127 |      *
 | 
        
           |  |  | 128 |      * @return string
 | 
        
           |  |  | 129 |      */
 | 
        
           |  |  | 130 |     public static function create_matrix_user_profile_fields(): string {
 | 
        
           |  |  | 131 |         global $CFG, $DB;
 | 
        
           |  |  | 132 |   | 
        
           |  |  | 133 |         require_once($CFG->dirroot . '/user/profile/definelib.php');
 | 
        
           |  |  | 134 |         require_once($CFG->dirroot . '/user/profile/field/text/define.class.php');
 | 
        
           |  |  | 135 |   | 
        
           |  |  | 136 |         // Check if communication category exists.
 | 
        
           |  |  | 137 |         $categoryname = get_string('communication', 'core_communication');
 | 
        
           |  |  | 138 |         $category = $DB->count_records('user_info_category', ['name' => $categoryname]);
 | 
        
           |  |  | 139 |   | 
        
           |  |  | 140 |         if ($category < 1) {
 | 
        
           |  |  | 141 |             $data = new \stdClass();
 | 
        
           |  |  | 142 |             $data->sortorder = $DB->count_records('user_info_category') + 1;
 | 
        
           |  |  | 143 |             $data->name = $categoryname;
 | 
        
           |  |  | 144 |             $data->id = $DB->insert_record('user_info_category', $data);
 | 
        
           |  |  | 145 |   | 
        
           |  |  | 146 |             $createdcategory = $DB->get_record('user_info_category', ['id' => $data->id]);
 | 
        
           |  |  | 147 |             $categoryid = $createdcategory->id;
 | 
        
           |  |  | 148 |             \core\event\user_info_category_created::create_from_category($createdcategory)->trigger();
 | 
        
           |  |  | 149 |         } else {
 | 
        
           |  |  | 150 |             $category = $DB->get_record('user_info_category', ['name' => $categoryname]);
 | 
        
           |  |  | 151 |             $categoryid = $category->id;
 | 
        
           |  |  | 152 |         }
 | 
        
           |  |  | 153 |   | 
        
           |  |  | 154 |         set_config('communication_category_field', $categoryname, 'core_communication');
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 |         // Check if matrixuserid exists in user_info_field table.
 | 
        
           |  |  | 157 |         $matrixuserid = $DB->count_records('user_info_field', [
 | 
        
           |  |  | 158 |             'shortname' => 'matrixuserid',
 | 
        
           |  |  | 159 |             'categoryid' => $categoryid,
 | 
        
           |  |  | 160 |         ]);
 | 
        
           |  |  | 161 |   | 
        
           |  |  | 162 |         if ($matrixuserid < 1) {
 | 
        
           |  |  | 163 |             $profileclass = new \profile_define_text();
 | 
        
           |  |  | 164 |   | 
        
           |  |  | 165 |             $data = (object) [
 | 
        
           |  |  | 166 |                 'shortname' => 'matrixuserid',
 | 
        
           |  |  | 167 |                 'name' => get_string('matrixuserid', 'communication_matrix'),
 | 
        
           |  |  | 168 |                 'datatype' => 'text',
 | 
        
           |  |  | 169 |                 'categoryid' => $categoryid,
 | 
        
           |  |  | 170 |                 'forceunique' => 1,
 | 
        
           |  |  | 171 |                 'visible' => 0,
 | 
        
           |  |  | 172 |                 'locked' => 1,
 | 
        
           |  |  | 173 |                 'param1' => 30,
 | 
        
           |  |  | 174 |                 'param2' => 2048,
 | 
        
           |  |  | 175 |             ];
 | 
        
           |  |  | 176 |   | 
        
           |  |  | 177 |             $profileclass->define_save($data);
 | 
        
           |  |  | 178 |             set_config('matrixuserid_field', 'matrixuserid', 'communication_matrix');
 | 
        
           |  |  | 179 |             return 'matrixuserid';
 | 
        
           |  |  | 180 |         }
 | 
        
           |  |  | 181 |     }
 | 
        
           |  |  | 182 |   | 
        
           |  |  | 183 |     /**
 | 
        
           |  |  | 184 |      * Get the profile field name, creating the profiel field if it does not exist.
 | 
        
           |  |  | 185 |      *
 | 
        
           |  |  | 186 |      * @return string
 | 
        
           |  |  | 187 |      */
 | 
        
           |  |  | 188 |     protected static function get_profile_field_name(): string {
 | 
        
           |  |  | 189 |         self::load_requirements();
 | 
        
           |  |  | 190 |         $matrixprofilefield = get_config('communication_matrix', 'matrixuserid_field');
 | 
        
           |  |  | 191 |         if ($matrixprofilefield === false) {
 | 
        
           |  |  | 192 |             $matrixprofilefield = self::create_matrix_user_profile_fields();
 | 
        
           |  |  | 193 |         }
 | 
        
           |  |  | 194 |   | 
        
           |  |  | 195 |         return $matrixprofilefield;
 | 
        
           |  |  | 196 |     }
 | 
        
           |  |  | 197 |   | 
        
           |  |  | 198 |     /**
 | 
        
           |  |  | 199 |      * Load requirements for profile field management.
 | 
        
           |  |  | 200 |      *
 | 
        
           |  |  | 201 |      * This is just a helper to keep loading legacy files isolated.
 | 
        
           |  |  | 202 |      */
 | 
        
           |  |  | 203 |     protected static function load_requirements(): void {
 | 
        
           |  |  | 204 |         global $CFG;
 | 
        
           |  |  | 205 |   | 
        
           |  |  | 206 |         require_once("{$CFG->dirroot}/user/profile/lib.php");
 | 
        
           |  |  | 207 |     }
 | 
        
           |  |  | 208 | }
 |