Commit 7a9f016a80b for woocommerce
commit 7a9f016a80be3a52a0a84fae5ac52db7ff3089a5
Author: Taha Paksu <3295+tpaksu@users.noreply.github.com>
Date: Thu Mar 19 02:37:23 2026 +0300
[WOOPLUG-6363] add: typed PHP API methods for tracking number and carrier management (#63573)
* [WOOPLUG-6363] add: typed PHP API methods for tracking number and carrier management
* Add typed helper methods for tracking number, shipping provider, and tracking URL to Fulfillment model and update docs
* Add string safety checks to new getters
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Fix conflicts after merge
* Address PR review comments: add @since tags, fix docblocks, use typed accessors
- Add @since 10.7.0 to all 6 new public methods in Fulfillment.php
- Fix missing * on blank docblock lines for get_shipping_provider and get_tracking_url
- Replace raw get_meta('_tracking_*') calls with typed accessors in
FulfillmentOrderNotes, FulfillmentUtils, and FulfillmentsRenderer
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
diff --git a/plugins/woocommerce/client/admin/docs/features/fulfillments-hooks.md b/plugins/woocommerce/client/admin/docs/features/fulfillments-hooks.md
index e631dbc512b..ddf17abd4a0 100644
--- a/plugins/woocommerce/client/admin/docs/features/fulfillments-hooks.md
+++ b/plugins/woocommerce/client/admin/docs/features/fulfillments-hooks.md
@@ -119,7 +119,7 @@ add_action( 'woocommerce_fulfillment_created_notification', 'send_sms_notificati
function send_sms_notification( $order_id, $fulfillment, $order ) {
$phone = $order->get_billing_phone();
- $tracking = $fulfillment->get_meta( '_tracking_number', true );
+ $tracking = $fulfillment->get_tracking_number();
if ( $phone && $tracking ) {
// Send SMS notification
@@ -278,7 +278,7 @@ Called after the fulfillment items table in emails.
add_action( 'woocommerce_email_after_fulfillment_table', 'add_tracking_info', 10, 5 );
function add_tracking_info( $order, $fulfillment, $sent_to_admin, $plain_text, $email ) {
- $tracking = $fulfillment->get_meta( '_tracking_number', true );
+ $tracking = $fulfillment->get_tracking_number();
if ( $tracking ) {
echo '<p>Track your package: ' . esc_html( $tracking ) . '</p>';
}
diff --git a/plugins/woocommerce/client/admin/docs/features/fulfillments-rest-api.md b/plugins/woocommerce/client/admin/docs/features/fulfillments-rest-api.md
index b98291dd3a4..29a6d1be903 100644
--- a/plugins/woocommerce/client/admin/docs/features/fulfillments-rest-api.md
+++ b/plugins/woocommerce/client/admin/docs/features/fulfillments-rest-api.md
@@ -652,6 +652,8 @@ Metadata objects have the following structure:
- `_is_locked` - Whether the fulfillment is locked for merchant modification
- `_lock_message` - What to show as the lock message for a locked fulfillment
+**Note:** The tracking number, shipping provider, and tracking URL metadata keys have typed convenience methods on the `Fulfillment` object: `get_tracking_number()` / `set_tracking_number()`, `get_shipping_provider()` / `set_shipping_provider()`, and `get_tracking_url()` / `set_tracking_url()`. These are recommended over direct `get_meta()` / `update_meta_data()` calls for better type safety and IDE autocompletion.
+
### Items Structure
The `_items` metadata must be an array of objects with the following structure:
diff --git a/plugins/woocommerce/src/Admin/Features/Fulfillments/Fulfillment.php b/plugins/woocommerce/src/Admin/Features/Fulfillments/Fulfillment.php
index 3792632eae9..1960986852a 100644
--- a/plugins/woocommerce/src/Admin/Features/Fulfillments/Fulfillment.php
+++ b/plugins/woocommerce/src/Admin/Features/Fulfillments/Fulfillment.php
@@ -264,6 +264,84 @@ class Fulfillment extends \WC_Data {
$this->update_meta_data( '_items', array_values( $items ) );
}
+ /**
+ * Get the tracking number.
+ *
+ * @since 10.7.0
+ * @return string|null Tracking number.
+ */
+ public function get_tracking_number(): ?string {
+ $value = $this->get_meta( '_tracking_number', true );
+ if ( ! is_scalar( $value ) ) {
+ return null;
+ }
+
+ $value = (string) $value;
+ return '' !== $value ? $value : null;
+ }
+
+ /**
+ * Set the tracking number.
+ *
+ * @since 10.7.0
+ * @param string $tracking_number Tracking number.
+ */
+ public function set_tracking_number( string $tracking_number ): void {
+ $this->update_meta_data( '_tracking_number', $tracking_number );
+ }
+
+ /**
+ * Get the shipping provider.
+ *
+ * @since 10.7.0
+ * @return string|null Shipping provider slug.
+ */
+ public function get_shipping_provider(): ?string {
+ $value = $this->get_meta( '_shipping_provider', true );
+ if ( ! is_scalar( $value ) ) {
+ return null;
+ }
+
+ $value = (string) $value;
+ return '' !== $value ? $value : null;
+ }
+
+ /**
+ * Set the shipping provider.
+ *
+ * @since 10.7.0
+ * @param string $shipping_provider Shipping provider slug.
+ */
+ public function set_shipping_provider( string $shipping_provider ): void {
+ $this->update_meta_data( '_shipping_provider', $shipping_provider );
+ }
+
+ /**
+ * Get the tracking URL.
+ *
+ * @since 10.7.0
+ * @return string|null Tracking URL.
+ */
+ public function get_tracking_url(): ?string {
+ $value = $this->get_meta( '_tracking_url', true );
+ if ( ! is_scalar( $value ) ) {
+ return null;
+ }
+
+ $value = (string) $value;
+ return '' !== $value ? $value : null;
+ }
+
+ /**
+ * Set the tracking URL.
+ *
+ * @since 10.7.0
+ * @param string $tracking_url Tracking URL.
+ */
+ public function set_tracking_url( string $tracking_url ): void {
+ $this->update_meta_data( '_tracking_url', $tracking_url );
+ }
+
/**
* Get the order associated with this fulfillment.
*
diff --git a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentOrderNotes.php b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentOrderNotes.php
index 2ea9aaf1ee9..57aeb0b7c45 100644
--- a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentOrderNotes.php
+++ b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentOrderNotes.php
@@ -323,17 +323,17 @@ class FulfillmentOrderNotes {
* @return string The formatted tracking information, or empty string if no tracking number is present.
*/
private function format_tracking( Fulfillment $fulfillment ): string {
- $tracking_number = $fulfillment->get_meta( '_tracking_number', true );
- $shipping_provider = $fulfillment->get_meta( '_shipping_provider', true );
- $tracking_url = $fulfillment->get_meta( '_tracking_url', true );
+ $tracking_number = $fulfillment->get_tracking_number();
+ $shipping_provider = $fulfillment->get_shipping_provider();
+ $tracking_url = $fulfillment->get_tracking_url();
- if ( ! is_string( $tracking_number ) || '' === $tracking_number ) {
+ if ( null === $tracking_number ) {
return '';
}
$parts = array( $tracking_number );
- if ( is_string( $shipping_provider ) && '' !== $shipping_provider ) {
+ if ( null !== $shipping_provider ) {
$parts[] = sprintf(
/* translators: %s: shipping provider name */
__( 'Provider: %s', 'woocommerce' ),
@@ -341,7 +341,7 @@ class FulfillmentOrderNotes {
);
}
- if ( is_string( $tracking_url ) && '' !== $tracking_url ) {
+ if ( null !== $tracking_url ) {
$parts[] = sprintf(
/* translators: %s: tracking URL */
__( 'URL: %s', 'woocommerce' ),
diff --git a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentUtils.php b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentUtils.php
index a638da56317..ecc4580544a 100644
--- a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentUtils.php
+++ b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentUtils.php
@@ -209,9 +209,9 @@ class FulfillmentUtils {
*/
public static function get_tracking_info_html( Fulfillment $fulfillment ): string {
$tracking_html = '';
- $tracking_url = $fulfillment->get_meta( '_tracking_url', true );
- $tracking_number = $fulfillment->get_meta( '_tracking_number', true );
- if ( ! empty( $tracking_url ) && ! empty( $tracking_number ) ) {
+ $tracking_url = $fulfillment->get_tracking_url();
+ $tracking_number = $fulfillment->get_tracking_number();
+ if ( null !== $tracking_url && null !== $tracking_number ) {
$tracking_html .= '<a href="' . esc_url( $tracking_url ) . '" target="_blank" rel="noopener noreferrer">';
$tracking_html .= esc_html( $tracking_number );
$tracking_html .= '</a>';
diff --git a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsRenderer.php b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsRenderer.php
index ea3933ca9ce..29cdb79cc08 100644
--- a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsRenderer.php
+++ b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsRenderer.php
@@ -203,7 +203,7 @@ class FulfillmentsRenderer {
private function render_shipment_tracking_column_row_data( WC_Order $order, array $fulfillments ) {
$tracking = array();
foreach ( $fulfillments as $fulfillment ) {
- $tracking[] = $fulfillment->get_meta( '_tracking_number' ) ?? null;
+ $tracking[] = $fulfillment->get_tracking_number();
}
$tracking = array_filter(