2015-12-16 00:48:30 +01:00
< ? php
App :: uses ( 'AppController' , 'Controller' );
2018-07-19 11:48:22 +02:00
class SightingsController extends AppController
{
public $components = array ( 'Session' , 'RequestHandler' );
2015-12-16 00:48:30 +01:00
2018-07-19 11:48:22 +02:00
public function beforeFilter ()
{
parent :: beforeFilter ();
}
2015-12-16 00:48:30 +01:00
2018-07-19 11:48:22 +02:00
public $paginate = array (
'limit' => 60 ,
2019-02-10 13:08:12 +01:00
'maxLimit' => 9999 , // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
2018-07-19 11:48:22 +02:00
'order' => array ( 'Sighting.date_sighting' => 'DESC' ),
);
2015-12-16 00:48:30 +01:00
2018-07-19 11:48:22 +02:00
// takes an attribute ID or UUID
public function add ( $id = false )
{
if ( $this -> request -> is ( 'post' )) {
$now = time ();
$values = false ;
$timestamp = false ;
$error = false ;
if ( $id === 'stix' ) {
$result = $this -> Sighting -> handleStixSighting ( file_get_contents ( 'php://input' ));
if ( $result [ 'success' ]) {
$result [ 'data' ] = json_decode ( $result [ 'data' ], true );
$timestamp = isset ( $result [ 'data' ][ 'timestamp' ]) ? strtotime ( $result [ 'data' ][ 'timestamp' ]) : $now ;
$type = '0' ;
$source = '' ;
if ( isset ( $result [ 'data' ][ 'values' ])) {
$values = $result [ 'data' ][ 'values' ];
} else {
$error = 'No valid values found that could be extracted from the sightings document.' ;
}
} else {
$error = $result [ 'message' ];
}
} else {
if ( isset ( $this -> request -> data [ 'request' ])) {
$this -> request -> data = $this -> request -> data [ 'request' ];
}
if ( isset ( $this -> request -> data [ 'Sighting' ])) {
$this -> request -> data = $this -> request -> data [ 'Sighting' ];
}
if ( ! empty ( $this -> request -> data [ 'date' ]) && ! empty ( $this -> request -> data [ 'time' ])) {
$timestamp = DateTime :: createFromFormat ( 'Y-m-d:H:i:s' , $this -> request -> data [ 'date' ] . ':' . $this -> request -> data [ 'time' ]);
$timestamp = $timestamp -> getTimestamp ();
} else {
$timestamp = isset ( $this -> request -> data [ 'timestamp' ]) ? $this -> request -> data [ 'timestamp' ] : $now ;
}
if ( isset ( $this -> request -> data [ 'value' ])) {
$this -> request -> data [ 'values' ] = array ( $this -> request -> data [ 'value' ]);
}
$values = isset ( $this -> request -> data [ 'values' ]) ? $this -> request -> data [ 'values' ] : false ;
if ( ! $id && isset ( $this -> request -> data [ 'uuid' ])) {
$id = $this -> request -> data [ 'uuid' ];
}
if ( ! $id && isset ( $this -> request -> data [ 'id' ])) {
$id = $this -> request -> data [ 'id' ];
}
$type = isset ( $this -> request -> data [ 'type' ]) ? $this -> request -> data [ 'type' ] : '0' ;
$source = isset ( $this -> request -> data [ 'source' ]) ? trim ( $this -> request -> data [ 'source' ]) : '' ;
}
if ( ! $error ) {
$result = $this -> Sighting -> saveSightings ( $id , $values , $timestamp , $this -> Auth -> user (), $type , $source );
}
if ( ! is_numeric ( $result )) {
$error = $result ;
}
if ( $this -> request -> is ( 'ajax' )) {
if ( $error ) {
$error_message = 'Could not add the Sighting. Reason: ' . $error ;
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => $error_message )), 'status' => 200 , 'type' => 'json' ));
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => $result . ' ' . $this -> Sighting -> type [ $type ] . (( $result == 1 ) ? '' : 's' ) . ' added.' )), 'status' => 200 , 'type' => 'json' ));
}
} else {
if ( $error ) {
2018-10-30 17:14:42 +01:00
$error_message = __ ( 'Could not add the Sighting. Reason: ' ) . $error ;
if ( $this -> _isRest () || $this -> response -> type () === 'application/json' ) {
$this -> set ( 'message' , $error_message );
$this -> set ( '_serialize' , array ( 'message' ));
} else {
$this -> Flash -> error ( $error_message );
$this -> redirect ( $this -> referer ());
}
2018-07-19 11:48:22 +02:00
} else {
2018-10-30 17:14:42 +01:00
if ( $this -> _isRest () || $this -> response -> type () === 'application/json' ) {
$this -> set ( 'message' , __ ( 'Sighting added' ));
$this -> set ( '_serialize' , array ( 'message' ));
} else {
$this -> Flash -> success ( __ ( 'Sighting added' ));
$this -> redirect ( $this -> referer ());
}
2018-07-19 11:48:22 +02:00
}
}
} else {
if ( $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Sightings' , 'add' , false , $this -> response -> type ());
}
if ( ! $this -> request -> is ( 'ajax' )) {
throw new MethodNotAllowedException ( 'This method is only accessible via POST requests and ajax GET requests.' );
} else {
$this -> layout = false ;
$this -> loadModel ( 'Attribute' );
$attributes = $this -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array ( 'conditions' => array ( 'Attribute.id' => $id ), 'flatten' => 1 ));
if ( empty ( $attributes )) {
throw new MethodNotAllowedExeption ( 'Invalid Attribute.' );
}
$this -> set ( 'event_id' , $attributes [ 0 ][ 'Attribute' ][ 'event_id' ]);
$this -> set ( 'id' , $id );
$this -> render ( 'ajax/add_sighting' );
}
}
}
2017-02-16 22:41:22 +01:00
2018-07-19 11:48:22 +02:00
public function advanced ( $id , $context = 'attribute' )
{
if ( empty ( $id )) {
throw new MethodNotAllowedException ( 'Invalid ' . $context . '.' );
}
$input_id = $id ;
$id = $this -> Sighting -> explodeIdList ( $id );
if ( $context == 'attribute' ) {
$this -> loadModel ( 'Attribute' );
$attributes = $this -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array ( 'conditions' => array ( 'Attribute.id' => $id ), 'flatten' => 1 ));
if ( empty ( $attributes )) {
throw new MethodNotAllowedException ( 'Invalid attribute.' );
}
} else {
$this -> loadModel ( 'Event' );
$events = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $id , 'metadata' => true ));
if ( empty ( $events )) {
throw new MethodNotAllowedException ( 'Invalid event.' );
}
}
$this -> set ( 'context' , $context );
$this -> set ( 'id' , $input_id );
$this -> render ( '/Sightings/ajax/advanced' );
}
2017-02-16 22:41:22 +01:00
2019-01-29 16:07:03 +01:00
public function quickAdd ( $id = false , $type = 1 , $onvalue = false )
2018-11-23 14:11:33 +01:00
{
2018-10-30 17:14:42 +01:00
if ( ! $this -> userRole [ 'perm_modify_org' ]) {
throw new MethodNotAllowedException ( __ ( 'You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.' ));
}
if ( ! $this -> request -> is ( 'post' )) {
$this -> loadModel ( 'Attribute' );
$attribute = $this -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array ( 'conditions' => array ( 'Attribute.id' => $id , 'Attribute.deleted' => 0 ), 'flatten' => 1 ));
if ( empty ( $attribute )) {
throw new MethodNotAllowedException ( __ ( 'Attribute not found' ));
} else {
$attribute = $attribute [ 0 ][ 'Attribute' ];
if ( ! $onvalue ) {
$this -> set ( 'id' , $attribute [ 'id' ]);
$this -> set ( 'tosight' , $attribute [ 'id' ]);
} else {
$this -> set ( 'id' , '' );
$this -> set ( 'tosight' , $attribute [ 'value' ]);
}
$this -> set ( 'value' , $attribute [ 'value' ]);
$this -> set ( 'event_id' , $attribute [ 'event_id' ]);
2019-01-29 16:07:03 +01:00
$this -> set ( 'sighting_type' , $type );
2018-10-30 17:14:42 +01:00
$this -> set ( 'onvalue' , $onvalue );
$this -> render ( 'ajax/quickAddConfirmationForm' );
}
} else {
if ( ! isset ( $id )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'errors' => __ ( 'Invalid request.' ))), 'status' => 200 , 'type' => 'json' ));
} else {
if ( $onvalue ) {
$result = $this -> Sighting -> add ();
} else {
$result = $this -> Sighting -> add ( $id );
}
if ( $result ) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => __ ( 'Sighting added.' ))), 'status' => 200 , 'type' => 'json' ));
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'errors' => __ ( 'Sighting could not be added' ))), 'status' => 200 , 'type' => 'json' ));
}
}
}
}
2018-07-19 11:48:22 +02:00
public function quickDelete ( $id , $rawId , $context )
{
if ( ! $this -> userRole [ 'perm_modify_org' ]) {
throw new MethodNotAllowedException ( 'You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.' );
}
if ( ! $this -> request -> is ( 'post' )) {
$this -> set ( 'id' , $id );
$sighting = $this -> Sighting -> find ( 'first' , array ( 'conditions' => array ( 'Sighting.id' => $id ), 'recursive' => - 1 , 'fields' => array ( 'Sighting.attribute_id' )));
$this -> set ( 'rawId' , $rawId );
$this -> set ( 'context' , $context );
$this -> render ( 'ajax/quickDeleteConfirmationForm' );
} else {
if ( ! isset ( $id )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'errors' => 'Invalid request.' )), 'status' => 200 , 'type' => 'json' ));
} else {
$sighting = $this -> Sighting -> find ( 'first' , array ( 'conditions' => array ( 'Sighting.id' => $id ), 'recursive' => - 1 ));
if ( empty ( $sighting )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'errors' => 'Invalid sighting.' )), 'status' => 200 , 'type' => 'json' ));
}
if ( ! $this -> _isSiteAdmin () && $sighting [ 'Sighting' ][ 'org_id' ] != $this -> Auth -> user ( 'org_id' )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'errors' => 'Invalid sighting.' )), 'status' => 200 , 'type' => 'json' ));
}
$result = $this -> Sighting -> delete ( $id );
if ( $result ) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => 'Sighting deleted.' )), 'status' => 200 , 'type' => 'json' ));
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'errors' => 'Sighting could not be deleted' )), 'status' => 200 , 'type' => 'json' ));
}
}
}
}
2015-12-16 00:48:30 +01:00
2018-07-19 11:48:22 +02:00
// takes a sighting ID
public function delete ( $id )
{
if ( ! $this -> userRole [ 'perm_modify_org' ]) {
throw new MethodNotAllowedException ( 'You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.' );
}
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( 'This action can only be accessed via a post request.' );
}
$sighting = $this -> Sighting -> find ( 'first' , array ( 'conditions' => array ( 'Sighting.id' => $id ), 'recursive' => - 1 ));
if ( empty ( $sighting )) {
throw new NotFoundException ( 'Invalid sighting.' );
}
if ( ! $this -> _isSiteAdmin ()) {
if ( $sighting [ 'Sighting' ][ 'org_id' ] != $this -> Auth -> user ( 'org_id' )) {
throw new NotFoundException ( 'Invalid sighting.' );
}
}
$result = $this -> Sighting -> delete ( $sighting [ 'Sighting' ][ 'id' ]);
if ( ! $result ) {
return $this -> RestResponse -> saveFailResponse ( 'Sighting' , 'delete' , $id , 'Could not delete the Sighting.' );
} else {
return $this -> RestResponse -> saveSuccessResponse ( 'Sighting' , 'delete' , $id , false , 'Sighting successfuly deleted.' );
}
}
2017-01-05 20:48:03 +01:00
2018-07-19 11:48:22 +02:00
public function index ( $eventid = false )
{
$this -> loadModel ( 'Event' );
$sightingConditions = array ();
if ( $eventid ) {
$sightingConditions = array ( 'Sighting.event_id' => $eventid );
}
$sightedEvents = $this -> Sighting -> find ( 'list' , array (
'group' => 'Sighting.event_id' ,
'fields' => array ( 'Sighting.event_id' ),
'conditions' => $sightingConditions
));
if ( empty ( $sightedEvents )) {
$this -> RestResponse -> viewData ( array ());
}
$conditions = array ( 'metadata' => true , 'contain' => false );
if ( $eventid ) {
$conditions [ 'eventid' ] = $sightedEvents ;
}
$events = $this -> Event -> fetchEventIds ( $this -> Auth -> user (), false , false , false , false , false , false , $sightedEvents );
$sightings = array ();
if ( ! empty ( $events )) {
foreach ( $events as $k => $event ) {
$sightings = array_merge ( $sightings , $this -> Sighting -> attachToEvent ( $event , $this -> Auth -> user ()));
}
}
return $this -> RestResponse -> viewData ( $sightings );
}
2017-02-06 14:08:55 +01:00
2018-10-23 11:24:03 +02:00
public function restSearch ( $context = false )
2018-10-22 23:27:58 +02:00
{
2018-10-23 13:06:37 +02:00
$allowedContext = array ( false , 'event' , 'attribute' );
2018-10-23 18:26:10 +02:00
$paramArray = array ( 'returnFormat' , 'id' , 'type' , 'from' , 'to' , 'last' , 'org_id' , 'source' , 'includeAttribute' , 'includeEvent' );
2018-10-22 23:27:58 +02:00
$filterData = array (
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'paramArray' => $paramArray ,
'ordered_url_params' => compact ( $paramArray )
);
$filters = $this -> _harvestParameters ( $filterData , $exception );
2018-10-23 13:06:37 +02:00
2018-10-23 13:39:29 +02:00
// validate context
2018-10-23 13:06:37 +02:00
if ( ! in_array ( $context , $allowedContext , true )) {
throw new MethodNotAllowedException ( _ ( 'Invalid context.' ));
}
2018-10-23 13:39:29 +02:00
// ensure that an id is provided if context is set
2018-10-23 13:06:37 +02:00
if ( $context !== false && ! isset ( $filters [ 'id' ])) {
throw new MethodNotAllowedException ( _ ( 'An id must be provided if the context is set.' ));
}
2018-10-22 23:27:58 +02:00
$filters [ 'context' ] = $context ;
2018-10-23 11:24:03 +02:00
if ( isset ( $filters [ 'returnFormat' ])) {
$returnFormat = $filters [ 'returnFormat' ];
}
if ( $returnFormat === 'download' ) {
$returnFormat = 'json' ;
}
2018-10-23 12:17:54 +02:00
$sightings = $this -> Sighting -> restSearch ( $this -> Auth -> user (), $returnFormat , $filters );
2018-10-23 11:24:03 +02:00
$validFormats = $this -> Sighting -> validFormats ;
$responseType = $validFormats [ $returnFormat ][ 0 ];
return $this -> RestResponse -> viewData ( $sightings , $responseType , false , true );
2018-10-22 23:27:58 +02:00
}
2018-07-19 11:48:22 +02:00
public function listSightings ( $id , $context = 'attribute' , $org_id = false )
{
$this -> loadModel ( 'Event' );
$rawId = $id ;
$id = $this -> Sighting -> explodeIdList ( $id );
if ( $context === 'attribute' ) {
$object = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array ( 'conditions' => array ( 'Attribute.id' => $id , 'Attribute.deleted' => 0 ), 'flatten' => 1 ));
} else {
// let's set the context to event here, since we reuse the variable later on for some additional lookups.
// Passing $context = 'org' could have interesting results otherwise...
$context = 'event' ;
$object = $this -> Event -> fetchEvent ( $this -> Auth -> user (), $options = array ( 'eventid' => $id , 'metadata' => true ));
}
if ( empty ( $object )) {
throw new MethodNotAllowedException ( 'Invalid object.' );
}
$conditions = array (
'Sighting.' . $context . '_id' => $id
);
if ( $org_id ) {
$conditions [] = array ( 'Sighting.org_id' => $org_id );
}
$sightings = $this -> Sighting -> find ( 'all' , array (
'conditions' => $conditions ,
'recursive' => - 1 ,
'contain' => array ( 'Organisation.name' ),
'order' => array ( 'Sighting.date_sighting DESC' )
));
2019-02-28 20:27:36 +01:00
if ( ! empty ( $sightings ) && empty ( Configure :: read ( 'Plugin.Sightings_policy' )) && ! $this -> _isSiteAdmin ()) {
$eventOwnerOrgIdList = array ();
foreach ( $sightings as $k => $sighting ) {
if ( empty ( $eventOwnerOrgIdList [ $sighting [ 'Sighting' ][ 'event_id' ]])) {
$temp_event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array ( 'Event.id' => $sighting [ 'Sighting' ][ 'event_id' ]),
'fields' => array ( 'Event.id' , 'Event.orgc_id' )
));
$eventOwnerOrgIdList [ $temp_event [ 'Event' ][ 'id' ]] = $temp_event [ 'Event' ][ 'orgc_id' ];
}
if ( empty ( $eventOwnerOrgIdList [ $sighting [ 'Sighting' ][ 'event_id' ]]) || $eventOwnerOrgIdList [ $sighting [ 'Sighting' ][ 'event_id' ]] !== $this -> Auth -> user ( 'org_id' )) {
unset ( $sightings [ $k ]);
}
}
$sightings = array_values ( $sightings );
} else if ( ! empty ( $sightings ) && Configure :: read ( 'Plugin.Sightings_policy' ) == 1 && ! $this -> _isSiteAdmin ()) {
$eventsWithOwnSightings = array ();
foreach ( $sightings as $k => $sighting ) {
if ( empty ( $eventsWithOwnSightings [ $sighting [ 'Sighting' ][ 'event_id' ]])) {
$eventsWithOwnSightings [ $sighting [ 'Sighting' ][ 'event_id' ]] = false ;
$sighting_temp = $this -> Sighting -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array (
'Sighting.event_id' => $sighting [ 'Sighting' ][ 'event_id' ],
'Sighting.org_id' => $this -> Auth -> user ( 'org_id' )
)
));
if ( empty ( $sighting_temp )) {
$temp_event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array (
'Event.id' => $sighting [ 'Sighting' ][ 'event_id' ],
'Event.orgc_id' => $this -> Auth -> user ( 'org_id' )
),
'fields' => array ( 'Event.id' , 'Event.orgc_id' )
));
$eventsWithOwnSightings [ $sighting [ 'Sighting' ][ 'event_id' ]] = ! empty ( $temp_event );
} else {
$eventsWithOwnSightings [ $sighting [ 'Sighting' ][ 'event_id' ]] = true ;
}
}
if ( ! $eventsWithOwnSightings [ $sighting [ 'Sighting' ][ 'event_id' ]]) {
unset ( $sightings [ $k ]);
}
}
$sightings = array_values ( $sightings );
}
2018-07-19 11:48:22 +02:00
$this -> set ( 'org_id' , $org_id );
$this -> set ( 'rawId' , $rawId );
$this -> set ( 'context' , $context );
$this -> set ( 'types' , array ( 'Sighting' , 'False-positive' , 'Expiration' ));
if ( Configure :: read ( 'Plugin.Sightings_anonymise' ) && ! $this -> _isSiteAdmin ()) {
2019-02-28 20:27:36 +01:00
if ( ! empty ( $sightings )) {
foreach ( $sightings as $k => $v ) {
if ( $v [ 'Sighting' ][ 'org_id' ] != $this -> Auth -> user ( 'org_id' )) {
$sightings [ $k ][ 'Organisation' ][ 'name' ] = '' ;
$sightings [ $k ][ 'Sighting' ][ 'org_id' ] = 0 ;
}
2018-07-19 11:48:22 +02:00
}
}
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $sightings , $this -> response -> type ());
}
2019-02-28 20:27:36 +01:00
$this -> set ( 'sightings' , empty ( $sightings ) ? array () : $sightings );
2018-07-19 11:48:22 +02:00
$this -> layout = false ;
$this -> render ( 'ajax/list_sightings' );
}
2017-02-16 22:41:22 +01:00
2018-07-19 11:48:22 +02:00
public function viewSightings ( $id , $context = 'attribute' )
{
$this -> loadModel ( 'Event' );
$id = $this -> Sighting -> explodeIdList ( $id );
if ( $context === 'attribute' ) {
$attribute_id = $id ;
$object = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array ( 'conditions' => array ( 'Attribute.id' => $id , 'Attribute.deleted' => 0 ), 'flatten' => 1 ));
if ( empty ( $object )) {
throw new MethodNotAllowedException ( 'Invalid object.' );
}
$eventIds = array ();
foreach ( $object as $k => $v ) {
$eventIds [] = $v [ 'Attribute' ][ 'event_id' ];
}
$events = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $eventIds ));
} else {
$attribute_id = false ;
// let's set the context to event here, since we reuse the variable later on for some additional lookups.
// Passing $context = 'org' could have interesting results otherwise...
$context = 'event' ;
$events = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $id ));
}
if ( empty ( $events )) {
throw new MethodNotAllowedException ( 'Invalid object.' );
}
$results = array ();
$raw = array ();
foreach ( $events as $event ) {
$raw = array_merge ( $raw , $this -> Sighting -> attachToEvent ( $event , $this -> Auth -> user (), $attribute_id ));
}
foreach ( $raw as $sighting ) {
$results [ $sighting [ 'type' ]][ date ( 'Ymd' , $sighting [ 'date_sighting' ])][] = $sighting ;
}
$tsv = 'date\tSighting\tFalse-positive\n' ;
$dataPoints = array ();
$startDate = ( date ( 'Ymd' ));
$details = array ();
$range = ( ! empty ( Configure :: read ( 'MISP.Sightings_range' )) && is_numeric ( Configure :: read ( 'MISP.Sightings_range' ))) ? Configure :: read ( 'MISP.Sightings_range' ) : 365 ;
$range = date ( 'Ymd' , strtotime ( " - " . $range . " days " , time ()));
foreach ( $results as $type => $data ) {
foreach ( $data as $date => $sighting ) {
if ( $date < $startDate ) {
if ( $date >= $range ) {
$startDate = $date ;
}
}
$temp = array ();
foreach ( $sighting as $sightingInstance ) {
if ( ! isset ( $sightingInstance [ 'Organisation' ][ 'name' ])) {
$org = 'Anonymised' ;
} else {
$org = $sightingInstance [ 'Organisation' ][ 'name' ];
}
$temp [ $org ] = isset ( $temp [ $org ]) ? $temp [ $org ] + 1 : 1 ;
}
$dataPoints [ $date ][ $type ] = array ( 'count' => count ( $sighting ), 'details' => $temp );
}
}
$startDate = date ( 'Ymd' , strtotime ( " -3 days " , strtotime ( $startDate )));
for ( $i = $startDate ; $i < date ( 'Ymd' ) + 1 ; $i ++ ) {
if ( checkdate ( substr ( $i , 4 , 2 ), substr ( $i , 6 , 2 ), substr ( $i , 0 , 4 ))) {
$tsv .= $i . '\t' . ( isset ( $dataPoints [ $i ][ 0 ][ 'count' ]) ? $dataPoints [ $i ][ 0 ][ 'count' ] : 0 ) . '\t' . ( isset ( $dataPoints [ $i ][ 1 ][ 'count' ]) ? $dataPoints [ $i ][ 1 ][ 'count' ] : 0 ) . '\n' ;
$details [ $i ][ 0 ] = isset ( $dataPoints [ $i ][ 0 ][ 'details' ]) ? $dataPoints [ $i ][ 0 ][ 'details' ] : array ();
$details [ $i ][ 1 ] = isset ( $dataPoints [ $i ][ 1 ][ 'details' ]) ? $dataPoints [ $i ][ 1 ][ 'details' ] : array ();
}
}
$this -> set ( 'tsv' , $tsv );
$this -> set ( 'results' , $results );
$this -> layout = 'ajax' ;
$this -> render ( 'ajax/view_sightings' );
}
2015-12-16 00:48:30 +01:00
}