[product ID, variation ID] (loaded once per request). * * @var array|null */ private $watched = null; /** * Constructor. * * @param Plugin $plugin Plugin. */ public function __construct( Plugin $plugin ) { $this->plugin = $plugin; } /** * Registers the hooks. */ public function register(): void { // Stock and stock status, however they are changed (product screen, import, REST, code). add_action( 'woocommerce_variation_set_stock', array( $this, 'on_item_object' ) ); add_action( 'woocommerce_product_set_stock', array( $this, 'on_item_object' ) ); add_action( 'woocommerce_variation_set_stock_status', array( $this, 'on_item' ) ); add_action( 'woocommerce_product_set_stock_status', array( $this, 'on_item' ) ); // Price, text, photos, attributes. add_action( 'woocommerce_update_product_variation', array( $this, 'on_item' ) ); add_action( 'woocommerce_save_product_variation', array( $this, 'on_item' ) ); add_action( 'woocommerce_update_product', array( $this, 'on_item' ) ); // Trash, unpublish, delete. add_action( 'transition_post_status', array( $this, 'on_transition' ), 10, 3 ); add_action( 'before_delete_post', array( $this, 'on_item' ) ); } /** * A stock change that passes the product object. * * @param mixed $product Product. */ public function on_item_object( $product ): void { if ( is_object( $product ) && method_exists( $product, 'get_id' ) ) { $this->on_item( (int) $product->get_id() ); } } /** * A product or variation changed. * * @param mixed $post_id Product or variation ID. */ public function on_item( $post_id ): void { $post_id = (int) $post_id; $touched = array(); foreach ( $this->watched() as $listing_id => $ids ) { if ( $ids[0] === $post_id || $ids[1] === $post_id ) { $touched[] = $listing_id; } } if ( ! $touched ) { return; } $auto_update = (bool) apply_filters( 'tidelist_auto_update', false ); foreach ( $touched as $listing_id ) { Takedown::schedule( $listing_id, self::DEBOUNCE ); if ( $auto_update ) { UpdateListing::schedule( $listing_id, self::DEBOUNCE ); } } do_action( 'tidelist_after_product_change', $touched, $post_id ); } /** * A product or variation changed its status (trash, draft, publish …). * * @param string $new_status New status. * @param string $old_status Old status. * @param \WP_Post $post Post. */ public function on_transition( $new_status, $old_status, $post ): void { if ( $new_status !== $old_status && $post instanceof \WP_Post && in_array( $post->post_type, array( 'product', 'product_variation' ), true ) ) { $this->on_item( $post->ID ); } } /** * Adverts that are on the marketplace (live, being checked or waiting for payment). * * @return array */ private function watched(): array { if ( null === $this->watched ) { $this->watched = array(); foreach ( $this->plugin->listings()->all( array( 'status' => ListingStatus::on_marketplace() ) ) as $row ) { if ( '' !== (string) $row['remote_id'] ) { $this->watched[ (int) $row['id'] ] = array( (int) $row['product_id'], (int) $row['variation_id'] ); } } } return $this->watched; } }