WordPress как на ладони
Очень Удобный и Быстрый Хостинг для сайтов на WordPress. Пользуюсь сам и вам рекомендую!
класс не описан

Automattic\WooCommerce\Internal\ProductAttributesLookup

DataRegenerator{} WC 1.0

This class handles the (re)generation of the product attributes lookup table. It schedules the regeneration in small product batches by itself, so it can be used outside the regular WooCommerce data regenerations mechanism.

After the regeneration is completed a wp_wc_product_attributes_lookup table will exist with entries for all the products that existed when initiate_regeneration was invoked; entries for products created after that are supposed to be created/updated by the appropriate data store classes (or by the code that uses the data store classes) whenever a product is created/updated.

Additionally, after the regeneration is completed a 'woocommerce_attribute_lookup_enabled' option with a value of 'no' will have been created.

This class also adds two entries to the Status - Tools menu: one for manually regenerating the table contents, and another one for enabling or disabling the actual lookup table usage.

Хуков нет.

Возвращает

null. Ничего.

Использование

$DataRegenerator = new DataRegenerator();
// use class methods

Методы

  1. __construct()
  2. add_initiate_regeneration_entry_to_tools_array( array $tools_array )
  3. check_can_do_lookup_table_regeneration( $product_id = null )
  4. delete_all_attributes_lookup_data()
  5. do_regeneration_step()
  6. enable_or_disable_lookup_table_usage( $enable )
  7. enqueue_regeneration_step_run()
  8. finalize_regeneration()
  9. init( LookupDataStore $data_store )
  10. initialize_table_and_data()
  11. initiate_regeneration()
  12. initiate_regeneration_from_tools_page()
  13. run_regeneration_step_callback()

Код DataRegenerator{} WC 6.1.1

class DataRegenerator {

	const PRODUCTS_PER_GENERATION_STEP = 10;

	/**
	 * The data store to use.
	 *
	 * @var LookupDataStore
	 */
	private $data_store;

	/**
	 * The lookup table name.
	 *
	 * @var string
	 */
	private $lookup_table_name;

	/**
	 * DataRegenerator constructor.
	 */
	public function __construct() {
		global $wpdb;

		$this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup';

		add_filter(
			'woocommerce_debug_tools',
			function( $tools ) {
				return $this->add_initiate_regeneration_entry_to_tools_array( $tools );
			},
			1,
			999
		);

		add_action(
			'woocommerce_run_product_attribute_lookup_regeneration_callback',
			function () {
				$this->run_regeneration_step_callback();
			}
		);
	}

	/**
	 * Class initialization, invoked by the DI container.
	 *
	 * @internal
	 * @param LookupDataStore $data_store The data store to use.
	 */
	final public function init( LookupDataStore $data_store ) {
		$this->data_store = $data_store;
	}

	/**
	 * Initialize the regeneration procedure:
	 * deletes the lookup table and related options if they exist,
	 * then it creates the table and runs the first step of the regeneration process.
	 *
	 * This is the method that should be used as a callback for a data regeneration in wc-update-functions, e.g.:
	 *
	 * function wc_update_XX_regenerate_product_attributes_lookup_table() {
	 *   wc_get_container()->get(DataRegenerator::class)->initiate_regeneration();
	 *   return false;
	 * }
	 *
	 * (Note how we are returning "false" since the class handles the step scheduling by itself).
	 */
	public function initiate_regeneration() {
		$this->enable_or_disable_lookup_table_usage( false );

		$this->delete_all_attributes_lookup_data();
		$products_exist = $this->initialize_table_and_data();
		if ( $products_exist ) {
			$this->enqueue_regeneration_step_run();
		} else {
			$this->finalize_regeneration();
		}
	}

