es() );
// Delete HPOS tables tool.
if ( $this->custom_orders_table_usage_is_enabled() || $this->data_synchronizer->data_sync_is_enabled() ) {
$disabled = true;
$message = __( 'This will delete the custom orders tables. The tables can be deleted only if the "High-Performance order storage" is not authoritative and sync is disabled (via Settings > Advanced > Features).', 'woocommerce' );
} else {
$disabled = false;
$message = __( 'This will delete the custom orders tables. To create them again enable the "High-Performance order storage" feature (via Settings > Advanced > Features).', 'woocommerce' );
}
$tools_array['delete_custom_orders_table'] = array(
'name' => __( 'Delete the custom orders tables', 'woocommerce' ),
'desc' => sprintf(
'%1$s %2$s',
__( 'Note:', 'woocommerce' ),
$message
),
'requires_refresh' => true,
'callback' => function () {
$this->features_controller->change_feature_enable( self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, false );
$this->delete_custom_orders_tables();
return __( 'Custom orders tables have been deleted.', 'woocommerce' );
},
'button' => __( 'Delete', 'woocommerce' ),
'disabled' => $disabled,
);
return $tools_array;
}
/**
* Delete the custom orders tables and any related options and data in response to the user pressing the tool button.
*
* @throws \Exception Can't delete the tables.
*/
private function delete_custom_orders_tables() {
if ( $this->custom_orders_table_usage_is_enabled() ) {
throw new \Exception( "Can't delete the custom orders tables: they are currently in use (via Settings > Advanced > Features)." );
}
delete_option( self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION );
$this->data_synchronizer->delete_database_tables();
}
/**
* Handler for the individual setting updated hook.
*
* @param string $option Setting name.
* @param mixed $old_value Old value of the setting.
* @param mixed $value New value of the setting.
*/
private function process_updated_option( $option, $old_value, $value ) {
if ( DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION === $option && 'no' === $value ) {
$this->data_synchronizer->cleanup_synchronization_state();
}
}
/**
* Handler for the setting pre-update hook.
* We use it to verify that authoritative orders table switch doesn't happen while sync is pending.
*
* @param mixed $value New value of the setting.
* @param string $option Setting name.
* @param mixed $old_value Old value of the setting.
*
* @throws \Exception Attempt to change the authoritative orders table while orders sync is pending.
*/
private function process_pre_update_option( $value, $option, $old_value ) {
if ( DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION === $option && $value !== $old_value ) {
$this->order_cache->flush();
return $value;
}
if ( self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION !== $option ) {
return $value;
}
if ( $old_value === $value ) {
return $value;
}
$this->order_cache->flush();
if ( ! $this->data_synchronizer->check_orders_table_exists() ) {
$this->data_synchronizer->create_database_tables();
}
$tables_created = get_option( DataSynchronizer::ORDERS_TABLE_CREATED ) === 'yes';
if ( ! $tables_created ) {
return 'no';
}
$sync_is_pending = 0 !== $this->data_synchronizer->get_current_orders_pending_sync_count();
if ( $sync_is_pending && ! $this->changing_data_source_with_sync_pending_is_allowed() ) {
throw new \Exception( "The authoritative table for orders storage can't be changed while there are orders out of sync" );
}
return $value;
}
/**
* Callback to trigger a sync immediately by clicking a button on the Features screen.
*
* @return void
*/
private function sync_now() {
$section = filter_input( INPUT_GET, 'section' );
if ( 'features' !== $section ) {
return;
}
if ( ! filter_input( INPUT_GET, self::SYNC_QUERY_ARG, FILTER_VALIDATE_BOOLEAN ) ) {
return;
}
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ?? '' ) ), 'hpos-sync-now' ) ) {
WC_Admin_Settings::add_error( esc_html__( 'Unable to start synchronization. The link you followed may have expired.', 'woocommerce' ) );
return;
}
$this->data_cleanup->toggle_flag( false );
$this->batch_processing_controller->enqueue_processor( DataSynchronizer::class );
}
/**
* Tell WP Admin to remove the sync query arg from the URL.
*
* @param array $query_args The query args that are removable.
*
* @return array
*/
private function register_removable_query_arg( $query_args ) {
$query_args[] = self::SYNC_QUERY_ARG;
return $query_args;
}
/**
* Handler for the woocommerce_after_register_post_type post,
* registers the post type for placeholder orders.
*
* @return void
*/
private function register_post_type_for_order_placeholders(): void {
wc_register_order_type(
DataSynchronizer::PLACEHOLDER_ORDER_POST_TYPE,
array(
'public' => false,
'exclude_from_search' => true,
'publicly_queryable' => false,
'show_ui' => false,
'show_in_menu' => false,
'show_in_nav_menus' => false,
'show_in_admin_bar' => false,
'show_in_rest' => false,
'rewrite' => false,
'query_var' => false,
'can_export' => false,
'supports' => array(),
'capabilities' => array(),
'exclude_from_order_count' => true,
'exclude_from_order_views' => true,
'exclude_from_order_reports' => true,
'exclude_from_order_sales_reports' => true,
)
);
}
/**
* Add the definition for the HPOS feature.
*
* @param FeaturesController $features_controller The instance of FeaturesController.
*
* @return void
*/
private function add_feature_definition( $features_controller ) {
$definition = array(
'option_key' => self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION,
'is_experimental' => false,
'enabled_by_default' => false,
'order' => 50,
'setting' => $this->get_hpos_setting_for_feature(),
'additional_settings' => array(
$this->get_hpos_setting_for_sync(),
),
);
$features_controller->add_feature_definition(
'custom_order_tables',
__( 'High-Performance order storage', 'woocommerce' ),
$definition
);
}
/**
* Returns the HPOS setting for rendering HPOS vs Post setting block in Features section of the settings page.
*
* @return array Feature setting object.
*/
private function get_hpos_setting_for_feature() {
if ( 'yes' === get_transient( 'wc_installing' ) ) {
return array();
}
$get_value = function() {
return $this->custom_orders_table_usage_is_enabled() ? 'yes' : 'no';
};
/**
* ⚠️The FeaturesController instance must only be accessed from within the callback functions. Otherwise it
* gets called while it's still being instantiated and creates and endless loop.
*/
$get_desc = function() {
$plugin_compatibility = $this->features_controller->get_compatible_plugins_for_feature( 'custom_order_tables', true );
return $this->plugin_util->generate_incompatible_plugin_feature_warning( 'custom_order_tables', $plugin_compatibility );
};
$get_disabled = function() {
$plugin_compatibility = $this->features_controller->get_compatible_plugins_for_feature( 'custom_order_tables', true );
$sync_complete = 0 === $this->get_orders_pending_sync_count();
$disabled = array();
// Changing something here? might also want to look at `enable|disable` functions in CLIRunner.
if ( count( array_merge( $plugin_compatibility['uncertain'], $plugin_compatibility['incompatible'] ) ) > 0 ) {
$disabled = array( 'yes' );
}
if ( ! $sync_complete && ! $this->changing_data_source_with_sync_pending_is_allowed() ) {
$disabled = array( 'yes', 'no' );
}
return $disabled;
};
return array(
'id' => self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION,
'title' => __( 'Order data storage', 'woocommerce' ),
'type' => 'radio',
'options' => array(
'no' => __( 'WordPress posts storage (legacy)', 'woocommerce' ),
'yes' => __( 'High-performance order storage (recommended)', 'woocommerce' ),
),
'value' => $get_value,
'disabled' => $get_disabled,
'desc' => $get_desc,
'desc_at_end' => true,
'row_class' => self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION,
);
}
/**
* Returns the setting for rendering sync enabling setting block in Features section of the settings page.
*
* @return array Feature setting object.
*/
private function get_hpos_setting_for_sync() {
if ( 'yes' === get_transient( 'wc_installing' ) ) {
return array();
}
$get_value = function() {
return get_option( DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION );
};
$get_sync_message = function() {
$orders_pending_sync_count = $this->get_orders_pending_sync_count();
$sync_in_progress = $this->batch_processing_controller->is_enqueued( get_class( $this->data_synchronizer ) );
$sync_enabled = $this->data_synchronizer->data_sync_is_enabled();
$sync_is_pending = $orders_pending_sync_count > 0;
$sync_message = array();
$is_dangerous = $sync_is_pending && $this->changing_data_source_with_sync_pending_is_allowed();
if ( $is_dangerous ) {
$sync_message[] = wp_kses_data(
sprintf(
// translators: %d: number of pending orders.
_n(
"There's %d order pending sync. Switching data storage while sync is incomplete is dangerous and can lead to order data corruption or loss! ",
'There are %d orders pending sync. Switching data storage while sync is incomplete is dangerous and can lead to order data corruption or loss! ',
$orders_pending_sync_count,
'woocommerce'
),
$orders_pending_sync_count,
)
);
}
if ( ! $sync_enabled && $this->data_synchronizer->background_sync_is_enabled() ) {
$sync_message[] = __( 'Background sync is enabled.', 'woocommerce' );
}
if ( $sync_in_progress && $sync_is_pending ) {
$sync_message[] = sprintf(
// translators: %d: number of pending orders.
__( 'Currently syncing orders... %d pending', 'woocommerce' ),
$orders_pending_sync_count
);
} elseif ( $sync_is_pending ) {
$sync_now_url = wp_nonce_url(
add_query_arg(
array(
self::SYNC_QUERY_ARG => true,
),
wc_get_container()->get( FeaturesController::class )->get_features_page_url()
),
'hpos-sync-now'
);
if ( ! $is_dangerous ) {
$sync_message[] = wp_kses_data(
sprintf(
// translators: %d: number of pending orders.
_n(
"There's %d order pending sync. You can switch order data storage only when the posts and orders tables are in sync .",
'There are %d orders pending sync. You can switch order data storage only when the posts and orders tables are in sync .',
$orders_pending_sync_count,
'woocommerce'
),
$orders_pending_sync_count
)
);
}
$sync_message[] = sprintf(
'%2$s ',
esc_url( $sync_now_url ),
sprintf(
// translators: %d: number of pending orders.
_n(
'Sync %s pending order',
'Sync %s pending orders',
$orders_pending_sync_count,
'woocommerce'
),
number_format_i18n( $orders_pending_sync_count )
)
);
}
return implode( ' ', $sync_message );
};
$get_description_is_error = function() {
$sync_is_pending = $this->get_orders_pending_sync_count() > 0;
return $sync_is_pending && $this->changing_data_source_with_sync_pending_is_allowed();
};
return array(
'id' => DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION,
'title' => '',
'type' => 'checkbox',
'desc' => __( 'Enable compatibility mode (synchronizes orders to the posts table).', 'woocommerce' ),
'value' => $get_value,
'desc_tip' => $get_sync_message,
'description_is_error' => $get_description_is_error,
'row_class' => DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION,
);
}
/**
* Returns a value indicating if changing the authoritative data source for orders while there are orders pending synchronization is allowed.
*
* @return bool
*/
private function changing_data_source_with_sync_pending_is_allowed(): bool {
/**
* Filter to allow changing where order data is stored, even when there are orders pending synchronization.
*
* DANGER! This filter is intended for usage when doing manual and automated testing in development environments only,
* it should NEVER be used in production environments. Order data corruption or loss can happen!
*
* @param bool $allow True to allow changing order storage when there are orders pending synchronization, false to disallow.
* @returns bool
*
* @since 8.3.0
*/
return apply_filters( 'wc_allow_changing_orders_storage_while_sync_is_pending', false );
}
/**
* Returns the count of orders pending synchronization.
*
* @return int
*/
private function get_orders_pending_sync_count(): int {
return $this->data_synchronizer->get_sync_status()['current_pending_count'];
}
}
Iphone 15 AMA book case – alibabatelecom
View cart “Iphone 6 plus AAA Display” has been added to your cart.
Iphone 15 AMA book case 299.00 kr
AMA book case is the high-quality faux premuim case with built-in stand function and inside pockets for cards and documents.
inside of the case is silicone and it is not going broke when you lose your phone
It combines elegant colours and is equipped with a hard shell to ensure the stability and protection of your Smartphone.
iphone
Iphone 15
Color
Dark bleu
Brand
AMA
7 in stock
Description
AMA book case is the high-quality faux premuim case with built-in stand function and inside pockets for cards and documents.
inside of the case is silicone and it is not going broke when you lose your phone
It combines elegant colours and is equipped with a hard shell to ensure the stability and protection of your Smartphone.