function showTimeTable($links) { global $mode, $viewmode, $user; if ($links == 1) { $imageid = getContinuationVar('imageid'); $length = getContinuationVar('length'); $requestid = getContinuationVar('requestid', 0); $showmessage = getContinuationVar('showmessage', 0); $platforms = array(); $schedules = array(); } else { $imageid = 0; $length = 0; $requestid = 0; $showmessage = 0; $platforms = getContinuationVar("platforms"); if (empty($platforms)) { $platforms = processInputVar("platforms", ARG_MULTINUMERIC); } $schedules = getContinuationVar("schedules"); if (empty($schedules)) { $schedules = processInputVar("schedules", ARG_MULTINUMERIC); } } $argstart = getContinuationVar("start"); $argend = getContinuationVar("end"); $resources = getUserResources(array("computerAdmin")); $userCompIDs = array_keys($resources["computer"]); $computerData = getComputers(); $imageData = getImages(); $now = time(); if ($links) { $resources = getUserResources(array("imageAdmin", "imageCheckOut")); $usercomputerids = array_keys($resources["computer"]); # get list of computers' platformids $qh = doQuery("SELECT platformid FROM image WHERE id = {$imageid}", 110); $row = mysql_fetch_row($qh); $platformid = $row[0]; $computer_platformids = array(); $qh = doQuery("SELECT id, platformid FROM computer", 111); while ($row = mysql_fetch_row($qh)) { $computer_platformids[$row[0]] = $row[1]; } $mappedcomputers = getMappedResources($imageid, "image", "computer"); $compidlist = array_intersect($mappedcomputers, $usercomputerids); } else { $compidlist = $userCompIDs; } if (!empty($argstart) && !empty($argend)) { $timeslots = getTimeSlots($compidlist, $argend, $argstart); $start = $argstart; $end = $argend; } else { $start = $now; $end = $start + SECINDAY / 2; $timeslots = getTimeSlots($compidlist, $end); } print "<DIV align=center>\n"; print "<H2>Time Table</H2>\n"; print "</DIV>\n"; $computeridrow = ""; $displayedids = array(); $computers = array_keys($timeslots); if ($links) { $computers = array_intersect($computers, $usercomputerids); } foreach ($computers as $id) { if ($links) { # don't show computers that don't meet hardware criteria, are not # in the available state, are the wrong platform, or wrong group, # or aren't mapped in resourcemap if ($computer_platformids[$id] != $platformid || $computerData[$id]["stateid"] != 2 && $computerData[$id]["stateid"] != 3 && $computerData[$id]["stateid"] != 6 && $computerData[$id]["stateid"] != 8 || $computerData[$id]["ram"] < $imageData[$imageid]["minram"] || $computerData[$id]["procnumber"] < $imageData[$imageid]["minprocnumber"] || $computerData[$id]["procspeed"] < $imageData[$imageid]["minprocspeed"] || $computerData[$id]["network"] < $imageData[$imageid]["minnetwork"] || !in_array($id, $mappedcomputers)) { continue; } } elseif (!array_key_exists($id, $computerData) || !in_array($computerData[$id]["platformid"], $platforms) || !in_array($computerData[$id]["scheduleid"], $schedules) || !in_array($id, $userCompIDs)) { continue; } $computeridrow .= " <TH>{$id}</TH>\n"; array_push($displayedids, $id); } if (empty($displayedids)) { if ($links) { print "There are currently no computers available that can run the application you selected.\n"; } else { print "There are no computers that meet the specified criteria\n"; } return; } if ($showmessage) { print "The time you have requested to use the environment is not "; print "available. You may select from the green blocks of time to "; print "select an available time slot to make a reservation.<br>\n"; } print "<table summary=\"\">\n"; print " <TR>\n"; print " <TD>"; # print Previous/Next links if (!empty($argstart) && $argstart - SECINDAY / 2 > $now - 600) { $prevstart = $start - SECINDAY / 2; $prevend = $end - SECINDAY / 2; print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n"; $cdata = array('start' => $prevstart, 'end' => $prevend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules); $cont = addContinuationsEntry($mode, $cdata, SECINDAY); print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n"; print "<INPUT type=submit value=Previous>\n"; print "</FORM>\n"; } print "</TD>\n"; print " <TD>"; if ($end + SECINDAY / 2 < $now + DAYSAHEAD * SECINDAY) { $nextstart = $start + SECINDAY / 2; $nextend = $end + SECINDAY / 2; print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n"; $cdata = array('start' => $nextstart, 'end' => $nextend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules); $cont = addContinuationsEntry($mode, $cdata, SECINDAY); print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n"; print "<INPUT type=submit value=Next>\n"; print "</FORM>\n"; } print "</TD>\n"; print " </TR>\n"; print " <TR>\n"; print " <TD>\n"; $tmpArr = array_keys($computers); $first = $computers[$tmpArr[0]]; print " <table id=ttlayout summary=\"\">\n"; if (!$links || $viewmode >= ADMIN_DEVELOPER) { print " <TR>\n"; print " <TH align=right>Computer ID:</TH>\n"; print $computeridrow; print " </TR>\n"; } $yesterday = ""; foreach (array_keys($timeslots[$first]) as $stamp) { if ($stamp < $now) { continue; } print " <TR>\n"; $stampArr = getdate($stamp); $label = ""; if ($stampArr["mday"] != $yesterday) { $label = date('n/d/Y+g:i+a', $stamp); $label = str_replace('+', ' ', $label); $yesterday = $stampArr["mday"]; } elseif ($stampArr["minutes"] == 0) { $label = date('g:i a', $stamp); } print " <TH align=right>{$label}</TH>\n"; $free = 0; # print the cells foreach ($computers as $id) { if (!in_array($id, $displayedids)) { continue; } if ($links && ($computer_platformids[$id] != $platformid || $computerData[$id]["stateid"] == 10 || $computerData[$id]["stateid"] == 5)) { continue; } # computer's schedule is currently closed if ($timeslots[$id][$stamp]["scheduleclosed"] == 1) { print " <TD bgcolor=\"#a0a0a0\"><img src=images/gray.jpg "; print "alt=scheduleclosed border=0></TD>\n"; } elseif ($computerData[$id]["stateid"] == 10) { print " <TD bgcolor=\"#a0a0a0\"><img src=images/gray.jpg "; print "alt=maintenance border=0></TD>\n"; } elseif ($timeslots[$id][$stamp]['blockRequest'] && ($timeslots[$id][$stamp]['blockRequestInfo']['imageid'] != $imageid || !in_array($timeslots[$id][$stamp]['blockRequestInfo']['groupid'], array_keys($user['groups']))) && $timeslots[$id][$stamp]['available']) { if ($links) { print " <TD bgcolor=\"#ff0000\"><img src=images/red.jpg "; print "alt=blockrequest border=0></TD>\n"; } else { print " <TD bgcolor=\"#e58304\"><img src=images/orange.jpg "; $title = "Block Request: {$timeslots[$id][$stamp]['blockRequestInfo']['name']}\n" . "Image: {$timeslots[$id][$stamp]['blockRequestInfo']['image']}"; print "alt=blockrequest border=0 title=\"{$title}\"></TD>\n"; } } elseif ($timeslots[$id][$stamp]["available"]) { if ($links) { print " <TD bgcolor=\"#00ff00\"><a href=\"" . BASEURL . SCRIPT; print "?mode=newRequest&stamp={$stamp}&imageid={$imageid}&length={$length}\"><img "; print "src=images/green.jpg alt=free border=0></a></TD>\n"; } else { print " <TD bgcolor=\"#00ff00\"><img src=images/green.jpg alt=free border=0></TD>\n"; } } else { if ($links) { print " <TD bgcolor=\"#ff0000\"><font color=\"#ff0000\">used</font></TD>\n"; } else { $title = "User: "******"unityid"] . " Image: " . $timeslots[$id][$stamp]["prettyimage"]; $cdata = array('requestid' => $timeslots[$id][$stamp]["requestid"]); $cont = addContinuationsEntry('viewRequestInfo', $cdata); print " <TD bgcolor=\"#ff0000\"><a href=\"" . BASEURL; print SCRIPT . "?continuation={$cont}\"><img src=images/red.jpg "; print "alt=used border=0 title=\"{$title}\"></a></TD>\n"; } } } print " </TR>\n"; } print " </table>\n"; print " </TD>\n"; print " </TR>\n"; print " <TR>\n"; print " <TD>"; # print Previous/Next links if (!empty($argstart) && $argstart - SECINDAY / 2 > $now - 600) { $prevstart = $start - SECINDAY / 2; $prevend = $end - SECINDAY / 2; print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n"; $cdata = array('start' => $prevstart, 'end' => $prevend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules); $cont = addContinuationsEntry($mode, $cdata, SECINDAY); print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n"; print "<INPUT type=submit value=Previous>\n"; print "</FORM>\n"; } print "</TD>\n"; print " <TD>"; if ($end + SECINDAY / 2 < $now + DAYSAHEAD * SECINDAY) { $nextstart = $start + SECINDAY / 2; $nextend = $end + SECINDAY / 2; print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n"; $cdata = array('start' => $nextstart, 'end' => $nextend, 'imageid' => $imageid, 'requestid' => $requestid, 'length' => $length, 'platforms' => $platforms, 'schedules' => $schedules); $cont = addContinuationsEntry($mode, $cdata, SECINDAY); print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n"; print "<INPUT type=submit value=Next>\n"; print "</FORM>\n"; } print "</TD>\n"; print " </TR>\n"; print "</table>\n"; }
function findAvailableTimes($start, $end, $imageid, $userid, $usedaysahead, $reqid = '', $extendonly = 0, $ip = '', $mac = '') { global $user; if ($userid == $user['id']) { $ingroups = implode(',', array_keys($user['groups'])); } else { $userdata = getUserInfo($userid, 0, 1); $ingroups = implode(',', array_keys($userdata['groups'])); } # TODO make this work for cluster images if (!$extendonly) { $mappedcomputers = getMappedResources($imageid, 'image', 'computer'); $resources = getUserResources(array('imageAdmin', 'imageCheckOut'), array('available'), 0, 0, $userid); $compids = array_intersect($mappedcomputers, array_keys($resources['computer'])); if (!count($compids)) { return array(); } $incompids = implode(',', $compids); } else { $request = getRequestInfo($reqid); $incompids = $request['reservations'][0]['computerid']; } $scheduleids = getAvailableSchedules($start, $end); if (empty($scheduleids)) { return array(); } $schedules = implode(',', $scheduleids); $platformid = getImagePlatform($imageid); if (is_null($platformid)) { return array(); } $reqduration = $end - $start; $startdt = unixToDatetime($start); $end += 900; $enddt = unixToDatetime($end); $ignorestates = "'maintenance','vmhostinuse','hpc','failed'"; $nowignorestates = "{$ignorestates},'timeout'"; if (!$extendonly) { $nowignorestates .= ",'reloading','reload','inuse'"; } $slots = array(); $removes = array(); $minstart = $start; $maxend = $start; $newcompids = array(); $daysahead = time() + DAYSAHEAD * SECINDAY; # add computers that are available now with no future reservations # restricting duration; we do this so that they'll be in our arrays to check # for concurrent image use, block allocations, ip/mac overlap, and # maintenance window overlap $query = "SELECT c.id AS compid " . "FROM computer c, " . "image i, " . "state s, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE c.stateid = s.id AND " . "i.id = {$imageid} AND " . "s.name NOT IN ({$nowignorestates}) AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.id NOT IN (SELECT rs.computerid " . "FROM reservation rs, " . "request rq " . "WHERE rs.requestid = rq.id AND "; if ($reqid != '') { $query .= "rq.id != {$reqid} AND "; } $query .= "DATE_ADD(rq.end, INTERVAL 15 MINUTE) >= '{$startdt}' AND " . "rs.computerid IN ({$incompids})) AND " . "c.id IN ({$incompids}) " . "ORDER BY RAM, " . "(c.procspeed * c.procnumber), " . "network"; $qh = doQuery($query, 101); while ($row = mysql_fetch_assoc($qh)) { $row['duration'] = $reqduration; $row['startts'] = $start; $row['start'] = $startdt; $row['endts'] = $start + $reqduration; $slots[$row['compid']] = array(); $slots[$row['compid']][] = $row; $newcompids[] = $row['compid']; } if (!$extendonly) { # find available timeslots based on spacing between existing reservations $query = "SELECT rs1.computerid AS compid, " . "DATE_ADD(rq1.end, INTERVAL 15 MINUTE) AS start, " . "MIN(UNIX_TIMESTAMP(rq2.start) - UNIX_TIMESTAMP(rq1.end) - 1800) AS duration " . "FROM request rq1, " . "request rq2, " . "reservation rs1, " . "reservation rs2, " . "image i, " . "state s, " . "computer c, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE rq1.id = rs1.requestid AND " . "rs2.requestid = rq2.id AND " . "rq1.id != rq2.id AND " . "rq1.start < rq2.start AND " . "DATE_ADD(rq1.end, INTERVAL 15 MINUTE) >= '{$startdt}' AND " . "rs1.computerid = rs2.computerid AND " . "rs1.computerid IN ({$incompids}) AND " . "i.id = {$imageid} AND " . "c.id = rs1.computerid AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.stateid = s.id AND " . "s.name NOT IN ({$ignorestates}) AND "; if ($reqid != '') { $query .= "rq1.id != {$reqid} AND " . "rq2.id != {$reqid} AND "; } $query .= "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) " . "GROUP BY rq1.id "; $query .= "ORDER BY rs1.computerid, rq1.start, rq1.end"; $qh = doQuery($query, 101); while ($row = mysql_fetch_assoc($qh)) { $row['startts'] = datetimeToUnix($row['start']); if ($row['startts'] % 900) { $row['startts'] = $row['startts'] - $row['startts'] % 900 + 900; $row['start'] = unixToDatetime($row['startts']); $row['duration'] -= 900; } if ($row['duration'] >= 1800) { if ($usedaysahead && $row['startts'] > $daysahead) { continue; } if ($row['duration'] > $reqduration) { $row['duration'] = $reqduration; } $row['endts'] = $row['startts'] + $row['duration']; if (!array_key_exists($row['compid'], $slots)) { $slots[$row['compid']] = array(); } $slots[$row['compid']][] = $row; if ($row['startts'] < $minstart) { $minstart = $row['startts']; } if ($row['endts'] > $maxend) { $maxend = $row['endts']; } $newcompids[] = $row['compid']; } } } # find slots that are available now $query = "SELECT UNIX_TIMESTAMP(MIN(rq.start)) - UNIX_TIMESTAMP('{$startdt}') - 900 AS duration, " . "UNIX_TIMESTAMP(MIN(rq.start)) AS endts, " . "rs.computerid AS compid " . "FROM request rq, " . "reservation rs, " . "image i, " . "state s, " . "computer c, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE rs.requestid = rq.id AND " . "(rq.start > '{$startdt}' OR " . "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '{$startdt}' AND rq.start <= '{$startdt}')) AND " . "rs.computerid IN ({$incompids}) AND " . "i.id = {$imageid} AND " . "c.id = rs.computerid AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.stateid = s.id AND " . "s.name NOT IN ({$nowignorestates}) AND "; if ($reqid != '') { $query .= "rq.id != {$reqid} AND "; } $query .= "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) " . "GROUP BY rs.computerid"; $qh = doQuery($query, 101); while ($row = mysql_fetch_assoc($qh)) { if ($row['endts'] % 900) { $row['endts'] = $row['endts'] - $row['endts'] % 900; $row['duration'] -= 900; } if ($row['duration'] >= 1800) { if ($row['duration'] > $reqduration) { $row['duration'] = $reqduration; } $row['start'] = $startdt; $row['startts'] = $start; if (!array_key_exists($row['compid'], $slots)) { $slots[$row['compid']] = array(); } $slots[$row['compid']][] = $row; if ($row['endts'] > $maxend) { $maxend = $row['endts']; } $newcompids[] = $row['compid']; } } # find slots that are available after all reservations are over $query = "SELECT UNIX_TIMESTAMP(MAX(rq.end)) + 900 AS startts, " . "DATE_ADD(MAX(rq.end), INTERVAL 15 MINUTE) AS start, " . "rs.computerid AS compid " . "FROM request rq, " . "reservation rs, " . "image i, " . "state s, " . "computer c, " . "provisioningOSinstalltype poi, " . "OSinstalltype oi, " . "OS o " . "WHERE rs.requestid = rq.id AND " . "(rq.start > '{$startdt}' OR " . "(DATE_ADD(rq.end, INTERVAL 15 MINUTE) > '{$startdt}' AND rq.start <= '{$startdt}')) AND " . "rs.computerid IN ({$incompids}) AND " . "i.id = {$imageid} AND " . "c.id = rs.computerid AND " . "c.platformid = {$platformid} AND " . "c.scheduleid IN ({$schedules}) AND " . "i.OSid = o.id AND " . "o.installtype = oi.name AND " . "oi.id = poi.OSinstalltypeid AND " . "poi.provisioningid = c.provisioningid AND " . "c.RAM >= i.minram AND " . "c.procnumber >= i.minprocnumber AND " . "c.procspeed >= i.minprocspeed AND " . "c.network >= i.minnetwork AND " . "c.deleted = 0 AND " . "c.stateid = s.id AND " . "s.name NOT IN ({$ignorestates}) AND "; if ($reqid != '') { $query .= "rq.id != {$reqid} AND "; } $query .= "(c.type != 'virtualmachine' OR c.vmhostid IS NOT NULL) " . "GROUP BY rs.computerid"; if ($extendonly) { $query .= " HAVING start = '{$startdt}'"; } $qh = doQuery($query, 101); while ($row = mysql_fetch_assoc($qh)) { if ($usedaysahead && $row['startts'] > $daysahead) { continue; } if ($row['startts'] % 900) { $row['startts'] = $row['startts'] - $row['startts'] % 900 + 900; $row['start'] = unixToDatetime($row['startts']); } $row['endts'] = $row['startts'] + $reqduration; $row['duration'] = $reqduration; if (!array_key_exists($row['compid'], $slots)) { $slots[$row['compid']] = array(); } $slots[$row['compid']][] = $row; if ($row['endts'] > $maxend) { $maxend = $row['endts']; } $newcompids[] = $row['compid']; } if (empty($newcompids)) { return array(); } # remove block computers $minstartdt = unixToDatetime($minstart); $maxenddt = unixToDatetime($maxend); $newincompids = implode(',', $newcompids); $query = "SELECT bc.computerid AS compid, " . "UNIX_TIMESTAMP(bt.start) AS start, " . "UNIX_TIMESTAMP(bt.end) AS end " . "FROM blockComputers bc, " . "blockTimes bt, " . "blockRequest br " . "WHERE bt.id = bc.blockTimeid AND " . "br.id = bt.blockRequestid AND " . "bt.skip = 0 AND " . "bt.start < '{$maxenddt}' AND " . "bt.end > '{$minstartdt}' AND "; if ($ingroups != '') { $query .= "(br.groupid NOT IN ({$ingroups}) OR " . "br.imageid != {$imageid}) AND "; } $query .= "bc.computerid IN ({$newincompids})"; $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { if (array_key_exists($row['compid'], $slots)) { fATremoveOverlaps($slots, $row['compid'], $row['start'], $row['end'], 0); } } # remove mac/ip overlaps $newcompids = array_keys($slots); $newincompids = implode(',', $newcompids); if (!empty($ip) || !empty($mac)) { $query = "SELECT rs.computerid AS compid, " . "UNIX_TIMESTAMP(rq.start) AS start, " . "UNIX_TIMESTAMP(rq.end) AS end " . "FROM serverrequest s, " . "request rq, " . "reservation rs " . "WHERE s.requestid = rq.id AND " . "rs.requestid = rq.id AND " . "rq.start < '{$maxenddt}' AND " . "rq.end > '{$minstartdt}' AND " . "rs.computerid IN ({$newincompids}) AND "; if ($reqid != '') { $query .= "rq.id != {$reqid} AND "; } if (!empty($ip) && !empty($mac)) { $query .= "(s.fixedIP = '{$ip}' OR s.fixedMAC = '{$mac}')"; } elseif (!empty($ip)) { $query .= "s.fixedIP = '{$ip}'"; } elseif (!empty($mac)) { $query .= "s.fixedIP = '{$mac}'"; } $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { if (array_key_exists($row['compid'], $slots)) { fATremoveOverlaps($slots, $row['compid'], $row['start'], $row['end'], 0); } } } # remove slots overlapping with scheduled maintenance $query = "SELECT UNIX_TIMESTAMP(start) AS start, " . "UNIX_TIMESTAMP(end) AS end, " . "allowreservations " . "FROM sitemaintenance " . "WHERE start < '{$maxenddt}' AND " . "end > '{$minstartdt}'"; $qh = doQuery($query); while ($row = mysql_fetch_assoc($qh)) { foreach (array_keys($slots) as $compid) { fATremoveOverlaps($slots, $compid, $row['start'], $row['end'], $row['allowreservations']); } } $imgdata = getImages(0, $imageid); $options = array(); foreach ($slots as $comp) { foreach ($comp as $data) { $data['duration'] = $data['duration'] - $data['duration'] % 900; if (!$extendonly) { if ($data['duration'] > 3600 && $data['duration'] < 7200) { $data['duration'] = 3600; } elseif ($data['duration'] > 7200 && $data['duration'] < SECINDAY * 2) { $data['duration'] = $data['duration'] - $data['duration'] % 7200; } elseif ($data['duration'] > SECINDAY * 2) { $data['duration'] = $data['duration'] - $data['duration'] % SECINDAY; } } # skip computers that have no controlling management node if (!findManagementNode($data['compid'], $data['start'], 'future')) { continue; } # skip slots that would cause a concurrent use violation if ($imgdata[$imageid]['maxconcurrent'] != NULL && fATconcurrentOverlap($data['startts'], $data['duration'], $imageid, $imgdata[$imageid]['maxconcurrent'], $ignorestates, $extendonly, $reqid)) { continue; } if (array_key_exists($data['startts'], $options)) { if ($data['duration'] > $options[$data['startts']]['duration']) { $options[$data['startts']]['duration'] = $data['duration']; if (checkUserHasPerm('View Debug Information')) { $options[$data['startts']]['compid'] = $data['compid']; } } } else { $options[$data['startts']] = array('start' => $data['start'], 'startts' => $data['startts'], 'duration' => $data['duration']); if (checkUserHasPerm('View Debug Information')) { $options[$data['startts']]['compid'] = $data['compid']; } } } } uasort($options, "sortAvailableTimesByStart"); return $options; }