Skip to content
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

Add suggested-products product endpoint #43720

Merged
merged 28 commits into from Jan 22, 2024

Conversation

retrofox
Copy link
Contributor

@retrofox retrofox commented Jan 16, 2024

Submission Review Guidelines:

Changes proposed in this Pull Request:

This PR introduces a new Suggested Products endpoint:

wc/v2/products/suggested-products

Params

The endpoint accepts three parameters: categories, tags, and limit.

wc/v2/products/suggested-products?related_categories[]=<cat-01>&related_categories[]=<cat-02>&tags[]=<tag-01>...

Also, it accepts the combine param to combine or not the current product items (related_categories, related_tags, ...) with the provided ones.

Closes #43714

How to test the changes in this Pull Request:

Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:

A simple way to check this endpoint if by using the apiFetch library which is exposed globally in the new Product Editor app:

  1. Enable the new Product Editor app
  2. Create/edit a product
  3. Open the dev console

Now, you can start to perform requests by using the apiFetch lib:

wp.apiFetch( { path: 'wc/v3/products/suggested-products' } ).then( console.log ).catch( console.error )

Get default suggested products

  1. Ensure you have a few products to test.
  2. Set categories and tags to get suggested products
  3. Get the suggested products by running the following script. Remember you need to define the parameters for your testing site. I've defined category 21, and limit 3
wp.apiFetch( { path: 'wc/v3/products/suggested-products?categories=21&limit=3' } )
    .then( console.log )
    .catch( console.error )
image

Changelog entry

  • Automatically create a changelog entry from the details below.

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Message

Comment

@retrofox retrofox added focus: new product ux revamped product management experience team: Mothra labels Jan 16, 2024
@retrofox retrofox requested a review from a team January 16, 2024 21:36
@retrofox retrofox self-assigned this Jan 16, 2024
@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Jan 16, 2024
Copy link
Contributor

Hi , @woocommerce/mothra

Apart from reviewing the code changes, please make sure to review the testing instructions as well.

You can follow this guide to find out what good testing instructions should look like:
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions

@retrofox retrofox linked an issue Jan 16, 2024 that may be closed by this pull request
Copy link
Contributor

github-actions bot commented Jan 16, 2024

Test Results Summary

Commit SHA: 7286f43

Test 🧪Passed ✅Failed 🚨Broken 🚧Skipped ⏭️Unknown ❔Total 📊Duration ⏱️
API Tests25900202610m 37s
E2E Tests259002802875m 37s

To view the full API test report, click here.
To view the full E2E test report, click here.
To view all test reports, visit the WooCommerce Test Reports Dashboard.

@retrofox retrofox changed the title Add linked-products product endpoint Add related-products product endpoint Jan 17, 2024
@retrofox retrofox force-pushed the update/add-product-related-products-endpoint branch from 69b70a6 to 2a0b44f Compare January 18, 2024 17:28
Copy link
Contributor

@louwie17 louwie17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this @retrofox, I haven't tested this, but left some more thoughts on the implementation of this, let me know what you think?

),
),
array(
'methods' => WP_REST_Server::READABLE,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are supporting the passing in of the attributes/categories/tags and such should we turn this into a POST instead? So that data can be passed in as data versus a query?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not opposed to leaving it as a GET request for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that using GET method is appropriate in this case as we do not intend to make any changes to the data.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I suppose that is fine, it just seems like it may get messy when we also support the passing in of attributes, as attributes contain a key and value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good point. It doesn't seem pretty easy to pass it in the query. right?

Copy link
Contributor

@louwie17 louwie17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @retrofox, this is heading in the right direction I think, and your right it is pretty clean :)
I did leave several inline suggestions and noticed two bugs, one around the combining of the tags/categories and another around a caching issue with transients ( I left inline comments around the relevant code for each of those ).

'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_related_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably have a unique function for this, I left another comment below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The related-products endpoint supports almost all of them. Maybe we should rake over the include one.

I do imagine a scenario where we want to pick all related products except a few:

products/100/related-products?related_categories=10?exclude=1,2,3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now I got it.
Let me update the PR.

