*/ private const SEVERITY = [ self::ALLOW => 0, self::NEED_LOGIN => 1, self::NEED_PURCHASE => 2, self::NEED_PASSWORD => 3, ]; public function __construct( public string $status, public ?string $teaserHtml = null, public ?string $checkoutUrl = null, public ?string $message = null, ) {} public static function allow(): self { return new self(self::ALLOW); } public static function needPassword(?string $message = null): self { return new self(self::NEED_PASSWORD, message: $message); } public static function needPurchase(?string $teaserHtml = null, ?string $checkoutUrl = null, ?string $message = null): self { return new self(self::NEED_PURCHASE, $teaserHtml, $checkoutUrl, $message); } public function isAllow(): bool { return $this->status === self::ALLOW; } public function severity(): int { return self::SEVERITY[$this->status] ?? 0; } /** * Only allow tightening (higher severity). Metadata from the stricter side wins when status changes; * otherwise fill empty meta from $other. */ public function tightenWith(self $other): self { if ($other->severity() < $this->severity()) { return new self( $this->status, $this->teaserHtml ?? $other->teaserHtml, $this->checkoutUrl ?? $other->checkoutUrl, $this->message ?? $other->message, ); } if ($other->severity() > $this->severity()) { return new self( $other->status, $other->teaserHtml ?? $this->teaserHtml, $other->checkoutUrl ?? $this->checkoutUrl, $other->message ?? $this->message, ); } return new self( $this->status, $other->teaserHtml ?? $this->teaserHtml, $other->checkoutUrl ?? $this->checkoutUrl, $other->message ?? $this->message, ); } /** * @return array{status: string, teaser_html: ?string, checkout_url: ?string, message: ?string} */ public function toArray(): array { return [ 'status' => $this->status, 'teaser_html' => $this->teaserHtml, 'checkout_url' => $this->checkoutUrl, 'message' => $this->message, ]; } }