-
Notifications
You must be signed in to change notification settings - Fork 10
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
Multiple Variations Support #235
Draft
faisal-alvi
wants to merge
115
commits into
trunk
Choose a base branch
from
multiple-variations-support
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 114 commits
Commits
Show all changes
115 commits
Select commit
Hold shift + click to select a range
45942fa
fetch options data
faisal-alvi 4f0b842
prepare options data
faisal-alvi 277167d
Stop if there are no options
faisal-alvi f665807
remove unnecessary older attributes data
faisal-alvi c9e10a7
prepare variation data
faisal-alvi 51d93bd
use the newer version of variation data
faisal-alvi f95af7d
Create transient only when step completes
faisal-alvi 3beeb06
adding since and throw in doc
faisal-alvi 235fd1d
vertically inlined equals
faisal-alvi 344a2a7
do not stop if options do no exist, we may have custom variations
faisal-alvi 5d320f6
remove extract options data logic
faisal-alvi b10816f
prepare attributes for custom variations
faisal-alvi 41c85d8
add `extract_attributes_from_square_options()`
faisal-alvi 23de016
add `extract_attributes_from_square_variations()`
faisal-alvi d480fb3
a few spacing adjustments
faisal-alvi 8bc38f4
extract attributes as per the option type
faisal-alvi a7796b4
check for options just before when its needed
faisal-alvi c7a3410
pass `custom_meta` in data for product
faisal-alvi a1a8aa8
handle `custom_meta` and update meta
faisal-alvi 4c6e132
update the meta name to hide it
faisal-alvi 74b36fd
init attribute and variations
faisal-alvi 46d9c1e
consider dynamic options if more than one attributes exits; also dele…
faisal-alvi 4e569c3
Set the product as a dynamic options product
faisal-alvi ae96951
Loop through the attributes to create options and values at Square.
faisal-alvi e49c6b4
Set the item_option_id for each option to the product
faisal-alvi 6f1b741
Check if Square already has the option created with the same name
faisal-alvi 3d3b2af
If name does not exist, create a new option in Square
faisal-alvi c3e6d8d
Loop through the attribute values to create option values
faisal-alvi c5ab52a
Set the option values
faisal-alvi d5fe986
Push option object to Square to create a new one. Used timestamp as i…
faisal-alvi 79a4e28
Handle error
faisal-alvi ef72054
Log the error and throw it
faisal-alvi 539cbc2
Add @todo list
faisal-alvi 2ba4519
Set the name of the variation if it's a single variation
faisal-alvi fb3f2f5
Handle dynamic options while syncing to Square
faisal-alvi 692f19c
Set the `item_option_values` for the variation
faisal-alvi a5afdb1
Prepare data if data found in transient
faisal-alvi 3bdd65f
Create step to fetch_options_data in Manual Sync
faisal-alvi 3700856
Request refresh when we do not have Square's Dynamic options data ready
faisal-alvi eff9924
Update the fetch_options_data function to be dynamically used in more…
faisal-alvi b749aea
Remove unused namespace
faisal-alvi c756618
Add a function `retrieve_options_data` to be used in more files
faisal-alvi 22a1f5e
Use `ListCatalogResponse`
faisal-alvi c15f204
Handle the new cursor properly
faisal-alvi 4c6c390
fix variable name
faisal-alvi 5013533
fix spacing
faisal-alvi 7439434
Fix: Taxonomy Attribute converting to the Custom Attribute
faisal-alvi 08856d8
Fix: attribute name values changed at square issue!
faisal-alvi f0ede25
Fix: 'Attribute' set as attribute name issue
faisal-alvi bb991ef
remove use of catalog_options
faisal-alvi 9846a16
imrpove condition; skip checking catalog options
faisal-alvi 00f1bdd
options_ID to options_id
faisal-alvi 67a9e55
get attribute values as per the type
faisal-alvi 0dd016f
check if attribute and its all values exist, if not create!
faisal-alvi 6e4fb66
reset options when product has only one attribute
faisal-alvi 9239a92
also for simple products, reset options from catalog
faisal-alvi 218fb05
use correct name for attribute
faisal-alvi aeaa7d6
place init vars on correct location
faisal-alvi 9dd7e7f
use attribute_id to match with transient name
faisal-alvi b81f7e1
check for attribute value's Square ID
faisal-alvi d08b0db
remove loop break for both IDs found
faisal-alvi 7c6afe6
create options and values when IDs not found in transient
faisal-alvi 91c27d5
variation name as combination of all attribute values
faisal-alvi 02d0f43
pass slug to find the taxonomy
faisal-alvi 769b0e2
save option value ids in transient
faisal-alvi 3d5a617
again pass slug to catch the taxonomy
faisal-alvi db245d9
replace 'pa_' from attribute name to use as a slug
faisal-alvi 1d40484
API function to create options and values at Square
faisal-alvi bc2d941
Merge branch 'trunk' into multiple-variations-support
faisal-alvi 84fcb81
phpcs: spacing issues fixed
faisal-alvi 158e041
phpcs fix about the short ternaries
faisal-alvi 83f0b20
phpcs fix for short ternary in another file
faisal-alvi d194709
phpcs fixes for variable naming, params, etc
faisal-alvi 268a216
add Todo task to improve approach
faisal-alvi eec517d
update doc comments
faisal-alvi 7e57e87
Merge branch 'trunk' of github.com:woocommerce/woocommerce-square int…
iamdharmesh 3748828
Added initial tests.
iamdharmesh 0c593c1
Disable new product editor in sync tests.
iamdharmesh 5ac6a65
Multiple Vars Support in Manual Sync
faisal-alvi 33b1eac
change the func scope to avail it for sync process
faisal-alvi 568230d
Multiple Vars Support in Auto Sync / Interval Polling
faisal-alvi 306d1bf
apply filters for name and desc on update
faisal-alvi 0c81bab
remove unnecessary overwrites by old methods
faisal-alvi 535af2f
if no variation was found, check if the parent product exists
faisal-alvi 4256504
fix issue of 0 option values expected, found 3
faisal-alvi d9833b9
fix attributes object vs variation items
faisal-alvi 5ed09f5
fixed: [BAD_REQUEST] Expected ItemVariation to have 0 Item Option Val…
faisal-alvi 85ee8c4
removing comment
faisal-alvi bfef00d
Merge branch 'trunk' into multiple-variations-support
iamdharmesh d2725b9
Add Additional multiple variations tests.
iamdharmesh e516c35
Add tests for update product.
iamdharmesh c5ec9ef
Removed it from here as this would be handled in issue 254
faisal-alvi 6f3dde0
Merge branch 'trunk' into multiple-variations-support
faisal-alvi 11f883d
Merge push tests into single tests to save test run time.
iamdharmesh f63e00e
Added initial tests for Square SOR sync.
iamdharmesh d2a3c89
Merge branch 'multiple-variations-support' of github.com:woocommerce/…
iamdharmesh a7f6e4f
Tag the test correctly.
iamdharmesh 4942e33
Update time limit for looking for catalog data.
iamdharmesh 63df232
Fix flaky tests of Square SOR
iamdharmesh a2593a2
create new taxonomy attribute if does not found on import
faisal-alvi 3b60296
Update Square SOR test.
iamdharmesh 0ec5e01
If the attribute value is 'Any', add it to the attribute option values
faisal-alvi efa7d66
Set empty if attribute is to 'Any' to prevent it from being saved
faisal-alvi 5036cc2
fix phps errors,
faisal-alvi 9485c0a
phpcs spacing issue fixed,
faisal-alvi ed80611
TEMP: try identify failure root cause.
iamdharmesh 5c1644a
Try update idempotency key to something better, instead of `time()` w…
iamdharmesh 5ee9a88
Revert "TEMP: try identify failure root cause."
iamdharmesh d3fb826
Merge branch 'trunk' into multiple-variations-support
faisal-alvi 49eb1aa
use options instead of transients
faisal-alvi e949832
Merge branch 'multiple-variations-support' of github.com:woocommerce/…
faisal-alvi 51532ee
use transient in a more safer way
faisal-alvi 122ca65
Merge branch 'trunk' into multiple-variations-support
faisal-alvi ab6a035
Merge branch 'trunk' into multiple-variations-support
faisal-alvi 38b5adb
suggestions implemented
faisal-alvi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,12 +81,76 @@ public static function update_catalog_item( CatalogObject $catalog_object, \WC_P | |
$item_data->setReportingCategory( $square_category ); | ||
} | ||
|
||
$catalog_variations = $item_data->getVariations() ?: array(); | ||
$attributes = $product->get_attributes(); | ||
|
||
$product_variation_ids = $product->get_children(); | ||
$catalog_variations = $item_data->getVariations() ? $item_data->getVariations() : array(); | ||
faisal-alvi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// if dealing with a variable product, try and match the variations | ||
if ( $product->is_type( 'variable' ) ) { | ||
|
||
$product_variation_ids = $product->get_children(); | ||
/** | ||
* If there are multiple variations, it must be a considered as Dynamic Options supported product. | ||
* Create/Update and Assign Dynamic Options only if a product | ||
* has multiple attributes OR options already exists in Square. | ||
*/ | ||
if ( | ||
count( $attributes ) > 1 | ||
) { | ||
$options_ids = array(); | ||
$result = wc_square()->get_api()->retrieve_options_data(); | ||
$options_data = isset( $result[1] ) ? $result[1] : array(); | ||
faisal-alvi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Set the product as a dynamic options product. | ||
update_post_meta( $product->get_id(), '_dynamic_options', true ); | ||
|
||
// Loop through the attributes to create options and values at Square. | ||
foreach ( $attributes as $attribute_id => $attribute ) { | ||
|
||
$attribute_name = $attribute->get_name(); | ||
// Check if its a taxonomy-based attribute. | ||
$attribute_option_values = array(); | ||
if ( taxonomy_exists( $attribute_id ) ) { | ||
$terms = get_terms( $attribute_id ); | ||
$attribute_option_values = wp_list_pluck( $terms, 'name' ); | ||
} else { | ||
$attribute_option_values = $attribute->get_options(); | ||
} | ||
|
||
// Check if Square already has the option created with the same name. | ||
// To do so, we can check if we already have the name in options/transient, | ||
// if yes, use the relative Square ID. | ||
$option_id = false; | ||
foreach ( $options_data as $transient_option_id => $option_data_transient ) { | ||
if ( $option_data_transient['name'] === $attribute_name ) { | ||
$option_id = $transient_option_id; | ||
break; | ||
} | ||
} | ||
|
||
// If name does not exist, create a new option in Square. | ||
// If name exists, check if all values are present in Square. | ||
// If not, create the missing values. | ||
$option = wc_square()->get_api()->create_options_and_values( $option_id, $attribute_name, $attribute_option_values ); | ||
$options_ids[] = $option->getId(); | ||
} | ||
|
||
// Set the item_option_id for each option to the product. | ||
$product_options = array(); | ||
|
||
foreach ( $options_ids as $option_id ) { | ||
$item_option = new \Square\Models\CatalogItemOptionForItem(); | ||
$item_option->setItemOptionId( $option_id ); | ||
$product_options[] = $item_option; | ||
} | ||
|
||
$catalog_object->getItemData()->setItemOptions( $product_options ); | ||
} else { | ||
// If the product has only one attribute, it's not a dynamic options product. | ||
// So, remove the dynamic options meta. | ||
delete_post_meta( $product->get_id(), '_dynamic_options' ); | ||
$catalog_object->getItemData()->setItemOptions( null ); | ||
} | ||
|
||
if ( is_array( $catalog_variations ) ) { | ||
|
||
|
@@ -157,6 +221,8 @@ public static function update_catalog_item( CatalogObject $catalog_object, \WC_P | |
} | ||
|
||
$catalog_variations = array( self::update_catalog_variation( $variation_object, $product ) ); | ||
|
||
$catalog_object->getItemData()->setItemOptions( null ); | ||
} | ||
|
||
$item_data->setVariations( array_values( $catalog_variations ) ); | ||
|
@@ -225,7 +291,111 @@ public static function update_catalog_variation( CatalogObject $catalog_object, | |
* @see https://github.com/woocommerce/woocommerce-square/issues/570 | ||
*/ | ||
if ( 'variation' === $product->get_type() ) { | ||
$variation_data->setName( $product->get_name() ); | ||
$result = wc_square()->get_api()->retrieve_options_data(); | ||
$options_data = isset( $result[1] ) ? $result[1] : array(); | ||
$parent_product = wc_get_product( $product->get_parent_id() ); | ||
$attributes = $parent_product->get_attributes(); | ||
$variation_items = $product->get_attributes(); | ||
$variation_item_values = array(); | ||
|
||
if ( 1 === count( $attributes ) ) { | ||
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 see that these changes contain multiple "actions" that could be new methods to make reading easier. Basically, every time we have a comment here, the following code could be a new method named after the explanation. But this is optional |
||
// Set the name of the variation if it's a single variation. | ||
$variation_data->setName( reset( $variation_items ) ); | ||
$variation_data->setItemOptionValues( null ); | ||
} else { | ||
// If there are multiple attributes, the name of the variation is the combination of all attribute values. | ||
$variation_name = array(); | ||
|
||
/** | ||
* Set the `item_option_values` for the variation. | ||
* | ||
* Retrieve the options data from the transient. At this point, the options data | ||
* should already be available, as we have already created the necessary options | ||
* and values in the parent product above. | ||
*/ | ||
foreach ( $variation_items as $attribute_id => $attribute_value ) { | ||
// If the attribute value is empty, set it to 'Any'. | ||
$attribute_value = empty( $attribute_value ) ? 'Any' : $attribute_value; | ||
|
||
// Check if it's a global attribute (taxonomy-based, e.g., "pa_color") | ||
$taxonomy_exists = false; | ||
if ( taxonomy_exists( $attribute_id ) ) { | ||
// Use wc_attribute_label for global attributes | ||
$attribute_name = $attribute_id; | ||
$variation_name[] = $attribute_value = 'Any' === $attribute_value ? 'Any' : get_term_by( 'slug', $attribute_value, $attribute_id )->name; | ||
$taxonomy_exists = true; | ||
} else { | ||
// For custom attributes, simply use the cleaned-up attribute ID | ||
$attribute_name = ucwords( str_replace( '-', ' ', $attribute_id ) ); | ||
$attribute_id = $attribute_name; | ||
$variation_name[] = $attribute_value; | ||
} | ||
|
||
foreach ( $options_data as $option_id_transient => $option_data_transient ) { | ||
$option_id = ''; | ||
$option_value_id = ''; | ||
|
||
// Check for the Square ID of $attribute_name. | ||
if ( $option_data_transient['name'] === $attribute_id ) { // @TODO: If merchant changes the name of the attribute, this will create a new item at Square. Think of a way to handle this. | ||
$option_id = $option_id_transient; | ||
// Check for the Square ID of $attribute_value. | ||
foreach ( $option_data_transient['value_ids'] as $value_id => $value_name ) { | ||
if ( $value_name === $attribute_value ) { | ||
$option_value_id = $value_id; | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
|
||
if ( $option_id && $option_value_id ) { | ||
$option_value_object = new \Square\Models\CatalogItemOptionValueForItemVariation(); | ||
$option_value_object->setItemOptionId( $option_id ); | ||
$option_value_object->setItemOptionValueId( $option_value_id ); | ||
|
||
$variation_item_values[] = $option_value_object; | ||
} else { | ||
|
||
if ( $taxonomy_exists ) { | ||
// Get all attribute terms from Woo taxonomy. | ||
$attribute_option_values = get_terms( $attribute_id ); | ||
$attribute_option_values = wp_list_pluck( $attribute_option_values, 'name' ); | ||
} else { | ||
// Get all attribute values from the parent product. | ||
$attribute_option_values = $parent_product->get_attribute( $attribute_id ); | ||
$attribute_option_values = array_map( 'trim', explode( '|', $attribute_option_values ) ); | ||
} | ||
|
||
// If the attribute value is 'Any', add it to the attribute option values. | ||
if ( 'Any' === $attribute_value && ! in_array( 'Any', $attribute_option_values, true ) ) { | ||
$attribute_option_values[] = 'Any'; | ||
} | ||
|
||
$option = wc_square()->get_api()->create_options_and_values( $option_id, $attribute_name, $attribute_option_values ); | ||
$option_id = $option->getId(); | ||
|
||
// Get the Square ID of the attribute value. | ||
$updated_option_values = $option->getItemOptionData()->getValues(); | ||
foreach ( $updated_option_values as $option_value ) { | ||
if ( $option_value->getItemOptionValueData()->getName() === $attribute_value ) { | ||
$option_value_id = $option_value->getId(); | ||
break; | ||
} | ||
} | ||
|
||
$option_value_object = new \Square\Models\CatalogItemOptionValueForItemVariation(); | ||
$option_value_object->setItemOptionId( $option_id ); | ||
$option_value_object->setItemOptionValueId( $option_value_id ); | ||
|
||
$variation_item_values[] = $option_value_object; | ||
} | ||
} | ||
|
||
// Set the name of the variation as the combination of all attribute values. | ||
$variation_data->setName( implode( ', ', $variation_name ) ); | ||
$variation_data->setItemOptionValues( $variation_item_values ); | ||
} | ||
} | ||
|
||
if ( wc_square()->get_settings_handler()->is_inventory_sync_enabled() ) { | ||
|
@@ -307,6 +477,4 @@ public static function set_catalog_object_location_ids( CatalogObject $catalog_o | |
|
||
return $catalog_object; | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Can any of the getters return
null
values? If so, it would be nice to add some checks to avoid errors.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.
At this point in the code, there is a
getDisplayName
, which appears to be present for every item.