[ ] Does your code follow the WooCommerce Sniffs variant of WordPress coding standards?
[ ] Have you written new tests for your changes, as applicable?
[ ] Have you successfully run tests with your changes locally?
[ ] Will this change require new documentation or changes to existing documentation?
Changes proposed in this Pull Request:
This PR adds support for Multiple Variations.
Square and WooCommerce Attribute Types
Square options:
Dynamic Options: Shared across multiple items, similar to WooCommerce’s taxonomy attributes; variation names cannot be changed.
Static Options: Unique to individual items; variation names can be changed.
WooCommerce attributes:
Taxonomy: Defined globally across products.
Custom: Defined on a per-product basis.
Key Differences Between Dynamic and Static Options
Dynamic options can be shared across products and mirror WooCommerce’s taxonomy attributes, and variation names cannot be modified, as they are automatically generated by combining the attribute values. For example: “Red, Small.” Static options are unique to each item. If multiple options exist at Square, they must be dynamic.
Syncing Logic (Overview)
WooCommerce to Square Sync:
Creates dynamic options if there are multiple WooCommerce attributes, regardless of the WooCommerce's attributes type.
For a single attribute, it creates a static option at Square.
Square to WooCommerce Sync/Import:
Creates taxonomy attributes if the option slug matches an existing WooCommerce taxonomy attribute.
If only one option is received, it checks for an existing WooCommerce taxonomy attribute or creates a custom attribute if no match is found.
Syncing Logic for WooCommerce and Square (Detail)
From WooCommerce to Square:
If WooCommerce has more than one attribute and is set as the Source of Record (SOR), this PR will create dynamic options at Square, regardless of whether the attributes are taxonomy or custom. This is because we cannot create more than one static options for the single item (i.e product) at Square.
If there’s only one attribute, it creates a static option at Square.
If an attribute requires syncing, the PR creates an option at Square. New attribute values are also created at Square when synced from WooCommerce.
From Square to WooCommerce:
If the option name received from Square matches the slug of an existing WooCommerce taxonomy attribute, this PR creates a taxonomy attribute. If the merchant updates the slug in WooCommerce, it may not match next time and a custom attribute will be created instead.
If only one option is received, this PR checks against existing WooCommerce taxonomy attributes and attaches it if matched; otherwise, it creates a custom attribute at the product level. When creating a custom attribute, the PR reuses an existing custom attribute name, as Square does not provide the static option name. If no matching name exists, "Attribute" is assigned as the custom name.
Square API Limitations and Solutions
Square’s API only provides the option ID used in variations, not the display name. However, to match WooCommerce taxonomy attributes or to create a custom attribute, we need the option's display name. To address this, we fetch all options via another Square API (discussion link) and store the option names and their IDs in a transient (wc_square_options_data) with a 1-day expiration. The fetch_options_data() function initiates this before any import or sync process.
If a transient doesn’t have updated data, a sync may fail when creating an option with a name that already exists at Square, which would require a latest options data. This PR then stops the sync and sets the woocommerce_square_refresh_sync_cycle option to refresh the data.
Avoiding Attribute Name Conflicts
If WooCommerce’s taxonomy attribute is used, this PR passes the taxonomy name (e.g., “pacolor” rather than “Color”) to Square, preventing conflicts with custom attributes of the same name. The “pa” prefix helps WooCommerce users distinguish between taxonomy and custom attributes, avoiding potential conflicts.
New Option for Tracking
This PR introduces a new _dynamic_options option with true/false values to track whether dynamic options are used for a product. This is not in use but may be useful in future.
Pending Tasks
[ ] Optimize API call iterations by storing data in transients.
[ ] Importing/Syncing from Square to Woocommerce, all the dynamic option values are added to the attribute, for example, for colour attribute, if there is only red and green options are selected at Square, after the import/sync, it adds all of the dynamic option values to the Woocommerce attribute regardless of what selection. This is not creating any issue to the purchases of the side, but this should be addressed.
[ ] Confirm whether syncing products with the same attribute name but different values causes conflicts: Create a 2 custom attributes at Woocommerce with the same name, but use in two different products, each should have different values, for example, one should have “A|B|C” the other should “X|Y|Z”, when Syncing them to the square, first one will create an option with the values “A|B|C”, but when the second one will sync, it will override the previous values with the “X|Y|Z”, this is a conflict, which is currently theoretically written, needs to verify if this is the case and fix or maybe document it for merchants that they do not use the same name?
[ ] Perform full tests with Square as SOR to confirm behavior.
[ ] We check all attributes and their values exists on square for each variation iteration! Make it smart enough not to keep checking in thousands of loops, maybe by storing the data in transient with short term expiry?
[ ] If merchant changes the name of the attribute, this will create a new item instead of using the previous one. Think of a way to handle this. This can be considered as a separate issue, and handled in a post-PR.
Notes for Merchants
Avoid leaving any variation dropdowns set to “Any” in products with multiple attributes, as Square does not support empty values for dynamic options.
Avoid changing taxonomy attribute slugs or attribute names in WooCommerce, or renaming dynamic options in Square.
Do not create custom attributes with names identical to existing taxonomy attributes.
Closes #6, Closes #31 and Closes #231.
Steps to test the changes in this Pull Request:
Set WooCommerce as SOR.
Create the following product types in WooCommerce:
Simple Product
Variable Product with:
1 Custom Attribute
1 Taxonomy Attribute
2 Taxonomy Attributes
2 Custom Attributes
1 Custom + 1 Taxonomy Attribute
2 Taxonomy Attributes + 1 Custom Attribute
Confirm these products are auto-synced and correctly created in Square.
Confirm the same for manual sync using the “Sync” button in settings.
Import all products from Square to WooCommerce and verify they retain attributes without issues (e.g., taxonomy attribute not converted to custom).
Make changes to the random products and confirm it syncs to the Square and Imports back to the Woo without and issues, few examples:
add one more custom attribute to the “2 Taxonomy Attributes” product
remove 1 taxonomy attribute from the “2 Taxonomy Attributes + 1 Custom Attribute” product
add one more variation to any product
remove one variation from any product
change the dropdown of any variation in “1 Custom Attribute” product
change the dropdown of all variations in “2 Taxonomy Attributes + 1 Custom Attribute” product
add one more attribute value and create update the dropdown values of each variation
etc.
Set Square as SOR and perform all of the above steps (sorry :)) This time the chagnes from the point 6 should be made at Square.
Important: Confirm no issues affect existing users by creating all product types in trunk and performing sync/import in the fix branch.
All Submissions:
Changes proposed in this Pull Request:
This PR adds support for Multiple Variations.
Square and WooCommerce Attribute Types
Square options:
WooCommerce attributes:
Key Differences Between Dynamic and Static Options
Dynamic options can be shared across products and mirror WooCommerce’s taxonomy attributes, and variation names cannot be modified, as they are automatically generated by combining the attribute values. For example: “Red, Small.” Static options are unique to each item. If multiple options exist at Square, they must be dynamic.
Syncing Logic (Overview)
WooCommerce to Square Sync:
Square to WooCommerce Sync/Import:
Syncing Logic for WooCommerce and Square (Detail)
From WooCommerce to Square:
From Square to WooCommerce:
Square API Limitations and Solutions
Square’s API only provides the option ID used in variations, not the display name. However, to match WooCommerce taxonomy attributes or to create a custom attribute, we need the option's display name. To address this, we fetch all options via another Square API (discussion link) and store the option names and their IDs in a transient (
wc_square_options_data
) with a 1-day expiration. Thefetch_options_data()
function initiates this before any import or sync process.If a transient doesn’t have updated data, a sync may fail when creating an option with a name that already exists at Square, which would require a latest options data. This PR then stops the sync and sets the
woocommerce_square_refresh_sync_cycle
option to refresh the data.Avoiding Attribute Name Conflicts
If WooCommerce’s taxonomy attribute is used, this PR passes the taxonomy name (e.g., “pacolor” rather than “Color”) to Square, preventing conflicts with custom attributes of the same name. The “pa” prefix helps WooCommerce users distinguish between taxonomy and custom attributes, avoiding potential conflicts.
New Option for Tracking
This PR introduces a new
_dynamic_options
option withtrue/false
values to track whether dynamic options are used for a product. This is not in use but may be useful in future.Pending Tasks
Notes for Merchants
Closes #6, Closes #31 and Closes #231.
Steps to test the changes in this Pull Request:
Changelog entry