diff --git a/htdocs/web_portal/controllers/downtime/add_downtime.php b/htdocs/web_portal/controllers/downtime/add_downtime.php index becb0c73f..1238f731d 100644 --- a/htdocs/web_portal/controllers/downtime/add_downtime.php +++ b/htdocs/web_portal/controllers/downtime/add_downtime.php @@ -24,6 +24,7 @@ require_once __DIR__.'/../../../../lib/Gocdb_Services/Factory.php'; require_once __DIR__.'/../utils.php'; require_once __DIR__.'/../../../web_portal/components/Get_User_Principle.php'; +require_once __DIR__ . '/downtime_utils.php'; /** * Controller for a new_downtime request. @@ -71,53 +72,52 @@ function submit(\User $user = null) { if($confirmed == true){ //Downtime is confirmed, submit it //$downtimeInfo = unserialize($_REQUEST['newValues']); // didn't cater for UTF-8 chars + /** + * If confirmed by an user, submit the details of affected services + * and endpoints along with other details for each individual site. + */ $downtimeInfo = json_decode($_POST['newValues'], TRUE); $serv = \Factory::getDowntimeService(); + $downtimeInfo = unsetVariables($downtimeInfo, 'add'); + $params = []; + + foreach ($downtimeInfo['SITE_LEVEL_DETAILS'] as $siteID) { + $downtimeInfo['Impacted_Services'] = $siteID['services']; + $downtimeInfo['Impacted_Endpoints'] = $siteID['endpoints']; + + $params['submittedDowntimes'][$siteID['siteName']] = + $serv->addDowntime($downtimeInfo, $user); + } - $params['dt'] = $serv->addDowntime($downtimeInfo, $user); show_view("downtime/added_downtime.php", $params); }else{ //Show user confirmation screen with their input $downtimeInfo = getDtDataFromWeb(); - //Need to sort the impacted_ids into impacted services and impacted endpoints - $impactedids = $downtimeInfo['IMPACTED_IDS']; + list( + $siteLevelDetails, + $serviceWithEndpoints + ) = endpointToServiceMapping($downtimeInfo['IMPACTED_IDS']); - $services=array(); - $endpoints=array(); + // Delete the unsorted IDs from the downtime info + unset($downtimeInfo['IMPACTED_IDS']); - //For each impacted id sort between endpoints and services using the prepended letter - foreach($impactedids as $id){ - if (strpos($id, 's') !== FALSE){ - //This is a service id - $services[] = str_replace('s', '', $id); //trim off the identifying char before storing in array - }else{ - //This is an endpoint id - $endpoints[] = str_replace('e', '', $id); //trim off the identifying char before storing in array - } + if (!count($siteLevelDetails) > 1) { + $downtimeInfo['SINGLE_TIMEZONE'] = true; } - unset($downtimeInfo['IMPACTED_IDS']); //Delete the unsorted Ids from the downtime info - - $downtimeInfo['Impacted_Endpoints'] = $endpoints; - - - $serv = \Factory::getServiceService(); - - /** For endpoint put into downtime we want the parent service also. If a user has selected - * endpoints but not the parent service here we will add the service to maintain the link beteween - * a downtime having both the service and the endpoint. - */ - foreach($downtimeInfo['Impacted_Endpoints'] as $endpointIds){ - $endpoint = $serv->getEndpoint($endpointIds); - $services[] = $endpoint->getService()->getId(); - } - - //Remove any duplicate service ids and store the array of ids - $services = array_unique($services); - - //Assign the impacted services and endpoints to their own arrays for us by the addDowntime method - $downtimeInfo['Impacted_Services'] = $services; + list( + $siteLevelDetails, + $serviceWithEndpoints + ) = addParentServiceForEndpoints( + $serviceWithEndpoints, + $siteLevelDetails, + false, + $downtimeInfo['DOWNTIME'] + ); + + $downtimeInfo['SITE_LEVEL_DETAILS'] = $siteLevelDetails; + $downtimeInfo['SERVICE_WITH_ENDPOINTS'] = $serviceWithEndpoints; show_view("downtime/confirm_add_downtime.php", $downtimeInfo); } diff --git a/htdocs/web_portal/controllers/downtime/downtime_utils.php b/htdocs/web_portal/controllers/downtime/downtime_utils.php new file mode 100644 index 000000000..f0905c4f6 --- /dev/null +++ b/htdocs/web_portal/controllers/downtime/downtime_utils.php @@ -0,0 +1,169 @@ + $siteData) { + $siteDetails[$siteID]['services'] = []; + + $newSite = \Factory::getSiteService()->getSite($siteID); + $siteDetails[$siteID]['siteName'] = $newSite->getShortName(); + + if ($hasMultipleTimezones) { + list( + $siteDetails[$siteID]['START_TIMESTAMP'], + $siteDetails[$siteID]['END_TIMESTAMP'] + ) = setLocalTimeForSites($downtimeDetails, $siteID); + } + + foreach (array_keys($siteData) as $serviceID) { + $servWithEndpoints[$siteID][$serviceID]['services'] = []; + $servWithEndpoints[$siteID][$serviceID]['services'][] = $serviceID; + // Ensuring that service IDs are unique for the selected sites. + $siteDetails[$siteID]['services'][] = $serviceID; + } + } + + return [$siteDetails, $servWithEndpoints]; +} + +/** + * Converts UTC start and end timestamps to the local timezone + * of a specific site based on that site's timezone. + * + * @param mixed $downtimeDetails Downtime information. + * @param integer $siteID Site ID + */ +function setLocalTimeForSites($downtimeDetails, $siteID) +{ + $site = \Factory::getSiteService()->getSite($siteID); + + $siteTimezone = $site->getTimeZoneId(); + + $startTimeAsString = $downtimeDetails['START_TIMESTAMP']; + $utcEndTime = $downtimeDetails['END_TIMESTAMP']; + + $utcStartDateTime = DateTime::createFromFormat( + 'd/m/Y H:i', + $startTimeAsString, + new DateTimeZone('UTC') + ); + $utcEndDateTime = DateTime::createFromFormat( + 'd/m/Y H:i', + $utcEndTime, + new DateTimeZone('UTC') + ); + + $targetSiteTimezone = new DateTimeZone($siteTimezone); + $utcOffset = $targetSiteTimezone->getOffset($utcStartDateTime); + + // Calculate the equivalent time in the target timezone. + // Ref: https://www.php.net/manual/en/datetime.modify.php + $siteStartDateTime = $utcStartDateTime->modify("-$utcOffset seconds"); + $siteEndDateTime = $utcEndDateTime->modify("-$utcOffset seconds"); + + return [ + $siteStartDateTime->format('d/m/Y H:i'), + $siteEndDateTime->format('d/m/Y H:i') + ]; +} + +/** + * Unset a given variable, helper method to destroy the specified variables. + * + * @param mixed $downtimeObj Object to destroy specified variables. + * @param string $fromLocation Location from where the + * function is being called. + */ +function unsetVariables($downtimeObj, $fromLocation) +{ + if ($fromLocation == "add") { + unset($downtimeObj['SERVICE_WITH_ENDPOINTS']); + unset($downtimeObj['SINGLE_TIMEZONE']); + } else { + unset($downtimeObj['DOWNTIME']['EXISTINGID']); + unset($downtimeObj['isEdit']); + unset($downtimeObj['SERVICE_WITH_ENDPOINTS']); + unset($downtimeObj['SINGLE_TIMEZONE']); + } + + return $downtimeObj; +} diff --git a/htdocs/web_portal/controllers/downtime/edit_downtime.php b/htdocs/web_portal/controllers/downtime/edit_downtime.php index 9bf244428..3f74cb16f 100644 --- a/htdocs/web_portal/controllers/downtime/edit_downtime.php +++ b/htdocs/web_portal/controllers/downtime/edit_downtime.php @@ -21,6 +21,7 @@ require_once __DIR__ . '/../../../../lib/Gocdb_Services/Factory.php'; require_once __DIR__ . '/../../../../htdocs/web_portal/components/Get_User_Principle.php'; require_once __DIR__ . '/../utils.php'; +require_once __DIR__ . '/downtime_utils.php'; /** * Controller for an edit downtime request @@ -88,11 +89,18 @@ function submit(\User $user = null) { if($confirmed == true){ //Downtime is confirmed, submit it $downtimeInfo = json_decode($_POST['newValues'], TRUE); - + $params = []; $serv = \Factory::getDowntimeService(); $dt = $serv->getDowntime($downtimeInfo['DOWNTIME']['EXISTINGID']); - unset($downtimeInfo['DOWNTIME']['EXISTINGID']); - unset($downtimeInfo['isEdit']); + $downtimeInfo = unsetVariables($downtimeInfo, 'edit'); + + foreach ($downtimeInfo['SITE_LEVEL_DETAILS'] as $siteIDs) { + $downtimeInfo['Impacted_Services'] = $siteIDs['services']; + $downtimeInfo['Impacted_Endpoints'] = $siteIDs['endpoints']; + } + + unset($downtimeInfo['SITE_LEVEL_DETAILS']); + $params['dt'] = $serv->editDowntime($dt, $downtimeInfo, $user); show_view("downtime/edited_downtime.php", $params); @@ -101,43 +109,30 @@ function submit(\User $user = null) { $downtimeInfo = getDtDataFromWeb(); //Need to sort the impacted_ids into impacted services and impacted endpoints - $impactedids = $downtimeInfo['IMPACTED_IDS']; - - $services=array(); - $endpoints=array(); - - //For each impacted id sort between endpoints and services using the prepended letter - foreach($impactedids as $id){ - if (strpos($id, 's') !== FALSE){ - //This is a service id - $services[] = str_replace('s', '', $id); //trim off the identifying char before storing in array - }else{ - //This is an endpoint id - $endpoints[] = str_replace('e', '', $id); //trim off the identifying char before storing in array - } - } - - unset($downtimeInfo['IMPACTED_IDS']); //Delete the unsorted Ids from the downtime info - - $downtimeInfo['Impacted_Endpoints'] = $endpoints; + list( + $siteLevelDetails, + $serviceWithEndpoints + ) = endpointToServiceMapping($downtimeInfo['IMPACTED_IDS']); + // Delete the unsorted IDs from the downtime info + unset($downtimeInfo['IMPACTED_IDS']); - $serv = \Factory::getServiceService(); - - /** For endpoint put into downtime we want the parent service also. If a user has selected - * endpoints but not the parent service here we will add the service to maintain the link beteween - * a downtime having both the service and the endpoint. - */ - foreach($downtimeInfo['Impacted_Endpoints'] as $endpointIds){ - $endpoint = $serv->getEndpoint($endpointIds); - $services[] = $endpoint->getService()->getId(); + if (!count($siteLevelDetails) > 1) { + $downtimeInfo['SINGLE_TIMEZONE'] = true; } - //Remove any duplicate service ids and store the array of ids - $services = array_unique($services); - - //Assign the impacted services and endpoints to their own arrays for us by the addDowntime method - $downtimeInfo['Impacted_Services'] = $services; + list( + $siteLevelDetails, + $serviceWithEndpoints + ) = addParentServiceForEndpoints( + $serviceWithEndpoints, + $siteLevelDetails, + false, + $downtimeInfo['DOWNTIME'] + ); + + $downtimeInfo['SITE_LEVEL_DETAILS'] = $siteLevelDetails; + $downtimeInfo['SERVICE_WITH_ENDPOINTS'] = $serviceWithEndpoints; //Pass the edit variable so the confirm_add view works as the confirm edit view. $downtimeInfo['isEdit'] = true; show_view("downtime/confirm_add_downtime.php", $downtimeInfo); diff --git a/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php b/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php index eb9f81946..c8451d787 100644 --- a/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php +++ b/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php @@ -19,19 +19,30 @@ * limitations under the License. * /*====================================================== */ +use Doctrine\Common\Collections\ArrayCollection; +use Exception; + function getServiceandEndpointList() { require_once __DIR__ . '/../utils.php'; require_once __DIR__ . '/../../../web_portal/components/Get_User_Principle.php'; + $params = []; $dn = Get_User_Principle(); $user = \Factory::getUserService()->getUserByPrinciple($dn); $params['portalIsReadOnly'] = portalIsReadOnlyAndUserIsNotAdmin($user); + $siteIDs = $_REQUEST['site_id']; - if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id']) ){ - throw new Exception("An id must be specified"); + if (empty($siteIDs)) { + throw new Exception("Please select at least one site."); } - $site = \Factory::getSiteService()->getSite($_REQUEST['site_id']); - $services = $site->getServices(); + + $services = new ArrayCollection(); + + foreach ($siteIDs as $value) { + $site = \Factory::getSiteService()->getSite($value); + $services[$value] = $site->getServices(); + } + $params['services'] = $services; show_view("downtime/view_nested_endpoints_list.php", $params, null, true); } @@ -41,18 +52,26 @@ function editDowntimePopulateEndpointTree() { require_once __DIR__ . '/../utils.php'; require_once __DIR__ . '/../../../web_portal/components/Get_User_Principle.php'; + $params = []; $dn = Get_User_Principle(); $user = \Factory::getUserService()->getUserByPrinciple($dn); $params['portalIsReadOnly'] = portalIsReadOnlyAndUserIsNotAdmin($user); + $siteIDs = $_REQUEST['site_id']; - if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id']) ){ - throw new Exception("A site id must be specified"); + if (empty($_REQUEST['site_id'])) { + throw new Exception("Please select at least one site."); } if (!isset($_REQUEST['dt_id']) || !is_numeric($_REQUEST['dt_id']) ){ throw new Exception("A downtime id must be specified"); } - $site = \Factory::getSiteService()->getSite($_REQUEST['site_id']); - $services = $site->getServices(); + + $services = new ArrayCollection(); + + foreach ($siteIDs as $value) { + $site = \Factory::getSiteService()->getSite($value); + $services[$value] = $site->getServices(); + } + $params['services'] = $services; $downtime = \Factory::getDowntimeService()->getDowntime($_REQUEST['dt_id']); diff --git a/htdocs/web_portal/views/downtime/add_downtime.php b/htdocs/web_portal/views/downtime/add_downtime.php index 35508c0d2..6435dd6ec 100644 --- a/htdocs/web_portal/views/downtime/add_downtime.php +++ b/htdocs/web_portal/views/downtime/add_downtime.php @@ -67,7 +67,13 @@ - +
+ WARNING: You are NOT allowed to create downtimes
+ when you have selected multiple sites
+ using the Site Timezone
option.
+