* overwriting the post__in parameter.
*/
if ( ! empty( $this->related_producs_ids ) ) {
$args['post__in'] = $this->related_producs_ids;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aaah I was curious how the parent::get_items( $request ); was still working, but I guess that is because of this.

Do you think it would make more sense if we just call wc_get_product here with array_map, I saw something similar in one of the template functions ( don't have to copy this, just an example of array_map:

$args['related_products'] = array_filter( array_map( 'wc_get_product', wc_get_related_products( $product->get_id(), $args['posts_per_page'], $product->get_upsell_ids() ) ), 'wc_products_array_filter_visible' );
// Handle orderby.
$args['related_products'] = wc_products_array_orderby( $args['related_products'], $args['orderby'], $args['order'] );

Copy link
Contributor Author

@retrofox retrofox Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The (good, I think) thing about using the parent get_items() is that it will inherit the whole behavior.
For instance, could I use the _fields, per_page, and other params with this approach? I think we could, but it will require addressing them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see any issue by using the get_items() method? In the end, what we need to return is a products collection

plugins/woocommerce/includes/rest-api/Server.php Outdated Show resolved Hide resolved
@retrofox retrofox changed the title Add related-products product endpoint Add suggested-products product endpoint Jan 19, 2024
Copy link
Contributor

@louwie17 louwie17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tested well and code looks great, there is just one slight clean up thing necessary ( I left an inline comment ), otherwise good work!!

Copy link
Contributor

@louwie17 louwie17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating :) and sorry for not noticing another piece of code that could also be removed ( I left an inline comment ), not sure how I missed it in the last review.

*/
if ( ! empty( $this->suggested_products_ids ) ) {
$args['post__in'] = $this->suggested_products_ids;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not noticing this earlier, but this can also be removed right?

Copy link
Contributor Author

@retrofox retrofox Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't sorry at all. It's my mistake. Thanks for reviewing. Addressed.

Actually, the endpoint keeps relying on the parent get_items() method. If we take this path, these changes are needed.

@retrofox retrofox force-pushed the update/add-product-related-products-endpoint branch from 97f84c0 to 7286f43 Compare January 22, 2024 18:33
Copy link
Contributor

@louwie17 louwie17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how this came together, nice work @retrofox 🎉

@retrofox retrofox merged commit 0940201 into trunk Jan 22, 2024
34 checks passed
@retrofox retrofox deleted the update/add-product-related-products-endpoint branch January 22, 2024 20:18
@github-actions github-actions bot added this to the 8.6.0 milestone Jan 22, 2024
@github-actions github-actions bot added the needs: analysis Indicates if the PR requires a PR testing scrub session. label Jan 22, 2024
@alopezari alopezari added needs: internal testing Indicates if the PR requires further testing conducted by Solaris status: analysis complete Indicates if a PR has been analysed by Solaris contains: rest api change Indicates if the PR contains a REST API change. and removed needs: analysis Indicates if the PR requires a PR testing scrub session. labels Jan 23, 2024
opr pushed a commit that referenced this pull request Jan 25, 2024
* init approach of related products endpoint

* register related prodducts endpoint

* rename response prop with ids

* filter categoris from endpoint params

* filter categories when pulling related products

* changelog

* extend from WC_REST_CRUD_Controller class

* iterate over defininf endpoint params

* doc

* merge product terms with params

* introduce `combine` param

* return products collection instead of plain array

* fixinf eslint issues

* pass proper fn args to bound fns

* do not call parent register method

* post type is defined by parent controller class

* remove related products controller

* extend products controller with `related-products`endpoint

* filter post__in param

* when no related products found return empty array

* change and register endpoint params

* remove commented line

* add a custom method to extend the params

* update

* fix typo

* ensure to respect the products limit

* fix eslint issue

* remove unrequired endpoint id param
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contains: rest api change Indicates if the PR contains a REST API change. focus: new product ux revamped product management experience needs: internal testing Indicates if the PR requires further testing conducted by Solaris plugin: woocommerce Issues related to the WooCommerce Core plugin. status: analysis complete Indicates if a PR has been analysed by Solaris team: Mothra
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create a custom related-products endpoint
4 participants