get_meta( self::META_CLICK, true ) ) { return false; } $order->update_meta_data( self::META_CLICK, (string) $context['click_id'] ); $order->update_meta_data( self::META_BOUND, (int) ( isset( $context['captured'] ) ? $context['captured'] : time() ) ); if ( ! empty( $context['landing_url'] ) ) { $order->update_meta_data( self::META_LANDING, substr( (string) $context['landing_url'], 0, 512 ) ); } for ( $i = 1; $i <= 5; $i++ ) { $key = 'sub' . $i; if ( ! empty( $context[ $key ] ) ) { $order->update_meta_data( self::META_SUB . $i, (string) $context[ $key ] ); } } $order->save(); return true; } /** * The click context bound to an order. * * @param WC_Order $order The order. * @return array */ public static function context( $order ) { if ( ! is_a( $order, 'WC_Order' ) ) { return array(); } $click_id = (string) $order->get_meta( self::META_CLICK, true ); if ( '' === $click_id ) { return array(); } $context = array( 'click_id' => $click_id, 'landing_url' => (string) $order->get_meta( self::META_LANDING, true ), 'captured' => (int) $order->get_meta( self::META_BOUND, true ), ); for ( $i = 1; $i <= 5; $i++ ) { $context[ 'sub' . $i ] = (string) $order->get_meta( self::META_SUB . $i, true ); } return $context; } /** * Write a click onto an order by hand. * * The back-office case: a merchant took the order over the telephone and * knows which affiliate sent the customer. Used by the order screen panel. * * @param WC_Order $order The order. * @param string $click_id Validated click id. * @return bool */ public static function set_click( $order, $click_id ) { if ( ! is_a( $order, 'WC_Order' ) ) { return false; } $click_id = Affiliatant_Capture::clean_click_id( $click_id ); if ( '' === $click_id ) { return false; } $order->update_meta_data( self::META_CLICK, $click_id ); $order->update_meta_data( self::META_BOUND, time() ); $order->save(); return true; } /** * A plain-array snapshot of the order. * * Decimal strings, exactly as WooCommerce stores them. The conversion to * integer minor units happens in one place, Affiliatant_Payload, through * the SDK's string arithmetic. * * The order's own currency IS the currency of these amounts. WooCommerce * stores an order in the currency it was placed in, so there is none of * the display-currency trap the CubeCart plugin has to work around. * * @param WC_Order $order The order. * @return array */ public static function snapshot( $order ) { if ( ! is_a( $order, 'WC_Order' ) ) { return array(); } $created = $order->get_date_created(); return array( 'order_id' => (int) $order->get_id(), 'order_number' => (string) $order->get_order_number(), 'status' => (string) $order->get_status(), 'currency' => (string) $order->get_currency(), 'total' => (string) $order->get_total(), 'total_tax' => (string) $order->get_total_tax(), 'shipping_total' => (string) $order->get_shipping_total(), 'shipping_tax' => (string) $order->get_shipping_tax(), 'discount_total' => (string) $order->get_total_discount( true ), 'customer_id' => (int) $order->get_customer_id(), 'payment_method' => (string) $order->get_payment_method(), 'parent_order_id' => (int) $order->get_parent_id(), // gmdate through the object's own timestamp, so the value sent is // UTC whatever the shop's timezone is set to. 'date_created' => $created ? gmdate( 'c', $created->getTimestamp() ) : gmdate( 'c' ), 'coupons' => array_map( 'strval', (array) $order->get_coupon_codes() ), 'items' => self::items( $order ), ); } /** * Line items as plain arrays. * * @param WC_Order $order The order. * @return array */ private static function items( $order ) { $out = array(); foreach ( $order->get_items( 'line_item' ) as $item ) { if ( ! is_a( $item, 'WC_Order_Item_Product' ) ) { continue; } $product = $item->get_product(); $out[] = array( 'name' => (string) $item->get_name(), 'sku' => is_object( $product ) ? (string) $product->get_sku() : '', 'product_id' => (int) $item->get_product_id(), 'variation_id' => (int) $item->get_variation_id(), 'quantity' => (int) $item->get_quantity(), 'subtotal' => (string) $item->get_subtotal(), 'total' => (string) $item->get_total(), 'total_tax' => (string) $item->get_total_tax(), ); } return $out; } /** * Everything refunded against an order so far, as a positive decimal string. * * Cumulative, not this refund alone: a second partial refund has to be * reasoned about against the whole, or two fifty percent refunds each * claw back half of the entire commission. * * @param WC_Order $order The order. * @return string */ public static function refunded_total( $order ) { if ( ! is_a( $order, 'WC_Order' ) ) { return '0'; } return (string) $order->get_total_refunded(); } }