__('Zone pending'), 'active' => __('Zone active'), 'failed' => __('Zone failed'), ]; } public function getNsStatusList(): array { return [ 'pending' => __('NS pending'), 'verified' => __('NS verified'), 'failed' => __('NS failed'), ]; } public function getDnsStatusList(): array { return [ 'pending' => __('DNS pending'), 'created' => __('DNS created'), 'failed' => __('DNS failed'), ]; } public function getZoneStatusTextAttr($value, $data): string { $value = $value ?: ($data['zone_status'] ?? ''); $list = $this->getZoneStatusList(); return $list[$value] ?? ''; } public function getNsStatusTextAttr($value, $data): string { $value = $value ?: ($data['ns_status'] ?? ''); $list = $this->getNsStatusList(); return $list[$value] ?? ''; } public function getDnsStatusTextAttr($value, $data): string { $value = $value ?: ($data['dns_status'] ?? ''); $list = $this->getDnsStatusList(); return $list[$value] ?? ''; } public function setNameserversAttr($value): string { if (is_array($value)) { return json_encode(array_values($value), JSON_UNESCAPED_UNICODE); } return (string)$value; } /** * @return array */ public function getNameserversArray(): array { $value = $this->getAttr('nameservers'); if (is_array($value)) { return $value; } if (is_string($value) && $value !== '') { $decoded = json_decode($value, true); return is_array($decoded) ? $decoded : []; } return []; } public static function normalizeDomain(string $domain): string { return strtolower(trim($domain)); } public static function isValidRootDomain(string $domain): bool { $domain = self::normalizeDomain($domain); if ($domain === '' || strlen($domain) > 253) { return false; } if (strpos($domain, 'www.') === 0) { return false; } if (!preg_match('/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i', $domain)) { return false; } if (self::isChinaSuffix($domain)) { return false; } $label = self::getDomainLabelWithoutSuffix($domain); if ($label === '' || strpos($label, '.') !== false) { return false; } return true; } public static function isChinaSuffix(string $domain): bool { $domain = self::normalizeDomain($domain); foreach (self::CHINA_SUFFIX_BLACKLIST as $suffix) { if ($domain === $suffix || self::endsWith($domain, '.' . $suffix)) { return true; } } return false; } public static function getMatchedSuffix(string $domain): string { $domain = self::normalizeDomain($domain); $suffixes = array_merge(self::CHINA_SUFFIX_BLACKLIST, ['co.uk', 'com', 'net', 'org', 'io', 'co', 'me', 'info', 'biz']); usort($suffixes, function ($a, $b) { return strlen($b) - strlen($a); }); foreach ($suffixes as $suffix) { if ($domain === $suffix || self::endsWith($domain, '.' . $suffix)) { return $suffix; } } return ''; } public static function getDomainLabelWithoutSuffix(string $domain): string { $domain = self::normalizeDomain($domain); $suffix = self::getMatchedSuffix($domain); if ($suffix === '') { $pos = strrpos($domain, '.'); return $pos === false ? $domain : substr($domain, 0, $pos); } $suffixWithDot = '.' . $suffix; if (self::endsWith($domain, $suffixWithDot)) { return substr($domain, 0, -strlen($suffixWithDot)); } return $domain; } public static function mapCloudflareZoneStatus(string $status): string { if ($status === 'active') { return 'active'; } if (in_array($status, ['pending', 'initializing'], true)) { return 'pending'; } return 'failed'; } private static function endsWith(string $haystack, string $needle): bool { if ($needle === '') { return true; } return substr($haystack, -strlen($needle)) === $needle; } }