Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/woo-product-feed-pro/classes/class-get-products.php
+++ b/woo-product-feed-pro/classes/class-get-products.php
@@ -3,6 +3,7 @@
use AdTribesPFPHelpersHelper;
use AdTribesPFPHelpersProduct_Feed_Helper;
use AdTribesPFPClassesShipping_Data;
+use AdTribesPFPFactoriesProduct_Feed;
use AdTribesPFPHelpersFormatting;
use AdTribesPFPHelpersSanitization;
@@ -2465,14 +2466,16 @@
* Returns relative and absolute file path
*/
public function woosea_create_csvtxt_feed( $products, $feed, $header ) {
- $upload_dir = wp_upload_dir();
- $base = $upload_dir['basedir'];
- $path = $base . '/woo-product-feed-pro/' . $feed->file_format;
- $file = $path . '/' . sanitize_file_name( $feed->file_name ) . '_tmp.' . $feed->file_format;
+ $upload_dir = wp_upload_dir();
+ $base = $upload_dir['basedir'];
+ // For csv.gz, write the plain CSV tmp file under the 'csv' directory.
+ $base_format = Product_Feed::get_base_file_format( $feed->file_format );
+ $path = $base . '/woo-product-feed-pro/' . $base_format;
+ $file = $path . '/' . sanitize_file_name( $feed->file_name ) . '_tmp.' . $base_format;
- // External location for downloading the file
+ // External location for downloading the file (points to the final compressed file if gz).
$external_base = $upload_dir['baseurl'];
- $external_path = $external_base . '/woo-product-feed-pro/' . $feed->file_format;
+ $external_path = $external_base . '/woo-product-feed-pro/' . $base_format;
$external_file = $external_path . '/' . sanitize_file_name( $feed->file_name ) . '.' . $feed->file_format;
// Check if directory in uploads exists, if not create one
@@ -2637,7 +2640,7 @@
foreach ( $pieces as $k_inner => $v ) {
// For CSV fileformat the keys need to get stripped of the g:
- if ( $header === 'true' && in_array( $feed->file_format, array( 'csv', 'txt', 'tsv' ), true ) ) {
+ if ( $header === 'true' && in_array( $feed->file_format, array( 'csv', 'txt', 'tsv', 'csv.gz' ), true ) ) {
$v = str_replace( 'g:', '', $v );
}
@@ -2706,7 +2709,7 @@
* Construct header line for CSV ans TXT files, for XML create the XML root and header
*/
$products = array();
- if ( $file_format == 'jsonl' ) {
+ if ( $file_format == 'jsonl' || $file_format == 'jsonl.gz' ) {
// Initialize JSONL feed (no header needed for JSONL format).
$jsonl_writer = AdTribesPFPClassesFeed_WritersFeed_Writer_JSONL::instance();
$file = $jsonl_writer->write_feed( array(), $feed, true );
@@ -5103,7 +5106,7 @@
$products[] = array( $attr_line );
// Track preview mode product count (CSV/TXT feeds only)
- if ( $is_preview_mode && $file_format != 'xml' && $file_format != 'jsonl' ) {
+ if ( $is_preview_mode && $file_format != 'xml' && $file_format != 'jsonl' && $file_format != 'jsonl.gz' ) {
$preview_found_count++;
// Exit the inner while loop if we have enough CSV products
if ( $preview_found_count >= $preview_target_count ) {
@@ -5127,7 +5130,7 @@
$products[] = array( $attr_line );
// Track preview mode product count (CSV/TXT feeds only)
- if ( $is_preview_mode && $file_format != 'xml' && $file_format != 'jsonl' ) {
+ if ( $is_preview_mode && $file_format != 'xml' && $file_format != 'jsonl' && $file_format != 'jsonl.gz' ) {
$preview_found_count++;
// Exit the inner while loop if we have enough CSV products
if ( $preview_found_count >= $preview_target_count ) {
@@ -5406,11 +5409,25 @@
$xml_piece[ $product->get_id() ] = $xml_product;
}
} else {
+ // For JSONL formats, allow channel-specific product-level transformations
+ // (e.g. shipping parsing and HTML entity decoding for OpenAI).
+ if ( $file_format === 'jsonl' || $file_format === 'jsonl.gz' ) {
+ /**
+ * Filter a single JSONL product array before it is added to the batch.
+ *
+ * @since 13.5.2
+ *
+ * @param array $xml_product The product data key/value array.
+ * @param array $feed_channel The active channel configuration.
+ * @param object $feed The feed object.
+ */
+ $xml_product = apply_filters( 'adt_product_feed_jsonl_product', $xml_product, $feed_channel, $feed );
+ }
$xml_piece[] = $xml_product;
}
// Track preview mode product count (XML/JSONL feeds only)
- if ( $is_preview_mode && ( $file_format == 'xml' || $file_format == 'jsonl' ) ) {
+ if ( $is_preview_mode && ( $file_format == 'xml' || $file_format == 'jsonl' || $file_format == 'jsonl.gz' ) ) {
$preview_found_count++;
// Exit the inner while loop if we have enough products
if ( $preview_found_count >= $preview_target_count ) {
@@ -5456,7 +5473,7 @@
/**
* Write row to CSV/TXT or XML or JSONL file
*/
- if ( $file_format == 'jsonl' && is_array( $xml_piece ) && ! empty( $xml_piece ) ) {
+ if ( ( $file_format == 'jsonl' || $file_format == 'jsonl.gz' ) && is_array( $xml_piece ) && ! empty( $xml_piece ) ) {
$jsonl_writer = AdTribesPFPClassesFeed_WritersFeed_Writer_JSONL::instance();
$file = $jsonl_writer->write_feed( array_filter( $xml_piece ), $feed, false );
unset( $xml_piece );
--- a/woo-product-feed-pro/includes/Classes/Feeds/OpenAI_Product_Feed.php
+++ b/woo-product-feed-pro/includes/Classes/Feeds/OpenAI_Product_Feed.php
@@ -9,7 +9,6 @@
use AdTribesPFPAbstractsAbstract_Class;
use AdTribesPFPTraitsSingleton_Trait;
-use AdTribesPFPFactoriesProduct_Feed;
/**
* Google Product Review class.
@@ -30,6 +29,27 @@
protected $feed_type = 'openai_product_feed';
/**
+ * Required OpenAI feed fields and their safe empty defaults.
+ *
+ * These fields must be present in every product object even when the mapped
+ * WooCommerce value is empty or the user has not yet configured a static value.
+ * The defaults ensure the field key exists in the JSONL output so OpenAI does
+ * not reject the feed for a missing required attribute.
+ *
+ * @since 13.5.2.2
+ *
+ * @var array<string,mixed>
+ */
+ protected $required_field_defaults = array(
+ 'weight' => '',
+ 'inventory_quantity' => 0,
+ 'seller_tos' => '',
+ 'return_policy' => '',
+ 'return_window' => '',
+ );
+
+
+ /**
* Handle the XML attribute.
*
* @since 13.4.9
@@ -148,6 +168,153 @@
}
/**
+ * Register OpenAI as a platform that requires pure plain text.
+ *
+ * This makes Sanitization::sanitize_html_content() route title, description,
+ * and similar fields through convert_to_pure_plain_text() — which strips HTML
+ * tags and decodes HTML entities — instead of convert_to_plain_text() which
+ * re-encodes entities with htmlentities() for XML compatibility.
+ *
+ * @since 13.5.2.2
+ *
+ * @param array $platforms Platform slugs requiring pure plain text.
+ * @return array
+ */
+ public function register_pure_plain_text_platform( $platforms ) {
+ $platforms[] = 'openai';
+ return $platforms;
+ }
+
+ /**
+ * Transform an OpenAI JSONL product array before it is written to the feed file.
+ *
+ * Handles three concerns specific to the JSONL path:
+ * 1. Shipping — converts internal WOOSEA_COUNTRY##/… marker strings into
+ * an array of structured shipping objects.
+ * 2. HTML entities — decodes any remaining entities (e.g. > in
+ * product_category which is built outside sanitize_html_content()).
+ * Fields like title and description are already clean plain text at this
+ * point because OpenAI is registered as a pure-plain-text platform.
+ * 3. Required field defaults — ensures every required field is present in the
+ * output even when the product has no mapped value.
+ *
+ * @since 13.5.2.2
+ *
+ * @param array $product_data The product key/value array being built for JSONL.
+ * @param array $feed_channel The active channel configuration array.
+ * @param object $feed The feed object.
+ * @return array
+ */
+ public function transform_jsonl_product( $product_data, $feed_channel, $feed ) {
+ if ( ! isset( $feed_channel['fields'] ) || 'openai' !== $feed_channel['fields'] ) {
+ return $product_data;
+ }
+
+ // 1. Transform shipping field from internal marker format to array of objects.
+ if ( ! empty( $product_data['shipping'] ) ) {
+ $product_data['shipping'] = $this->parse_shipping_for_jsonl( $product_data['shipping'] );
+ }
+
+ // 2. Decode any remaining HTML entities in string values.
+ // (title/description are already plain text via convert_to_pure_plain_text();
+ // this covers fields like product_category that are built outside sanitize_html_content().)
+ foreach ( $product_data as $key => $value ) {
+ if ( is_string( $value ) ) {
+ $product_data[ $key ] = html_entity_decode( $value, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
+ }
+ }
+
+ // 3. Ensure every required field is present; use the registered default when absent.
+ foreach ( $this->required_field_defaults as $field => $default ) {
+ if ( ! array_key_exists( $field, $product_data ) ) {
+ $product_data[ $field ] = $default;
+ }
+ }
+
+ return $product_data;
+ }
+
+ /**
+ * Decode HTML entities in OpenAI CSV row data.
+ *
+ * For CSV.GZ format, fields like product_category carry HTML entities
+ * (e.g. > as the category separator) that are not decoded by the
+ * sanitize_html_content() pipeline. This filter decodes all entity-encoded
+ * values in the row so the CSV output is clean plain text.
+ *
+ * @since 13.5.2.2
+ *
+ * @param array $pieces_row The indexed array of CSV cell values for this row.
+ * @param array $old_attributes_config The feed attribute mapping configuration.
+ * @param array $product_data The full product data array.
+ * @param object $feed The feed object.
+ * @return array
+ */
+ public function handle_csv_row_data( $pieces_row, $old_attributes_config, $product_data, $feed ) {
+ if ( 'openai' !== $feed->get_channel( 'fields' ) ) {
+ return $pieces_row;
+ }
+
+ return array_map(
+ function ( $value ) {
+ return is_string( $value ) ? html_entity_decode( $value, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) : $value;
+ },
+ $pieces_row
+ );
+ }
+
+ /**
+ * Parse a raw internal shipping string into an array of structured shipping objects.
+ *
+ * Reuses the same token parsing as write_shipping_attribute() but returns an
+ * array of associative arrays rather than a semicolon-delimited string, which
+ * is correct for JSON serialisation.
+ *
+ * @since 13.5.2
+ *
+ * @param string $value Raw shipping value in WOOSEA_COUNTRY##…:WOOSEA_SERVICE##…:… format,
+ * with multiple entries separated by '||'.
+ * @return array Array of shipping entry objects, each with 'country', 'service', 'price'
+ * and optionally 'region' keys.
+ */
+ private function parse_shipping_for_jsonl( $value ) {
+ $shipping_entries = array();
+ $shipping_array = explode( '||', $value );
+
+ foreach ( $shipping_array as $shipping ) {
+ $country = '';
+ $region = '';
+ $service = '';
+ $price = '';
+
+ $shipping_pieces = explode( ':', $shipping );
+
+ foreach ( $shipping_pieces as $piece ) {
+ if ( strpos( $piece, 'WOOSEA_COUNTRY##' ) !== false ) {
+ $country = str_replace( 'WOOSEA_COUNTRY##', '', $piece );
+ } elseif ( strpos( $piece, 'WOOSEA_REGION##' ) !== false ) {
+ $region = str_replace( 'WOOSEA_REGION##', '', $piece );
+ } elseif ( strpos( $piece, 'WOOSEA_SERVICE##' ) !== false ) {
+ $service = str_replace( 'WOOSEA_SERVICE##', '', $piece );
+ } elseif ( strpos( $piece, 'WOOSEA_PRICE##' ) !== false ) {
+ $price = str_replace( 'WOOSEA_PRICE##', '', $piece );
+ }
+ }
+
+ $entry = array( 'country' => $country );
+ if ( ! empty( $region ) ) {
+ $entry['region'] = $region;
+ }
+ $entry['service'] = $service;
+ $entry['price'] = $price;
+
+ $shipping_entries[] = $entry;
+ }
+
+ return $shipping_entries;
+ }
+
+ /**
* Run the class.
*
* @since 13.4.9
@@ -155,5 +322,8 @@
public function run() {
add_filter( 'adt_product_feed_xml_attribute_handling', array( $this, 'handle_xml_attribute' ), 10, 7 );
add_filter( 'adt_product_data_availability_format', array( $this, 'format_availability' ), 10, 3 );
+ add_filter( 'adt_product_feed_jsonl_product', array( $this, 'transform_jsonl_product' ), 10, 3 );
+ add_filter( 'adt_product_feed_platform_requires_pure_plain_text_fields', array( $this, 'register_pure_plain_text_platform' ), 10, 1 );
+ add_filter( 'adt_product_feed_csv_row_data', array( $this, 'handle_csv_row_data' ), 10, 4 );
}
}
--- a/woo-product-feed-pro/includes/Classes/Usage.php
+++ b/woo-product-feed-pro/includes/Classes/Usage.php
@@ -756,7 +756,7 @@
wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'woo-product-feed-pro' ) ) );
}
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
}
@@ -786,7 +786,7 @@
wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'woo-product-feed-pro' ) ) );
}
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'adt_pfp_allow_tracking_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'adt_pfp_allow_tracking_nonce' ) ) {
wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
}
--- a/woo-product-feed-pro/includes/Classes/WP_Admin.php
+++ b/woo-product-feed-pro/includes/Classes/WP_Admin.php
@@ -449,7 +449,7 @@
wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'woo-product-feed-pro' ) ) );
}
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
}
@@ -477,7 +477,7 @@
wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'woo-product-feed-pro' ) ) );
}
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
}
@@ -500,7 +500,7 @@
wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'woo-product-feed-pro' ) ) );
}
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
}
@@ -579,7 +579,7 @@
* @access public
*/
public function ajax_use_legacy_filters_and_rules() {
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
wp_send_json_error( array( 'message' => __( 'Invalid security token', 'woo-product-feed-pro' ) ) );
}
@@ -612,6 +612,10 @@
wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'woo-product-feed-pro' ) ) );
}
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
+ }
+
// Reset backward compatibility options.
delete_option( 'adt_cron_projects' );
@@ -658,7 +662,7 @@
* @access public
**/
public function ajax_dismiss_get_elite_notice() {
- if ( isset( $_REQUEST['security'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
+ if ( ! isset( $_REQUEST['security'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['security'] ) ), 'woosea_ajax_nonce' ) ) {
wp_send_json_error( __( 'Invalid security token', 'woo-product-feed-pro' ) );
}
--- a/woo-product-feed-pro/includes/Factories/Product_Feed.php
+++ b/woo-product-feed-pro/includes/Factories/Product_Feed.php
@@ -491,6 +491,27 @@
}
/**
+ * Get the base file format, stripping any .gz suffix.
+ *
+ * For compressed formats like 'jsonl.gz' or 'csv.gz', returns the underlying
+ * format ('jsonl' or 'csv') used for directory naming and temp-file extensions.
+ * Declared static so it can be reused across classes without duplicating
+ * the stripping logic (e.g. Product_Feed::get_base_file_format( $feed->file_format )).
+ *
+ * @since 13.5.2
+ * @access public
+ *
+ * @param string $format The file format string to evaluate.
+ * @return string
+ */
+ public static function get_base_file_format( $format ) {
+ if ( substr( $format, -3 ) === '.gz' ) {
+ return substr( $format, 0, -3 );
+ }
+ return $format;
+ }
+
+ /**
* Get product feed file format.
*
* @since 13.3.5
@@ -499,9 +520,10 @@
* @return string
*/
public function get_file_url() {
- $upload_dir = wp_upload_dir();
- $base_url = set_url_scheme( $upload_dir['baseurl'], is_ssl() ? 'https' : 'http' );
- return $base_url . '/' . self::UPLOAD_SUB_DIR . '/' . $this->file_format . '/' . $this->file_name . '.' . $this->file_format;
+ $upload_dir = wp_upload_dir();
+ $base_url = set_url_scheme( $upload_dir['baseurl'], is_ssl() ? 'https' : 'http' );
+ $base_format = self::get_base_file_format( $this->file_format );
+ return $base_url . '/' . self::UPLOAD_SUB_DIR . '/' . $base_format . '/' . $this->file_name . '.' . $this->file_format;
}
/**
@@ -513,9 +535,9 @@
* @return string
*/
public function get_file_path() {
- $upload_dir = wp_upload_dir();
- $asd = $upload_dir['basedir'] . '/' . self::UPLOAD_SUB_DIR . '/' . $this->file_format . '/' . $this->file_name . '.' . $this->file_format;
- return $asd;
+ $upload_dir = wp_upload_dir();
+ $base_format = self::get_base_file_format( $this->file_format );
+ return $upload_dir['basedir'] . '/' . self::UPLOAD_SUB_DIR . '/' . $base_format . '/' . $this->file_name . '.' . $this->file_format;
}
/**
@@ -1121,11 +1143,15 @@
* @access public
*/
public function move_feed_file_to_final() {
- $upload_dir = wp_upload_dir();
- $base = $upload_dir['basedir'];
- $path = $base . '/woo-product-feed-pro/' . $this->file_format;
- $tmp_file = $path . '/' . sanitize_file_name( $this->file_name ) . '_tmp.' . $this->file_format;
- $new_file = $path . '/' . sanitize_file_name( $this->file_name ) . '.' . $this->file_format;
+ $upload_dir = wp_upload_dir();
+ $base = $upload_dir['basedir'];
+ $base_format = self::get_base_file_format( $this->file_format );
+ $is_gz = self::get_base_file_format( $this->file_format ) !== $this->file_format;
+
+ // For gz formats the tmp file uses the base format (e.g. _tmp.jsonl for jsonl.gz).
+ $path = $base . '/woo-product-feed-pro/' . $base_format;
+ $tmp_file = $path . '/' . sanitize_file_name( $this->file_name ) . '_tmp.' . $base_format;
+ $new_file = $path . '/' . sanitize_file_name( $this->file_name ) . '.' . $this->file_format;
// Check if temporary file exists before attempting to copy.
if ( ! file_exists( $tmp_file ) ) {
@@ -1145,6 +1171,75 @@
return;
}
+ if ( $is_gz ) {
+ // Compress the plain tmp file into a gzip-compressed final file.
+ $gz_handle = gzopen( $new_file, 'wb9' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
+ $plain_handle = fopen( $tmp_file, 'rb' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
+
+ if ( false === $gz_handle || false === $plain_handle ) {
+ if ( $gz_handle ) {
+ gzclose( $gz_handle );
+ }
+ if ( $plain_handle ) {
+ fclose( $plain_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
+ }
+ if ( function_exists( 'wc_get_logger' ) ) {
+ $logger = wc_get_logger();
+ $logger->error(
+ 'Failed to open files for gzip compression',
+ array(
+ 'source' => 'woo-product-feed-pro',
+ 'feed_id' => $this->id,
+ 'feed_title' => $this->title,
+ 'tmp_file' => $tmp_file,
+ 'new_file' => $new_file,
+ 'file_format' => $this->file_format,
+ )
+ );
+ }
+ return;
+ }
+
+ $write_error = false;
+ while ( ! feof( $plain_handle ) ) {
+ $data = fread( $plain_handle, 65536 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread
+ if ( false === $data ) {
+ $write_error = true;
+ break;
+ }
+ $bytes_written = gzwrite( $gz_handle, $data );
+ if ( false === $bytes_written || ( 0 === $bytes_written && strlen( $data ) > 0 ) ) {
+ $write_error = true;
+ break;
+ }
+ }
+
+ fclose( $plain_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
+ gzclose( $gz_handle );
+
+ if ( $write_error ) {
+ wp_delete_file( $new_file );
+ if ( function_exists( 'wc_get_logger' ) ) {
+ $logger = wc_get_logger();
+ $logger->error(
+ 'Gzip compression failed during feed file write',
+ array(
+ 'source' => 'woo-product-feed-pro',
+ 'feed_id' => $this->id,
+ 'feed_title' => $this->title,
+ 'tmp_file' => $tmp_file,
+ 'new_file' => $new_file,
+ 'file_format' => $this->file_format,
+ )
+ );
+ }
+ return;
+ }
+
+ wp_delete_file( $tmp_file );
+ return;
+ }
+
// Format XML file with proper indentation before moving (for large feeds).
if ( 'xml' === $this->file_format ) {
$get_products = new WooSEA_Get_Products();
--- a/woo-product-feed-pro/templates/edit-feed/tabs/general-tab.php
+++ b/woo-product-feed-pro/templates/edit-feed/tabs/general-tab.php
@@ -196,7 +196,7 @@
<td>
<select name="fileformat" id="fileformat" class="select-field">
<?php
- $format_arr = array( 'xml', 'csv', 'txt', 'tsv', 'jsonl' );
+ $format_arr = array( 'xml', 'csv', 'txt', 'tsv', 'jsonl', 'jsonl.gz', 'csv.gz' );
foreach ( $format_arr as $format ) :
$selected = '';
if ( $edit_feed ) {
--- a/woo-product-feed-pro/woocommerce-sea.php
+++ b/woo-product-feed-pro/woocommerce-sea.php
@@ -1,7 +1,7 @@
<?php
/**
* Plugin Name: Product Feed PRO for WooCommerce
- * Version: 13.5.2.1
+ * Version: 13.5.2.2
* Plugin URI: https://www.adtribes.io/support/?utm_source=wpadmin&utm_medium=plugin&utm_campaign=woosea_product_feed_pro
* Description: Configure and maintain your WooCommerce product feeds for Google Shopping, Catalog managers, Remarketing, Bing, Skroutz, Yandex, Comparison shopping websites and over a 100 channels more.
* Author: AdTribes.io
@@ -17,7 +17,7 @@
* Domain Path: /languages
*
* WC requires at least: 4.4
- * WC tested up to: 10.5.2
+ * WC tested up to: 10.5.3
*
* Product Feed PRO for WooCommerce is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@
/**
* Define plugin constants.
*/
-define( 'WOOCOMMERCESEA_PLUGIN_VERSION', '13.5.2.1' );
+define( 'WOOCOMMERCESEA_PLUGIN_VERSION', '13.5.2.2' );
define( 'WOOCOMMERCESEA_PLUGIN_NAME', 'woocommerce-product-feed-pro' );
define( 'WOOCOMMERCESEA_PLUGIN_NAME_SHORT', 'woo-product-feed-pro' );