translate('Password cannot be empty'); return $errors; } if ($password !== '' && $password !== $password2) { $errors[] = $this->translate('Passwords must match'); } if ($password === '') { return $errors; } if (strlen($password) < self::PASSWORD_MIN_LENGTH) { $errors[] = $this->translate('Password must be at least %d characters', self::PASSWORD_MIN_LENGTH); } if (!preg_match('/[A-Z]/', $password)) { $errors[] = $this->translate('Password must include an uppercase letter'); } if (!preg_match('/[a-z]/', $password)) { $errors[] = $this->translate('Password must include a lowercase letter'); } if (!preg_match('/\d/', $password)) { $errors[] = $this->translate('Password must include a number'); } if (!preg_match('/[^a-zA-Z0-9]/', $password)) { $errors[] = $this->translate('Password must include a symbol'); } if ($email !== null) { $email = trim($email); if ($email !== '' && stripos($password, $email) !== false) { $errors[] = $this->translate('Password must not contain your email'); } } return $errors; } public function hints(): array { return [ ['rule' => 'min', 'text' => $this->translate('At least %d characters', self::PASSWORD_MIN_LENGTH)], ['rule' => 'upper', 'text' => $this->translate('At least one uppercase letter')], ['rule' => 'lower', 'text' => $this->translate('At least one lowercase letter')], ['rule' => 'number', 'text' => $this->translate('At least one number')], ['rule' => 'symbol', 'text' => $this->translate('At least one symbol')], ['rule' => 'email', 'text' => $this->translate('Must not contain your email')], ]; } public function minLength(): int { return self::PASSWORD_MIN_LENGTH; } // Wrapper so this service can be used in tests before the t() helper is loaded. private function translate(string $text, mixed ...$args): string { if (function_exists('t')) { return t($text, ...$args); } if ($args === []) { return $text; } return vsprintf($text, array_map(static fn ($arg) => (string) $arg, $args)); } }