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
2020-02-04 23:50:23 +00:00
use Automattic\Jetpack\Constants ;
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
2020-08-05 16:36:24 +00:00
* @ 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 () {
$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' ),
2020-02-05 14:59:02 +00:00
'options' => $this -> load_shipping_method_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.
2021-03-17 16:20:46 +00:00
if ( $order && 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
}
}
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
$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-05-25 11:54:58 +00:00
if ( ! count ( $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
2020-01-28 22:33:53 +00:00
/**
* Checks to see whether or not the admin settings are being accessed by the current request .
*
* @ return bool
*/
private function is_accessing_settings () {
2020-02-06 20:29:01 +00:00
if ( is_admin () ) {
// phpcs:disable WordPress.Security.NonceVerification
if ( ! isset ( $_REQUEST [ 'page' ] ) || 'wc-settings' !== $_REQUEST [ 'page' ] ) {
return false ;
}
if ( ! isset ( $_REQUEST [ 'tab' ] ) || 'checkout' !== $_REQUEST [ 'tab' ] ) {
return false ;
2020-02-06 18:03:26 +00:00
}
2020-02-06 20:29:01 +00:00
if ( ! isset ( $_REQUEST [ 'section' ] ) || 'cod' !== $_REQUEST [ 'section' ] ) {
return false ;
}
// phpcs:enable WordPress.Security.NonceVerification
return true ;
2020-01-28 22:33:53 +00:00
}
2020-02-04 23:50:23 +00:00
if ( Constants :: is_true ( 'REST_REQUEST' ) ) {
2020-01-28 22:33:53 +00:00
global $wp ;
2020-02-04 23:50:23 +00:00
if ( isset ( $wp -> query_vars [ 'rest_route' ] ) && false !== strpos ( $wp -> query_vars [ 'rest_route' ], '/payment_gateways' ) ) {
return true ;
2020-01-28 22:33:53 +00:00
}
}
2020-02-04 23:50:23 +00:00
return false ;
2020-01-28 22:33:53 +00:00
}
2020-02-05 14:59:02 +00:00
/**
* Loads all of the shipping method options for the enable_for_methods field .
*
* @ return array
*/
private function load_shipping_method_options () {
// Since this is expensive, we only want to do it if we're actually on the settings page.
if ( ! $this -> is_accessing_settings () ) {
return 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 );
$options = array ();
foreach ( WC () -> shipping () -> load_shipping_methods () as $method ) {
$options [ $method -> get_method_title () ] = array ();
// Translators: %1$s shipping method name.
$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 ();
// Translators: %1$s shipping method title, %2$s shipping method id.
$option_instance_title = sprintf ( __ ( '%1$s (#%2$s)' , 'woocommerce' ), $shipping_method_instance -> get_title (), $shipping_method_instance_id );
// Translators: %1$s zone name, %2$s shipping method instance name.
$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 ;
}
}
}
return $options ;
}
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
*
2018-05-25 11:54:58 +00:00
* @ param array $order_shipping_items Array of WC_Order_Item_Shipping objects .
* @ return array $canonical_rate_ids Rate IDs in a canonical format .
2018-01-25 14:40:31 +00:00
*/
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
*
2018-05-25 11:54:58 +00:00
* @ param array $chosen_package_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 .
2018-01-25 14:40:31 +00:00
*/
private function get_canonical_package_rate_ids ( $chosen_package_rate_ids ) {
2018-10-02 15:03:17 +00:00
$shipping_packages = WC () -> shipping () -> get_packages ();
2018-01-25 14:40:31 +00:00
$canonical_rate_ids = array ();
2018-05-25 11:54:58 +00:00
if ( ! empty ( $chosen_package_rate_ids ) && is_array ( $chosen_package_rate_ids ) ) {
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 ();
}
2018-01-25 14:40:31 +00:00
}
}
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
*
2018-05-25 11:54:58 +00:00
* @ param array $rate_ids Rate ids to check .
2018-01-25 14:40:31 +00:00
* @ 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
// 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 .
*
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
}