__( 'Missing field key.', 'repeaterkit' ) ), 400 ); } // Capability check. if ( $post_id > 0 && ! current_user_can( 'edit_post', $post_id ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'repeaterkit' ) ), 403 ); } elseif ( ! current_user_can( 'edit_posts' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'repeaterkit' ) ), 403 ); } $field = function_exists( 'acf_get_field' ) ? acf_get_field( $field_key ) : null; if ( ! $field ) { wp_send_json_error( array( 'message' => __( 'Field not found.', 'repeaterkit' ) ), 404 ); } // Fetch raw rows from storage. $raw_value = get_post_meta( $post_id, $field['name'], true ); $rows = Storage::load_rows( $raw_value, $field ); wp_send_json_success( array( 'field' => $field['name'], 'count' => count( $rows ), 'rows' => $rows, ) ); } /** * Import and validate rows from JSON. * * @return void */ public static function handle_import_rows(): void { check_ajax_referer( 'repeaterkit_ajax_nonce', 'nonce' ); $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0; $field_key = isset( $_POST['field_key'] ) ? sanitize_key( (string) $_POST['field_key'] ) : ''; $json_input = isset( $_POST['json_data'] ) ? wp_unslash( (string) $_POST['json_data'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized // Payload size check to prevent DoS. if ( strlen( $json_input ) > self::MAX_PAYLOAD_BYTES ) { wp_send_json_error( array( 'message' => __( 'Payload exceeds 500 KB limit.', 'repeaterkit' ) ), 413 ); } // Capability check. if ( $post_id > 0 && ! current_user_can( 'edit_post', $post_id ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'repeaterkit' ) ), 403 ); } elseif ( ! current_user_can( 'edit_posts' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'repeaterkit' ) ), 403 ); } $field = function_exists( 'acf_get_field' ) ? acf_get_field( $field_key ) : null; if ( ! $field ) { wp_send_json_error( array( 'message' => __( 'Field not found.', 'repeaterkit' ) ), 404 ); } $decoded = json_decode( $json_input, true ); if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $decoded ) ) { wp_send_json_error( array( 'message' => __( 'Invalid JSON syntax.', 'repeaterkit' ) ), 400 ); } // Extract rows if wrapped in an export envelope. $raw_rows = isset( $decoded['rows'] ) && is_array( $decoded['rows'] ) ? $decoded['rows'] : $decoded; // Convert rows into ACF post submission format for standard validation and save. $submission_format = array(); foreach ( $raw_rows as $idx => $row ) { if ( ! is_array( $row ) ) { continue; } $row_id = 'r_' . substr( md5( (string) $idx . microtime() ), 0, 8 ); $submission_format[ $row_id ] = $row; } $sanitized_rows = Storage::save_rows( $submission_format, $post_id, $field ); wp_send_json_success( array( 'count' => count( $sanitized_rows ), 'rows' => $sanitized_rows, ) ); } }