I am using WooCommerce Subscriptions to manage recurring payments on my WordPress site, which sells baby diapers.
I want to add additional detail to my subscriptions, so that my customers can differentiate between their subscriptions in other ways than by subscription id.
I capture leads about the customers baby, including their name, in a form at the beginning of the customers journey.
To add my extra detail field to the subscriptions data, I modified the wcs_create_subscription
function located here:
wp-content/plugins/woocommerce-subscriptions/vendor/woocommerce/subscriptions-core/wcs-functions.php
by first adding a ‘baby_name’ argument to the $default_args
array, that I have set to store the current users id with get_current_user_id()
, just to test the functionality:
$default_args = array(
'status' => '',
'baby_name' => get_current_user_id(),
'order_id' => 0,
'customer_note' => null,
'customer_id' => ( ! empty( $order ) ) ? $order->get_user_id() : null,
'start_date' => $default_start_date,
'date_created' => $now,
'created_via' => ( ! empty( $order ) ) ? wcs_get_objects_property( $order, 'created_via' ) : '',
'order_version' => ( ! empty( $order ) ) ? wcs_get_objects_property( $order, 'version' ) : WC_VERSION,
'currency' => ( ! empty( $order ) ) ? wcs_get_objects_property( $order, 'currency' ) : get_woocommerce_currency(),
'prices_include_tax' => ( ! empty( $order ) ) ? ( ( wcs_get_objects_property( $order, 'prices_include_tax' ) ) ? 'yes' : 'no' ) : get_option( 'woocommerce_prices_include_tax' ), // we don't use wc_prices_include_tax() here because WC doesn't use it in wc_create_order(), not 100% sure why it doesn't also check the taxes are enabled, but there could forseeably be a reason
);
Then I run a update_post_meta()
function to save my argument in the subscriptions database:
update_post_meta( $subscription_id, '_baby_name', $args['baby_name'] );
Here is my full wcs_create_subscription
function:
/**
* Create a new subscription
*
* Returns a new WC_Subscription object on success which can then be used to add additional data.
*
* @return WC_Subscription | WP_Error A WC_Subscription on success or WP_Error object on failure
* @since 2.0
*/
function wcs_create_subscription( $args = array() ) {
$now = gmdate( 'Y-m-d H:i:s' );
$order = ( isset( $args['order_id'] ) ) ? wc_get_order( $args['order_id'] ) : null;
if ( ! empty( $order ) ) {
$default_start_date = wcs_get_datetime_utc_string( wcs_get_objects_property( $order, 'date_created' ) );
} else {
$default_start_date = ( isset( $args['date_created'] ) ) ? $args['date_created'] : $now;
}
$default_args = array(
'status' => '',
'baby_name' => get_current_user_id(),
'order_id' => 0,
'customer_note' => null,
'customer_id' => ( ! empty( $order ) ) ? $order->get_user_id() : null,
'start_date' => $default_start_date,
'date_created' => $now,
'created_via' => ( ! empty( $order ) ) ? wcs_get_objects_property( $order, 'created_via' ) : '',
'order_version' => ( ! empty( $order ) ) ? wcs_get_objects_property( $order, 'version' ) : WC_VERSION,
'currency' => ( ! empty( $order ) ) ? wcs_get_objects_property( $order, 'currency' ) : get_woocommerce_currency(),
'prices_include_tax' => ( ! empty( $order ) ) ? ( ( wcs_get_objects_property( $order, 'prices_include_tax' ) ) ? 'yes' : 'no' ) : get_option( 'woocommerce_prices_include_tax' ), // we don't use wc_prices_include_tax() here because WC doesn't use it in wc_create_order(), not 100% sure why it doesn't also check the taxes are enabled, but there could forseeably be a reason
);
$args = wp_parse_args( $args, $default_args );
$subscription_data = array();
// Validate the date_created arg.
if ( ! is_string( $args['date_created'] ) || false === wcs_is_datetime_mysql_format( $args['date_created'] ) ) {
return new WP_Error( 'woocommerce_subscription_invalid_date_created_format', _x( 'Invalid created date. The date must be a string and of the format: "Y-m-d H:i:s".', 'Error message while creating a subscription', 'woocommerce-subscriptions' ) );
} elseif ( wcs_date_to_time( $args['date_created'] ) > current_time( 'timestamp', true ) ) {
return new WP_Error( 'woocommerce_subscription_invalid_date_created', _x( 'Subscription created date must be before current day.', 'Error message while creating a subscription', 'woocommerce-subscriptions' ) );
}
// Validate the start_date arg.
if ( ! is_string( $args['start_date'] ) || false === wcs_is_datetime_mysql_format( $args['start_date'] ) ) {
return new WP_Error( 'woocommerce_subscription_invalid_start_date_format', _x( 'Invalid date. The date must be a string and of the format: "Y-m-d H:i:s".', 'Error message while creating a subscription', 'woocommerce-subscriptions' ) );
}
// check customer id is set
if ( empty( $args['customer_id'] ) || ! is_numeric( $args['customer_id'] ) || $args['customer_id'] <= 0 ) {
return new WP_Error( 'woocommerce_subscription_invalid_customer_id', _x( 'Invalid subscription customer_id.', 'Error message while creating a subscription', 'woocommerce-subscriptions' ) );
}
// check the billing period
if ( empty( $args['billing_period'] ) || ! in_array( strtolower( $args['billing_period'] ), array_keys( wcs_get_subscription_period_strings() ) ) ) {
return new WP_Error( 'woocommerce_subscription_invalid_billing_period', __( 'Invalid subscription billing period given.', 'woocommerce-subscriptions' ) );
}
// check the billing interval
if ( empty( $args['billing_interval'] ) || ! is_numeric( $args['billing_interval'] ) || absint( $args['billing_interval'] ) <= 0 ) {
return new WP_Error( 'woocommerce_subscription_invalid_billing_interval', __( 'Invalid subscription billing interval given. Must be an integer greater than 0.', 'woocommerce-subscriptions' ) );
}
$subscription_data['post_type'] = 'shop_subscription';
$subscription_data['post_status'] = 'wc-' . apply_filters( 'woocommerce_default_subscription_status', 'pending' );
$subscription_data['ping_status'] = 'closed';
$subscription_data['post_author'] = 1;
$subscription_data['post_password'] = uniqid( 'order_' );
// translators: Order date parsed by strftime
$post_title_date = strftime( _x( '%b %d, %Y @ %I:%M %p', 'Used in subscription post title. "Subscription renewal order - <this>"', 'woocommerce-subscriptions' ) ); // phpcs:ignore WordPress.WP.I18n.UnorderedPlaceholdersText
// translators: placeholder is order date parsed by strftime
$subscription_data['post_title'] = sprintf( _x( 'Subscription – %s', 'The post title for the new subscription', 'woocommerce-subscriptions' ), $post_title_date );
$subscription_data['post_date_gmt'] = $args['date_created'];
$subscription_data['post_date'] = get_date_from_gmt( $args['date_created'] );
if ( $args['order_id'] > 0 ) {
$subscription_data['post_parent'] = absint( $args['order_id'] );
}
if ( ! is_null( $args['customer_note'] ) && ! empty( $args['customer_note'] ) ) {
$subscription_data['post_excerpt'] = $args['customer_note'];
}
// Only set the status if creating a new subscription, use wcs_update_subscription to update the status
if ( $args['status'] ) {
if ( ! in_array( 'wc-' . $args['status'], array_keys( wcs_get_subscription_statuses() ) ) ) {
return new WP_Error( 'woocommerce_invalid_subscription_status', __( 'Invalid subscription status given.', 'woocommerce-subscriptions' ) );
}
$subscription_data['post_status'] = 'wc-' . $args['status'];
}
$subscription_id = wp_insert_post( apply_filters( 'woocommerce_new_subscription_data', $subscription_data, $args ), true );
if ( is_wp_error( $subscription_id ) ) {
return $subscription_id;
}
// Default order meta data.
update_post_meta( $subscription_id, '_order_key', wcs_generate_order_key() );
update_post_meta( $subscription_id, '_order_currency', $args['currency'] );
update_post_meta( $subscription_id, '_prices_include_tax', $args['prices_include_tax'] );
update_post_meta( $subscription_id, '_created_via', sanitize_text_field( $args['created_via'] ) );
// add/update the billing
update_post_meta( $subscription_id, '_billing_period', $args['billing_period'] );
update_post_meta( $subscription_id, '_billing_interval', absint( $args['billing_interval'] ) );
update_post_meta( $subscription_id, '_customer_user', $args['customer_id'] );
update_post_meta( $subscription_id, '_order_version', $args['order_version'] );
update_post_meta( $subscription_id, '_schedule_start', $args['start_date'] );
update_post_meta( $subscription_id, '_baby_name', $args['baby_name'] );
/**
* Filter the newly created subscription object.
*
* @since 2.2.22
* @param WC_Subscription $subscription
*/
$subscription = apply_filters( 'wcs_created_subscription', wcs_get_subscription( $subscription_id ) );
/**
* Triggered after a new subscription is created.
*
* @since 2.2.22
* @param WC_Subscription $subscription
*/
do_action( 'wcs_create_subscription', $subscription );
return $subscription;
}
I can confirm that this works, as I can see a row with _baby_name
in the meta_key field and my user id in the meta_value field for a subscription with id 2898 that I placed recently in my sites _postmeta
database table:
As I know that I should never modify the core plugin files, I am looking to make my modifications in a snippet or similar that I can place in my child themes function.php file. Any advice?
2
Answers
From the code you have posted it can be deduced that use can be made of the
wcs_create_subscription
action hook:There is no need to add this as an argument first. Via
$subscription
you can obtain multiple data, if desiredWith the new HPOS functionality that comes with WooCommerce 7.3, no longer is recommended to use post meta. You should use:
Where the $subscription is the object from subscription. If you haven’t loaded, you can use the function: