src/Entity/User/User.php line 24

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Entity\User;
  4. use App\Entity\Core\Institution;
  5. use App\Entity\Core\SelfStudy\SelfStudy;
  6. use App\Repository\User\UserRepository;
  7. use App\Services\User\Canonicalizer;
  8. use DateTime;
  9. use Doctrine\ORM\Mapping as ORM;
  10. use JsonSerializable;
  11. use Scheb\TwoFactorBundle\Model\Totp\TotpConfiguration;
  12. use Scheb\TwoFactorBundle\Model\Totp\TotpConfigurationInterface;
  13. use Scheb\TwoFactorBundle\Model\Totp\TwoFactorInterface;
  14. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  15. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  16. use Symfony\Component\Security\Core\User\UserInterface;
  17. #[ORM\Table(name: 'user')]
  18. #[ORM\Entity(repositoryClass: UserRepository::class)]
  19. #[UniqueEntity(fields: ['username'], message: 'user.username.taken')]
  20. class User implements JsonSerializable, TwoFactorInterface, UserInterface, PasswordAuthenticatedUserInterface
  21. {
  22. public const string role_admin = 'ROLE_ADMIN';
  23. public const string role_student = 'ROLE_STUDENT';
  24. public const string role_teacher = 'ROLE_TEACHER';
  25. #[ORM\Column(name: 'password', type: 'string', length: 255, nullable: true)]
  26. protected ?string $password = null;
  27. #[ORM\Column(name: 'email', type: 'string', length: 255, unique: false, nullable: true)]
  28. protected ?string $email = null;
  29. #[ORM\Column(name: 'salt', type: 'string', length: 255, nullable: true)]
  30. protected ?string $salt = null;
  31. #[ORM\Column(name: 'email_canonical', type: 'string', length: 255, unique: false, nullable: true)]
  32. protected string $emailCanonical;
  33. #[ORM\Id]
  34. #[ORM\Column(type: 'integer')]
  35. #[ORM\GeneratedValue(strategy: 'AUTO')]
  36. protected int $id;
  37. #[ORM\Column(name: 'first_name', type: 'string', length: 255)]
  38. protected string $firstName;
  39. #[ORM\Column(name: 'surname', type: 'string', length: 255)]
  40. protected string $surname;
  41. #[ORM\JoinColumn(name: 'institution', referencedColumnName: 'id', onDelete: 'CASCADE', nullable: true)]
  42. #[ORM\ManyToOne(targetEntity: Institution::class, cascade: ['persist'])]
  43. protected ?Institution $institution = null;
  44. #[ORM\Column(name: 'nickname', type: 'string', length: 255, nullable: true)]
  45. protected string $nickname;
  46. #[ORM\Column(name: 'first_login', type: 'boolean', options: ['default' => true])]
  47. protected bool $firstLogin = true;
  48. #[ORM\Column(name: 'is_subscribed', type: 'boolean', options: ['default' => false])]
  49. protected bool $isSubscribed = false;
  50. #[ORM\Column(name: 'is_demo', type: 'boolean', options: ['default' => false])]
  51. protected bool $isDemo = false;
  52. #[ORM\Column(name: 'desired_grade', type: 'smallint', nullable: true)]
  53. private int $desiredGrade;
  54. #[ORM\Column(name: 'class_level', type: 'smallint', nullable: true)]
  55. private ?int $classLevel = null;
  56. #[ORM\Column(name: 'self_study_level_adjustment', type: 'smallint', options: ['default' => 0])]
  57. private int $selfStudyLevelAdjustment = 0;
  58. #[ORM\Column(type: 'string', nullable: true)]
  59. private ?string $userAgent = null;
  60. #[ORM\Column(name: 'show_audio', type: 'boolean', options: ['default' => false], nullable: true)]
  61. private ?bool $showAudio = null;
  62. #[ORM\Column(name: 'classroom_overview', type: 'boolean', options: ['default' => true], nullable: true)]
  63. private ?bool $classroomOverview = null;
  64. #[ORM\Column(name: 'expiration_basis', type: 'datetime', nullable: true)]
  65. private ?DateTime $expirationBasis;
  66. #[ORM\Column(name: 'expiration_self_study', type: 'datetime', nullable: true)]
  67. private ?DateTime $expirationSelfStudy;
  68. #[ORM\Column(name: 'expiration_textbook', type: 'datetime', nullable: true)]
  69. private ?DateTime $expirationTextbook;
  70. #[ORM\Column(name: 'last_login_with_unilogin', type: 'datetime', nullable: true)]
  71. private ?DateTime $lastLoginWithUnilogin; // note that the last_login in the database is handled by FOSUserBundle and will be removed
  72. #[ORM\JoinColumn(name: 'selected_self_study', referencedColumnName: 'id', nullable: true)]
  73. #[ORM\ManyToOne(targetEntity: SelfStudy::class)]
  74. private ?SelfStudy $selectedSelfStudy = null;
  75. #[ORM\Column(name: 'ekeys_user_id', type: 'string', nullable: true)]
  76. private ?string $ekeysUserId;
  77. #[ORM\Column(name: 'totp_secret', type: 'string', nullable: true)]
  78. private ?string $totpSecret;
  79. #[ORM\Column(name: 'totp_validated', type: 'boolean', options: ['default' => false])]
  80. private bool $totpValidated = false;
  81. #[ORM\Column(name: 'class_name', type: 'string', nullable: true)]
  82. private ?string $className;
  83. #[ORM\Column(name: 'username', type: 'string', length: 180, nullable: false)]
  84. protected string $username;
  85. #[ORM\Column(name: 'username_canonical', type: 'string', length: 180, nullable: false, unique: true)]
  86. protected string $usernameCanonical;
  87. #[ORM\Column(name: 'enabled', type: 'boolean', nullable: false)]
  88. protected bool $enabled = false;
  89. #[ORM\Column(name: 'roles', type: 'array', nullable: false)]
  90. protected array $roles = [];
  91. #[ORM\Column(name: 'last_login', type: 'datetime', nullable: true)]
  92. private ?DateTime $lastLogin;
  93. public function setUsername(string $username): User
  94. {
  95. $this->username = $username;
  96. $this->usernameCanonical = Canonicalizer::canonicalize($username);
  97. return $this;
  98. }
  99. public function getClassName(): ?string
  100. {
  101. return $this->className;
  102. }
  103. public function setClassName(?string $className): void
  104. {
  105. $this->className = $className;
  106. }
  107. public function setInstitution(?Institution $institution): User
  108. {
  109. $this->institution = $institution;
  110. return $this;
  111. }
  112. public function getInstitution(): ?Institution
  113. {
  114. return $this->institution;
  115. }
  116. public function getEkeysUserId(): ?string
  117. {
  118. return $this->ekeysUserId;
  119. }
  120. public function setEkeysUserId(?string $ekeysUserId): void
  121. {
  122. $this->ekeysUserId = $ekeysUserId;
  123. }
  124. public function getClassLevelName(?bool $isSelfStudy = false): string {
  125. $levelName = '';
  126. $classLevel = $isSelfStudy ? $this->getSelfStudyLevel() : $this->getClassLevel();
  127. if ($classLevel <= 3) {
  128. $levelName = 'indskoling';
  129. }
  130. elseif ($classLevel >= 4 && $classLevel <= 6) {
  131. $levelName = 'mellemtrin';
  132. }
  133. elseif ($classLevel >= 7) {
  134. $levelName = 'udskoling';
  135. }
  136. return $levelName;
  137. }
  138. public function getNickname(): string
  139. {
  140. if (!empty($this->nickname)) {
  141. return $this->nickname;
  142. }
  143. if (!empty($this->getFirstName()) && !empty($this->getSurname())) {
  144. return $this->getFirstName() . ' ' . $this->getSurname();
  145. }
  146. $nickname = $this->getFirstName();
  147. if ($surname = $this->getSurname()) {
  148. preg_match_all('/(?<=\s|^)[a-z]/i', $surname, $matches);
  149. $nickname .= implode('', $matches[0]);
  150. }
  151. return $nickname;
  152. }
  153. public function setNickname($nickname = null): User
  154. {
  155. if (!empty($nickname)) {
  156. $this->nickname = $nickname;
  157. return $this;
  158. }
  159. if (!empty($this->getFirstName()) && !empty($this->getSurname())) {
  160. $this->nickname = $this->getFirstName() . ' ' . $this->getSurname();
  161. return $this;
  162. }
  163. $nickname = $this->getFirstName();
  164. if ($surname = $this->getSurname()) {
  165. preg_match_all('/(?<=\s|^)[a-z]/i', $surname, $matches);
  166. $nickname .= implode('', $matches[0]);
  167. }
  168. $this->nickname = $nickname;
  169. return $this;
  170. }
  171. public function getFirstLogin(): bool
  172. {
  173. return $this->firstLogin;
  174. }
  175. public function setFirstLogin(bool $firstLogin): User
  176. {
  177. $this->firstLogin = $firstLogin;
  178. return $this;
  179. }
  180. public function getId(): int
  181. {
  182. return $this->id;
  183. }
  184. public function setId(int $id): void
  185. {
  186. $this->id = $id;
  187. }
  188. public function getSurname(): string
  189. {
  190. return $this->surname;
  191. }
  192. public function setSurname(string $surname): User
  193. {
  194. $this->surname = $surname;
  195. return $this;
  196. }
  197. public function getIsSubscribed(): bool
  198. {
  199. return $this->isSubscribed;
  200. }
  201. public function setIsSubscribed(bool $isSubscribed): void
  202. {
  203. $this->isSubscribed = $isSubscribed;
  204. }
  205. public function getFirstName(): string
  206. {
  207. return $this->firstName;
  208. }
  209. public function setFirstName(string $firstName): User
  210. {
  211. $this->firstName = $firstName;
  212. return $this;
  213. }
  214. public function isDemo(): bool
  215. {
  216. return $this->isDemo;
  217. }
  218. public function setIsDemo(bool $isDemo): void
  219. {
  220. $this->isDemo = $isDemo;
  221. }
  222. public function isDebugUser(): bool
  223. {
  224. return $this->getUsername() === "teacher1_demo";
  225. }
  226. public function getDesiredGrade(): ?int
  227. {
  228. return $this->desiredGrade;
  229. }
  230. public function setDesiredGrade(?int $desiredGrade): void
  231. {
  232. $this->desiredGrade = $desiredGrade;
  233. }
  234. public function getSelfStudyLevelAdjustment(): int
  235. {
  236. return $this->selfStudyLevelAdjustment;
  237. }
  238. public function setSelfStudyLevelAdjustment(int $levelAdjustment)
  239. {
  240. $this->selfStudyLevelAdjustment = $levelAdjustment;
  241. }
  242. public function getSelfStudyLevel(): ?int
  243. {
  244. return $this->getClassLevel() === null ? null : $this->getClassLevel() + $this->getSelfStudyLevelAdjustment();
  245. }
  246. public function getUserAgent(): ?string
  247. {
  248. return $this->userAgent;
  249. }
  250. public function setUserAgent(string $userAgent)
  251. {
  252. $this->userAgent = $userAgent;
  253. }
  254. public function getFullName(): string
  255. {
  256. return ucwords($this->firstName) . ' ' . ucwords($this->surname);
  257. }
  258. public function getCompactName(): string
  259. {
  260. return ucwords($this->firstName) . ' ' . strtoupper(substr($this->surname, 0, 2));
  261. }
  262. public function getClassLevel(): ?int
  263. {
  264. return $this->classLevel;
  265. }
  266. public function setClassLevel(?int $classLevel): void
  267. {
  268. $this->classLevel = $classLevel;
  269. }
  270. public function isShowAudio(): ?bool
  271. {
  272. return $this->showAudio;
  273. }
  274. public function setShowAudio(bool $showAudio): void
  275. {
  276. $this->showAudio = $showAudio;
  277. }
  278. public function getClassroomOverview(): ?bool
  279. {
  280. return $this->classroomOverview;
  281. }
  282. public function setClassroomOverview(bool $classroomOverview): void
  283. {
  284. $this->classroomOverview = $classroomOverview;
  285. }
  286. public function getExpirationBasis(): ?DateTime
  287. {
  288. return $this->expirationBasis;
  289. }
  290. public function setExpirationBasis(?DateTime $expirationBasis): void
  291. {
  292. $this->expirationBasis = $expirationBasis;
  293. }
  294. public function getExpirationSelfStudy(): ?DateTime
  295. {
  296. return $this->expirationSelfStudy;
  297. }
  298. public function setExpirationSelfStudy(?DateTime $expirationSelfStudy): void
  299. {
  300. $this->expirationSelfStudy = $expirationSelfStudy;
  301. }
  302. public function getExpirationTextbook(): ?DateTime
  303. {
  304. return $this->expirationTextbook;
  305. }
  306. public function setExpirationTextbook(?DateTime $expirationTextbook): void
  307. {
  308. $this->expirationTextbook = $expirationTextbook;
  309. }
  310. public function jsonSerialize(): mixed
  311. {
  312. return [
  313. "id" => $this->getId(),
  314. "name" => $this->getFullName(),
  315. "classLevel" => $this->getClassLevel()
  316. ];
  317. }
  318. public function getLastLoginWithUnilogin(): ?DateTime
  319. {
  320. return $this->lastLoginWithUnilogin;
  321. }
  322. public function getLastLogin(): ?DateTime
  323. {
  324. return $this->lastLogin;
  325. }
  326. public function setLastLogin(?DateTime $time = null)
  327. {
  328. $this->lastLogin = $time;
  329. return $this;
  330. }
  331. public function setEnabled($boolean): User
  332. {
  333. $this->enabled = (bool) $boolean;
  334. return $this;
  335. }
  336. public function setLastLoginWithUnilogin(DateTime $lastLoginWithUnilogin): void
  337. {
  338. $this->lastLoginWithUnilogin = $lastLoginWithUnilogin;
  339. }
  340. public function getSelectedSelfStudy(): ?SelfStudy
  341. {
  342. return $this->selectedSelfStudy;
  343. }
  344. public function setSelectedSelfStudy(SelfStudy $selectedSelfStudy): void
  345. {
  346. $this->selectedSelfStudy = $selectedSelfStudy;
  347. }
  348. public function setTotpSecret(string $secret): void
  349. {
  350. $this->totpSecret = $secret;
  351. }
  352. public function isTotpAuthenticationEnabled(): bool
  353. {
  354. return $this->totpValidated;
  355. }
  356. public function getTotpAuthenticationUsername(): string
  357. {
  358. return $this->username;
  359. }
  360. public function getTotpAuthenticationConfiguration(): ?TotpConfigurationInterface
  361. {
  362. // SHA1, 30 seconds and 6 digits is will make it work with Google authenticator and equivalent.
  363. return new TotpConfiguration($this->totpSecret, TotpConfiguration::ALGORITHM_SHA1, 30, 6);
  364. }
  365. public function isTotpValidated(): bool
  366. {
  367. return $this->totpValidated;
  368. }
  369. public function setTotpValidated(bool $totpValidated): void
  370. {
  371. $this->totpValidated = $totpValidated;
  372. }
  373. public function getRoles(): array
  374. {
  375. return $this->roles;
  376. }
  377. public function getPassword(): ?string
  378. {
  379. return $this->password;
  380. }
  381. public function getSalt(): ?string
  382. {
  383. return $this->salt;
  384. }
  385. public function eraseCredentials(): void
  386. {
  387. }
  388. public function getUsername(): string
  389. {
  390. return $this->username;
  391. }
  392. public function isEnabled(): bool
  393. {
  394. return $this->enabled;
  395. }
  396. /**
  397. * Avoid deprecation warning
  398. */
  399. public function getUserIdentifier(): string
  400. {
  401. return $this->username;
  402. }
  403. public function setRoles(array $roles): User
  404. {
  405. $this->roles = [];
  406. foreach ($roles as $role) {
  407. $this->addRole($role);
  408. }
  409. return $this;
  410. }
  411. public function addRole(string $role): void
  412. {
  413. $role = strtoupper($role);
  414. if (!in_array($role, $this->roles, true)) {
  415. $this->roles[] = $role;
  416. }
  417. }
  418. public function removeRole(string $role): void
  419. {
  420. if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
  421. unset($this->roles[$key]);
  422. $this->roles = array_values($this->roles);
  423. }
  424. }
  425. public function hasRole(string $role): bool
  426. {
  427. return in_array(strtoupper($role), $this->getRoles(), true);
  428. }
  429. public function getEmail(): ?string
  430. {
  431. return $this->email;
  432. }
  433. public function setEmail(string $email): void
  434. {
  435. $this->email = $email;
  436. $this->emailCanonical = Canonicalizer::canonicalize($email);
  437. }
  438. public function setSalt(string $salt): void
  439. {
  440. $this->salt = $salt;
  441. }
  442. public function setPassword(string $password): void
  443. {
  444. $this->password = $password;
  445. }
  446. public function __toString(): string
  447. {
  448. return $this->getUsername();
  449. }
  450. }