src/Entity/Creator.php line 42

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Entity;
  4. use ApiPlatform\Core\Annotation\ApiResource;
  5. use App\Contracts\Activity\Status;
  6. use App\Contracts\Platform\Platform;
  7. use App\Contracts\User\Subscription;
  8. use App\Entity\Survey\UserAnswer;
  9. use DateTime;
  10. use DateTimeImmutable;
  11. use Doctrine\Common\Collections\ArrayCollection;
  12. use Doctrine\Common\Collections\Collection;
  13. use Doctrine\ORM\Mapping\Column;
  14. use Doctrine\ORM\Mapping\Entity;
  15. use Doctrine\ORM\Mapping\Index;
  16. use Doctrine\ORM\Mapping\JoinColumn;
  17. use Doctrine\ORM\Mapping\JoinTable;
  18. use Doctrine\ORM\Mapping\ManyToMany;
  19. use Doctrine\ORM\Mapping\ManyToOne;
  20. use Doctrine\ORM\Mapping\OneToMany;
  21. use Doctrine\ORM\Mapping\OneToOne;
  22. use Symfony\Component\Uid\Uuid;
  23. use LogicException;
  24. use stdClass;
  25. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  26. #[Entity]
  27. #[Index(fields: ['username'], name'username')]
  28. #[Index(fields: ['skippedAt'], name'skipped_at')]
  29. #[Index(fields: ['verifiedAt'], name'verified_at')]
  30. #[Index(fields: ['platform'], name'platform')]
  31. #[Index(fields: ['username''platform'], name'idx_creator_username_platform')]
  32. #[Index(columns: ['last_active_at''skipped_at'], name'idx_last_active_skipped')]
  33. #[Index(columns: ['locked_tik_tok_union_id'], name'idx_creator_locked_union')]
  34. #[Index(columns: ['language'], name'idx_creator_language')]
  35. #[ApiResource(attributes: ['route_prefix' => 'v1'])]
  36. class Creator extends User implements PasswordAuthenticatedUserInterface
  37. {
  38.     public const ROLE_NAME 'ROLE_CREATOR';
  39.     /** @var int */
  40.     public const DEFAULT_MINIMAL_AMOUNT 0;
  41.     public const DEFAULT_VIP_MINIMAL_AMOUNT 0;
  42.     public const DEFAULT_NON_VIP_CREATOR_VIP_MULTIPLIER 1;
  43.     public const DEFAULT_VIP_CREATOR_VIP_MULTIPLIER 1.5;
  44.     public const DEFAULT_MIN_FLAT_FEE 0;
  45.     public const DEFAULT_IS_SHOW_LESS_THAN_FLAT_FEE true;
  46.     #[Column(enumTypePlatform::class, nullabletrue)]
  47.     private ?Platform $platform null;
  48.     
  49.     /**
  50.      * Primary posting language as an ISO-639-1 code (e.g. 'en', 'es', 'pt'), derived from the mode of
  51.      * the creator's recent post textLanguage (profile language fallback). Mirrors
  52.      * creator_classification.posting_language onto the creator row so it is directly readable and
  53.      * filterable for sponsor targeting. Null when TikTok exposes no usable language signal.
  54.      */
  55.     #[Column(type'string'length8nullabletrue)]
  56.     private ?string $language null;
  57.     #[Column(type'string')]
  58.     private string $username;
  59.     #[Column(nullablefalse)]
  60.     private int $gender;
  61.     #[Column(type'date'nullablefalse)]
  62.     private DateTime $birthday;
  63.     #[Column(type'integer'options: ['unsigned' => true])]
  64.     private int $minimalAmount;
  65.     #[Column(type'integer'options: ['unsigned' => true])]
  66.     private int $minimalVipAmount;
  67.     #[Column(type'bigint'options: ['unsigned' => true])]
  68.     private int $followers;
  69.     #[Column(type'bigint'options: ['unsigned' => true])]
  70.     private int $likes;
  71.     #[Column(type'bigint'options: ['unsigned' => true])]
  72.     private int $averageViews;
  73.     #[Column(type'float'precision10scale2nullabletrueoptions: ['unsigned' => true,])]
  74.     private ?float $engagementRate;
  75.     #[Column(type'float'precision10scale2nullabletrueoptions: ['unsigned' => true,])]
  76.     private ?float $averageViewsCoeff 1.0;
  77.     #[Column(type'bigint'options: ['unsigned' => true'default' => 0])]
  78.     private int $videos;
  79.     #[Column(type'bigint'nullabletrueoptions: ['unsigned' => true])]
  80.     private ?int $tier;
  81.     #[Column(type'bigint'nullabletrueoptions: ['unsigned' => true])]
  82.     private ?int $ethnicity;
  83.     #[Column(type'bigint'nullabletrueoptions: ['unsigned' => true])]
  84.     private ?int $categoryGender;
  85.     #[Column(type'bigint'nullabletrueoptions: ['unsigned' => true])]
  86.     private ?int $ageGroup;
  87.     #[Column(type'bigint'nullabletrueoptions: ['unsigned' => true])]
  88.     private ?int $categoryParent;
  89.     #[Column(type'bigint'nullabletrueoptions: ['unsigned' => true])]
  90.     private ?int $attractivenessLevel;
  91.     #[Column(type'boolean')]
  92.     private bool $phoneNotifyCampaigns;
  93.     #[Column(type'boolean')]
  94.     private bool $emailNotifyCampaigns;
  95.     #[Column(type'boolean')]
  96.     private bool $emailNotifyNewsletter;
  97.     #[Column(type'boolean')]
  98.     private bool $vip false;
  99.     #[Column(type'float'nullablefalseoptions: ['default' => 1])]
  100.     private float $vipMultiplier self::DEFAULT_NON_VIP_CREATOR_VIP_MULTIPLIER;
  101.     #[Column(type'boolean')]
  102.     private bool $darkTheme false;
  103.     #[Column(type'boolean')]
  104.     private bool $isSurveyRequired true;
  105.     #[Column(type'boolean'options: ['default' => true])]
  106.     private bool $isActive true;
  107.     /**
  108.      * The TikTok canonical identity (union_id) this creator's submission account is LOCKED to.
  109.      * Set on first connect and on a post-90-day swap; the TikTok handle is mutable so identity is keyed
  110.      * on the stable union_id, never the username. Null = not yet locked (locks on next OAuth).
  111.      */
  112.     #[Column(type'uuid'nullabletrue)]
  113.     private ?Uuid $lockedTikTokUnionId null;
  114.     /**
  115.      * When {@see $lockedTikTokUnionId} was established. The 90-day swap window is measured from here.
  116.      */
  117.     #[Column(type'datetime_immutable'nullabletrue)]
  118.     private ?DateTimeImmutable $lockedAt null;
  119.     #[Column(type'text')]
  120.     private string $bio '';
  121.     #[Column(type'string')]
  122.     private string $facebook '';
  123.     #[Column(type'string')]
  124.     private string $youtube '';
  125.     #[Column(type'string')]
  126.     private string $instagram '';
  127.     #[Column(type'string')]
  128.     private ?string $twitter null;
  129.     #[Column(type'string'nullabletrue)]
  130.     private ?string $cover null;
  131.     #[Column(type'string'nullabletrue)]
  132.     private ?string $profilePictureUrl null;
  133.     #[Column(type'string'nullabletrue)]
  134.     private ?string $paypalId null;
  135.     #[Column(type'string'nullabletrue)]
  136.     private ?string $tikTokId;
  137.     #[Column(
  138.         type'json',
  139.         columnDefinition'JSON DEFAULT (JSON_ARRAY()) NOT NULL',
  140.     )]
  141.     private ?array $lastNotifications = [];
  142.     #[Column(
  143.         type'json',
  144.         columnDefinition'JSON DEFAULT (JSON_OBJECT()) NOT NULL',
  145.     )]
  146.     private array|object $updates;
  147.     #[Column(type'datetime_immutable'nullabletrue)]
  148.     private ?DateTimeImmutable $lastActiveAt;
  149.     #[Column(type'datetime_immutable'nullabletrue)]
  150.     private ?DateTimeImmutable $scrapedAt;
  151.     #[Column(type'datetime_immutable'nullabletrue)]
  152.     private ?DateTimeImmutable $videoScrapedAt;
  153.     #[Column(type'boolean')]
  154.     private bool $canChangeCountry true;
  155.     #[OneToOne(targetEntityTikTokAuth::class)]
  156.     private ?TikTokAuth $tikTokAuth null;
  157.     #[OneToOne(targetEntityInstagramAuth::class)]
  158.     private ?InstagramAuth $instagramAuth;
  159.     #[OneToOne(targetEntityYoutubeAuth::class, cascade: ['persist''remove'])]
  160.     private ?YoutubeAuth $youtubeAuth;
  161.     #[OneToOne(targetEntityGeolocation::class, cascade: ['persist''remove'])]
  162.     private ?Geolocation $geolocation;
  163.     #[ManyToOne(targetEntityCountry::class)]
  164.     private Country $country;
  165.     #[ManyToOne(targetEntityCountry::class)]
  166.     private ?Country $initiallyCountry;
  167.     #[ManyToMany(targetEntityRoster::class, mappedBy'creators'cascade: ['persist'])]
  168.     private Collection $rosters;
  169.     #[OneToMany(mappedBy'creator'targetEntityActivity::class)]
  170.     private Collection $activities;
  171.     #[ManyToMany(targetEntityBadge::class)]
  172.     private Collection $badges;
  173.     #[OneToMany(mappedBy'creator'targetEntityDevice::class)]
  174.     private Collection $devices;
  175.     #[OneToMany(mappedBy'creator'targetEntityUserAnswer::class)]
  176.     private Collection $surveyAnswers;
  177.     #[OneToMany(mappedBy'creator'targetEntityVideo::class)]
  178.     private Collection $videoCollection;
  179.     #[Column(type'datetime'nullabletrue)]
  180.     private ?DateTime $skippedAt null;
  181.     #[Column(type'datetime'nullabletrue)]
  182.     private ?DateTime $verifiedAt null;
  183.     #[Column(options: ['unsigned' => true'default' => self::DEFAULT_MIN_FLAT_FEE])]
  184.     private int $minFlatFee;
  185.     #[Column(type'boolean'options: ['default' => self::DEFAULT_IS_SHOW_LESS_THAN_FLAT_FEE])]
  186.     private bool $isShowLessThanFlatFee;
  187.     #[OneToOne(mappedBy'creator'targetEntityAnalyticsCreatorsData::class, cascade: ['persist''remove'])]
  188.     private ?AnalyticsCreatorsData $analytics null;
  189.     #[Column(type'string'nullabletrue)]
  190.     private ?string $stripeId;
  191.     #[Column(name'password'type'string'nullabletrue)]
  192.     private ?string $password null;
  193.     #[Column(type'boolean'options: ['default' => false])]
  194.     private bool $stripeConnected false;
  195.     /**
  196.      * Owning login user (may differ from profile id when multiple creator profiles share one account).
  197.      */
  198.     #[ManyToOne(targetEntityUser::class)]
  199.     #[JoinColumn(name'user_id'referencedColumnName'id'nullabletrueonDelete'SET NULL')]
  200.     private ?User $owningUser null;
  201.     public function __construct()
  202.     {
  203.         $this->updates = new stdClass();
  204.         $this->activities = new ArrayCollection();
  205.         $this->devices = new ArrayCollection();
  206.         $this->videoCollection = new ArrayCollection();
  207.         $this->badges = new ArrayCollection();
  208.         $this->surveyAnswers = new ArrayCollection();
  209.     }
  210.     public function __toString(): string
  211.     {
  212.         return sprintf('#%d @%s'$this->getId(), $this->getUsername());
  213.     }
  214.     public function getPlatform(): ?Platform
  215.     {
  216.         if ($this->platform instanceof Platform) {
  217.             return $this->platform;
  218.         }
  219.         if ($this->youtubeAuth !== null) {
  220.             return Platform::YOUTUBE;
  221.         }
  222.         if ($this->tikTokAuth !== null) {
  223.             return Platform::TIKTOK;
  224.         }
  225.         if ($this->instagramAuth !== null) {
  226.             return Platform::INSTAGRAM;
  227.         }
  228.         return null;
  229.     }
  230.     /**
  231.      * @return Platform[]
  232.      */
  233.     public function getLinkedPlatforms(): array
  234.     {
  235.         $platforms = [];
  236.         if ($this->platform instanceof Platform) {
  237.             $platforms[$this->platform->value] = $this->platform;
  238.         }
  239.         if ($this->youtubeAuth !== null) {
  240.             $platforms[Platform::YOUTUBE->value] = Platform::YOUTUBE;
  241.         }
  242.         if ($this->tikTokAuth !== null) {
  243.             $platforms[Platform::TIKTOK->value] = Platform::TIKTOK;
  244.         }
  245.         if ($this->instagramAuth !== null) {
  246.             $platforms[Platform::INSTAGRAM->value] = Platform::INSTAGRAM;
  247.         }
  248.         return array_values($platforms);
  249.     }
  250.     /**
  251.      * @return string[]
  252.      */
  253.     public function getLinkedPlatformValues(): array
  254.     {
  255.         return array_map(
  256.             static fn (Platform $platform): string => $platform->value,
  257.             $this->getLinkedPlatforms(),
  258.         );
  259.     }
  260.     public function requirePlatform(): Platform
  261.     {
  262.         $platform $this->getPlatform();
  263.         if ($platform === null) {
  264.             throw new LogicException(sprintf('Creator #%d has no linked platform'$this->getId() ?? 0));
  265.         }
  266.         return $platform;
  267.     }
  268.     public function setPlatform(?Platform $platform): static
  269.     {
  270.         $this->platform $platform;
  271.         return $this;
  272.     }
  273.     /**
  274.      * ISO-639-1 posting language for this creator profile only ({@see User::$language} on this row).
  275.      * Not propagated to owning-account peers â€” each linked platform profile keeps its own language.
  276.      */
  277.     public function getLanguage(): ?string
  278.     {
  279.         return $this->getLanguageValue();
  280.     }
  281.     public function setLanguage(?string $language): static
  282.     {
  283.         $this->setLanguageValue($language);
  284.         return $this;
  285.     }
  286.     public function fromInstagramPlatform(): bool
  287.     {
  288.         return $this->getPlatform() === Platform::INSTAGRAM;
  289.     }
  290.     public function fromTiktokPlatform(): bool
  291.     {
  292.         return $this->getPlatform() === Platform::TIKTOK;
  293.     }
  294.     public function getDisplayPlatform(): string
  295.     {
  296.         return $this->getPlatform()?->label() ?? 'Unknown';
  297.     }
  298.     public function getUsername(): string
  299.     {
  300.         if (!isset($this->username)) {
  301.             return parent::getUsername();
  302.         }
  303.         return $this->username;
  304.     }
  305.     public function setUsername(string $username): static
  306.     {
  307.         $this->username $username;
  308.         return $this;
  309.     }
  310.     public function getGender(): int
  311.     {
  312.         return $this->gender;
  313.     }
  314.     public function setGender(int $gender): static
  315.     {
  316.         $this->gender $gender;
  317.         return $this;
  318.     }
  319.     public function getBirthday(): DateTime
  320.     {
  321.         return $this->birthday;
  322.     }
  323.     public function setBirthday(DateTime $birthday): static
  324.     {
  325.         $this->birthday $birthday;
  326.         return $this;
  327.     }
  328.     public function setMinimalAmount(int $amount): static
  329.     {
  330.         $this->minimalAmount $amount;
  331.         return $this;
  332.     }
  333.     public function getMinimalAmount(): int
  334.     {
  335.         return $this->minimalAmount;
  336.     }
  337.     /**
  338.      * @return int
  339.      */
  340.     public function getMinimalVipAmount(): int
  341.     {
  342.         return $this->minimalVipAmount;
  343.     }
  344.     /**
  345.      * @param int $minimalVipAmount
  346.      */
  347.     public function setMinimalVipAmount(int $minimalVipAmount): static
  348.     {
  349.         $this->minimalVipAmount $minimalVipAmount;
  350.         return $this;
  351.     }
  352.     public function setLikes(int $likes): static
  353.     {
  354.         $this->likes $likes;
  355.         return $this;
  356.     }
  357.     public function getLikes(): int
  358.     {
  359.         return $this->likes;
  360.     }
  361.     public function getFollowers(): int
  362.     {
  363.         return $this->followers;
  364.     }
  365.     public function setFollowers(int $followers): static
  366.     {
  367.         $this->followers $followers;
  368.         return $this;
  369.     }
  370.     public function getAverageViews(): int
  371.     {
  372.         return $this->averageViews;
  373.     }
  374.     public function setAverageViews(int $views): static
  375.     {
  376.         $this->averageViews $views;
  377.         return $this;
  378.     }
  379.     public function setVideos(int $videos): static
  380.     {
  381.         $this->videos $videos;
  382.         return $this;
  383.     }
  384.     public function getVideos(): int
  385.     {
  386.         return $this->videos;
  387.     }
  388.     public function getVideoCollection(): Collection
  389.     {
  390.         return $this->videoCollection;
  391.     }
  392.     public function getSubscriptions(): array
  393.     {
  394.         $result = [];
  395.         if ($this->isEmailNotifyCampaigns()) {
  396.             $result[] = Subscription::CAMPAIGN_EMAIL;
  397.         }
  398.         if ($this->isEmailNotifyNewsletter()) {
  399.             $result[] = Subscription::NEWSLETTER_EMAIL;
  400.         }
  401.         return $result;
  402.     }
  403.     public function isSurveyRequired(): bool
  404.     {
  405.         return $this->isSurveyRequired;
  406.     }
  407.     public function setIsSurveyRequired(bool $isSurveyRequired): void
  408.     {
  409.         $this->isSurveyRequired $isSurveyRequired;
  410.     }
  411.     public function isActive(): bool
  412.     {
  413.         return $this->isActive;
  414.     }
  415.     public function setIsActive(bool $isActive): static
  416.     {
  417.         $this->isActive $isActive;
  418.         return $this;
  419.     }
  420.     public function getLockedTikTokUnionId(): ?Uuid
  421.     {
  422.         return $this->lockedTikTokUnionId;
  423.     }
  424.     public function setLockedTikTokUnionId(?Uuid $lockedTikTokUnionId): static
  425.     {
  426.         $this->lockedTikTokUnionId $lockedTikTokUnionId;
  427.         return $this;
  428.     }
  429.     public function getLockedAt(): ?DateTimeImmutable
  430.     {
  431.         return $this->lockedAt;
  432.     }
  433.     public function setLockedAt(?DateTimeImmutable $lockedAt): static
  434.     {
  435.         $this->lockedAt $lockedAt;
  436.         return $this;
  437.     }
  438.     /**
  439.      * True when this creator is locked to a TikTok union_id AND the lock window has not elapsed,
  440.      * i.e. the submission account cannot be swapped to a different union_id yet.
  441.      */
  442.     public function isTikTokLockActive(DateTimeImmutable $nowint $lockDays): bool
  443.     {
  444.         if ($this->lockedTikTokUnionId === null || $this->lockedAt === null) {
  445.             return false;
  446.         }
  447.         return $this->lockedAt->modify(sprintf('+%d days'$lockDays)) > $now;
  448.     }
  449.     public function isPhoneNotifyCampaigns(): bool
  450.     {
  451.         return $this->phoneNotifyCampaigns;
  452.     }
  453.     public function setPhoneNotifyCampaigns(bool $phoneNotifyCampaigns): static
  454.     {
  455.         $this->phoneNotifyCampaigns $phoneNotifyCampaigns;
  456.         return $this;
  457.     }
  458.     public function isEmailNotifyCampaigns(): bool
  459.     {
  460.         return $this->emailNotifyCampaigns;
  461.     }
  462.     public function setEmailNotifyCampaigns(bool $emailNotifyCampaigns): static
  463.     {
  464.         $this->emailNotifyCampaigns $emailNotifyCampaigns;
  465.         return $this;
  466.     }
  467.     public function isEmailNotifyNewsletter(): bool
  468.     {
  469.         return $this->emailNotifyNewsletter;
  470.     }
  471.     public function setEmailNotifyNewsletter(bool $emailNotifyNewsletter): static
  472.     {
  473.         $this->emailNotifyNewsletter $emailNotifyNewsletter;
  474.         return $this;
  475.     }
  476.     public function getLastNotifications(): array
  477.     {
  478.         return $this->lastNotifications ?? [];
  479.     }
  480.     public function addLastNotification(string $type\DateTimeInterface $dateTime): void
  481.     {
  482.         $this->lastNotifications[$type] = $dateTime->getTimestamp();
  483.     }
  484.     public function getTikTokAuth(): ?TikTokAuth
  485.     {
  486.         return $this->tikTokAuth;
  487.     }
  488.     public function setTikTokAuth(?TikTokAuth $tikTokAuth): static
  489.     {
  490.         $this->tikTokAuth $tikTokAuth;
  491.         return $this;
  492.     }
  493.     public function getInstagramAuth(): ?InstagramAuth
  494.     {
  495.         return $this->instagramAuth;
  496.     }
  497.     public function setInstagramAuth(?InstagramAuth $instagramAuth): static
  498.     {
  499.         $this->instagramAuth $instagramAuth;
  500.         return $this;
  501.     }
  502.     public function getYoutubeAuth(): ?YoutubeAuth
  503.     {
  504.         return $this->youtubeAuth;
  505.     }
  506.     public function setYoutubeAuth(?YoutubeAuth $youtubeAuth): static
  507.     {
  508.         $this->youtubeAuth $youtubeAuth;
  509.         return $this;
  510.     }
  511.     public function getCountry(): Country
  512.     {
  513.         return $this->country;
  514.     }
  515.     public function setCountry(Country $country): self
  516.     {
  517.         $this->country $country;
  518.         return $this;
  519.     }
  520.     public function getRosters(): Collection
  521.     {
  522.         return $this->rosters;
  523.     }
  524.     public function addRoster(Roster $roster): void
  525.     {
  526.         if (!$this->rosters->contains($roster)) {
  527.             $this->rosters->add($roster);
  528.             $roster->addCreator($this);
  529.         }
  530.     }
  531.     public function setRosters(Collection $rosters): static
  532.     {
  533.         $this->rosters $rosters;
  534.         return $this;
  535.     }
  536.     public function getActivities(): Collection
  537.     {
  538.         return $this->activities;
  539.     }
  540.     public function getActiveActivitiesCount(): int
  541.     {
  542.         return $this->activities->filter(function ($activity) {
  543.             return in_array($activity->getStatus(), [
  544.                 Status::ACTIVE,
  545.                 Status::ACCEPTED,
  546.                 Status::VIDEO_PENDING,
  547.                 Status::VIDEO_REVIEW,
  548.             ]);
  549.         })->count();
  550.     }
  551.     public function getDevices(): Collection
  552.     {
  553.         return $this->devices;
  554.     }
  555.     public function setVip(bool $vip): static
  556.     {
  557.         $this->vip $vip;
  558.         return $this;
  559.     }
  560.     public function isVip(): bool
  561.     {
  562.         return $this->vip;
  563.     }
  564.     public function getVipMultiplier(): float
  565.     {
  566.         return $this->vipMultiplier;
  567.     }
  568.     public function setVipMultiplier(float $vipMultiplier): static
  569.     {
  570.         $this->vipMultiplier $vipMultiplier;
  571.         return $this;
  572.     }
  573.     public function setDarkTheme(bool $darkTheme): static
  574.     {
  575.         $this->darkTheme $darkTheme;
  576.         return $this;
  577.     }
  578.     public function isDarkTheme(): bool
  579.     {
  580.         return $this->darkTheme;
  581.     }
  582.     public function setBadges(Collection $badges): static
  583.     {
  584.         $this->badges $badges;
  585.         return $this;
  586.     }
  587.     public function getBadges(): Collection
  588.     {
  589.         return $this->badges;
  590.     }
  591.     public function setBio(string $bio): static
  592.     {
  593.         $this->bio $bio;
  594.         return $this;
  595.     }
  596.     public function getBio(): string
  597.     {
  598.         return $this->bio;
  599.     }
  600.     public function setFacebook(string $facebook): static
  601.     {
  602.         $this->facebook $facebook;
  603.         return $this;
  604.     }
  605.     public function getFacebook(): string
  606.     {
  607.         return $this->facebook;
  608.     }
  609.     public function setYoutube(string $youtube): static
  610.     {
  611.         $this->youtube $youtube;
  612.         return $this;
  613.     }
  614.     public function getYoutube(): string
  615.     {
  616.         return $this->youtube;
  617.     }
  618.     public function setInstagram(string $instagram): static
  619.     {
  620.         $this->instagram $instagram;
  621.         return $this;
  622.     }
  623.     public function getInstagram(): string
  624.     {
  625.         return $this->instagram;
  626.     }
  627.     public function getTwitter(): ?string
  628.     {
  629.         return $this->twitter;
  630.     }
  631.     public function setTwitter(?string $twitter): void
  632.     {
  633.         $this->twitter $twitter;
  634.     }
  635.     public function getCover(): ?string
  636.     {
  637.         return $this->cover;
  638.     }
  639.     public function getProfilePictureUrl(): ?string
  640.     {
  641.         return $this->profilePictureUrl;
  642.     }
  643.     public function setProfilePictureUrl(?string $profilePictureUrl): static
  644.     {
  645.         $this->profilePictureUrl $profilePictureUrl;
  646.         return $this;
  647.     }
  648.     public function setUpdates(object|array $updates): static
  649.     {
  650.         $this->updates $updates;
  651.         return $this;
  652.     }
  653.     public function getUpdates(): object|array
  654.     {
  655.         return $this->updates;
  656.     }
  657.     public function getPaypalId(): ?string
  658.     {
  659.         return $this->paypalId;
  660.     }
  661.     public function setPaypalId(?string $paypalId): static
  662.     {
  663.         $this->paypalId $paypalId;
  664.         return $this;
  665.     }
  666.     public function getTiktokId(): ?string
  667.     {
  668.         return $this->tikTokId;
  669.     }
  670.     public function setTikTokId(?string $tikTokId): static
  671.     {
  672.         $this->tikTokId $tikTokId;
  673.         return $this;
  674.     }
  675.     public function setLastActiveAt(?DateTimeImmutable $lastActiveAt): void
  676.     {
  677.         $this->lastActiveAt $lastActiveAt;
  678.     }
  679.     public function getLastActiveAt(): ?DateTimeImmutable
  680.     {
  681.         return $this->lastActiveAt;
  682.     }
  683.     public function setScrapedAt(?DateTimeImmutable $scrapedAt): void
  684.     {
  685.         $this->scrapedAt $scrapedAt;
  686.     }
  687.     public function getScrapedAt(): ?DateTimeImmutable
  688.     {
  689.         return $this->scrapedAt;
  690.     }
  691.     public function setVideoScrapedAt(?DateTimeImmutable $videoScrapedAt): void
  692.     {
  693.         $this->videoScrapedAt $videoScrapedAt;
  694.     }
  695.     public function getVideoScrapedAt(): ?DateTimeImmutable
  696.     {
  697.         return $this->videoScrapedAt;
  698.     }
  699.     public function hasMobileApp(): bool
  700.     {
  701.         return $this->devices->count() > 0;
  702.     }
  703.     public function mobilePlatform(): ?string
  704.     {
  705.         $device $this->devices->first();
  706.         /** @var Device|false $device */
  707.         if ($device !== false) {
  708.             return $device->getPlatform();
  709.         }
  710.         return null;
  711.     }
  712.     public function isSkipped(): bool
  713.     {
  714.         return $this->skippedAt !== null
  715.             && $this->skippedAt->modify('+1 month') > new DateTime();
  716.     }
  717.     public function setSkippedAt(?DateTime $skippedAt)
  718.     {
  719.         $this->skippedAt $skippedAt;
  720.         if ($skippedAt !== null) {
  721.             $this->verifiedAt null;
  722.         }
  723.     }
  724.     public function isVerified(): bool
  725.     {
  726.         return $this->verifiedAt !== null;
  727.     }
  728.     public function setVerifiedAt(?DateTime $verifiedAt)
  729.     {
  730.         $this->verifiedAt $verifiedAt;
  731.         if ($verifiedAt !== null) {
  732.             $this->skippedAt null;
  733.         }
  734.     }
  735.     public function getGeolocation(): ?Geolocation
  736.     {
  737.         return $this->geolocation;
  738.     }
  739.     public function setGeolocation(Geolocation $geolocation): void
  740.     {
  741.         $this->geolocation $geolocation;
  742.     }
  743.     public function getSurveyAnswers(): Collection
  744.     {
  745.         return $this->surveyAnswers;
  746.     }
  747.     public function needUpdate(string $keyNameint $updatePeriodDays): bool
  748.     {
  749.         $lastUpdateDate $this->updates[$keyName] ?? null;
  750.         if (is_null($lastUpdateDate)) {
  751.             return true;
  752.         }
  753.         $now = new DateTimeImmutable();
  754.         return (new DateTimeImmutable($lastUpdateDate))->diff($now)->days >= $updatePeriodDays;
  755.     }
  756.     public function needUpdateAllStatistic(int $updatePeriodDays): bool
  757.     {
  758.         return $this->needUpdate('allStatistic'$updatePeriodDays);
  759.     }
  760.     public function needUpdateAvatar(int $updatePeriodDays): bool
  761.     {
  762.         return $this->needUpdate('avatar'$updatePeriodDays);
  763.     }
  764.     public function getInitiallyCountry(): ?Country
  765.     {
  766.         return $this->initiallyCountry;
  767.     }
  768.     public function setInitiallyCountry(?Country $initiallyCountry): void
  769.     {
  770.         $this->initiallyCountry $initiallyCountry;
  771.     }
  772.     public function getCanChangeCountry(): bool
  773.     {
  774.         return $this->canChangeCountry;
  775.     }
  776.     public function setCanChangeCountry(bool $canChangeCountry): void
  777.     {
  778.         $this->canChangeCountry $canChangeCountry;
  779.     }
  780.     public function getEngagementRate(): ?float
  781.     {
  782.         return $this->engagementRate;
  783.     }
  784.     public function setEngagementRate(float $engagementRate): static
  785.     {
  786.         $this->engagementRate $engagementRate;
  787.         return $this;
  788.     }
  789.     public function getAverageViewsCoeff(): ?float
  790.     {
  791.         return $this->averageViewsCoeff;
  792.     }
  793.     public function setAverageViewsCoeff(float $averageViewsCoeff): static
  794.     {
  795.         $this->averageViewsCoeff $averageViewsCoeff;
  796.         return $this;
  797.     }
  798.     /**
  799.      * @return int|null
  800.      */
  801.     public function getTier(): ?int
  802.     {
  803.         return $this->tier;
  804.     }
  805.     /**
  806.      * @param int $tier
  807.      */
  808.     public function setTier(?int $tier): static
  809.     {
  810.         $this->tier $tier;
  811.         return $this;
  812.     }
  813.     /**
  814.      * @return int|null
  815.      */
  816.     public function getEthnicity(): ?int
  817.     {
  818.         return $this->ethnicity;
  819.     }
  820.     /**
  821.      * @param int|null $ethnicity
  822.      */
  823.     public function setEthnicity(?int $ethnicity): static
  824.     {
  825.         $this->ethnicity $ethnicity;
  826.         return $this;
  827.     }
  828.     /**
  829.      * @return int|null
  830.      */
  831.     public function getCategoryGender(): ?int
  832.     {
  833.         return $this->categoryGender;
  834.     }
  835.     /**
  836.      * @param int|null $categoryGender
  837.      */
  838.     public function setCategoryGender(?int $categoryGender): static
  839.     {
  840.         $this->categoryGender $categoryGender;
  841.         return $this;
  842.     }
  843.     /**
  844.      * @return int|null
  845.      */
  846.     public function getAgeGroup(): ?int
  847.     {
  848.         return $this->ageGroup;
  849.     }
  850.     /**
  851.      * @param int|null $ageGroup
  852.      */
  853.     public function setAgeGroup(?int $ageGroup): static
  854.     {
  855.         $this->ageGroup $ageGroup;
  856.         return $this;
  857.     }
  858.     /**
  859.      * @return int|null
  860.      */
  861.     public function getCategoryParent(): ?int
  862.     {
  863.         return $this->categoryParent;
  864.     }
  865.     /**
  866.      * @param int|null $categoryParent
  867.      */
  868.     public function setCategoryParent(?int $categoryParent): static
  869.     {
  870.         $this->categoryParent $categoryParent;
  871.         return $this;
  872.     }
  873.     /**
  874.      * @return int|null
  875.      */
  876.     public function getAttractivenessLevel(): ?int
  877.     {
  878.         return $this->attractivenessLevel;
  879.     }
  880.     /**
  881.      * @param int|null $attractivenessLevel
  882.      */
  883.     public function setAttractivenessLevel(?int $attractivenessLevel): static
  884.     {
  885.         $this->attractivenessLevel $attractivenessLevel;
  886.         return $this;
  887.     }
  888.     public function getMinFlatFee(): int
  889.     {
  890.         return $this->minFlatFee;
  891.     }
  892.     public function setMinFlatFee(int $minFlatFee)
  893.     {
  894.         $this->minFlatFee $minFlatFee;
  895.         return $this;
  896.     }
  897.     public function getIsShowLessThanFlatFee(): bool
  898.     {
  899.         return $this->isShowLessThanFlatFee;
  900.     }
  901.     public function setIsShowLessThanFlatFee(bool $isShowLessThanFlatFee)
  902.     {
  903.         $this->isShowLessThanFlatFee $isShowLessThanFlatFee;
  904.         return $this;
  905.     }
  906.     public function getAnalytics(): ?AnalyticsCreatorsData
  907.     {
  908.         return $this->analytics;
  909.     }
  910.     public function setAnalytics(?AnalyticsCreatorsData $analytics)
  911.     {
  912.         $this->analytics $analytics;
  913.         return $this;
  914.     }
  915.     public function getStripeId(): ?string
  916.     {
  917.         return $this->stripeId;
  918.     }
  919.     public function setStripeId(?string $stripeId)
  920.     {
  921.         $this->stripeId $stripeId;
  922.         return $this;
  923.     }
  924.     public function getStripeConnected(): bool
  925.     {
  926.         return $this->stripeConnected;
  927.     }
  928.     public function setStripeConnected(bool $stripeConnected)
  929.     {
  930.         $this->stripeConnected $stripeConnected;
  931.         return $this;
  932.     }
  933.     public function isStripeConnected(): bool
  934.     {
  935.         return $this->stripeConnected;
  936.     }
  937.     public function setPassword(?string $password): static
  938.     {
  939.         $this->password $password;
  940.         return $this;
  941.     }
  942.     public function getPassword(): string
  943.     {
  944.         return $this->password ?? '';
  945.     }
  946.     public function getOwningUser(): ?User
  947.     {
  948.         return $this->owningUser;
  949.     }
  950.     public function setOwningUser(?User $owningUser): static
  951.     {
  952.         $this->owningUser $owningUser;
  953.         return $this;
  954.     }
  955.     /**
  956.      * Owning account user id for JWT `user_id` claim / grouping; falls back to this profile's id.
  957.      */
  958.     public function getOwningUserId(): int
  959.     {
  960.         if ($this->owningUser instanceof User) {
  961.             $oid $this->owningUser->getId();
  962.             if ($oid !== null) {
  963.                 return $oid;
  964.             }
  965.         }
  966.         $id $this->getId();
  967.         if ($id === null) {
  968.             throw new LogicException('Creator id must be known to resolve owning user id.');
  969.         }
  970.         return $id;
  971.     }
  972. }