Skip to content

Commit e1633e0

Browse files
unnivgitfacebook-github-bot
authored andcommitted
DO change: Add route & feed column (#3580)
Summary: ## Description A new rewrite rule for the path '/fbcollection' is setup to intercept the query parameters clicked_product_id and shown_product_ids for displaying the linked products. ### Type of change - Add (non-breaking change which adds functionality) ## Checklist - [x] I have commented my code, particularly in hard-to-understand areas, if any. - [x] I have confirmed that my changes do not introduce any new PHPCS warnings or errors. - [x] I have checked plugin debug logs that my changes do not introduce any new PHP warnings or FATAL errors. - [x] I followed general Pull Request best practices. Meta employees to follow this [wiki]([url](https://fburl.com/wiki/2cgfduwc)). - [x] I have added tests (if necessary) and all the new and existing unit tests pass locally with my changes. - [x] I have completed dogfooding and QA testing, or I have conducted thorough due diligence to ensure that it does not break existing functionality. - [] I have updated or requested update to plugin documentations (if necessary). Meta employees to follow this [wiki]([url](https://fburl.com/wiki/nhx73tgs)). ## Changelog entry A new rewrite rule for '/fbcollection' ie., a new page Query parameters being processed: clicked_product_id, shown_product_ids Pull Request resolved: #3580 Test Plan: 1. Basic URL Access URL: /fbcollection/ Expected: Shows 8 popular products (default fallback). <img width="469" height="327" alt="image" src="https://github.com/user-attachments/assets/83ef2d80-1eb0-467b-80e0-7d629992c533" /> 2. With only clicked_product_id URL: /fbcollection/?clicked_product_id={Product SKU}_{Product Id} Expected: Shows the product with ID 'Product Id' if valid and visible. <img width="468" height="358" alt="image" src="https://github.com/user-attachments/assets/108faa5a-091c-486c-b5a7-5c18cdd4ce47" /> 3. With shown_product_ids URL: /fbcollection/?clicked_product_id={Product SKU1}_{Product Id1}&shown_product_ids={Product SKU2}_{Product Id2},{Product SKU3}_{Product Id3} Expected: Shows product 1,2,3 if valid and visible. Repeating IDs are cut to just one. <img width="475" height="338" alt="image" src="https://github.com/user-attachments/assets/6d186604-77a9-477a-837f-c0d1cced1a92" /> 4. Invalid or Missing Parameters URL: /fbcollection/?clicked_product_id=xdyr123_999999&shown_product_ids=asdf_abc_123,def_1231241 Expected: Falls back to 8 popular products due to invalid IDs. <img width="471" height="370" alt="image" src="https://github.com/user-attachments/assets/764549c8-ea27-4aec-8eff-ab805fc857c6" /> Reviewed By: akpurifb Differential Revision: D81484046 Pulled By: vahidkay-meta fbshipit-source-id: f159b68234f9e7e8abe0de120f122fab0f97feda
1 parent 6ff55af commit e1633e0

File tree

4 files changed

+143
-3
lines changed

4 files changed

+143
-3
lines changed

class-wc-facebookcommerce.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
require_once __DIR__ . '/includes/fbutils.php';
12+
require_once __DIR__ . '/includes/fbcollection.php';
1213

1314
use Automattic\WooCommerce\Admin\Features\Features as WooAdminFeatures;
1415
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
@@ -190,7 +191,9 @@ public function init() {
190191
// Hook the setup task. The hook admin_init is not triggered when the WC fetches the tasks using the endpoint: wp-json/wc-admin/onboarding/tasks and hence hooking into init.
191192
add_action( 'init', array( $this, 'add_setup_task' ), 20 );
192193
add_action( 'admin_notices', array( $this, 'add_inbox_notes' ) );
193-
194+
if ( class_exists( '\Facebook\WooCommerce\Commerce_Page_Override' ) ) {
195+
new \Facebook\WooCommerce\Commerce_Page_Override();
196+
}
194197
add_filter(
195198
'wc_' . self::PLUGIN_ID . '_http_request_args',
196199
array( $this, 'force_user_agent_in_latin' )

includes/fbcollection.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
/**
3+
* Facebook Commerce Recommendation Override for /fbcollection/
4+
* New URL Example: /fbcollection/?clicked_product_id=SKU123_123&shown_product_ids=SKU456_456,SKU789_789
5+
*/
6+
7+
namespace Facebook\WooCommerce;
8+
9+
use WooCommerce\Facebook\Framework\Logger;
10+
11+
defined( 'ABSPATH' ) || exit;
12+
13+
/**
14+
* Commerce Page Override class for handling /fbcollection/ endpoint
15+
*/
16+
class Commerce_Page_Override {
17+
18+
const REWRITE_VERSION = '1.0.0'; // Bump this ONLY when rewrite rules change.
19+
20+
public function __construct() {
21+
add_action( 'init', [ $this, 'register_rewrite_rule' ] );
22+
add_filter( 'query_vars', [ $this, 'add_query_vars' ] );
23+
add_action( 'woocommerce_product_query', [ $this, 'modify_product_query' ] );
24+
add_action( 'plugins_loaded', [ $this, 'check_and_trigger_flush' ] );
25+
add_action( 'init', [ $this, 'flush_rewrite_if_needed' ] );
26+
}
27+
28+
/**
29+
* Register /fbcollection/ as a virtual WooCommerce archive page.
30+
*/
31+
public function register_rewrite_rule() {
32+
add_rewrite_rule( '^fbcollection/?$', 'index.php?post_type=product&custom_fbcollection_page=1', 'top' );
33+
}
34+
35+
/**
36+
* Add custom query variable.
37+
*
38+
* @param array $vars Query variables.
39+
* @return array
40+
*/
41+
public function add_query_vars( $vars ) {
42+
$vars[] = 'custom_fbcollection_page';
43+
return $vars;
44+
}
45+
46+
/**
47+
* Modify WooCommerce product query to inject custom product IDs.
48+
*
49+
* @param WP_Query $query The WooCommerce product query.
50+
*/
51+
public function modify_product_query( $query ) {
52+
if ( 1 !== intval( get_query_var( 'custom_fbcollection_page' ) ) ) {
53+
return;
54+
}
55+
56+
// Debug logger to verify query filtering triggers
57+
Logger::log(
58+
'FBCollection Query Triggered: ' . print_r( $_GET, true ),
59+
[],
60+
array(
61+
'should_send_log_to_meta' => false,
62+
'should_save_log_in_woocommerce' => true,
63+
'woocommerce_log_level' => \WC_Log_Levels::DEBUG,
64+
)
65+
);
66+
67+
// Helper to extract product_id from retailer_id format
68+
$extract_product_id = function ( $retailer_id ) {
69+
if ( false !== strpos( $retailer_id, '_' ) ) {
70+
$parts = explode( '_', $retailer_id );
71+
return absint( end( $parts ) );
72+
}
73+
return absint( $retailer_id );
74+
};
75+
76+
// Parse clicked_product_id
77+
$clicked_product_id_raw = sanitize_text_field( wp_unslash( $_GET['clicked_product_id'] ?? '' ) );
78+
$clicked_product_id = $extract_product_id( $clicked_product_id_raw );
79+
80+
// Parse shown_product_ids
81+
$shown_product_ids_raw = explode( ',', sanitize_text_field( wp_unslash( $_GET['shown_product_ids'] ?? '' ) ) );
82+
$shown_product_ids = array_map( $extract_product_id, array_map( 'sanitize_text_field', $shown_product_ids_raw ) );
83+
$shown_product_ids = array_filter( $shown_product_ids ); // Remove empty/invalid
84+
$shown_product_ids = array_slice( $shown_product_ids, 0, 30 ); // Limit to 30
85+
86+
$final_product_ids = [];
87+
88+
if ( $clicked_product_id && 'product' === get_post_type( $clicked_product_id ) ) {
89+
$final_product_ids[] = $clicked_product_id;
90+
}
91+
92+
$valid_shown_ids = array_filter(
93+
$shown_product_ids,
94+
function ( $id ) use ( $clicked_product_id ) {
95+
if ( $clicked_product_id === $id ) {
96+
return false;
97+
}
98+
$product = wc_get_product( $id );
99+
return $product && $product->is_visible();
100+
}
101+
);
102+
103+
$final_product_ids = array_merge( $final_product_ids, $valid_shown_ids );
104+
105+
if ( ! empty( $final_product_ids ) ) {
106+
$query->set( 'post__in', $final_product_ids );
107+
$query->set( 'orderby', 'post__in' );
108+
$query->set( 'posts_per_page', count( $final_product_ids ) );
109+
} else {
110+
$query->set( 'orderby', 'popularity' );
111+
$query->set( 'posts_per_page', 8 );
112+
}
113+
}
114+
115+
/**
116+
* Versioned Rewrite Rules Flush on Upgrade.
117+
*/
118+
public function check_and_trigger_flush() {
119+
$stored_version = get_option( 'fbwcommerce_rewrites_flushed' );
120+
if ( self::REWRITE_VERSION !== $stored_version ) {
121+
update_option( 'fbwcommerce_flush_needed', true );
122+
update_option( 'fbwcommerce_rewrites_flushed', self::REWRITE_VERSION );
123+
}
124+
}
125+
126+
public function flush_rewrite_if_needed() {
127+
// This function checks if a flush is required (flagged by check_and_trigger_flush)
128+
// If the flag is set, it flushes rewrite rules and deletes the flag to avoid repeat flushes.
129+
if ( get_option( 'fbwcommerce_flush_needed' ) ) {
130+
flush_rewrite_rules();
131+
delete_option( 'fbwcommerce_flush_needed' );
132+
}
133+
}
134+
}

includes/fbproduct.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,9 @@ public function prepare_product( $retailer_id = null, $type_to_prepare_for = sel
17871787
$product_data['age_group'] = $this->get_fb_age_group();
17881788
$product_data['gender'] = $this->get_fb_gender();
17891789
$product_data['material'] = Helper::str_truncate( $this->get_fb_material(), 100 );
1790-
1790+
// Generate and add collection URI
1791+
$collection_uri = site_url( '/fbcollection/' );
1792+
$product_data['custom_label_4'] = $collection_uri;
17911793
if ( $this->get_type() === 'variation' ) {
17921794
$parent_id = $this->woo_product->get_parent_id();
17931795
$parent_product = wc_get_product( $parent_id );

includes/fbproductfeed.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ public function get_product_feed_header_row() {
420420
'brand,price,availability,item_group_id,checkout_url,' .
421421
'additional_image_link,sale_price_effective_date,sale_price,condition,' .
422422
'visibility,gender,color,size,pattern,google_product_category,default_product,' .
423-
'variant,gtin,quantity_to_sell_on_facebook,rich_text_description,internal_label,external_update_time,' .
423+
'variant,gtin,quantity_to_sell_on_facebook,custom_label_4,rich_text_description,internal_label,external_update_time,' .
424424
'external_variant_id, is_woo_all_products_sync' . PHP_EOL;
425425
}
426426

@@ -578,6 +578,7 @@ private function prepare_product_for_feed( $woo_product, &$attribute_variants )
578578
static::format_string_for_feed( static::get_value_from_product_data( $product_data, 'variant' ) ) . ',' .
579579
static::format_string_for_feed( static::get_value_from_product_data( $product_data, 'gtin' ) ) . ',' .
580580
static::format_string_for_feed( static::get_value_from_product_data( $product_data, 'quantity_to_sell_on_facebook' ) ) . ',' .
581+
static::format_string_for_feed( static::get_value_from_product_data( $product_data, 'custom_label_4' ) ) . ',' .
581582
static::format_string_for_feed( static::get_value_from_product_data( $product_data, 'rich_text_description' ) ) . ',' .
582583
static::format_internal_labels_for_feed( static::get_value_from_product_data( $product_data, 'internal_label' ) ) . ',' .
583584
static::get_value_from_product_data( $product_data, 'external_update_time' ) . ',' .

0 commit comments

Comments
 (0)