WP_REST_Server::READABLE, 'callback' => 'statpress_get_activities_api', 'permission_callback' => 'statpress_api_permissions_check', 'args' => array( 'page' => array( 'validate_callback' => 'is_numeric', ), 'per_page' => array( 'validate_callback' => 'is_numeric', ), ), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => 'statpress_create_activity_api', 'permission_callback' => 'statpress_api_permissions_check', ), ) ); // Route for a single activity register_rest_route( $namespace, '/activities/(?P[\d]+)', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => 'statpress_get_activity_api', 'permission_callback' => 'statpress_api_permissions_check', ), array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => 'statpress_update_activity_api', 'permission_callback' => 'statpress_api_permissions_check', ), array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => 'statpress_delete_activity_api', 'permission_callback' => 'statpress_api_permissions_check', ), ) ); // Route for parsing GPX file summary register_rest_route( $namespace, '/gpx/parse-summary', array( 'methods' => WP_REST_Server::CREATABLE, // Use POST to send URL in the body 'callback' => 'statpress_parse_gpx_summary_api', 'permission_callback' => 'statpress_api_permissions_check', 'args' => array( 'gpx_url' => array( 'required' => true, 'validate_callback' => 'esc_url_raw', ), ), ) ); } /** * Permission check for API endpoints. * * @return bool */ function statpress_api_permissions_check() { return current_user_can( 'manage_options' ); } /** * Get a collection of activities. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error */ function statpress_get_activities_api( WP_REST_Request $request ) { global $wpdb; $table_activities = $wpdb->prefix . 'statpress_activities'; $per_page = $request->get_param( 'per_page' ) ? (int) $request->get_param( 'per_page' ) : 20; $page = $request->get_param( 'page' ) ? (int) $request->get_param( 'page' ) : 1; $offset = ( $page - 1 ) * $per_page; // Get total items for pagination headers $total_items = (int) $wpdb->get_var( "SELECT COUNT(id) FROM $table_activities" ); $total_pages = ceil( $total_items / $per_page ); $sql = $wpdb->prepare( "SELECT a.*, c.name as category_name, et.name as event_type_name, eq.name as equipment_name FROM $table_activities a LEFT JOIN {$wpdb->prefix}statpress_categories c ON a.category_id = c.id LEFT JOIN {$wpdb->prefix}statpress_event_types et ON a.event_type_id = et.id LEFT JOIN {$wpdb->prefix}statpress_equipment eq ON a.equipment_id = eq.id ORDER BY a.date DESC, a.id DESC LIMIT %d OFFSET %d", $per_page, $offset ); $results = $wpdb->get_results( $sql ); $response = new WP_REST_Response( $results, 200 ); $response->header( 'X-WP-Total', $total_items ); $response->header( 'X-WP-TotalPages', $total_pages ); return $response; } /** * Get a single activity. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error */ function statpress_get_activity_api( WP_REST_Request $request ) { global $wpdb; $id = (int) $request['id']; // Use the same rich query as the collection endpoint for consistency. $sql = $wpdb->prepare( "SELECT a.*, c.name as category_name, et.name as event_type_name, eq.name as equipment_name FROM {$wpdb->prefix}statpress_activities a LEFT JOIN {$wpdb->prefix}statpress_categories c ON a.category_id = c.id LEFT JOIN {$wpdb->prefix}statpress_event_types et ON a.event_type_id = et.id LEFT JOIN {$wpdb->prefix}statpress_equipment eq ON a.equipment_id = eq.id WHERE a.id = %d", $id ); $activity = $wpdb->get_row( $sql ); if ( ! $activity ) { return new WP_Error( 'not_found', 'Activity not found', array( 'status' => 404 ) ); } return new WP_REST_Response( $activity, 200 ); } /** * Create a new activity. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error */ function statpress_create_activity_api( WP_REST_Request $request ) { $params = $request->get_json_params(); $activity_id = statpress_save_activity_data( $params ); if ( ! $activity_id ) { return new WP_Error( 'cant-create', 'Error creating activity', array( 'status' => 500 ) ); } // Create a new request object to fetch the newly created activity. $new_request = new WP_REST_Request(); $new_request->set_param( 'id', $activity_id ); $response = statpress_get_activity_api( $new_request ); $response->set_status( 201 ); // 201 Created return $response; } /** * Update an existing activity. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error */ function statpress_update_activity_api( WP_REST_Request $request ) { $id = (int) $request['id']; $params = $request->get_json_params(); $activity_id = statpress_save_activity_data( $params, $id ); if ( ! $activity_id ) { return new WP_Error( 'cant-update', 'Error updating activity', array( 'status' => 500 ) ); } return statpress_get_activity_api( $request ); } /** * Delete an activity. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error */ function statpress_delete_activity_api( WP_REST_Request $request ) { global $wpdb; $id = (int) $request['id']; $result = $wpdb->delete( $wpdb->prefix . 'statpress_activities', array( 'id' => $id ), array( '%d' ) ); if ( ! $result ) { return new WP_Error( 'cant-delete', 'Error deleting activity', array( 'status' => 500 ) ); } return new WP_REST_Response( array( 'message' => 'Activity deleted successfully.' ), 200 ); } /** * API callback to parse a GPX file and return its summary data. * * @param WP_REST_Request $request The request object. * @return WP_REST_Response|WP_Error A response object with summary data or an error. */ function statpress_parse_gpx_summary_api( WP_REST_Request $request ) { $params = $request->get_json_params(); $gpx_url = $params['gpx_url'] ?? ''; if ( empty( $gpx_url ) ) { return new WP_Error( 'no_url_provided', 'Nie podano adresu URL do pliku GPX.', array( 'status' => 400 ) ); } // This new function will do the heavy lifting of calculation. $summary = statpress_calculate_gpx_summary( $gpx_url ); if ( empty( $summary ) || ! $summary['distance'] > 0 ) { return new WP_Error( 'gpx_parse_error', 'Nie udało się przetworzyć pliku GPX. Sprawdź, czy plik jest poprawny i zawiera dane trasy.', array( 'status' => 400 ) ); } return new WP_REST_Response( $summary, 200 ); }