2020-08-31 14:37:22 +00:00
< ? php
2022-06-01 19:46:18 +00:00
ini_set ( 'display_errors' , '' );
2020-10-19 12:50:11 +00:00
$message = '' ;
$data = array ();
//
// INITIALIZE AND CHECK SANITY
//
2021-10-25 16:34:28 +00:00
if ( ! canView ( 'Events' ))
2023-04-23 16:57:29 +00:00
$message = 'Insufficient permissions for user ' . $user -> Username () . '<br/>' ;
2020-10-19 12:50:11 +00:00
2021-10-25 16:34:28 +00:00
if ( empty ( $_REQUEST [ 'task' ])) {
$message = 'Must specify a task<br/>' ;
2020-10-19 12:50:11 +00:00
} else {
$task = $_REQUEST [ 'task' ];
}
2020-08-31 14:37:22 +00:00
2021-10-25 16:34:28 +00:00
if ( empty ( $_REQUEST [ 'eids' ])) {
if ( isset ( $_REQUEST [ 'task' ]) && $_REQUEST [ 'task' ] != 'query' )
$message = 'No event id(s) supplied<br/>' ;
2020-10-19 12:50:11 +00:00
} else {
$eids = $_REQUEST [ 'eids' ];
}
2021-10-25 16:34:28 +00:00
if ( $message ) {
2020-10-19 12:50:11 +00:00
ajaxError ( $message );
return ;
}
2020-11-05 17:20:49 +00:00
require_once ( 'includes/Filter.php' );
2020-10-23 21:55:43 +00:00
$filter = isset ( $_REQUEST [ 'filter' ]) ? ZM\Filter :: parse ( $_REQUEST [ 'filter' ]) : new ZM\Filter ();
2023-04-23 17:26:03 +00:00
if ( count ( $user -> unviewableMonitorIds ())) {
2023-04-23 16:57:29 +00:00
$filter = $filter -> addTerm ( array ( 'cnj' => 'and' , 'attr' => 'MonitorId' , 'op' => 'IN' , 'val' => $user -> viewableMonitorIds ()));
2020-10-23 21:55:43 +00:00
}
2022-12-05 21:16:55 +00:00
if ( ! empty ( $_REQUEST [ 'StartDateTime' ])) {
$filter -> addTerm ( array ( 'cnj' => 'and' , 'attr' => 'StartDateTime' , 'op' => '>=' , 'val' => $_REQUEST [ 'StartDateTime' ]));
}
if ( ! empty ( $_REQUEST [ 'EndDateTime' ])) {
$filter -> addTerm ( array ( 'cnj' => 'and' , 'attr' => 'EndDateTime' , 'op' => '<=' , 'val' => $_REQUEST [ 'EndDateTime' ]));
}
if ( ! empty ( $_REQUEST [ 'MonitorId' ])) {
$filter -> addTerm ( array ( 'cnj' => 'and' , 'attr' => 'MonitorId' , 'op' => '=' , 'val' => $_REQUEST [ 'MonitorId' ]));
}
2020-10-23 21:55:43 +00:00
2020-10-19 12:50:11 +00:00
// Search contains a user entered string to search on
$search = isset ( $_REQUEST [ 'search' ]) ? $_REQUEST [ 'search' ] : '' ;
// Advanced search contains an array of "column name" => "search text" pairs
// Bootstrap table sends json_ecoded array, which we must decode
2020-10-23 20:44:50 +00:00
$advsearch = isset ( $_REQUEST [ 'advsearch' ]) ? json_decode ( $_REQUEST [ 'advsearch' ], JSON_OBJECT_AS_ARRAY ) : array ();
2020-10-19 12:50:11 +00:00
2021-06-15 14:33:42 +00:00
// Order specifies the sort direction, either asc or desc
2021-10-25 16:34:28 +00:00
$order = $filter -> sort_asc () ? 'ASC' : 'DESC' ;
if ( isset ( $_REQUEST [ 'order' ])) {
2021-10-28 05:43:44 +00:00
if ( strtolower ( $_REQUEST [ 'order' ]) == 'asc' ) {
2021-10-25 16:34:28 +00:00
$order = 'ASC' ;
2021-10-28 05:43:44 +00:00
} else if ( strtolower ( $_REQUEST [ 'order' ]) == 'desc' ) {
2021-10-25 16:34:28 +00:00
$order = 'DESC' ;
} else {
2021-12-13 20:00:35 +00:00
Warning ( 'Invalid value for order ' . $_REQUEST [ 'order' ]);
2021-10-25 16:34:28 +00:00
}
}
2021-06-15 14:33:42 +00:00
2020-10-19 12:50:11 +00:00
// Sort specifies the name of the column to sort on
2021-10-25 16:34:28 +00:00
$sort = $filter -> sort_field ();
2021-06-15 14:33:42 +00:00
if ( isset ( $_REQUEST [ 'sort' ])) {
2020-10-22 18:27:47 +00:00
$sort = $_REQUEST [ 'sort' ];
2020-08-31 14:37:22 +00:00
}
2020-10-19 12:50:11 +00:00
// Offset specifies the starting row to return, used for pagination
$offset = 0 ;
2021-11-09 15:48:50 +00:00
if ( isset ( $_REQUEST [ 'offset' ])) {
if (( ! is_int ( $_REQUEST [ 'offset' ]) and ! ctype_digit ( $_REQUEST [ 'offset' ]))) {
2020-10-19 12:50:11 +00:00
ZM\Error ( 'Invalid value for offset: ' . $_REQUEST [ 'offset' ]);
} else {
$offset = $_REQUEST [ 'offset' ];
}
}
// Limit specifies the number of rows to return
2020-11-14 16:27:33 +00:00
// Set the default to 0 for events view, to prevent an issue with ALL pagination
$limit = 0 ;
2021-11-09 15:48:50 +00:00
if ( isset ( $_REQUEST [ 'limit' ])) {
if (( ! is_int ( $_REQUEST [ 'limit' ]) and ! ctype_digit ( $_REQUEST [ 'limit' ]))) {
2020-10-19 12:50:11 +00:00
ZM\Error ( 'Invalid value for limit: ' . $_REQUEST [ 'limit' ]);
} else {
$limit = $_REQUEST [ 'limit' ];
}
}
//
// MAIN LOOP
//
2021-11-09 15:48:50 +00:00
switch ( $task ) {
2020-10-19 12:50:11 +00:00
case 'archive' :
2021-11-09 15:48:50 +00:00
foreach ( $eids as $eid ) archiveRequest ( $task , $eid );
2020-12-08 15:33:25 +00:00
break ;
2020-10-19 12:50:11 +00:00
case 'unarchive' :
2020-12-08 15:33:25 +00:00
# The idea is that anyone can archive, but only people with Event Edit permission can unarchive..
2021-11-09 15:48:50 +00:00
if ( ! canEdit ( 'Events' )) {
2023-04-23 16:57:29 +00:00
ajaxError ( 'Insufficient permissions for user ' . $user -> Username ());
2020-12-08 15:33:25 +00:00
return ;
}
2021-11-09 15:48:50 +00:00
foreach ( $eids as $eid ) archiveRequest ( $task , $eid );
2020-10-19 12:50:11 +00:00
break ;
case 'delete' :
2021-11-09 15:48:50 +00:00
if ( ! canEdit ( 'Events' )) {
2023-04-23 16:57:29 +00:00
ajaxError ( 'Insufficient permissions for user ' . $user -> Username ());
2020-12-08 15:33:25 +00:00
return ;
}
2022-06-06 17:09:35 +00:00
foreach ( $eids as $eid ) {
$message = deleteRequest ( $eid );
if ( count ( $message )) {
$data [] = $message ;
}
}
2020-10-19 12:50:11 +00:00
break ;
case 'query' :
2020-10-23 21:55:43 +00:00
$data = queryRequest ( $filter , $search , $advsearch , $sort , $offset , $order , $limit );
2020-10-19 12:50:11 +00:00
break ;
default :
ZM\Fatal ( " Unrecognised task ' $task ' " );
} // end switch task
ajaxResponse ( $data );
2020-08-31 14:37:22 +00:00
2020-10-19 12:50:11 +00:00
//
// FUNCTION DEFINITIONS
//
function archiveRequest ( $task , $eid ) {
$archiveVal = ( $task == 'archive' ) ? 1 : 0 ;
dbQuery (
'UPDATE Events SET Archived = ? WHERE Id = ?' ,
array ( $archiveVal , $eid )
);
}
function deleteRequest ( $eid ) {
2020-08-31 14:37:22 +00:00
$message = array ();
2020-10-19 12:50:11 +00:00
$event = new ZM\Event ( $eid );
if ( ! $event -> Id () ) {
$message [] = array ( $eid => 'Event not found.' );
} else if ( $event -> Archived () ) {
$message [] = array ( $eid => 'Event is archived, cannot delete it.' );
2021-11-09 15:48:50 +00:00
} else if ( ! $event -> canEdit ()) {
$message [] = array ( $eid => 'You do not have permission to delete event ' . $event -> Id ());
2020-10-19 12:50:11 +00:00
} else {
$event -> delete ();
}
return $message ;
}
2020-10-23 21:55:43 +00:00
function queryRequest ( $filter , $search , $advsearch , $sort , $offset , $order , $limit ) {
2022-06-01 19:46:18 +00:00
global $dateTimeFormatter ;
2020-10-26 13:58:47 +00:00
$data = array (
'total' => 0 ,
'totalNotFiltered' => 0 ,
'rows' => array (),
2022-06-01 19:46:18 +00:00
'updated' => $dateTimeFormatter -> format ( time ())
2020-10-26 13:58:47 +00:00
);
2022-07-29 17:59:01 +00:00
if ( ! $filter -> test_pre_sql_conditions ()) {
2020-10-26 13:58:47 +00:00
ZM\Debug ( 'Pre conditions failed, not doing sql' );
return $data ;
}
2020-10-19 12:50:11 +00:00
// Put server pagination code here
// The table we want our data from
$table = 'Events' ;
2020-08-31 14:37:22 +00:00
2020-10-23 15:21:32 +00:00
// The names of the dB columns in the events table we are interested in
2020-11-04 18:58:03 +00:00
$columns = array ( 'Id' , 'MonitorId' , 'StorageId' , 'Name' , 'Cause' , 'StartDateTime' , 'EndDateTime' , 'Length' , 'Frames' , 'AlarmFrames' , 'TotScore' , 'AvgScore' , 'MaxScore' , 'Archived' , 'Emailed' , 'Notes' , 'DiskSpace' );
2020-10-19 12:50:11 +00:00
2020-10-22 18:27:47 +00:00
// The names of columns shown in the event view that are NOT dB columns in the database
2020-10-19 12:50:11 +00:00
$col_alt = array ( 'Monitor' , 'Storage' );
2021-12-13 20:00:35 +00:00
if ( $sort != '' ) {
if ( ! in_array ( $sort , array_merge ( $columns , $col_alt ))) {
ZM\Error ( 'Invalid sort field: ' . $sort );
$sort = '' ;
} else if ( $sort == 'Monitor' ) {
$sort = 'M.Name' ;
2022-04-13 21:18:59 +00:00
} else if ( $sort == 'EndDateTime' ) {
if ( $order == 'ASC' ) {
$sort = 'E.EndDateTime IS NULL, E.EndDateTime' ;
} else {
$sort = 'E.EndDateTime IS NOT NULL, E.EndDateTime' ;
}
2021-12-13 20:00:35 +00:00
} else {
$sort = 'E.' . $sort ;
}
2020-10-22 18:27:47 +00:00
}
2020-11-05 17:20:49 +00:00
$values = array ();
2020-10-19 12:50:11 +00:00
$likes = array ();
2020-11-05 17:20:49 +00:00
$where = $filter -> sql () ? ' WHERE (' . $filter -> sql () . ')' : '' ;
2020-10-19 12:50:11 +00:00
2023-05-12 19:13:48 +00:00
$col_str = ' E .* , UNIX_TIMESTAMP ( E . StartDateTime ) AS StartTimeSecs ,
CASE WHEN E . EndDateTime IS NULL THEN ( SELECT NOW ()) ELSE E . EndDateTime END AS EndDateTime ,
CASE WHEN E . EndDateTime IS NULL THEN ( SELECT UNIX_TIMESTAMP ( NOW ())) ELSE UNIX_TIMESTAMP ( EndDateTime ) END AS EndTimeSecs ,
M . Name AS Monitor ' ;
2021-12-13 20:00:35 +00:00
$sql = 'SELECT ' . $col_str . ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id' . $where . ( $sort ? ' ORDER BY ' . $sort . ' ' . $order : '' );
2022-07-29 17:59:01 +00:00
if ( $filter -> limit () and ! count ( $filter -> post_sql_conditions ())) {
2022-02-02 15:49:05 +00:00
$sql .= ' LIMIT ' . $filter -> limit ();
}
2020-10-19 12:50:11 +00:00
$storage_areas = ZM\Storage :: find ();
$StorageById = array ();
2021-11-09 15:48:50 +00:00
foreach ( $storage_areas as $S ) {
2020-10-19 12:50:11 +00:00
$StorageById [ $S -> Id ()] = $S ;
}
2020-11-05 17:20:49 +00:00
$unfiltered_rows = array ();
$event_ids = array ();
2021-01-16 18:17:31 +00:00
ZM\Debug ( 'Calling the following sql query: ' . $sql );
$query = dbQuery ( $sql , $values );
2021-11-09 15:48:50 +00:00
if ( ! $query ) {
ajaxError ( dbError ( $sql ));
return ;
2020-11-05 17:20:49 +00:00
}
2021-11-09 15:48:50 +00:00
while ( $row = dbFetchNext ( $query )) {
$event = new ZM\Event ( $row );
$event -> remove_from_cache ();
if ( ! $filter -> test_post_sql_conditions ( $event )) {
continue ;
}
$event_ids [] = $event -> Id ();
$unfiltered_rows [] = $row ;
} # end foreach row
2020-11-05 17:20:49 +00:00
2022-02-02 15:49:05 +00:00
# Filter limits come before pagination limits.
if ( $filter -> limit () and ( $filter -> limit () > count ( $unfiltered_rows ))) {
ZM\Debug ( " Filtering rows due to filter->limit " . count ( $unfiltered_rows ) . " limit: " . $filter -> limit ());
$unfiltered_rows = array_slice ( $unfiltered_rows , 0 , $filter -> limit ());
}
2020-11-13 13:24:17 +00:00
ZM\Debug ( 'Have ' . count ( $unfiltered_rows ) . ' events matching base filter.' );
2020-11-05 17:20:49 +00:00
$filtered_rows = null ;
2021-11-09 15:48:50 +00:00
if ( count ( $advsearch ) or $search != '' ) {
2020-11-05 17:20:49 +00:00
$search_filter = new ZM\Filter ();
$search_filter = $search_filter -> addTerm ( array ( 'cnj' => 'and' , 'attr' => 'Id' , 'op' => 'IN' , 'val' => $event_ids ));
// There are two search bars in the log view, normal and advanced
// Making an exuctive decision to ignore the normal search, when advanced search is in use
// Alternatively we could try to do both
2021-11-09 15:48:50 +00:00
if ( count ( $advsearch )) {
2020-11-05 17:20:49 +00:00
$terms = array ();
2021-11-09 15:48:50 +00:00
foreach ( $advsearch as $col => $text ) {
2020-11-05 17:20:49 +00:00
$terms [] = array ( 'cnj' => 'and' , 'attr' => $col , 'op' => 'LIKE' , 'val' => $text );
} # end foreach col in advsearch
$terms [ 0 ][ 'obr' ] = 1 ;
$terms [ count ( $terms ) - 1 ][ 'cbr' ] = 1 ;
$search_filter -> addTerms ( $terms );
2021-11-09 15:48:50 +00:00
} else if ( $search != '' ) {
2020-11-05 17:20:49 +00:00
$search = '%' . $search . '%' ;
$terms = array ();
2021-11-09 15:48:50 +00:00
foreach ( $columns as $col ) {
2023-05-12 19:13:48 +00:00
$terms [] = array ( 'cnj' => 'or' , 'attr' => $col , 'op' => 'LIKE' , 'val' => strtolower ( $search ), 'collate' => 'utf8mb4_general_ci' );
2020-11-05 17:20:49 +00:00
}
$terms [ 0 ][ 'obr' ] = 1 ;
$terms [ 0 ][ 'cnj' ] = 'and' ;
$terms [ count ( $terms ) - 1 ][ 'cbr' ] = 1 ;
$search_filter = $search_filter -> addTerms ( $terms , array ( 'obr' => 1 , 'cbr' => 1 , 'op' => 'OR' ));
} # end if search
$sql = 'SELECT ' . $col_str . ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE ' . $search_filter -> sql () . ' ORDER BY ' . $sort . ' ' . $order ;
$filtered_rows = dbFetchAll ( $sql );
2021-11-02 21:23:23 +00:00
ZM\Debug ( 'Have ' . count ( $filtered_rows ) . ' events matching search filter: ' . $sql );
2020-11-05 17:20:49 +00:00
} else {
$filtered_rows = $unfiltered_rows ;
} # end if search_filter->terms() > 1
2022-11-03 21:48:39 +00:00
if ( $limit and $limit < count ( $filtered_rows )) {
2022-02-02 15:49:05 +00:00
ZM\Debug ( " Filtering rows due to limit " . count ( $filtered_rows ) . " offset: $offset limit: $limit " );
2021-11-02 21:23:23 +00:00
$filtered_rows = array_slice ( $filtered_rows , $offset , $limit );
2022-02-02 15:49:05 +00:00
}
2021-11-02 21:23:23 +00:00
2020-11-05 17:20:49 +00:00
$returned_rows = array ();
2021-11-02 21:23:23 +00:00
foreach ( $filtered_rows as $row ) {
2020-11-05 17:20:49 +00:00
$event = new ZM\Event ( $row );
2023-05-12 19:13:48 +00:00
$event -> remove_from_cache ();
if ( ! $event -> canView ()) continue ;
2023-04-22 13:37:53 +00:00
if ( $event -> Monitor () -> Deleted ()) continue ;
2020-11-05 17:20:49 +00:00
2020-10-20 17:59:30 +00:00
$scale = intval ( 5 * 100 * ZM_WEB_LIST_THUMB_WIDTH / $event -> Width ());
2020-12-08 16:26:43 +00:00
$imgSrc = $event -> getThumbnailSrc ( array (), '&' );
2020-10-20 17:13:12 +00:00
$streamSrc = $event -> getStreamSrc ( array (
2020-10-29 13:39:48 +00:00
'mode' => 'jpeg' , 'scale' => $scale , 'maxfps' => ZM_WEB_VIDEO_MAXFPS , 'replay' => 'single' , 'rate' => '400' ), '&' );
2020-10-20 17:13:12 +00:00
2020-10-19 12:50:11 +00:00
// Modify the row data as needed
2022-02-15 18:00:26 +00:00
$row [ 'imgHtml' ] = '<img id="thumbnail' . $event -> Id () . '" src="' . $imgSrc . '" alt="Event ' . $event -> Id () . '" width="' . validInt ( $event -> ThumbnailWidth ()) . '" height="' . validInt ( $event -> ThumbnailHeight ()) . '" stream_src="' . $streamSrc . '" still_src="' . $imgSrc . '" loading="lazy" />' ;
2023-04-27 17:46:41 +00:00
$row [ 'imgWidth' ] = validInt ( $event -> ThumbnailWidth ());
$row [ 'imgHeight' ] = validInt ( $event -> ThumbnailHeight ());
2020-10-19 19:18:21 +00:00
$row [ 'Name' ] = validHtmlStr ( $row [ 'Name' ]);
$row [ 'Archived' ] = $row [ 'Archived' ] ? translate ( 'Yes' ) : translate ( 'No' );
$row [ 'Emailed' ] = $row [ 'Emailed' ] ? translate ( 'Yes' ) : translate ( 'No' );
$row [ 'Cause' ] = validHtmlStr ( $row [ 'Cause' ]);
2022-06-01 19:46:18 +00:00
$row [ 'StartDateTime' ] = $dateTimeFormatter -> format ( strtotime ( $row [ 'StartDateTime' ]));
$row [ 'EndDateTime' ] = $row [ 'EndDateTime' ] ? $dateTimeFormatter -> format ( strtotime ( $row [ 'EndDateTime' ])) : null ;
2020-10-19 17:25:13 +00:00
$row [ 'Storage' ] = ( $row [ 'StorageId' ] and isset ( $StorageById [ $row [ 'StorageId' ]]) ) ? $StorageById [ $row [ 'StorageId' ]] -> Name () : 'Default' ;
2020-10-29 19:08:14 +00:00
$row [ 'Notes' ] = nl2br ( htmlspecialchars ( $row [ 'Notes' ]));
2020-10-24 12:50:59 +00:00
$row [ 'DiskSpace' ] = human_filesize ( $event -> DiskSpace ());
2020-11-05 17:20:49 +00:00
$returned_rows [] = $row ;
} # end foreach row matching search
2023-05-12 19:13:48 +00:00
$data [ 'rows' ] = & $returned_rows ;
2020-10-19 12:50:11 +00:00
2020-10-31 16:26:29 +00:00
# totalNotFiltered must equal total, except when either search bar has been used
2020-11-13 13:24:17 +00:00
$data [ 'totalNotFiltered' ] = count ( $unfiltered_rows );
2020-10-31 16:26:29 +00:00
if ( $search != '' || count ( $advsearch ) ) {
2020-11-05 17:20:49 +00:00
$data [ 'total' ] = count ( $filtered_rows );
2020-10-31 16:26:29 +00:00
} else {
2020-11-13 13:24:17 +00:00
$data [ 'total' ] = $data [ 'totalNotFiltered' ];
2020-10-31 16:26:29 +00:00
}
2023-05-12 19:13:48 +00:00
ZM\Debug ( " Done " );
2020-10-19 12:50:11 +00:00
return $data ;
}
2020-08-31 14:37:22 +00:00
?>