| 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 | /**
 | 
        
           |  |  | 18 |  * Class process
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @package     tool_uploaduser
 | 
        
           |  |  | 21 |  * @copyright   2020 Moodle
 | 
        
           |  |  | 22 |  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | namespace tool_uploaduser;
 | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 | use context_system;
 | 
        
           |  |  | 30 | use context_coursecat;
 | 
        
           |  |  | 31 | use core_course_category;
 | 
        
           |  |  | 32 |   | 
        
           |  |  | 33 | use tool_uploaduser\local\field_value_validators;
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 | require_once($CFG->dirroot.'/user/profile/lib.php');
 | 
        
           |  |  | 36 | require_once($CFG->dirroot.'/user/lib.php');
 | 
        
           |  |  | 37 | require_once($CFG->dirroot.'/group/lib.php');
 | 
        
           |  |  | 38 | require_once($CFG->dirroot.'/cohort/lib.php');
 | 
        
           |  |  | 39 | require_once($CFG->libdir.'/csvlib.class.php');
 | 
        
           |  |  | 40 | require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/uploaduser/locallib.php');
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 | /**
 | 
        
           |  |  | 43 |  * Process CSV file with users data, this will create/update users, enrol them into courses, etc
 | 
        
           |  |  | 44 |  *
 | 
        
           |  |  | 45 |  * @package     tool_uploaduser
 | 
        
           |  |  | 46 |  * @copyright   2020 Moodle
 | 
        
           |  |  | 47 |  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 48 |  */
 | 
        
           |  |  | 49 | class process {
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 |     /** @var \csv_import_reader  */
 | 
        
           |  |  | 52 |     protected $cir;
 | 
        
           |  |  | 53 |     /** @var \stdClass  */
 | 
        
           |  |  | 54 |     protected $formdata;
 | 
        
           |  |  | 55 |     /** @var \uu_progress_tracker  */
 | 
        
           |  |  | 56 |     protected $upt;
 | 
        
           |  |  | 57 |     /** @var array  */
 | 
        
           |  |  | 58 |     protected $filecolumns = null;
 | 
        
           |  |  | 59 |     /** @var int  */
 | 
        
           |  |  | 60 |     protected $today;
 | 
        
           |  |  | 61 |     /** @var \enrol_plugin|null */
 | 
        
           |  |  | 62 |     protected $manualenrol = null;
 | 
        
           |  |  | 63 |     /** @var array */
 | 
        
           |  |  | 64 |     protected $standardfields = [];
 | 
        
           |  |  | 65 |     /** @var array */
 | 
        
           |  |  | 66 |     protected $profilefields = [];
 | 
        
           |  |  | 67 |     /** @var \profile_field_base[] */
 | 
        
           |  |  | 68 |     protected $allprofilefields = [];
 | 
        
           |  |  | 69 |     /** @var string|\uu_progress_tracker|null  */
 | 
        
           |  |  | 70 |     protected $progresstrackerclass = null;
 | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |     /** @var int */
 | 
        
           |  |  | 73 |     protected $usersnew      = 0;
 | 
        
           |  |  | 74 |     /** @var int */
 | 
        
           |  |  | 75 |     protected $usersupdated  = 0;
 | 
        
           |  |  | 76 |     /** @var int /not printed yet anywhere */
 | 
        
           |  |  | 77 |     protected $usersuptodate = 0;
 | 
        
           |  |  | 78 |     /** @var int */
 | 
        
           |  |  | 79 |     protected $userserrors   = 0;
 | 
        
           |  |  | 80 |     /** @var int */
 | 
        
           |  |  | 81 |     protected $deletes       = 0;
 | 
        
           |  |  | 82 |     /** @var int */
 | 
        
           |  |  | 83 |     protected $deleteerrors  = 0;
 | 
        
           |  |  | 84 |     /** @var int */
 | 
        
           |  |  | 85 |     protected $renames       = 0;
 | 
        
           |  |  | 86 |     /** @var int */
 | 
        
           |  |  | 87 |     protected $renameerrors  = 0;
 | 
        
           |  |  | 88 |     /** @var int */
 | 
        
           |  |  | 89 |     protected $usersskipped  = 0;
 | 
        
           |  |  | 90 |     /** @var int */
 | 
        
           |  |  | 91 |     protected $weakpasswords = 0;
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |     /** @var array course cache - do not fetch all courses here, we  will not probably use them all anyway */
 | 
        
           |  |  | 94 |     protected $ccache         = [];
 | 
        
           |  |  | 95 |     /** @var array */
 | 
        
           |  |  | 96 |     protected $cohorts        = [];
 | 
        
           |  |  | 97 |     /** @var array  Course roles lookup cache. */
 | 
        
           |  |  | 98 |     protected $rolecache      = [];
 | 
        
           |  |  | 99 |     /** @var array System roles lookup cache. */
 | 
        
           |  |  | 100 |     protected $sysrolecache   = [];
 | 
        
           |  |  | 101 |     /** @var array cache of used manual enrol plugins in each course */
 | 
        
           |  |  | 102 |     protected $manualcache    = [];
 | 
        
           |  |  | 103 |     /** @var array officially supported plugins that are enabled */
 | 
        
           |  |  | 104 |     protected $supportedauths = [];
 | 
        
           |  |  | 105 |   | 
        
           |  |  | 106 |     /**
 | 
        
           |  |  | 107 |      * process constructor.
 | 
        
           |  |  | 108 |      *
 | 
        
           |  |  | 109 |      * @param \csv_import_reader $cir
 | 
        
           |  |  | 110 |      * @param string|null $progresstrackerclass
 | 
        
           |  |  | 111 |      * @throws \coding_exception
 | 
        
           |  |  | 112 |      */
 | 
        
           | 1441 | ariadna | 113 |     public function __construct(\csv_import_reader $cir, ?string $progresstrackerclass = null) {
 | 
        
           | 1 | efrain | 114 |         $this->cir = $cir;
 | 
        
           |  |  | 115 |         if ($progresstrackerclass) {
 | 
        
           |  |  | 116 |             if (!class_exists($progresstrackerclass) || !is_subclass_of($progresstrackerclass, \uu_progress_tracker::class)) {
 | 
        
           |  |  | 117 |                 throw new \coding_exception('Progress tracker class must extend \uu_progress_tracker');
 | 
        
           |  |  | 118 |             }
 | 
        
           |  |  | 119 |             $this->progresstrackerclass = $progresstrackerclass;
 | 
        
           |  |  | 120 |         } else {
 | 
        
           |  |  | 121 |             $this->progresstrackerclass = \uu_progress_tracker::class;
 | 
        
           |  |  | 122 |         }
 | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 |         // Keep timestamp consistent.
 | 
        
           |  |  | 125 |         $today = time();
 | 
        
           |  |  | 126 |         $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
 | 
        
           |  |  | 127 |         $this->today = $today;
 | 
        
           |  |  | 128 |   | 
        
           |  |  | 129 |         $this->sysrolecache   = uu_allowed_sysroles_cache(); // System roles lookup cache.
 | 
        
           |  |  | 130 |         $this->supportedauths = uu_supported_auths(); // Officially supported plugins that are enabled.
 | 
        
           |  |  | 131 |   | 
        
           |  |  | 132 |         if (enrol_is_enabled('manual')) {
 | 
        
           |  |  | 133 |             // We use only manual enrol plugin here, if it is disabled no enrol is done.
 | 
        
           |  |  | 134 |             $this->manualenrol = enrol_get_plugin('manual');
 | 
        
           |  |  | 135 |         }
 | 
        
           |  |  | 136 |   | 
        
           |  |  | 137 |         $this->find_profile_fields();
 | 
        
           |  |  | 138 |         $this->find_standard_fields();
 | 
        
           |  |  | 139 |     }
 | 
        
           |  |  | 140 |   | 
        
           |  |  | 141 |     /**
 | 
        
           |  |  | 142 |      * Standard user fields.
 | 
        
           |  |  | 143 |      */
 | 
        
           |  |  | 144 |     protected function find_standard_fields(): void {
 | 
        
           |  |  | 145 |         $this->standardfields = array('id', 'username', 'email', 'emailstop',
 | 
        
           |  |  | 146 |             'city', 'country', 'lang', 'timezone', 'mailformat',
 | 
        
           |  |  | 147 |             'maildisplay', 'maildigest', 'htmleditor', 'autosubscribe',
 | 
        
           |  |  | 148 |             'institution', 'department', 'idnumber', 'phone1', 'phone2', 'address',
 | 
        
           |  |  | 149 |             'description', 'descriptionformat', 'password',
 | 
        
           |  |  | 150 |             'auth',        // Watch out when changing auth type or using external auth plugins!
 | 
        
           |  |  | 151 |             'oldusername', // Use when renaming users - this is the original username.
 | 
        
           |  |  | 152 |             'suspended',   // 1 means suspend user account, 0 means activate user account, nothing means keep as is.
 | 
        
           |  |  | 153 |             'theme',       // Define a theme for user when 'allowuserthemes' is enabled.
 | 
        
           |  |  | 154 |             'deleted',     // 1 means delete user
 | 
        
           |  |  | 155 |             'mnethostid',  // Can not be used for adding, updating or deleting of users - only for enrolments,
 | 
        
           |  |  | 156 |                            // groups, cohorts and suspending.
 | 
        
           |  |  | 157 |             'interests',
 | 
        
           |  |  | 158 |         );
 | 
        
           |  |  | 159 |         // Include all name fields.
 | 
        
           |  |  | 160 |         $this->standardfields = array_merge($this->standardfields, \core_user\fields::get_name_fields());
 | 
        
           |  |  | 161 |     }
 | 
        
           |  |  | 162 |   | 
        
           |  |  | 163 |     /**
 | 
        
           |  |  | 164 |      * Profile fields
 | 
        
           |  |  | 165 |      */
 | 
        
           |  |  | 166 |     protected function find_profile_fields(): void {
 | 
        
           |  |  | 167 |         global $CFG;
 | 
        
           |  |  | 168 |         require_once($CFG->dirroot . '/user/profile/lib.php');
 | 
        
           |  |  | 169 |         $this->allprofilefields = profile_get_user_fields_with_data(0);
 | 
        
           |  |  | 170 |         $this->profilefields = [];
 | 
        
           |  |  | 171 |         if ($proffields = $this->allprofilefields) {
 | 
        
           |  |  | 172 |             foreach ($proffields as $key => $proffield) {
 | 
        
           |  |  | 173 |                 $profilefieldname = 'profile_field_'.$proffield->get_shortname();
 | 
        
           |  |  | 174 |                 $this->profilefields[] = $profilefieldname;
 | 
        
           |  |  | 175 |                 // Re-index $proffields with key as shortname. This will be
 | 
        
           |  |  | 176 |                 // used while checking if profile data is key and needs to be converted (eg. menu profile field).
 | 
        
           |  |  | 177 |                 $proffields[$profilefieldname] = $proffield;
 | 
        
           |  |  | 178 |                 unset($proffields[$key]);
 | 
        
           |  |  | 179 |             }
 | 
        
           |  |  | 180 |             $this->allprofilefields = $proffields;
 | 
        
           |  |  | 181 |         }
 | 
        
           |  |  | 182 |     }
 | 
        
           |  |  | 183 |   | 
        
           |  |  | 184 |     /**
 | 
        
           |  |  | 185 |      * Returns the list of columns in the file
 | 
        
           |  |  | 186 |      *
 | 
        
           |  |  | 187 |      * @return array
 | 
        
           |  |  | 188 |      */
 | 
        
           |  |  | 189 |     public function get_file_columns(): array {
 | 
        
           |  |  | 190 |         if ($this->filecolumns === null) {
 | 
        
           |  |  | 191 |             $returnurl = new \moodle_url('/admin/tool/uploaduser/index.php');
 | 
        
           |  |  | 192 |             $this->filecolumns = uu_validate_user_upload_columns($this->cir,
 | 
        
           |  |  | 193 |                 $this->standardfields, $this->profilefields, $returnurl);
 | 
        
           |  |  | 194 |         }
 | 
        
           |  |  | 195 |         return $this->filecolumns;
 | 
        
           |  |  | 196 |     }
 | 
        
           |  |  | 197 |   | 
        
           |  |  | 198 |     /**
 | 
        
           |  |  | 199 |      * Set data from the form (or from CLI options)
 | 
        
           |  |  | 200 |      *
 | 
        
           |  |  | 201 |      * @param \stdClass $formdata
 | 
        
           |  |  | 202 |      */
 | 
        
           |  |  | 203 |     public function set_form_data(\stdClass $formdata): void {
 | 
        
           |  |  | 204 |         global $SESSION;
 | 
        
           |  |  | 205 |         $this->formdata = $formdata;
 | 
        
           |  |  | 206 |   | 
        
           |  |  | 207 |         // Clear bulk selection.
 | 
        
           |  |  | 208 |         if ($this->get_bulk()) {
 | 
        
           |  |  | 209 |             $SESSION->bulk_users = array();
 | 
        
           |  |  | 210 |         }
 | 
        
           |  |  | 211 |     }
 | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 |     /**
 | 
        
           |  |  | 214 |      * Operation type
 | 
        
           |  |  | 215 |      * @return int
 | 
        
           |  |  | 216 |      */
 | 
        
           |  |  | 217 |     protected function get_operation_type(): int {
 | 
        
           |  |  | 218 |         return (int)$this->formdata->uutype;
 | 
        
           |  |  | 219 |     }
 | 
        
           |  |  | 220 |   | 
        
           |  |  | 221 |     /**
 | 
        
           |  |  | 222 |      * Setting to allow deletes
 | 
        
           |  |  | 223 |      * @return bool
 | 
        
           |  |  | 224 |      */
 | 
        
           |  |  | 225 |     protected function get_allow_deletes(): bool {
 | 
        
           |  |  | 226 |         $optype = $this->get_operation_type();
 | 
        
           |  |  | 227 |         return (!empty($this->formdata->uuallowdeletes) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC);
 | 
        
           |  |  | 228 |     }
 | 
        
           |  |  | 229 |   | 
        
           |  |  | 230 |     /**
 | 
        
           |  |  | 231 |      * Setting to allow matching user accounts on email
 | 
        
           |  |  | 232 |      * @return bool
 | 
        
           |  |  | 233 |      */
 | 
        
           |  |  | 234 |     protected function get_match_on_email(): bool {
 | 
        
           |  |  | 235 |         $optype = $this->get_operation_type();
 | 
        
           |  |  | 236 |         return (!empty($this->formdata->uumatchemail) && $optype != UU_USER_ADDNEW && $optype != UU_USER_ADDINC);
 | 
        
           |  |  | 237 |     }
 | 
        
           |  |  | 238 |   | 
        
           |  |  | 239 |     /**
 | 
        
           |  |  | 240 |      * Setting to allow deletes
 | 
        
           |  |  | 241 |      * @return bool
 | 
        
           |  |  | 242 |      */
 | 
        
           |  |  | 243 |     protected function get_allow_renames(): bool {
 | 
        
           |  |  | 244 |         $optype = $this->get_operation_type();
 | 
        
           |  |  | 245 |         return (!empty($this->formdata->uuallowrenames) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC);
 | 
        
           |  |  | 246 |     }
 | 
        
           |  |  | 247 |   | 
        
           |  |  | 248 |     /**
 | 
        
           |  |  | 249 |      * Setting to select for bulk actions (not available in CLI)
 | 
        
           |  |  | 250 |      * @return bool
 | 
        
           |  |  | 251 |      */
 | 
        
           |  |  | 252 |     public function get_bulk(): bool {
 | 
        
           |  |  | 253 |         return $this->formdata->uubulk ?? false;
 | 
        
           |  |  | 254 |     }
 | 
        
           |  |  | 255 |   | 
        
           |  |  | 256 |     /**
 | 
        
           |  |  | 257 |      * Setting for update type
 | 
        
           |  |  | 258 |      * @return int
 | 
        
           |  |  | 259 |      */
 | 
        
           |  |  | 260 |     protected function get_update_type(): int {
 | 
        
           |  |  | 261 |         return isset($this->formdata->uuupdatetype) ? $this->formdata->uuupdatetype : 0;
 | 
        
           |  |  | 262 |     }
 | 
        
           |  |  | 263 |   | 
        
           |  |  | 264 |     /**
 | 
        
           |  |  | 265 |      * Setting to allow update passwords
 | 
        
           |  |  | 266 |      * @return bool
 | 
        
           |  |  | 267 |      */
 | 
        
           |  |  | 268 |     protected function get_update_passwords(): bool {
 | 
        
           |  |  | 269 |         return !empty($this->formdata->uupasswordold)
 | 
        
           |  |  | 270 |             and $this->get_operation_type() != UU_USER_ADDNEW
 | 
        
           |  |  | 271 |             and $this->get_operation_type() != UU_USER_ADDINC
 | 
        
           |  |  | 272 |             and ($this->get_update_type() == UU_UPDATE_FILEOVERRIDE or $this->get_update_type() == UU_UPDATE_ALLOVERRIDE);
 | 
        
           |  |  | 273 |     }
 | 
        
           |  |  | 274 |   | 
        
           |  |  | 275 |     /**
 | 
        
           |  |  | 276 |      * Setting to allow email duplicates
 | 
        
           |  |  | 277 |      * @return bool
 | 
        
           |  |  | 278 |      */
 | 
        
           |  |  | 279 |     protected function get_allow_email_duplicates(): bool {
 | 
        
           |  |  | 280 |         global $CFG;
 | 
        
           |  |  | 281 |         return !(empty($CFG->allowaccountssameemail) ? 1 : $this->formdata->uunoemailduplicates);
 | 
        
           |  |  | 282 |     }
 | 
        
           |  |  | 283 |   | 
        
           |  |  | 284 |     /**
 | 
        
           |  |  | 285 |      * Setting for reset password
 | 
        
           |  |  | 286 |      * @return int UU_PWRESET_NONE, UU_PWRESET_WEAK, UU_PWRESET_ALL
 | 
        
           |  |  | 287 |      */
 | 
        
           |  |  | 288 |     protected function get_reset_passwords(): int {
 | 
        
           |  |  | 289 |         return isset($this->formdata->uuforcepasswordchange) ? $this->formdata->uuforcepasswordchange : UU_PWRESET_NONE;
 | 
        
           |  |  | 290 |     }
 | 
        
           |  |  | 291 |   | 
        
           |  |  | 292 |     /**
 | 
        
           |  |  | 293 |      * Setting to allow create passwords
 | 
        
           |  |  | 294 |      * @return bool
 | 
        
           |  |  | 295 |      */
 | 
        
           |  |  | 296 |     protected function get_create_paswords(): bool {
 | 
        
           |  |  | 297 |         return (!empty($this->formdata->uupasswordnew) and $this->get_operation_type() != UU_USER_UPDATE);
 | 
        
           |  |  | 298 |     }
 | 
        
           |  |  | 299 |   | 
        
           |  |  | 300 |     /**
 | 
        
           |  |  | 301 |      * Setting to allow suspends
 | 
        
           |  |  | 302 |      * @return bool
 | 
        
           |  |  | 303 |      */
 | 
        
           |  |  | 304 |     protected function get_allow_suspends(): bool {
 | 
        
           |  |  | 305 |         return !empty($this->formdata->uuallowsuspends);
 | 
        
           |  |  | 306 |     }
 | 
        
           |  |  | 307 |   | 
        
           |  |  | 308 |     /**
 | 
        
           |  |  | 309 |      * Setting to normalise user names
 | 
        
           |  |  | 310 |      * @return bool
 | 
        
           |  |  | 311 |      */
 | 
        
           |  |  | 312 |     protected function get_normalise_user_names(): bool {
 | 
        
           |  |  | 313 |         return !empty($this->formdata->uustandardusernames);
 | 
        
           |  |  | 314 |     }
 | 
        
           |  |  | 315 |   | 
        
           |  |  | 316 |     /**
 | 
        
           |  |  | 317 |      * Helper method to return Yes/No string
 | 
        
           |  |  | 318 |      *
 | 
        
           |  |  | 319 |      * @param bool $value
 | 
        
           |  |  | 320 |      * @return string
 | 
        
           |  |  | 321 |      */
 | 
        
           |  |  | 322 |     protected function get_string_yes_no($value): string {
 | 
        
           |  |  | 323 |         return $value ? get_string('yes') : get_string('no');
 | 
        
           |  |  | 324 |     }
 | 
        
           |  |  | 325 |   | 
        
           |  |  | 326 |     /**
 | 
        
           |  |  | 327 |      * Process the CSV file
 | 
        
           |  |  | 328 |      */
 | 
        
           |  |  | 329 |     public function process() {
 | 
        
           |  |  | 330 |         // Init csv import helper.
 | 
        
           |  |  | 331 |         $this->cir->init();
 | 
        
           |  |  | 332 |   | 
        
           |  |  | 333 |         $classname = $this->progresstrackerclass;
 | 
        
           |  |  | 334 |         $this->upt = new $classname();
 | 
        
           |  |  | 335 |         $this->upt->start(); // Start table.
 | 
        
           |  |  | 336 |   | 
        
           |  |  | 337 |         $linenum = 1; // Column header is first line.
 | 
        
           |  |  | 338 |         while ($line = $this->cir->next()) {
 | 
        
           |  |  | 339 |             $this->upt->flush();
 | 
        
           |  |  | 340 |             $linenum++;
 | 
        
           |  |  | 341 |   | 
        
           |  |  | 342 |             $this->upt->track('line', $linenum);
 | 
        
           |  |  | 343 |             $this->process_line($line);
 | 
        
           |  |  | 344 |         }
 | 
        
           |  |  | 345 |   | 
        
           |  |  | 346 |         $this->upt->close(); // Close table.
 | 
        
           |  |  | 347 |         $this->cir->close();
 | 
        
           |  |  | 348 |         $this->cir->cleanup(true);
 | 
        
           |  |  | 349 |     }
 | 
        
           |  |  | 350 |   | 
        
           |  |  | 351 |     /**
 | 
        
           |  |  | 352 |      * Prepare one line from CSV file as a user record
 | 
        
           |  |  | 353 |      *
 | 
        
           |  |  | 354 |      * @param array $line
 | 
        
           |  |  | 355 |      * @return \stdClass|null
 | 
        
           |  |  | 356 |      */
 | 
        
           |  |  | 357 |     protected function prepare_user_record(array $line): ?\stdClass {
 | 
        
           |  |  | 358 |         global $CFG, $USER;
 | 
        
           |  |  | 359 |   | 
        
           |  |  | 360 |         $user = new \stdClass();
 | 
        
           |  |  | 361 |   | 
        
           |  |  | 362 |         // Add fields to user object.
 | 
        
           |  |  | 363 |         foreach ($line as $keynum => $value) {
 | 
        
           |  |  | 364 |             if (!isset($this->get_file_columns()[$keynum])) {
 | 
        
           |  |  | 365 |                 // This should not happen.
 | 
        
           |  |  | 366 |                 continue;
 | 
        
           |  |  | 367 |             }
 | 
        
           |  |  | 368 |             $key = $this->get_file_columns()[$keynum];
 | 
        
           |  |  | 369 |             if (strpos($key, 'profile_field_') === 0) {
 | 
        
           |  |  | 370 |                 // NOTE: bloody mega hack alert!!
 | 
        
           |  |  | 371 |                 if (isset($USER->$key) and is_array($USER->$key)) {
 | 
        
           |  |  | 372 |                     // This must be some hacky field that is abusing arrays to store content and format.
 | 
        
           |  |  | 373 |                     $user->$key = array();
 | 
        
           |  |  | 374 |                     $user->{$key['text']}   = $value;
 | 
        
           |  |  | 375 |                     $user->{$key['format']} = FORMAT_MOODLE;
 | 
        
           |  |  | 376 |                 } else {
 | 
        
           |  |  | 377 |                     $user->$key = trim($value);
 | 
        
           |  |  | 378 |                 }
 | 
        
           |  |  | 379 |             } else {
 | 
        
           |  |  | 380 |                 $user->$key = trim($value);
 | 
        
           |  |  | 381 |             }
 | 
        
           |  |  | 382 |   | 
        
           |  |  | 383 |             if (in_array($key, $this->upt->columns)) {
 | 
        
           |  |  | 384 |                 // Default value in progress tracking table, can be changed later.
 | 
        
           |  |  | 385 |                 $this->upt->track($key, s($value), 'normal');
 | 
        
           |  |  | 386 |             }
 | 
        
           |  |  | 387 |         }
 | 
        
           |  |  | 388 |         if (!isset($user->username)) {
 | 
        
           |  |  | 389 |             // Prevent warnings below.
 | 
        
           |  |  | 390 |             $user->username = '';
 | 
        
           |  |  | 391 |         }
 | 
        
           |  |  | 392 |   | 
        
           |  |  | 393 |         if ($this->get_operation_type() == UU_USER_ADDNEW or $this->get_operation_type() == UU_USER_ADDINC) {
 | 
        
           |  |  | 394 |             // User creation is a special case - the username may be constructed from templates using firstname and lastname
 | 
        
           |  |  | 395 |             // better never try this in mixed update types.
 | 
        
           |  |  | 396 |             $error = false;
 | 
        
           |  |  | 397 |             if (!isset($user->firstname) or $user->firstname === '') {
 | 
        
           |  |  | 398 |                 $this->upt->track('status', get_string('missingfield', 'error', 'firstname'), 'error');
 | 
        
           |  |  | 399 |                 $this->upt->track('firstname', get_string('error'), 'error');
 | 
        
           |  |  | 400 |                 $error = true;
 | 
        
           |  |  | 401 |             }
 | 
        
           |  |  | 402 |             if (!isset($user->lastname) or $user->lastname === '') {
 | 
        
           |  |  | 403 |                 $this->upt->track('status', get_string('missingfield', 'error', 'lastname'), 'error');
 | 
        
           |  |  | 404 |                 $this->upt->track('lastname', get_string('error'), 'error');
 | 
        
           |  |  | 405 |                 $error = true;
 | 
        
           |  |  | 406 |             }
 | 
        
           |  |  | 407 |             if ($error) {
 | 
        
           |  |  | 408 |                 $this->userserrors++;
 | 
        
           |  |  | 409 |                 return null;
 | 
        
           |  |  | 410 |             }
 | 
        
           |  |  | 411 |             // We require username too - we might use template for it though.
 | 
        
           |  |  | 412 |             if (empty($user->username) and !empty($this->formdata->username)) {
 | 
        
           |  |  | 413 |                 $user->username = uu_process_template($this->formdata->username, $user);
 | 
        
           |  |  | 414 |                 $this->upt->track('username', s($user->username));
 | 
        
           |  |  | 415 |             }
 | 
        
           |  |  | 416 |         }
 | 
        
           |  |  | 417 |   | 
        
           |  |  | 418 |         // Normalize username.
 | 
        
           |  |  | 419 |         $user->originalusername = $user->username;
 | 
        
           |  |  | 420 |         if ($this->get_normalise_user_names()) {
 | 
        
           |  |  | 421 |             $user->username = \core_user::clean_field($user->username, 'username');
 | 
        
           |  |  | 422 |         }
 | 
        
           |  |  | 423 |   | 
        
           |  |  | 424 |         // Make sure we really have username.
 | 
        
           |  |  | 425 |         if (empty($user->username) && !$this->get_match_on_email()) {
 | 
        
           |  |  | 426 |             $this->upt->track('status', get_string('missingfield', 'error', 'username'), 'error');
 | 
        
           |  |  | 427 |             $this->upt->track('username', get_string('error'), 'error');
 | 
        
           |  |  | 428 |             $this->userserrors++;
 | 
        
           |  |  | 429 |             return null;
 | 
        
           |  |  | 430 |         } else if ($user->username === 'guest') {
 | 
        
           |  |  | 431 |             $this->upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
 | 
        
           |  |  | 432 |             $this->userserrors++;
 | 
        
           |  |  | 433 |             return null;
 | 
        
           |  |  | 434 |         }
 | 
        
           |  |  | 435 |   | 
        
           |  |  | 436 |         if ($user->username !== \core_user::clean_field($user->username, 'username')) {
 | 
        
           |  |  | 437 |             $this->upt->track('status', get_string('invalidusername', 'error', 'username'), 'error');
 | 
        
           |  |  | 438 |             $this->upt->track('username', get_string('error'), 'error');
 | 
        
           |  |  | 439 |             $this->userserrors++;
 | 
        
           |  |  | 440 |         }
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 |         if (empty($user->mnethostid)) {
 | 
        
           |  |  | 443 |             $user->mnethostid = $CFG->mnet_localhost_id;
 | 
        
           |  |  | 444 |         }
 | 
        
           |  |  | 445 |   | 
        
           |  |  | 446 |         return $user;
 | 
        
           |  |  | 447 |     }
 | 
        
           |  |  | 448 |   | 
        
           |  |  | 449 |     /**
 | 
        
           |  |  | 450 |      * Process one line from CSV file
 | 
        
           |  |  | 451 |      *
 | 
        
           |  |  | 452 |      * @param array $line
 | 
        
           |  |  | 453 |      * @throws \coding_exception
 | 
        
           |  |  | 454 |      * @throws \dml_exception
 | 
        
           |  |  | 455 |      * @throws \moodle_exception
 | 
        
           |  |  | 456 |      */
 | 
        
           |  |  | 457 |     public function process_line(array $line) {
 | 
        
           |  |  | 458 |         global $DB, $CFG, $SESSION;
 | 
        
           |  |  | 459 |   | 
        
           |  |  | 460 |         if (!$user = $this->prepare_user_record($line)) {
 | 
        
           |  |  | 461 |             return;
 | 
        
           |  |  | 462 |         }
 | 
        
           |  |  | 463 |   | 
        
           |  |  | 464 |         if ($this->get_match_on_email()) {
 | 
        
           |  |  | 465 |             // Case-insensitive query for the given email address.
 | 
        
           |  |  | 466 |             $userselect = $DB->sql_equal('email', ':email', false);
 | 
        
           |  |  | 467 |             $userparams = ['email' => $user->email];
 | 
        
           |  |  | 468 |         } else {
 | 
        
           |  |  | 469 |             $userselect = 'username = :username';
 | 
        
           |  |  | 470 |             $userparams = ['username' => $user->username];
 | 
        
           |  |  | 471 |         }
 | 
        
           |  |  | 472 |   | 
        
           |  |  | 473 |         // Match the user, also accounting for multiple records by email.
 | 
        
           |  |  | 474 |         $existinguser = $DB->get_records_select('user', "{$userselect} AND mnethostid = :mnethostid",
 | 
        
           |  |  | 475 |             $userparams + ['mnethostid' => $user->mnethostid]);
 | 
        
           |  |  | 476 |         $existingusercount = count($existinguser);
 | 
        
           |  |  | 477 |   | 
        
           |  |  | 478 |         if ($existingusercount > 0) {
 | 
        
           |  |  | 479 |             if ($existingusercount !== 1) {
 | 
        
           |  |  | 480 |                 $this->upt->track('status', get_string('duplicateemail', 'tool_uploaduser', $user->email), 'warning');
 | 
        
           |  |  | 481 |                 $this->userserrors++;
 | 
        
           |  |  | 482 |                 return;
 | 
        
           |  |  | 483 |   | 
        
           |  |  | 484 |             }
 | 
        
           |  |  | 485 |   | 
        
           |  |  | 486 |             $existinguser = is_array($existinguser) ? array_values($existinguser)[0] : $existinguser;
 | 
        
           |  |  | 487 |             $this->upt->track('id', $existinguser->id, 'normal', false);
 | 
        
           |  |  | 488 |         }
 | 
        
           |  |  | 489 |   | 
        
           |  |  | 490 |         if ($user->mnethostid == $CFG->mnet_localhost_id) {
 | 
        
           |  |  | 491 |             $remoteuser = false;
 | 
        
           |  |  | 492 |   | 
        
           |  |  | 493 |             // Find out if username incrementing required.
 | 
        
           |  |  | 494 |             if ($existinguser and $this->get_operation_type() == UU_USER_ADDINC) {
 | 
        
           |  |  | 495 |                 $user->username = uu_increment_username($user->username);
 | 
        
           |  |  | 496 |                 $existinguser = false;
 | 
        
           |  |  | 497 |             }
 | 
        
           |  |  | 498 |   | 
        
           |  |  | 499 |         } else {
 | 
        
           |  |  | 500 |             if (!$existinguser or $this->get_operation_type() == UU_USER_ADDINC) {
 | 
        
           |  |  | 501 |                 $this->upt->track('status', get_string('errormnetadd', 'tool_uploaduser'), 'error');
 | 
        
           |  |  | 502 |                 $this->userserrors++;
 | 
        
           |  |  | 503 |                 return;
 | 
        
           |  |  | 504 |             }
 | 
        
           |  |  | 505 |   | 
        
           |  |  | 506 |             $remoteuser = true;
 | 
        
           |  |  | 507 |   | 
        
           |  |  | 508 |             // Make sure there are no changes of existing fields except the suspended status.
 | 
        
           |  |  | 509 |             foreach ((array)$existinguser as $k => $v) {
 | 
        
           |  |  | 510 |                 if ($k === 'suspended') {
 | 
        
           |  |  | 511 |                     continue;
 | 
        
           |  |  | 512 |                 }
 | 
        
           |  |  | 513 |                 if (property_exists($user, $k)) {
 | 
        
           |  |  | 514 |                     $user->$k = $v;
 | 
        
           |  |  | 515 |                 }
 | 
        
           |  |  | 516 |                 if (in_array($k, $this->upt->columns)) {
 | 
        
           |  |  | 517 |                     if ($k === 'password' or $k === 'oldusername' or $k === 'deleted') {
 | 
        
           |  |  | 518 |                         $this->upt->track($k, '', 'normal', false);
 | 
        
           |  |  | 519 |                     } else {
 | 
        
           |  |  | 520 |                         $this->upt->track($k, s($v), 'normal', false);
 | 
        
           |  |  | 521 |                     }
 | 
        
           |  |  | 522 |                 }
 | 
        
           |  |  | 523 |             }
 | 
        
           |  |  | 524 |             unset($user->oldusername);
 | 
        
           |  |  | 525 |             unset($user->password);
 | 
        
           |  |  | 526 |             $user->auth = $existinguser->auth;
 | 
        
           |  |  | 527 |         }
 | 
        
           |  |  | 528 |   | 
        
           |  |  | 529 |         // Notify about nay username changes.
 | 
        
           |  |  | 530 |         if ($user->originalusername !== $user->username) {
 | 
        
           |  |  | 531 |             $this->upt->track('username', '', 'normal', false); // Clear previous.
 | 
        
           |  |  | 532 |             $this->upt->track('username', s($user->originalusername).'-->'.s($user->username), 'info');
 | 
        
           |  |  | 533 |         } else {
 | 
        
           |  |  | 534 |             $this->upt->track('username', s($user->username), 'normal', false);
 | 
        
           |  |  | 535 |         }
 | 
        
           |  |  | 536 |         unset($user->originalusername);
 | 
        
           |  |  | 537 |   | 
        
           |  |  | 538 |         // Verify if the theme is valid and allowed to be set.
 | 
        
           |  |  | 539 |         if (isset($user->theme)) {
 | 
        
           |  |  | 540 |             list($status, $message) = field_value_validators::validate_theme($user->theme);
 | 
        
           |  |  | 541 |             if ($status !== 'normal' && !empty($message)) {
 | 
        
           |  |  | 542 |                 $this->upt->track('status', $message, $status);
 | 
        
           |  |  | 543 |                 // Unset the theme when validation fails.
 | 
        
           |  |  | 544 |                 unset($user->theme);
 | 
        
           |  |  | 545 |             }
 | 
        
           |  |  | 546 |         }
 | 
        
           |  |  | 547 |   | 
        
           |  |  | 548 |         // Add default values for remaining fields.
 | 
        
           |  |  | 549 |         $formdefaults = array();
 | 
        
           |  |  | 550 |         if (!$existinguser ||
 | 
        
           |  |  | 551 |                 ($this->get_update_type() != UU_UPDATE_FILEOVERRIDE && $this->get_update_type() != UU_UPDATE_NOCHANGES)) {
 | 
        
           |  |  | 552 |             foreach ($this->standardfields as $field) {
 | 
        
           |  |  | 553 |                 if (isset($user->$field)) {
 | 
        
           |  |  | 554 |                     continue;
 | 
        
           |  |  | 555 |                 }
 | 
        
           |  |  | 556 |                 // All validation moved to form2.
 | 
        
           |  |  | 557 |                 if (isset($this->formdata->$field)) {
 | 
        
           |  |  | 558 |                     // Process templates.
 | 
        
           |  |  | 559 |                     $user->$field = uu_process_template($this->formdata->$field, $user);
 | 
        
           |  |  | 560 |                     $formdefaults[$field] = true;
 | 
        
           |  |  | 561 |                     if (in_array($field, $this->upt->columns)) {
 | 
        
           |  |  | 562 |                         $this->upt->track($field, s($user->$field), 'normal');
 | 
        
           |  |  | 563 |                     }
 | 
        
           |  |  | 564 |                 }
 | 
        
           |  |  | 565 |             }
 | 
        
           |  |  | 566 |             foreach ($this->allprofilefields as $field => $profilefield) {
 | 
        
           |  |  | 567 |                 if (isset($user->$field)) {
 | 
        
           |  |  | 568 |                     continue;
 | 
        
           |  |  | 569 |                 }
 | 
        
           |  |  | 570 |                 if (isset($this->formdata->$field)) {
 | 
        
           |  |  | 571 |                     // Process templates.
 | 
        
           |  |  | 572 |                     $user->$field = uu_process_template($this->formdata->$field, $user);
 | 
        
           |  |  | 573 |   | 
        
           |  |  | 574 |                     // Form contains key and later code expects value.
 | 
        
           |  |  | 575 |                     // Convert key to value for required profile fields.
 | 
        
           |  |  | 576 |                     if (method_exists($profilefield, 'convert_external_data')) {
 | 
        
           |  |  | 577 |                         $user->$field = $profilefield->edit_save_data_preprocess($user->$field, null);
 | 
        
           |  |  | 578 |                     }
 | 
        
           |  |  | 579 |   | 
        
           |  |  | 580 |                     $formdefaults[$field] = true;
 | 
        
           |  |  | 581 |                 }
 | 
        
           |  |  | 582 |             }
 | 
        
           |  |  | 583 |         }
 | 
        
           |  |  | 584 |   | 
        
           |  |  | 585 |         // Delete user.
 | 
        
           |  |  | 586 |         if (!empty($user->deleted)) {
 | 
        
           |  |  | 587 |             if (!$this->get_allow_deletes() or $remoteuser or
 | 
        
           |  |  | 588 |                     !has_capability('moodle/user:delete', context_system::instance())) {
 | 
        
           |  |  | 589 |                 $this->usersskipped++;
 | 
        
           |  |  | 590 |                 $this->upt->track('status', get_string('usernotdeletedoff', 'error'), 'warning');
 | 
        
           |  |  | 591 |                 return;
 | 
        
           |  |  | 592 |             }
 | 
        
           |  |  | 593 |             if ($existinguser) {
 | 
        
           |  |  | 594 |                 if (is_siteadmin($existinguser->id)) {
 | 
        
           |  |  | 595 |                     $this->upt->track('status', get_string('usernotdeletedadmin', 'error'), 'error');
 | 
        
           |  |  | 596 |                     $this->deleteerrors++;
 | 
        
           |  |  | 597 |                     return;
 | 
        
           |  |  | 598 |                 }
 | 
        
           |  |  | 599 |                 if (delete_user($existinguser)) {
 | 
        
           |  |  | 600 |                     $this->upt->track('status', get_string('userdeleted', 'tool_uploaduser'));
 | 
        
           |  |  | 601 |                     $this->deletes++;
 | 
        
           |  |  | 602 |                 } else {
 | 
        
           |  |  | 603 |                     $this->upt->track('status', get_string('usernotdeletederror', 'error'), 'error');
 | 
        
           |  |  | 604 |                     $this->deleteerrors++;
 | 
        
           |  |  | 605 |                 }
 | 
        
           |  |  | 606 |             } else {
 | 
        
           |  |  | 607 |                 $this->upt->track('status', get_string('usernotdeletedmissing', 'error'), 'error');
 | 
        
           |  |  | 608 |                 $this->deleteerrors++;
 | 
        
           |  |  | 609 |             }
 | 
        
           |  |  | 610 |             return;
 | 
        
           |  |  | 611 |         }
 | 
        
           |  |  | 612 |         // We do not need the deleted flag anymore.
 | 
        
           |  |  | 613 |         unset($user->deleted);
 | 
        
           |  |  | 614 |   | 
        
           |  |  | 615 |         $matchonemailallowrename = $this->get_match_on_email() && $this->get_allow_renames();
 | 
        
           |  |  | 616 |         if ($matchonemailallowrename && $user->username && ($user->username !== $existinguser->username)) {
 | 
        
           |  |  | 617 |             $user->oldusername = $existinguser->username;
 | 
        
           |  |  | 618 |             $existinguser = false;
 | 
        
           |  |  | 619 |         }
 | 
        
           |  |  | 620 |   | 
        
           |  |  | 621 |         // Renaming requested?
 | 
        
           |  |  | 622 |         if (!empty($user->oldusername) ) {
 | 
        
           |  |  | 623 |             if (!$this->get_allow_renames()) {
 | 
        
           |  |  | 624 |                 $this->usersskipped++;
 | 
        
           |  |  | 625 |                 $this->upt->track('status', get_string('usernotrenamedoff', 'error'), 'warning');
 | 
        
           |  |  | 626 |                 return;
 | 
        
           |  |  | 627 |             }
 | 
        
           |  |  | 628 |   | 
        
           |  |  | 629 |             if ($existinguser) {
 | 
        
           |  |  | 630 |                 $this->upt->track('status', get_string('usernotrenamedexists', 'error'), 'error');
 | 
        
           |  |  | 631 |                 $this->renameerrors++;
 | 
        
           |  |  | 632 |                 return;
 | 
        
           |  |  | 633 |             }
 | 
        
           |  |  | 634 |   | 
        
           |  |  | 635 |             if ($user->username === 'guest') {
 | 
        
           |  |  | 636 |                 $this->upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
 | 
        
           |  |  | 637 |                 $this->renameerrors++;
 | 
        
           |  |  | 638 |                 return;
 | 
        
           |  |  | 639 |             }
 | 
        
           |  |  | 640 |   | 
        
           |  |  | 641 |             if ($this->get_normalise_user_names()) {
 | 
        
           |  |  | 642 |                 $oldusername = \core_user::clean_field($user->oldusername, 'username');
 | 
        
           |  |  | 643 |             } else {
 | 
        
           |  |  | 644 |                 $oldusername = $user->oldusername;
 | 
        
           |  |  | 645 |             }
 | 
        
           |  |  | 646 |   | 
        
           |  |  | 647 |             // No guessing when looking for old username, it must be exact match.
 | 
        
           |  |  | 648 |             if ($olduser = $DB->get_record('user',
 | 
        
           |  |  | 649 |                     ['username' => $oldusername, 'mnethostid' => $CFG->mnet_localhost_id])) {
 | 
        
           |  |  | 650 |                 $this->upt->track('id', $olduser->id, 'normal', false);
 | 
        
           |  |  | 651 |                 if (is_siteadmin($olduser->id)) {
 | 
        
           |  |  | 652 |                     $this->upt->track('status', get_string('usernotrenamedadmin', 'error'), 'error');
 | 
        
           |  |  | 653 |                     $this->renameerrors++;
 | 
        
           |  |  | 654 |                     return;
 | 
        
           |  |  | 655 |                 }
 | 
        
           |  |  | 656 |                 $DB->set_field('user', 'username', $user->username, ['id' => $olduser->id]);
 | 
        
           |  |  | 657 |                 $this->upt->track('username', '', 'normal', false); // Clear previous.
 | 
        
           |  |  | 658 |                 $this->upt->track('username', s($oldusername).'-->'.s($user->username), 'info');
 | 
        
           |  |  | 659 |                 $this->upt->track('status', get_string('userrenamed', 'tool_uploaduser'));
 | 
        
           |  |  | 660 |                 $this->renames++;
 | 
        
           |  |  | 661 |             } else {
 | 
        
           |  |  | 662 |                 $this->upt->track('status', get_string('usernotrenamedmissing', 'error'), 'error');
 | 
        
           |  |  | 663 |                 $this->renameerrors++;
 | 
        
           |  |  | 664 |                 return;
 | 
        
           |  |  | 665 |             }
 | 
        
           |  |  | 666 |             $existinguser = $olduser;
 | 
        
           |  |  | 667 |             $existinguser->username = $user->username;
 | 
        
           |  |  | 668 |         }
 | 
        
           |  |  | 669 |   | 
        
           |  |  | 670 |         // Can we process with update or insert?
 | 
        
           |  |  | 671 |         $skip = false;
 | 
        
           |  |  | 672 |         switch ($this->get_operation_type()) {
 | 
        
           |  |  | 673 |             case UU_USER_ADDNEW:
 | 
        
           |  |  | 674 |                 if ($existinguser) {
 | 
        
           |  |  | 675 |                     $this->usersskipped++;
 | 
        
           |  |  | 676 |                     $this->upt->track('status', get_string('usernotaddedregistered', 'error'), 'warning');
 | 
        
           |  |  | 677 |                     $skip = true;
 | 
        
           |  |  | 678 |                 }
 | 
        
           |  |  | 679 |                 break;
 | 
        
           |  |  | 680 |   | 
        
           |  |  | 681 |             case UU_USER_ADDINC:
 | 
        
           |  |  | 682 |                 if ($existinguser) {
 | 
        
           |  |  | 683 |                     // This should not happen!
 | 
        
           |  |  | 684 |                     $this->upt->track('status', get_string('usernotaddederror', 'error'), 'error');
 | 
        
           |  |  | 685 |                     $this->userserrors++;
 | 
        
           |  |  | 686 |                     $skip = true;
 | 
        
           |  |  | 687 |                 }
 | 
        
           |  |  | 688 |                 break;
 | 
        
           |  |  | 689 |   | 
        
           |  |  | 690 |             case UU_USER_ADD_UPDATE:
 | 
        
           |  |  | 691 |                 if ($this->get_match_on_email()) {
 | 
        
           |  |  | 692 |                     if ($usersbyname = $DB->get_records('user', ['username' => $user->username])) {
 | 
        
           |  |  | 693 |                         foreach ($usersbyname as $userbyname) {
 | 
        
           |  |  | 694 |                             if (strtolower($userbyname->email) != strtolower($user->email)) {
 | 
        
           |  |  | 695 |                                 $this->usersskipped++;
 | 
        
           |  |  | 696 |                                 $this->upt->track('status', get_string('usernotaddedusernameexists', 'error'), 'warning');
 | 
        
           |  |  | 697 |                                 $skip = true;
 | 
        
           |  |  | 698 |                             }
 | 
        
           |  |  | 699 |                         }
 | 
        
           |  |  | 700 |                     }
 | 
        
           |  |  | 701 |                 }
 | 
        
           |  |  | 702 |                 break;
 | 
        
           |  |  | 703 |   | 
        
           |  |  | 704 |             case UU_USER_UPDATE:
 | 
        
           |  |  | 705 |                 if (!$existinguser) {
 | 
        
           |  |  | 706 |                     $this->usersskipped++;
 | 
        
           |  |  | 707 |                     $this->upt->track('status', get_string('usernotupdatednotexists', 'error'), 'warning');
 | 
        
           |  |  | 708 |                     $skip = true;
 | 
        
           |  |  | 709 |                 }
 | 
        
           |  |  | 710 |                 break;
 | 
        
           |  |  | 711 |   | 
        
           |  |  | 712 |             default:
 | 
        
           |  |  | 713 |                 // Unknown type.
 | 
        
           |  |  | 714 |                 $skip = true;
 | 
        
           |  |  | 715 |         }
 | 
        
           |  |  | 716 |   | 
        
           |  |  | 717 |         if ($skip) {
 | 
        
           |  |  | 718 |             return;
 | 
        
           |  |  | 719 |         }
 | 
        
           |  |  | 720 |   | 
        
           |  |  | 721 |         if ($existinguser) {
 | 
        
           |  |  | 722 |             $user->id = $existinguser->id;
 | 
        
           |  |  | 723 |   | 
        
           |  |  | 724 |             $this->upt->track('username', \html_writer::link(
 | 
        
           |  |  | 725 |                 new \moodle_url('/user/profile.php', ['id' => $existinguser->id]), s($existinguser->username)), 'normal', false);
 | 
        
           |  |  | 726 |             $this->upt->track('suspended', $this->get_string_yes_no($existinguser->suspended) , 'normal', false);
 | 
        
           |  |  | 727 |             $this->upt->track('auth', $existinguser->auth, 'normal', false);
 | 
        
           |  |  | 728 |   | 
        
           |  |  | 729 |             if (is_siteadmin($user->id)) {
 | 
        
           |  |  | 730 |                 $this->upt->track('status', get_string('usernotupdatedadmin', 'error'), 'error');
 | 
        
           |  |  | 731 |                 $this->userserrors++;
 | 
        
           |  |  | 732 |                 return;
 | 
        
           |  |  | 733 |             }
 | 
        
           |  |  | 734 |   | 
        
           |  |  | 735 |             $existinguser->timemodified = time();
 | 
        
           |  |  | 736 |             // Do NOT mess with timecreated or firstaccess here!
 | 
        
           |  |  | 737 |   | 
        
           |  |  | 738 |             // Load existing profile data.
 | 
        
           |  |  | 739 |             profile_load_data($existinguser);
 | 
        
           |  |  | 740 |   | 
        
           |  |  | 741 |             $doupdate = false;
 | 
        
           |  |  | 742 |             $dologout = false;
 | 
        
           |  |  | 743 |   | 
        
           |  |  | 744 |             if ($this->get_update_type() != UU_UPDATE_NOCHANGES and !$remoteuser) {
 | 
        
           |  |  | 745 |   | 
        
           |  |  | 746 |                 // Handle 'auth' column separately, the field can never be missing from a user.
 | 
        
           |  |  | 747 |                 if (!empty($user->auth) && ($user->auth !== $existinguser->auth) &&
 | 
        
           |  |  | 748 |                         ($this->get_update_type() != UU_UPDATE_MISSING)) {
 | 
        
           |  |  | 749 |   | 
        
           |  |  | 750 |                     $this->upt->track('auth', s($existinguser->auth).'-->'.s($user->auth), 'info', false);
 | 
        
           |  |  | 751 |                     $existinguser->auth = $user->auth;
 | 
        
           |  |  | 752 |                     if (!isset($this->supportedauths[$user->auth])) {
 | 
        
           |  |  | 753 |                         $this->upt->track('auth', get_string('userauthunsupported', 'error'), 'warning');
 | 
        
           |  |  | 754 |                     }
 | 
        
           |  |  | 755 |                     $doupdate = true;
 | 
        
           |  |  | 756 |                     if ($existinguser->auth === 'nologin') {
 | 
        
           |  |  | 757 |                         $dologout = true;
 | 
        
           |  |  | 758 |                     }
 | 
        
           |  |  | 759 |                 }
 | 
        
           |  |  | 760 |                 $allcolumns = array_merge($this->standardfields, $this->profilefields);
 | 
        
           |  |  | 761 |                 foreach ($allcolumns as $column) {
 | 
        
           |  |  | 762 |                     if ($column === 'username' or $column === 'password' or $column === 'auth' or $column === 'suspended') {
 | 
        
           |  |  | 763 |                         // These can not be changed here.
 | 
        
           |  |  | 764 |                         continue;
 | 
        
           |  |  | 765 |                     }
 | 
        
           |  |  | 766 |                     if (!property_exists($user, $column) or !property_exists($existinguser, $column)) {
 | 
        
           |  |  | 767 |                         continue;
 | 
        
           |  |  | 768 |                     }
 | 
        
           |  |  | 769 |                     if ($this->get_update_type() == UU_UPDATE_MISSING) {
 | 
        
           |  |  | 770 |                         if (!is_null($existinguser->$column) and $existinguser->$column !== '') {
 | 
        
           |  |  | 771 |                             continue;
 | 
        
           |  |  | 772 |                         }
 | 
        
           |  |  | 773 |                     } else if ($this->get_update_type() == UU_UPDATE_ALLOVERRIDE) {
 | 
        
           |  |  | 774 |                         // We override everything.
 | 
        
           |  |  | 775 |                         null;
 | 
        
           |  |  | 776 |                     } else if ($this->get_update_type() == UU_UPDATE_FILEOVERRIDE) {
 | 
        
           |  |  | 777 |                         if (!empty($formdefaults[$column])) {
 | 
        
           |  |  | 778 |                             // Do not override with form defaults.
 | 
        
           |  |  | 779 |                             continue;
 | 
        
           |  |  | 780 |                         }
 | 
        
           |  |  | 781 |                     }
 | 
        
           |  |  | 782 |                     if ($existinguser->$column !== $user->$column) {
 | 
        
           |  |  | 783 |                         if ($column === 'email') {
 | 
        
           |  |  | 784 |                             $select = $DB->sql_like('email', ':email', false, true, false, '|');
 | 
        
           |  |  | 785 |                             $params = array('email' => $DB->sql_like_escape($user->email, '|'));
 | 
        
           |  |  | 786 |                             if ($DB->record_exists_select('user', $select , $params)) {
 | 
        
           |  |  | 787 |   | 
        
           |  |  | 788 |                                 $changeincase = \core_text::strtolower($existinguser->$column) === \core_text::strtolower(
 | 
        
           |  |  | 789 |                                         $user->$column);
 | 
        
           |  |  | 790 |   | 
        
           |  |  | 791 |                                 if ($changeincase) {
 | 
        
           |  |  | 792 |                                     // If only case is different then switch to lower case and carry on.
 | 
        
           |  |  | 793 |                                     $user->$column = \core_text::strtolower($user->$column);
 | 
        
           |  |  | 794 |                                     continue;
 | 
        
           |  |  | 795 |                                 } else if (!$this->get_allow_email_duplicates()) {
 | 
        
           |  |  | 796 |                                     $this->upt->track('email', get_string('useremailduplicate', 'error'), 'error');
 | 
        
           |  |  | 797 |                                     $this->upt->track('status', get_string('usernotupdatederror', 'error'), 'error');
 | 
        
           |  |  | 798 |                                     $this->userserrors++;
 | 
        
           |  |  | 799 |                                     return;
 | 
        
           |  |  | 800 |                                 } else {
 | 
        
           |  |  | 801 |                                     $this->upt->track('email', get_string('useremailduplicate', 'error'), 'warning');
 | 
        
           |  |  | 802 |                                 }
 | 
        
           |  |  | 803 |                             }
 | 
        
           |  |  | 804 |                             if (!validate_email($user->email)) {
 | 
        
           |  |  | 805 |                                 $this->upt->track('email', get_string('invalidemail'), 'warning');
 | 
        
           |  |  | 806 |                             }
 | 
        
           |  |  | 807 |                         }
 | 
        
           |  |  | 808 |   | 
        
           |  |  | 809 |                         if ($column === 'lang') {
 | 
        
           |  |  | 810 |                             if (empty($user->lang)) {
 | 
        
           |  |  | 811 |                                 // Do not change to not-set value.
 | 
        
           |  |  | 812 |                                 continue;
 | 
        
           |  |  | 813 |                             } else if (\core_user::clean_field($user->lang, 'lang') === '') {
 | 
        
           |  |  | 814 |                                 $this->upt->track('status', get_string('cannotfindlang', 'error', $user->lang), 'warning');
 | 
        
           |  |  | 815 |                                 continue;
 | 
        
           |  |  | 816 |                             }
 | 
        
           |  |  | 817 |                         }
 | 
        
           |  |  | 818 |   | 
        
           |  |  | 819 |                         if (in_array($column, $this->upt->columns)) {
 | 
        
           |  |  | 820 |                             $this->upt->track($column, s($existinguser->$column).'-->'.s($user->$column), 'info', false);
 | 
        
           |  |  | 821 |                         }
 | 
        
           |  |  | 822 |                         $existinguser->$column = $user->$column;
 | 
        
           |  |  | 823 |                         $doupdate = true;
 | 
        
           |  |  | 824 |                     }
 | 
        
           |  |  | 825 |                 }
 | 
        
           |  |  | 826 |             }
 | 
        
           |  |  | 827 |   | 
        
           |  |  | 828 |             try {
 | 
        
           |  |  | 829 |                 $auth = get_auth_plugin($existinguser->auth);
 | 
        
           |  |  | 830 |             } catch (\Exception $e) {
 | 
        
           |  |  | 831 |                 $this->upt->track('auth', get_string('userautherror', 'error', s($existinguser->auth)), 'error');
 | 
        
           |  |  | 832 |                 $this->upt->track('status', get_string('usernotupdatederror', 'error'), 'error');
 | 
        
           |  |  | 833 |                 $this->userserrors++;
 | 
        
           |  |  | 834 |                 return;
 | 
        
           |  |  | 835 |             }
 | 
        
           |  |  | 836 |             $isinternalauth = $auth->is_internal();
 | 
        
           |  |  | 837 |   | 
        
           |  |  | 838 |             // Deal with suspending and activating of accounts.
 | 
        
           |  |  | 839 |             if ($this->get_allow_suspends() and isset($user->suspended) and $user->suspended !== '') {
 | 
        
           |  |  | 840 |                 $user->suspended = $user->suspended ? 1 : 0;
 | 
        
           |  |  | 841 |                 if ($existinguser->suspended != $user->suspended) {
 | 
        
           |  |  | 842 |                     $this->upt->track('suspended', '', 'normal', false);
 | 
        
           |  |  | 843 |                     $this->upt->track('suspended',
 | 
        
           |  |  | 844 |                         $this->get_string_yes_no($existinguser->suspended).'-->'.$this->get_string_yes_no($user->suspended),
 | 
        
           |  |  | 845 |                         'info', false);
 | 
        
           |  |  | 846 |                     $existinguser->suspended = $user->suspended;
 | 
        
           |  |  | 847 |                     $doupdate = true;
 | 
        
           |  |  | 848 |                     if ($existinguser->suspended) {
 | 
        
           |  |  | 849 |                         $dologout = true;
 | 
        
           |  |  | 850 |                     }
 | 
        
           |  |  | 851 |                 }
 | 
        
           |  |  | 852 |             }
 | 
        
           |  |  | 853 |   | 
        
           |  |  | 854 |             // Changing of passwords is a special case
 | 
        
           |  |  | 855 |             // do not force password changes for external auth plugins!
 | 
        
           |  |  | 856 |             $oldpw = $existinguser->password;
 | 
        
           |  |  | 857 |   | 
        
           |  |  | 858 |             if ($remoteuser) {
 | 
        
           |  |  | 859 |                 // Do not mess with passwords of remote users.
 | 
        
           |  |  | 860 |                 null;
 | 
        
           |  |  | 861 |             } else if (!$isinternalauth) {
 | 
        
           |  |  | 862 |                 $existinguser->password = AUTH_PASSWORD_NOT_CACHED;
 | 
        
           |  |  | 863 |                 $this->upt->track('password', '-', 'normal', false);
 | 
        
           |  |  | 864 |                 // Clean up prefs.
 | 
        
           |  |  | 865 |                 unset_user_preference('create_password', $existinguser);
 | 
        
           |  |  | 866 |                 unset_user_preference('auth_forcepasswordchange', $existinguser);
 | 
        
           |  |  | 867 |   | 
        
           |  |  | 868 |             } else if (!empty($user->password)) {
 | 
        
           |  |  | 869 |                 if ($this->get_update_passwords()) {
 | 
        
           |  |  | 870 |                     // Check for passwords that we want to force users to reset next
 | 
        
           |  |  | 871 |                     // time they log in.
 | 
        
           |  |  | 872 |                     $errmsg = null;
 | 
        
           |  |  | 873 |                     $weak = !check_password_policy($user->password, $errmsg, $user);
 | 
        
           |  |  | 874 |                     if ($this->get_reset_passwords() == UU_PWRESET_ALL or
 | 
        
           |  |  | 875 |                             ($this->get_reset_passwords() == UU_PWRESET_WEAK and $weak)) {
 | 
        
           |  |  | 876 |                         if ($weak) {
 | 
        
           |  |  | 877 |                             $this->weakpasswords++;
 | 
        
           |  |  | 878 |                             $this->upt->track('password', get_string('invalidpasswordpolicy', 'error'), 'warning');
 | 
        
           |  |  | 879 |                         }
 | 
        
           |  |  | 880 |                         set_user_preference('auth_forcepasswordchange', 1, $existinguser);
 | 
        
           |  |  | 881 |                     } else {
 | 
        
           |  |  | 882 |                         unset_user_preference('auth_forcepasswordchange', $existinguser);
 | 
        
           |  |  | 883 |                     }
 | 
        
           |  |  | 884 |                     unset_user_preference('create_password', $existinguser); // No need to create password any more.
 | 
        
           |  |  | 885 |   | 
        
           |  |  | 886 |                     // Use a low cost factor when generating bcrypt hash otherwise
 | 
        
           |  |  | 887 |                     // hashing would be slow when uploading lots of users. Hashes
 | 
        
           |  |  | 888 |                     // will be automatically updated to a higher cost factor the first
 | 
        
           |  |  | 889 |                     // time the user logs in.
 | 
        
           |  |  | 890 |                     $existinguser->password = hash_internal_user_password($user->password, true);
 | 
        
           |  |  | 891 |                     $this->upt->track('password', $user->password, 'normal', false);
 | 
        
           |  |  | 892 |                 } else {
 | 
        
           |  |  | 893 |                     // Do not print password when not changed.
 | 
        
           |  |  | 894 |                     $this->upt->track('password', '', 'normal', false);
 | 
        
           |  |  | 895 |                 }
 | 
        
           |  |  | 896 |             }
 | 
        
           |  |  | 897 |   | 
        
           |  |  | 898 |             if ($doupdate or $existinguser->password !== $oldpw) {
 | 
        
           |  |  | 899 |                 // We want only users that were really updated.
 | 
        
           |  |  | 900 |                 user_update_user($existinguser, false, false);
 | 
        
           |  |  | 901 |   | 
        
           |  |  | 902 |                 $this->upt->track('status', get_string('useraccountupdated', 'tool_uploaduser'));
 | 
        
           |  |  | 903 |                 $this->usersupdated++;
 | 
        
           |  |  | 904 |   | 
        
           |  |  | 905 |                 if (!$remoteuser) {
 | 
        
           |  |  | 906 |                     // Pre-process custom profile menu fields data from csv file.
 | 
        
           |  |  | 907 |                     $existinguser = uu_pre_process_custom_profile_data($existinguser);
 | 
        
           |  |  | 908 |                     // Save custom profile fields data from csv file.
 | 
        
           |  |  | 909 |                     profile_save_data($existinguser);
 | 
        
           |  |  | 910 |                 }
 | 
        
           |  |  | 911 |   | 
        
           |  |  | 912 |                 if ($this->get_bulk() == UU_BULK_UPDATED or $this->get_bulk() == UU_BULK_ALL) {
 | 
        
           | 1441 | ariadna | 913 |                     if (!array_key_exists($user->id, $SESSION->bulk_users)) {
 | 
        
           |  |  | 914 |                         $SESSION->bulk_users[$user->id] = $user->id;
 | 
        
           | 1 | efrain | 915 |                     }
 | 
        
           |  |  | 916 |                 }
 | 
        
           |  |  | 917 |   | 
        
           |  |  | 918 |                 // Trigger event.
 | 
        
           |  |  | 919 |                 \core\event\user_updated::create_from_userid($existinguser->id)->trigger();
 | 
        
           |  |  | 920 |   | 
        
           |  |  | 921 |             } else {
 | 
        
           |  |  | 922 |                 // No user information changed.
 | 
        
           |  |  | 923 |                 $this->upt->track('status', get_string('useraccountuptodate', 'tool_uploaduser'));
 | 
        
           |  |  | 924 |                 $this->usersuptodate++;
 | 
        
           |  |  | 925 |   | 
        
           |  |  | 926 |                 if ($this->get_bulk() == UU_BULK_ALL) {
 | 
        
           | 1441 | ariadna | 927 |                     if (!array_key_exists($user->id, $SESSION->bulk_users)) {
 | 
        
           |  |  | 928 |                         $SESSION->bulk_users[$user->id] = $user->id;
 | 
        
           | 1 | efrain | 929 |                     }
 | 
        
           |  |  | 930 |                 }
 | 
        
           |  |  | 931 |             }
 | 
        
           |  |  | 932 |   | 
        
           |  |  | 933 |             if ($dologout) {
 | 
        
           | 1441 | ariadna | 934 |                 \core\session\manager::destroy_user_sessions($existinguser->id);
 | 
        
           | 1 | efrain | 935 |             }
 | 
        
           |  |  | 936 |   | 
        
           |  |  | 937 |         } else {
 | 
        
           |  |  | 938 |             // Save the new user to the database.
 | 
        
           |  |  | 939 |             $user->confirmed    = 1;
 | 
        
           |  |  | 940 |             $user->timemodified = time();
 | 
        
           |  |  | 941 |             $user->timecreated  = time();
 | 
        
           |  |  | 942 |             $user->mnethostid   = $CFG->mnet_localhost_id; // We support ONLY local accounts here, sorry.
 | 
        
           |  |  | 943 |   | 
        
           |  |  | 944 |             if (!isset($user->suspended) or $user->suspended === '') {
 | 
        
           |  |  | 945 |                 $user->suspended = 0;
 | 
        
           |  |  | 946 |             } else {
 | 
        
           |  |  | 947 |                 $user->suspended = $user->suspended ? 1 : 0;
 | 
        
           |  |  | 948 |             }
 | 
        
           |  |  | 949 |             $this->upt->track('suspended', $this->get_string_yes_no($user->suspended), 'normal', false);
 | 
        
           |  |  | 950 |   | 
        
           |  |  | 951 |             if (empty($user->auth)) {
 | 
        
           |  |  | 952 |                 $user->auth = 'manual';
 | 
        
           |  |  | 953 |             }
 | 
        
           |  |  | 954 |             $this->upt->track('auth', $user->auth, 'normal', false);
 | 
        
           |  |  | 955 |   | 
        
           |  |  | 956 |             // Do not insert record if new auth plugin does not exist!
 | 
        
           |  |  | 957 |             try {
 | 
        
           |  |  | 958 |                 $auth = get_auth_plugin($user->auth);
 | 
        
           |  |  | 959 |             } catch (\Exception $e) {
 | 
        
           |  |  | 960 |                 $this->upt->track('auth', get_string('userautherror', 'error', s($user->auth)), 'error');
 | 
        
           |  |  | 961 |                 $this->upt->track('status', get_string('usernotaddederror', 'error'), 'error');
 | 
        
           |  |  | 962 |                 $this->userserrors++;
 | 
        
           |  |  | 963 |                 return;
 | 
        
           |  |  | 964 |             }
 | 
        
           |  |  | 965 |             if (!isset($this->supportedauths[$user->auth])) {
 | 
        
           |  |  | 966 |                 $this->upt->track('auth', get_string('userauthunsupported', 'error'), 'warning');
 | 
        
           |  |  | 967 |             }
 | 
        
           |  |  | 968 |   | 
        
           |  |  | 969 |             $isinternalauth = $auth->is_internal();
 | 
        
           |  |  | 970 |   | 
        
           |  |  | 971 |             if (empty($user->email)) {
 | 
        
           |  |  | 972 |                 $this->upt->track('email', get_string('invalidemail'), 'error');
 | 
        
           |  |  | 973 |                 $this->upt->track('status', get_string('usernotaddederror', 'error'), 'error');
 | 
        
           |  |  | 974 |                 $this->userserrors++;
 | 
        
           |  |  | 975 |                 return;
 | 
        
           |  |  | 976 |   | 
        
           |  |  | 977 |             } else if ($DB->record_exists('user', ['email' => $user->email])) {
 | 
        
           |  |  | 978 |                 if (!$this->get_allow_email_duplicates()) {
 | 
        
           |  |  | 979 |                     $this->upt->track('email', get_string('useremailduplicate', 'error'), 'error');
 | 
        
           |  |  | 980 |                     $this->upt->track('status', get_string('usernotaddederror', 'error'), 'error');
 | 
        
           |  |  | 981 |                     $this->userserrors++;
 | 
        
           |  |  | 982 |                     return;
 | 
        
           |  |  | 983 |                 } else {
 | 
        
           |  |  | 984 |                     $this->upt->track('email', get_string('useremailduplicate', 'error'), 'warning');
 | 
        
           |  |  | 985 |                 }
 | 
        
           |  |  | 986 |             }
 | 
        
           |  |  | 987 |             if (!validate_email($user->email)) {
 | 
        
           |  |  | 988 |                 $this->upt->track('email', get_string('invalidemail'), 'warning');
 | 
        
           |  |  | 989 |             }
 | 
        
           |  |  | 990 |   | 
        
           |  |  | 991 |             if (empty($user->lang)) {
 | 
        
           |  |  | 992 |                 $user->lang = '';
 | 
        
           |  |  | 993 |             } else if (\core_user::clean_field($user->lang, 'lang') === '') {
 | 
        
           |  |  | 994 |                 $this->upt->track('status', get_string('cannotfindlang', 'error', $user->lang), 'warning');
 | 
        
           |  |  | 995 |                 $user->lang = '';
 | 
        
           |  |  | 996 |             }
 | 
        
           |  |  | 997 |   | 
        
           |  |  | 998 |             $forcechangepassword = false;
 | 
        
           |  |  | 999 |   | 
        
           |  |  | 1000 |             if ($isinternalauth) {
 | 
        
           |  |  | 1001 |                 if (empty($user->password)) {
 | 
        
           |  |  | 1002 |                     if ($this->get_create_paswords()) {
 | 
        
           |  |  | 1003 |                         $user->password = 'to be generated';
 | 
        
           |  |  | 1004 |                         $this->upt->track('password', '', 'normal', false);
 | 
        
           |  |  | 1005 |                         $this->upt->track('password', get_string('uupasswordcron', 'tool_uploaduser'), 'warning', false);
 | 
        
           |  |  | 1006 |                     } else {
 | 
        
           |  |  | 1007 |                         $this->upt->track('password', '', 'normal', false);
 | 
        
           |  |  | 1008 |                         $this->upt->track('password', get_string('missingfield', 'error', 'password'), 'error');
 | 
        
           |  |  | 1009 |                         $this->upt->track('status', get_string('usernotaddederror', 'error'), 'error');
 | 
        
           |  |  | 1010 |                         $this->userserrors++;
 | 
        
           |  |  | 1011 |                         return;
 | 
        
           |  |  | 1012 |                     }
 | 
        
           |  |  | 1013 |                 } else {
 | 
        
           |  |  | 1014 |                     $errmsg = null;
 | 
        
           |  |  | 1015 |                     $weak = !check_password_policy($user->password, $errmsg, $user);
 | 
        
           |  |  | 1016 |                     if ($this->get_reset_passwords() == UU_PWRESET_ALL or
 | 
        
           |  |  | 1017 |                             ($this->get_reset_passwords() == UU_PWRESET_WEAK and $weak)) {
 | 
        
           |  |  | 1018 |                         if ($weak) {
 | 
        
           |  |  | 1019 |                             $this->weakpasswords++;
 | 
        
           |  |  | 1020 |                             $this->upt->track('password', get_string('invalidpasswordpolicy', 'error'), 'warning');
 | 
        
           |  |  | 1021 |                         }
 | 
        
           |  |  | 1022 |                         $forcechangepassword = true;
 | 
        
           |  |  | 1023 |                     }
 | 
        
           |  |  | 1024 |                     // Use a low cost factor when generating bcrypt hash otherwise
 | 
        
           |  |  | 1025 |                     // hashing would be slow when uploading lots of users. Hashes
 | 
        
           |  |  | 1026 |                     // will be automatically updated to a higher cost factor the first
 | 
        
           |  |  | 1027 |                     // time the user logs in.
 | 
        
           |  |  | 1028 |                     $user->password = hash_internal_user_password($user->password, true);
 | 
        
           |  |  | 1029 |                 }
 | 
        
           |  |  | 1030 |             } else {
 | 
        
           |  |  | 1031 |                 $user->password = AUTH_PASSWORD_NOT_CACHED;
 | 
        
           |  |  | 1032 |                 $this->upt->track('password', '-', 'normal', false);
 | 
        
           |  |  | 1033 |             }
 | 
        
           |  |  | 1034 |   | 
        
           |  |  | 1035 |             $user->id = user_create_user($user, false, false);
 | 
        
           |  |  | 1036 |             $this->upt->track('username', \html_writer::link(
 | 
        
           |  |  | 1037 |                 new \moodle_url('/user/profile.php', ['id' => $user->id]), s($user->username)), 'normal', false);
 | 
        
           |  |  | 1038 |   | 
        
           |  |  | 1039 |             // Pre-process custom profile menu fields data from csv file.
 | 
        
           |  |  | 1040 |             $user = uu_pre_process_custom_profile_data($user);
 | 
        
           |  |  | 1041 |             // Save custom profile fields data.
 | 
        
           |  |  | 1042 |             profile_save_data($user);
 | 
        
           |  |  | 1043 |   | 
        
           |  |  | 1044 |             if ($forcechangepassword) {
 | 
        
           |  |  | 1045 |                 set_user_preference('auth_forcepasswordchange', 1, $user);
 | 
        
           |  |  | 1046 |             }
 | 
        
           |  |  | 1047 |             if ($user->password === 'to be generated') {
 | 
        
           |  |  | 1048 |                 set_user_preference('create_password', 1, $user);
 | 
        
           |  |  | 1049 |             }
 | 
        
           |  |  | 1050 |   | 
        
           |  |  | 1051 |             // Trigger event.
 | 
        
           |  |  | 1052 |             \core\event\user_created::create_from_userid($user->id)->trigger();
 | 
        
           |  |  | 1053 |   | 
        
           |  |  | 1054 |             $this->upt->track('status', get_string('newuser'));
 | 
        
           |  |  | 1055 |             $this->upt->track('id', $user->id, 'normal', false);
 | 
        
           |  |  | 1056 |             $this->usersnew++;
 | 
        
           |  |  | 1057 |   | 
        
           |  |  | 1058 |             // Make sure user context exists.
 | 
        
           |  |  | 1059 |             \context_user::instance($user->id);
 | 
        
           |  |  | 1060 |   | 
        
           |  |  | 1061 |             if ($this->get_bulk() == UU_BULK_NEW or $this->get_bulk() == UU_BULK_ALL) {
 | 
        
           | 1441 | ariadna | 1062 |                 if (!array_key_exists($user->id, $SESSION->bulk_users)) {
 | 
        
           |  |  | 1063 |                     $SESSION->bulk_users[$user->id] = $user->id;
 | 
        
           | 1 | efrain | 1064 |                 }
 | 
        
           |  |  | 1065 |             }
 | 
        
           |  |  | 1066 |         }
 | 
        
           |  |  | 1067 |   | 
        
           |  |  | 1068 |         // Update user interests.
 | 
        
           |  |  | 1069 |         if (isset($user->interests) && strval($user->interests) !== '') {
 | 
        
           |  |  | 1070 |             useredit_update_interests($user, preg_split('/\s*,\s*/', $user->interests, -1, PREG_SPLIT_NO_EMPTY));
 | 
        
           |  |  | 1071 |         }
 | 
        
           |  |  | 1072 |   | 
        
           |  |  | 1073 |         // Add to cohort first, it might trigger enrolments indirectly - do NOT create cohorts here!
 | 
        
           |  |  | 1074 |         foreach ($this->get_file_columns() as $column) {
 | 
        
           |  |  | 1075 |             if (!preg_match('/^cohort\d+$/', $column)) {
 | 
        
           |  |  | 1076 |                 continue;
 | 
        
           |  |  | 1077 |             }
 | 
        
           |  |  | 1078 |   | 
        
           |  |  | 1079 |             if (!empty($user->$column)) {
 | 
        
           |  |  | 1080 |                 $addcohort = $user->$column;
 | 
        
           |  |  | 1081 |                 if (!isset($this->cohorts[$addcohort])) {
 | 
        
           |  |  | 1082 |                     if (is_number($addcohort)) {
 | 
        
           |  |  | 1083 |                         // Only non-numeric idnumbers!
 | 
        
           |  |  | 1084 |                         $cohort = $DB->get_record('cohort', ['id' => $addcohort]);
 | 
        
           |  |  | 1085 |                     } else {
 | 
        
           |  |  | 1086 |                         $cohort = $DB->get_record('cohort', ['idnumber' => $addcohort]);
 | 
        
           |  |  | 1087 |                         if (empty($cohort) && has_capability('moodle/cohort:manage', \context_system::instance())) {
 | 
        
           |  |  | 1088 |                             // Cohort was not found. Create a new one.
 | 
        
           |  |  | 1089 |                             $cohortid = cohort_add_cohort((object)array(
 | 
        
           |  |  | 1090 |                                 'idnumber' => $addcohort,
 | 
        
           |  |  | 1091 |                                 'name' => $addcohort,
 | 
        
           |  |  | 1092 |                                 'contextid' => \context_system::instance()->id
 | 
        
           |  |  | 1093 |                             ));
 | 
        
           |  |  | 1094 |                             $cohort = $DB->get_record('cohort', ['id' => $cohortid]);
 | 
        
           |  |  | 1095 |                         }
 | 
        
           |  |  | 1096 |                     }
 | 
        
           |  |  | 1097 |   | 
        
           |  |  | 1098 |                     if (empty($cohort)) {
 | 
        
           |  |  | 1099 |                         $this->cohorts[$addcohort] = get_string('unknowncohort', 'core_cohort', s($addcohort));
 | 
        
           |  |  | 1100 |                     } else if (!empty($cohort->component)) {
 | 
        
           |  |  | 1101 |                         // Cohorts synchronised with external sources must not be modified!
 | 
        
           |  |  | 1102 |                         $this->cohorts[$addcohort] = get_string('external', 'core_cohort');
 | 
        
           |  |  | 1103 |                     } else {
 | 
        
           |  |  | 1104 |                         $this->cohorts[$addcohort] = $cohort;
 | 
        
           |  |  | 1105 |                     }
 | 
        
           |  |  | 1106 |                 }
 | 
        
           |  |  | 1107 |   | 
        
           |  |  | 1108 |                 if (is_object($this->cohorts[$addcohort])) {
 | 
        
           |  |  | 1109 |                     $cohort = $this->cohorts[$addcohort];
 | 
        
           |  |  | 1110 |                     if (!$DB->record_exists('cohort_members', ['cohortid' => $cohort->id, 'userid' => $user->id])) {
 | 
        
           |  |  | 1111 |                         cohort_add_member($cohort->id, $user->id);
 | 
        
           |  |  | 1112 |                         // We might add special column later, for now let's abuse enrolments.
 | 
        
           |  |  | 1113 |                         $this->upt->track('enrolments', get_string('useradded', 'core_cohort', s($cohort->name)), 'info');
 | 
        
           |  |  | 1114 |                     }
 | 
        
           |  |  | 1115 |                 } else {
 | 
        
           |  |  | 1116 |                     // Error message.
 | 
        
           |  |  | 1117 |                     $this->upt->track('enrolments', $this->cohorts[$addcohort], 'error');
 | 
        
           |  |  | 1118 |                 }
 | 
        
           |  |  | 1119 |             }
 | 
        
           |  |  | 1120 |         }
 | 
        
           |  |  | 1121 |   | 
        
           |  |  | 1122 |         // Find course enrolments, groups, roles/types and enrol periods
 | 
        
           |  |  | 1123 |         // this is again a special case, we always do this for any updated or created users.
 | 
        
           |  |  | 1124 |         foreach ($this->get_file_columns() as $column) {
 | 
        
           |  |  | 1125 |             if (preg_match('/^sysrole\d+$/', $column)) {
 | 
        
           |  |  | 1126 |   | 
        
           |  |  | 1127 |                 if (!empty($user->$column)) {
 | 
        
           |  |  | 1128 |                     $sysrolename = $user->$column;
 | 
        
           |  |  | 1129 |                     if ($sysrolename[0] == '-') {
 | 
        
           |  |  | 1130 |                         $removing = true;
 | 
        
           |  |  | 1131 |                         $sysrolename = substr($sysrolename, 1);
 | 
        
           |  |  | 1132 |                     } else {
 | 
        
           |  |  | 1133 |                         $removing = false;
 | 
        
           |  |  | 1134 |                     }
 | 
        
           |  |  | 1135 |   | 
        
           |  |  | 1136 |                     if (array_key_exists($sysrolename, $this->sysrolecache)) {
 | 
        
           |  |  | 1137 |                         $sysroleid = $this->sysrolecache[$sysrolename]->id;
 | 
        
           |  |  | 1138 |                     } else {
 | 
        
           |  |  | 1139 |                         $this->upt->track('enrolments', get_string('unknownrole', 'error', s($sysrolename)), 'error');
 | 
        
           |  |  | 1140 |                         continue;
 | 
        
           |  |  | 1141 |                     }
 | 
        
           |  |  | 1142 |   | 
        
           |  |  | 1143 |                     if ($removing) {
 | 
        
           |  |  | 1144 |                         if (user_has_role_assignment($user->id, $sysroleid, SYSCONTEXTID)) {
 | 
        
           |  |  | 1145 |                             role_unassign($sysroleid, $user->id, SYSCONTEXTID);
 | 
        
           |  |  | 1146 |                             $this->upt->track('enrolments', get_string('unassignedsysrole',
 | 
        
           |  |  | 1147 |                                 'tool_uploaduser', $this->sysrolecache[$sysroleid]->name), 'info');
 | 
        
           |  |  | 1148 |                         }
 | 
        
           |  |  | 1149 |                     } else {
 | 
        
           |  |  | 1150 |                         if (!user_has_role_assignment($user->id, $sysroleid, SYSCONTEXTID)) {
 | 
        
           |  |  | 1151 |                             role_assign($sysroleid, $user->id, SYSCONTEXTID);
 | 
        
           |  |  | 1152 |                             $this->upt->track('enrolments', get_string('assignedsysrole',
 | 
        
           |  |  | 1153 |                                 'tool_uploaduser', $this->sysrolecache[$sysroleid]->name), 'info');
 | 
        
           |  |  | 1154 |                         }
 | 
        
           |  |  | 1155 |                     }
 | 
        
           |  |  | 1156 |                 }
 | 
        
           |  |  | 1157 |   | 
        
           |  |  | 1158 |                 continue;
 | 
        
           |  |  | 1159 |             }
 | 
        
           |  |  | 1160 |   | 
        
           |  |  | 1161 |             if (preg_match('/^categoryrole(?<roleid>\d+)$/', $column, $rolematches)) {
 | 
        
           |  |  | 1162 |                 $categoryrolecache = [];
 | 
        
           |  |  | 1163 |                 $categorycache  = []; // Category cache - do not fetch all categories here, we will not probably use them all.
 | 
        
           |  |  | 1164 |   | 
        
           |  |  | 1165 |                 $categoryfield = "category{$rolematches['roleid']}";
 | 
        
           |  |  | 1166 |                 $categoryrolefield = "categoryrole{$rolematches['roleid']}";
 | 
        
           |  |  | 1167 |   | 
        
           |  |  | 1168 |                 if (empty($user->{$categoryfield})) {
 | 
        
           |  |  | 1169 |                     continue;
 | 
        
           |  |  | 1170 |                 }
 | 
        
           |  |  | 1171 |   | 
        
           |  |  | 1172 |                 $categoryidnumber = $user->{$categoryfield};
 | 
        
           |  |  | 1173 |   | 
        
           |  |  | 1174 |                 if (!array_key_exists($categoryidnumber, $categorycache)) {
 | 
        
           |  |  | 1175 |                     $category = $DB->get_record('course_categories', ['idnumber' => $categoryidnumber], 'id, idnumber');
 | 
        
           |  |  | 1176 |                     if (empty($category)) {
 | 
        
           |  |  | 1177 |                         $this->upt->track('enrolments', get_string('unknowncategory', 'error', s($categoryidnumber)), 'error');
 | 
        
           |  |  | 1178 |                         continue;
 | 
        
           |  |  | 1179 |                     }
 | 
        
           |  |  | 1180 |                     $categoryrolecache[$categoryidnumber] = uu_allowed_roles_cache($category->id);
 | 
        
           |  |  | 1181 |                     $categoryobj = core_course_category::get($category->id);
 | 
        
           |  |  | 1182 |                     $context = context_coursecat::instance($categoryobj->id);
 | 
        
           |  |  | 1183 |                     $categorycache[$categoryidnumber] = $context;
 | 
        
           |  |  | 1184 |                 }
 | 
        
           |  |  | 1185 |                 // Check the user's category role.
 | 
        
           |  |  | 1186 |                 if (!empty($user->{$categoryrolefield})) {
 | 
        
           |  |  | 1187 |                     $rolename = $user->{$categoryrolefield};
 | 
        
           |  |  | 1188 |                     if (array_key_exists($rolename, $categoryrolecache[$categoryidnumber])) {
 | 
        
           |  |  | 1189 |                         $roleid = $categoryrolecache[$categoryidnumber][$rolename]->id;
 | 
        
           |  |  | 1190 |                         // Assign a role to user with category context.
 | 
        
           |  |  | 1191 |                         role_assign($roleid, $user->id, $categorycache[$categoryidnumber]->id);
 | 
        
           |  |  | 1192 |                     } else {
 | 
        
           |  |  | 1193 |                         $this->upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
 | 
        
           |  |  | 1194 |                         continue;
 | 
        
           |  |  | 1195 |                     }
 | 
        
           |  |  | 1196 |                 } else {
 | 
        
           |  |  | 1197 |                     $this->upt->track('enrolments', get_string('missingcategoryrole', 'error', s($categoryidnumber)), 'error');
 | 
        
           |  |  | 1198 |                     continue;
 | 
        
           |  |  | 1199 |                 }
 | 
        
           |  |  | 1200 |             }
 | 
        
           |  |  | 1201 |   | 
        
           |  |  | 1202 |             if (!preg_match('/^course\d+$/', $column)) {
 | 
        
           |  |  | 1203 |                 continue;
 | 
        
           |  |  | 1204 |             }
 | 
        
           |  |  | 1205 |             $i = substr($column, 6);
 | 
        
           |  |  | 1206 |   | 
        
           |  |  | 1207 |             if (empty($user->{'course'.$i})) {
 | 
        
           |  |  | 1208 |                 continue;
 | 
        
           |  |  | 1209 |             }
 | 
        
           |  |  | 1210 |             $shortname = $user->{'course'.$i};
 | 
        
           |  |  | 1211 |             if (!array_key_exists($shortname, $this->ccache)) {
 | 
        
           |  |  | 1212 |                 if (!$course = $DB->get_record('course', ['shortname' => $shortname], 'id, shortname')) {
 | 
        
           |  |  | 1213 |                     $this->upt->track('enrolments', get_string('unknowncourse', 'error', s($shortname)), 'error');
 | 
        
           |  |  | 1214 |                     continue;
 | 
        
           |  |  | 1215 |                 }
 | 
        
           |  |  | 1216 |                 $this->ccache[$shortname] = $course;
 | 
        
           |  |  | 1217 |                 $this->ccache[$shortname]->groups = null;
 | 
        
           |  |  | 1218 |             }
 | 
        
           |  |  | 1219 |             $courseid      = $this->ccache[$shortname]->id;
 | 
        
           |  |  | 1220 |             $coursecontext = \context_course::instance($courseid);
 | 
        
           |  |  | 1221 |             if (!isset($this->manualcache[$courseid])) {
 | 
        
           |  |  | 1222 |                 $this->manualcache[$courseid] = false;
 | 
        
           |  |  | 1223 |                 if ($this->manualenrol) {
 | 
        
           |  |  | 1224 |                     if ($instances = enrol_get_instances($courseid, false)) {
 | 
        
           |  |  | 1225 |                         foreach ($instances as $instance) {
 | 
        
           |  |  | 1226 |                             if ($instance->enrol === 'manual') {
 | 
        
           |  |  | 1227 |                                 $this->manualcache[$courseid] = $instance;
 | 
        
           |  |  | 1228 |                                 break;
 | 
        
           |  |  | 1229 |                             }
 | 
        
           |  |  | 1230 |                         }
 | 
        
           |  |  | 1231 |                     }
 | 
        
           |  |  | 1232 |                 }
 | 
        
           |  |  | 1233 |             }
 | 
        
           |  |  | 1234 |   | 
        
           |  |  | 1235 |             if (!array_key_exists($courseid, $this->rolecache)) {
 | 
        
           |  |  | 1236 |                 $this->rolecache[$courseid] = uu_allowed_roles_cache(null, (int)$courseid);
 | 
        
           |  |  | 1237 |             }
 | 
        
           |  |  | 1238 |   | 
        
           |  |  | 1239 |             if ($courseid == SITEID) {
 | 
        
           |  |  | 1240 |                 // Technically frontpage does not have enrolments, but only role assignments,
 | 
        
           |  |  | 1241 |                 // let's not invent new lang strings here for this rarely used feature.
 | 
        
           |  |  | 1242 |   | 
        
           |  |  | 1243 |                 if (!empty($user->{'role'.$i})) {
 | 
        
           |  |  | 1244 |                     $rolename = $user->{'role'.$i};
 | 
        
           |  |  | 1245 |                     if (array_key_exists($rolename, $this->rolecache[$courseid]) ) {
 | 
        
           |  |  | 1246 |                         $roleid = $this->rolecache[$courseid][$rolename]->id;
 | 
        
           |  |  | 1247 |                     } else {
 | 
        
           |  |  | 1248 |                         $this->upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
 | 
        
           |  |  | 1249 |                         continue;
 | 
        
           |  |  | 1250 |                     }
 | 
        
           |  |  | 1251 |   | 
        
           |  |  | 1252 |                     role_assign($roleid, $user->id, \context_course::instance($courseid));
 | 
        
           |  |  | 1253 |   | 
        
           |  |  | 1254 |                     $a = new \stdClass();
 | 
        
           |  |  | 1255 |                     $a->course = $shortname;
 | 
        
           |  |  | 1256 |                     $a->role = $this->rolecache[$courseid][$roleid]->name;
 | 
        
           |  |  | 1257 |                     $this->upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a), 'info');
 | 
        
           |  |  | 1258 |                 }
 | 
        
           |  |  | 1259 |   | 
        
           |  |  | 1260 |             } else if ($this->manualenrol and $this->manualcache[$courseid]) {
 | 
        
           |  |  | 1261 |   | 
        
           |  |  | 1262 |                 // Find role.
 | 
        
           |  |  | 1263 |                 $roleid = false;
 | 
        
           |  |  | 1264 |                 if (!empty($user->{'role'.$i})) {
 | 
        
           |  |  | 1265 |                     $rolename = $user->{'role'.$i};
 | 
        
           |  |  | 1266 |                     if (array_key_exists($rolename, $this->rolecache[$courseid])) {
 | 
        
           |  |  | 1267 |                         $roleid = $this->rolecache[$courseid][$rolename]->id;
 | 
        
           |  |  | 1268 |                     } else {
 | 
        
           |  |  | 1269 |                         $this->upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
 | 
        
           |  |  | 1270 |                         continue;
 | 
        
           |  |  | 1271 |                     }
 | 
        
           |  |  | 1272 |   | 
        
           |  |  | 1273 |                 } else if (!empty($user->{'type'.$i})) {
 | 
        
           |  |  | 1274 |                     // If no role, then find "old" enrolment type.
 | 
        
           |  |  | 1275 |                     $addtype = $user->{'type'.$i};
 | 
        
           |  |  | 1276 |                     if ($addtype < 1 or $addtype > 3) {
 | 
        
           |  |  | 1277 |                         $this->upt->track('enrolments', get_string('error').': typeN = 1|2|3', 'error');
 | 
        
           |  |  | 1278 |                         continue;
 | 
        
           |  |  | 1279 |                     } else if (empty($this->formdata->{'uulegacy'.$addtype})) {
 | 
        
           |  |  | 1280 |                         continue;
 | 
        
           |  |  | 1281 |                     } else {
 | 
        
           |  |  | 1282 |                         $roleid = $this->formdata->{'uulegacy'.$addtype};
 | 
        
           |  |  | 1283 |                     }
 | 
        
           |  |  | 1284 |                 } else {
 | 
        
           |  |  | 1285 |                     // No role specified, use the default from manual enrol plugin.
 | 
        
           |  |  | 1286 |                     $defaultenrolroleid = (int)$this->manualcache[$courseid]->roleid;
 | 
        
           |  |  | 1287 |                     // Validate the current user can assign this role.
 | 
        
           |  |  | 1288 |                     if (array_key_exists($defaultenrolroleid, $this->rolecache[$courseid]) ) {
 | 
        
           |  |  | 1289 |                         $roleid = $defaultenrolroleid;
 | 
        
           |  |  | 1290 |                     } else {
 | 
        
           |  |  | 1291 |                         $role = $DB->get_record('role', ['id' => $defaultenrolroleid]);
 | 
        
           |  |  | 1292 |                         $this->upt->track('enrolments', get_string('unknownrole', 'error', s($role->shortname)), 'error');
 | 
        
           |  |  | 1293 |                         continue;
 | 
        
           |  |  | 1294 |                     }
 | 
        
           |  |  | 1295 |                 }
 | 
        
           |  |  | 1296 |   | 
        
           |  |  | 1297 |                 if ($roleid) {
 | 
        
           |  |  | 1298 |                     // Find duration and/or enrol status.
 | 
        
           |  |  | 1299 |                     $timeend = 0;
 | 
        
           |  |  | 1300 |                     $timestart = $this->today;
 | 
        
           |  |  | 1301 |                     $status = null;
 | 
        
           |  |  | 1302 |   | 
        
           |  |  | 1303 |                     if (isset($user->{'enrolstatus'.$i})) {
 | 
        
           |  |  | 1304 |                         $enrolstatus = $user->{'enrolstatus'.$i};
 | 
        
           |  |  | 1305 |                         if ($enrolstatus == '') {
 | 
        
           |  |  | 1306 |                             $status = null;
 | 
        
           |  |  | 1307 |                         } else if ($enrolstatus === (string)ENROL_USER_ACTIVE) {
 | 
        
           |  |  | 1308 |                             $status = ENROL_USER_ACTIVE;
 | 
        
           |  |  | 1309 |                         } else if ($enrolstatus === (string)ENROL_USER_SUSPENDED) {
 | 
        
           |  |  | 1310 |                             $status = ENROL_USER_SUSPENDED;
 | 
        
           |  |  | 1311 |                         } else {
 | 
        
           |  |  | 1312 |                             debugging('Unknown enrolment status.');
 | 
        
           |  |  | 1313 |                         }
 | 
        
           |  |  | 1314 |                     }
 | 
        
           |  |  | 1315 |   | 
        
           |  |  | 1316 |                     if (!empty($user->{'enroltimestart'.$i})) {
 | 
        
           |  |  | 1317 |                         $parsedtimestart = strtotime($user->{'enroltimestart'.$i});
 | 
        
           |  |  | 1318 |                         if ($parsedtimestart !== false) {
 | 
        
           |  |  | 1319 |                             $timestart = $parsedtimestart;
 | 
        
           |  |  | 1320 |                         }
 | 
        
           |  |  | 1321 |                     }
 | 
        
           |  |  | 1322 |   | 
        
           |  |  | 1323 |                     if (!empty($user->{'enrolperiod'.$i})) {
 | 
        
           |  |  | 1324 |                         $duration = (int)$user->{'enrolperiod'.$i} * 60 * 60 * 24; // Convert days to seconds.
 | 
        
           |  |  | 1325 |                         if ($duration > 0) { // Sanity check.
 | 
        
           |  |  | 1326 |                             $timeend = $timestart + $duration;
 | 
        
           |  |  | 1327 |                         }
 | 
        
           |  |  | 1328 |                     } else if ($this->manualcache[$courseid]->enrolperiod > 0) {
 | 
        
           |  |  | 1329 |                         $timeend = $timestart + $this->manualcache[$courseid]->enrolperiod;
 | 
        
           |  |  | 1330 |                     }
 | 
        
           |  |  | 1331 |   | 
        
           |  |  | 1332 |                     $this->manualenrol->enrol_user($this->manualcache[$courseid], $user->id, $roleid,
 | 
        
           |  |  | 1333 |                         $timestart, $timeend, $status);
 | 
        
           |  |  | 1334 |   | 
        
           |  |  | 1335 |                     $a = new \stdClass();
 | 
        
           |  |  | 1336 |                     $a->course = $shortname;
 | 
        
           |  |  | 1337 |                     $a->role = $this->rolecache[$courseid][$roleid]->name;
 | 
        
           |  |  | 1338 |                     $this->upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a), 'info');
 | 
        
           |  |  | 1339 |                 }
 | 
        
           |  |  | 1340 |             }
 | 
        
           |  |  | 1341 |   | 
        
           |  |  | 1342 |             // Find group to add to.
 | 
        
           |  |  | 1343 |             if (!empty($user->{'group'.$i})) {
 | 
        
           |  |  | 1344 |                 // Make sure user is enrolled into course before adding into groups.
 | 
        
           |  |  | 1345 |                 if (!is_enrolled($coursecontext, $user->id)) {
 | 
        
           |  |  | 1346 |                     $this->upt->track('enrolments', get_string('addedtogroupnotenrolled', '', $user->{'group'.$i}), 'error');
 | 
        
           |  |  | 1347 |                     continue;
 | 
        
           |  |  | 1348 |                 }
 | 
        
           |  |  | 1349 |                 // Build group cache.
 | 
        
           |  |  | 1350 |                 if (is_null($this->ccache[$shortname]->groups)) {
 | 
        
           |  |  | 1351 |                     $this->ccache[$shortname]->groups = array();
 | 
        
           |  |  | 1352 |                     if ($groups = groups_get_all_groups($courseid)) {
 | 
        
           |  |  | 1353 |                         foreach ($groups as $gid => $group) {
 | 
        
           |  |  | 1354 |                             $this->ccache[$shortname]->groups[$gid] = new \stdClass();
 | 
        
           |  |  | 1355 |                             $this->ccache[$shortname]->groups[$gid]->id   = $gid;
 | 
        
           |  |  | 1356 |                             $this->ccache[$shortname]->groups[$gid]->name = $group->name;
 | 
        
           |  |  | 1357 |                             if (!is_numeric($group->name)) { // Only non-numeric names are supported!!!
 | 
        
           |  |  | 1358 |                                 $this->ccache[$shortname]->groups[$group->name] = new \stdClass();
 | 
        
           |  |  | 1359 |                                 $this->ccache[$shortname]->groups[$group->name]->id   = $gid;
 | 
        
           |  |  | 1360 |                                 $this->ccache[$shortname]->groups[$group->name]->name = $group->name;
 | 
        
           |  |  | 1361 |                             }
 | 
        
           |  |  | 1362 |                         }
 | 
        
           |  |  | 1363 |                     }
 | 
        
           |  |  | 1364 |                 }
 | 
        
           |  |  | 1365 |                 // Group exists?
 | 
        
           |  |  | 1366 |                 $addgroup = $user->{'group'.$i};
 | 
        
           |  |  | 1367 |                 if (!array_key_exists($addgroup, $this->ccache[$shortname]->groups)) {
 | 
        
           |  |  | 1368 |                     // If group doesn't exist,  create it.
 | 
        
           |  |  | 1369 |                     $newgroupdata = new \stdClass();
 | 
        
           |  |  | 1370 |                     $newgroupdata->name = $addgroup;
 | 
        
           |  |  | 1371 |                     $newgroupdata->courseid = $this->ccache[$shortname]->id;
 | 
        
           |  |  | 1372 |                     $newgroupdata->description = '';
 | 
        
           |  |  | 1373 |                     $gid = groups_create_group($newgroupdata);
 | 
        
           |  |  | 1374 |                     if ($gid) {
 | 
        
           |  |  | 1375 |                         $this->ccache[$shortname]->groups[$addgroup] = new \stdClass();
 | 
        
           |  |  | 1376 |                         $this->ccache[$shortname]->groups[$addgroup]->id   = $gid;
 | 
        
           |  |  | 1377 |                         $this->ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name;
 | 
        
           |  |  | 1378 |                     } else {
 | 
        
           |  |  | 1379 |                         $this->upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error');
 | 
        
           |  |  | 1380 |                         continue;
 | 
        
           |  |  | 1381 |                     }
 | 
        
           |  |  | 1382 |                 }
 | 
        
           |  |  | 1383 |                 $gid   = $this->ccache[$shortname]->groups[$addgroup]->id;
 | 
        
           |  |  | 1384 |                 $gname = $this->ccache[$shortname]->groups[$addgroup]->name;
 | 
        
           |  |  | 1385 |   | 
        
           |  |  | 1386 |                 try {
 | 
        
           |  |  | 1387 |                     if (groups_add_member($gid, $user->id)) {
 | 
        
           |  |  | 1388 |                         $this->upt->track('enrolments', get_string('addedtogroup', '', s($gname)), 'info');
 | 
        
           |  |  | 1389 |                     } else {
 | 
        
           |  |  | 1390 |                         $this->upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
 | 
        
           |  |  | 1391 |                     }
 | 
        
           |  |  | 1392 |                 } catch (\moodle_exception $e) {
 | 
        
           |  |  | 1393 |                     $this->upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
 | 
        
           |  |  | 1394 |                     continue;
 | 
        
           |  |  | 1395 |                 }
 | 
        
           |  |  | 1396 |             }
 | 
        
           |  |  | 1397 |         }
 | 
        
           |  |  | 1398 |   | 
        
           |  |  | 1399 |         // Warn user about invalid data values.
 | 
        
           |  |  | 1400 |         if (($invalid = \core_user::validate($user)) !== true) {
 | 
        
           |  |  | 1401 |             $listseparator = get_string('listsep', 'langconfig') . ' ';
 | 
        
           |  |  | 1402 |             $this->upt->track('status', get_string('invaliduserdatavalues', 'tool_uploaduser', [
 | 
        
           |  |  | 1403 |                 'username' => s($user->username),
 | 
        
           |  |  | 1404 |                 'values' => implode($listseparator, array_keys($invalid)),
 | 
        
           |  |  | 1405 |             ]), 'warning');
 | 
        
           |  |  | 1406 |         }
 | 
        
           |  |  | 1407 |     }
 | 
        
           |  |  | 1408 |   | 
        
           |  |  | 1409 |     /**
 | 
        
           |  |  | 1410 |      * Summary about the whole process (how many users created, skipped, updated, etc)
 | 
        
           |  |  | 1411 |      *
 | 
        
           |  |  | 1412 |      * @return array
 | 
        
           |  |  | 1413 |      */
 | 
        
           |  |  | 1414 |     public function get_stats() {
 | 
        
           |  |  | 1415 |         $lines = [];
 | 
        
           |  |  | 1416 |   | 
        
           |  |  | 1417 |         if ($this->get_operation_type() != UU_USER_UPDATE) {
 | 
        
           |  |  | 1418 |             $lines[] = get_string('userscreated', 'tool_uploaduser').': '.$this->usersnew;
 | 
        
           |  |  | 1419 |         }
 | 
        
           |  |  | 1420 |         if ($this->get_operation_type() == UU_USER_UPDATE or $this->get_operation_type() == UU_USER_ADD_UPDATE) {
 | 
        
           |  |  | 1421 |             $lines[] = get_string('usersupdated', 'tool_uploaduser').': '.$this->usersupdated;
 | 
        
           |  |  | 1422 |         }
 | 
        
           |  |  | 1423 |         if ($this->get_allow_deletes()) {
 | 
        
           |  |  | 1424 |             $lines[] = get_string('usersdeleted', 'tool_uploaduser').': '.$this->deletes;
 | 
        
           |  |  | 1425 |             $lines[] = get_string('deleteerrors', 'tool_uploaduser').': '.$this->deleteerrors;
 | 
        
           |  |  | 1426 |         }
 | 
        
           |  |  | 1427 |         if ($this->get_allow_renames()) {
 | 
        
           |  |  | 1428 |             $lines[] = get_string('usersrenamed', 'tool_uploaduser').': '.$this->renames;
 | 
        
           |  |  | 1429 |             $lines[] = get_string('renameerrors', 'tool_uploaduser').': '.$this->renameerrors;
 | 
        
           |  |  | 1430 |         }
 | 
        
           |  |  | 1431 |         if ($usersskipped = $this->usersskipped) {
 | 
        
           |  |  | 1432 |             $lines[] = get_string('usersskipped', 'tool_uploaduser').': '.$usersskipped;
 | 
        
           |  |  | 1433 |         }
 | 
        
           |  |  | 1434 |         $lines[] = get_string('usersweakpassword', 'tool_uploaduser').': '.$this->weakpasswords;
 | 
        
           |  |  | 1435 |         $lines[] = get_string('errors', 'tool_uploaduser').': '.$this->userserrors;
 | 
        
           |  |  | 1436 |   | 
        
           |  |  | 1437 |         return $lines;
 | 
        
           |  |  | 1438 |     }
 | 
        
           |  |  | 1439 | }
 |