-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Free Listings + Paid Ads: Group variations type for syncable products #1713
Changes from 5 commits
69f14cd
4c01002
409742b
eb9f841
0a87d8f
c96b4c3
459cd23
cffa97f
caa7228
ad96bf5
856eeee
3d64f9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -230,9 +230,15 @@ protected function get_synced_google_ids(): array { | |
/** @var ProductMetaQueryHelper $product_meta_query_helper */ | ||
$product_meta_query_helper = $this->container->get( ProductMetaQueryHelper::class ); | ||
|
||
// Get only synced simple and variations | ||
// Get only synced simple and variations, and group variation products if they have the same parent | ||
/** @var ProductHelper $product_helper */ | ||
$product_helper = $this->container->get( ProductHelper::class ); | ||
$args['type'] = array_diff( ProductSyncer::get_supported_product_types(), [ 'variable' ] ); | ||
$filtered_product_ids = array_flip( $product_repository->find_synced_product_ids( $args ) ); | ||
$filtered_product_ids = array_flip( | ||
$product_helper->maybe_swap_for_parent_ids( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've been working with an array of product ID's, but this call will load the product object for each ID to check if it should get the parent ID. Since caching is in place that can cause a lot of resource usage if we have a large amount of synced products. Have we tested whether this will hit any resource limits? For aggregating by variable product we previously used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out, I just did a quick check and looks like I can get the correct synced count from |
||
$product_repository->find_synced_product_ids( $args ) | ||
) | ||
); | ||
$all_google_ids = $product_meta_query_helper->get_all_values( ProductMetaHandler::KEY_GOOGLE_IDS ); | ||
$filtered_google_ids = []; | ||
foreach ( array_intersect_key( $all_google_ids, $filtered_product_ids ) as $product_ids ) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -465,12 +465,29 @@ public function get_mc_status( WC_Product $wc_product ): ?string { | |
} | ||
} | ||
|
||
/** | ||
* If an item from the provided list of products has a parent, replace it with the parent ID. | ||
* | ||
* @param int[] $product_ids A list of WooCommerce product ID. | ||
* | ||
* @return int[] A list of parent ID or product ID if it doesn't have a parent. | ||
* | ||
* @throws InvalidValue If a given ID doesn't reference a valid product. Or if a variation product does not have a | ||
* valid parent ID (i.e. it's an orphan). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was confusing at first. It seems though that an orphan will get excluded when creating the batches of syncable products. So it shouldn't encounter any orphans here. However there is still a small chance that a parent or even just a regular product gets deleted after the batches get created (should that be covered by a unit test). If that happens then wouldn't we just want to exclude those from the count, instead of making the whole batch fail? Which won't show as an error but instead excludes a large amount of products from the count. |
||
*/ | ||
public function maybe_swap_for_parent_ids( array $product_ids ) { | ||
foreach ( $product_ids as $index => $product_id ) { | ||
$product_ids[ $index ] = $this->maybe_swap_for_parent_id( $product_id ); | ||
} | ||
return array_unique( $product_ids ); | ||
} | ||
|
||
/** | ||
* If the provided product has a parent, return its ID. Otherwise, return the given (valid product) ID. | ||
* | ||
* @param int $product_id WooCommerce product ID. | ||
* | ||
* @return int The parent ID or product ID of it doesn't have a parent. | ||
* @return int The parent ID or product ID if it doesn't have a parent. | ||
* | ||
* @throws InvalidValue If a given ID doesn't reference a valid product. Or if a variation product does not have a | ||
* valid parent ID (i.e. it's an orphan). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,11 @@ | |
|
||
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\PluginHelper; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Product\ProductHelper; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Value\ChannelVisibility; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Value\MCStatus; | ||
use WC_Product; | ||
use WC_Product_Variable; | ||
|
||
defined( 'ABSPATH' ) || exit; | ||
|
||
|
@@ -32,15 +34,22 @@ class ProductRepository implements Service { | |
*/ | ||
protected $product_filter; | ||
|
||
/** | ||
* @var ProductHelper | ||
*/ | ||
protected $product_helper; | ||
|
||
/** | ||
* ProductRepository constructor. | ||
* | ||
* @param ProductMetaHandler $meta_handler | ||
* @param ProductFilter $product_filter | ||
* @param ProductHelper $product_helper | ||
*/ | ||
public function __construct( ProductMetaHandler $meta_handler, ProductFilter $product_filter ) { | ||
public function __construct( ProductMetaHandler $meta_handler, ProductFilter $product_filter, ProductHelper $product_helper ) { | ||
$this->meta_handler = $meta_handler; | ||
$this->product_filter = $product_filter; | ||
$this->product_helper = $product_helper; | ||
} | ||
|
||
/** | ||
|
@@ -248,20 +257,21 @@ public function find_expiring_product_ids( int $limit = - 1, int $offset = 0 ): | |
} | ||
|
||
/** | ||
* Find and return an array of WooCommerce product IDs that are marked as MC not_synced. | ||
* Excludes variations and variable products without variations. | ||
* Find and return an array of WooCommerce product IDs that are syncable but marked as MC not_synced. | ||
* Excludes: | ||
* - variable products without variations, and | ||
* - variable products with all of their variations are not syncable. | ||
* | ||
* @param int $limit Maximum number of results to retrieve or -1 for unlimited. | ||
* @param int $offset Amount to offset product results. | ||
* | ||
* @return int[] Array of WooCommerce product IDs | ||
*/ | ||
public function find_mc_not_synced_product_ids( int $limit = -1, int $offset = 0 ): array { | ||
$types = ProductSyncer::get_supported_product_types(); | ||
$types = array_diff( $types, [ 'variation' ] ); | ||
$args = [ | ||
'status' => 'publish', | ||
'type' => $types, | ||
// Get simple and variable products that are marked as MC 'not synced'. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have similar thoughts about this section. While switching to variable products can speed it up / limit resources. If we have a site with 10k simple products then this will still be an issue. |
||
$args = [ | ||
'status' => [ 'publish' ], | ||
'type' => array_diff( ProductSyncer::get_supported_product_types(), [ 'variation' ] ), | ||
'meta_query' => [ | ||
[ | ||
'key' => ProductMetaHandler::KEY_MC_STATUS, | ||
|
@@ -271,7 +281,39 @@ public function find_mc_not_synced_product_ids( int $limit = -1, int $offset = 0 | |
], | ||
]; | ||
|
||
return $this->find_ids( $args, $limit, $offset ); | ||
$not_synced_ids = $this->find_ids( $args, $limit, $offset ); | ||
|
||
// Get only the product that is syncable from 'not synced' products, | ||
// including variation products of a variable product. | ||
$product_ids = array_filter( | ||
$not_synced_ids, | ||
function ( $product_id ) { | ||
$product = $this->product_helper->get_wc_product( $product_id ); | ||
|
||
// If it's a variable product, check its children variation products. | ||
if ( $product instanceof WC_Product_Variable ) { | ||
if ( empty( $product->get_children() ) ) { | ||
// Return false if no variation products. I.e. it's not syncable. | ||
return false; | ||
} else { | ||
// Get a list of variation products, return true if any of a varation product | ||
// is syncable, otherwise return false. | ||
foreach ( $product->get_children() as $variation_id ) { | ||
$variation = $this->product_helper->get_wc_product( $variation_id ); | ||
if ( $this->product_helper->is_sync_ready( $variation ) ) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
// Check if a simple product is syncable. | ||
return $this->product_helper->is_sync_ready( $product ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing this out, this is something I've missed. |
||
} | ||
); | ||
|
||
return $product_ids; | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not already store unique ID's here, will save us having to do it later when counting.