	/**
	 * Delete all the existing data related to the lookup table, including the table itself.
	 *
	 * Shortcut to run this method in case the debug tools UI isn't available or for quick debugging:
	 *
	 * wp eval "wc_get_container()->get(Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator::class)->delete_all_attributes_lookup_data();"
	 */
	public function delete_all_attributes_lookup_data() {
		global $wpdb;

		delete_option( 'woocommerce_attribute_lookup_enabled' );
		delete_option( 'woocommerce_attribute_lookup_last_product_id_to_process' );
		delete_option( 'woocommerce_attribute_lookup_last_products_page_processed' );
		$this->data_store->unset_regeneration_in_progress_flag();

		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->lookup_table_name );
	}

	/**
	 * Create the lookup table and initialize the options that will be temporarily used
	 * while the regeneration is in progress.
	 *
	 * @return bool True if there's any product at all in the database, false otherwise.
	 */
	private function initialize_table_and_data() {
		global $wpdb;

		// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
		$wpdb->query(
			'
CREATE TABLE ' . $this->lookup_table_name . '(
  product_id bigint(20) NOT NULL,
  product_or_parent_id bigint(20) NOT NULL,
  taxonomy varchar(32) NOT NULL,
  term_id bigint(20) NOT NULL,
  is_variation_attribute tinyint(1) NOT NULL,
  in_stock tinyint(1) NOT NULL
 );
		'
		);
		// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared

		$last_existing_product_id =
			WC()->call_function(
				'wc_get_products',
				array(
					'return'  => 'ids',
					'limit'   => 1,
					'orderby' => array(
						'ID' => 'DESC',
					),
				)
			);

		if ( ! $last_existing_product_id ) {
			// No products exist, nothing to (re)generate.
			return false;
		}

		$this->data_store->set_regeneration_in_progress_flag();
		update_option( 'woocommerce_attribute_lookup_last_product_id_to_process', current( $last_existing_product_id ) );
		update_option( 'woocommerce_attribute_lookup_last_products_page_processed', 0 );

		return true;
	}

	/**
	 * Action scheduler callback, performs one regeneration step and then
	 * schedules the next step if necessary.
	 */
	private function run_regeneration_step_callback() {
		if ( ! $this->data_store->regeneration_is_in_progress() ) {
			return;
		}

		$result = $this->do_regeneration_step();
		if ( $result ) {
			$this->enqueue_regeneration_step_run();
		} else {
			$this->finalize_regeneration();
		}
	}

	/**
	 * Enqueue one regeneration step in action scheduler.
	 */
	private function enqueue_regeneration_step_run() {
		$queue = WC()->get_instance_of( \WC_Queue::class );
		$queue->schedule_single(
			WC()->call_function( 'time' ) + 1,
			'woocommerce_run_product_attribute_lookup_regeneration_callback',
			array(),
			'woocommerce-db-updates'
		);
	}

	/**
	 * Perform one regeneration step: grabs a chunk of products and creates
	 * the appropriate entries for them in the lookup table.
	 *
	 * @return bool True if more steps need to be run, false otherwise.
	 */
	private function do_regeneration_step() {
		$last_products_page_processed = get_option( 'woocommerce_attribute_lookup_last_products_page_processed' );
		$current_products_page        = (int) $last_products_page_processed + 1;

		$product_ids = WC()->call_function(
			'wc_get_products',
			array(
				'limit'   => self::PRODUCTS_PER_GENERATION_STEP,
				'page'    => $current_products_page,
				'orderby' => array(
					'ID' => 'ASC',
				),
				'return'  => 'ids',
			)
		);

		if ( ! $product_ids ) {
			return false;
		}

		foreach ( $product_ids as $id ) {
			$this->data_store->create_data_for_product( $id );
		}

		update_option( 'woocommerce_attribute_lookup_last_products_page_processed', $current_products_page );

		$last_product_id_to_process = get_option( 'woocommerce_attribute_lookup_last_product_id_to_process' );
		return end( $product_ids ) < $last_product_id_to_process;
	}

	/**
	 * Cleanup/final option setup after the regeneration has been completed.
	 */
	private function finalize_regeneration() {
		delete_option( 'woocommerce_attribute_lookup_last_product_id_to_process' );
		delete_option( 'woocommerce_attribute_lookup_last_products_page_processed' );
		update_option( 'woocommerce_attribute_lookup_enabled', 'no' );
		$this->data_store->unset_regeneration_in_progress_flag();
	}

	/**
	 * Add a 'Regenerate product attributes lookup table' entry to the Status - Tools page.
	 *
	 * @param array $tools_array The tool definitions array that is passed ro the woocommerce_debug_tools filter.
	 * @return array The tools array with the entry added.
	 */
	private function add_initiate_regeneration_entry_to_tools_array( array $tools_array ) {
		$lookup_table_exists       = $this->data_store->check_lookup_table_exists();
		$generation_is_in_progress = $this->data_store->regeneration_is_in_progress();

		// Regenerate table.

		if ( $lookup_table_exists ) {
			$generate_item_name   = __( 'Regenerate the product attributes lookup table', 'woocommerce' );
			$generate_item_desc   = __( 'This tool will regenerate the product attributes lookup table data from existing product(s) data. This process may take a while.', 'woocommerce' );
			$generate_item_return = __( 'Product attributes lookup table data is regenerating', 'woocommerce' );
			$generate_item_button = __( 'Regenerate', 'woocommerce' );
		} else {
			$generate_item_name   = __( 'Create and fill product attributes lookup table', 'woocommerce' );
			$generate_item_desc   = __( 'This tool will create the product attributes lookup table data and fill it with existing products data. This process may take a while.', 'woocommerce' );
			$generate_item_return = __( 'Product attributes lookup table is being filled', 'woocommerce' );
			$generate_item_button = __( 'Create', 'woocommerce' );
		}

		$entry = array(
			'name'             => $generate_item_name,
			'desc'             => $generate_item_desc,
			'requires_refresh' => true,
			'callback'         => function() use ( $generate_item_return ) {
				$this->initiate_regeneration_from_tools_page();
				return $generate_item_return;
			},
		);

		if ( $lookup_table_exists ) {
			$entry['selector'] = array(
				'description'   => __( 'Select a product to regenerate the data for, or leave empty for a full table regeneration:', 'woocommerce' ),
				'class'         => 'wc-product-search',
				'search_action' => 'woocommerce_json_search_products',
				'name'          => 'regenerate_product_attribute_lookup_data_product_id',
				'placeholder'   => esc_attr__( 'Search for a product&hellip;', 'woocommerce' ),
			);
		}

		if ( $generation_is_in_progress ) {
			$entry['button'] = sprintf(
				/* translators: %d: How many products have been processed so far. */
				__( 'Filling in progress (%d)', 'woocommerce' ),
				get_option( 'woocommerce_attribute_lookup_last_products_page_processed', 0 ) * self::PRODUCTS_PER_GENERATION_STEP
			);
			$entry['disabled'] = true;
		} else {
			$entry['button'] = $generate_item_button;
		}

		$tools_array['regenerate_product_attributes_lookup_table'] = $entry;

		if ( $lookup_table_exists ) {

			// Delete the table.

			$tools_array['delete_product_attributes_lookup_table'] = array(
				'name'             => __( 'Delete the product attributes lookup table', 'woocommerce' ),
				'desc'             => sprintf(
					'<strong class="red">%1$s</strong> %2$s',
					__( 'Note:', 'woocommerce' ),
					__( 'This will delete the product attributes lookup table. You can create it again with the "Create and fill product attributes lookup table" tool.', 'woocommerce' )
				),
				'button'           => __( 'Delete', 'woocommerce' ),
				'requires_refresh' => true,
				'callback'         => function () {
					$this->delete_all_attributes_lookup_data();
					return __( 'Product attributes lookup table has been deleted.', 'woocommerce' );
				},
			);
		}

		return $tools_array;
	}

	/**
	 * Callback to initiate the regeneration process from the Status - Tools page.
	 *
	 * @throws \Exception The regeneration is already in progress.
	 */
	private function initiate_regeneration_from_tools_page() {
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
		if ( ! isset( $_REQUEST['_wpnonce'] ) || false === wp_verify_nonce( $_REQUEST['_wpnonce'], 'debug_action' ) ) {
			throw new \Exception( 'Invalid nonce' );
		}

		if ( isset( $_REQUEST['regenerate_product_attribute_lookup_data_product_id'] ) ) {
			$product_id = (int) $_REQUEST['regenerate_product_attribute_lookup_data_product_id'];
			$this->check_can_do_lookup_table_regeneration( $product_id );
			$this->data_store->create_data_for_product( $product_id );
		} else {
			$this->check_can_do_lookup_table_regeneration();
			$this->initiate_regeneration();
		}
	}

	/**
	 * Enable or disable the actual lookup table usage.
	 *
	 * @param bool $enable True to enable, false to disable.
	 * @throws \Exception A lookup table regeneration is currently in progress.
	 */
	private function enable_or_disable_lookup_table_usage( $enable ) {
		if ( $this->data_store->regeneration_is_in_progress() ) {
			throw new \Exception( "Can't enable or disable the attributes lookup table usage while it's regenerating." );
		}

		update_option( 'woocommerce_attribute_lookup_enabled', $enable ? 'yes' : 'no' );
	}

	/**
	 * Check if everything is good to go to perform a complete or per product lookup table data regeneration
	 * and throw an exception if not.
	 *
	 * @param mixed $product_id The product id to check the regeneration viability for, or null to check if a complete regeneration is possible.
	 * @throws \Exception Something prevents the regeneration from starting.
	 */
	private function check_can_do_lookup_table_regeneration( $product_id = null ) {
		if ( $product_id && ! $this->data_store->check_lookup_table_exists() ) {
			throw new \Exception( "Can't do product attribute lookup data regeneration: lookup table doesn't exist" );
		}
		if ( $this->data_store->regeneration_is_in_progress() ) {
			throw new \Exception( "Can't do product attribute lookup data regeneration: regeneration is already in progress" );
		}
		if ( $product_id && ! wc_get_product( $product_id ) ) {
			throw new \Exception( "Can't do product attribute lookup data regeneration: product doesn't exist" );
		}
	}
}