src/Entity/Core/Users.php line 35

Open in your IDE?
  1. <?php
  2. namespace App\Entity\Core;
  3. use App\Entity\Cvs\Candidates;
  4. use App\Repository\Core\UsersRepository;
  5. use Doctrine\DBAL\Types\Types;
  6. use Doctrine\ORM\Mapping as ORM;
  7. use Symfony\Component\Security\Core\User\UserInterface;
  8. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  9. use Symfony\Component\Validator\Constraints as Assert;
  10. use Vich\UploaderBundle\Mapping\Annotation as Vich;
  11. use Symfony\Component\HttpFoundation\File\File;
  12. use Symfony\Component\HttpFoundation\File\UploadedFile;
  13. use Vich\UploaderBundle\Entity\File as EmbeddedFile;
  14. use ApiPlatform\Core\Annotation\ApiResource;
  15. use Symfony\Component\Serializer\Annotation\Groups;
  16. use Symfony\Component\Serializer\Annotation\SerializedName;
  17. use Serializable;
  18. use DateTimeImmutable;
  19. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  20. use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
  21. /**
  22. * @ORM\Entity(repositoryClass=UsersRepository::class)
  23. * @ORM\Table(name="users")
  24. * @ORM\HasLifecycleCallbacks()
  25. * @Vich\Uploadable
  26. *
  27. * @ApiResource(
  28. * normalizationContext={"groups"={"user:read"}},
  29. * denormalizationContext={"groups"={"user:write"}}
  30. * )
  31. */
  32. class Users implements UserInterface, PasswordAuthenticatedUserInterface, \Serializable
  33. {
  34. /**
  35. * @ORM\Id
  36. * @ORM\GeneratedValue
  37. * @ORM\Column(type="integer")
  38. *
  39. * @Groups("user:read")
  40. */
  41. private $id;
  42. /**
  43. * @var datetime
  44. *
  45. * @ORM\Column(name="createdAt", type="datetime", nullable=true)
  46. *
  47. * @Groups("user:read")
  48. */
  49. private $createdAt;
  50. /**
  51. * @var datetime
  52. *
  53. * @ORM\Column(name="updatedAt", type="datetime", nullable=true)
  54. */
  55. private $updatedAt;
  56. /**
  57. * @var datetime
  58. *
  59. * @ORM\Column(name="last_login", type="datetime", nullable=true)
  60. */
  61. private $lastLogin;
  62. /**
  63. * @ORM\Column(type="string", length=180, unique=true)
  64. * @Groups("user:read")
  65. */
  66. private $email;
  67. /**
  68. * @ORM\Column(type="string", length=180, nullable=true)
  69. * @Groups("user:read")
  70. */
  71. private $name;
  72. /**
  73. * @ORM\Column(type="string", length=180, nullable=true)
  74. * @Groups("user:read")
  75. */
  76. private $lastname;
  77. /**
  78. * @ORM\Column(type="json")
  79. */
  80. private $roles = [];
  81. /**
  82. * @var string The hashed password
  83. * @ORM\Column(type="string")
  84. */
  85. private $password;
  86. /**
  87. * @ORM\Column(type="string", length=180, nullable=true)
  88. */
  89. private $username;
  90. /**
  91. * @ORM\Column(type="boolean", length=180, nullable=true)
  92. */
  93. private $first;
  94. /**
  95. * @ORM\Column(type="boolean", length=180, nullable=true)
  96. */
  97. private $enabled;
  98. /**
  99. * @ORM\Column(type="boolean", length=11, nullable=true)
  100. */
  101. private $verification;
  102. /**
  103. * @var string
  104. *
  105. * @ORM\Column(name="premium", type="boolean", nullable=false)
  106. */
  107. private $premium;
  108. /* ══════════════════════════════════════════════════════════════════════
  109. LE QUOTA DE RÉDACTION PAR IA
  110. ⚠️ DEUX COLONNES, PAS UNE TABLE À PART.
  111. Le compteur vivait dans une table du site vitrine
  112. (`wr_ia_offre_usage`). Deux défauts :
  113. · le quota d'un COMPTE était stocké là où le compte n'existe
  114. pas — l'utilisateur vit ici, dans l'API ;
  115. · l'application mobile et tout autre client passant par l'API
  116. n'auraient pas été décomptés du tout.
  117. Deux colonnes sur l'utilisateur suffisent : un compteur et le jour
  118. auquel il se rapporte.
  119. ⚠️ LE JOUR EST STOCKÉ, PAS DÉDUIT.
  120. Sans lui, il faudrait une purge nocturne pour remettre les
  121. compteurs à zéro — un travail planifié de plus, qui tombe en
  122. panne sans que personne ne le voie, et le quota ne se réinitialise
  123. plus. En comparant la date stockée à celle du jour, la remise à
  124. zéro est implicite : elle a lieu au premier usage suivant.
  125. ══════════════════════════════════════════════════════════════════════ */
  126. /**
  127. * @var int
  128. *
  129. * @ORM\Column(name="ia_offre_count", type="smallint", nullable=false, options={"default": 0, "unsigned": true})
  130. */
  131. private $iaOffreCount = 0;
  132. /**
  133. * @var \DateTimeInterface|null
  134. *
  135. * @ORM\Column(name="ia_offre_day", type="date", nullable=true)
  136. */
  137. private $iaOffreDay;
  138. /**
  139. * ⚠️ UN PLAFOND PROPRE À CE COMPTE, OU RIEN.
  140. *
  141. * `NULL` veut dire « suit le défaut » — 2 sans abonnement, 100 avec.
  142. * C'est la même convention que `share_quota_per_day`, et elle mérite
  143. * d'être la même partout : deux quotas voisins qui traitent
  144. * différemment une valeur vide seraient un piège.
  145. *
  146. * Une valeur ici l'emporte, abonnement ou pas. Elle sert au geste
  147. * commercial — un client qui lance une campagne et a besoin de plus
  148. * que son forfait pour deux semaines.
  149. *
  150. * `0` est une valeur valide et signifie « aucune rédaction ». Ce
  151. * n'est PAS la même chose que vide.
  152. *
  153. * @var int|null
  154. *
  155. * @ORM\Column(name="ia_offre_quota", type="integer", nullable=true, options={"comment":"Plafond de rédactions IA par jour (NULL = selon premium)"})
  156. */
  157. private $iaOffreQuota;
  158. /**
  159. * Le moteur de recherche de candidats est-il ouvert à ce compte ?
  160. *
  161. * ⚠️ DEUX VERROUS, ET IL FAUT LES DEUX (option A).
  162. *
  163. * Accès = `premium` ET `searchEnabled`.
  164. *
  165. * `premium` est le droit COMMERCIAL : il s'achète et il expire.
  166. * `searchEnabled` est l'octroi EFFECTIF, posé compte par compte
  167. * depuis le back-office.
  168. *
  169. * Les deux parce qu'ils ne disent pas la même chose : un abonnement
  170. * qui s'arrête doit couper l'accès automatiquement (d'où `premium`),
  171. * et un abonnement qui démarre ne doit pas ouvrir la recherche sans
  172. * qu'on l'ait décidé (d'où le drapeau).
  173. *
  174. * ⚠️ Conséquence à assumer : un client premium sans le drapeau
  175. * n'aura PAS la recherche et écrira au support. C'est le prix de ce
  176. * modèle — le back-office doit donc afficher les deux états côte à
  177. * côte pour que le diagnostic prenne trois secondes.
  178. *
  179. * Faux à l'inscription. Personne ne l'obtient par défaut.
  180. *
  181. * @var bool|null
  182. *
  183. * @ORM\Column(name="search_enabled", type="boolean", nullable=true, options={"default":0,"comment":"Moteur de recherche candidats ouvert à ce compte"})
  184. */
  185. private $searchEnabled;
  186. /**
  187. * QUAND le recruteur a demandé l'accès au moteur de recherche.
  188. *
  189. * ⚠️ LA DEMANDE VIT ICI, PAS DANS LA BASE DU SITE VITRINE.
  190. *
  191. * Elle y était (liste d'attente locale) : le backoffice de l'API,
  192. * qui seul peut ouvrir l'accès (`searchEnabled`), ne la voyait pas.
  193. * Une demande et la décision qui y répond doivent être au même
  194. * endroit. Null = jamais demandé, ou demande refusée.
  195. *
  196. * @ORM\Column(name="search_requested_at", type="datetime", nullable=true, options={"comment":"Demande d'accès au moteur de recherche"})
  197. */
  198. private $searchRequestedAt;
  199. /**
  200. * Le quota d'envois de CV anonyme, par 24 h glissantes.
  201. *
  202. * ⚠️ NULL N'EST PAS ZÉRO. NULL = « le réglage par défaut ».
  203. *
  204. * Un `0` interdirait tout envoi — ce qui est un réglage LÉGITIME et
  205. * qu'on doit pouvoir poser volontairement (compte signalé, abus).
  206. * Si NULL valait zéro, tous les comptes existants seraient muets du
  207. * jour où la colonne apparaît.
  208. *
  209. * La distinction se paie d'une colonne nullable et se gagne en
  210. * lisibilité : le back-office affiche « par défaut (5) » ou une
  211. * valeur explicite, jamais un zéro ambigu.
  212. *
  213. * @var int|null
  214. *
  215. * @ORM\Column(name="share_quota_per_day", type="integer", nullable=true, options={"comment":"Envois de CV anonyme par 24h (NULL = défaut)"})
  216. */
  217. private $shareQuotaPerDay;
  218. public function getShareQuotaPerDay(): ?int
  219. {
  220. return $this->shareQuotaPerDay;
  221. }
  222. public function setShareQuotaPerDay(?int $shareQuotaPerDay): self
  223. {
  224. $this->shareQuotaPerDay = $shareQuotaPerDay === null
  225. ? null
  226. : max(0, min(500, $shareQuotaPerDay));
  227. return $this;
  228. }
  229. /**
  230. * Le quota EFFECTIF : la valeur du compte, ou le défaut.
  231. *
  232. * ⚠️ UN SEUL ENDROIT RÉPOND À CETTE QUESTION.
  233. *
  234. * Écrire `$user->getShareQuotaPerDay() ?? 5` dans le contrôleur
  235. * marcherait — jusqu'au deuxième endroit qui le fait, avec un autre
  236. * défaut. Et le jour où le défaut change, on en corrige un sur deux.
  237. */
  238. public function quotaPartageParJour(int $defaut = 5): int
  239. {
  240. return $this->shareQuotaPerDay ?? $defaut;
  241. }
  242. public function isSearchEnabled(): bool
  243. {
  244. return (bool) $this->searchEnabled;
  245. }
  246. public function getSearchRequestedAt(): ?\DateTimeInterface
  247. {
  248. return $this->searchRequestedAt;
  249. }
  250. public function setSearchRequestedAt(?\DateTimeInterface $v): self
  251. {
  252. $this->searchRequestedAt = $v;
  253. return $this;
  254. }
  255. public function setSearchEnabled(?bool $searchEnabled): self
  256. {
  257. $this->searchEnabled = (bool) $searchEnabled;
  258. return $this;
  259. }
  260. /**
  261. * Le compte peut-il utiliser le moteur de recherche ? (option A)
  262. *
  263. * Un seul endroit répond à cette question. La dupliquer dans chaque
  264. * endpoint, c'est garantir qu'un jour l'un des deux verrous sera oublié
  265. * quelque part — et ce jour-là, la recherche sera ouverte à tous.
  266. */
  267. public function peutChercher(): bool
  268. {
  269. return $this->isPremium() && $this->isSearchEnabled();
  270. }
  271. /**
  272. * NOTE: This is not a mapped field of entity metadata, just a simple property.
  273. *
  274. * @Vich\UploadableField(mapping="avatars_files", fileNameProperty="image.name", size="image.size", mimeType="image.mimeType", originalName="image.originalName", dimensions="image.dimensions")
  275. *
  276. * @var File|null
  277. */
  278. private $imageFile;
  279. /**
  280. * @ORM\Embedded(class="Vich\UploaderBundle\Entity\File")
  281. *
  282. * @var EmbeddedFile
  283. */
  284. private $image;
  285. /**
  286. * @var \Agencies
  287. *
  288. * @ORM\ManyToOne(targetEntity="App\Entity\Core\Agencies")
  289. * @ORM\JoinColumns({
  290. * @ORM\JoinColumn(name="current_agency_id", referencedColumnName="id", nullable=true)
  291. * })
  292. */
  293. protected $currentAgency;
  294. /**
  295. * @ORM\Column(name="password_forgotten", type="string", length=180, nullable=true)
  296. */
  297. private $passwordForgotten;
  298. /**
  299. * @var datetime
  300. *
  301. * @ORM\Column(name="password_forgotten_last_date", type="datetime", nullable=true)
  302. */
  303. private $passwordForgottenLastDate;
  304. /**
  305. * @var string
  306. *
  307. * @ORM\Column(name="partenariat", type="boolean", nullable=true)
  308. */
  309. private $partenariat;
  310. /**
  311. * @ORM\Column(name="description", type="text", nullable=true)
  312. */
  313. private $description;
  314. /**
  315. * @var string
  316. *
  317. * @ORM\Column(name="notifications_messages", type="boolean", nullable=true)
  318. */
  319. private $notificationsMessages;
  320. /**
  321. * @var string
  322. *
  323. * @ORM\Column(name="notifications_suivis", type="boolean", nullable=true)
  324. */
  325. private $notificationsSuivis;
  326. /**
  327. * @var string
  328. *
  329. * @ORM\Column(name="user_commission_unit", type="float", length=11, nullable=true)
  330. */
  331. private $userCommissionUnit;
  332. /**
  333. * @var string
  334. *
  335. * @ORM\Column(name="user_commission_pourcent", type="float", length=11, nullable=true)
  336. */
  337. private $userCommissionPourcent;
  338. /**
  339. * @var string
  340. *
  341. * @ORM\Column(name="type_account", type="string", length=255, nullable=true)
  342. */
  343. private $typeAccount;
  344. /**
  345. * @var \Candidates
  346. *
  347. * @ORM\ManyToOne(targetEntity="App\Entity\Cvs\Candidates")
  348. * @ORM\JoinColumns({
  349. * @ORM\JoinColumn(name="candidate_id", referencedColumnName="id", nullable=true)
  350. * })
  351. */
  352. protected $candidate;
  353. /**
  354. * @var string
  355. *
  356. * @ORM\Column(name="subscription_customer_stripe", type="string", length=255, nullable=true)
  357. */
  358. private $subscriptionCustomerStripe;
  359. /**
  360. * @ORM\Column(type="string", length=255, nullable=true)
  361. */
  362. private $verificationToken;
  363. /**
  364. * @ORM\Column(type="datetime", nullable=true)
  365. */
  366. private $tokenExpiration;
  367. /**
  368. * @ORM\Column(name="language", type="text", nullable=true)
  369. */
  370. private $language;
  371. /**
  372. * @ORM\Column(name="motif_verification", type="text", nullable=true)
  373. */
  374. private $motif;
  375. public function __construct()
  376. {
  377. $this->image = new \Vich\UploaderBundle\Entity\File();
  378. }
  379. /**
  380. * @ORM\PrePersist
  381. */
  382. public function setCreatedAtValue(): void
  383. {
  384. $this->setCreatedAt( new \DateTime("now"));
  385. $this->setUpdatedAt( new \DateTime("now"));
  386. $this->setPremium(false);
  387. }
  388. /**
  389. * @ORM\PreUpdate
  390. */
  391. public function setUpdatedAtValue(): void
  392. {
  393. $this->setUpdatedAt( new \DateTime("now"));
  394. }
  395. public function __toString()
  396. {
  397. return "#".$this->id." ".$this->getName()." ".$this->getLastname().' ('.$this->getEmail().')';
  398. }
  399. public function getTitlePartner(): ?string
  400. {
  401. return "#".$this->id." ".$this->getName()." ".$this->getLastname();
  402. }
  403. public function serialize(): string
  404. {
  405. return serialize([
  406. $this->id,
  407. $this->email,
  408. $this->password,
  409. // autres propriétés que vous souhaitez sérialiser, sauf $imageFile
  410. ]);
  411. }
  412. public function unserialize($serialized): void
  413. {
  414. list(
  415. $this->id,
  416. $this->email,
  417. $this->password,
  418. // autres propriétés que vous souhaitez désérialiser, sauf $imageFile
  419. ) = unserialize($serialized);
  420. }
  421. public function getId(): ?int
  422. {
  423. return $this->id;
  424. }
  425. /**
  426. * Retourne l'identifiant unique de l'utilisateur pour Symfony 5.3+
  427. * On utilise l'email comme identifiant
  428. */
  429. public function getUserIdentifier(): string
  430. {
  431. return (string) $this->email;
  432. }
  433. public function getEmail(): ?string
  434. {
  435. return $this->email;
  436. }
  437. public function setEmail(string $email): self
  438. {
  439. $this->email = $email;
  440. return $this;
  441. }
  442. /**
  443. * @see UserInterface
  444. */
  445. public function getRoles(): array
  446. {
  447. $roles = $this->roles;
  448. // guarantee every user at least has ROLE_USER
  449. $roles[] = 'ROLE_USER';
  450. return array_unique($roles);
  451. }
  452. public function setRoles(array $roles): self
  453. {
  454. $this->roles = $roles;
  455. return $this;
  456. }
  457. /**
  458. * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
  459. * of 'UploadedFile' is injected into this setter to trigger the update. If this
  460. * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
  461. * must be able to accept an instance of 'File' as the bundle will inject one here
  462. * during Doctrine hydration.
  463. *
  464. * @param File|UploadedFile|null $imageFile
  465. */
  466. public function setImageFile(?File $imageFile = null)
  467. {
  468. $this->imageFile = $imageFile;
  469. if (null !== $imageFile) {
  470. // It is required that at least one field changes if you are using doctrine
  471. // otherwise the event listeners won't be called and the file is lost
  472. $this->setUpdatedAt(new \DateTime("now"));
  473. }
  474. }
  475. public function getImageFile(): ?File
  476. {
  477. return $this->imageFile;
  478. }
  479. public function getImageBase64(): ?string
  480. {
  481. if (!$this->image || !$this->image->getName()) {
  482. return null;
  483. }
  484. // Utiliser $_SERVER['DOCUMENT_ROOT'] qui pointe vers /public
  485. $filePath = $_SERVER['DOCUMENT_ROOT'] . '/uploads/avatars/' . $this->image->getName();
  486. if (!file_exists($filePath)) {
  487. // Debug : retourner le chemin pour voir ce qui cloche
  488. return null; // ou "Path: " . $filePath pour debugger
  489. }
  490. $imageData = file_get_contents($filePath);
  491. $mimeType = $this->image->getMimeType() ?? mime_content_type($filePath);
  492. return 'data:' . $mimeType . ';base64,' . base64_encode($imageData);
  493. }
  494. public function setImage(EmbeddedFile $image): void
  495. {
  496. $this->image = $image;
  497. }
  498. public function getImage(): ?EmbeddedFile
  499. {
  500. return $this->image;
  501. }
  502. /**
  503. * @see UserInterface
  504. */
  505. public function getPassword(): string
  506. {
  507. return (string) $this->password;
  508. }
  509. /**
  510. * @see UserInterface
  511. */
  512. public function getUsername(): string
  513. {
  514. return (string) $this->username;
  515. }
  516. public function setPassword(string $password): self
  517. {
  518. $this->password = $password;
  519. return $this;
  520. }
  521. /**
  522. * @see UserInterface
  523. */
  524. public function getSalt()
  525. {
  526. // not needed when using the "bcrypt" algorithm in security.yaml
  527. }
  528. /**
  529. * @see UserInterface
  530. */
  531. public function eraseCredentials()
  532. {
  533. // If you store any temporary, sensitive data on the user, clear it here
  534. // $this->plainPassword = null;
  535. }
  536. public function getCreatedAt(): ?\DateTimeInterface
  537. {
  538. return $this->createdAt;
  539. }
  540. public function setCreatedAt(?\DateTimeInterface $createdAt): self
  541. {
  542. $this->createdAt = $createdAt;
  543. return $this;
  544. }
  545. public function getUpdatedAt(): ?\DateTimeInterface
  546. {
  547. return $this->updatedAt;
  548. }
  549. public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
  550. {
  551. $this->updatedAt = $updatedAt;
  552. return $this;
  553. }
  554. public function getLastLogin(): ?\DateTimeInterface
  555. {
  556. return $this->lastLogin;
  557. }
  558. public function setLastLogin(?\DateTimeInterface $lastLogin): self
  559. {
  560. $this->lastLogin = $lastLogin;
  561. return $this;
  562. }
  563. public function getName(): ?string
  564. {
  565. return $this->name;
  566. }
  567. public function setName(?string $name): self
  568. {
  569. $this->name = $name;
  570. return $this;
  571. }
  572. public function getLastname(): ?string
  573. {
  574. return $this->lastname;
  575. }
  576. public function setLastname(?string $lastname): self
  577. {
  578. $this->lastname = $lastname;
  579. return $this;
  580. }
  581. public function setUsername(?string $username): self
  582. {
  583. $this->username = $username;
  584. return $this;
  585. }
  586. public function getFirst(): ?bool
  587. {
  588. return $this->first;
  589. }
  590. public function setFirst(?bool $first): self
  591. {
  592. $this->first = $first;
  593. return $this;
  594. }
  595. public function getEnabled(): ?bool
  596. {
  597. return $this->enabled;
  598. }
  599. public function setEnabled(?bool $enabled): self
  600. {
  601. $this->enabled = $enabled;
  602. return $this;
  603. }
  604. public function getPremium(): ?bool
  605. {
  606. return $this->premium;
  607. }
  608. public function setPremium(bool $premium): self
  609. {
  610. $this->premium = $premium;
  611. return $this;
  612. }
  613. public function getPasswordForgotten(): ?string
  614. {
  615. return $this->passwordForgotten;
  616. }
  617. public function setPasswordForgotten(?string $passwordForgotten): self
  618. {
  619. $this->passwordForgotten = $passwordForgotten;
  620. return $this;
  621. }
  622. public function getPasswordForgottenLastDate(): ?\DateTimeInterface
  623. {
  624. return $this->passwordForgottenLastDate;
  625. }
  626. public function setPasswordForgottenLastDate(?\DateTimeInterface $passwordForgottenLastDate): self
  627. {
  628. $this->passwordForgottenLastDate = $passwordForgottenLastDate;
  629. return $this;
  630. }
  631. public function getPartenariat(): ?bool
  632. {
  633. return $this->partenariat;
  634. }
  635. public function setPartenariat(?bool $partenariat): self
  636. {
  637. $this->partenariat = $partenariat;
  638. return $this;
  639. }
  640. public function getDescription(): ?string
  641. {
  642. return $this->description;
  643. }
  644. public function setDescription(?string $description): self
  645. {
  646. $this->description = $description;
  647. return $this;
  648. }
  649. public function getNotificationsMessages(): ?bool
  650. {
  651. return $this->notificationsMessages;
  652. }
  653. public function setNotificationsMessages(?bool $notificationsMessages): self
  654. {
  655. $this->notificationsMessages = $notificationsMessages;
  656. return $this;
  657. }
  658. public function getNotificationsSuivis(): ?bool
  659. {
  660. return $this->notificationsSuivis;
  661. }
  662. public function setNotificationsSuivis(?bool $notificationsSuivis): self
  663. {
  664. $this->notificationsSuivis = $notificationsSuivis;
  665. return $this;
  666. }
  667. public function getUserCommissionUnit(): ?float
  668. {
  669. return $this->userCommissionUnit;
  670. }
  671. public function setUserCommissionUnit(?float $userCommissionUnit): self
  672. {
  673. $this->userCommissionUnit = $userCommissionUnit;
  674. return $this;
  675. }
  676. public function getUserCommissionPourcent(): ?float
  677. {
  678. return $this->userCommissionPourcent;
  679. }
  680. public function setUserCommissionPourcent(?float $userCommissionPourcent): self
  681. {
  682. $this->userCommissionPourcent = $userCommissionPourcent;
  683. return $this;
  684. }
  685. public function getCurrentAgency(): ?Agencies
  686. {
  687. return $this->currentAgency;
  688. }
  689. public function setCurrentAgency(?Agencies $currentAgency): self
  690. {
  691. $this->currentAgency = $currentAgency;
  692. return $this;
  693. }
  694. public function isFirst(): ?bool
  695. {
  696. return $this->first;
  697. }
  698. public function isEnabled(): ?bool
  699. {
  700. return $this->enabled;
  701. }
  702. public function isPremium(): ?bool
  703. {
  704. return $this->premium;
  705. }
  706. public function isPartenariat(): ?bool
  707. {
  708. return $this->partenariat;
  709. }
  710. public function isNotificationsMessages(): ?bool
  711. {
  712. return $this->notificationsMessages;
  713. }
  714. public function isNotificationsSuivis(): ?bool
  715. {
  716. return $this->notificationsSuivis;
  717. }
  718. public function getTypeAccount(): ?string
  719. {
  720. return $this->typeAccount;
  721. }
  722. public function setTypeAccount(?string $description): self
  723. {
  724. $this->typeAccount = $description;
  725. return $this;
  726. }
  727. public function getCandidate(): ?Candidates
  728. {
  729. return $this->candidate;
  730. }
  731. public function setCandidate(?Candidates $candidate): static
  732. {
  733. $this->candidate = $candidate;
  734. return $this;
  735. }
  736. public function getSubscriptionCustomerStripe(): ?string
  737. {
  738. return $this->subscriptionCustomerStripe;
  739. }
  740. public function setSubscriptionCustomerStripe(?string $subscriptionCustomerStripe): static
  741. {
  742. $this->subscriptionCustomerStripe = $subscriptionCustomerStripe;
  743. return $this;
  744. }
  745. public function getVerificationToken(): ?string
  746. {
  747. return $this->verificationToken;
  748. }
  749. public function setVerificationToken(?string $verificationToken): self
  750. {
  751. $this->verificationToken = $verificationToken;
  752. return $this;
  753. }
  754. public function getTokenExpiration(): ?\DateTimeInterface
  755. {
  756. return $this->tokenExpiration;
  757. }
  758. public function setTokenExpiration(?\DateTimeInterface $tokenExpiration): self
  759. {
  760. $this->tokenExpiration = $tokenExpiration;
  761. return $this;
  762. }
  763. public function getLanguage(): ?string
  764. {
  765. return $this->language;
  766. }
  767. public function setLanguage(?string $description): self
  768. {
  769. $this->language = $description;
  770. return $this;
  771. }
  772. public function isVerification(): ?bool
  773. {
  774. return $this->verification;
  775. }
  776. public function setVerification(?bool $verification): self
  777. {
  778. $this->verification = $verification;
  779. return $this;
  780. }
  781. public function getMotif(): ?string
  782. {
  783. return $this->motif;
  784. }
  785. public function setMotif(?string $motif): self
  786. {
  787. $this->motif = $motif;
  788. return $this;
  789. }
  790. public function getIaOffreCount(): int
  791. {
  792. return (int) $this->iaOffreCount;
  793. }
  794. public function setIaOffreCount(int $n): self
  795. {
  796. $this->iaOffreCount = $n;
  797. return $this;
  798. }
  799. public function getIaOffreDay(): ?\DateTimeInterface
  800. {
  801. return $this->iaOffreDay;
  802. }
  803. public function setIaOffreDay(?\DateTimeInterface $jour): self
  804. {
  805. $this->iaOffreDay = $jour;
  806. return $this;
  807. }
  808. /**
  809. * Combien de rédactions ce compte a consommées AUJOURD'HUI.
  810. *
  811. * ⚠️ UN COMPTEUR D'HIER VAUT ZÉRO, IL NE SE PURGE PAS.
  812. *
  813. * La remise à zéro est implicite : si la date stockée n'est pas
  814. * celle du jour, le compteur ne concerne pas aujourd'hui. Pas de
  815. * travail planifié, donc pas de travail planifié en panne.
  816. */
  817. public function iaOffreUtiliseAujourdhui(): int
  818. {
  819. if (!$this->iaOffreDay) {
  820. return 0;
  821. }
  822. return $this->iaOffreDay->format('Y-m-d') === (new \DateTime())->format('Y-m-d')
  823. ? (int) $this->iaOffreCount
  824. : 0;
  825. }
  826. public function getIaOffreQuota(): ?int
  827. {
  828. return $this->iaOffreQuota;
  829. }
  830. public function setIaOffreQuota(?int $n): self
  831. {
  832. $this->iaOffreQuota = $n;
  833. return $this;
  834. }
  835. /**
  836. * Le plafond applicable à ce compte.
  837. *
  838. * ⚠️ LE RÉGLAGE INDIVIDUEL L'EMPORTE, Y COMPRIS À LA BAISSE.
  839. *
  840. * Un abonné à qui l'on a fixé 5 aura 5, pas 100. C'est voulu : le
  841. * champ sert autant à ouvrir qu'à restreindre — un compte qui abuse
  842. * se borne sans qu'on ait à lui retirer son abonnement.
  843. *
  844. * @param int $defaut le plafond selon l'abonnement, décidé par l'appelant
  845. */
  846. public function iaOffrePlafond(int $defaut): int
  847. {
  848. return $this->iaOffreQuota === null ? $defaut : max(0, (int) $this->iaOffreQuota);
  849. }
  850. /** Enregistre une rédaction de plus pour aujourd'hui. */
  851. public function iaOffreIncremente(): self
  852. {
  853. $this->iaOffreCount = $this->iaOffreUtiliseAujourdhui() + 1;
  854. $this->iaOffreDay = new \DateTime();
  855. return $this;
  856. }
  857. }