projectDir = $projectDir; $this->passwordHasher = $passwordHasher; $this->userRepository = $userRepository; } public function createUserFromData(array $data) : User { $user = new User(); foreach ($data as $key => $value) { if ($key != 'password') { $pieces = explode('_', $key); foreach ($pieces as $k => $v) { $pieces[$k] = ucfirst($v); } $method = 'set' . implode('_', $pieces); if (method_exists($user, $method)) { $user->$method($value); } } } $hashedPassword = $this->passwordHasher->hashPassword( $user, $data['password'] ); $user->setPassword($hashedPassword); return $user; } public function updateUserFromData(User $user, array $data) { foreach ($data as $key => $value) { if ($key != 'password') { $pieces = explode('_', $key); foreach ($pieces as $k => $v) { $pieces[$k] = ucfirst($v); } $method = 'set' . implode('_', $pieces); if (method_exists($user, $method)) { $user->$method($value); } } } //empty password means no changey password, non empty password means changey password if ($data['password'] != '') { $hashedPassword = $this->passwordHasher->hashPassword( $user, $data['password'] ); $user->setPassword($hashedPassword); } } public function sanitiseUserData(array $data) : array { $user = new User(); $stringValues = []; $emailValues = [ 'email', 'personal_email' ]; $dateValues = [ 'start_date' => 'Start Date', 'leave_date' => 'Leave Date' ]; foreach ($data as $key => $value) { $pieces = explode('_', $key); foreach ($pieces as $k => $v) { $pieces[$k] = ucfirst($v); } $method = 'get' . implode('_', $pieces); if ($method != 'getId' && method_exists($user, $method)) { $objval = $user->$method($value); if (is_string($objval)) { $stringValues[$key] = implode(' ', $pieces); } } } foreach ($stringValues as $key => $value) { if ($key == 'password') { //do nothing } else if (in_array($key, $emailValues)) { $data[$key] = filter_var($data[$key], FILTER_VALIDATE_EMAIL); } else { $data[$key] = htmlentities($data[$key], ENT_QUOTES | ENT_IGNORE, "UTF-8"); } if (!is_string($data[$key])) { $data[$key] = ''; //don't allow null or false values in strings... filter var can return null } } if (isset($data['roles']) && is_array($data['roles'])) { foreach ($data['roles'] as $key => $value) { if (!in_array($value, $this->permittedRoles)) { unset($data['roles'][$key]); } } if (!in_array($this->requiredRole, $data['roles'])) { $data['roles'][] = $this->requiredRole; } } foreach ($dateValues as $key => $value) { if (isset($data[$key])) { $date = date_parse_from_format('Y-m-d', $data[$key]); if (checkdate($date['month'], $date['day'], $date['year'])) { $data[$key] = \DateTime::createFromFormat('Y-m-d', $data[$key]); } else { $data[$key] = null; } } } if (isset($data['holiday_refresh_month'])) { $data['holiday_refresh_month'] = (int)$data['holiday_refresh_month']; if ($data['holiday_refresh_month'] < 0 || $data['holiday_refresh_month'] > 12) { $data['holiday_refresh_month'] = 0; } } return $data; } public function validateUserData(array $data, bool $isMyAccount = false) : array { $user = new User(); $result = [ 'success' => true, 'errors' => [] ]; $stringValues = []; $requiredValues = [ 'first_name', 'second_name', 'job_title', 'email' ]; $dateValues = [ 'start_date' => 'Start Date', 'leave_date' => 'Leave Date' ]; if ($isMyAccount) { $requiredValues = []; } foreach ($data as $key => $value) { $pieces = explode('_', $key); foreach ($pieces as $k => $v) { $pieces[$k] = ucfirst($v); } $method = 'get' . implode('_', $pieces); if ($method != 'getId' && method_exists($user, $method)) { $objval = $user->$method($value); if (is_string($objval)) { $stringValues[$key] = implode(' ', $pieces); } } } foreach ($stringValues as $key => $value) { if (isset($data[$key]) && is_string($data[$key])) { if ($key == 'password' && $data['password'] != '') { $noOfCaps = $this->countPasswordCaps($data['password']); $noOfNumbers = $this->countPasswordNumbers($data['password']); $noOfSymbols = $this->countPasswordSymbols($data['password']); $containsIdenticalConsecutiveCharacters = $this->containsIdenticalConsecutiveCharacters($data['password']); if (strlen($data['password']) < $this->passwordMinLength) { $result['errors'][] = 'Password is too short.'; } else if (strlen($data['password']) > $this->passwordMaxLength) { $result['errors'][] = 'Password is too long.'; } else if ($noOfCaps < $this->passwordMinCaps) { $result['errors'][] = 'Password doesn\'t contain enough capital letters.'; } else if ($noOfNumbers < $this->passwordMinNumbers) { $result['errors'][] = 'Password doesn\'t contain enough numbers.'; } else if ($noOfSymbols < $this->passwordMinSymbols) { $result['errors'][] = 'Password doesn\'t contain enough symbols.'; } else if ($containsIdenticalConsecutiveCharacters) { $result['errors'][] = 'Password contains identical consecutive characters.'; } else if ($data['password'] != $data['confirm_password']) { $result['errors'][] = 'Password does not match confirm password.'; } } else if (in_array($key, $requiredValues) && strlen($data[$key]) == 0) { $result['errors'][] = $value . ' is required.'; } else if (strlen($data[$key]) > 64) { $result['errors'][] = $value . ' is too long.'; } } else { $result['errors'][] = $value . ' not provided.'; } } if (!$isMyAccount) { if (isset($data['roles']) && is_array($data['roles'])) { foreach ($data['roles'] as $key => $value) { if (!in_array($value, $this->permittedRoles)) { $result['errors'][] = 'User Roles contains unknown values.'; } } } else { $result['errors'][] = 'User Roles not provided.'; } } foreach ($dateValues as $key => $value) { if (isset($data[$value])) { $date = date_parse_from_format('Y-m-d', $data[$value]); if (!checkdate($date['month'], $date['day'], $date['year'])) { $result['errors'][] = $value . ' is invalid.'; } } } if (isset($data['holiday_refresh_month'])) { if (is_int($data['holiday_refresh_month'])) { if ($data['holiday_refresh_month'] < 0 || $data['holiday_refresh_month'] > 12) { $result['errors'][] = $data['holiday_refresh_month'] . 'Holiday Refresh is out of acceptable range.'; } } else { $result['errors'][] = 'Holiday Refresh is invalid.'; } } if (count($result['errors']) > 0) { $result['success'] = false; } return $result; } public function isEmailUsed(string $email) : bool { $user = $this->userRepository->findOneByEmail($email); if ($user != null) { return true; } return false; } private function countPasswordCaps(string $password) : int { $lowerCase = mb_strtolower($password); return strlen($lowerCase) - similar_text($password, $lowerCase); } private function countPasswordNumbers(string $password) : int { $matches = []; preg_match_all("/[0-9]/", $password, $matches); return count($matches); } private function countPasswordSymbols(string $password) : int { $alphanumeric = mb_ereg_replace("[^A-Za-z0-9]", "", $password); return strlen($password) - strlen($alphanumeric); } private function containsIdenticalConsecutiveCharacters(string $password) : bool { $count = 1; $currentChar = ''; $containsIdenticalConsecutiveCharacters = false; foreach (str_split($password) as $char) { if ($currentChar == $char) { $count++; } else { $count = 1; } if ($count > $this->passwordMaxIdenticleConsecutiveCharacters) { $containsIdenticalConsecutiveCharacters = true; break; } $currentChar = $char; } return $containsIdenticalConsecutiveCharacters; } }