context = 'woocommerce';
add_action( 'woocommerce_after_order_notes', array( $this, 'affiliate_select_or_input' ) );
add_action( 'woocommerce_checkout_process', array( $this, 'check_affiliate_field' ) );
// Set selected affiliate.
if ( version_compare( AFFILIATEWP_VERSION, '2.1.8', '>=' ) ) {
// AffiliateWP v2.1.8 introduced woocommerce_checkout_update_order_meta which is used to insert a pending referral.
add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'set_selected_affiliate' ), 0, 2 );
} else {
// AffiliateWP v2.1.7 and lower used woocommerce_checkout_order_processed.
add_action( 'woocommerce_checkout_order_processed', array( $this, 'set_selected_affiliate' ), 0, 2 );
}
if ( is_admin() ) {
return; // The below is frontend only.
}
// WooCommerce checkout block versions.
add_action( 'woocommerce_init', [ $this, 'register_affiliate_select_or_input_for_checkout_block'] );
add_action( 'woocommerce_set_additional_field_value', [ $this, 'save_affiliate_select_or_input_for_checkout_block'], 10, 4 );
}
/**
* Add Affiliate Selector (or Input) to checkout blocks.
*
* @since 1.2.2
*
* @link https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/additional-checkout-fields.md#supported-field-types
*/
public function register_affiliate_select_or_input_for_checkout_block() {
$shared_input_args = [
'id' => $this->woocommerce_checkout_block_field_id,
'label' => esc_html( affwp_cr_checkout_text() ),
'location' => 'order',
'required' => (bool) affwp_cr_require_affiliate(),
'show_in_order_confirmation' => true,
];
if ( 'input' === $this->get_affiliate_selection() ) {
// Text input.
woocommerce_register_additional_checkout_field(
array_merge( $shared_input_args, [ 'type' => 'text' ] )
);
return;
}
// Select dropdown (only other option).
woocommerce_register_additional_checkout_field(
array_merge(
$shared_input_args,
[
'type' => 'select',
'options' => $this->get_woocommerce_checkout_block_affiliates_select_list(),
]
)
);
}
/**
* Save Selected Affiliate (WooCommerce Checkout Blocks).
*
* @param string $key The key.
* @param [type] $value The value.
* @param string $group The group.
* @param \Automattic\WooCommerce\Admin\Overrides\Order $wc_object The checkout object.
*
* @since 1.2.2
*
* @link https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce-blocks/docs/third-party-developers/extensibility/checkout-block/additional-checkout-fields.md#react-to-to-saving-fields
*
* @return void
*/
public function save_affiliate_select_or_input_for_checkout_block(
string $key,
$value,
string $group,
\Automattic\WooCommerce\Admin\Overrides\Order $wc_object
) : void {
if ( $this->woocommerce_checkout_block_field_id !== $key ) {
return;
}
$affiliate = is_numeric( $value )
? absint( $value )
: $value;
if ( is_numeric( $affiliate ) && $affiliate <= 0 ) {
return;
}
// $this->set_affiliate_id() will override with this value when using the select dropdown.
$_POST['woocommerce_affiliate'] = $affiliate;
$this->set_selected_affiliate(
$wc_object->get_order_number(),
// $this->set_affiliate_id() will use this when using input.
$affiliate
);
}
/**
* Get a list of affiliates to select in a format for WooCommerce checkout blocks.
*
* @since 1.2.2
*
* @return array
*/
private function get_woocommerce_checkout_block_affiliates_select_list() : array {
$affiliates = $this->get_affiliates_select_list( $this->get_affiliates() );
return array_filter(
array_map(
function( $affiliate_name, $affiliate_id ) {
return [
'value' => absint( $affiliate_id ),
'label' => (string) $affiliate_name,
];
},
$affiliates,
array_keys( $affiliates )
),
function( $affiliate ) {
// Exclude the "Select Affiliate" default option.
if ( 0 === intval( $affiliate['value'] ?? 0 ) ) {
return false;
}
return true;
}
);
}
/**
* Set selected affiliate
*
* @param int $order_id The Order ID.
* @param mixed $posted Posted (unused).
*
* @since 1.0.1
* @since 1.2.2 Updated so `$posted` has a default so a notice isn't presented in PHP 8.2+.
*
* @return void
*/
public function set_selected_affiliate( $order_id = 0, $posted = null ) {
if ( $this->already_tracking_referral() ) {
return;
}
add_filter( 'affwp_was_referred', '__return_true' );
add_filter( 'affwp_get_referring_affiliate_id', array( $this, 'set_affiliate_id' ), 10, 3 );
}
/**
* Check affiliate select menu.
*
* @since 1.0
*/
public function check_affiliate_field() {
if ( $this->already_tracking_referral() ) {
return;
}
// Check if there's any errors.
if ( $this->get_error( $_POST[ $this->context . '_affiliate'] ) ) {
wc_add_notice( $this->get_error( $_POST[ $this->context . '_affiliate'] ), 'error' );
}
}
/**
* Affiliate Select/Input.
*
* @param object|null|string $checkout Checkout object where previous value might be stored,
* string of type of checkout, or null.
*
* @since 1.0
*/
public function affiliate_select_or_input( $checkout = null ) {
if ( $this->already_tracking_referral() ) {
return;
}
$description = affwp_cr_checkout_text();
$affiliate_list = $this->get_affiliates();
?>
get_affiliate_selection() ) : ?>
'select',
'class' => array( 'form-row-wide' ),
'label' => $description,
'options' => $this->get_affiliates_select_list( $affiliate_list ),
'required' => affwp_cr_require_affiliate(),
),
is_object( $checkout )
? $checkout->get_value( 'woocommerce_affiliate' )
: null
);
}
?>