Nothing to see here

Go Back"; } else { $client_id = intval($service['service_client_id']); enforceClientAccess(); $client_url = "client_id=$client_id&"; $service_name = escapeHtml($service['service_name']); $service_archived = !empty($service['service_archived_at']); $is_favorite = intval($service['service_favorite']) === 1; $can_edit = serviceCan(2) && !$service_archived; $can_restore = serviceCan(2); $can_delete = serviceCan(3) && !empty($config_destructive_deletes_enable); $can_credentials = lookupUserPermission('module_credential') >= 1; $can_link_credentials = $can_edit && linkCanEdit('service', 'credential'); $service_tags_display = tagPills('service', $service_id, tagsForRecord('service', $service_id), "services.php?client_id=$client_id&", $can_edit); // Override Tab Title // No Sanitizing needed as this var will only be used in the tab title $page_title = $service['service_name']; $counts = serviceCounts([$service_id])[$service_id]; $issues = serviceIssues([$service_id])[$service_id]; $review = serviceReview($service); $urls = serviceUrls($service_id, $can_credentials); // What it runs on - each with its address, network, site and warranty $assets = []; $sql = mysqli_query($mysqli, "SELECT assets.asset_id, asset_name, asset_type, asset_make, asset_model, asset_status, asset_warranty_expire, asset_archived_at, asset_contact_id, asset_location_id, interface_ip, interface_network_id, network_name, network_type, network_vlan, location_name, contact_name, contact_photo FROM service_assets JOIN assets ON assets.asset_id = service_assets.asset_id LEFT JOIN asset_interfaces ON interface_asset_id = assets.asset_id AND interface_primary = 1 LEFT JOIN networks ON network_id = interface_network_id AND interface_network_id > 0 LEFT JOIN locations ON location_id = asset_location_id LEFT JOIN contacts ON contact_id = asset_contact_id WHERE service_assets.service_id = $service_id ORDER BY asset_archived_at IS NOT NULL, asset_name ASC"); while ($row = mysqli_fetch_assoc($sql)) { $assets[] = $row; } // The networks it is on, each once - linked to their pages $networks = []; foreach ($assets as $asset_row) { if (!$asset_row['asset_archived_at'] && $asset_row['network_name']) { $networks[intval($asset_row['interface_network_id'])] = networkLink($asset_row['interface_network_id'], $asset_row['network_name'], $client_id, ['type' => networkType($asset_row)]); } } $sites = array_unique(array_filter(array_column(array_filter($assets, function ($a) { return !$a['asset_archived_at']; }), 'location_name'))); // Its logins, and the ones on the assets it runs on $credentials = $can_credentials ? credentialRows("credential_id IN (SELECT credential_id FROM service_credentials WHERE service_id = $service_id)") : []; $asset_credentials = $can_credentials ? credentialRows("credential_client_id = $client_id AND credential_asset_id IN (SELECT asset_id FROM service_assets WHERE service_id = $service_id) AND credential_id NOT IN (SELECT credential_id FROM service_credentials WHERE service_id = $service_id)") : []; $domains = serviceLinked($service_id, 'domain'); $certificates = serviceLinked($service_id, 'certificate'); $documents = serviceLinked($service_id, 'document'); $contacts = serviceLinked($service_id, 'contact'); $vendors = serviceLinked($service_id, 'vendor'); $archived_credentials = $can_credentials ? array_values(array_filter(serviceLinked($service_id, 'credential'), function ($row) { return $row['archived_at']; })) : []; // Who to call - the vendors' and people's details for the call $vendor_details = []; if ($vendors) { $sql = mysqli_query($mysqli, "SELECT vendor_id, vendor_account_number, vendor_code, vendor_email, vendor_website, vendor_hours, vendor_sla FROM vendors WHERE vendor_id IN (" . implode(',', array_map('intval', array_column($vendors, 'id'))) . ")"); while ($row = mysqli_fetch_assoc($sql)) { $vendor_details[intval($row['vendor_id'])] = $row; } } $contact_details = []; if ($contacts) { $sql = mysqli_query($mysqli, "SELECT contact_id, contact_email, contact_phone, contact_phone_country_code, contact_extension, contact_mobile, contact_mobile_country_code FROM contacts WHERE contact_id IN (" . implode(',', array_map('intval', array_column($contacts, 'id'))) . ")"); while ($row = mysqli_fetch_assoc($sql)) { $contact_details[intval($row['contact_id'])] = $row; } } $tickets = ticketRows(serviceTicketsSql($service_id), 100); $linked_ticket_ids = []; $sql = mysqli_query($mysqli, "SELECT ticket_id FROM service_tickets WHERE service_id = $service_id"); while ($row = mysqli_fetch_row($sql)) { $linked_ticket_ids[intval($row[0])] = true; } $open_tickets = count(array_filter($tickets, 'ticketIsOpen')); $history = auditLogHistory('Service', $service_id); $service_tabs = [ 'assets' => ['label' => 'Runs on', 'icon' => 'fa-desktop', 'count' => count($assets)], 'logins' => ['label' => 'Logins', 'icon' => 'fa-key', 'count' => count($credentials) + count($asset_credentials) + count($archived_credentials)], 'web' => ['label' => 'Domains & SSL', 'icon' => 'fa-globe', 'count' => count($domains) + count($certificates)], 'documents' => ['label' => 'Documents', 'icon' => 'fa-file-alt', 'count' => count($documents)], 'tickets' => ['label' => 'Tickets', 'icon' => 'fa-life-ring', 'count' => count($tickets), 'alarm' => $open_tickets], 'history' => ['label' => 'History', 'icon' => 'fa-history', 'count' => $history['count']], ]; if (!$can_credentials) { unset($service_tabs['logins']); } $link_url = "modals/link/link.php?from=service&id=$service_id&to="; $unlink_url = function ($to, $other_id) use ($service_id) { return "post.php?unlink_item&from=service&id=$service_id&to=$to&other=" . intval($other_id) . "&csrf_token=" . $_SESSION['csrf_token']; }; $report_url = 'modals/ticket/ticket_add.php?' . http_build_query(['client_id' => $client_id, 'service_id' => $service_id]); $has_danger = in_array('danger', array_column($issues, 'tone'), true); /** An archived record still linked - struck through, with a way to unlink it. */ $archived_row = function ($to, $row) use ($can_edit, $unlink_url) { $entity = LINK_ENTITIES[$to]; return ''; }; ?>

