When "Create variations from all attributes" is used to create
variations it generates term relationship entries for all the generated
variations, however that doesn't happen when the term can be interpreted
as a numeric value. This is because in that case product->get_attributes
returns the attribute values as numbers, but the code that generates
the term relationships expect those to always be strings.
When manually adding a given variation this doesn't happen.
The fix is to simply strval-ize the value before using it, but it might
be worth investigating why this is happening.
The previous commit fixes a bug that causes the "attribute_" metadata
with an empty value to not be created when a new variation attribute
is added to the product (so that all variations have the attribute
with a value of "Any..."). This commit adds a data migration to
backfill the missing metadata for existing variations.
When a new variation attribute is added, the corresponding 'attribute_'
meta entries are added for all variations with an empty value;
and when an existing variation attribute is removed, the existing
'attribute_' meta entries are deleted for all variations.
This is necessary for the filter by attribute widget to work properly
when variations exist with a value of "Any..." for attributes.
When a variation product has an attribute with a value of "Any...",
and there's a filter by attribute widget for that attribute, then
that product won't be included in the counts displayed in the widget
(and if the count ends up being zero, the attribute won't be shown
in the widget).
This happens before since Woo 4.4, this widget works by looking at
entries in the term relationships table for varitions too
(used to do so for simple products and for "main" variable products
only), see PR #26260; but there are no such entries for
"Any..." attributes.
This commit fixes that by extending the SQL query used by the widget
to look for variations that have empty attribute values in the meta
table too.
Previously 'dirname( __FILE__ )' was used to import files, however, the directory separator was missing.
This commit replaces 'dirname( __FILE__ )' that was introduced in 5370d02484 with __DIR__ and added DIRECTORY_SEPARATOR
Relative include paths in PHP can break whenever the server is running opcache. As such, WordPress.com deploy system refuses to include WooCommerce because of that issue.
This commit changes the relative include paths to absolute include paths.
Relates to #27269
This bug was introduced in #26260. The sequence is:
1. WC_Query::adjust_posts_count runs, to handle found_posts filter,
this indirectly executes wc_setup_loop.
2. At this point $GLOBALS['wp_query']->max_num_pages hasn't been set
yet, and has a value of 0. Thus the loop variable total_pages
is set to 0.
3. Later wc_setup_loop runs again and this time
$GLOBALS['wp_query']->max_num_pages is already set, but since
the loop variable total_pages already exists, it keeps its
value of 0.
4. The pagination controls never show if total_pages is less than 2.
The fix consists of hooking into the_posts to set the value of
total_pages again, at that point $GLOBALS['wp_query']->max_num_pages
is already set.
PR #26260 introduced a handler for 'found_posts' filter in WC_Query
class in order to adjust the count depending on the visibility
of variation products. However the handler incorrectly assumed
that the filter was triggered only when listing products, when
actually it's also triggered for any post type e.g. pages.
In these cases the post count was set to zero, which caused bugs.
Now the handler starts with the originally supplied posts count,
and only decrements it when a post is a product AND is not visible.
- Fix a call to get_available_variations with incorrect optional arguments.
- Add code that has been removed in WC_Product_Variable::get_available_variations.
Now, if there are filters present the logic is as follows:
- For multiple filtering values of the same attribute:
the product is visible if there's at least one variation
that has one of the filtering values associated to the attribute,
or if there's at least one variation having the attribute
with a value of "Any".
- For filtering by more than one attribute:
the product is visible if there's at least one variation that
is visible for ALL the attributes according to the above rule.
Note that this is irrespective of the type of logic configured for
the filter (OR or AND).
Two adjustments were needed:
- Adjust the count even when there's no nav filtering in the query.
This is necessary to present the proper products count.
even when the woocommerce_product_is_visible filter is used.
- Account for the case where $GLOBALS['wp_query']->posts
returns objects instead of ids (for example when viewing
a product page).
After the change that registers variation attributes as terms
(in addition to reigstering them as post meta) it is now time
to modify the get_filtered_term_product_counts methods in
WC_Widget_Layered_Nav so that it works consistently for both
variable and non-variable products. The logic for the counters
is now as follows:
with OR operator:
- Simple products: count the attributes of all visible products
(unchanged behavior).
- Variable products: count attributes corresponding to
visible variations.
with AND operator:
- Simple products: count the attributes of visible products but only
for products that have all the selected (unchanged behavior).
- Variable products: find all the products for which all the variations
corresponding to the selected attributes exist and are visible,
then count the attributes corresponding to the visible variations
of those products.
A product is "visible" if it's published, not excluded for catalog,
and has stock. Additionally, a variable product will not be considered
visible if the parent product is not.
Product attributes are currently recorded as terms in
wp_term_relationships (product attributes are actually taxonomies).
In the case of variable products this is true for the main product,
but not for the variations. The attributes used to define variations
are stored as post meta, but nothing is recorded in the term
relationships table.
This is a problem when using the layered nav filtering plugin,
since the attribute counters displayed are calculated based solely
on the contents of the term relationships table. Adding meta queries
would be really messy (especially when the widget is configured
with AND operator) and would probably also hurt performance.
This commit adds a change to store the attributes for variations
as term relationships, additionally to storing them as post meta.
Terms are stored on variation creation, and updated/deleted together
with the variation as appropriate. "Any" variations (stored in meta
as empty values) are not stored as terms.
Additionally, a database upgrade is included in order to backfill
terms for already existing products.
The layered nav filtering doesn't work well with variable products
when some variations have stock and other don't. When a term is
selected in the widget, a variable product having no stock for
the variation corresponding to that term but having stock for
other variations will be displayed, but it shouldn't.
This commit fixes that by introducing two changes:
- A new override of "is_visible" for WC_Product_Variable that
looks at the supplied filters, compares them against the corresponding
available variations and calculates the visibility based on
the query type (OR or AND).
- A hook on the "found_posts" filter in WC_Query, that adjusts
the posts count based on the found products visibility
when there are filters available; this is needed to sync the
"displaying X posts" messages and the paging when variable
products are hidden due to stock status.
Additionally, the visibility calculated in "found_posts" is cached
as loop variables so that it isn't calculated again when actually
displaying the products.
Using WooCommerce on a multisite network using the hyperdb drop-in, the foreign key check fails although there is a foreign key.
32037e37dd/includes/class-wc-install.php (L745-L763)
The first problem is that hyperdb wasn't designed to route `information_schema` queries. After patching hyperdb, the query is routed to the correct database.
The second problem is that the query still finds zero foreign keys because `$wpdb->dbname` is blank when the query is generated. Hyperdb only has a dbname in the context of a query being executed; hyperdb extracts the table name, then maps that to the correct database.
Although we could find a way to support such `information_schema` queries, they are also not preferred because they are notoriously slow. On WordPress.com they take 300ms, versus 3ms for a `SHOW CREATE TABLE` which similarly reveals the existence of the foreign key.
The proposed changes simplify the check, make it faster, and make it work with hyperdb.
This makes match with WP sanitization for post_title.
WP sanitize post_title using kses_init_filters() when
the current user can't use unfiltered HTML.
It is possible for a later duplicate webhook to be fired too early if
the same webhook triggers in one request more than once with the updated
changes from the second one missing if it happens too quickly.
This queues all webhook to be register on shutdown instead of just
syncronous ones to make sure all data from the request is updated first
before the webhook gets queued.
`wc_round_tax_total` is for when prices are inclusive of taxes, however, shipping taxes can never include taxes so they should always use `round( $price, wc_price_get_decimals() )` instead.
When rounding at subtotal is enabled, line items are already rounded where they need to, so we only should do any further rounding when displaying values and no where else.
This is part of our larger attempt to remove individual rounding as much as possible.
- src/README.md largely expanded
- tests/README.md expanded
- includes/README.md added
- src/Internal/REAMDE.md added
src/README.md and includes/README.md have TODO placeholders to add
guidelines regarding to actions and filters.
The following methods are added and can be invoked using `WC()`,
they just redirect to the same methods in LegacyProxy:
call_function
call_static
get_instance_of
- Method and class renames.
- Removed unnecessary autoloader registration.
- Add a unit test for classes with non-object type hints
in constructor arguments.
- The `Container` class now implements `Psr\Container\ContainerInterface`
(and registers itself as such), holding a private instance of the
real container. This way it's a read-only container from the point
of view of plugins (which should use their own containers, but
can still use this to get WooCommerce classes).
- All registrations are now done in the `Container` constructor via
service providers.
- The container instance is now held in a global variable, set in
`woocommerce.php`
- Added the `wc_get_container` function for old code.
- Added the `AbstractServiceProvider` class, which inherits with the
corresponding League's class and adds some utility methods,
most notably `add/shareWithAutoArguments`.
- Added the `ActionsProxy` and `LegacyProxy` classes, they are
registered via a dedicated service provider.
- `WC_Queue_Interface` is no longer resolvable via the container
(which is for classes inside `src` only).
- All the method names in the new classes have the format `fooBarFizz`
to be PSR4 compliant, so the MethodNameInvalid error has been
disabled in phpcs.xml for the `src` directory.
- Introduced the `@public` annotation for public API classes
(classes that plugins can use and whose backwards compatibility
we guarantee), applied to `ActionsProxy` and to `LegacyProxy` for now.
- Removed the hack for the autoloader as now it doesn't work anyway.
For the changes in this branch to work, now WP_DEBUG must be false.
- Renamed from `ObjectContainer` to `Container`.
- It now inherits from PHP League's `Container`.
- It has now a `defineAsSharedAutowired` method.
- Initialization moved to the `WooCommerce::init_container` method.
- The static method for object resolution is now `WooCommerce::get_instance_of`.
- Add PHP League's Container package via Composer.
- Add an ObjectContainer class that encapsulates all the configuration
and insulates the codebase from the concrete DI engine used.
- Add an improved ReflectionContainer class that will allow to
register individual classes as singletons while autowiring.
- Use ObjectContainer to resolve the WooCommerce class, everything
instantiated with "new" inside it, and all singletons that are
usually obtained via WC() function.
- Introduce the CustomerProvider class.
- Introduce a service provider to resolve WC_Queue_Interface,
this replaces the WC_Queue class.
- Mark as obsolete all the replaced "instance()" methods,
and the entire WC_Queue class.
While variations only uses "published" and "private" statuses when
exporting we should display the variations as "draft" in case the parent
product it's also a draft.
At some point the 'change_stock' key is assumed to be present
in the request data, but it might not. Fixed to test for existence
before using the value.
Create a new `request_data` method in WC_Admin_Post_Types that
just returns $_REQUEST. This is intended to ease unit testing,
as this method can be easily mocked to return test data.
For bulk edit: even if stock status was left as "No change", the
status of all variations was being changed to whatever the status
of the product was before it was converted to variable. Now
no change is performed when "No change" is selected, and all
variations change to whatever is selected otherwise.
For quick edit: a new "No change" option is added that will be
preselected when the product is variable. Previously, whatever
status the product had before being converted to variable was being
shown, and that's the status that would be set when saving.
Also, a "This will change the stock status of all variations"
message is displayed before the selector.
Two methods have been created:
- update_stock_status, replaces code that was duplicated in the
quick_edit_save and bulk_edit_save methods.
- set_new_price, replaces code that was duplicated-ish in the
bulk_edit_save for setting the new regular and sales prices
(code was not identical but very similar).
Also, `round` is now used on sale price calculations that involve
multiplying by a percent, the same was as it was done already
to calculate the regular price.
Some of our endpoints don't have an "<id>" parameter but we're expecting one in the CLI. Since the `id` is already part of the supported IDs we don't actually need this since it will pull it from the route.
Fix the error message shown when the max setting for rows is shown. before it stated "The minimum allowed setting is 8" when it should be "The maximum allowed setting is 8"