[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/admin/tool/uploaduser/ -> index.php (source)

   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   * Bulk user registration script from a comma separated file
  19   *
  20   * @package    tool
  21   * @subpackage uploaduser
  22   * @copyright  2004 onwards Martin Dougiamas (http://dougiamas.com)
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  require('../../../config.php');
  27  require_once($CFG->libdir.'/adminlib.php');
  28  require_once($CFG->libdir.'/csvlib.class.php');
  29  require_once($CFG->dirroot.'/user/profile/lib.php');
  30  require_once($CFG->dirroot.'/user/lib.php');
  31  require_once($CFG->dirroot.'/group/lib.php');
  32  require_once($CFG->dirroot.'/cohort/lib.php');
  33  require_once ('locallib.php');
  34  require_once ('user_form.php');
  35  
  36  $iid         = optional_param('iid', '', PARAM_INT);
  37  $previewrows = optional_param('previewrows', 10, PARAM_INT);
  38  
  39  core_php_time_limit::raise(60*60); // 1 hour should be enough
  40  raise_memory_limit(MEMORY_HUGE);
  41  
  42  require_login();
  43  admin_externalpage_setup('tooluploaduser');
  44  require_capability('moodle/site:uploadusers', context_system::instance());
  45  
  46  $struserrenamed             = get_string('userrenamed', 'tool_uploaduser');
  47  $strusernotrenamedexists    = get_string('usernotrenamedexists', 'error');
  48  $strusernotrenamedmissing   = get_string('usernotrenamedmissing', 'error');
  49  $strusernotrenamedoff       = get_string('usernotrenamedoff', 'error');
  50  $strusernotrenamedadmin     = get_string('usernotrenamedadmin', 'error');
  51  
  52  $struserupdated             = get_string('useraccountupdated', 'tool_uploaduser');
  53  $strusernotupdated          = get_string('usernotupdatederror', 'error');
  54  $strusernotupdatednotexists = get_string('usernotupdatednotexists', 'error');
  55  $strusernotupdatedadmin     = get_string('usernotupdatedadmin', 'error');
  56  
  57  $struseruptodate            = get_string('useraccountuptodate', 'tool_uploaduser');
  58  
  59  $struseradded               = get_string('newuser');
  60  $strusernotadded            = get_string('usernotaddedregistered', 'error');
  61  $strusernotaddederror       = get_string('usernotaddederror', 'error');
  62  
  63  $struserdeleted             = get_string('userdeleted', 'tool_uploaduser');
  64  $strusernotdeletederror     = get_string('usernotdeletederror', 'error');
  65  $strusernotdeletedmissing   = get_string('usernotdeletedmissing', 'error');
  66  $strusernotdeletedoff       = get_string('usernotdeletedoff', 'error');
  67  $strusernotdeletedadmin     = get_string('usernotdeletedadmin', 'error');
  68  
  69  $strcannotassignrole        = get_string('cannotassignrole', 'error');
  70  
  71  $struserauthunsupported     = get_string('userauthunsupported', 'error');
  72  $stremailduplicate          = get_string('useremailduplicate', 'error');
  73  
  74  $strinvalidpasswordpolicy   = get_string('invalidpasswordpolicy', 'error');
  75  $errorstr                   = get_string('error');
  76  
  77  $stryes                     = get_string('yes');
  78  $strno                      = get_string('no');
  79  $stryesnooptions = array(0=>$strno, 1=>$stryes);
  80  
  81  $returnurl = new moodle_url('/admin/tool/uploaduser/index.php');
  82  $bulknurl  = new moodle_url('/admin/user/user_bulk.php');
  83  
  84  $today = time();
  85  $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
  86  
  87  // array of all valid fields for validation
  88  $STD_FIELDS = array('id', 'username', 'email',
  89          'city', 'country', 'lang', 'timezone', 'mailformat',
  90          'maildisplay', 'maildigest', 'htmleditor', 'autosubscribe',
  91          'institution', 'department', 'idnumber', 'skype',
  92          'msn', 'aim', 'yahoo', 'icq', 'phone1', 'phone2', 'address',
  93          'url', 'description', 'descriptionformat', 'password',
  94          'auth',        // watch out when changing auth type or using external auth plugins!
  95          'oldusername', // use when renaming users - this is the original username
  96          'suspended',   // 1 means suspend user account, 0 means activate user account, nothing means keep as is for existing users
  97          'deleted',     // 1 means delete user
  98          'mnethostid',  // Can not be used for adding, updating or deleting of users - only for enrolments, groups, cohorts and suspending.
  99      );
 100  // Include all name fields.
 101  $STD_FIELDS = array_merge($STD_FIELDS, get_all_user_name_fields());
 102  
 103  $PRF_FIELDS = array();
 104  
 105  if ($proffields = $DB->get_records('user_info_field')) {
 106      foreach ($proffields as $key => $proffield) {
 107          $profilefieldname = 'profile_field_'.$proffield->shortname;
 108          $PRF_FIELDS[] = $profilefieldname;
 109          // Re-index $proffields with key as shortname. This will be
 110          // used while checking if profile data is key and needs to be converted (eg. menu profile field)
 111          $proffields[$profilefieldname] = $proffield;
 112          unset($proffields[$key]);
 113      }
 114  }
 115  
 116  if (empty($iid)) {
 117      $mform1 = new admin_uploaduser_form1();
 118  
 119      if ($formdata = $mform1->get_data()) {
 120          $iid = csv_import_reader::get_new_iid('uploaduser');
 121          $cir = new csv_import_reader($iid, 'uploaduser');
 122  
 123          $content = $mform1->get_file_content('userfile');
 124  
 125          $readcount = $cir->load_csv_content($content, $formdata->encoding, $formdata->delimiter_name);
 126          $csvloaderror = $cir->get_error();
 127          unset($content);
 128  
 129          if (!is_null($csvloaderror)) {
 130              print_error('csvloaderror', '', $returnurl, $csvloaderror);
 131          }
 132          // test if columns ok
 133          $filecolumns = uu_validate_user_upload_columns($cir, $STD_FIELDS, $PRF_FIELDS, $returnurl);
 134          // continue to form2
 135  
 136      } else {
 137          echo $OUTPUT->header();
 138  
 139          echo $OUTPUT->heading_with_help(get_string('uploadusers', 'tool_uploaduser'), 'uploadusers', 'tool_uploaduser');
 140  
 141          $mform1->display();
 142          echo $OUTPUT->footer();
 143          die;
 144      }
 145  } else {
 146      $cir = new csv_import_reader($iid, 'uploaduser');
 147      $filecolumns = uu_validate_user_upload_columns($cir, $STD_FIELDS, $PRF_FIELDS, $returnurl);
 148  }
 149  
 150  $mform2 = new admin_uploaduser_form2(null, array('columns'=>$filecolumns, 'data'=>array('iid'=>$iid, 'previewrows'=>$previewrows)));
 151  
 152  // If a file has been uploaded, then process it
 153  if ($formdata = $mform2->is_cancelled()) {
 154      $cir->cleanup(true);
 155      redirect($returnurl);
 156  
 157  } else if ($formdata = $mform2->get_data()) {
 158      // Print the header
 159      echo $OUTPUT->header();
 160      echo $OUTPUT->heading(get_string('uploadusersresult', 'tool_uploaduser'));
 161  
 162      $optype = $formdata->uutype;
 163  
 164      $updatetype        = isset($formdata->uuupdatetype) ? $formdata->uuupdatetype : 0;
 165      $createpasswords   = (!empty($formdata->uupasswordnew) and $optype != UU_USER_UPDATE);
 166      $updatepasswords   = (!empty($formdata->uupasswordold)  and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC and ($updatetype == UU_UPDATE_FILEOVERRIDE or $updatetype == UU_UPDATE_ALLOVERRIDE));
 167      $allowrenames      = (!empty($formdata->uuallowrenames) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC);
 168      $allowdeletes      = (!empty($formdata->uuallowdeletes) and $optype != UU_USER_ADDNEW and $optype != UU_USER_ADDINC);
 169      $allowsuspends     = (!empty($formdata->uuallowsuspends));
 170      $bulk              = $formdata->uubulk;
 171      $noemailduplicates = $formdata->uunoemailduplicates;
 172      $standardusernames = $formdata->uustandardusernames;
 173      $resetpasswords    = isset($formdata->uuforcepasswordchange) ? $formdata->uuforcepasswordchange : UU_PWRESET_NONE;
 174  
 175      // verification moved to two places: after upload and into form2
 176      $usersnew      = 0;
 177      $usersupdated  = 0;
 178      $usersuptodate = 0; //not printed yet anywhere
 179      $userserrors   = 0;
 180      $deletes       = 0;
 181      $deleteerrors  = 0;
 182      $renames       = 0;
 183      $renameerrors  = 0;
 184      $usersskipped  = 0;
 185      $weakpasswords = 0;
 186  
 187      // caches
 188      $ccache         = array(); // course cache - do not fetch all courses here, we  will not probably use them all anyway!
 189      $cohorts        = array();
 190      $rolecache      = uu_allowed_roles_cache(); // roles lookup cache
 191      $manualcache    = array(); // cache of used manual enrol plugins in each course
 192      $supportedauths = uu_supported_auths(); // officially supported plugins that are enabled
 193  
 194      // we use only manual enrol plugin here, if it is disabled no enrol is done
 195      if (enrol_is_enabled('manual')) {
 196          $manual = enrol_get_plugin('manual');
 197      } else {
 198          $manual = NULL;
 199      }
 200  
 201      // clear bulk selection
 202      if ($bulk) {
 203          $SESSION->bulk_users = array();
 204      }
 205  
 206      // init csv import helper
 207      $cir->init();
 208      $linenum = 1; //column header is first line
 209  
 210      // init upload progress tracker
 211      $upt = new uu_progress_tracker();
 212      $upt->start(); // start table
 213  
 214      while ($line = $cir->next()) {
 215          $upt->flush();
 216          $linenum++;
 217  
 218          $upt->track('line', $linenum);
 219  
 220          $user = new stdClass();
 221  
 222          // add fields to user object
 223          foreach ($line as $keynum => $value) {
 224              if (!isset($filecolumns[$keynum])) {
 225                  // this should not happen
 226                  continue;
 227              }
 228              $key = $filecolumns[$keynum];
 229              if (strpos($key, 'profile_field_') === 0) {
 230                  //NOTE: bloody mega hack alert!!
 231                  if (isset($USER->$key) and is_array($USER->$key)) {
 232                      // this must be some hacky field that is abusing arrays to store content and format
 233                      $user->$key = array();
 234                      $user->$key['text']   = $value;
 235                      $user->$key['format'] = FORMAT_MOODLE;
 236                  } else {
 237                      $user->$key = trim($value);
 238                  }
 239              } else {
 240                  $user->$key = trim($value);
 241              }
 242  
 243              if (in_array($key, $upt->columns)) {
 244                  // default value in progress tracking table, can be changed later
 245                  $upt->track($key, s($value), 'normal');
 246              }
 247          }
 248          if (!isset($user->username)) {
 249              // prevent warnings below
 250              $user->username = '';
 251          }
 252  
 253          if ($optype == UU_USER_ADDNEW or $optype == UU_USER_ADDINC) {
 254              // user creation is a special case - the username may be constructed from templates using firstname and lastname
 255              // better never try this in mixed update types
 256              $error = false;
 257              if (!isset($user->firstname) or $user->firstname === '') {
 258                  $upt->track('status', get_string('missingfield', 'error', 'firstname'), 'error');
 259                  $upt->track('firstname', $errorstr, 'error');
 260                  $error = true;
 261              }
 262              if (!isset($user->lastname) or $user->lastname === '') {
 263                  $upt->track('status', get_string('missingfield', 'error', 'lastname'), 'error');
 264                  $upt->track('lastname', $errorstr, 'error');
 265                  $error = true;
 266              }
 267              if ($error) {
 268                  $userserrors++;
 269                  continue;
 270              }
 271              // we require username too - we might use template for it though
 272              if (empty($user->username) and !empty($formdata->username)) {
 273                  $user->username = uu_process_template($formdata->username, $user);
 274                  $upt->track('username', s($user->username));
 275              }
 276          }
 277  
 278          // normalize username
 279          $originalusername = $user->username;
 280          if ($standardusernames) {
 281              $user->username = clean_param($user->username, PARAM_USERNAME);
 282          }
 283  
 284          // make sure we really have username
 285          if (empty($user->username)) {
 286              $upt->track('status', get_string('missingfield', 'error', 'username'), 'error');
 287              $upt->track('username', $errorstr, 'error');
 288              $userserrors++;
 289              continue;
 290          } else if ($user->username === 'guest') {
 291              $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
 292              $userserrors++;
 293              continue;
 294          }
 295  
 296          if ($user->username !== clean_param($user->username, PARAM_USERNAME)) {
 297              $upt->track('status', get_string('invalidusername', 'error', 'username'), 'error');
 298              $upt->track('username', $errorstr, 'error');
 299              $userserrors++;
 300          }
 301  
 302          if (empty($user->mnethostid)) {
 303              $user->mnethostid = $CFG->mnet_localhost_id;
 304          }
 305  
 306          if ($existinguser = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$user->mnethostid))) {
 307              $upt->track('id', $existinguser->id, 'normal', false);
 308          }
 309  
 310          if ($user->mnethostid == $CFG->mnet_localhost_id) {
 311              $remoteuser = false;
 312  
 313              // Find out if username incrementing required.
 314              if ($existinguser and $optype == UU_USER_ADDINC) {
 315                  $user->username = uu_increment_username($user->username);
 316                  $existinguser = false;
 317              }
 318  
 319          } else {
 320              if (!$existinguser or $optype == UU_USER_ADDINC) {
 321                  $upt->track('status', get_string('errormnetadd', 'tool_uploaduser'), 'error');
 322                  $userserrors++;
 323                  continue;
 324              }
 325  
 326              $remoteuser = true;
 327  
 328              // Make sure there are no changes of existing fields except the suspended status.
 329              foreach ((array)$existinguser as $k => $v) {
 330                  if ($k === 'suspended') {
 331                      continue;
 332                  }
 333                  if (property_exists($user, $k)) {
 334                      $user->$k = $v;
 335                  }
 336                  if (in_array($k, $upt->columns)) {
 337                      if ($k === 'password' or $k === 'oldusername' or $k === 'deleted') {
 338                          $upt->track($k, '', 'normal', false);
 339                      } else {
 340                          $upt->track($k, s($v), 'normal', false);
 341                      }
 342                  }
 343              }
 344              unset($user->oldusername);
 345              unset($user->password);
 346              $user->auth = $existinguser->auth;
 347          }
 348  
 349          // notify about nay username changes
 350          if ($originalusername !== $user->username) {
 351              $upt->track('username', '', 'normal', false); // clear previous
 352              $upt->track('username', s($originalusername).'-->'.s($user->username), 'info');
 353          } else {
 354              $upt->track('username', s($user->username), 'normal', false);
 355          }
 356  
 357          // add default values for remaining fields
 358          $formdefaults = array();
 359          foreach ($STD_FIELDS as $field) {
 360              if (isset($user->$field)) {
 361                  continue;
 362              }
 363              // all validation moved to form2
 364              if (isset($formdata->$field)) {
 365                  // process templates
 366                  $user->$field = uu_process_template($formdata->$field, $user);
 367                  $formdefaults[$field] = true;
 368                  if (in_array($field, $upt->columns)) {
 369                      $upt->track($field, s($user->$field), 'normal');
 370                  }
 371              }
 372          }
 373          foreach ($PRF_FIELDS as $field) {
 374              if (isset($user->$field)) {
 375                  continue;
 376              }
 377              if (isset($formdata->$field)) {
 378                  // process templates
 379                  $user->$field = uu_process_template($formdata->$field, $user);
 380  
 381                  // Form contains key and later code expects value.
 382                  // Convert key to value for required profile fields.
 383                  require_once($CFG->dirroot.'/user/profile/field/'.$proffields[$field]->datatype.'/field.class.php');
 384                  $profilefieldclass = 'profile_field_'.$proffields[$field]->datatype;
 385                  $profilefield = new $profilefieldclass($proffields[$field]->id);
 386                  if (method_exists($profilefield, 'convert_external_data')) {
 387                      $user->$field = $profilefield->edit_save_data_preprocess($user->$field, null);
 388                  }
 389  
 390                  $formdefaults[$field] = true;
 391              }
 392          }
 393  
 394          // delete user
 395          if (!empty($user->deleted)) {
 396              if (!$allowdeletes or $remoteuser) {
 397                  $usersskipped++;
 398                  $upt->track('status', $strusernotdeletedoff, 'warning');
 399                  continue;
 400              }
 401              if ($existinguser) {
 402                  if (is_siteadmin($existinguser->id)) {
 403                      $upt->track('status', $strusernotdeletedadmin, 'error');
 404                      $deleteerrors++;
 405                      continue;
 406                  }
 407                  if (delete_user($existinguser)) {
 408                      $upt->track('status', $struserdeleted);
 409                      $deletes++;
 410                  } else {
 411                      $upt->track('status', $strusernotdeletederror, 'error');
 412                      $deleteerrors++;
 413                  }
 414              } else {
 415                  $upt->track('status', $strusernotdeletedmissing, 'error');
 416                  $deleteerrors++;
 417              }
 418              continue;
 419          }
 420          // we do not need the deleted flag anymore
 421          unset($user->deleted);
 422  
 423          // renaming requested?
 424          if (!empty($user->oldusername) ) {
 425              if (!$allowrenames) {
 426                  $usersskipped++;
 427                  $upt->track('status', $strusernotrenamedoff, 'warning');
 428                  continue;
 429              }
 430  
 431              if ($existinguser) {
 432                  $upt->track('status', $strusernotrenamedexists, 'error');
 433                  $renameerrors++;
 434                  continue;
 435              }
 436  
 437              if ($user->username === 'guest') {
 438                  $upt->track('status', get_string('guestnoeditprofileother', 'error'), 'error');
 439                  $renameerrors++;
 440                  continue;
 441              }
 442  
 443              if ($standardusernames) {
 444                  $oldusername = clean_param($user->oldusername, PARAM_USERNAME);
 445              } else {
 446                  $oldusername = $user->oldusername;
 447              }
 448  
 449              // no guessing when looking for old username, it must be exact match
 450              if ($olduser = $DB->get_record('user', array('username'=>$oldusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
 451                  $upt->track('id', $olduser->id, 'normal', false);
 452                  if (is_siteadmin($olduser->id)) {
 453                      $upt->track('status', $strusernotrenamedadmin, 'error');
 454                      $renameerrors++;
 455                      continue;
 456                  }
 457                  $DB->set_field('user', 'username', $user->username, array('id'=>$olduser->id));
 458                  $upt->track('username', '', 'normal', false); // clear previous
 459                  $upt->track('username', s($oldusername).'-->'.s($user->username), 'info');
 460                  $upt->track('status', $struserrenamed);
 461                  $renames++;
 462              } else {
 463                  $upt->track('status', $strusernotrenamedmissing, 'error');
 464                  $renameerrors++;
 465                  continue;
 466              }
 467              $existinguser = $olduser;
 468              $existinguser->username = $user->username;
 469          }
 470  
 471          // can we process with update or insert?
 472          $skip = false;
 473          switch ($optype) {
 474              case UU_USER_ADDNEW:
 475                  if ($existinguser) {
 476                      $usersskipped++;
 477                      $upt->track('status', $strusernotadded, 'warning');
 478                      $skip = true;
 479                  }
 480                  break;
 481  
 482              case UU_USER_ADDINC:
 483                  if ($existinguser) {
 484                      //this should not happen!
 485                      $upt->track('status', $strusernotaddederror, 'error');
 486                      $userserrors++;
 487                      $skip = true;
 488                  }
 489                  break;
 490  
 491              case UU_USER_ADD_UPDATE:
 492                  break;
 493  
 494              case UU_USER_UPDATE:
 495                  if (!$existinguser) {
 496                      $usersskipped++;
 497                      $upt->track('status', $strusernotupdatednotexists, 'warning');
 498                      $skip = true;
 499                  }
 500                  break;
 501  
 502              default:
 503                  // unknown type
 504                  $skip = true;
 505          }
 506  
 507          if ($skip) {
 508              continue;
 509          }
 510  
 511          if ($existinguser) {
 512              $user->id = $existinguser->id;
 513  
 514              $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$existinguser->id)), s($existinguser->username)), 'normal', false);
 515              $upt->track('suspended', $stryesnooptions[$existinguser->suspended] , 'normal', false);
 516              $upt->track('auth', $existinguser->auth, 'normal', false);
 517  
 518              if (is_siteadmin($user->id)) {
 519                  $upt->track('status', $strusernotupdatedadmin, 'error');
 520                  $userserrors++;
 521                  continue;
 522              }
 523  
 524              $existinguser->timemodified = time();
 525              // do NOT mess with timecreated or firstaccess here!
 526  
 527              //load existing profile data
 528              profile_load_data($existinguser);
 529  
 530              $doupdate = false;
 531              $dologout = false;
 532  
 533              if ($updatetype != UU_UPDATE_NOCHANGES and !$remoteuser) {
 534                  if (!empty($user->auth) and $user->auth !== $existinguser->auth) {
 535                      $upt->track('auth', s($existinguser->auth).'-->'.s($user->auth), 'info', false);
 536                      $existinguser->auth = $user->auth;
 537                      if (!isset($supportedauths[$user->auth])) {
 538                          $upt->track('auth', $struserauthunsupported, 'warning');
 539                      }
 540                      $doupdate = true;
 541                      if ($existinguser->auth === 'nologin') {
 542                          $dologout = true;
 543                      }
 544                  }
 545                  $allcolumns = array_merge($STD_FIELDS, $PRF_FIELDS);
 546                  foreach ($allcolumns as $column) {
 547                      if ($column === 'username' or $column === 'password' or $column === 'auth' or $column === 'suspended') {
 548                          // these can not be changed here
 549                          continue;
 550                      }
 551                      if (!property_exists($user, $column) or !property_exists($existinguser, $column)) {
 552                          continue;
 553                      }
 554                      if ($updatetype == UU_UPDATE_MISSING) {
 555                          if (!is_null($existinguser->$column) and $existinguser->$column !== '') {
 556                              continue;
 557                          }
 558                      } else if ($updatetype == UU_UPDATE_ALLOVERRIDE) {
 559                          // we override everything
 560  
 561                      } else if ($updatetype == UU_UPDATE_FILEOVERRIDE) {
 562                          if (!empty($formdefaults[$column])) {
 563                              // do not override with form defaults
 564                              continue;
 565                          }
 566                      }
 567                      if ($existinguser->$column !== $user->$column) {
 568                          if ($column === 'email') {
 569                              if ($DB->record_exists('user', array('email'=>$user->email))) {
 570                                  if ($noemailduplicates) {
 571                                      $upt->track('email', $stremailduplicate, 'error');
 572                                      $upt->track('status', $strusernotupdated, 'error');
 573                                      $userserrors++;
 574                                      continue 2;
 575                                  } else {
 576                                      $upt->track('email', $stremailduplicate, 'warning');
 577                                  }
 578                              }
 579                              if (!validate_email($user->email)) {
 580                                  $upt->track('email', get_string('invalidemail'), 'warning');
 581                              }
 582                          }
 583  
 584                          if ($column === 'lang') {
 585                              if (empty($user->lang)) {
 586                                  // Do not change to not-set value.
 587                                  continue;
 588                              } else if (clean_param($user->lang, PARAM_LANG) === '') {
 589                                  $upt->track('status', get_string('cannotfindlang', 'error', $user->lang), 'warning');
 590                                  continue;
 591                              }
 592                          }
 593  
 594                          if (in_array($column, $upt->columns)) {
 595                              $upt->track($column, s($existinguser->$column).'-->'.s($user->$column), 'info', false);
 596                          }
 597                          $existinguser->$column = $user->$column;
 598                          $doupdate = true;
 599                      }
 600                  }
 601              }
 602  
 603              try {
 604                  $auth = get_auth_plugin($existinguser->auth);
 605              } catch (Exception $e) {
 606                  $upt->track('auth', get_string('userautherror', 'error', s($existinguser->auth)), 'error');
 607                  $upt->track('status', $strusernotupdated, 'error');
 608                  $userserrors++;
 609                  continue;
 610              }
 611              $isinternalauth = $auth->is_internal();
 612  
 613              // deal with suspending and activating of accounts
 614              if ($allowsuspends and isset($user->suspended) and $user->suspended !== '') {
 615                  $user->suspended = $user->suspended ? 1 : 0;
 616                  if ($existinguser->suspended != $user->suspended) {
 617                      $upt->track('suspended', '', 'normal', false);
 618                      $upt->track('suspended', $stryesnooptions[$existinguser->suspended].'-->'.$stryesnooptions[$user->suspended], 'info', false);
 619                      $existinguser->suspended = $user->suspended;
 620                      $doupdate = true;
 621                      if ($existinguser->suspended) {
 622                          $dologout = true;
 623                      }
 624                  }
 625              }
 626  
 627              // changing of passwords is a special case
 628              // do not force password changes for external auth plugins!
 629              $oldpw = $existinguser->password;
 630  
 631              if ($remoteuser) {
 632                  // Do not mess with passwords of remote users.
 633  
 634              } else if (!$isinternalauth) {
 635                  $existinguser->password = AUTH_PASSWORD_NOT_CACHED;
 636                  $upt->track('password', '-', 'normal', false);
 637                  // clean up prefs
 638                  unset_user_preference('create_password', $existinguser);
 639                  unset_user_preference('auth_forcepasswordchange', $existinguser);
 640  
 641              } else if (!empty($user->password)) {
 642                  if ($updatepasswords) {
 643                      // Check for passwords that we want to force users to reset next
 644                      // time they log in.
 645                      $errmsg = null;
 646                      $weak = !check_password_policy($user->password, $errmsg);
 647                      if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
 648                          if ($weak) {
 649                              $weakpasswords++;
 650                              $upt->track('password', $strinvalidpasswordpolicy, 'warning');
 651                          }
 652                          set_user_preference('auth_forcepasswordchange', 1, $existinguser);
 653                      } else {
 654                          unset_user_preference('auth_forcepasswordchange', $existinguser);
 655                      }
 656                      unset_user_preference('create_password', $existinguser); // no need to create password any more
 657  
 658                      // Use a low cost factor when generating bcrypt hash otherwise
 659                      // hashing would be slow when uploading lots of users. Hashes
 660                      // will be automatically updated to a higher cost factor the first
 661                      // time the user logs in.
 662                      $existinguser->password = hash_internal_user_password($user->password, true);
 663                      $upt->track('password', $user->password, 'normal', false);
 664                  } else {
 665                      // do not print password when not changed
 666                      $upt->track('password', '', 'normal', false);
 667                  }
 668              }
 669  
 670              if ($doupdate or $existinguser->password !== $oldpw) {
 671                  // We want only users that were really updated.
 672                  user_update_user($existinguser, false, false);
 673  
 674                  $upt->track('status', $struserupdated);
 675                  $usersupdated++;
 676  
 677                  if (!$remoteuser) {
 678                      // pre-process custom profile menu fields data from csv file
 679                      $existinguser = uu_pre_process_custom_profile_data($existinguser);
 680                      // save custom profile fields data from csv file
 681                      profile_save_data($existinguser);
 682                  }
 683  
 684                  if ($bulk == UU_BULK_UPDATED or $bulk == UU_BULK_ALL) {
 685                      if (!in_array($user->id, $SESSION->bulk_users)) {
 686                          $SESSION->bulk_users[] = $user->id;
 687                      }
 688                  }
 689  
 690                  // Trigger event.
 691                  \core\event\user_updated::create_from_userid($existinguser->id)->trigger();
 692  
 693              } else {
 694                  // no user information changed
 695                  $upt->track('status', $struseruptodate);
 696                  $usersuptodate++;
 697  
 698                  if ($bulk == UU_BULK_ALL) {
 699                      if (!in_array($user->id, $SESSION->bulk_users)) {
 700                          $SESSION->bulk_users[] = $user->id;
 701                      }
 702                  }
 703              }
 704  
 705              if ($dologout) {
 706                  \core\session\manager::kill_user_sessions($existinguser->id);
 707              }
 708  
 709          } else {
 710              // save the new user to the database
 711              $user->confirmed    = 1;
 712              $user->timemodified = time();
 713              $user->timecreated  = time();
 714              $user->mnethostid   = $CFG->mnet_localhost_id; // we support ONLY local accounts here, sorry
 715  
 716              if (!isset($user->suspended) or $user->suspended === '') {
 717                  $user->suspended = 0;
 718              } else {
 719                  $user->suspended = $user->suspended ? 1 : 0;
 720              }
 721              $upt->track('suspended', $stryesnooptions[$user->suspended], 'normal', false);
 722  
 723              if (empty($user->auth)) {
 724                  $user->auth = 'manual';
 725              }
 726              $upt->track('auth', $user->auth, 'normal', false);
 727  
 728              // do not insert record if new auth plugin does not exist!
 729              try {
 730                  $auth = get_auth_plugin($user->auth);
 731              } catch (Exception $e) {
 732                  $upt->track('auth', get_string('userautherror', 'error', s($user->auth)), 'error');
 733                  $upt->track('status', $strusernotaddederror, 'error');
 734                  $userserrors++;
 735                  continue;
 736              }
 737              if (!isset($supportedauths[$user->auth])) {
 738                  $upt->track('auth', $struserauthunsupported, 'warning');
 739              }
 740  
 741              $isinternalauth = $auth->is_internal();
 742  
 743              if (empty($user->email)) {
 744                  $upt->track('email', get_string('invalidemail'), 'error');
 745                  $upt->track('status', $strusernotaddederror, 'error');
 746                  $userserrors++;
 747                  continue;
 748  
 749              } else if ($DB->record_exists('user', array('email'=>$user->email))) {
 750                  if ($noemailduplicates) {
 751                      $upt->track('email', $stremailduplicate, 'error');
 752                      $upt->track('status', $strusernotaddederror, 'error');
 753                      $userserrors++;
 754                      continue;
 755                  } else {
 756                      $upt->track('email', $stremailduplicate, 'warning');
 757                  }
 758              }
 759              if (!validate_email($user->email)) {
 760                  $upt->track('email', get_string('invalidemail'), 'warning');
 761              }
 762  
 763              if (empty($user->lang)) {
 764                  $user->lang = '';
 765              } else if (clean_param($user->lang, PARAM_LANG) === '') {
 766                  $upt->track('status', get_string('cannotfindlang', 'error', $user->lang), 'warning');
 767                  $user->lang = '';
 768              }
 769  
 770              $forcechangepassword = false;
 771  
 772              if ($isinternalauth) {
 773                  if (empty($user->password)) {
 774                      if ($createpasswords) {
 775                          $user->password = 'to be generated';
 776                          $upt->track('password', '', 'normal', false);
 777                          $upt->track('password', get_string('uupasswordcron', 'tool_uploaduser'), 'warning', false);
 778                      } else {
 779                          $upt->track('password', '', 'normal', false);
 780                          $upt->track('password', get_string('missingfield', 'error', 'password'), 'error');
 781                          $upt->track('status', $strusernotaddederror, 'error');
 782                          $userserrors++;
 783                          continue;
 784                      }
 785                  } else {
 786                      $errmsg = null;
 787                      $weak = !check_password_policy($user->password, $errmsg);
 788                      if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
 789                          if ($weak) {
 790                              $weakpasswords++;
 791                              $upt->track('password', $strinvalidpasswordpolicy, 'warning');
 792                          }
 793                          $forcechangepassword = true;
 794                      }
 795                      // Use a low cost factor when generating bcrypt hash otherwise
 796                      // hashing would be slow when uploading lots of users. Hashes
 797                      // will be automatically updated to a higher cost factor the first
 798                      // time the user logs in.
 799                      $user->password = hash_internal_user_password($user->password, true);
 800                  }
 801              } else {
 802                  $user->password = AUTH_PASSWORD_NOT_CACHED;
 803                  $upt->track('password', '-', 'normal', false);
 804              }
 805  
 806              $user->id = user_create_user($user, false, false);
 807              $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id'=>$user->id)), s($user->username)), 'normal', false);
 808  
 809              // pre-process custom profile menu fields data from csv file
 810              $user = uu_pre_process_custom_profile_data($user);
 811              // save custom profile fields data
 812              profile_save_data($user);
 813  
 814              if ($forcechangepassword) {
 815                  set_user_preference('auth_forcepasswordchange', 1, $user);
 816              }
 817              if ($user->password === 'to be generated') {
 818                  set_user_preference('create_password', 1, $user);
 819              }
 820  
 821              // Trigger event.
 822              \core\event\user_created::create_from_userid($user->id)->trigger();
 823  
 824              $upt->track('status', $struseradded);
 825              $upt->track('id', $user->id, 'normal', false);
 826              $usersnew++;
 827  
 828              // make sure user context exists
 829              context_user::instance($user->id);
 830  
 831              if ($bulk == UU_BULK_NEW or $bulk == UU_BULK_ALL) {
 832                  if (!in_array($user->id, $SESSION->bulk_users)) {
 833                      $SESSION->bulk_users[] = $user->id;
 834                  }
 835              }
 836          }
 837  
 838  
 839          // add to cohort first, it might trigger enrolments indirectly - do NOT create cohorts here!
 840          foreach ($filecolumns as $column) {
 841              if (!preg_match('/^cohort\d+$/', $column)) {
 842                  continue;
 843              }
 844  
 845              if (!empty($user->$column)) {
 846                  $addcohort = $user->$column;
 847                  if (!isset($cohorts[$addcohort])) {
 848                      if (is_number($addcohort)) {
 849                          // only non-numeric idnumbers!
 850                          $cohort = $DB->get_record('cohort', array('id'=>$addcohort));
 851                      } else {
 852                          $cohort = $DB->get_record('cohort', array('idnumber'=>$addcohort));
 853                          if (empty($cohort) && has_capability('moodle/cohort:manage', context_system::instance())) {
 854                              // Cohort was not found. Create a new one.
 855                              $cohortid = cohort_add_cohort((object)array(
 856                                  'idnumber' => $addcohort,
 857                                  'name' => $addcohort,
 858                                  'contextid' => context_system::instance()->id
 859                              ));
 860                              $cohort = $DB->get_record('cohort', array('id'=>$cohortid));
 861                          }
 862                      }
 863  
 864                      if (empty($cohort)) {
 865                          $cohorts[$addcohort] = get_string('unknowncohort', 'core_cohort', s($addcohort));
 866                      } else if (!empty($cohort->component)) {
 867                          // cohorts synchronised with external sources must not be modified!
 868                          $cohorts[$addcohort] = get_string('external', 'core_cohort');
 869                      } else {
 870                          $cohorts[$addcohort] = $cohort;
 871                      }
 872                  }
 873  
 874                  if (is_object($cohorts[$addcohort])) {
 875                      $cohort = $cohorts[$addcohort];
 876                      if (!$DB->record_exists('cohort_members', array('cohortid'=>$cohort->id, 'userid'=>$user->id))) {
 877                          cohort_add_member($cohort->id, $user->id);
 878                          // we might add special column later, for now let's abuse enrolments
 879                          $upt->track('enrolments', get_string('useradded', 'core_cohort', s($cohort->name)));
 880                      }
 881                  } else {
 882                      // error message
 883                      $upt->track('enrolments', $cohorts[$addcohort], 'error');
 884                  }
 885              }
 886          }
 887  
 888  
 889          // find course enrolments, groups, roles/types and enrol periods
 890          // this is again a special case, we always do this for any updated or created users
 891          foreach ($filecolumns as $column) {
 892              if (!preg_match('/^course\d+$/', $column)) {
 893                  continue;
 894              }
 895              $i = substr($column, 6);
 896  
 897              if (empty($user->{'course'.$i})) {
 898                  continue;
 899              }
 900              $shortname = $user->{'course'.$i};
 901              if (!array_key_exists($shortname, $ccache)) {
 902                  if (!$course = $DB->get_record('course', array('shortname'=>$shortname), 'id, shortname')) {
 903                      $upt->track('enrolments', get_string('unknowncourse', 'error', s($shortname)), 'error');
 904                      continue;
 905                  }
 906                  $ccache[$shortname] = $course;
 907                  $ccache[$shortname]->groups = null;
 908              }
 909              $courseid      = $ccache[$shortname]->id;
 910              $coursecontext = context_course::instance($courseid);
 911              if (!isset($manualcache[$courseid])) {
 912                  $manualcache[$courseid] = false;
 913                  if ($manual) {
 914                      if ($instances = enrol_get_instances($courseid, false)) {
 915                          foreach ($instances as $instance) {
 916                              if ($instance->enrol === 'manual') {
 917                                  $manualcache[$courseid] = $instance;
 918                                  break;
 919                              }
 920                          }
 921                      }
 922                  }
 923              }
 924  
 925              if ($courseid == SITEID) {
 926                  // Technically frontpage does not have enrolments, but only role assignments,
 927                  // let's not invent new lang strings here for this rarely used feature.
 928  
 929                  if (!empty($user->{'role'.$i})) {
 930                      $addrole = $user->{'role'.$i};
 931                      if (array_key_exists($addrole, $rolecache)) {
 932                          $rid = $rolecache[$addrole]->id;
 933                      } else {
 934                          $upt->track('enrolments', get_string('unknownrole', 'error', s($addrole)), 'error');
 935                          continue;
 936                      }
 937  
 938                      role_assign($rid, $user->id, context_course::instance($courseid));
 939  
 940                      $a = new stdClass();
 941                      $a->course = $shortname;
 942                      $a->role   = $rolecache[$rid]->name;
 943                      $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
 944                  }
 945  
 946              } else if ($manual and $manualcache[$courseid]) {
 947  
 948                  // find role
 949                  $rid = false;
 950                  if (!empty($user->{'role'.$i})) {
 951                      $addrole = $user->{'role'.$i};
 952                      if (array_key_exists($addrole, $rolecache)) {
 953                          $rid = $rolecache[$addrole]->id;
 954                      } else {
 955                          $upt->track('enrolments', get_string('unknownrole', 'error', s($addrole)), 'error');
 956                          continue;
 957                      }
 958  
 959                  } else if (!empty($user->{'type'.$i})) {
 960                      // if no role, then find "old" enrolment type
 961                      $addtype = $user->{'type'.$i};
 962                      if ($addtype < 1 or $addtype > 3) {
 963                          $upt->track('enrolments', $strerror.': typeN = 1|2|3', 'error');
 964                          continue;
 965                      } else if (empty($formdata->{'uulegacy'.$addtype})) {
 966                          continue;
 967                      } else {
 968                          $rid = $formdata->{'uulegacy'.$addtype};
 969                      }
 970                  } else {
 971                      // no role specified, use the default from manual enrol plugin
 972                      $rid = $manualcache[$courseid]->roleid;
 973                  }
 974  
 975                  if ($rid) {
 976                      // Find duration and/or enrol status.
 977                      $timeend = 0;
 978                      $status = null;
 979  
 980                      if (isset($user->{'enrolstatus'.$i})) {
 981                          $enrolstatus = $user->{'enrolstatus'.$i};
 982                          if ($enrolstatus == '') {
 983                              $status = null;
 984                          } else if ($enrolstatus === (string)ENROL_USER_ACTIVE) {
 985                              $status = ENROL_USER_ACTIVE;
 986                          } else if ($enrolstatus === (string)ENROL_USER_SUSPENDED) {
 987                              $status = ENROL_USER_SUSPENDED;
 988                          } else {
 989                              debugging('Unknown enrolment status.');
 990                          }
 991                      }
 992  
 993                      if (!empty($user->{'enrolperiod'.$i})) {
 994                          $duration = (int)$user->{'enrolperiod'.$i} * 60*60*24; // convert days to seconds
 995                          if ($duration > 0) { // sanity check
 996                              $timeend = $today + $duration;
 997                          }
 998                      } else if ($manualcache[$courseid]->enrolperiod > 0) {
 999                          $timeend = $today + $manualcache[$courseid]->enrolperiod;
1000                      }
1001  
1002                      $manual->enrol_user($manualcache[$courseid], $user->id, $rid, $today, $timeend, $status);
1003  
1004                      $a = new stdClass();
1005                      $a->course = $shortname;
1006                      $a->role   = $rolecache[$rid]->name;
1007                      $upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a));
1008                  }
1009              }
1010  
1011              // find group to add to
1012              if (!empty($user->{'group'.$i})) {
1013                  // make sure user is enrolled into course before adding into groups
1014                  if (!is_enrolled($coursecontext, $user->id)) {
1015                      $upt->track('enrolments', get_string('addedtogroupnotenrolled', '', $user->{'group'.$i}), 'error');
1016                      continue;
1017                  }
1018                  //build group cache
1019                  if (is_null($ccache[$shortname]->groups)) {
1020                      $ccache[$shortname]->groups = array();
1021                      if ($groups = groups_get_all_groups($courseid)) {
1022                          foreach ($groups as $gid=>$group) {
1023                              $ccache[$shortname]->groups[$gid] = new stdClass();
1024                              $ccache[$shortname]->groups[$gid]->id   = $gid;
1025                              $ccache[$shortname]->groups[$gid]->name = $group->name;
1026                              if (!is_numeric($group->name)) { // only non-numeric names are supported!!!
1027                                  $ccache[$shortname]->groups[$group->name] = new stdClass();
1028                                  $ccache[$shortname]->groups[$group->name]->id   = $gid;
1029                                  $ccache[$shortname]->groups[$group->name]->name = $group->name;
1030                              }
1031                          }
1032                      }
1033                  }
1034                  // group exists?
1035                  $addgroup = $user->{'group'.$i};
1036                  if (!array_key_exists($addgroup, $ccache[$shortname]->groups)) {
1037                      // if group doesn't exist,  create it
1038                      $newgroupdata = new stdClass();
1039                      $newgroupdata->name = $addgroup;
1040                      $newgroupdata->courseid = $ccache[$shortname]->id;
1041                      $newgroupdata->description = '';
1042                      $gid = groups_create_group($newgroupdata);
1043                      if ($gid){
1044                          $ccache[$shortname]->groups[$addgroup] = new stdClass();
1045                          $ccache[$shortname]->groups[$addgroup]->id   = $gid;
1046                          $ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name;
1047                      } else {
1048                          $upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error');
1049                          continue;
1050                      }
1051                  }
1052                  $gid   = $ccache[$shortname]->groups[$addgroup]->id;
1053                  $gname = $ccache[$shortname]->groups[$addgroup]->name;
1054  
1055                  try {
1056                      if (groups_add_member($gid, $user->id)) {
1057                          $upt->track('enrolments', get_string('addedtogroup', '', s($gname)));
1058                      }  else {
1059                          $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
1060                      }
1061                  } catch (moodle_exception $e) {
1062                      $upt->track('enrolments', get_string('addedtogroupnot', '', s($gname)), 'error');
1063                      continue;
1064                  }
1065              }
1066          }
1067      }
1068      $upt->close(); // close table
1069  
1070      $cir->close();
1071      $cir->cleanup(true);
1072  
1073      echo $OUTPUT->box_start('boxwidthnarrow boxaligncenter generalbox', 'uploadresults');
1074      echo '<p>';
1075      if ($optype != UU_USER_UPDATE) {
1076          echo get_string('userscreated', 'tool_uploaduser').': '.$usersnew.'<br />';
1077      }
1078      if ($optype == UU_USER_UPDATE or $optype == UU_USER_ADD_UPDATE) {
1079          echo get_string('usersupdated', 'tool_uploaduser').': '.$usersupdated.'<br />';
1080      }
1081      if ($allowdeletes) {
1082          echo get_string('usersdeleted', 'tool_uploaduser').': '.$deletes.'<br />';
1083          echo get_string('deleteerrors', 'tool_uploaduser').': '.$deleteerrors.'<br />';
1084      }
1085      if ($allowrenames) {
1086          echo get_string('usersrenamed', 'tool_uploaduser').': '.$renames.'<br />';
1087          echo get_string('renameerrors', 'tool_uploaduser').': '.$renameerrors.'<br />';
1088      }
1089      if ($usersskipped) {
1090          echo get_string('usersskipped', 'tool_uploaduser').': '.$usersskipped.'<br />';
1091      }
1092      echo get_string('usersweakpassword', 'tool_uploaduser').': '.$weakpasswords.'<br />';
1093      echo get_string('errors', 'tool_uploaduser').': '.$userserrors.'</p>';
1094      echo $OUTPUT->box_end();
1095  
1096      if ($bulk) {
1097          echo $OUTPUT->continue_button($bulknurl);
1098      } else {
1099          echo $OUTPUT->continue_button($returnurl);
1100      }
1101      echo $OUTPUT->footer();
1102      die;
1103  }
1104  
1105  // Print the header
1106  echo $OUTPUT->header();
1107  
1108  echo $OUTPUT->heading(get_string('uploaduserspreview', 'tool_uploaduser'));
1109  
1110  // NOTE: this is JUST csv processing preview, we must not prevent import from here if there is something in the file!!
1111  //       this was intended for validation of csv formatting and encoding, not filtering the data!!!!
1112  //       we definitely must not process the whole file!
1113  
1114  // preview table data
1115  $data = array();
1116  $cir->init();
1117  $linenum = 1; //column header is first line
1118  $noerror = true; // Keep status of any error.
1119  while ($linenum <= $previewrows and $fields = $cir->next()) {
1120      $linenum++;
1121      $rowcols = array();
1122      $rowcols['line'] = $linenum;
1123      foreach($fields as $key => $field) {
1124          $rowcols[$filecolumns[$key]] = s(trim($field));
1125      }
1126      $rowcols['status'] = array();
1127  
1128      if (isset($rowcols['username'])) {
1129          $stdusername = clean_param($rowcols['username'], PARAM_USERNAME);
1130          if ($rowcols['username'] !== $stdusername) {
1131              $rowcols['status'][] = get_string('invalidusernameupload');
1132          }
1133          if ($userid = $DB->get_field('user', 'id', array('username'=>$stdusername, 'mnethostid'=>$CFG->mnet_localhost_id))) {
1134              $rowcols['username'] = html_writer::link(new moodle_url('/user/profile.php', array('id'=>$userid)), $rowcols['username']);
1135          }
1136      } else {
1137          $rowcols['status'][] = get_string('missingusername');
1138      }
1139  
1140      if (isset($rowcols['email'])) {
1141          if (!validate_email($rowcols['email'])) {
1142              $rowcols['status'][] = get_string('invalidemail');
1143          }
1144          if ($DB->record_exists('user', array('email'=>$rowcols['email']))) {
1145              $rowcols['status'][] = $stremailduplicate;
1146          }
1147      }
1148  
1149      if (isset($rowcols['city'])) {
1150          $rowcols['city'] = $rowcols['city'];
1151      }
1152      // Check if rowcols have custom profile field with correct data and update error state.
1153      $noerror = uu_check_custom_profile_data($rowcols) && $noerror;
1154      $rowcols['status'] = implode('<br />', $rowcols['status']);
1155      $data[] = $rowcols;
1156  }
1157  if ($fields = $cir->next()) {
1158      $data[] = array_fill(0, count($fields) + 2, '...');
1159  }
1160  $cir->close();
1161  
1162  $table = new html_table();
1163  $table->id = "uupreview";
1164  $table->attributes['class'] = 'generaltable';
1165  $table->tablealign = 'center';
1166  $table->summary = get_string('uploaduserspreview', 'tool_uploaduser');
1167  $table->head = array();
1168  $table->data = $data;
1169  
1170  $table->head[] = get_string('uucsvline', 'tool_uploaduser');
1171  foreach ($filecolumns as $column) {
1172      $table->head[] = $column;
1173  }
1174  $table->head[] = get_string('status');
1175  
1176  echo html_writer::tag('div', html_writer::table($table), array('class'=>'flexible-wrap'));
1177  
1178  // Print the form if valid values are available
1179  if ($noerror) {
1180      $mform2->display();
1181  }
1182  echo $OUTPUT->footer();
1183  die;
1184  


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1