src/Entity/Account/User.php line 50

Open in your IDE?
  1. <?php
  2. namespace App\Entity\Account;
  3. use App\Entity\Channel\Channel;
  4. use App\Entity\Channel\Group;
  5. use App\Entity\Channel\Service;
  6. use App\Entity\Channel\UserFromChannel;
  7. use App\Entity\ChannelUserData\ChannelUserData;
  8. use App\Entity\Common\Address;
  9. use App\Entity\Common\Contact;
  10. use App\Entity\Common\ImportableData\ImportableDataInterface;
  11. use App\Entity\Common\ImportableData\ImportableDataTrait;
  12. use App\Entity\Sync\SyncableWithExcludedPropertiesInterface;
  13. use App\Repository\Account\UserRepository;
  14. use Doctrine\Common\Collections\ArrayCollection;
  15. use Doctrine\Common\Collections\Collection;
  16. use Doctrine\ORM\Mapping as ORM;
  17. use Drosalys\Bundle\ApiBundle\Serializer\Attributes\IdGroups;
  18. use DrosalysWeb\ObjectExtensions\Blame\Model\BlameInterface;use DrosalysWeb\ObjectExtensions\Blame\Model\BlameTrait;
  19. use DrosalysWeb\ObjectExtensions\Timestamp\Model\TimestampInterface;
  20. use DrosalysWeb\ObjectExtensions\Timestamp\Model\TimestampTrait;
  21. use Nellapp\Bundle\SDKBundle\Auth\Entity\UserInterface;
  22. use Nellapp\Bundle\SDKBundle\Auth\Entity\UserMethodTrait;
  23. use Nellapp\Bundle\SDKBundle\Auth\Entity\UserWithContact\UserWithContactInterface;
  24. use Nellapp\Bundle\SDKBundle\Auth\Entity\UserWithContact\UserWithContactTrait;
  25. use Nellapp\Bundle\SDKBundle\Sync\EntityKeys;
  26. use OpenApi\Annotations as OA;
  27. use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
  28. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  29. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  30. use Symfony\Component\Serializer\Annotation as Serial;
  31. use Symfony\Component\Validator\Constraints as Assert;
  32. /**
  33. * @method self|null getCreatedBy()
  34. * @method self setCreatedBy(self $createdBy)
  35. * @method self|null getUpdatedBy()
  36. * @method self setUpdatedBy(self $updatedBy)
  37. */
  38. #[UniqueEntity(fields: 'email', message: 'user.entity.email.UniqueEntity', groups: ['register', 'user_edition', 'super_admin_user_edition', 'admin_user_edition', 'flow_channel_user_create_step1', 'admin_learner_profile', 'admin_admin_profile'])]
  39. #[UniqueEntity(fields: 'id', message: 'user.entity.id.UniqueEntity', groups: ['register', 'flow_channel_user_create_step1'])]
  40. #[
  41. ORM\Entity(repositoryClass: UserRepository::class),
  42. ORM\Table(name: 'account_users'),
  43. ORM\Index(fields: ['email'], flags: ['fulltext']),
  44. ORM\Index(fields: ['firstName'], flags: ['fulltext']),
  45. ORM\Index(fields: ['lastName'], flags: ['fulltext']),
  46. ]
  47. class User implements
  48. UserInterface,
  49. UserWithContactInterface,
  50. PasswordAuthenticatedUserInterface,
  51. TimestampInterface,
  52. BlameInterface,
  53. SyncableWithExcludedPropertiesInterface,
  54. ImportableDataInterface
  55. {
  56. use BlameTrait;
  57. use TimestampTrait;
  58. use UserMethodTrait;
  59. use UserWithContactTrait;
  60. use ImportableDataTrait;
  61. #[
  62. ORM\Id, ORM\GeneratedValue(strategy: 'CUSTOM'),
  63. ORM\CustomIdGenerator(class: UuidGenerator::class),
  64. ORM\Column(type: 'string', length: 36)
  65. ]
  66. #[Serial\Groups(['Profile', 'Manager', 'Sync', 'GlobalJSVariable', 'activity:get'])]
  67. private ?string $id = null;
  68. #[ORM\Column(type: 'string', length: 180, unique: true)]
  69. #[
  70. Assert\NotBlank(message: 'user.entity.email.NotBlank', groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step1', 'admin_learner_profile', 'admin_admin_profile']),
  71. Assert\Email(message: 'user.entity.email.Email', mode: 'strict', groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step1', 'admin_learner_profile', 'admin_admin_profile']),
  72. Assert\Length(
  73. min: 6,
  74. max: 64,
  75. minMessage: 'user.entity.email.Length.min',
  76. maxMessage: 'user.entity.email.Length.max',
  77. groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step1', 'admin_learner_profile', 'admin_admin_profile']),
  78. ]
  79. #[Serial\Groups(['Profile', 'Manager', 'UserPostManager', 'Sync', 'activity:get'])]
  80. private ?string $email = null;
  81. /**
  82. * @var string[]
  83. */
  84. #[ORM\Column(type: 'json')]
  85. #[Serial\Groups(['Profile', 'Sync'])]
  86. private array $roles = [];
  87. #[ORM\Column(type: 'string')]
  88. #[
  89. Assert\NotBlank(message: 'user.entity.password.NotBlank', groups: ['register', 'user_edition']),
  90. Assert\Length(
  91. min: 8,
  92. max: 255,
  93. minMessage: 'user.entity.password.Length.min',
  94. maxMessage: 'user.entity.password.Length.max',
  95. groups: ['register', 'user_edition']),
  96. Assert\Regex(
  97. pattern: '/(?=.*[0-9])/',
  98. message: 'user.entity.password.Regex.digit',
  99. groups: ['register', 'user_edition']),
  100. Assert\Regex(
  101. pattern: '/(?=.*[A-Z])/',
  102. message: 'user.entity.password.Regex.up',
  103. groups: ['register', 'user_edition']),
  104. Assert\Regex(
  105. pattern: '/(?=.*[a-z])/',
  106. message: 'user.entity.password.Regex.low',
  107. groups: ['register', 'user_edition']),
  108. ]
  109. private ?string $password = null;
  110. #[ORM\Column(type: 'boolean')]
  111. #[
  112. Assert\NotNull(message: 'user.entity.enabled.NotNull'),
  113. Assert\Type(type: 'boolean', message: 'user.entity.enabled.Type')
  114. ]
  115. private bool $enabled = true;
  116. #[ORM\Column(type: 'string', length: 63, nullable: true)]
  117. private ?string $passwordToken = null;
  118. #[ORM\Column(type: 'datetime', nullable: true)]
  119. private ?\DateTimeInterface $passwordTokenAt = null;
  120. #[ORM\Column(type: 'string', nullable: true)]
  121. #[
  122. Assert\NotBlank(message: 'user.entity.firstName.NotBlank', groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step2', 'admin_learner_profile', 'admin_admin_profile']),
  123. Assert\Length(
  124. min: 2,
  125. max: 255,
  126. minMessage: 'user.entity.firstName.Length.min',
  127. maxMessage: 'user.entity.firstName.Length.max',
  128. groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step2', 'admin_learner_profile', 'admin_admin_profile'])
  129. ]
  130. #[Serial\Groups(['Profile', 'Manager', 'UserPostManager', 'Sync', 'GlobalJSVariable', 'activity:get'])]
  131. private ?string $firstName = null;
  132. #[ORM\Column(type: 'string', nullable: true)]
  133. #[
  134. Assert\NotBlank(message: 'user.entity.lastName.NotBlank', groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step2', 'admin_learner_profile', 'admin_admin_profile']),
  135. Assert\Length(
  136. min: 2,
  137. max: 255,
  138. minMessage: 'user.entity.lastName.Length.min',
  139. maxMessage: 'user.entity.lastName.Length.max',
  140. groups: ['register', 'user_edition', 'admin_user_edition', 'super_admin_user_edition', 'group_user', 'flow_channel_user_create_step2', 'admin_learner_profile', 'admin_admin_profile'])
  141. ]
  142. #[Serial\Groups(['Profile', 'Manager', 'UserPostManager', 'Sync', 'GlobalJSVariable', 'activity:get'])]
  143. private ?string $lastName = null;
  144. #[ORM\Column(type: 'string', length: 20, nullable: true)]
  145. #[Assert\Length(
  146. min: 8,
  147. max: 20,
  148. minMessage: 'user.entity.phone.Length.min',
  149. maxMessage: 'user.entity.phone.Length.max',
  150. groups: ['user_edition', 'admin_user_edition', 'super_admin_user_edition', 'flow_channel_user_create_step2', 'admin_learner_profile', 'admin_admin_profile'])
  151. ]
  152. private ?string $phoneNumber = null;
  153. #[ORM\Column(type: 'text', nullable: true)]
  154. #[Serial\Groups(['Profile', 'Sync'])]
  155. private ?string $description = null;
  156. #[ORM\Column(type: 'string', nullable: true)]
  157. #[Assert\Length(max: 255, groups: ['user_edition'])]
  158. private ?string $roleDescription = null;
  159. #[ORM\Column(type: 'boolean', nullable: true)]
  160. private ?bool $avatar = null;
  161. #[ORM\Column(type: 'text', nullable: true)]
  162. #[Serial\Groups(['Sync', 'Manager', 'GlobalJSVariable', 'activity:get'])]
  163. private ?string $avatarPath = null;
  164. #[ORM\Column(type: 'string', length: 2, nullable: true)]
  165. #[Assert\Choice(choices: ['m', 'f', 'o'], message: 'user.entity.gender.Choice', groups: ['user_edition', 'admin_user_edition', 'super_admin_user_edition', 'admin_learner_profile', 'admin_admin_profile'])]
  166. private ?string $gender = null;
  167. #[ORM\Column(type: 'date', nullable: true)]
  168. private ?\DateTimeInterface $birthAt = null;
  169. #[ORM\Embedded(class: Address::class)]
  170. #[Assert\Valid(groups: ['user_edition', 'flow_channel_user_create_step2', 'admin_learner_profile', 'admin_admin_profile'])]
  171. private ?Address $address = null;
  172. #[ORM\Column(type: 'boolean')]
  173. private bool $isVerified = false;
  174. #[ORM\OneToOne(mappedBy: 'user', targetEntity: UserFromChannel::class, cascade: ['remove'], orphanRemoval: true)]
  175. private ?UserFromChannel $userFromChannel = null;
  176. #[ORM\OneToOne(inversedBy: 'user', targetEntity: Contact::class, cascade: ['persist'])]
  177. #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
  178. #[IdGroups(['Sync'])]
  179. private ?Contact $contact = null;
  180. #[ORM\Column(type: 'datetime', nullable: true)]
  181. #[Serial\Groups(['Profile', 'Sync', 'UserPutSigningDate'])]
  182. private ?\DateTime $signingLimitDate = null;
  183. #[ORM\Column(type: 'datetime', nullable: true)]
  184. private ?\DateTime $lastConnectedAt = null;
  185. #[ORM\Column(type: 'boolean', nullable: false)]
  186. private bool $shownAlert = false; // Modal alert displayed for general informations
  187. #[ORM\OneToMany(mappedBy: 'user', targetEntity: ChannelUserData::class)]
  188. private ?Collection $channelUserDatas;
  189. #[ORM\ManyToMany(targetEntity: Group::class, mappedBy: 'users', fetch: 'EXTRA_LAZY')]
  190. private ?Collection $groups;
  191. #[ORM\ManyToMany(targetEntity: Service::class, mappedBy: 'users', fetch: 'EXTRA_LAZY')]
  192. private ?Collection $services;
  193. public function __construct()
  194. {
  195. $this->channelUserDatas = new ArrayCollection();
  196. $this->groups = new ArrayCollection();
  197. $this->services = new ArrayCollection();
  198. }
  199. /**
  200. * Overrides UserMethodTrait::__serialize(): the SDK trait serializes id/email/token,
  201. * but core's User has no $token property (renamed to $passwordToken in 160c40a2,
  202. * Nov 2023) — core is the OAuth server, it never needed the SDK's OAuth-client Token.
  203. */
  204. public function __serialize(): array
  205. {
  206. return [
  207. 'id' => $this->id,
  208. 'email' => $this->email,
  209. ];
  210. }
  211. public function __unserialize(array $data): void
  212. {
  213. $this->id = $data['id'];
  214. $this->email = $data['email'];
  215. }
  216. public static function getSyncKey(): string
  217. {
  218. return EntityKeys::USER;
  219. }
  220. public function getSyncDisplayLabel(): string
  221. {
  222. return $this->getEmail() ?? 'Email';
  223. }
  224. public static function getExcludedProperties(): array
  225. {
  226. return [
  227. 'lastConnectedAt',
  228. ];
  229. }
  230. #[
  231. Serial\SerializedName('username'),
  232. Serial\Groups(['Profile', 'Manager', 'Sync'])
  233. ]
  234. public function getUsername(): string
  235. {
  236. return $this;
  237. }
  238. /**
  239. * @OA\Property(type="array", @OA\Items(type="string"))
  240. */
  241. #[
  242. Serial\Groups(['Profile'])
  243. ]
  244. public function getChannelIds(): array
  245. {
  246. return $this->getChannelUserDatas()->map(fn(ChannelUserData $cud) => $cud->getChannel()->getId())->toArray();
  247. }
  248. public function getRoles(): array
  249. {
  250. return array_unique(array_merge($this->roles, [
  251. 'ROLE_USER',
  252. ]));
  253. }
  254. public function setRoles(array $roles): static
  255. {
  256. $this->roles = array_unique(array_values($roles));
  257. return $this;
  258. }
  259. public function getPassword(): ?string
  260. {
  261. return $this->password;
  262. }
  263. public function setPassword(string $password): static
  264. {
  265. $this->password = $password;
  266. return $this;
  267. }
  268. public function getEnabled(): ?bool
  269. {
  270. return $this->enabled;
  271. }
  272. public function setEnabled(bool $enabled): static
  273. {
  274. $this->enabled = $enabled;
  275. return $this;
  276. }
  277. public function toggleEnabled(): static
  278. {
  279. $this->enabled = !$this->enabled;
  280. return $this;
  281. }
  282. public function getPasswordToken(): ?string
  283. {
  284. return $this->passwordToken;
  285. }
  286. public function setPasswordToken(?string $passwordToken): static
  287. {
  288. $this->passwordToken = $passwordToken;
  289. return $this;
  290. }
  291. public function getPasswordTokenAt(): ?\DateTimeInterface
  292. {
  293. return $this->passwordTokenAt;
  294. }
  295. public function setPasswordTokenAt(?\DateTimeInterface $passwordTokenAt): static
  296. {
  297. $this->passwordTokenAt = $passwordTokenAt;
  298. return $this;
  299. }
  300. public function getPhoneNumber(): ?string
  301. {
  302. return $this->phoneNumber;
  303. }
  304. public function setPhoneNumber(?string $phoneNumber): static
  305. {
  306. $this->phoneNumber = $phoneNumber;
  307. return $this;
  308. }
  309. public function getRoleDescription(): ?string
  310. {
  311. return $this->roleDescription;
  312. }
  313. public function setRoleDescription(?string $roleDescription): static
  314. {
  315. $this->roleDescription = $roleDescription;
  316. return $this;
  317. }
  318. public function getGender(): ?string
  319. {
  320. return $this->gender;
  321. }
  322. public function setGender(?string $gender): static
  323. {
  324. $this->gender = $gender;
  325. return $this;
  326. }
  327. public function getBirthAt(): ?\DateTimeInterface
  328. {
  329. return $this->birthAt;
  330. }
  331. public function setBirthAt(?\DateTimeInterface $birthAt): static
  332. {
  333. $this->birthAt = $birthAt;
  334. return $this;
  335. }
  336. /**
  337. * @return \DateTime|null
  338. */
  339. public function getLastConnectedAt(): ?\DateTime
  340. {
  341. return $this->lastConnectedAt;
  342. }
  343. /**
  344. * @param \DateTime|null $lastConnectedAt
  345. */
  346. public function setLastConnectedAt(?\DateTime $lastConnectedAt): static
  347. {
  348. $this->lastConnectedAt = $lastConnectedAt;
  349. return $this;
  350. }
  351. public function getAddress(): Address
  352. {
  353. return $this->address ?: $this->address = new Address();
  354. }
  355. public function setAddress(Address $address): static
  356. {
  357. $this->address = $address;
  358. return $this;
  359. }
  360. public function isVerified(): bool
  361. {
  362. return $this->isVerified;
  363. }
  364. public function setIsVerified(bool $isVerified): static
  365. {
  366. $this->isVerified = $isVerified;
  367. return $this;
  368. }
  369. public function getGroups(): ?Collection
  370. {
  371. return $this->groups;
  372. }
  373. public function getGroupsByChannel(Channel $channel): ?array
  374. {
  375. return array_filter($this->groups->toArray(), function (Group $group) use ($channel) {
  376. return $group->getChannel() === $channel;
  377. });
  378. }
  379. public function setGroups(?Collection $groups): User
  380. {
  381. $this->groups = $groups;
  382. return $this;
  383. }
  384. public function getServices(): ?Collection
  385. {
  386. return $this->services;
  387. }
  388. public function getUserFromChannel(): ?UserFromChannel
  389. {
  390. return $this->userFromChannel;
  391. }
  392. public function setUserFromChannel(?UserFromChannel $userFromChannel): self
  393. {
  394. $this->userFromChannel = $userFromChannel;
  395. return $this;
  396. }
  397. public function isShownAlert(): bool
  398. {
  399. return $this->shownAlert;
  400. }
  401. public function setShownAlert(bool $shownAlert): User
  402. {
  403. $this->shownAlert = $shownAlert;
  404. return $this;
  405. }
  406. public function serialize(): ?string
  407. {
  408. return serialize([
  409. $this->id,
  410. $this->email,
  411. $this->password,
  412. $this->enabled,
  413. ]);
  414. }
  415. public function unserialize($data): void
  416. {
  417. list(
  418. $this->id,
  419. $this->email,
  420. $this->password,
  421. $this->enabled
  422. ) = unserialize($data);
  423. }
  424. }