2012-05-26 16:25:07 +00:00
< ? php
2018-03-09 18:44:48 +00:00
/**
* Class WC_Gateway_COD file .
*
* @ package WooCommerce\Gateways
*/
2013-02-20 17:14:46 +00:00
2014-09-20 19:42:58 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
2018-03-09 18:44:48 +00:00
exit ; // Exit if accessed directly.
2014-09-20 19:42:58 +00:00
}
2013-02-20 17:14:46 +00:00
2012-05-26 16:25:07 +00:00
/**
2015-11-03 13:31:20 +00:00
* Cash on Delivery Gateway .
2012-08-15 18:15:06 +00:00
*
2012-05-26 16:25:07 +00:00
* Provides a Cash on Delivery Payment Gateway .
*
2018-03-09 12:53:10 +00:00
* @ class WC_Gateway_COD
* @ extends WC_Payment_Gateway
* @ version 2.1 . 0
* @ package WooCommerce / Classes / Payment
2012-05-26 16:25:07 +00:00
*/
2012-12-31 18:25:09 +00:00
class WC_Gateway_COD extends WC_Payment_Gateway {
2012-08-15 18:15:06 +00:00
2016-07-11 14:56:35 +00:00
/**
* Constructor for the gateway .
*/
2013-08-05 15:34:48 +00:00
public function __construct () {
2018-03-09 18:44:48 +00:00
// Setup general properties.
2016-10-13 15:47:56 +00:00
$this -> setup_properties ();
2012-08-15 18:15:06 +00:00
2018-03-09 18:44:48 +00:00
// Load the settings.
2013-01-02 13:38:33 +00:00
$this -> init_form_fields ();
2012-05-26 16:25:07 +00:00
$this -> init_settings ();
2012-08-15 18:15:06 +00:00
2018-03-09 18:44:48 +00:00
// Get settings.
2012-12-31 12:07:43 +00:00
$this -> title = $this -> get_option ( 'title' );
$this -> description = $this -> get_option ( 'description' );
2017-01-17 18:11:49 +00:00
$this -> instructions = $this -> get_option ( 'instructions' );
2012-12-31 12:07:43 +00:00
$this -> enable_for_methods = $this -> get_option ( 'enable_for_methods' , array () );
2018-03-21 22:57:10 +00:00
$this -> enable_for_virtual = $this -> get_option ( 'enable_for_virtual' , 'yes' ) === 'yes' ;
2012-08-15 18:15:06 +00:00
2012-12-31 18:25:09 +00:00
add_action ( 'woocommerce_update_options_payment_gateways_' . $this -> id , array ( $this , 'process_admin_options' ) );
2016-10-13 15:43:07 +00:00
add_action ( 'woocommerce_thankyou_' . $this -> id , array ( $this , 'thankyou_page' ) );
2017-05-24 17:48:34 +00:00
add_filter ( 'woocommerce_payment_complete_order_status' , array ( $this , 'change_payment_complete_order_status' ), 10 , 3 );
2014-04-28 04:17:40 +00:00
2018-03-09 18:44:48 +00:00
// Customer Emails.
2016-07-11 14:56:35 +00:00
add_action ( 'woocommerce_email_before_order_table' , array ( $this , 'email_instructions' ), 10 , 3 );
2012-05-26 16:25:07 +00:00
}
2016-10-13 19:51:18 +00:00
2016-10-13 15:47:56 +00:00
/**
* Setup general properties for the gateway .
*/
protected function setup_properties () {
$this -> id = 'cod' ;
$this -> icon = apply_filters ( 'woocommerce_cod_icon' , '' );
$this -> method_title = __ ( 'Cash on delivery' , 'woocommerce' );
$this -> method_description = __ ( 'Have your customers pay with cash (or by other means) upon delivery.' , 'woocommerce' );
$this -> has_fields = false ;
}
2012-08-15 18:15:06 +00:00
2016-07-11 14:56:35 +00:00
/**
* Initialise Gateway Settings Form Fields .
*/
public function init_form_fields () {
2018-01-25 14:37:10 +00:00
$options = array ();
$data_store = WC_Data_Store :: load ( 'shipping-zone' );
$raw_zones = $data_store -> get_zones ();
foreach ( $raw_zones as $raw_zone ) {
$zones [] = new WC_Shipping_Zone ( $raw_zone );
}
$zones [] = new WC_Shipping_Zone ( 0 );
2012-11-27 16:22:47 +00:00
2016-09-07 11:37:39 +00:00
foreach ( WC () -> shipping () -> load_shipping_methods () as $method ) {
2018-01-25 14:37:10 +00:00
$options [ $method -> get_method_title () ] = array ();
$options [ $method -> get_method_title () ][ $method -> id ] = sprintf ( __ ( 'Any "%1$s" method' , 'woocommerce' ), $method -> get_method_title () );
foreach ( $zones as $zone ) {
$shipping_method_instances = $zone -> get_shipping_methods ();
foreach ( $shipping_method_instances as $shipping_method_instance_id => $shipping_method_instance ) {
if ( $shipping_method_instance -> id !== $method -> id ) {
continue ;
}
$option_id = $shipping_method_instance -> get_rate_id ();
$option_instance_title = sprintf ( __ ( '%1$s (#%2$s)' , 'woocommerce' ), $shipping_method_instance -> get_title (), $shipping_method_instance_id );
$option_title = sprintf ( __ ( '%1$s – %2$s' , 'woocommerce' ), $zone -> get_id () ? $zone -> get_zone_name () : __ ( 'Other locations' , 'woocommerce' ), $option_instance_title );
$options [ $method -> get_method_title () ][ $option_id ] = $option_title ;
}
}
2016-07-20 09:49:27 +00:00
}
2012-11-27 16:22:47 +00:00
2016-07-11 14:56:35 +00:00
$this -> form_fields = array (
2018-03-09 12:53:10 +00:00
'enabled' => array (
2016-10-11 01:39:13 +00:00
'title' => __ ( 'Enable/Disable' , 'woocommerce' ),
2016-10-12 10:16:30 +00:00
'label' => __ ( 'Enable cash on delivery' , 'woocommerce' ),
2013-08-05 15:34:48 +00:00
'type' => 'checkbox' ,
2012-08-15 18:15:06 +00:00
'description' => '' ,
2016-08-27 01:46:45 +00:00
'default' => 'no' ,
2012-08-15 18:15:06 +00:00
),
2018-03-09 12:53:10 +00:00
'title' => array (
2013-08-05 15:34:48 +00:00
'title' => __ ( 'Title' , 'woocommerce' ),
'type' => 'text' ,
'description' => __ ( 'Payment method description that the customer will see on your checkout.' , 'woocommerce' ),
2016-10-12 10:16:30 +00:00
'default' => __ ( 'Cash on delivery' , 'woocommerce' ),
2013-08-05 15:34:48 +00:00
'desc_tip' => true ,
2012-08-15 18:15:06 +00:00
),
2018-03-09 12:53:10 +00:00
'description' => array (
2013-08-05 15:34:48 +00:00
'title' => __ ( 'Description' , 'woocommerce' ),
'type' => 'textarea' ,
2012-08-15 18:15:06 +00:00
'description' => __ ( 'Payment method description that the customer will see on your website.' , 'woocommerce' ),
2013-08-05 15:34:48 +00:00
'default' => __ ( 'Pay with cash upon delivery.' , 'woocommerce' ),
'desc_tip' => true ,
2012-08-15 18:15:06 +00:00
),
2018-03-09 12:53:10 +00:00
'instructions' => array (
2013-08-05 15:34:48 +00:00
'title' => __ ( 'Instructions' , 'woocommerce' ),
'type' => 'textarea' ,
2012-08-15 18:15:06 +00:00
'description' => __ ( 'Instructions that will be added to the thank you page.' , 'woocommerce' ),
2013-08-05 15:34:48 +00:00
'default' => __ ( 'Pay with cash upon delivery.' , 'woocommerce' ),
'desc_tip' => true ,
2012-08-15 18:15:06 +00:00
),
2012-09-07 09:49:31 +00:00
'enable_for_methods' => array (
2013-10-11 14:27:04 +00:00
'title' => __ ( 'Enable for shipping methods' , 'woocommerce' ),
'type' => 'multiselect' ,
2015-01-12 16:29:01 +00:00
'class' => 'wc-enhanced-select' ,
2016-12-21 11:36:48 +00:00
'css' => 'width: 400px;' ,
2013-10-11 14:27:04 +00:00
'default' => '' ,
'description' => __ ( 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.' , 'woocommerce' ),
2018-01-25 14:37:10 +00:00
'options' => $options ,
2013-10-11 14:27:04 +00:00
'desc_tip' => true ,
'custom_attributes' => array (
2016-08-27 01:46:45 +00:00
'data-placeholder' => __ ( 'Select shipping methods' , 'woocommerce' ),
),
2014-05-08 14:05:34 +00:00
),
'enable_for_virtual' => array (
2018-03-09 12:53:10 +00:00
'title' => __ ( 'Accept for virtual orders' , 'woocommerce' ),
'label' => __ ( 'Accept COD if the order is virtual' , 'woocommerce' ),
'type' => 'checkbox' ,
'default' => 'yes' ,
2016-08-27 01:46:45 +00:00
),
2018-03-09 12:53:10 +00:00
);
2016-07-11 14:56:35 +00:00
}
2012-08-15 18:15:06 +00:00
2012-09-07 09:49:31 +00:00
/**
2015-11-03 13:31:20 +00:00
* Check If The Gateway Is Available For Use .
2012-09-07 09:49:31 +00:00
*
* @ return bool
*/
2013-08-05 15:34:48 +00:00
public function is_available () {
2015-08-13 22:54:16 +00:00
$order = null ;
$needs_shipping = false ;
2018-03-09 18:44:48 +00:00
// Test if shipping is needed first.
2015-08-13 22:54:16 +00:00
if ( WC () -> cart && WC () -> cart -> needs_shipping () ) {
$needs_shipping = true ;
} elseif ( is_page ( wc_get_page_id ( 'checkout' ) ) && 0 < get_query_var ( 'order-pay' ) ) {
$order_id = absint ( get_query_var ( 'order-pay' ) );
$order = wc_get_order ( $order_id );
// Test if order needs shipping.
2018-03-09 18:44:48 +00:00
if ( 0 < count ( $order -> get_items () ) ) {
2015-08-13 22:54:16 +00:00
foreach ( $order -> get_items () as $item ) {
2016-08-22 15:51:24 +00:00
$_product = $item -> get_product ();
2015-10-15 07:43:53 +00:00
if ( $_product && $_product -> needs_shipping () ) {
2015-08-13 22:54:16 +00:00
$needs_shipping = true ;
break ;
2014-04-24 18:33:14 +00:00
}
}
2015-08-13 22:54:16 +00:00
}
2018-01-25 14:42:54 +00:00
} elseif ( WC () -> cart && WC () -> cart -> needs_shipping () ) {
$needs_shipping = true ;
2015-08-13 22:54:16 +00:00
}
2014-04-24 18:33:14 +00:00
2015-08-13 22:54:16 +00:00
$needs_shipping = apply_filters ( 'woocommerce_cart_needs_shipping' , $needs_shipping );
2014-04-24 18:33:14 +00:00
2018-03-09 18:44:48 +00:00
// Virtual order, with virtual disabled.
2015-08-13 22:54:16 +00:00
if ( ! $this -> enable_for_virtual && ! $needs_shipping ) {
return false ;
2014-04-24 18:33:14 +00:00
}
2017-07-13 15:21:59 +00:00
// Only apply if all packages are being shipped via chosen method, or order is virtual.
2015-08-13 22:54:16 +00:00
if ( ! empty ( $this -> enable_for_methods ) && $needs_shipping ) {
2018-04-03 15:24:19 +00:00
$canonical_rate_ids = array ();
$order_shipping_items = is_object ( $order ) ? $order -> get_shipping_methods () : false ;
2018-03-09 18:44:48 +00:00
$chosen_shipping_methods_session = WC () -> session -> get ( 'chosen_shipping_methods' );
2013-08-14 20:00:34 +00:00
2018-04-03 15:24:19 +00:00
if ( $order_shipping_items ) {
2018-01-25 14:40:31 +00:00
$canonical_rate_ids = $this -> get_canonical_order_shipping_item_rate_ids ( $order_shipping_items );
2018-04-03 15:24:19 +00:00
} else {
$canonical_rate_ids = $this -> get_canonical_package_rate_ids ( $chosen_shipping_methods_session );
2012-09-07 09:49:31 +00:00
}
2012-11-27 16:22:47 +00:00
2018-01-25 14:40:31 +00:00
if ( ! sizeof ( $this -> get_matching_rates ( $canonical_rate_ids ) ) ) {
2012-09-07 09:49:31 +00:00
return false ;
2014-04-24 15:37:31 +00:00
}
2012-09-07 09:49:31 +00:00
}
2012-11-27 16:22:47 +00:00
2012-09-07 09:49:31 +00:00
return parent :: is_available ();
}
2012-11-27 16:22:47 +00:00
2018-01-25 14:40:31 +00:00
/**
* Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format .
*
* @ since 3.4 . 0
*
* @ param array $order_shipping_items Array of WC_Order_Item_Shipping objects .
* @ return array $canonical_rate_ids Rate IDs in a canonical format .
*/
private function get_canonical_order_shipping_item_rate_ids ( $order_shipping_items ) {
$canonical_rate_ids = array ();
foreach ( $order_shipping_items as $order_shipping_item ) {
$canonical_rate_ids [] = $order_shipping_item -> get_method_id () . ':' . $order_shipping_item -> get_instance_id ();
}
return $canonical_rate_ids ;
}
/**
* Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format .
*
* @ since 3.4 . 0
*
* @ param array $rate_ids Rate IDs as generated by shipping methods . Can be anything if a shipping method doesn ' t honor WC conventions .
* @ return array $canonical_rate_ids Rate IDs in a canonical format .
*/
private function get_canonical_package_rate_ids ( $chosen_package_rate_ids ) {
$shipping_packages = WC () -> shipping -> get_packages ();
$canonical_rate_ids = array ();
foreach ( $chosen_package_rate_ids as $package_key => $chosen_package_rate_id ) {
if ( ! empty ( $shipping_packages [ $package_key ][ 'rates' ][ $chosen_package_rate_id ] ) ) {
$chosen_rate = $shipping_packages [ $package_key ][ 'rates' ][ $chosen_package_rate_id ];
$canonical_rate_ids [] = $chosen_rate -> get_method_id () . ':' . $chosen_rate -> get_instance_id ();
}
}
return $canonical_rate_ids ;
}
/**
* Indicates whether a rate exists in an array of canonically - formatted rate IDs that activates this gateway .
*
* @ since 3.4 . 0
*
* @ param array $rate_ids
* @ return boolean
*/
private function get_matching_rates ( $rate_ids ) {
// First, match entries in 'method_id:instance_id' format. Then, match entries in 'method_id' format by stripping off the instance ID from the candidates.
return array_unique ( array_merge ( array_intersect ( $this -> enable_for_methods , $rate_ids ), array_intersect ( $this -> enable_for_methods , array_unique ( array_map ( 'wc_get_string_before_colon' , $rate_ids ) ) ) ) );
}
2014-04-24 18:03:33 +00:00
2016-07-11 14:56:35 +00:00
/**
* Process the payment and return the result .
*
2018-03-09 18:44:48 +00:00
* @ param int $order_id Order ID .
2016-07-11 14:56:35 +00:00
* @ return array
*/
2013-08-05 15:34:48 +00:00
public function process_payment ( $order_id ) {
2014-08-15 12:29:21 +00:00
$order = wc_get_order ( $order_id );
2012-05-26 16:25:07 +00:00
2017-11-30 03:31:10 +00:00
if ( $order -> get_total () > 0 ) {
2018-03-09 18:44:48 +00:00
// Mark as processing or on-hold (payment won't be taken until delivery).
2017-11-30 03:31:10 +00:00
$order -> update_status ( apply_filters ( 'woocommerce_cod_process_payment_order_status' , $order -> has_downloadable_item () ? 'on-hold' : 'processing' , $order ), __ ( 'Payment to be made upon delivery.' , 'woocommerce' ) );
} else {
$order -> payment_complete ();
}
2012-08-15 18:15:06 +00:00
2018-03-09 18:44:48 +00:00
// Reduce stock levels.
2016-08-09 13:15:04 +00:00
wc_reduce_stock_levels ( $order_id );
2012-08-15 18:15:06 +00:00
2018-03-09 18:44:48 +00:00
// Remove cart.
2013-08-05 15:34:48 +00:00
WC () -> cart -> empty_cart ();
2012-08-15 18:15:06 +00:00
2018-03-09 18:44:48 +00:00
// Return thankyou redirect.
2012-05-26 16:25:07 +00:00
return array (
2018-03-09 12:53:10 +00:00
'result' => 'success' ,
'redirect' => $this -> get_return_url ( $order ),
2012-05-26 16:25:07 +00:00
);
}
2012-08-15 18:15:06 +00:00
2016-07-11 14:56:35 +00:00
/**
* Output for the order received page .
*/
2013-08-05 15:34:48 +00:00
public function thankyou_page () {
2014-05-07 14:54:22 +00:00
if ( $this -> instructions ) {
2018-03-09 18:44:48 +00:00
echo wp_kses_post ( wpautop ( wptexturize ( $this -> instructions ) ) );
2014-05-07 14:54:22 +00:00
}
2012-05-26 16:25:07 +00:00
}
2014-04-28 04:17:40 +00:00
2017-05-24 17:48:34 +00:00
/**
* Change payment complete order status to completed for COD orders .
*
* @ since 3.1 . 0
2018-03-09 18:44:48 +00:00
* @ param string $status Current order status .
* @ param int $order_id Order ID .
* @ param WC_Order | false $order Order object .
2017-05-24 17:48:34 +00:00
* @ return string
*/
2017-06-15 14:43:32 +00:00
public function change_payment_complete_order_status ( $status , $order_id = 0 , $order = false ) {
2017-05-24 17:48:34 +00:00
if ( $order && 'cod' === $order -> get_payment_method () ) {
$status = 'completed' ;
}
return $status ;
}
2016-07-11 14:56:35 +00:00
/**
* Add content to the WC emails .
*
* @ access public
2018-03-09 18:44:48 +00:00
* @ param WC_Order $order Order object .
* @ param bool $sent_to_admin Sent to admin .
* @ param bool $plain_text Email format : plain text or HTML .
2016-07-11 14:56:35 +00:00
*/
2014-04-28 04:17:40 +00:00
public function email_instructions ( $order , $sent_to_admin , $plain_text = false ) {
2016-10-13 15:43:07 +00:00
if ( $this -> instructions && ! $sent_to_admin && $this -> id === $order -> get_payment_method () ) {
2018-03-09 18:44:48 +00:00
echo wp_kses_post ( wpautop ( wptexturize ( $this -> instructions ) ) . PHP_EOL );
2014-05-07 14:54:22 +00:00
}
2014-04-28 04:17:40 +00:00
}
2014-02-18 11:27:05 +00:00
}