<?php
declare(strict_types=1);
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Contracts\Activity\Status;
use App\Contracts\Platform\Platform;
use App\Contracts\User\Subscription;
use App\Entity\Survey\UserAnswer;
use DateTime;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\JoinTable;
use Doctrine\ORM\Mapping\ManyToMany;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\OneToOne;
use Symfony\Component\Uid\Uuid;
use LogicException;
use stdClass;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
#[Entity]
#[Index(fields: ['username'], name: 'username')]
#[Index(fields: ['skippedAt'], name: 'skipped_at')]
#[Index(fields: ['verifiedAt'], name: 'verified_at')]
#[Index(fields: ['platform'], name: 'platform')]
#[Index(fields: ['username', 'platform'], name: 'idx_creator_username_platform')]
#[Index(columns: ['last_active_at', 'skipped_at'], name: 'idx_last_active_skipped')]
#[Index(columns: ['locked_tik_tok_union_id'], name: 'idx_creator_locked_union')]
#[Index(columns: ['language'], name: 'idx_creator_language')]
#[ApiResource(attributes: ['route_prefix' => 'v1'])]
class Creator extends User implements PasswordAuthenticatedUserInterface
{
public const ROLE_NAME = 'ROLE_CREATOR';
/** @var int */
public const DEFAULT_MINIMAL_AMOUNT = 0;
public const DEFAULT_VIP_MINIMAL_AMOUNT = 0;
public const DEFAULT_NON_VIP_CREATOR_VIP_MULTIPLIER = 1;
public const DEFAULT_VIP_CREATOR_VIP_MULTIPLIER = 1.5;
public const DEFAULT_MIN_FLAT_FEE = 0;
public const DEFAULT_IS_SHOW_LESS_THAN_FLAT_FEE = true;
#[Column(enumType: Platform::class, nullable: true)]
private ?Platform $platform = null;
/**
* Primary posting language as an ISO-639-1 code (e.g. 'en', 'es', 'pt'), derived from the mode of
* the creator's recent post textLanguage (profile language fallback). Mirrors
* creator_classification.posting_language onto the creator row so it is directly readable and
* filterable for sponsor targeting. Null when TikTok exposes no usable language signal.
*/
#[Column(type: 'string', length: 8, nullable: true)]
private ?string $language = null;
#[Column(type: 'string')]
private string $username;
#[Column(nullable: false)]
private int $gender;
#[Column(type: 'date', nullable: false)]
private DateTime $birthday;
#[Column(type: 'integer', options: ['unsigned' => true])]
private int $minimalAmount;
#[Column(type: 'integer', options: ['unsigned' => true])]
private int $minimalVipAmount;
#[Column(type: 'bigint', options: ['unsigned' => true])]
private int $followers;
#[Column(type: 'bigint', options: ['unsigned' => true])]
private int $likes;
#[Column(type: 'bigint', options: ['unsigned' => true])]
private int $averageViews;
#[Column(type: 'float', precision: 10, scale: 2, nullable: true, options: ['unsigned' => true,])]
private ?float $engagementRate;
#[Column(type: 'float', precision: 10, scale: 2, nullable: true, options: ['unsigned' => true,])]
private ?float $averageViewsCoeff = 1.0;
#[Column(type: 'bigint', options: ['unsigned' => true, 'default' => 0])]
private int $videos;
#[Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $tier;
#[Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $ethnicity;
#[Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $categoryGender;
#[Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $ageGroup;
#[Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $categoryParent;
#[Column(type: 'bigint', nullable: true, options: ['unsigned' => true])]
private ?int $attractivenessLevel;
#[Column(type: 'boolean')]
private bool $phoneNotifyCampaigns;
#[Column(type: 'boolean')]
private bool $emailNotifyCampaigns;
#[Column(type: 'boolean')]
private bool $emailNotifyNewsletter;
#[Column(type: 'boolean')]
private bool $vip = false;
#[Column(type: 'float', nullable: false, options: ['default' => 1])]
private float $vipMultiplier = self::DEFAULT_NON_VIP_CREATOR_VIP_MULTIPLIER;
#[Column(type: 'boolean')]
private bool $darkTheme = false;
#[Column(type: 'boolean')]
private bool $isSurveyRequired = true;
#[Column(type: 'boolean', options: ['default' => true])]
private bool $isActive = true;
/**
* The TikTok canonical identity (union_id) this creator's submission account is LOCKED to.
* Set on first connect and on a post-90-day swap; the TikTok handle is mutable so identity is keyed
* on the stable union_id, never the username. Null = not yet locked (locks on next OAuth).
*/
#[Column(type: 'uuid', nullable: true)]
private ?Uuid $lockedTikTokUnionId = null;
/**
* When {@see $lockedTikTokUnionId} was established. The 90-day swap window is measured from here.
*/
#[Column(type: 'datetime_immutable', nullable: true)]
private ?DateTimeImmutable $lockedAt = null;
#[Column(type: 'text')]
private string $bio = '';
#[Column(type: 'string')]
private string $facebook = '';
#[Column(type: 'string')]
private string $youtube = '';
#[Column(type: 'string')]
private string $instagram = '';
#[Column(type: 'string')]
private ?string $twitter = null;
#[Column(type: 'string', nullable: true)]
private ?string $cover = null;
#[Column(type: 'string', nullable: true)]
private ?string $profilePictureUrl = null;
#[Column(type: 'string', nullable: true)]
private ?string $paypalId = null;
#[Column(type: 'string', nullable: true)]
private ?string $tikTokId;
#[Column(
type: 'json',
columnDefinition: 'JSON DEFAULT (JSON_ARRAY()) NOT NULL',
)]
private ?array $lastNotifications = [];
#[Column(
type: 'json',
columnDefinition: 'JSON DEFAULT (JSON_OBJECT()) NOT NULL',
)]
private array|object $updates;
#[Column(type: 'datetime_immutable', nullable: true)]
private ?DateTimeImmutable $lastActiveAt;
#[Column(type: 'datetime_immutable', nullable: true)]
private ?DateTimeImmutable $scrapedAt;
#[Column(type: 'datetime_immutable', nullable: true)]
private ?DateTimeImmutable $videoScrapedAt;
#[Column(type: 'boolean')]
private bool $canChangeCountry = true;
#[OneToOne(targetEntity: TikTokAuth::class)]
private ?TikTokAuth $tikTokAuth = null;
#[OneToOne(targetEntity: InstagramAuth::class)]
private ?InstagramAuth $instagramAuth;
#[OneToOne(targetEntity: YoutubeAuth::class, cascade: ['persist', 'remove'])]
private ?YoutubeAuth $youtubeAuth;
#[OneToOne(targetEntity: Geolocation::class, cascade: ['persist', 'remove'])]
private ?Geolocation $geolocation;
#[ManyToOne(targetEntity: Country::class)]
private Country $country;
#[ManyToOne(targetEntity: Country::class)]
private ?Country $initiallyCountry;
#[ManyToMany(targetEntity: Roster::class, mappedBy: 'creators', cascade: ['persist'])]
private Collection $rosters;
#[OneToMany(mappedBy: 'creator', targetEntity: Activity::class)]
private Collection $activities;
#[ManyToMany(targetEntity: Badge::class)]
private Collection $badges;
#[OneToMany(mappedBy: 'creator', targetEntity: Device::class)]
private Collection $devices;
#[OneToMany(mappedBy: 'creator', targetEntity: UserAnswer::class)]
private Collection $surveyAnswers;
#[OneToMany(mappedBy: 'creator', targetEntity: Video::class)]
private Collection $videoCollection;
#[Column(type: 'datetime', nullable: true)]
private ?DateTime $skippedAt = null;
#[Column(type: 'datetime', nullable: true)]
private ?DateTime $verifiedAt = null;
#[Column(options: ['unsigned' => true, 'default' => self::DEFAULT_MIN_FLAT_FEE])]
private int $minFlatFee;
#[Column(type: 'boolean', options: ['default' => self::DEFAULT_IS_SHOW_LESS_THAN_FLAT_FEE])]
private bool $isShowLessThanFlatFee;
#[OneToOne(mappedBy: 'creator', targetEntity: AnalyticsCreatorsData::class, cascade: ['persist', 'remove'])]
private ?AnalyticsCreatorsData $analytics = null;
#[Column(type: 'string', nullable: true)]
private ?string $stripeId;
#[Column(name: 'password', type: 'string', nullable: true)]
private ?string $password = null;
#[Column(type: 'boolean', options: ['default' => false])]
private bool $stripeConnected = false;
/**
* Owning login user (may differ from profile id when multiple creator profiles share one account).
*/
#[ManyToOne(targetEntity: User::class)]
#[JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
private ?User $owningUser = null;
public function __construct()
{
$this->updates = new stdClass();
$this->activities = new ArrayCollection();
$this->devices = new ArrayCollection();
$this->videoCollection = new ArrayCollection();
$this->badges = new ArrayCollection();
$this->surveyAnswers = new ArrayCollection();
}
public function __toString(): string
{
return sprintf('#%d @%s', $this->getId(), $this->getUsername());
}
public function getPlatform(): ?Platform
{
if ($this->platform instanceof Platform) {
return $this->platform;
}
if ($this->youtubeAuth !== null) {
return Platform::YOUTUBE;
}
if ($this->tikTokAuth !== null) {
return Platform::TIKTOK;
}
if ($this->instagramAuth !== null) {
return Platform::INSTAGRAM;
}
return null;
}
/**
* @return Platform[]
*/
public function getLinkedPlatforms(): array
{
$platforms = [];
if ($this->platform instanceof Platform) {
$platforms[$this->platform->value] = $this->platform;
}
if ($this->youtubeAuth !== null) {
$platforms[Platform::YOUTUBE->value] = Platform::YOUTUBE;
}
if ($this->tikTokAuth !== null) {
$platforms[Platform::TIKTOK->value] = Platform::TIKTOK;
}
if ($this->instagramAuth !== null) {
$platforms[Platform::INSTAGRAM->value] = Platform::INSTAGRAM;
}
return array_values($platforms);
}
/**
* @return string[]
*/
public function getLinkedPlatformValues(): array
{
return array_map(
static fn (Platform $platform): string => $platform->value,
$this->getLinkedPlatforms(),
);
}
public function requirePlatform(): Platform
{
$platform = $this->getPlatform();
if ($platform === null) {
throw new LogicException(sprintf('Creator #%d has no linked platform', $this->getId() ?? 0));
}
return $platform;
}
public function setPlatform(?Platform $platform): static
{
$this->platform = $platform;
return $this;
}
/**
* ISO-639-1 posting language for this creator profile only ({@see User::$language} on this row).
* Not propagated to owning-account peers — each linked platform profile keeps its own language.
*/
public function getLanguage(): ?string
{
return $this->getLanguageValue();
}
public function setLanguage(?string $language): static
{
$this->setLanguageValue($language);
return $this;
}
public function fromInstagramPlatform(): bool
{
return $this->getPlatform() === Platform::INSTAGRAM;
}
public function fromTiktokPlatform(): bool
{
return $this->getPlatform() === Platform::TIKTOK;
}
public function getDisplayPlatform(): string
{
return $this->getPlatform()?->label() ?? 'Unknown';
}
public function getUsername(): string
{
if (!isset($this->username)) {
return parent::getUsername();
}
return $this->username;
}
public function setUsername(string $username): static
{
$this->username = $username;
return $this;
}
public function getGender(): int
{
return $this->gender;
}
public function setGender(int $gender): static
{
$this->gender = $gender;
return $this;
}
public function getBirthday(): DateTime
{
return $this->birthday;
}
public function setBirthday(DateTime $birthday): static
{
$this->birthday = $birthday;
return $this;
}
public function setMinimalAmount(int $amount): static
{
$this->minimalAmount = $amount;
return $this;
}
public function getMinimalAmount(): int
{
return $this->minimalAmount;
}
/**
* @return int
*/
public function getMinimalVipAmount(): int
{
return $this->minimalVipAmount;
}
/**
* @param int $minimalVipAmount
*/
public function setMinimalVipAmount(int $minimalVipAmount): static
{
$this->minimalVipAmount = $minimalVipAmount;
return $this;
}
public function setLikes(int $likes): static
{
$this->likes = $likes;
return $this;
}
public function getLikes(): int
{
return $this->likes;
}
public function getFollowers(): int
{
return $this->followers;
}
public function setFollowers(int $followers): static
{
$this->followers = $followers;
return $this;
}
public function getAverageViews(): int
{
return $this->averageViews;
}
public function setAverageViews(int $views): static
{
$this->averageViews = $views;
return $this;
}
public function setVideos(int $videos): static
{
$this->videos = $videos;
return $this;
}
public function getVideos(): int
{
return $this->videos;
}
public function getVideoCollection(): Collection
{
return $this->videoCollection;
}
public function getSubscriptions(): array
{
$result = [];
if ($this->isEmailNotifyCampaigns()) {
$result[] = Subscription::CAMPAIGN_EMAIL;
}
if ($this->isEmailNotifyNewsletter()) {
$result[] = Subscription::NEWSLETTER_EMAIL;
}
return $result;
}
public function isSurveyRequired(): bool
{
return $this->isSurveyRequired;
}
public function setIsSurveyRequired(bool $isSurveyRequired): void
{
$this->isSurveyRequired = $isSurveyRequired;
}
public function isActive(): bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): static
{
$this->isActive = $isActive;
return $this;
}
public function getLockedTikTokUnionId(): ?Uuid
{
return $this->lockedTikTokUnionId;
}
public function setLockedTikTokUnionId(?Uuid $lockedTikTokUnionId): static
{
$this->lockedTikTokUnionId = $lockedTikTokUnionId;
return $this;
}
public function getLockedAt(): ?DateTimeImmutable
{
return $this->lockedAt;
}
public function setLockedAt(?DateTimeImmutable $lockedAt): static
{
$this->lockedAt = $lockedAt;
return $this;
}
/**
* True when this creator is locked to a TikTok union_id AND the lock window has not elapsed,
* i.e. the submission account cannot be swapped to a different union_id yet.
*/
public function isTikTokLockActive(DateTimeImmutable $now, int $lockDays): bool
{
if ($this->lockedTikTokUnionId === null || $this->lockedAt === null) {
return false;
}
return $this->lockedAt->modify(sprintf('+%d days', $lockDays)) > $now;
}
public function isPhoneNotifyCampaigns(): bool
{
return $this->phoneNotifyCampaigns;
}
public function setPhoneNotifyCampaigns(bool $phoneNotifyCampaigns): static
{
$this->phoneNotifyCampaigns = $phoneNotifyCampaigns;
return $this;
}
public function isEmailNotifyCampaigns(): bool
{
return $this->emailNotifyCampaigns;
}
public function setEmailNotifyCampaigns(bool $emailNotifyCampaigns): static
{
$this->emailNotifyCampaigns = $emailNotifyCampaigns;
return $this;
}
public function isEmailNotifyNewsletter(): bool
{
return $this->emailNotifyNewsletter;
}
public function setEmailNotifyNewsletter(bool $emailNotifyNewsletter): static
{
$this->emailNotifyNewsletter = $emailNotifyNewsletter;
return $this;
}
public function getLastNotifications(): array
{
return $this->lastNotifications ?? [];
}
public function addLastNotification(string $type, \DateTimeInterface $dateTime): void
{
$this->lastNotifications[$type] = $dateTime->getTimestamp();
}
public function getTikTokAuth(): ?TikTokAuth
{
return $this->tikTokAuth;
}
public function setTikTokAuth(?TikTokAuth $tikTokAuth): static
{
$this->tikTokAuth = $tikTokAuth;
return $this;
}
public function getInstagramAuth(): ?InstagramAuth
{
return $this->instagramAuth;
}
public function setInstagramAuth(?InstagramAuth $instagramAuth): static
{
$this->instagramAuth = $instagramAuth;
return $this;
}
public function getYoutubeAuth(): ?YoutubeAuth
{
return $this->youtubeAuth;
}
public function setYoutubeAuth(?YoutubeAuth $youtubeAuth): static
{
$this->youtubeAuth = $youtubeAuth;
return $this;
}
public function getCountry(): Country
{
return $this->country;
}
public function setCountry(Country $country): self
{
$this->country = $country;
return $this;
}
public function getRosters(): Collection
{
return $this->rosters;
}
public function addRoster(Roster $roster): void
{
if (!$this->rosters->contains($roster)) {
$this->rosters->add($roster);
$roster->addCreator($this);
}
}
public function setRosters(Collection $rosters): static
{
$this->rosters = $rosters;
return $this;
}
public function getActivities(): Collection
{
return $this->activities;
}
public function getActiveActivitiesCount(): int
{
return $this->activities->filter(function ($activity) {
return in_array($activity->getStatus(), [
Status::ACTIVE,
Status::ACCEPTED,
Status::VIDEO_PENDING,
Status::VIDEO_REVIEW,
]);
})->count();
}
public function getDevices(): Collection
{
return $this->devices;
}
public function setVip(bool $vip): static
{
$this->vip = $vip;
return $this;
}
public function isVip(): bool
{
return $this->vip;
}
public function getVipMultiplier(): float
{
return $this->vipMultiplier;
}
public function setVipMultiplier(float $vipMultiplier): static
{
$this->vipMultiplier = $vipMultiplier;
return $this;
}
public function setDarkTheme(bool $darkTheme): static
{
$this->darkTheme = $darkTheme;
return $this;
}
public function isDarkTheme(): bool
{
return $this->darkTheme;
}
public function setBadges(Collection $badges): static
{
$this->badges = $badges;
return $this;
}
public function getBadges(): Collection
{
return $this->badges;
}
public function setBio(string $bio): static
{
$this->bio = $bio;
return $this;
}
public function getBio(): string
{
return $this->bio;
}
public function setFacebook(string $facebook): static
{
$this->facebook = $facebook;
return $this;
}
public function getFacebook(): string
{
return $this->facebook;
}
public function setYoutube(string $youtube): static
{
$this->youtube = $youtube;
return $this;
}
public function getYoutube(): string
{
return $this->youtube;
}
public function setInstagram(string $instagram): static
{
$this->instagram = $instagram;
return $this;
}
public function getInstagram(): string
{
return $this->instagram;
}
public function getTwitter(): ?string
{
return $this->twitter;
}
public function setTwitter(?string $twitter): void
{
$this->twitter = $twitter;
}
public function getCover(): ?string
{
return $this->cover;
}
public function getProfilePictureUrl(): ?string
{
return $this->profilePictureUrl;
}
public function setProfilePictureUrl(?string $profilePictureUrl): static
{
$this->profilePictureUrl = $profilePictureUrl;
return $this;
}
public function setUpdates(object|array $updates): static
{
$this->updates = $updates;
return $this;
}
public function getUpdates(): object|array
{
return $this->updates;
}
public function getPaypalId(): ?string
{
return $this->paypalId;
}
public function setPaypalId(?string $paypalId): static
{
$this->paypalId = $paypalId;
return $this;
}
public function getTiktokId(): ?string
{
return $this->tikTokId;
}
public function setTikTokId(?string $tikTokId): static
{
$this->tikTokId = $tikTokId;
return $this;
}
public function setLastActiveAt(?DateTimeImmutable $lastActiveAt): void
{
$this->lastActiveAt = $lastActiveAt;
}
public function getLastActiveAt(): ?DateTimeImmutable
{
return $this->lastActiveAt;
}
public function setScrapedAt(?DateTimeImmutable $scrapedAt): void
{
$this->scrapedAt = $scrapedAt;
}
public function getScrapedAt(): ?DateTimeImmutable
{
return $this->scrapedAt;
}
public function setVideoScrapedAt(?DateTimeImmutable $videoScrapedAt): void
{
$this->videoScrapedAt = $videoScrapedAt;
}
public function getVideoScrapedAt(): ?DateTimeImmutable
{
return $this->videoScrapedAt;
}
public function hasMobileApp(): bool
{
return $this->devices->count() > 0;
}
public function mobilePlatform(): ?string
{
$device = $this->devices->first();
/** @var Device|false $device */
if ($device !== false) {
return $device->getPlatform();
}
return null;
}
public function isSkipped(): bool
{
return $this->skippedAt !== null
&& $this->skippedAt->modify('+1 month') > new DateTime();
}
public function setSkippedAt(?DateTime $skippedAt)
{
$this->skippedAt = $skippedAt;
if ($skippedAt !== null) {
$this->verifiedAt = null;
}
}
public function isVerified(): bool
{
return $this->verifiedAt !== null;
}
public function setVerifiedAt(?DateTime $verifiedAt)
{
$this->verifiedAt = $verifiedAt;
if ($verifiedAt !== null) {
$this->skippedAt = null;
}
}
public function getGeolocation(): ?Geolocation
{
return $this->geolocation;
}
public function setGeolocation(Geolocation $geolocation): void
{
$this->geolocation = $geolocation;
}
public function getSurveyAnswers(): Collection
{
return $this->surveyAnswers;
}
public function needUpdate(string $keyName, int $updatePeriodDays): bool
{
$lastUpdateDate = $this->updates[$keyName] ?? null;
if (is_null($lastUpdateDate)) {
return true;
}
$now = new DateTimeImmutable();
return (new DateTimeImmutable($lastUpdateDate))->diff($now)->days >= $updatePeriodDays;
}
public function needUpdateAllStatistic(int $updatePeriodDays): bool
{
return $this->needUpdate('allStatistic', $updatePeriodDays);
}
public function needUpdateAvatar(int $updatePeriodDays): bool
{
return $this->needUpdate('avatar', $updatePeriodDays);
}
public function getInitiallyCountry(): ?Country
{
return $this->initiallyCountry;
}
public function setInitiallyCountry(?Country $initiallyCountry): void
{
$this->initiallyCountry = $initiallyCountry;
}
public function getCanChangeCountry(): bool
{
return $this->canChangeCountry;
}
public function setCanChangeCountry(bool $canChangeCountry): void
{
$this->canChangeCountry = $canChangeCountry;
}
public function getEngagementRate(): ?float
{
return $this->engagementRate;
}
public function setEngagementRate(float $engagementRate): static
{
$this->engagementRate = $engagementRate;
return $this;
}
public function getAverageViewsCoeff(): ?float
{
return $this->averageViewsCoeff;
}
public function setAverageViewsCoeff(float $averageViewsCoeff): static
{
$this->averageViewsCoeff = $averageViewsCoeff;
return $this;
}
/**
* @return int|null
*/
public function getTier(): ?int
{
return $this->tier;
}
/**
* @param int $tier
*/
public function setTier(?int $tier): static
{
$this->tier = $tier;
return $this;
}
/**
* @return int|null
*/
public function getEthnicity(): ?int
{
return $this->ethnicity;
}
/**
* @param int|null $ethnicity
*/
public function setEthnicity(?int $ethnicity): static
{
$this->ethnicity = $ethnicity;
return $this;
}
/**
* @return int|null
*/
public function getCategoryGender(): ?int
{
return $this->categoryGender;
}
/**
* @param int|null $categoryGender
*/
public function setCategoryGender(?int $categoryGender): static
{
$this->categoryGender = $categoryGender;
return $this;
}
/**
* @return int|null
*/
public function getAgeGroup(): ?int
{
return $this->ageGroup;
}
/**
* @param int|null $ageGroup
*/
public function setAgeGroup(?int $ageGroup): static
{
$this->ageGroup = $ageGroup;
return $this;
}
/**
* @return int|null
*/
public function getCategoryParent(): ?int
{
return $this->categoryParent;
}
/**
* @param int|null $categoryParent
*/
public function setCategoryParent(?int $categoryParent): static
{
$this->categoryParent = $categoryParent;
return $this;
}
/**
* @return int|null
*/
public function getAttractivenessLevel(): ?int
{
return $this->attractivenessLevel;
}
/**
* @param int|null $attractivenessLevel
*/
public function setAttractivenessLevel(?int $attractivenessLevel): static
{
$this->attractivenessLevel = $attractivenessLevel;
return $this;
}
public function getMinFlatFee(): int
{
return $this->minFlatFee;
}
public function setMinFlatFee(int $minFlatFee)
{
$this->minFlatFee = $minFlatFee;
return $this;
}
public function getIsShowLessThanFlatFee(): bool
{
return $this->isShowLessThanFlatFee;
}
public function setIsShowLessThanFlatFee(bool $isShowLessThanFlatFee)
{
$this->isShowLessThanFlatFee = $isShowLessThanFlatFee;
return $this;
}
public function getAnalytics(): ?AnalyticsCreatorsData
{
return $this->analytics;
}
public function setAnalytics(?AnalyticsCreatorsData $analytics)
{
$this->analytics = $analytics;
return $this;
}
public function getStripeId(): ?string
{
return $this->stripeId;
}
public function setStripeId(?string $stripeId)
{
$this->stripeId = $stripeId;
return $this;
}
public function getStripeConnected(): bool
{
return $this->stripeConnected;
}
public function setStripeConnected(bool $stripeConnected)
{
$this->stripeConnected = $stripeConnected;
return $this;
}
public function isStripeConnected(): bool
{
return $this->stripeConnected;
}
public function setPassword(?string $password): static
{
$this->password = $password;
return $this;
}
public function getPassword(): string
{
return $this->password ?? '';
}
public function getOwningUser(): ?User
{
return $this->owningUser;
}
public function setOwningUser(?User $owningUser): static
{
$this->owningUser = $owningUser;
return $this;
}
/**
* Owning account user id for JWT `user_id` claim / grouping; falls back to this profile's id.
*/
public function getOwningUserId(): int
{
if ($this->owningUser instanceof User) {
$oid = $this->owningUser->getId();
if ($oid !== null) {
return $oid;
}
}
$id = $this->getId();
if ($id === null) {
throw new LogicException('Creator id must be known to resolve owning user id.');
}
return $id;
}
}