Add DNS monitoring and refresh functionality
Introduce DNS monitoring: add DnsService (comprehensive DNS lookup, crt.sh discovery, Cloudflare detection, IP enrichment) and a new DnsRecord model to persist snapshots, manage diffs, and provide queries/stats. Update DomainController to support a dns_monitoring_enabled flag, refactor WHOIS/DNS refresh logic into performWhoisRefresh/performDnsRefresh, and add endpoints for refreshWhois, refreshDns and refreshAll; send notifications when DNS monitoring is toggled. Add UI templates/tabs for DNS, billing, notifications, overview, SSL and WHOIS and wire DNS data into the domain view; expose cached IP details. Add cron/check_dns.php and migration 027_add_dns_monitoring.sql (and include it in installer migration lists). Other tweaks: safer EmailHelper subject handling, TldRegistry search improvements, domain sorting using an effective status (expiring_soon), Discord channel null-safe fields, settings UI additions (domain_view_template and cron staleness warnings), and route/migration updates. This enables scheduled and manual DNS scans with persistent records and notifications.
This commit is contained in:
@@ -259,6 +259,24 @@ class Domain extends Model
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get effective status for sorting (active + daysLeft within threshold = expiring_soon)
|
||||
*/
|
||||
private static function getEffectiveStatusForSort(array $domain, int $expiringThreshold): string
|
||||
{
|
||||
$status = $domain['status'] ?? '';
|
||||
if ($status === 'inactive') {
|
||||
return 'inactive';
|
||||
}
|
||||
if ($status === 'active' && !empty($domain['expiration_date'])) {
|
||||
$daysLeft = (int) floor((strtotime($domain['expiration_date']) - time()) / 86400);
|
||||
if ($daysLeft <= $expiringThreshold && $daysLeft >= 0) {
|
||||
return 'expiring_soon';
|
||||
}
|
||||
}
|
||||
return $status ?: 'error';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered, sorted, and paginated domains
|
||||
*/
|
||||
@@ -332,10 +350,33 @@ class Domain extends Model
|
||||
$totalDomains = count($domains);
|
||||
|
||||
// Apply sorting
|
||||
usort($domains, function($a, $b) use ($sortBy, $sortOrder) {
|
||||
usort($domains, function($a, $b) use ($sortBy, $sortOrder, $expiringThreshold) {
|
||||
$aVal = $a[$sortBy] ?? '';
|
||||
$bVal = $b[$sortBy] ?? '';
|
||||
|
||||
|
||||
// When sorting by status: use effective status (active + daysLeft<=threshold = expiring_soon) and logical priority order
|
||||
if ($sortBy === 'status') {
|
||||
$aVal = self::getEffectiveStatusForSort($a, $expiringThreshold);
|
||||
$bVal = self::getEffectiveStatusForSort($b, $expiringThreshold);
|
||||
$priority = [
|
||||
'expired' => 1,
|
||||
'redemption_period' => 2,
|
||||
'pending_delete' => 3,
|
||||
'expiring_soon' => 4,
|
||||
'active' => 5,
|
||||
'available' => 6,
|
||||
'error' => 7,
|
||||
'inactive' => 8,
|
||||
];
|
||||
$aOrder = $priority[$aVal] ?? 99;
|
||||
$bOrder = $priority[$bVal] ?? 99;
|
||||
$comparison = $aOrder <=> $bOrder;
|
||||
if ($comparison === 0) {
|
||||
$comparison = strcasecmp($a['domain_name'] ?? '', $b['domain_name'] ?? '');
|
||||
}
|
||||
return $sortOrder === 'desc' ? -$comparison : $comparison;
|
||||
}
|
||||
|
||||
$comparison = strcasecmp($aVal, $bVal);
|
||||
return $sortOrder === 'desc' ? -$comparison : $comparison;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user