public function testUpdateSetsCoordinatesForLocation() { $ticket = new Ticket(); $ticket->handleUpdate(array('location' => $this->data['location'])); $this->assertNotEmpty($ticket->getLatitude()); $this->assertNotEmpty($ticket->getLongitude()); }
public function testDefaultSubstatus() { $s1 = new Substatus('Test One'); $s2 = new Substatus('Test Two'); $ticket = new Ticket(); $this->assertEquals('Test One', $ticket->getSubstatus()->getName()); $s2->setDefault(true); $s2->save(); $ticket = new Ticket(); $this->assertEquals('Test Two', $ticket->getSubstatus()->getName()); }
public function testAddressServiceDataDoesNotLatLong() { $ticket = new Ticket(); $ticket->setLocation('Somewhere'); $ticket->setLatitude(37); $ticket->setLongitude(-80); $ticket->setAddressServiceData($this->data); $this->assertEquals($this->data['location'], $ticket->getLocation(), 'Address string was not updated from AddressService'); $this->assertEquals(37, $ticket->getLatitude(), 'Latitude was changed from AddressService'); $this->assertEquals(-80, $ticket->getLongitude(), 'Longitude was changed from AddressService'); }
/** * @param REQUEST service_request_id */ public function requests() { if (!empty($_REQUEST['service_code'])) { try { $category = new Category($_REQUEST['service_code']); } catch (\Exception $e) { header('HTTP/1.0 404 Not Found', true, 404); $_SESSION['errorMessages'][] = $e; return; } } // Display a single request if (!empty($_REQUEST['service_request_id'])) { try { $ticket = new Ticket($_REQUEST['service_request_id']); if ($ticket->allowsDisplay($this->person)) { $this->template->blocks[] = new Block('open311/requestInfo.inc', array('ticket' => $ticket)); } else { header('HTTP/1.0 403 Forbidden', true, 403); $_SESSION['errorMessages'][] = new \Exception('noAccessAllowed'); } } catch (\Exception $e) { // Unknown ticket header('HTTP/1.0 404 Not Found', true, 404); $_SESSION['errorMessages'][] = $e; return; } } elseif (isset($_POST['service_code'])) { try { $ticket = new Ticket(); $ticket->handleAdd(Open311Client::translatePostArray($_POST)); // Media can only be attached after the ticket is saved // It uses the issue_id in the directory structure if (isset($_FILES['media'])) { $issue = $ticket->getIssue(); try { $media = new Media(); $media->setIssue($issue); $media->setFile($_FILES['media']); $media->save(); } catch (\Exception $e) { // Just ignore any media errors for now } } $this->template->blocks[] = new Block('open311/requestInfo.inc', array('ticket' => $ticket)); } catch (\Exception $e) { $_SESSION['errorMessages'][] = $e; switch ($e->getMessage()) { case 'clients/unknownClient': header('HTTP/1.0 403 Forbidden', true, 403); break; default: header('HTTP/1.0 400 Bad Request', true, 400); } } } else { $search = array(); if (isset($category)) { if ($category->allowsDisplay($this->person)) { $search['category_id'] = $category->getId(); } else { header('HTTP/1.0 404 Not Found', true, 404); $_SESSION['errorMessages'][] = new \Exception('categories/unknownCategory'); return; } } if (!empty($_REQUEST['start_date'])) { $search['start_date'] = $_REQUEST['start_date']; } if (!empty($_REQUEST['end_date'])) { $search['end_date'] = $_REQUEST['end_date']; } if (!empty($_REQUEST['status'])) { $search['status'] = $_REQUEST['status']; } if (!empty($_REQUEST['updated_before'])) { $search['lastModified_before'] = $_REQUEST['updated_before']; } if (!empty($_REQUEST['updated_after'])) { $search['lastModified_after'] = $_REQUEST['updated_after']; } if (!empty($_REQUEST['bbox'])) { $search['bbox'] = $_REQUEST['bbox']; } $pageSize = 1000; if (!empty($_REQUEST['page_size'])) { $p = (int) $_REQUEST['page_size']; if ($p) { $pageSize = $p; } } // Pagination pages are one-based and will treat page=0 // as exactly the same as page=1 $page = 0; if (!empty($_REQUEST['page'])) { $p = (int) $_REQUEST['page']; if ($p) { $page = $p; } } $table = new TicketTable(); $tickets = $table->find($search, null, true); $tickets->setCurrentPageNumber($page); $tickets->setItemCountPerPage($pageSize); $this->template->blocks[] = new Block('open311/requestList.inc', array('ticketList' => $tickets)); if ($this->template->outputFormat == 'html') { $this->template->blocks[] = new Block('pageNavigation.inc', ['paginator' => $tickets]); } } }
/** * Send a notification of this action to the actionPerson * * Does not send if the enteredByPerson and actionPerson are the same person * @param Ticket $ticket */ public function sendNotification($ticket = null) { $enteredByPerson = $this->getEnteredByPerson(); $actionPerson = $this->getActionPerson(); $url = $ticket ? $ticket->getURL() : ''; if ($actionPerson && (!$enteredByPerson || $enteredByPerson->getId() != $actionPerson->getId())) { $actionPerson->sendNotification("{$url}\n\n{$this->getDescription()}\n\n{$this->getNotes()}", APPLICATION_NAME . ' ' . $this->getAction()); } }
/** * @param Ticket $ticket */ private function addStandardInfoBlocks(Ticket $ticket) { $this->template->blocks['history-panel'][] = new Block('tickets/history.inc', array('history' => $ticket->getHistory())); $this->template->blocks['issue-panel'][] = new Block('tickets/issueList.inc', array('issueList' => $ticket->getIssues(), 'ticket' => $ticket, 'disableButtons' => $ticket->getStatus() == 'closed')); if ($ticket->getLocation()) { $locationBlocks = array('locationInfo', 'masterAddressData', 'locationPeople'); foreach ($locationBlocks as $b) { $this->template->blocks['bottom-left'][] = new Block("locations/{$b}.inc", array('location' => $ticket->getLocation(), 'disableButtons' => true)); } $this->template->blocks['bottom-right'][] = new Block('tickets/ticketLocationInfo.inc', array('ticket' => $ticket)); $table = new TicketTable(); $list = $table->find(array('location' => $ticket->getLocation())); if (count($list) > 1) { $this->template->blocks['bottom-left'][] = new Block('tickets/ticketList.inc', array('ticketList' => $list, 'title' => 'Other cases for this location', 'filterTicket' => $ticket, 'disableButtons' => true)); } } }
/** * @param Ticket $ticket */ private function addLocationInfoBlocks(Ticket $ticket) { if ($ticket->getLocation()) { $this->template->blocks['bottom-left'][] = new Block('locations/locationInfo.inc', array('location' => $ticket->getLocation(), 'disableButtons' => true)); $table = new TicketTable(); $this->template->blocks['bottom-right'][] = new Block('tickets/ticketList.inc', array('ticketList' => $table->find(['location' => $ticket->getLocation()]), 'title' => 'Other tickets for this location', 'disableButtons' => true, 'filterTicket' => $ticket)); } }
/** * Transfers issues and history from another ticket into this one * * We're only migrating the issue and history * Once we're done we delete the other ticket * * @param Ticket $ticket */ public function mergeFrom(Ticket $ticket) { if ($this->getId()) { $zend_db = Database::getConnection(); $zend_db->getDriver()->getConnection()->beginTransaction(); try { $zend_db->query('update ticketHistory set ticket_id=? where ticket_id=?')->execute([$this->getId(), $ticket->getId()]); $zend_db->query('update issues set ticket_id=? where ticket_id=?')->execute([$this->getId(), $ticket->getId()]); $zend_db->query('delete from tickets where id=?')->execute([$ticket->getId()]); } catch (\Exception $e) { $zend_db->getDriver()->getConnection()->rollback(); throw $e; } $zend_db->getDriver()->getConnection()->commit(); $search = new Search(); $search->delete($ticket); $search->add($this); $search->solrClient->commit(); } }
/** * Finds or creates a cluster for the given Ticket * * If there is already a cluster within a certain distance, * this will return the ID for that cluster. * If it doesn't find a nearby cluster, this will add a * new cluster to the database and return the new ID. * * @param Ticket $ticket * @param int $level */ public static function assignClusterIdForLevel(Ticket $ticket, $level) { $lat = $ticket->getLatitude(); $lng = $ticket->getLongitude(); $dist = 0.01 * pow(2, $level * 2); $minX = $lng - $dist; $maxX = $lng + $dist; $minY = $lat - $dist; $maxY = $lat + $dist; // Geocluster center points are in the database, so we can just look // them up. However, MySQL spatial functions only allow bounding box // queries, not points inside a circle, which is what we want. // So, here, we're still calculating the haversine distance $sql = "\n\t\tSELECT id,x(center) as longitude, y(center) as latitude,\n\t\t\t( SELECT\n\t\t\t\t(ACOS(SIN(RADIANS(y(center))) * SIN(RADIANS({$lat}))\n\t\t\t\t + COS(RADIANS(y(center))) * COS(RADIANS({$lat}))\n\t\t\t\t * COS(RADIANS(x(center) - {$lng}))) * 6371.0)\n\t\t\t) as distance\n\t\tFROM geoclusters\n\t\tWHERE level=?\n\t\t and (ACOS(SIN(RADIANS(y(center))) * SIN(RADIANS({$lat}))\n\t\t\t + COS(RADIANS(y(center))) * COS(RADIANS({$lat}))\n\t\t\t * COS(RADIANS(x(center) - {$lng}))) * 6371.0) < {$dist}\n\t\torder by distance\n\t\tLIMIT 1\n\t\t"; $zend_db = Database::getConnection(); $result = $zend_db->query($sql)->execute([$level]); if (count($result)) { $row = $result->current(); return $row['id']; } else { $cluster = new GeoCluster(); $cluster->setLevel($level); $cluster->setLatitude($lat); $cluster->setLongitude($lng); $cluster->save(); return $cluster->getId(); } }
/** * Event handler called from Ticket::handleAdd() * * Handles the autoClose and autoResponse sending * @param Ticket $ticket */ public function onTicketAdd(Ticket &$ticket) { if ($this->autoCloseIsActive()) { $ticket->handleChangeStatus(['status' => 'closed', 'substatus_id' => $this->getAutoCloseSubstatus_id(), 'notes' => AUTO_CLOSE_COMMENT]); } if ($this->autoResponseIsActive()) { foreach ($ticket->getReportedByPeople() as $person) { $message = $this->getAutoResponseText(); # Commenting out the inclusion of a link to the ticket #if ($this->allowsDisplay($person)) { # $message.="\n\n{$ticket->getURL()}\n"; #} $person->sendNotification($message, null, $this->getNotificationReplyEmail()); } } }