/**
  * Create new user
  *
  * This function is used to create a new user in the system
  * The user is created based on a a properties array, in which
  * the user login, name, surname and email must be present, otherwise
  * an EfrontUserException is thrown. Apart from these, all the other
  * user elements are optional, and defaults will be used if they are left
  * blank.
  * Once the database representation is created, the constructor tries to create the
  * user directories, G_UPLOADPATH.'login/' and message attachments subfolders. Finally
  * it assigns a default avatar to the user. The function instantiates the user based on
  * its type.
  * <br/>Example:
  * <code>
  * $properties = array('login' => 'jdoe', 'name' => 'john', 'surname' => 'doe', 'email' => '*****@*****.**');
  * $user = EfrontUser :: createUser($properties);
  * </code>
  *
  * @param array $userProperties The new user properties
  * @param array $users The list of existing users, with logins and active properties, in the form array($login => $active). It is handy to specify when creating massively users
  * @return array with new user settings if the new user was successfully created
  * @since 3.5.0
  * @access public
  */
 public static function createUser($userProperties, $users = array(), $addToDefaultGroup = true)
 {
     $result = eF_getTableData("users", "count(id) as total", "active=1");
     $activatedUsers = $result[0]['total'];
     if (!isset($userProperties['login']) || !eF_checkParameter($userProperties['login'], 'login')) {
         throw new EfrontUserException(_INVALIDLOGIN . ': ' . $userProperties['login'], EfrontUserException::INVALID_LOGIN);
     }
     $result = eF_getTableData("users", "login, archive", "login='******'login']}'");
     //collation is by default utf8_general_ci, meaning that this search is case-insensitive
     if (sizeof($result) > 0) {
         if ($result[0]['archive']) {
             throw new EfrontUserException(_USERALREADYEXISTSARCHIVED . ': ' . $userProperties['login'], EfrontUserException::USER_EXISTS);
         } else {
             throw new EfrontUserException(_USERALREADYEXISTS . ': ' . $userProperties['login'], EfrontUserException::USER_EXISTS);
         }
     }
     /*		
     		$archived_keys = array_combine(array_keys($archived),array_keys($archived));  
     		if (isset($archived_keys[mb_strtolower($userProperties['login'])])) {
     		//if (in_array(mb_strtolower($userProperties['login']), array_keys($archived), true) !== false) {	
     			throw new EfrontUserException(_USERALREADYEXISTSARCHIVED.': '.$userProperties['login'], EfrontUserException :: USER_EXISTS);
     		}	
     		
     		$user_keys = array_combine(array_keys($users),array_keys($users));  
     		if (isset($user_keys[mb_strtolower($userProperties['login'])])) { 
     		//if (in_array(mb_strtolower($userProperties['login']), array_keys($users), true) !== false) {
     			throw new EfrontUserException(_USERALREADYEXISTS.': '.$userProperties['login'], EfrontUserException :: USER_EXISTS);
     		}
     */
     if (G_VERSIONTYPE != 'community') {
         #cpp#ifndef COMMUNITY
         if (G_VERSIONTYPE != 'standard') {
             #cpp#ifndef STANDARD
             //pr($activatedUsers);
             if (isset($GLOBALS['configuration']['version_users']) && $activatedUsers > $GLOBALS['configuration']['version_users'] && $GLOBALS['configuration']['version_users'] > 0) {
                 throw new EfrontUserException(_MAXIMUMUSERSNUMBERREACHED . ' (' . $GLOBALS['configuration']['version_users'] . '): ' . $userProperties['login'], EfrontUserException::MAXIMUM_REACHED);
             }
         }
         #cpp#endif
     }
     #cpp#endif
     if ($userProperties['email'] && !eF_checkParameter($userProperties['email'], 'email')) {
         throw new EfrontUserException(_INVALIDEMAIL . ': ' . $userProperties['email'], EfrontUserException::INVALID_PARAMETER);
     }
     if (!isset($userProperties['name'])) {
         throw new EfrontUserException(_INVALIDNAME . ': ' . $userProperties['name'], EfrontUserException::INVALID_PARAMETER);
     }
     if (!isset($userProperties['surname'])) {
         throw new EfrontUserException(_INVALIDSURNAME . ': ' . $userProperties['login'], EfrontUserException::INVALID_PARAMETER);
     }
     $roles = EfrontUser::getRoles();
     $rolesTypes = EfrontUser::getRoles(true);
     foreach (EfrontUser::getRoles(true) as $key => $value) {
         $rolesTypes[$key] = mb_strtolower($value);
     }
     //If a user type is not specified, by default make the new user student
     if (!isset($userProperties['user_type'])) {
         $userProperties['user_type'] = 'student';
     } else {
         if (in_array(mb_strtolower($userProperties['user_type']), $roles)) {
             $userProperties['user_type'] = mb_strtolower($userProperties['user_type']);
         } else {
             if ($k = array_search(mb_strtolower($userProperties['user_type']), $rolesTypes)) {
                 $userProperties['user_types_ID'] = $k;
                 $userProperties['user_type'] = $roles[$k];
             } else {
                 $userProperties['user_type'] = 'student';
             }
         }
     }
     if (!in_array($userProperties['user_type'], EFrontUser::$basicUserTypes)) {
         $userProperties['user_type'] = 'student';
         $userProperties['user_types_ID'] = 0;
     }
     //!isset($userProperties['user_type']) || !in_array($userProperties['user_type'], EfrontUser::getRoles())	  ? $userProperties['user_type']	  = 'student'									 : null;
     isset($userProperties['password']) && $userProperties['password'] != '' ? $passwordNonTransformed = $userProperties['password'] : ($passwordNonTransformed = $userProperties['login']);
     if ($userProperties['password'] != 'ldap') {
         !isset($userProperties['password']) || $userProperties['password'] == '' ? $userProperties['password'] = EfrontUser::createPassword($userProperties['login']) : ($userProperties['password'] = self::createPassword($userProperties['password']));
         if ($GLOBALS['configuration']['force_change_password']) {
             $userProperties['need_pwd_change'] = 1;
         }
     }
     !isset($userProperties['email']) ? $userProperties['email'] = '' : null;
     // 0 means not pending, 1 means pending
     !isset($userProperties['languages_NAME']) ? $userProperties['languages_NAME'] = $GLOBALS['configuration']['default_language'] : null;
     //If language is not specified, use default language
     !isset($userProperties['active']) || $userProperties['active'] == "" ? $userProperties['active'] = 0 : null;
     // 0 means inactive, 1 means active
     !isset($userProperties['pending']) ? $userProperties['pending'] = 0 : null;
     // 0 means not pending, 1 means pending
     !isset($userProperties['timestamp']) || $userProperties['timestamp'] == "" ? $userProperties['timestamp'] = time() : null;
     !isset($userProperties['user_types_ID']) ? $userProperties['user_types_ID'] = 0 : null;
     $languages = EfrontSystem::getLanguages();
     if (in_array($userProperties['languages_NAME'], array_keys($languages)) === false) {
         $userProperties['languages_NAME'] = $GLOBALS['configuration']['default_language'];
     }
     if ($userProperties['archive']) {
         $userProperties['archive'] = time();
         $userProperties['active'] = 0;
     }
     !isset($userProperties['timezone']) || $userProperties['timezone'] == '' ? $userProperties['timezone'] = $GLOBALS['configuration']['time_zone'] : null;
     $userProfile = eF_getTableData("user_profile", "name,options", "active=1 AND type='select'");
     foreach ($userProfile as $field) {
         if (isset($userProperties[$field['name']])) {
             $options = unserialize($field['options']);
             $userProperties[$field['name']] = array_search($userProperties[$field['name']], $options);
         }
     }
     eF_insertTableData("users", $userProperties);
     // Assign to the new user all skillgap tests that should be automatically assigned to every new student
     if (G_VERSIONTYPE != 'community') {
         #cpp#ifndef COMMUNITY
         if (G_VERSIONTYPE != 'standard') {
             #cpp#ifndef STANDARD
             if ($userProperties['user_type'] == 'student') {
                 $tests = EfrontTest::getAutoAssignedTests();
                 foreach ($tests as $test) {
                     eF_insertTableData("users_to_skillgap_tests", array("users_LOGIN" => $userProperties['login'], "tests_ID" => $test));
                 }
             }
         }
         #cpp#endif
     }
     #cpp#endif
     $newUser = EfrontUserFactory::factory($userProperties['login']);
     //$newUser -> user['password'] = $passwordNonTransformed;	//commented out because it was not needed any more, and created problems. Will be removed in next pass
     global $currentUser;
     // this is for running eF_loadAllModules ..needs to go somewhere else
     if (!$currentUser) {
         $currentUser = $newUser;
     }
     EfrontEvent::triggerEvent(array("type" => EfrontEvent::SYSTEM_JOIN, "users_LOGIN" => $newUser->user['login'], "users_name" => $newUser->user['name'], "users_surname" => $newUser->user['surname'], "entity_name" => $passwordNonTransformed));
     EfrontEvent::triggerEvent(array("type" => -1 * EfrontEvent::SYSTEM_VISITED, "users_LOGIN" => $newUser->user['login'], "users_name" => $newUser->user['name'], "users_surname" => $newUser->user['surname']));
     if (G_VERSIONTYPE != 'community') {
         #cpp#ifndef COMMUNITY
         if (G_VERSIONTYPE != 'standard') {
             #cpp#ifndef STANDARD
             if ($addToDefaultGroup) {
                 EfrontGroup::addToDefaultGroup($newUser, $newUser->user['user_types_ID'] ? $newUser->user['user_types_ID'] : $newUser->user['user_type']);
             }
         }
         #cpp#endif
     }
     #cpp#endif
     ///MODULES1 - Module user add events
     // Get all modules (NOT only the ones that have to do with the user type)
     if (!self::$cached_modules) {
         self::$cached_modules = eF_loadAllModules();
     }
     // Trigger all necessary events. If the function has not been re-defined in the derived module class, nothing will happen
     foreach (self::$cached_modules as $module) {
         $module->onNewUser($userProperties['login']);
     }
     EfrontCache::getInstance()->deleteCache('usernames');
     if (G_VERSIONTYPE != 'community') {
         #cpp#ifndef COMMUNITY
         if (G_VERSIONTYPE != 'standard') {
             #cpp#ifndef STANDARD
             $threshold = self::NOTIFY_THRESHOLD * $GLOBALS['configuration']['version_users'];
             if (isset($GLOBALS['configuration']['version_users']) && $GLOBALS['configuration']['version_users'] > 0 && $activatedUsers < $threshold && $activatedUsers + 1 > $threshold) {
                 $admin = EfrontSystem::getAdministrator();
                 eF_mail($GLOBALS['configuration']['system_email'], $admin->user['email'], _YOUAREREACHINGYOURSUBSCRIPTIONLIMIT, str_replace(array('%w', '%x', '%y', '%z'), array($admin->user['name'], self::NOTIFY_THRESHOLD * 100, $GLOBALS['configuration']['site_name'], G_SERVERNAME), _YOUAREREACHINGYOURSUBSCRIPTIONLIMITBODY));
             }
         }
         #cpp#endif
     }
     #cpp#endif
     return $newUser;
 }