417 lines
14 KiB
PHP
417 lines
14 KiB
PHP
<?php /** @noinspection ALL */
|
|
|
|
/**
|
|
* WP Db Management Class.
|
|
*
|
|
* @package WP Product Feed Manager/Data/Classes
|
|
* @version 1.9.0
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
if ( ! class_exists( 'WPPFM_Db_Management' ) ) :
|
|
|
|
/**
|
|
* Db Management Class
|
|
*/
|
|
class WPPFM_Db_Management {
|
|
|
|
/**
|
|
* Checks if a table exists in the database.
|
|
*
|
|
* @param string $table_name Name of the table to check.
|
|
*
|
|
* @return boolean true if the table exists, false if not.
|
|
*/
|
|
public static function table_exists( $table_name ) {
|
|
global $wpdb;
|
|
|
|
// Check if the table can be queried
|
|
$table = $wpdb->prefix . $table_name;
|
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- No core API for table existence; query is prepared. Caching table existence checks doesn't make sense.
|
|
if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table ) ) === $table ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Makes a duplicate of a selected feed and stores it in the database.
|
|
*
|
|
* @param string $feed_id Feed id of the feed that needs to be duplicated.
|
|
*
|
|
* @return boolean False if duplication process failed.
|
|
*/
|
|
public static function duplicate_feed( $feed_id ) {
|
|
$queries_class = new WPPFM_Queries();
|
|
$support_class = new WPPFM_Feed_Support();
|
|
|
|
// Get the feed data.
|
|
$feed_data = $queries_class->get_feed_row( $feed_id );
|
|
|
|
// Get the meta data.
|
|
$meta_data = $queries_class->read_metadata( $feed_id );
|
|
|
|
// Get the Feed Filter data.
|
|
$feed_filter_data = $queries_class->get_product_filter_query( $feed_id );
|
|
|
|
// Get the category mapping.
|
|
$category_mapping = $queries_class->read_category_mapping( $feed_id );
|
|
|
|
// Generate a new unique feed name.
|
|
$feed_data->title = $support_class->next_unique_feed_name( $feed_data->title );
|
|
$feed_data->url = __( 'Feed needs to be generated first', 'wp-product-feed-manager' );
|
|
|
|
$feed_data_to_store = array(
|
|
'channel_id' => $feed_data->channel_id,
|
|
'language' => $feed_data->language,
|
|
'is_aggregator' => $feed_data->is_aggregator,
|
|
'include_variations' => $feed_data->include_variations,
|
|
'country_id' => $feed_data->country_id,
|
|
'source_id' => $feed_data->source_id,
|
|
'title' => $feed_data->title,
|
|
'feed_title' => $feed_data->feed_title,
|
|
'feed_description' => $feed_data->feed_description,
|
|
'main_category' => $feed_data->main_category,
|
|
'url' => $feed_data->url,
|
|
'status_id' => $feed_data->status_id,
|
|
'schedule' => $feed_data->schedule,
|
|
'products' => 0,
|
|
'feed_type_id' => $feed_data->feed_type_id,
|
|
'aggregator_name' => $feed_data->aggregator_name,
|
|
'publisher_name' => $feed_data->publisher_name,
|
|
'publisher_favicon_url' => $feed_data->publisher_favicon_url,
|
|
'currency' => $feed_data->currency,
|
|
'google_analytics' => $feed_data->google_analytics,
|
|
'utm_id' => $feed_data->utm_id,
|
|
'utm_source' => $feed_data->utm_source,
|
|
'utm_medium' => $feed_data->utm_medium,
|
|
'utm_campaign' => $feed_data->utm_campaign,
|
|
'utm_source_platform' => $feed_data->utm_source_platform,
|
|
'utm_term' => $feed_data->utm_term,
|
|
'utm_content' => $feed_data->utm_content,
|
|
);
|
|
|
|
$feed_data_types = array(
|
|
'%d',
|
|
'%s',
|
|
'%d',
|
|
'%d',
|
|
'%d',
|
|
'%d',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%d',
|
|
'%s',
|
|
'%d',
|
|
'%d',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%d',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
'%s',
|
|
);
|
|
|
|
// Store a copy of the new feed in the database.
|
|
$new_feed_id = $queries_class->create_feed( $feed_data_to_store, $feed_data_types );
|
|
|
|
$new_feed_id > 0 ? $queries_class->insert_meta_data( $new_feed_id, $meta_data, $feed_filter_data, $category_mapping ) : false;
|
|
}
|
|
|
|
/**
|
|
* Backups all plugin related data from the database to a file
|
|
*
|
|
* @since 1.7.2
|
|
*
|
|
* @param string $backup_file_name the file name under which to store the backup.
|
|
*
|
|
* @return boolean true if the backup is successfull, false if not.
|
|
*/
|
|
public static function backup_database_tables( $backup_file_name ) {
|
|
$backup_class = new WPPFM_Backup();
|
|
$file_class = new WPPFM_File();
|
|
|
|
$backup_file = WPPFM_BACKUP_DIR . '/' . $backup_file_name . '.sql';
|
|
$backup_path = str_replace( '\\', '/', $backup_file );
|
|
|
|
// Prepare the folder structure to support saving backup files.
|
|
if ( ! file_exists( WPPFM_BACKUP_DIR ) ) {
|
|
WPPFM_Folders::make_backup_folder();
|
|
}
|
|
|
|
if ( ! file_exists( $backup_path ) ) {
|
|
$backup_file_text = $backup_class->read_full_backup_data();
|
|
|
|
return $file_class->write_full_backup_file( $backup_path, $backup_file_text );
|
|
} else {
|
|
return 'name_exists';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks the existing backup files for non-compliant versions
|
|
*
|
|
* @since 1.8.0
|
|
* @since 3.12.0 - Switched from using file_put_contents to WP_Filesystem.
|
|
*
|
|
* @return boolean true if a non-compliant backup file exists
|
|
*/
|
|
public static function invalid_backup_exist() {
|
|
if ( ! file_exists( WPPFM_BACKUP_DIR ) ) {
|
|
return false;
|
|
}
|
|
|
|
$wp_filesystem = wppfm_get_wp_filesystem();
|
|
$files = wppfm_list_sql_files( WPPFM_BACKUP_DIR );
|
|
|
|
if ( count( $files ) === 0 ) {
|
|
return false;
|
|
}
|
|
|
|
foreach ( $files as $file ) {
|
|
$backup_string = $wp_filesystem->get_contents( $file );
|
|
|
|
// get the db version
|
|
$backup_version_string = ltrim( substr( $backup_string, stripos( $backup_string, '#' ) ), '#' );
|
|
$backup_db_version = substr( $backup_version_string, 0, strpos( $backup_version_string, '#' ) );
|
|
|
|
if ( $backup_db_version < get_option( 'wppfm_db_version' ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Restores the data from a backup file
|
|
*
|
|
* @since 1.7.2
|
|
* @since 3.12.0 - Switched from using file_put_contents to WP_Filesystem.
|
|
*
|
|
* @param string name of the backup file
|
|
*
|
|
* @return boolean if restored successfully, string when not
|
|
*/
|
|
public static function restore_backup( $backup_file_name ) {
|
|
$backup_class = new WPPFM_Backup();
|
|
$wp_filesystem = wppfm_get_wp_filesystem();
|
|
|
|
$backup_file = WPPFM_BACKUP_DIR . '/' . $backup_file_name;
|
|
$backup_path = str_replace( '\\', '/', $backup_file );
|
|
|
|
$current_db_version = get_option( 'wppfm_db_version' );
|
|
|
|
if ( file_exists( $backup_path ) ) {
|
|
$table_queries = array();
|
|
$backup_string = $wp_filesystem->get_contents( $backup_file );
|
|
|
|
// remove the date string
|
|
$backup_string = substr( $backup_string, stripos( $backup_string, '#' ) );
|
|
|
|
// get the db version
|
|
$backup_db_version = ltrim( $backup_string, '#' );
|
|
$backup_db_version = substr( $backup_db_version, 0, strpos( $backup_db_version, '#' ) );
|
|
|
|
if ( $backup_db_version < $current_db_version ) {
|
|
return __( 'The backup file is of an older version of the database and can not be restored as it is not compatible with the current database.', 'wp-product-feed-manager' );
|
|
}
|
|
|
|
// remove the version
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// remove the ftp passive setting
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// reset the auto feed fix setting
|
|
$auto_feed_fix_setting = ltrim( $backup_string, '#' );
|
|
$auto_feed_fix_setting = substr( $auto_feed_fix_setting, 0, strpos( $auto_feed_fix_setting, '#' ) );
|
|
update_option( 'wppfm_auto_feed_fix', $auto_feed_fix_setting );
|
|
|
|
// remove the auto feed fix setting
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// reset the third party attributes string
|
|
$third_party_attributes_string = ltrim( $backup_string, '#' );
|
|
$third_party_attributes_string = substr( $third_party_attributes_string, 0, strpos( $third_party_attributes_string, '#' ) );
|
|
update_option( 'wppfm_third_party_attribute_keywords', $third_party_attributes_string );
|
|
|
|
// remove the third party attributes string
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// reset the disable background option
|
|
$disable_background_setting = ltrim( $backup_string, '#' );
|
|
$disable_background_setting = substr( $disable_background_setting, 0, strpos( $disable_background_setting, '#' ) );
|
|
update_option( 'wppfm_disabled_background_mode', $disable_background_setting );
|
|
|
|
// remove the disable background option string
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// reset the process logger option string
|
|
$feed_logger_setting = ltrim( $backup_string, '#' );
|
|
$feed_logger_setting = substr( $feed_logger_setting, 0, strpos( $feed_logger_setting, '#' ) );
|
|
update_option( 'wppfm_process_logger_status', $feed_logger_setting );
|
|
|
|
// remove the process logger option string
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// reset the show product identifiers option string
|
|
$show_product_identifiers_setting = ltrim( $backup_string, '#' );
|
|
$show_product_identifiers_setting = substr( $show_product_identifiers_setting, 0, strpos( $show_product_identifiers_setting, '#' ) );
|
|
update_option( 'wppfm_show_product_identifiers', $show_product_identifiers_setting );
|
|
|
|
// remove the show product identifiers option string
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// reset the WPML use full URL resolution option string
|
|
$wpml_use_full_url_resolution_setting = ltrim( $backup_string, '#' );
|
|
$wpml_use_full_url_resolution_setting = substr( $wpml_use_full_url_resolution_setting, 0, strpos( $wpml_use_full_url_resolution_setting, '#' ) );
|
|
update_option( 'wppfm_use_full_url_resolution', $wpml_use_full_url_resolution_setting );
|
|
|
|
// remove the use full url resolution option string
|
|
$backup_string = self::remove_left_data_part( $backup_string );
|
|
|
|
// split the string in table specific rows
|
|
$table_strings = explode( '# backup string for database -> ', $backup_string );
|
|
|
|
foreach ( $table_strings as $string ) {
|
|
$table_name = substr( $string, 0, stripos( $string, '#' ) );
|
|
$query_string = substr( $string, stripos( $string, '#' ), strlen( $string ) );
|
|
array_push( $table_queries, [ trim( $table_name ), ltrim( $query_string, '# <- # ' ) ] );
|
|
}
|
|
|
|
// remove the first (empty) element
|
|
array_shift( $table_queries );
|
|
|
|
return $backup_class->restore_backup_data( $table_queries );
|
|
} else {
|
|
return __( 'A backup file with the selected name does not exists.', 'wp-product-feed-manager' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes an existing backup file.
|
|
*
|
|
* @since 1.7.2
|
|
* @since 3.11.0 changed the return value from a string to a boolean.
|
|
*
|
|
* @param bool true if the backup file is deleted, false if not.
|
|
*/
|
|
public static function delete_backup_file( $backup_file_name ) {
|
|
$backup_file = realpath( WPPFM_BACKUP_DIR . '/' . $backup_file_name );
|
|
|
|
/* translators: %s: Selected backup file */
|
|
return file_exists( $backup_file ) ? wp_delete_file( $backup_file ) : false;
|
|
}
|
|
|
|
/**
|
|
* Duplicate an existing backup file
|
|
*
|
|
* @since 1.7.2
|
|
*
|
|
* @param string name of the backup file to be duplicated
|
|
*/
|
|
public static function duplicate_backup_file( $backup_file_name ) {
|
|
$support_class = new WPPFM_Feed_Support();
|
|
|
|
$backup_file_name_without_extension = rtrim( $backup_file_name, '.sql' );
|
|
$new_backup_file_title = $support_class->next_unique_feed_name( $backup_file_name_without_extension );
|
|
$new_backup_file_name = $new_backup_file_title . '.sql';
|
|
|
|
if ( ! copy( WPPFM_BACKUP_DIR . '/' . $backup_file_name, WPPFM_BACKUP_DIR . '/' . $new_backup_file_name ) ) {
|
|
/* translators: %s: selected backup file name */
|
|
return sprintf( __( 'Failed to make a copy of %s', 'wp-product-feed-manager' ), $backup_file_name );
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clears several options that could hinder a new feed process.
|
|
*/
|
|
public static function clean_options_table() {
|
|
// @since 2.10.0.
|
|
delete_option( 'wppfm_processed_products' );
|
|
|
|
// @since 3.11.0
|
|
delete_site_transient( 'wppfm_background_process_is_active' );
|
|
|
|
$queries_class = new WPPFM_Queries();
|
|
$queries_class->clear_feed_batch_options();
|
|
// also clear the multi site feed batch data
|
|
if ( is_multisite() ) {
|
|
$queries_class->clear_feed_batch_sitemeta();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the status_id's of failed feeds.
|
|
*
|
|
* @since 2.7.0
|
|
*/
|
|
public static function reset_status_of_failed_feeds() {
|
|
$queries_class = new WPPFM_Queries();
|
|
$queries_class->reset_all_feed_status();
|
|
}
|
|
|
|
/**
|
|
* Clears runtime indicators that could keep the background process blocked.
|
|
*
|
|
* @since 3.18.0
|
|
*/
|
|
public static function reset_feed_runtime_state() {
|
|
// Remove any lingering process locks so the queue can restart immediately.
|
|
delete_site_transient( 'wppfm_feed_generation_process_process_lock' );
|
|
// Remove any lingering heartbeat markers so watchdog/processing checks don't think a dead process is alive.
|
|
delete_site_option( 'wppfm_feed_generation_process_process_heartbeat' );
|
|
|
|
// Remove pending-dispatch markers so cron health checks stop trying to resume stale jobs.
|
|
$pending_dispatch_feeds = get_site_option( 'wppfm_pending_dispatch_feeds', array() );
|
|
|
|
if ( ! empty( $pending_dispatch_feeds ) ) {
|
|
foreach ( $pending_dispatch_feeds as $feed_id ) {
|
|
delete_site_transient( 'wppfm_pending_dispatch_' . $feed_id );
|
|
}
|
|
}
|
|
|
|
delete_site_option( 'wppfm_pending_dispatch_feeds' );
|
|
|
|
// Reset progress counters/monitors so the next feed starts from zero.
|
|
set_transient(
|
|
'wppfm_nr_of_processed_products',
|
|
0,
|
|
defined( 'WPPFM_TRANSIENT_LIVE' ) ? WPPFM_TRANSIENT_LIVE : DAY_IN_SECONDS
|
|
);
|
|
|
|
set_transient(
|
|
'wppfm_nr_of_handled_items',
|
|
0,
|
|
defined( 'WPPFM_TRANSIENT_LIVE' ) ? WPPFM_TRANSIENT_LIVE : DAY_IN_SECONDS
|
|
);
|
|
|
|
delete_transient( 'wppfm_feed_file_size' );
|
|
}
|
|
|
|
private static function remove_left_data_part( $data_string ) {
|
|
$ds = ltrim( $data_string, '#' );
|
|
|
|
return substr( $ds, stripos( $ds, '#' ) );
|
|
}
|
|
}
|
|
|
|
|
|
endif;
|