json_last_error_msg(), '_type' => gettype( $context ) ] ); } } $mdb -> insert( 'logs', [ 'level' => $level, 'source' => trim( (string) $source ), 'client_id' => $client_id !== null ? (int) $client_id : null, 'message' => (string) $message, 'context_json' => $context_json ] ); return (int) $mdb -> id(); } static public function get_data( $start, $length, $filters = [] ) { global $mdb; $start = max( 0, (int) $start ); $length = max( 1, min( 100, (int) $length ) ); $where_parts = []; $params = []; if ( !empty( $filters['level'] ) ) { $where_parts[] = 'l.level = :level'; $params[':level'] = (string) $filters['level']; } if ( !empty( $filters['source'] ) ) { $where_parts[] = 'l.source = :source'; $params[':source'] = (string) $filters['source']; } if ( !empty( $filters['date_from'] ) ) { $where_parts[] = 'l.date_add >= :date_from'; $params[':date_from'] = (string) $filters['date_from'] . ' 00:00:00'; } if ( !empty( $filters['date_to'] ) ) { $where_parts[] = 'l.date_add <= :date_to'; $params[':date_to'] = (string) $filters['date_to'] . ' 23:59:59'; } $where_sql = ''; if ( !empty( $where_parts ) ) { $where_sql = 'WHERE ' . implode( ' AND ', $where_parts ); } $sql = "SELECT l.*, c.name AS client_name FROM logs AS l LEFT JOIN clients AS c ON c.id = l.client_id {$where_sql} ORDER BY l.date_add DESC LIMIT {$start}, {$length}"; return $mdb -> query( $sql, $params ) -> fetchAll( \PDO::FETCH_ASSOC ); } static public function get_records_total( $filters = [] ) { global $mdb; $where_parts = []; $params = []; if ( !empty( $filters['level'] ) ) { $where_parts[] = 'level = :level'; $params[':level'] = (string) $filters['level']; } if ( !empty( $filters['source'] ) ) { $where_parts[] = 'source = :source'; $params[':source'] = (string) $filters['source']; } if ( !empty( $filters['date_from'] ) ) { $where_parts[] = 'date_add >= :date_from'; $params[':date_from'] = (string) $filters['date_from'] . ' 00:00:00'; } if ( !empty( $filters['date_to'] ) ) { $where_parts[] = 'date_add <= :date_to'; $params[':date_to'] = (string) $filters['date_to'] . ' 23:59:59'; } $where_sql = ''; if ( !empty( $where_parts ) ) { $where_sql = 'WHERE ' . implode( ' AND ', $where_parts ); } $row = $mdb -> query( "SELECT COUNT(*) AS cnt FROM logs {$where_sql}", $params ) -> fetch( \PDO::FETCH_ASSOC ); return (int) ( $row['cnt'] ?? 0 ); } static public function get_one( $id ) { global $mdb; return $mdb -> query( "SELECT l.*, c.name AS client_name FROM logs AS l LEFT JOIN clients AS c ON c.id = l.client_id WHERE l.id = :id", [ ':id' => (int) $id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static public function cleanup_old( $days = 30 ) { global $mdb; $days = max( 1, (int) $days ); $mdb -> query( "DELETE FROM logs WHERE date_add < DATE_SUB( NOW(), INTERVAL {$days} DAY )" ); } static public function get_sources() { global $mdb; $rows = $mdb -> query( "SELECT DISTINCT source FROM logs WHERE source != '' ORDER BY source ASC" ) -> fetchAll( \PDO::FETCH_COLUMN ); return is_array( $rows ) ? $rows : []; } }