'datetime', 'provisioned_at' => 'datetime', 'meta' => 'array', ]; public function user(): BelongsTo { return $this->belongsTo(User::class); } public function domain(): BelongsTo { return $this->belongsTo(Domain::class); } public function isActive(): bool { return $this->status === self::STATUS_ACTIVE; } public function isExpired(): bool { return $this->status === self::STATUS_EXPIRED || ($this->expires_at && $this->expires_at->isPast()); } public function getDomainNameAttribute($value): string { return $value ?: $this->metaValue([ 'domain_name', 'domainname', 'domain-name', 'domain', 'hostname', 'description', ], ''); } public function getPlanNameAttribute($value): ?string { $resolved = $value ?: $this->metaValue([ 'plan_name', 'planname', 'productcategory', 'productkey', 'description', ]); return $resolved !== '' ? $resolved : null; } public function getPlanIdAttribute(): ?string { $resolved = $this->metaValue([ 'plan_id', 'planid', 'plan-id', 'productkey', 'plan.name', 'entitytype.entitytypekey', ]); return $resolved !== null && $resolved !== '' ? (string) $resolved : null; } public function getRcOrderIdAttribute($value): ?string { $resolved = $value ?: $this->metaValue([ 'rc_order_id', 'order_id', 'orderid', 'order-id', 'entityid', 'entity-id', ]); return $resolved !== '' ? (string) $resolved : null; } public function getRcCustomerIdAttribute($value): ?string { $resolved = $value ?: $this->metaValue([ 'rc_customer_id', 'customer_id', 'customerid', 'customer-id', ]); return $resolved !== '' ? (string) $resolved : null; } public function getIpAddressAttribute($value): ?string { $resolved = $value ?: $this->metaValue([ 'ip_address', 'ipaddress', 'ip', ]); return $resolved !== '' ? $resolved : null; } public function getCpanelUrlAttribute($value): ?string { $resolved = $value ?: $this->metaValue([ 'cpanel_url', 'cpanelurl', 'controlpanelurl', 'access_url', 'url', ]); if ($this->looksLikeTemporaryHostingUrl($resolved)) { $resolved = null; } if (! $resolved && $preferredDomain = $this->preferredCpanelDomain()) { return 'https://'.$preferredDomain.'/cpanel'; } if (! $resolved && $this->ip_address) { return 'https://'.$this->ip_address.':2083'; } return $resolved !== '' ? $resolved : null; } public function getCpanelUsernameAttribute($value): ?string { $resolved = $value ?: $this->metaValue([ 'cpanel_username', 'cpanelusername', 'access_username', 'username', 'siteadminusername', ]); return $resolved !== '' ? $resolved : null; } /** * @return array */ public function getNameserversAttribute($value): array { $resolved = []; if (is_array($value)) { $resolved = $value; } else { $candidate = $this->metaValue([ 'nameservers', 'nameserver', 'name_servers', 'ns', 'dns.nameservers', 'server.nameservers', ]); if (is_array($candidate)) { $resolved = $candidate; } else { $resolved = array_filter([ $this->metaValue(['ns1', 'nameserver1', 'name_server_1', 'server.ns1']), $this->metaValue(['ns2', 'nameserver2', 'name_server_2', 'server.ns2']), $this->metaValue(['ns3', 'nameserver3', 'name_server_3', 'server.ns3']), $this->metaValue(['ns4', 'nameserver4', 'name_server_4', 'server.ns4']), ]); } } return collect($resolved) ->map(fn ($item) => strtolower(trim((string) $item, " \t\n\r\0\x0B."))) ->filter() ->unique() ->values() ->all(); } public function getWebsiteUrlAttribute(): ?string { $domain = strtolower(trim((string) $this->domain_name)); if ($domain === '' || filter_var($domain, FILTER_VALIDATE_IP)) { return null; } return 'https://'.$domain; } public function getDirectUrlAttribute(): ?string { $resolved = $this->metaValue([ 'tempurl', 'temp_url', 'temporary_url', 'server.tempurl', 'server.temporary_url', ]); return $resolved !== '' ? (string) $resolved : null; } public function getDiskSpaceMbAttribute($value): ?int { $resolved = $value ?? $this->metaValue([ 'disk_space_mb', 'diskspace', 'disk_space', ]); return is_numeric($resolved) && (int) $resolved >= 0 ? (int) $resolved : null; } public function getBandwidthMbAttribute($value): ?int { $resolved = $value ?? $this->metaValue([ 'bandwidth_mb', 'bandwidth', ]); return is_numeric($resolved) && (int) $resolved >= 0 ? (int) $resolved : null; } public function getStatusAttribute($value): string { $candidate = $value; if ($candidate === null || $candidate === '' || $candidate === self::STATUS_PENDING) { $candidate = $this->metaValue([ 'status', 'currentstatus', 'orderstatus', ], $candidate ?: self::STATUS_PENDING); } return $this->normalizeStatus((string) $candidate); } public function getProvisionedAtAttribute($value): ?Carbon { if ($value instanceof Carbon) { return $value; } if ($value) { return Carbon::parse($value); } $timestamp = $this->metaValue([ 'provisioned_at', 'creation_time', 'creationtime', 'creation-date', ]); if ($timestamp === null || $timestamp === '') { return null; } try { return is_numeric($timestamp) ? Carbon::createFromTimestamp((int) $timestamp) : Carbon::parse((string) $timestamp); } catch (\Throwable) { return null; } } public function getExpiresAtAttribute($value): ?Carbon { if ($value instanceof Carbon) { return $value; } if ($value) { return Carbon::parse($value); } $timestamp = $this->metaValue([ 'expires_at', 'end_time', 'endtime', 'expirytime', 'expiry-date', ]); if ($timestamp === null || $timestamp === '') { return null; } try { return is_numeric($timestamp) ? Carbon::createFromTimestamp((int) $timestamp) : Carbon::parse((string) $timestamp); } catch (\Throwable) { return null; } } private function metaValue(array $keys, mixed $default = null): mixed { $meta = $this->meta ?? []; $sources = []; if (is_array($meta)) { $sources[] = $meta; if (is_array($meta['raw'] ?? null)) { $sources[] = $meta['raw']; } } foreach ($sources as $source) { foreach ($keys as $key) { $nested = Arr::get($source, $key); if ($nested !== null && $nested !== '') { return $nested; } if (array_key_exists($key, $source) && $source[$key] !== null && $source[$key] !== '') { return $source[$key]; } } } return $default; } private function normalizeStatus(string $status): string { return match (strtolower(trim($status))) { 'active', 'active (paid)' => self::STATUS_ACTIVE, 'suspended', 'inactive' => self::STATUS_SUSPENDED, 'deleted', 'cancelled' => self::STATUS_CANCELLED, 'expired' => self::STATUS_EXPIRED, 'failed' => self::STATUS_FAILED, default => self::STATUS_PENDING, }; } private function looksLikeTemporaryHostingUrl(?string $value): bool { $normalized = strtolower(trim((string) $value)); if ($normalized === '') { return false; } return str_contains($normalized, 'tempwebhost.net') || str_contains($normalized, '/~'); } private function preferredCpanelDomain(): ?string { $domain = strtolower(trim((string) $this->domain_name)); if ($domain === '' || filter_var($domain, FILTER_VALIDATE_IP)) { return null; } if ($this->relationLoaded('domain') && $this->domain) { return $this->domainIsActive($this->domain) ? $domain : null; } if ($this->domain_id) { $linkedDomain = $this->domain()->first(); if ($linkedDomain) { return $this->domainIsActive($linkedDomain) ? $domain : null; } } $matchingDomain = Domain::query() ->where('host', $domain) ->latest('id') ->first(); if ($matchingDomain) { return $this->domainIsActive($matchingDomain) ? $domain : null; } return $domain; } private function domainIsActive(Domain $domain): bool { return (string) $domain->status === 'verified' && (string) $domain->onboarding_state === Domain::STATE_ACTIVE; } }