Archived

thing it depends on need attention

Service

Importance
Review
Not scheduled
Opens at
Where
Added
Updated

Backup and recovery

How it is backed up and how it comes back is not written down. Add it

Who to call

    '; continue; } $vendor_id = intval($vendor['id']); $details = $vendor_details[$vendor_id] ?? []; $phone = contactPhoneLink($vendor['vendor_phone'], $vendor['vendor_phone_country_code'], $vendor['vendor_extension']); $account = escapeHtml($details['vendor_account_number'] ?? ''); $pin = vendorSecretHtml($details['vendor_code'] ?? ''); $when = escapeHtml(implode(' · ', array_filter([$details['vendor_hours'] ?? '', $details['vendor_sla'] ?? '']))); ?>
  • true, 'client_id' => $client_id, 'class' => 'fw-semibold']) ?> Vendor
    PIN
  • '; continue; } $contact_id = intval($contact['id']); $details = $contact_details[$contact_id] ?? []; $phone = contactPhoneLink($details['contact_phone'] ?? '', $details['contact_phone_country_code'] ?? '', $details['contact_extension'] ?? ''); $mobile = contactPhoneLink($details['contact_mobile'] ?? '', $details['contact_mobile_country_code'] ?? ''); ?>
  • 'fw-semibold']) ?>
No vendor or person linked - who gets the call when it breaks?

Notes