Gruby refaktor

This commit is contained in:
2026-02-05 12:06:38 +01:00
parent 998f4348f3
commit af828068a9
18 changed files with 3093 additions and 2696 deletions
+139
View File
@@ -0,0 +1,139 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Fetches and parses a GPX file from a URL to extract track points and elevation profile.
*
* @param string $gpx_url The URL of the GPX file.
* @return array An array containing 'points' for the map and 'elevation_profile'.
*/
function mystat_parse_gpx_data( $gpx_url ) {
if ( empty( $gpx_url ) ) {
return array();
}
$response = wp_remote_get( $gpx_url, array( 'timeout' => 20 ) );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) {
return array();
}
$gpx_content = wp_remote_retrieve_body( $response );
if ( empty( $gpx_content ) ) {
return array();
}
// --- Privacy Zone ---
$privacy_options = get_option( 'mystat_privacy_options' );
$privacy_enabled = ! empty( $privacy_options['latitude'] ) && ! empty( $privacy_options['longitude'] ) && ! empty( $privacy_options['radius'] );
$privacy_center_lat = $privacy_enabled ? (float) $privacy_options['latitude'] : 0;
$privacy_center_lon = $privacy_enabled ? (float) $privacy_options['longitude'] : 0;
$privacy_radius_km = $privacy_enabled ? ( (int) $privacy_options['radius'] ) / 1000 : 0; // Convert meters to km
libxml_use_internal_errors( true );
$gpx = simplexml_load_string( $gpx_content );
libxml_clear_errors();
if ( false === $gpx ) {
return array();
}
// Use XPath to be more robust against different GPX structures/namespaces
$gpx->registerXPathNamespace( 'gpx', 'http://www.topografix.com/GPX/1/1' );
$trackpoints = $gpx->xpath( '//gpx:trkpt' );
if ( empty( $trackpoints ) ) {
$trackpoints = $gpx->xpath( '//trkpt' ); // Fallback for files without namespace
}
$raw_points = array();
$start_time = null;
foreach ( $trackpoints as $trkpt ) {
if ( isset( $trkpt['lat'], $trkpt['lon'] ) ) {
$extensions = $trkpt->extensions ? $trkpt->extensions->children( 'gpxtpx', true ) : null;
$time = isset( $trkpt->time ) ? strtotime( (string) $trkpt->time ) : null;
if ( $time && is_null( $start_time ) ) {
$start_time = $time;
}
$hr_val = ( $extensions && isset( $extensions->TrackPointExtension->hr ) ) ? (int) $extensions->TrackPointExtension->hr : null;
$cad_val = ( $extensions && isset( $extensions->TrackPointExtension->cad ) ) ? (int) $extensions->TrackPointExtension->cad : null;
$raw_points[] = array(
'lat' => (float) $trkpt['lat'],
'lon' => (float) $trkpt['lon'],
'ele' => isset( $trkpt->ele ) ? (float) $trkpt->ele : null,
'time_offset' => $start_time && $time ? $time - $start_time : null,
'hr' => $hr_val,
'cad' => $cad_val,
);
}
}
if ( empty( $raw_points ) ) {
return array();
}
// Process raw points to calculate profiles
$map_points = array();
$profiles = array(
'distance' => array(),
'time' => array(),
'elevation' => array(),
'speed' => array(),
'hr' => array(),
'cadence' => array(),
);
$cumulative_distance = 0;
$haversine = function( $lat1, $lon1, $lat2, $lon2 ) {
$earth_radius = 6371; // in km
$dLat = deg2rad( $lat2 - $lat1 );
$dLon = deg2rad( $lon2 - $lon1 );
$a = sin( $dLat / 2 ) * sin( $dLat / 2 ) + cos( deg2rad( $lat1 ) ) * cos( deg2rad( $lat2 ) ) * sin( $dLon / 2 ) * sin( $dLon / 2 );
$c = 2 * atan2( sqrt( $a ), sqrt( 1 - $a ) );
return $earth_radius * $c;
};
foreach ( $raw_points as $i => $point ) {
$is_in_privacy_zone = false;
if ( $privacy_enabled ) {
$distance_from_center = $haversine( $privacy_center_lat, $privacy_center_lon, $point['lat'], $point['lon'] );
if ( $distance_from_center <= $privacy_radius_km ) {
$is_in_privacy_zone = true;
}
}
if ( ! $is_in_privacy_zone ) {
$map_points[] = array( $point['lat'], $point['lon'] );
$speed = null;
if ( $i > 0 ) {
$prev_point = $raw_points[ $i - 1 ];
$distance_delta = $haversine( $prev_point['lat'], $prev_point['lon'], $point['lat'], $point['lon'] ); // km
$cumulative_distance += $distance_delta;
if ( ! is_null( $point['time_offset'] ) && ! is_null( $prev_point['time_offset'] ) ) {
$time_delta = $point['time_offset'] - $prev_point['time_offset']; // seconds
if ( $time_delta > 0 ) {
$speed = ( $distance_delta * 3600 ) / $time_delta; // km/h
}
}
}
$profiles['distance'][] = round( $cumulative_distance, 3 );
$profiles['time'][] = $point['time_offset'];
$profiles['elevation'][] = ! is_null( $point['ele'] ) ? round( $point['ele'], 2 ) : null;
$profiles['speed'][] = ! is_null( $speed ) ? round( $speed, 1 ) : null;
$profiles['hr'][] = $point['hr'];
$profiles['cadence'][] = $point['cad'];
}
}
return array(
'points' => $map_points,
'profiles' => $profiles,
);
}