Example #1
0
 public function testUpdateSetsCoordinatesForLocation()
 {
     $ticket = new Ticket();
     $ticket->handleUpdate(array('location' => $this->data['location']));
     $this->assertNotEmpty($ticket->getLatitude());
     $this->assertNotEmpty($ticket->getLongitude());
 }
Example #2
0
 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());
 }
Example #3
0
 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]);
         }
     }
 }
Example #5
0
 /**
  * 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));
     }
 }
Example #8
0
 /**
  * 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();
     }
 }
Example #9
0
 /**
  * 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();
     }
 }
Example #10
0
 /**
  * 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());
         }
     }
 }