1890 lines
60 KiB
PHP
1890 lines
60 KiB
PHP
<?php
|
|
/**
|
|
* @package CTXFeed\V5\Helper
|
|
*/
|
|
|
|
namespace CTXFeed\V5\Helper;
|
|
|
|
use CTXFeed\V5\Common\Helper;
|
|
use CTXFeed\V5\FTP\FtpClient;
|
|
use CTXFeed\V5\FTP\FtpException;
|
|
use CTXFeed\V5\Product\AttributeValueByType;
|
|
use CTXFeed\V5\Query\QueryFactory;
|
|
use CTXFeed\V5\Template\TemplateFactory;
|
|
use CTXFeed\V5\Utility\Cache;
|
|
use CTXFeed\V5\Utility\Config;
|
|
use CTXFeed\V5\Utility\FileSystem;
|
|
use CTXFeed\V5\Utility\Settings;
|
|
use WP_Error;
|
|
|
|
/**
|
|
* This class contains feed generated method
|
|
*/
|
|
class FeedHelper {
|
|
|
|
/**
|
|
* Sanitizes form fields recursively using WordPress standards.
|
|
*
|
|
* @param array $data Data associated with form fields to be sanitized.
|
|
*
|
|
* @return array Sanitized form data.
|
|
*/
|
|
public static function sanitize_form_fields( $data ) {
|
|
foreach ( $data as $k => $v ) {
|
|
if ( true === apply_filters( 'woo_feed_sanitize_form_fields', true, $k, $v, $data ) ) {
|
|
if ( is_array( $v ) ) {
|
|
$v = self::sanitize_form_fields( $v );
|
|
} else {
|
|
// $v = sanitize_text_field( $v ); #TODO should not trim Prefix and Suffix field
|
|
}
|
|
}
|
|
$data[ $k ] = apply_filters( 'woo_feed_sanitize_form_field', $v, $k );
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Generates a unique filename for a feed, ensuring no conflicts in the feed directory.
|
|
*
|
|
* @param string $file_name The initial filename.
|
|
* @param string $type The type of the feed (e.g., 'xml', 'csv').
|
|
* @param string $provider The provider for which the feed is being generated.
|
|
*
|
|
* @return string|false The unique filename, or false if an error occurs.
|
|
*/
|
|
public static function generate_unique_feed_file_name( $file_name, $type, $provider ) {
|
|
if ( ! \is_string( $file_name ) || ! \is_string( $type ) || ! \is_string( $provider ) ) {
|
|
// Handle invalid input types.
|
|
return false;
|
|
}
|
|
|
|
$feed_dir = Helper::get_file_dir( $provider, $type );
|
|
|
|
$raw_filename = \sanitize_title( $file_name, '', 'save' );
|
|
$raw_filename = self::unique_feed_slug( $raw_filename, 'wf_feed_' );
|
|
$raw_filename = \sanitize_file_name( $raw_filename . '.' . $type );
|
|
$raw_filename = \wp_unique_filename( $feed_dir, $raw_filename );
|
|
$base_filename = \str_replace( '.' . $type, '', $raw_filename );
|
|
|
|
return \is_numeric( $base_filename ) ? false : $base_filename;
|
|
}
|
|
|
|
/**
|
|
* Generates a unique slug for a feed by checking against existing database entries.
|
|
* This function delegates to CommonHelper::unique_option_name for actual uniqueness check.
|
|
* Use generate_unique_feed_file_name() for a complete unique file name generation.
|
|
*
|
|
* @param string $slug The initial slug for the feed.
|
|
* @param string $prefix An optional prefix to prepend to the slug.
|
|
* @param int $option_id An optional ID to exclude a specific option from the uniqueness check.
|
|
*
|
|
* @return string Unique slug for the feed.
|
|
* @see CommonHelper::unique_option_name()
|
|
*/
|
|
public static function unique_feed_slug( $slug, $prefix = '', $option_id = null ) {
|
|
return CommonHelper::unique_option_name( $slug, $prefix, $option_id );
|
|
|
|
}
|
|
|
|
/**
|
|
* Sanitizes and saves feed configuration data to the WordPress options table.
|
|
*
|
|
* @param array $feed_rules Data to be saved. Should be an associative array of feed rules.
|
|
* @param string|null $feed_option_name Optional. The name of the feed option. If null, a name is auto-generated.
|
|
* @param bool $configOnly Optional. Whether to save only 'wf_config' or both 'wf_config' and 'wf_feed_'. Defaults to true.
|
|
*
|
|
* @return bool|string False on failure, or the feed option name on success.
|
|
*/
|
|
public static function save_feed_config_data( $feed_rules, $feed_option_name = null, $configOnly = true ) {
|
|
if ( ! \is_array( $feed_rules ) ) {
|
|
// Handle invalid input
|
|
return false;
|
|
}
|
|
|
|
$prepared_feed_rules = self::prepare_feed_rules_to_save( $feed_rules, $feed_option_name );
|
|
if ( ! $prepared_feed_rules ) {
|
|
// Handle failure in preparing feed rules
|
|
return false;
|
|
}
|
|
|
|
$feed_option_name = $prepared_feed_rules['feed_option_name'];
|
|
$is_update = $prepared_feed_rules['is_update'];
|
|
|
|
self::call_action_before_update_feed_config( $is_update, $feed_rules, $feed_option_name );
|
|
|
|
$updated = update_option( $feed_option_name, $prepared_feed_rules['feedrules_to_save'], false );
|
|
|
|
self::call_action_after_update_feed_config( $is_update, $feed_rules, $feed_option_name );
|
|
|
|
// Return feed option name on success or false if update failed
|
|
return $updated ? $feed_option_name : false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Prepares feed rules for saving to the database, ensuring data integrity and sanitization.
|
|
*
|
|
* @param array $feed_rules Data to be saved, expected to contain 'filename', 'feedType', 'provider'.
|
|
* @param mixed $feed_option_name Optional. Feed name, auto-generated if null or empty.
|
|
*
|
|
* @return array|false Returns prepared data for saving or false if input is invalid.
|
|
*/
|
|
public static function prepare_feed_rules_to_save( $feed_rules, $feed_option_name ) {
|
|
if ( ! \is_array( $feed_rules ) || ! self::validate_feed_rules( $feed_rules ) ) {
|
|
return false;
|
|
}
|
|
|
|
$feed_rules = self::remove_unnecessary_fields( $feed_rules );
|
|
|
|
$feed_rules = self::sanitize_form_fields( $feed_rules );
|
|
|
|
// Handle feed option name generation or retrieval.
|
|
list( $feed_option_name, $old_feed, $update, $status ) = self::handle_feed_option_name( $feed_rules, $feed_option_name );
|
|
|
|
|
|
$feed_url = self::get_file_url( $feed_option_name, $feed_rules['provider'], $feed_rules['feedType'] );
|
|
|
|
// Modify feed rules before save to database.
|
|
$feed_rules = apply_filters( 'woo_feed_insert_feed_data', $feed_rules, $old_feed, $feed_option_name );
|
|
|
|
$feed_rulesToSave = [
|
|
'feedrules' => $feed_rules,
|
|
'url' => $feed_url,
|
|
'last_updated' => \current_time( 'mysql' ),
|
|
'status' => $status,
|
|
];
|
|
|
|
return [
|
|
'feedrules_to_save' => $feed_rulesToSave,
|
|
'is_update' => $update,
|
|
'old_data' => $old_feed,
|
|
'feed_option_name' => $feed_option_name,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Validates the required keys in feed rules.
|
|
*
|
|
* @param array $feed_rules
|
|
*
|
|
* @return bool
|
|
*/
|
|
private static function validate_feed_rules( $feed_rules ) {
|
|
return isset( $feed_rules['filename'], $feed_rules['feedType'], $feed_rules['provider'] );
|
|
}
|
|
|
|
/**
|
|
* Removes unnecessary fields from feed rules.
|
|
*
|
|
* @param array $feed_rules
|
|
*
|
|
* @return array
|
|
*/
|
|
private static function remove_unnecessary_fields( $feed_rules ) {
|
|
// Define fields to remove
|
|
$removables = array( 'closedpostboxesnonce', '_wpnonce', '_wp_http_referer', 'save_feed_config', 'edit-feed' );
|
|
foreach ( $removables as $removable ) {
|
|
unset( $feed_rules[ $removable ] );
|
|
}
|
|
|
|
return $feed_rules;
|
|
}
|
|
|
|
/**
|
|
* Handles the generation or retrieval of feed option name.
|
|
*
|
|
* @param array $feed_rules
|
|
* @param mixed $feed_option_name
|
|
*
|
|
* @return array
|
|
*/
|
|
private static function handle_feed_option_name( $feed_rules, $feed_option_name ) {
|
|
if ( empty( $feed_option_name ) ) {
|
|
$feed_option_name = AttributeValueByType::FEED_RULES_OPTION_PREFIX . self::generate_unique_feed_file_name(
|
|
$feed_rules['filename'],
|
|
$feed_rules['feedType'],
|
|
$feed_rules['provider']
|
|
);
|
|
|
|
return [ $feed_option_name, array(), false, 1 ];
|
|
} else {
|
|
$old_feed = maybe_unserialize( get_option( $feed_option_name, [] ) );
|
|
$status = isset( $old_feed['status'] ) && 1 === (int) $old_feed['status'] ? 1 : 0;
|
|
|
|
return [ $feed_option_name, $old_feed, true, $status ];
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $update
|
|
* @param $feed_rules
|
|
* @param $feed_option_name
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function call_action_before_update_feed_config( $update, $feed_rules, $feed_option_name ) {
|
|
if ( $update ) {
|
|
/**
|
|
* Before Updating Config to db
|
|
*
|
|
* @param array $feed_rules An array of sanitized config
|
|
* @param string $feed_option_name Option name
|
|
*/
|
|
do_action( 'woo_feed_before_update_config', $feed_rules, $feed_option_name );
|
|
} else {
|
|
/**
|
|
* Before inserting Config to db
|
|
*
|
|
* @param array $feed_rules An array of sanitized config
|
|
* @param string $feed_option_name Option name
|
|
*/
|
|
do_action( 'woo_feed_before_insert_config', $feed_rules, $feed_option_name );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $update
|
|
* @param $feed_rules
|
|
* @param $feed_option_name
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function call_action_after_update_feed_config( $update, $feed_rules, $feed_option_name ) {
|
|
if ( $update ) {
|
|
/**
|
|
* After Updating Config to db
|
|
*
|
|
* @param array $feed_rules An array of sanitized config
|
|
* @param string $feed_option_name Option name
|
|
*/
|
|
do_action( 'woo_feed_after_update_config', $feed_rules, $feed_option_name );
|
|
} else {
|
|
/**
|
|
* After inserting Config to db
|
|
*
|
|
* @param array $feed_rules An array of sanitized config
|
|
* @param string $feed_option_name Option name
|
|
*/
|
|
do_action( 'woo_feed_after_insert_config', $feed_rules, $feed_option_name );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $rules
|
|
* @param $context
|
|
*
|
|
* @return mixed|null
|
|
*/
|
|
public static function parse_feed_rules( $rules = array(), $context = 'view' ) {
|
|
|
|
if ( empty( $rules ) ) {
|
|
$rules = array();
|
|
}
|
|
|
|
$defaults = Config::default_feed_rules();
|
|
|
|
$rules = wp_parse_args( $rules, $defaults );
|
|
$rules['filter_mode'] = wp_parse_args(
|
|
$rules['filter_mode'],
|
|
array(
|
|
'product_ids' => 'include',
|
|
'categories' => 'include',
|
|
'post_status' => 'include',
|
|
)
|
|
);
|
|
|
|
$rules['campaign_parameters'] = wp_parse_args(
|
|
$rules['campaign_parameters'],
|
|
array(
|
|
'utm_source' => '',
|
|
'utm_medium' => '',
|
|
'utm_campaign' => '',
|
|
'utm_term' => '',
|
|
'utm_content' => '',
|
|
)
|
|
);
|
|
|
|
if ( ! empty( $rules['provider'] ) && is_string( $rules['provider'] ) ) {
|
|
/**
|
|
* filter parsed rules for provider
|
|
*
|
|
* @param array $rules
|
|
* @param string $context
|
|
*
|
|
* @since 3.3.7
|
|
*
|
|
*/
|
|
$rules = apply_filters( "woo_feed_{$rules['provider']}_parsed_rules", $rules, $context );
|
|
}
|
|
|
|
/**
|
|
* filter parsed rules
|
|
*
|
|
* @param array $rules
|
|
* @param string $context
|
|
*
|
|
* @since 3.3.7 $provider parameter removed
|
|
*
|
|
*/
|
|
return apply_filters( 'woo_feed_parsed_rules', $rules, $context );
|
|
}
|
|
|
|
/**
|
|
* Get pro version feed default rules.
|
|
*
|
|
* @param $rules
|
|
*
|
|
* @return mixed|null
|
|
*/
|
|
private static function free_default_feed_rules( $rules = [] ) {
|
|
$defaults = array(
|
|
'provider' => '',
|
|
'filename' => '',
|
|
'feedType' => '',
|
|
'feed_country' => '',
|
|
'ftpenabled' => 0,
|
|
'ftporsftp' => 'ftp',
|
|
'ftphost' => '',
|
|
'ftpport' => '21',
|
|
'ftpuser' => '',
|
|
'ftppassword' => '',
|
|
'ftppath' => '',
|
|
'ftpmode' => 'active',
|
|
'is_variations' => 'y',
|
|
'variable_price' => 'first',
|
|
'variable_quantity' => 'first',
|
|
'feedLanguage' => apply_filters( 'wpml_current_language', null ),
|
|
'feedCurrency' => get_woocommerce_currency(),
|
|
'itemsWrapper' => 'products',
|
|
'itemWrapper' => 'product',
|
|
'delimiter' => ',',
|
|
'enclosure' => 'double',
|
|
'extraHeader' => '',
|
|
'vendors' => array(),
|
|
// Feed Config
|
|
'mattributes' => array(), // merchant attributes
|
|
'prefix' => array(), // prefixes
|
|
'type' => array(), // value (attribute) types
|
|
'attributes' => array(), // product attribute mappings
|
|
'default' => array(), // default values (patterns) if value type set to pattern
|
|
'suffix' => array(), // suffixes
|
|
'output_type' => array(), // output type (output filter)
|
|
'limit' => array(), // limit or command
|
|
// filters tab
|
|
'composite_price' => '',
|
|
'shipping_country' => '',
|
|
'tax_country' => '',
|
|
'product_ids' => '',
|
|
'categories' => array(),
|
|
'post_status' => array( 'publish' ),
|
|
'filter_mode' => array(),
|
|
'campaign_parameters' => array(),
|
|
|
|
'ptitle_show' => '',
|
|
'decimal_separator' => wc_get_price_decimal_separator(),
|
|
'thousand_separator' => wc_get_price_thousand_separator(),
|
|
'decimals' => wc_get_price_decimals(),
|
|
);
|
|
$rules = wp_parse_args( $rules, $defaults );
|
|
|
|
return apply_filters( 'woo_feed_free_default_feed_rules', $rules );
|
|
}
|
|
|
|
/**
|
|
* Get pro version feed default rules.
|
|
*
|
|
* @param $rules
|
|
*
|
|
* @return mixed|null
|
|
*/
|
|
private static function pro_default_feed_rules( $rules = [] ) {
|
|
$defaults = array(
|
|
'provider' => '',
|
|
'feed_country' => '',
|
|
'filename' => '',
|
|
'feedType' => '',
|
|
'ftpenabled' => 0,
|
|
'ftporsftp' => 'ftp',
|
|
'ftphost' => '',
|
|
'ftpport' => '21',
|
|
'ftpuser' => '',
|
|
'ftppassword' => '',
|
|
'ftppath' => '',
|
|
'ftpmode' => 'active',
|
|
'is_variations' => 'y', // Only Variations (All Variations)
|
|
'variable_price' => 'first',
|
|
'variable_quantity' => 'first',
|
|
'feedLanguage' => apply_filters( 'wpml_current_language', null ),
|
|
'feedCurrency' => get_woocommerce_currency(),
|
|
'itemsWrapper' => 'products',
|
|
'itemWrapper' => 'product',
|
|
'delimiter' => ',',
|
|
'enclosure' => 'double',
|
|
'extraHeader' => '',
|
|
'vendors' => array(),
|
|
// Feed Config
|
|
'mattributes' => array(), // merchant attributes
|
|
'prefix' => array(), // prefixes
|
|
'type' => array(), // value (attribute) types
|
|
'attributes' => array(), // product attribute mappings
|
|
'default' => array(), // default values (patterns) if value type set to pattern
|
|
'suffix' => array(), // suffixes
|
|
'output_type' => array(), // output type (output filter)
|
|
'limit' => array(), // limit or command
|
|
// filters tab
|
|
'composite_price' => 'all_product_price',
|
|
'product_ids' => '',
|
|
'categories' => array(),
|
|
'post_status' => array( 'publish' ),
|
|
'filter_mode' => array(),
|
|
'campaign_parameters' => array(),
|
|
'is_outOfStock' => 'n',
|
|
'is_backorder' => 'n',
|
|
'is_emptyDescription' => 'n',
|
|
'is_emptyImage' => 'n',
|
|
'is_emptyPrice' => 'n',
|
|
'product_visibility' => 0,
|
|
// include hidden ? 1 yes 0 no
|
|
'outofstock_visibility' => 0,
|
|
// override wc global option for out-of-stock product hidden from catalog? 1 yes 0 no
|
|
'ptitle_show' => '',
|
|
'decimal_separator' => wc_get_price_decimal_separator(),
|
|
'thousand_separator' => wc_get_price_thousand_separator(),
|
|
'decimals' => wc_get_price_decimals(),
|
|
);
|
|
// $defaults = [
|
|
// "provider" => "",
|
|
// "feed_country" => "",
|
|
// "filename" => "",
|
|
// "feedType" => "xml",
|
|
// "ftpenabled" => false,
|
|
// "ftporsftp" => "ftp",
|
|
// "ftphost" => "",
|
|
// "ftpport" => "21",
|
|
// "ftpuser" => "",
|
|
// "ftppassword" => "",
|
|
// "ftppath" => "",
|
|
// "ftpmode" => "active",
|
|
// "is_variations" => "y",
|
|
// "variable_price" => "first",
|
|
// "variable_quantity" => "first",
|
|
// 'feedLanguage' => apply_filters( 'wpml_current_language', null ),
|
|
// 'feedCurrency' => get_woocommerce_currency(),
|
|
// "itemsWrapper" => "products",
|
|
// "itemWrapper" => "product",
|
|
// "delimiter" => ",",
|
|
// "enclosure" => "double",
|
|
// "extraHeader" => "",
|
|
// "vendors" => [],
|
|
// "mattributes" => [],
|
|
// "prefix" => [],
|
|
// "type" => [],
|
|
// "attributes" => [],
|
|
// "default" => [],
|
|
// "suffix" => [],
|
|
// "output_type" => [],
|
|
// "limit" => [],
|
|
// "composite_price" => "all_product_price",
|
|
// "product_ids" => [],
|
|
// "categories" => [],
|
|
// "post_status" => ["publish"],
|
|
// "filter_mode" => [
|
|
// "product_ids" => "include",
|
|
// "categories" => "include",
|
|
// "post_status" => "include"
|
|
// ],
|
|
// "campaign_parameters" => [
|
|
// "utm_source" => "",
|
|
// "utm_medium" => "",
|
|
// "utm_campaign" => "",
|
|
// "utm_term" => "",
|
|
// "utm_content" => ""
|
|
// ],
|
|
// "is_outOfStock" => false,
|
|
// "is_backorder" => false,
|
|
// "is_emptyDescription" => false,
|
|
// "is_emptyImage" => false,
|
|
// "is_emptyPrice" => false,
|
|
// "product_visibility" => false,
|
|
// "outofstock_visibility" => false,
|
|
// "ptitle_show" => "",
|
|
// 'decimal_separator' => wc_get_price_decimal_separator(),
|
|
// 'thousand_separator' => wc_get_price_thousand_separator(),
|
|
// 'decimals' => wc_get_price_decimals(),
|
|
// "feed_option_name" => "",
|
|
// "feed_id" => "",
|
|
// "meta-box-order-nonce" => "",
|
|
// "shipping_country" => "",
|
|
// "tax_country" => "",
|
|
// "str_replace" => [
|
|
// [
|
|
// "subject" => "",
|
|
// "search" => "",
|
|
// "replace" => ""
|
|
// ]
|
|
// ],
|
|
// "concatType" => [],
|
|
// "fattribute" => [],
|
|
// "condition" => [],
|
|
// "filterCompare" => [],
|
|
// "wf_tabs" => true,
|
|
// "option_id" => "",
|
|
// "option_name" => ""
|
|
// ];
|
|
|
|
$rules = wp_parse_args( $rules, $defaults );
|
|
|
|
|
|
return apply_filters( 'woo_feed_pro_default_feed_rules', $rules );
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $item
|
|
* @param $request
|
|
*
|
|
* @return void|\WP_Error|\WP_REST_Response
|
|
*/
|
|
public static function prepare_item_for_response( $item ) {
|
|
$actual_value_from_db = $item;
|
|
if ( isset( $item['option_value'] ) ) {
|
|
$item['option_value'] = maybe_unserialize( maybe_unserialize( $item['option_value'] ) );
|
|
|
|
return apply_filters( 'woo_feed_prepare_item_for_response', $item, $actual_value_from_db );
|
|
} else {
|
|
$item['option_value'] = maybe_unserialize( get_option( $item['option_name'] ) );
|
|
}
|
|
|
|
if ( ! isset( $item['option_value']['url'] ) ) {
|
|
$item['option_value']['url'] = Helper::get_file_url( $item['option_name'], $item['option_value']['feedrules']['provider'], $item['option_value']['feedrules']['feedType'] );
|
|
}
|
|
|
|
if ( ! isset( $item['option_value']['status'] ) ) {
|
|
$item['option_value']['status'] = false;
|
|
}
|
|
|
|
return apply_filters( 'woo_feed_prepare_item_for_response', $item, $actual_value_from_db );
|
|
}
|
|
|
|
/**
|
|
* @param $feed_lists
|
|
* @param $status
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function prepare_all_feeds( $feed_lists, $status ) {
|
|
$lists = [];
|
|
|
|
foreach ( $feed_lists as $feed ) {
|
|
$item = self::prepare_item_for_response( $feed );
|
|
// Skip invalid feed structure
|
|
if ( ! self::validate_feed_structure( $item ) ) {
|
|
continue;
|
|
}
|
|
if ( apply_filters( 'woo_feed_should_apply_validate_feed_structure', false ) && ! self::validate_feed_structure( $item, 'full' ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( $status ) {
|
|
if ( \is_object( $item['option_value'] ) ) {
|
|
$lists[] = $item;
|
|
continue;
|
|
}
|
|
if ( 'active' === $status && 1 === $item['option_value']['status'] ) {
|
|
$lists[] = $item;
|
|
}
|
|
if ( 'inactive' === $status && 0 === $item['option_value']['status'] ) {
|
|
$lists[] = $item;
|
|
}
|
|
} else {
|
|
$lists[] = $item;
|
|
}
|
|
}
|
|
|
|
// Modify the feed list before returning.
|
|
return apply_filters( 'woo_feed_prepare_all_feeds', $lists, $feed_lists, $status );
|
|
}
|
|
|
|
|
|
/**
|
|
* Validates the structure of a feed option.
|
|
*
|
|
* @param $feed
|
|
* @param $validation_type
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function validate_feed_structure( $feed, $validation_type = 'partial' ) {
|
|
// Define the nested structure of required keys
|
|
$required_structure = [
|
|
'option_id' => 'scalar',
|
|
'option_name' => 'scalar',
|
|
'option_value' => [
|
|
'feedrules' => [
|
|
'provider' => 'scalar',
|
|
'feed_country' => 'scalar',
|
|
'filename' => 'scalar',
|
|
'feedType' => 'scalar',
|
|
'ftpenabled' => 'scalar',
|
|
'ftporsftp' => 'scalar',
|
|
'ftphost' => 'scalar',
|
|
'ftpport' => 'scalar',
|
|
'ftpuser' => 'scalar',
|
|
'ftppassword' => 'scalar',
|
|
'ftppath' => 'scalar',
|
|
'ftpmode' => 'scalar',
|
|
'is_variations' => 'scalar',
|
|
'variable_price' => 'scalar',
|
|
'variable_quantity' => 'scalar',
|
|
'feedLanguage' => 'scalar',
|
|
'feedCurrency' => 'scalar',
|
|
'itemsWrapper' => 'scalar',
|
|
'itemWrapper' => 'scalar',
|
|
'delimiter' => 'scalar',
|
|
'enclosure' => 'scalar',
|
|
'extraHeader' => 'scalar',
|
|
'vendors' => 'array',
|
|
'mattributes' => 'array',
|
|
'prefix' => 'array',
|
|
'type' => 'array',
|
|
'attributes' => 'array',
|
|
'default' => 'array',
|
|
'suffix' => 'array',
|
|
'output_type' => 'array',
|
|
'limit' => 'array',
|
|
'composite_price' => 'scalar',
|
|
'product_ids' => 'array',
|
|
'categories' => 'array',
|
|
'post_status' => 'array',
|
|
'filter_mode' => [
|
|
'product_ids' => 'scalar',
|
|
'categories' => 'scalar',
|
|
'post_status' => 'scalar',
|
|
],
|
|
'campaign_parameters' => [
|
|
'utm_source' => 'scalar',
|
|
'utm_medium' => 'scalar',
|
|
'utm_campaign' => 'scalar',
|
|
'utm_term' => 'scalar',
|
|
'utm_content' => 'scalar',
|
|
],
|
|
'is_outOfStock' => 'scalar',
|
|
'is_backorder' => 'scalar',
|
|
'is_emptyDescription' => 'scalar',
|
|
'is_emptyImage' => 'scalar',
|
|
'is_emptyPrice' => 'scalar',
|
|
'product_visibility' => 'scalar',
|
|
'outofstock_visibility' => 'scalar',
|
|
'ptitle_show' => 'scalar',
|
|
'decimal_separator' => 'scalar',
|
|
'thousand_separator' => 'scalar',
|
|
'decimals' => 'scalar',
|
|
'feed_option_name' => 'scalar',
|
|
'feed_id' => 'scalar',
|
|
'meta-box-order-nonce' => 'scalar',
|
|
'shipping_country' => 'scalar',
|
|
'tax_country' => 'scalar',
|
|
'str_replace' => 'array',
|
|
'concatType' => 'array',
|
|
'fattribute' => 'array',
|
|
'condition' => 'array',
|
|
'filterCompare' => 'array',
|
|
'wf_tabs' => 'scalar',
|
|
],
|
|
'url' => 'scalar',
|
|
'last_updated' => 'scalar',
|
|
'status' => 'scalar',
|
|
],
|
|
'autoload' => 'scalar',
|
|
];
|
|
$is_valid = false;
|
|
if( $validation_type == 'partial' ) {
|
|
if(isset($feed['option_value'], $feed['option_name'],$feed['option_value']['feedrules'], $feed['option_value']['feedrules']['provider'], $feed['option_value']['feedrules']['feedType'] ) && $feed['option_value']['feedrules']['provider'] && $feed['option_value']['feedrules']['feedType'] ) {
|
|
$is_valid = true;
|
|
}
|
|
}else{
|
|
$is_valid = self::validate_structure( $feed, $required_structure );
|
|
}
|
|
|
|
|
|
|
|
return apply_filters( 'woo_feed_validate_feed_structure', $is_valid, $feed, $required_structure );
|
|
}
|
|
|
|
/**
|
|
* Validates the structure of a feed option.
|
|
*
|
|
* @param $array
|
|
* @param $required_structure
|
|
*
|
|
* @return bool
|
|
*/
|
|
private static function validate_structure( $array, $required_structure ) {
|
|
$is_valid = true;
|
|
foreach ( $required_structure as $key => $value ) {
|
|
if ( ! array_key_exists( $key, $array ) ) {
|
|
// Key is missing
|
|
$is_valid = false;
|
|
break;
|
|
}
|
|
if ( is_array( $value ) ) {
|
|
if ( ! is_array( $array[ $key ] ) ) {
|
|
// Expected an array, found something else
|
|
$is_valid = false;
|
|
break;
|
|
}
|
|
// Recursive check for nested structure
|
|
$valid = self::validate_structure( $array[ $key ], $value );
|
|
if ( ! $valid ) {
|
|
$is_valid = false;
|
|
break;
|
|
}
|
|
} else {
|
|
if ( $value === 'scalar' && is_array( $array[ $key ] ) ) {
|
|
// Expected a scalar value, found an array
|
|
$is_valid = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $is_valid;
|
|
}
|
|
|
|
|
|
/**
|
|
* Removes predefined prefixes from a feed option name and returns the resulting slug.
|
|
*
|
|
* @param string $feed The feed option name from which to remove prefixes.
|
|
*
|
|
* @return string The slug derived from the feed option name after removing specific prefixes.
|
|
*/
|
|
public static function get_feed_option_name( $feed ) {
|
|
if ( ! \is_string( $feed ) ) {
|
|
// Handle invalid input.
|
|
return '';
|
|
}
|
|
|
|
// Define the prefixes to be removed. Consider making these configurable if necessary.
|
|
$prefixes_to_remove = [ 'wf_feed_', 'wf_config' ];
|
|
|
|
return \str_replace( $prefixes_to_remove, '', $feed );
|
|
}
|
|
|
|
|
|
/**
|
|
* Get Schedule Intervals
|
|
* @return mixed
|
|
*/
|
|
public static function get_schedule_interval_options() {
|
|
if ( Helper::is_pro() ) {
|
|
$interval_options = array(
|
|
WEEK_IN_SECONDS => esc_html__( '1 Week', 'woo-feed' ),
|
|
DAY_IN_SECONDS => esc_html__( '24 Hours', 'woo-feed' ),
|
|
12 * HOUR_IN_SECONDS => esc_html__( '12 Hours', 'woo-feed' ),
|
|
6 * HOUR_IN_SECONDS => esc_html__( '6 Hours', 'woo-feed' ),
|
|
HOUR_IN_SECONDS => esc_html__( '1 Hour', 'woo-feed' ),
|
|
30 * MINUTE_IN_SECONDS => esc_html__( '30 Minutes', 'woo-feed' ),
|
|
15 * MINUTE_IN_SECONDS => esc_html__( '15 Minutes', 'woo-feed' ),
|
|
5 * MINUTE_IN_SECONDS => esc_html__( '5 Minutes', 'woo-feed' )
|
|
);
|
|
} else {
|
|
$interval_options = array(
|
|
WEEK_IN_SECONDS => esc_html__( '1 Week', 'woo-feed' ),
|
|
DAY_IN_SECONDS => esc_html__( '24 Hours', 'woo-feed' ),
|
|
12 * HOUR_IN_SECONDS => esc_html__( '12 Hours', 'woo-feed' ),
|
|
6 * HOUR_IN_SECONDS => esc_html__( '6 Hours', 'woo-feed' ),
|
|
HOUR_IN_SECONDS => esc_html__( '1 Hour', 'woo-feed' ),
|
|
);
|
|
}
|
|
|
|
return apply_filters(
|
|
'woo_feed_schedule_interval_options', $interval_options
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return false|float|int|string
|
|
*/
|
|
public static function get_minimum_interval_option() {
|
|
$intervals = \array_keys( self::get_schedule_interval_options() );
|
|
if ( ! empty( $intervals ) ) {
|
|
return \end( $intervals );
|
|
}
|
|
|
|
return 15 * MINUTE_IN_SECONDS;
|
|
}
|
|
|
|
/**
|
|
* Get Merchant list that are allowed on Custom2 Template
|
|
* @return array
|
|
*/
|
|
public static function get_custom2_merchant() {
|
|
return array( 'custom2', 'admarkt', 'yandex_xml', 'glami' );
|
|
}
|
|
|
|
/**
|
|
* Get Feed File URL
|
|
*
|
|
* @param string $file_name
|
|
* @param string $provider
|
|
* @param string $type
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function get_file_url( $file_name, $provider, $type ) {
|
|
$file_name = Helper::extract_feed_option_name( $file_name );
|
|
$upload_dir = wp_get_upload_dir();
|
|
|
|
return esc_url(
|
|
\sprintf(
|
|
'%s/woo-feed/%s/%s/%s.%s',
|
|
$upload_dir['baseurl'],
|
|
$provider,
|
|
$type,
|
|
$file_name,
|
|
$type
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Removes temporary feed files based on the given configuration and file name.
|
|
*
|
|
* @param array $config Feed configuration data.
|
|
* @param string $file_name The name of the feed file.
|
|
* @param bool $auto Flag indicating whether the process is automatic.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function unlink_temporary_files( $config, $file_name, $auto = false ) {
|
|
if ( ! \is_array( $config ) || ! \is_string( $file_name ) ) {
|
|
// Handle invalid input.
|
|
return;
|
|
}
|
|
|
|
$type = $config['feedType'];
|
|
$ext = self::get_file_type( $type );
|
|
$path = Helper::get_file_dir( $config['provider'], $type );
|
|
|
|
$temp_feed_body_prefix = self::get_feed_body_temp_prefix( $auto );
|
|
|
|
$files = [
|
|
'headerFile' => $path . '/' . AttributeValueByType::FEED_TEMP_HEADER_PREFIX . $file_name . '.' . $ext,
|
|
'bodyFile' => $path . '/' . $temp_feed_body_prefix . $file_name . '.' . $ext,
|
|
'footerFile' => $path . '/' . AttributeValueByType::FEED_TEMP_FOOTER_PREFIX . $file_name . '.' . $ext,
|
|
];
|
|
|
|
foreach ( $files as $file ) {
|
|
if ( \file_exists( $file ) ) {
|
|
\unlink( $file ); // Consider adding error handling here.
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Removes temporary feed files based on the given configuration and file name.
|
|
*
|
|
* @param array $config Feed configuration data.
|
|
* @param string $file_name The name of the feed file.
|
|
* @param bool $auto Flag indicating whether the process is automatic.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function unlink_temporary_cron_files( $path, $option_name, $files = [] ) {
|
|
if ( empty( $files ) || ! \is_string( $option_name ) ) {
|
|
// Handle invalid input.
|
|
return;
|
|
}
|
|
|
|
foreach ( $files as $file ) {
|
|
$temp_file_name = $path . '/' . $file;
|
|
|
|
if ( \file_exists( $temp_file_name ) ) {
|
|
\unlink( $temp_file_name ); // Consider adding error handling here.
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Saves a batch chunk of feed information to a file.
|
|
*
|
|
* @param string $feed_service Merchant service.
|
|
* @param string $type File type (extension).
|
|
* @param string|array $string Data to be saved.
|
|
* @param string $file_name File name.
|
|
* @param array $info Feed configuration.
|
|
*
|
|
* @return bool True on successful save, false otherwise.
|
|
*/
|
|
public static function save_batch_feed_info( $feed_service, $type, $string, $file_name, $info ) {
|
|
if ( ! \is_string( $feed_service ) || ! \is_string( $type ) || ! ( \is_string( $string ) || \is_array( $string ) ) || ! \is_string( $file_name ) ) {
|
|
// Handle invalid input.
|
|
return false;
|
|
}
|
|
|
|
$ext = self::get_file_type( $type );
|
|
if ( 'json' === $ext ) {
|
|
$string = \wp_json_encode( $string );
|
|
}
|
|
|
|
$path = Helper::get_file_dir( $feed_service, $type );
|
|
$file = $path . '/' . $file_name . '.' . $ext;
|
|
$status = FileSystem::saveFile( $path, $file, $string );
|
|
|
|
if ( Helper::is_debugging_enabled() ) {
|
|
$message = $status ? \sprintf( 'Batch chunk file (%s) saved.', $file_name ) :
|
|
\sprintf( 'Unable to save batch chunk file %s.', $file_name );
|
|
woo_feed_log_feed_process( $info['filename'], $message );
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Retrieves batch feed information from a file.
|
|
*
|
|
* @param string $feed_service The feed service.
|
|
* @param string $type The file type.
|
|
* @param string $file_name The file name.
|
|
*
|
|
* @return bool|array|string False if file does not exist or data is not readable, array or JSON string otherwise.
|
|
*/
|
|
public static function get_batch_feed_info( $feed_service, $type, $file_name ) {
|
|
if ( ! \is_string( $feed_service ) || ! \is_string( $type ) || ! \is_string( $file_name ) ) {
|
|
// Handle invalid input.
|
|
return false;
|
|
}
|
|
|
|
$ext = self::get_file_type( $type );
|
|
$path = Helper::get_file_dir( $feed_service, $type );
|
|
$file = $path . '/' . $file_name . '.' . $ext;
|
|
|
|
if ( ! \file_exists( $file ) ) {
|
|
return false;
|
|
}
|
|
|
|
$data = \file_get_contents( $file ); // Consider adding error handling here.
|
|
if ( false === $data ) {
|
|
return false;
|
|
}
|
|
|
|
return 'json' === $ext ? \json_decode( $data, true ) : $data;
|
|
}
|
|
|
|
/**
|
|
* Determines the appropriate file extension type for the given file type.
|
|
*
|
|
* @param string $type The file type (e.g., 'csv', 'json').
|
|
*
|
|
* @return string The determined file extension type, defaults to 'json' for certain types.
|
|
*/
|
|
public static function get_file_type( $type ) {
|
|
if ( ! \is_string( $type ) ) {
|
|
// Handle non-string type.
|
|
return '';
|
|
}
|
|
|
|
$json_types = array( 'csv', 'tsv', 'xls', 'xlsx', 'json' );
|
|
|
|
return \in_array( $type, $json_types ) ? 'json' : $type;
|
|
}
|
|
|
|
/**
|
|
* Determines if the content of a given file type should be JSON decoded.
|
|
*
|
|
* @param string $type The file type (e.g., 'csv', 'json').
|
|
*
|
|
* @return bool True if the content should be JSON decoded, false otherwise.
|
|
*/
|
|
public static function should_json_decode( $type ) {
|
|
if ( ! \is_string( $type ) ) {
|
|
// Handle non-string type.
|
|
return false;
|
|
}
|
|
|
|
$json_decodable_types = array( 'csv', 'tsv', 'xls', 'xlsx', 'json' );
|
|
|
|
return \in_array( $type, $json_decodable_types );
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $file_ext_type
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function should_create_footer( $file_ext_type ) {
|
|
return 'xml' == $file_ext_type;
|
|
}
|
|
|
|
/**
|
|
* @param $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_attribute_price_type( $value ) {
|
|
return \in_array( $value, [
|
|
'price',
|
|
'current_price',
|
|
'sale_price',
|
|
'price_with_tax',
|
|
'current_price_with_tax',
|
|
'sale_price_with_tax'
|
|
] );
|
|
}
|
|
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
public static function get_special_templates() {
|
|
return array(
|
|
'custom2',
|
|
'admarkt',
|
|
'glami',
|
|
'yandex_xml',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param $feed_info
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_product_ids( $feed_info ) {
|
|
|
|
$config = new Config( $feed_info );
|
|
|
|
do_action( 'before_woo_feed_get_product_information', $config );
|
|
|
|
$ids = QueryFactory::get_ids( $config );
|
|
|
|
do_action( 'after_woo_feed_get_product_information', $config );
|
|
|
|
return $ids;
|
|
}
|
|
|
|
private static function should_create_header_footer( $path, $feed_name, $file_type, $auto_update ) {
|
|
$should_create_header_footer = false;
|
|
|
|
$temp_feed_header_name = $auto_update ? AttributeValueByType::AUTO_FEED_TEMP_HEADER_PREFIX : AttributeValueByType::FEED_TEMP_HEADER_PREFIX;
|
|
$temp_feed_footer_name = $auto_update ? AttributeValueByType::AUTO_FEED_TEMP_FOOTER_PREFIX : AttributeValueByType::FEED_TEMP_FOOTER_PREFIX;
|
|
$temp_feed_header_name .= $feed_name . $file_type;
|
|
$temp_feed_footer_name .= $feed_name . $file_type;
|
|
|
|
if ( ! file_exists( $path . '/' . $temp_feed_header_name ) ) {
|
|
$should_create_header_footer = true;
|
|
}
|
|
|
|
if ( ! file_exists( $path . '/' . $temp_feed_footer_name ) && self::should_create_footer( $file_type ) ) {
|
|
$should_create_header_footer = true;
|
|
}
|
|
|
|
return $should_create_header_footer;
|
|
}
|
|
|
|
/**
|
|
* @param $feed_info
|
|
* @param $product_ids
|
|
* @param $offset
|
|
* @param $status
|
|
*
|
|
* @return bool|mixed
|
|
*/
|
|
public static function generate_temp_feed_body( $feed_info, $product_ids, $offset, $status = false, $auto = false ) {
|
|
|
|
$feed_rules = $feed_info['option_value']['feedrules'];
|
|
$feed_name = Helper::extract_feed_option_name( $feed_info['option_name'] );
|
|
|
|
$config = new Config( $feed_info );
|
|
|
|
do_action( 'before_woo_feed_generate_batch_data', $config );
|
|
|
|
if ( ! empty( $feed_rules['provider'] ) ) {
|
|
|
|
$provider = $config->get_feed_template();
|
|
$file_ext_type = $config->get_feed_file_type();
|
|
if ( $offset === 0 ) {
|
|
self::unlink_temporary_files( $feed_rules, $feed_rules['filename'], $auto );
|
|
}
|
|
$path = Helper::get_file_dir( $provider, $file_ext_type );
|
|
|
|
$feed_template = TemplateFactory::make_feed( $product_ids, $config );
|
|
//Generate Header footer
|
|
// TODO: call this function only when offset is 0. But when creating the new feed 0 is calling 2 times. and not generating the header footer.
|
|
if ( self::should_create_header_footer( $path, $feed_name, $file_ext_type, $auto ) ) {
|
|
self::generate_header_footer( $feed_template, $file_ext_type, $feed_name, $feed_rules, $provider, $auto );
|
|
}
|
|
|
|
$current_feed = $feed_template->get_feed();
|
|
woo_feed_log_feed_process( $feed_rules['filename'], sprintf( 'Initializing merchant Class %s for %s', $provider, $provider ) );
|
|
if ( ! empty( $current_feed ) ) {
|
|
// Get previous feed body data from temporary file to concat with current data.
|
|
//$temp_feed_body_name = AttributeValueByType::AUTO_FEED_TEMP_BODY_PREFIX . $feed_name;
|
|
$temp_feed_body_prefix = self::get_feed_body_temp_prefix( $auto );
|
|
$temp_feed_body_name = $temp_feed_body_prefix . $feed_name;
|
|
|
|
$previous_feed = self::get_batch_feed_info( $provider, $file_ext_type, $temp_feed_body_name );
|
|
|
|
// Has previous feed body.
|
|
if ( $previous_feed ) {
|
|
/**
|
|
* If file extension type is csv, tsv, xls, json, xlsx then
|
|
* merge previous array with current array
|
|
*
|
|
* Else concat previous feed body with current feed body
|
|
*/
|
|
if ( 'csv' === $file_ext_type || 'tsv' === $file_ext_type || 'xls' === $file_ext_type || 'json' === $file_ext_type || 'xlsx' === $file_ext_type ) {
|
|
if ( \is_array( $previous_feed ) ) {
|
|
$newFeed = \array_merge( $previous_feed, $current_feed );
|
|
self::save_batch_feed_info( $provider, $file_ext_type, $newFeed, $temp_feed_body_name, $feed_rules );
|
|
} else {
|
|
$newFeed = $previous_feed . $current_feed;
|
|
self::save_batch_feed_info( $provider, $file_ext_type, $newFeed, $temp_feed_body_name, $feed_rules );
|
|
}
|
|
} else {
|
|
$newFeed = $previous_feed . $current_feed;
|
|
self::save_batch_feed_info( $provider, $file_ext_type, $newFeed, $temp_feed_body_name, $feed_rules );
|
|
}
|
|
} else {
|
|
self::save_batch_feed_info( $provider, $file_ext_type, $current_feed, $temp_feed_body_name, $feed_rules );
|
|
}
|
|
$status = true;
|
|
} else {
|
|
$status = false;
|
|
}
|
|
}
|
|
do_action( 'after_woo_feed_generate_batch_data', $config );
|
|
|
|
return $status;
|
|
}
|
|
|
|
private static function get_re_indexed_files( $files ) {
|
|
|
|
$header_index = null;
|
|
$footer_index = null;
|
|
$header_value = '';
|
|
$footer_value = '';
|
|
// Find header and footer indices
|
|
foreach ( $files as $key => $value ) {
|
|
if ( strpos( $value, 'header' ) !== false ) {
|
|
$header_index = $key;
|
|
}
|
|
if ( strpos( $value, 'footer' ) !== false ) {
|
|
$footer_index = $key;
|
|
}
|
|
}
|
|
|
|
// Move header to the first position if it exists
|
|
if ( isset( $files[ $header_index ] ) && $header_index !== null ) {
|
|
$header_value = $files[ $header_index ];
|
|
unset( $files[ $header_index ] );
|
|
}
|
|
|
|
// Move footer to the last position if it exists
|
|
if ( isset( $files[ $footer_index ] ) && $footer_index !== null ) {
|
|
$footer_value = $files[ $footer_index ];
|
|
unset( $files[ $footer_index ] );
|
|
}
|
|
|
|
|
|
if ( ! empty( $header_value ) ) {
|
|
array_unshift( $files, $header_value );
|
|
}
|
|
if ( ! empty( $footer_value ) ) {
|
|
array_push( $files, $footer_value );
|
|
}
|
|
|
|
|
|
return array_values( $files );
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $path
|
|
* @param $option_name
|
|
* @param $feed_type_ext
|
|
*
|
|
* @return array
|
|
*/
|
|
private static function get_re_indexed_and_valid_files( $path, $option_name, $feed_type_ext ) {
|
|
|
|
// get all batched files and merge them. and save them in one file to extension type folder.
|
|
// Read files in the directory
|
|
$files = scandir( $path );
|
|
|
|
// Filter out '.' and '..' (current and parent directory entries)
|
|
$files = array_diff( $files, array( '.', '..' ) );
|
|
|
|
|
|
$valid_files = [];
|
|
// Find header and footer indices
|
|
foreach ( $files as $key => $file ) {
|
|
|
|
if ( strpos( $file, $feed_type_ext ) === false || strpos( $file, $option_name ) === false || empty( $file ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( strpos( $file, 'header' ) !== false && strpos( $file, AttributeValueByType::AUTO_FEED_TEMP_HEADER_PREFIX ) !== false ) {
|
|
$valid_files[] = $file;
|
|
continue;
|
|
}
|
|
|
|
if ( strpos( $file, 'footer' ) !== false && strpos( $file, AttributeValueByType::AUTO_FEED_TEMP_FOOTER_PREFIX ) !== false ) {
|
|
$valid_files[] = $file;
|
|
continue;
|
|
}
|
|
|
|
if ( strpos( $file, AttributeValueByType::AUTO_FEED_TEMP_BODY_PREFIX ) === false ) {
|
|
continue;
|
|
}
|
|
|
|
$valid_files[] = $file;
|
|
|
|
}
|
|
|
|
$get_re_indexed_files = self::get_re_indexed_files( $valid_files );
|
|
|
|
return $get_re_indexed_files;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $feed_info
|
|
* @param $should_update_last_update_time
|
|
*
|
|
* <<<<<<< HEAD
|
|
* =======
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function save_cron_batched_feed_files( $feed_info, $should_update_last_update_time = false, $auto = true ) {
|
|
$option_name_orginal = $feed_info['option_name'];
|
|
$provider = $feed_info['option_value']['feedrules']['provider'];
|
|
$feed_type_ext = $feed_info['option_value']['feedrules']['feedType'];
|
|
|
|
$path = Helper::get_file_dir( $provider, $feed_type_ext );
|
|
$option_name = Helper::extract_feed_option_name( $option_name_orginal );
|
|
$feed_url = Helper::get_file_url( $option_name, $provider, $feed_type_ext );
|
|
$contents = '';
|
|
|
|
$files = self::get_re_indexed_and_valid_files( $path, $option_name, $feed_type_ext );
|
|
|
|
foreach ( $files as $file ) {
|
|
$temp_content = FileSystem::ReadFile( $path, $file );
|
|
// If there is a problem regarding file system or other.
|
|
if ( is_wp_error( $temp_content ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( self::should_json_decode( $feed_type_ext ) ) {
|
|
$temp_content = \json_decode( $temp_content, true );
|
|
if ( \is_array( $temp_content ) || 'json' === $feed_type_ext ) { // json, csv fil
|
|
$temp_contents = $contents ? $contents : [];
|
|
$temp_content = $temp_content ? $temp_content : [];
|
|
$contents = \array_merge( $temp_contents, $temp_content );
|
|
} else {
|
|
$contents .= $temp_content;
|
|
}
|
|
} else {
|
|
$contents .= $temp_content;
|
|
}
|
|
}
|
|
|
|
|
|
$file_name = $option_name . '.' . $feed_type_ext;
|
|
|
|
if ( is_array( $contents ) ) { // file type json, csv
|
|
$contents = wp_json_encode( $contents );
|
|
$status = FileSystem::WriteFile( $contents, $path, $file_name );
|
|
}else if ( $contents ) {
|
|
$status = FileSystem::WriteFile( $contents, $path, $file_name );
|
|
} else {
|
|
$status = false;
|
|
}
|
|
|
|
// Upload ftp/sftp if enabled.
|
|
self::upload_feed_file_to_ftp_server( $feed_info, $path, $file_name );
|
|
|
|
// Remove temporary files.
|
|
self::unlink_temporary_cron_files( $path, $option_name, $files );
|
|
|
|
// Delete temporary cache data.
|
|
Cache::delete( 'wad_discounts' );
|
|
|
|
if ( ! isset( $feed_info['option_value']['url'] ) ) {
|
|
$feed_info['option_value']['url'] = Helper::get_file_url( $feed_info['option_name'], $feed_info['option_value']['feedrules']['provider'], $feed_info['option_value']['feedrules']['feedType'] );
|
|
}
|
|
|
|
if ( ! isset( $feed_info['option_value']['status'] ) ) {
|
|
$feed_info['option_value']['status'] = false;
|
|
}
|
|
|
|
if ( $should_update_last_update_time ) {
|
|
$feed_info['option_value']['last_updated'] = \date( 'Y-m-d H:i:s', \strtotime( \current_time( 'mysql' ) ) );
|
|
update_option( $option_name_orginal, $feed_info['option_value'] );
|
|
}
|
|
|
|
return [
|
|
'status' => $status,
|
|
'feed_url' => $feed_url,
|
|
];
|
|
|
|
}
|
|
|
|
/**
|
|
* @param $feed_info
|
|
* @param $should_update_last_update_time
|
|
*
|
|
* >>>>>>> feature/CV-79
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function save_feed_file( $feed_info, $should_update_last_update_time = false, $auto = false ) {
|
|
$option_name_orginal = $feed_info['option_name'];
|
|
$provider = $feed_info['option_value']['feedrules']['provider'];
|
|
$feed_type_ext = $feed_info['option_value']['feedrules']['feedType'];
|
|
|
|
$path = Helper::get_file_dir( $provider, $feed_type_ext );
|
|
$option_name = Helper::extract_feed_option_name( $option_name_orginal );
|
|
$feed_url = Helper::get_file_url( $option_name, $provider, $feed_type_ext );
|
|
|
|
$contents = '';
|
|
$sections = [ 'header', 'body', 'footer' ];
|
|
// Remove the footer if feed type is csv
|
|
if ( ! self::should_create_footer( $feed_type_ext ) ) {
|
|
$sections = \array_filter( $sections, function ( $section ) {
|
|
return 'footer' != $section;
|
|
} );
|
|
}
|
|
|
|
$temp_file_name = '';
|
|
foreach ( $sections as $section ) {
|
|
$temp_file_ext = self::get_file_type( $feed_type_ext );
|
|
if ( 'header' === $section ) {
|
|
$temp_file_name = AttributeValueByType::FEED_TEMP_HEADER_PREFIX . $option_name . '.' . $temp_file_ext;
|
|
} elseif ( 'footer' === $section ) {
|
|
$temp_file_name = AttributeValueByType::FEED_TEMP_FOOTER_PREFIX . $option_name . '.' . $temp_file_ext;
|
|
} else {
|
|
$temp_feed_body_prefix = self::get_feed_body_temp_prefix( $auto );
|
|
$temp_file_name = $temp_feed_body_prefix . $option_name . '.' . $temp_file_ext;
|
|
}
|
|
|
|
$temp_content = FileSystem::ReadFile( $path, $temp_file_name );
|
|
|
|
// If there is a problem regarding file system or other.
|
|
if ( is_wp_error( $temp_content ) ) {
|
|
$status = new WP_Error(
|
|
$temp_content->get_error_code(),
|
|
$temp_content->get_error_message(),
|
|
[ 'status' => 404 ]
|
|
);
|
|
|
|
return [
|
|
'status' => $status,
|
|
'feed_url' => $feed_url,
|
|
];
|
|
}
|
|
|
|
if ( self::should_json_decode( $feed_type_ext ) ) {
|
|
$temp_content = \json_decode( $temp_content, true );
|
|
if ( \is_array( $temp_content ) || 'json' === $feed_type_ext ) { // json, csv fil
|
|
$temp_contents = $contents ? $contents : [];
|
|
$temp_content = $temp_content ? $temp_content : [];
|
|
$contents = \array_merge( $temp_contents, $temp_content );
|
|
} else {
|
|
$contents .= $temp_content;
|
|
}
|
|
} else {
|
|
$contents .= $temp_content;
|
|
}
|
|
}
|
|
|
|
$file_name = $option_name . '.' . $feed_type_ext;
|
|
|
|
if ( is_array( $contents ) ) { // file type json, csv
|
|
$contents = wp_json_encode( $contents );
|
|
$status = FileSystem::WriteFile( $contents, $path, $file_name );
|
|
} else {
|
|
$status = FileSystem::WriteFile( $contents, $path, $file_name );
|
|
}
|
|
|
|
// Upload ftp/sftp if enabled.
|
|
self::upload_feed_file_to_ftp_server( $feed_info, $path, $file_name );
|
|
|
|
// Remove temporary files.
|
|
self::unlink_temporary_files( $feed_info['option_value']['feedrules'], $option_name, $auto );
|
|
|
|
// Delete temporary cache data.
|
|
Cache::delete( 'wad_discounts' );
|
|
|
|
if ( ! isset( $feed_info['option_value']['url'] ) ) {
|
|
$feed_info['option_value']['url'] = Helper::get_file_url( $feed_info['option_name'], $feed_info['option_value']['feedrules']['provider'], $feed_info['option_value']['feedrules']['feedType'] );
|
|
}
|
|
|
|
if ( ! isset( $feed_info['option_value']['status'] ) ) {
|
|
$feed_info['option_value']['status'] = false;
|
|
}
|
|
|
|
if ( $should_update_last_update_time ) {
|
|
$feed_info['option_value']['last_updated'] = \date( 'Y-m-d H:i:s', \strtotime( \current_time( 'mysql' ) ) );
|
|
update_option( $option_name_orginal, $feed_info['option_value'] );
|
|
}
|
|
|
|
delete_transient( 'ctx_feed_structure_transient' );
|
|
|
|
do_action('ctx_feed_after_save_feed_file', $status, $feed_info, $should_update_last_update_time, $auto );
|
|
|
|
return [
|
|
'status' => $status,
|
|
'feed_url' => $feed_url,
|
|
];
|
|
|
|
}
|
|
|
|
/**
|
|
* @param $feed_info
|
|
* @param $path
|
|
* @param $file_name
|
|
*
|
|
* @return void
|
|
* @throws \CTXFeed\V5\FTP\FtpException
|
|
*/
|
|
private static function upload_feed_file_to_ftp_server( $feed_info, $path, $file_name ) {
|
|
|
|
/**
|
|
* class FtpClient only can upload ftp/ftps not sftp upload.
|
|
* ftp_ssl_connect method is used for FTP SSL file upload
|
|
* ssh2_sftp is intended to use for sFTP file upload
|
|
*
|
|
* That's why here we use FtpClient class for FTP file upload and
|
|
* self::handle_file_transfer for sFTP uload.
|
|
*
|
|
* @see https://secure.helpscout.net/conversation/2390941164/29741?folderId=713813
|
|
* @see https://www.php.net/manual/en/function.ftp-ssl-connect.php
|
|
* @see https://www.php.net/manual/en/function.ssh2-sftp.php
|
|
* @see https://www.spiceworks.com/tech/networking/articles/sftp-vs-ftps/
|
|
*/
|
|
$global_ftp_status= Settings:: get();
|
|
if ( isset( $global_ftp_status['enable_ftp_upload'] ) && $global_ftp_status['enable_ftp_upload']=='yes' ) {
|
|
|
|
if (isset($feed_info['option_value']['feedrules']['ftpenabled']) && $feed_info['option_value']['feedrules']['ftpenabled']) {
|
|
$path = $path . '/' . $file_name; // locale file path to upload.
|
|
|
|
if (isset($feed_info['option_value']['feedrules']['ftporsftp']) & 'ftp' === $feed_info['option_value']['feedrules']['ftporsftp']) {
|
|
/*$ftp = new FtpClient();
|
|
$ftp_connect = $ftp->connect( $feed_info['option_value']['feedrules']['ftphost'], false, $feed_info['option_value']['feedrules']['ftpport'] ); // connect to ftp/sftp server
|
|
$ftp_connect = $ftp_connect->login( $feed_info['option_value']['feedrules']['ftpuser'], $feed_info['option_value']['feedrules']['ftppassword'] ); // login to server
|
|
|
|
$ftp_connect->putFromPath( $path );*/
|
|
|
|
$remote_file = basename($path);
|
|
self::uploadFileInFtp($feed_info['option_value']['feedrules']['ftpuser'], $feed_info['option_value']['feedrules']['ftppassword'], $feed_info['option_value']['feedrules']['ftphost'], $path, $remote_file);
|
|
|
|
|
|
} else {
|
|
$feed_rules = $feed_info['option_value']['feedrules'];
|
|
$is_file_uploaded = self::handle_file_transfer($path, $file_name, $feed_rules);
|
|
if ($is_file_uploaded) {
|
|
woo_feed_log_feed_process($file_name, 'file transfer request success.');
|
|
} else {
|
|
woo_feed_log_feed_process($file_name, 'Unable to process file transfer request.');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Transfer file as per ftp config
|
|
*
|
|
* @param string $file_from
|
|
* @param string $file_to
|
|
* @param array $info
|
|
*
|
|
* @return bool
|
|
*/
|
|
private static function handle_file_transfer( $file_from, $file_to, $info ) {
|
|
if ( $info['ftpenabled'] ) {
|
|
if ( ! file_exists( $file_from ) ) {
|
|
\woo_feed_log_feed_process( $info['filename'], 'Unable to process file transfer request. File does not exists.' );
|
|
|
|
return false;
|
|
}
|
|
$ftp_host = \sanitize_text_field( $info['ftphost'] );
|
|
$ftp_user = \sanitize_text_field( $info['ftpuser'] );
|
|
$ftp_password = \sanitize_text_field( $info['ftppassword'] );
|
|
$ftp_path = \trailingslashit( \untrailingslashit( \sanitize_text_field( $info['ftppath'] ) ) );
|
|
$ftp_passive_mode = ( isset( $info['ftpmode'] ) && \sanitize_text_field( $info['ftpmode'] ) === 'passive' ) ? true : false;
|
|
if ( isset( $info['ftporsftp'] ) & 'ftp' === $info['ftporsftp'] ) {
|
|
$ftporsftp = 'ftp';
|
|
} else {
|
|
$ftporsftp = 'sftp';
|
|
}
|
|
if ( isset( $info['ftpport'] ) && ! empty( $info['ftpport'] ) ) {
|
|
$ftp_port = \absint( $info['ftpport'] );
|
|
} else {
|
|
$ftp_port = false;
|
|
}
|
|
|
|
if ( ! $ftp_port || ! ( ( 1 <= $ftp_port ) && ( $ftp_port <= 65535 ) ) ) {
|
|
$ftp_port = 'sftp' === $ftporsftp ? 22 : 21;
|
|
}
|
|
|
|
\woo_feed_log_feed_process( $info['filename'], sprintf( 'Uploading Feed file via %s.', $ftporsftp ) );
|
|
|
|
|
|
try {
|
|
if ( 'ftp' === $ftporsftp ) {
|
|
|
|
$ftp = new \WebAppick\FTP\FTPConnection();
|
|
if ( $ftp->connect( $ftp_host, $ftp_user, $ftp_password, $ftp_passive_mode, $ftp_port ) ) {
|
|
return $ftp->upload_file( $file_from, $ftp_path . $file_to );
|
|
}
|
|
} elseif ( 'sftp' === $ftporsftp ) {
|
|
$sftp = new \WebAppick\FTP\SFTPConnection( $ftp_host, $ftp_port );
|
|
$sftp->login( $ftp_user, $ftp_password );
|
|
|
|
return $sftp->upload_file( $file_from, $file_to, $ftp_path );
|
|
|
|
}
|
|
} catch ( \Exception $e ) {
|
|
$message = 'Error Uploading Feed Via ' . $ftporsftp . PHP_EOL . 'Caught Exception :: ' . $e->getMessage();
|
|
\woo_feed_log( $info['filename'], $message, 'critical', $e, true );
|
|
\woo_feed_log_fatal_error( $message, $e );
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param array $feed_rules
|
|
* @param int $offset
|
|
* @param array $product_ids
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function log_data( $feed_rules, $offset, $product_ids ) {
|
|
\woo_feed_log_feed_process( $feed_rules['filename'], \sprintf( 'Processing Loop %d.', ( $offset + 1 ) ) );
|
|
$m = 'Processing Product Following Product (IDs) : ' . PHP_EOL;
|
|
foreach ( \array_chunk( $product_ids, 10 ) as $ids ) { // pretty print log [B-)=
|
|
$m .= \implode( ', ', $ids ) . PHP_EOL;
|
|
}
|
|
|
|
\woo_feed_log_feed_process( $feed_rules['filename'], $m );
|
|
}
|
|
|
|
|
|
/**
|
|
* Generates and saves the header and footer for a feed.
|
|
*
|
|
* @param object $feed_template The feed template object.
|
|
* @param string $file_ext_type The file extension type.
|
|
* @param string $feed_name The name of the feed.
|
|
* @param array $feed_rules Feed rules.
|
|
* @param string $provider The provider.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function generate_header_footer( $feed_template, $file_ext_type, $feed_name, $feed_rules, $provider, $auto_update = false ) {
|
|
$feed_header = $feed_template->get_header();
|
|
$feed_footer = $feed_template->get_footer();
|
|
|
|
$temp_feed_header_name = $auto_update ? AttributeValueByType::AUTO_FEED_TEMP_HEADER_PREFIX . $feed_name : AttributeValueByType::FEED_TEMP_HEADER_PREFIX . $feed_name;
|
|
$temp_feed_footer_name = $auto_update ? AttributeValueByType::AUTO_FEED_TEMP_FOOTER_PREFIX . $feed_name : AttributeValueByType::FEED_TEMP_FOOTER_PREFIX . $feed_name;
|
|
// TODO: should generate footer when template type is csv ?
|
|
self::save_batch_feed_info( $provider, $file_ext_type, $feed_header, $temp_feed_header_name, $feed_rules );
|
|
|
|
// create footer for xml file .
|
|
if ( self::should_create_footer( $file_ext_type ) ) {
|
|
self::save_batch_feed_info( $provider, $file_ext_type, $feed_footer, $temp_feed_footer_name, $feed_rules );
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Generates a feed during a cron job.
|
|
*
|
|
* @param array $feed_info Feed configuration information.
|
|
* @param int $offset Offset for batch processing.
|
|
* @param bool $should_update_last_update_time Flag indicating whether to update the last update time.
|
|
*
|
|
* @return bool True if the feed generation is successful, false otherwise.
|
|
*/
|
|
public static function generate_feed( $feed_info, $offset = 0, $should_update_last_update_time = true ) {
|
|
if ( ! \is_array( $feed_info ) || ! isset( $feed_info['option_value'] ) ) {
|
|
// Handle invalid input.
|
|
return false;
|
|
}
|
|
|
|
if ( $offset < 0 ) {
|
|
// Handle invalid offset.
|
|
return false;
|
|
}
|
|
|
|
$ids = self::get_product_ids( $feed_info );
|
|
|
|
if ( empty( $ids ) ) {
|
|
// Handle the case where no product IDs are found.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This parameter is used to check if the feed is generated by cron or not.
|
|
* Even the feed is generated by cron, it will be considered as manual feed.
|
|
* Because, The header, footer and body prefix is same for the manual and old cron feed.
|
|
* But the new cron feed has different prefix for header, footer and body.
|
|
* And this function is only called from old cron job functionality. So, it's not a new cron feed.
|
|
* That's why we have to send this parameter false to generate_temp_feed_body function.
|
|
*
|
|
* @link: https://webappick.atlassian.net/browse/CBT-363
|
|
* @since 7.3.13
|
|
*/
|
|
$is_auto_feed = false;
|
|
|
|
$status = self::generate_temp_feed_body( $feed_info, $ids, $offset, false, $is_auto_feed );
|
|
|
|
if ( $status ) {
|
|
self::save_feed_file( $feed_info, $should_update_last_update_time, $is_auto_feed );
|
|
}
|
|
|
|
return $status;
|
|
}
|
|
|
|
|
|
/**
|
|
* Generates a feed during a cron job.
|
|
*
|
|
* @param array $feed_info Feed configuration information.
|
|
* @param int $offset Offset for batch processing.
|
|
* @param bool $should_update_last_update_time Flag indicating whether to update the last update time.
|
|
*
|
|
* @return bool True if the feed generation is successful, false otherwise.
|
|
*/
|
|
public static function generate_cron_batched_feed( $feed_info, $offset = 0, $should_update_last_update_time = true, $ids = [] ) {
|
|
if ( ! \is_array( $feed_info ) || ! isset( $feed_info['option_value'] ) ) {
|
|
// Handle invalid input.
|
|
return false;
|
|
}
|
|
|
|
if ( empty( $ids ) ) {
|
|
// Handle the case where no product IDs are found.
|
|
return false;
|
|
}
|
|
|
|
$status = self::generate_temp_feed_body( $feed_info, $ids, $offset, false, true );
|
|
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Extracts a substring from a given string, delimited by start and end markers.
|
|
*
|
|
* @param string $string The full string to extract from.
|
|
* @param string $start The start marker of the desired substring.
|
|
* @param string $end The end marker of the desired substring.
|
|
*
|
|
* @return string The extracted substring, or an empty string if markers are not found.
|
|
*/
|
|
public static function get_string_between( $string, $start, $end ) {
|
|
if ( ! \is_string( $string ) || ! \is_string( $start ) || ! \is_string( $end ) ) {
|
|
// Handle invalid inputs.
|
|
return '';
|
|
}
|
|
|
|
$start_pos = \strpos( $string, $start );
|
|
|
|
if ( $start_pos === false ) {
|
|
return '';
|
|
}
|
|
|
|
$start_pos += \strlen( $start );
|
|
$end_pos = \strpos( $string, $end, $start_pos );
|
|
|
|
if ( $end_pos === false ) {
|
|
return '';
|
|
}
|
|
|
|
return \substr( $string, $start_pos, $end_pos - $start_pos );
|
|
}
|
|
|
|
/**
|
|
* Validate old feeds during cron job.
|
|
*
|
|
* @param array $feed_info feed information.
|
|
*
|
|
* @return array An array return form old feed.
|
|
*/
|
|
public static function validate_feed( $feed_info ) {
|
|
$temp_make_feed = $feed_info;
|
|
// Modify old feed data
|
|
$temp_make_rules = $temp_make_feed['option_value']['feedrules'];
|
|
$should_modify_filter = array(
|
|
'is_outOfStock' => false,
|
|
'is_backorder' => false,
|
|
'is_emptyDescription' => false,
|
|
'is_emptyImage' => false,
|
|
'is_emptyPrice' => false,
|
|
'product_visibility' => false,
|
|
'outofstock_visibility' => false,
|
|
);
|
|
$should_modify_filter = \array_keys( $should_modify_filter );
|
|
$feed_default_value = array( 'product_ids', 'post_status', 'categories' );
|
|
|
|
foreach ( $temp_make_rules as $key => $value ) {
|
|
if ( \in_array( $key, $should_modify_filter ) ) {
|
|
$temp_make_rules[ $key ] = self::get_toggle_value( $temp_make_rules[ $key ] );
|
|
}
|
|
|
|
/**
|
|
* Some previous feed is saving an error as value of product_ids.
|
|
* this value should be an array, it's default value is an array
|
|
*/
|
|
|
|
if ( \in_array( $key, $feed_default_value ) && ! \is_array( $temp_make_rules[ $key ] ) ) {
|
|
if ( $temp_make_rules[ $key ] ) {
|
|
if ( 'product_ids' === $key ) { // if key is product_ids then remove the extra space from ids.
|
|
$temp_data = \explode( ',', $temp_make_rules[ $key ] );
|
|
$temp_data = \array_map( 'absint', $temp_data );
|
|
$temp_make_rules[ $key ] = $temp_data;
|
|
} else {
|
|
$temp_make_rules[ $key ] = \explode( ',', $temp_make_rules[ $key ] );
|
|
}
|
|
} else {
|
|
$temp_make_rules[ $key ] = array();
|
|
}
|
|
}
|
|
}
|
|
|
|
$temp_make_feed['option_value']['feedrules'] = $temp_make_rules;
|
|
|
|
return $temp_make_feed;
|
|
}
|
|
|
|
/**
|
|
* Validate feed config.
|
|
*
|
|
* @param array $feed_rules feed rules.
|
|
*
|
|
* @return array feed config.
|
|
*/
|
|
public static function validate_config( $feed_rules ) {
|
|
// Modify old feed data
|
|
$temp_feed_rules = $feed_rules;
|
|
$should_modify_filter = array(
|
|
'is_outOfStock' => false,
|
|
'is_backorder' => false,
|
|
'is_emptyDescription' => false,
|
|
'is_emptyImage' => false,
|
|
'is_emptyPrice' => false,
|
|
'product_visibility' => false,
|
|
'outofstock_visibility' => false,
|
|
'is_emptyTitle' => false,
|
|
|
|
);
|
|
$should_modify_filter = \array_keys( $should_modify_filter );
|
|
|
|
foreach ( $temp_feed_rules as $key => $value ) {
|
|
if ( \in_array( $key, $should_modify_filter ) ) {
|
|
$temp_feed_rules[ $key ] = self::get_toggle_value( $temp_feed_rules[ $key ] );
|
|
}
|
|
}
|
|
|
|
return $temp_feed_rules;
|
|
}
|
|
|
|
/**
|
|
* Determines the boolean value based on various representations of 'false'.
|
|
*
|
|
* @param mixed $toggle_value The value to evaluate.
|
|
*
|
|
* @return bool Returns false for common representations of 'false', otherwise true.
|
|
*/
|
|
public static function get_toggle_value( $toggle_value ) {
|
|
$false_values = array( 'disable', 'off', 'no', false, '', 0, 'n', '0', 'false' );
|
|
|
|
// Check if the value is in the list of 'false' representations.
|
|
return ! \in_array( $toggle_value, $false_values, true );
|
|
}
|
|
|
|
/**
|
|
* Returns the appropriate temporary feed body prefix based on the automatic flag.
|
|
*
|
|
* @param bool $auto Indicates whether the automatic mode is enabled.
|
|
*
|
|
* @return string The temporary feed body prefix.
|
|
*/
|
|
public static function get_feed_body_temp_prefix( $auto = false ) {
|
|
if ( ! \is_bool( $auto ) ) {
|
|
// Handle non-boolean input.
|
|
return AttributeValueByType::FEED_TEMP_BODY_PREFIX;
|
|
}
|
|
|
|
$temp_feed_body_prefix = $auto ? AttributeValueByType::AUTO_FEED_TEMP_BODY_PREFIX : AttributeValueByType::FEED_TEMP_BODY_PREFIX;
|
|
|
|
return apply_filters( 'woo_feed_temp_feed_body_prefix', $temp_feed_body_prefix, $auto );
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public static function should_generate_feed_by_ajax() {
|
|
|
|
$should_generate_feed_by_ajax = true;
|
|
if ( is_plugin_active( 'polylang/polylang.php' ) ) {
|
|
$should_generate_feed_by_ajax = false;
|
|
}
|
|
|
|
if ( is_plugin_active( 'woocommerce-multilingual/wpml-woocommerce.php' ) ) {
|
|
$should_generate_feed_by_ajax = false;
|
|
}
|
|
|
|
$theme = wp_get_theme(); // gets the current theme
|
|
if ( 'Woodmart' == $theme->parent_theme ) {
|
|
$should_generate_feed_by_ajax = false;
|
|
}
|
|
|
|
return apply_filters( 'woo_feed_generate_feed_by_ajax', $should_generate_feed_by_ajax );
|
|
}
|
|
|
|
public static function uploadFileInFtp( $ftpUsername, $ftpPassword, $ftpServer, $localFilePath, $serverFilePath ) {
|
|
$conn_id = ftp_connect( $ftpServer );
|
|
if ( ! $conn_id ) {
|
|
throw new FtpException( "Failed to connect to the FTP server" );
|
|
}
|
|
$login = ftp_login( $conn_id, $ftpUsername, $ftpPassword );
|
|
if ( ! $login ) {
|
|
throw new FtpException( "FTP login failed" );
|
|
}
|
|
ftp_pasv( $conn_id, true );
|
|
|
|
if ( ! file_exists( $localFilePath ) ) {
|
|
throw new FtpException( "Local file not found: ".esc_attr($localFilePath)."." );
|
|
}
|
|
$content = file_get_contents( $localFilePath );
|
|
$tmp = fopen( tempnam( sys_get_temp_dir(), $localFilePath ), "w+" );
|
|
fwrite( $tmp, $content );
|
|
rewind( $tmp );
|
|
$upload = ftp_fput( $conn_id, $serverFilePath, $tmp, FTP_BINARY );
|
|
ftp_close( $conn_id );
|
|
|
|
if ( $upload ) {
|
|
return true;
|
|
} else {
|
|
throw new FtpException(
|
|
'Unable to put the remote file from the local file "' . esc_attr($localFilePath) . '"'
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
}
|