feat: Phase 1 - Backend API meta compatibility (Level 1)
**Implemented: Backend API Enhancement for Level 1 Compatibility** Following IMPLEMENTATION_PLAN_META_COMPAT.md Phase 1 **OrdersController.php:** ✅ Added get_order_meta_data() - Expose meta in API responses ✅ Added update_order_meta_data() - Update meta from API ✅ Modified show() - Include meta in response ✅ Modified update() - Handle meta updates ✅ Added filter: woonoow/order_allowed_private_meta ✅ Added filter: woonoow/order_updatable_meta ✅ Added filter: woonoow/order_api_data ✅ Added action: woonoow/order_updated **ProductsController.php:** ✅ Added get_product_meta_data() - Expose meta in API responses ✅ Added update_product_meta_data() - Update meta from API ✅ Modified format_product_full() - Include meta in response ✅ Modified update_product() - Handle meta updates ✅ Added filter: woonoow/product_allowed_private_meta ✅ Added filter: woonoow/product_updatable_meta ✅ Added filter: woonoow/product_api_data ✅ Added action: woonoow/product_updated **Meta Filtering Logic:** - Skip internal WooCommerce meta (_wc_*) - Skip WooNooW internal meta (_woonoow_*) - Public meta (no underscore) - always expose - Private meta (starts with _) - check allowed list - Plugins can add to allowed list via filters **Default Allowed Meta (Orders):** - _tracking_number - _tracking_provider - _tracking_url - _shipment_tracking_items - _wc_shipment_tracking_items - _transaction_id - _payment_method_title **How It Works:** 1. Plugin stores: update_post_meta($order_id, '_tracking_number', '123') 2. WooNooW API exposes: GET /orders/123 returns meta._tracking_number 3. Frontend can read/write via API 4. Plugin works WITHOUT any extra effort **Next Steps:** - Phase 2: Frontend components (MetaFields, useMetaFields) - Phase 3: PHP MetaFieldsRegistry system - Testing with popular plugins **Status:** Backend API ready for Level 1 compatibility! 🎉
This commit is contained in:
@@ -522,8 +522,12 @@ class OrdersController {
|
|||||||
'notes' => $notes,
|
'notes' => $notes,
|
||||||
'coupons' => $coupon_codes,
|
'coupons' => $coupon_codes,
|
||||||
'customer_note' => $order->get_customer_note(),
|
'customer_note' => $order->get_customer_note(),
|
||||||
|
'meta' => self::get_order_meta_data( $order ),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Allow plugins to modify response (Level 1 compatibility)
|
||||||
|
$data = apply_filters( 'woonoow/order_api_data', $data, $order, $req );
|
||||||
|
|
||||||
return new WP_REST_Response( $data, 200 );
|
return new WP_REST_Response( $data, 200 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,6 +686,11 @@ class OrdersController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update custom meta fields (Level 1 compatibility)
|
||||||
|
if ( isset( $p['meta'] ) && is_array( $p['meta'] ) ) {
|
||||||
|
self::update_order_meta_data( $order, $p['meta'] );
|
||||||
|
}
|
||||||
|
|
||||||
// SOLUTION: Block WooCommerce analytics tracking (pixel.wp.com) during save
|
// SOLUTION: Block WooCommerce analytics tracking (pixel.wp.com) during save
|
||||||
// This was causing 30s timeout on every order status change
|
// This was causing 30s timeout on every order status change
|
||||||
add_filter( 'pre_http_request', function( $preempt, $args, $url ) {
|
add_filter( 'pre_http_request', function( $preempt, $args, $url ) {
|
||||||
@@ -694,6 +703,9 @@ class OrdersController {
|
|||||||
|
|
||||||
$order->save();
|
$order->save();
|
||||||
|
|
||||||
|
// Allow plugins to perform additional updates (Level 1 compatibility)
|
||||||
|
do_action( 'woonoow/order_updated', $order, $p, $req );
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
remove_all_filters( 'pre_http_request' );
|
remove_all_filters( 'pre_http_request' );
|
||||||
|
|
||||||
@@ -2172,4 +2184,99 @@ class OrdersController {
|
|||||||
'expiry_date' => $coupon->get_date_expires() ? $coupon->get_date_expires()->date( 'Y-m-d' ) : null,
|
'expiry_date' => $coupon->get_date_expires() ? $coupon->get_date_expires()->date( 'Y-m-d' ) : null,
|
||||||
], 200 );
|
], 200 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get order meta data for API exposure (Level 1 compatibility)
|
||||||
|
* Filters out internal meta unless explicitly allowed
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function get_order_meta_data( $order ) {
|
||||||
|
$meta_data = [];
|
||||||
|
|
||||||
|
foreach ( $order->get_meta_data() as $meta ) {
|
||||||
|
$key = $meta->key;
|
||||||
|
$value = $meta->value;
|
||||||
|
|
||||||
|
// Skip internal WooCommerce meta (starts with _wc_)
|
||||||
|
if ( strpos( $key, '_wc_' ) === 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip WooNooW internal meta
|
||||||
|
if ( strpos( $key, '_woonoow_' ) === 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public meta (no underscore) - always expose
|
||||||
|
if ( strpos( $key, '_' ) !== 0 ) {
|
||||||
|
$meta_data[ $key ] = $value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private meta (starts with _) - check if allowed
|
||||||
|
$allowed_private = apply_filters( 'woonoow/order_allowed_private_meta', [
|
||||||
|
// Common shipping tracking fields
|
||||||
|
'_tracking_number',
|
||||||
|
'_tracking_provider',
|
||||||
|
'_tracking_url',
|
||||||
|
'_shipment_tracking_items',
|
||||||
|
'_wc_shipment_tracking_items',
|
||||||
|
|
||||||
|
// Payment gateway meta
|
||||||
|
'_transaction_id',
|
||||||
|
'_payment_method_title',
|
||||||
|
|
||||||
|
// Allow plugins to add their meta via filter
|
||||||
|
], $order );
|
||||||
|
|
||||||
|
if ( in_array( $key, $allowed_private, true ) ) {
|
||||||
|
$meta_data[ $key ] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $meta_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update order meta data from API (Level 1 compatibility)
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order
|
||||||
|
* @param array $meta_updates
|
||||||
|
*/
|
||||||
|
private static function update_order_meta_data( $order, $meta_updates ) {
|
||||||
|
// Get allowed updatable meta keys
|
||||||
|
$allowed = apply_filters( 'woonoow/order_updatable_meta', [
|
||||||
|
// Common shipping tracking fields
|
||||||
|
'_tracking_number',
|
||||||
|
'_tracking_provider',
|
||||||
|
'_tracking_url',
|
||||||
|
|
||||||
|
// Allow plugins to add their meta via filter
|
||||||
|
], $order );
|
||||||
|
|
||||||
|
foreach ( $meta_updates as $key => $value ) {
|
||||||
|
// Skip internal WooCommerce meta
|
||||||
|
if ( strpos( $key, '_wc_' ) === 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip WooNooW internal meta
|
||||||
|
if ( strpos( $key, '_woonoow_' ) === 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public meta (no underscore) - always allow
|
||||||
|
if ( strpos( $key, '_' ) !== 0 ) {
|
||||||
|
$order->update_meta_data( $key, $value );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private meta - check if allowed
|
||||||
|
if ( in_array( $key, $allowed, true ) ) {
|
||||||
|
$order->update_meta_data( $key, $value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -371,8 +371,16 @@ class ProductsController {
|
|||||||
$product->set_gallery_image_ids($data['gallery_image_ids']);
|
$product->set_gallery_image_ids($data['gallery_image_ids']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update custom meta fields (Level 1 compatibility)
|
||||||
|
if (isset($data['meta']) && is_array($data['meta'])) {
|
||||||
|
self::update_product_meta_data($product, $data['meta']);
|
||||||
|
}
|
||||||
|
|
||||||
$product->save();
|
$product->save();
|
||||||
|
|
||||||
|
// Allow plugins to perform additional updates (Level 1 compatibility)
|
||||||
|
do_action('woonoow/product_updated', $product, $data, $request);
|
||||||
|
|
||||||
// Handle variations for variable products
|
// Handle variations for variable products
|
||||||
if ($product->is_type('variable')) {
|
if ($product->is_type('variable')) {
|
||||||
if (isset($data['attributes'])) {
|
if (isset($data['attributes'])) {
|
||||||
@@ -565,6 +573,12 @@ class ProductsController {
|
|||||||
$data['variations'] = self::get_product_variations($product);
|
$data['variations'] = self::get_product_variations($product);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose meta data (Level 1 compatibility)
|
||||||
|
$data['meta'] = self::get_product_meta_data($product);
|
||||||
|
|
||||||
|
// Allow plugins to modify response (Level 1 compatibility)
|
||||||
|
$data = apply_filters('woonoow/product_api_data', $data, $product);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,4 +711,89 @@ class ProductsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get product meta data for API exposure (Level 1 compatibility)
|
||||||
|
* Filters out internal meta unless explicitly allowed
|
||||||
|
*
|
||||||
|
* @param \WC_Product $product
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function get_product_meta_data($product) {
|
||||||
|
$meta_data = [];
|
||||||
|
|
||||||
|
foreach ($product->get_meta_data() as $meta) {
|
||||||
|
$key = $meta->key;
|
||||||
|
$value = $meta->value;
|
||||||
|
|
||||||
|
// Skip internal WooCommerce meta (starts with _wc_)
|
||||||
|
if (strpos($key, '_wc_') === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip WooNooW internal meta
|
||||||
|
if (strpos($key, '_woonoow_') === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public meta (no underscore) - always expose
|
||||||
|
if (strpos($key, '_') !== 0) {
|
||||||
|
$meta_data[$key] = $value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private meta (starts with _) - check if allowed
|
||||||
|
$allowed_private = apply_filters('woonoow/product_allowed_private_meta', [
|
||||||
|
// Common custom fields
|
||||||
|
'_custom_field',
|
||||||
|
|
||||||
|
// Allow plugins to add their meta via filter
|
||||||
|
], $product);
|
||||||
|
|
||||||
|
if (in_array($key, $allowed_private, true)) {
|
||||||
|
$meta_data[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $meta_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update product meta data from API (Level 1 compatibility)
|
||||||
|
*
|
||||||
|
* @param \WC_Product $product
|
||||||
|
* @param array $meta_updates
|
||||||
|
*/
|
||||||
|
private static function update_product_meta_data($product, $meta_updates) {
|
||||||
|
// Get allowed updatable meta keys
|
||||||
|
$allowed = apply_filters('woonoow/product_updatable_meta', [
|
||||||
|
// Common custom fields
|
||||||
|
'_custom_field',
|
||||||
|
|
||||||
|
// Allow plugins to add their meta via filter
|
||||||
|
], $product);
|
||||||
|
|
||||||
|
foreach ($meta_updates as $key => $value) {
|
||||||
|
// Skip internal WooCommerce meta
|
||||||
|
if (strpos($key, '_wc_') === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip WooNooW internal meta
|
||||||
|
if (strpos($key, '_woonoow_') === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public meta (no underscore) - always allow
|
||||||
|
if (strpos($key, '_') !== 0) {
|
||||||
|
$product->update_meta_data($key, $value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private meta - check if allowed
|
||||||
|
if (in_array($key, $allowed, true)) {
|
||||||
|
$product->update_meta_data($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user