1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
4
|
|
|
exit; // Exit if accessed directly |
5
|
|
|
} |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Cash on Delivery Gateway. |
9
|
|
|
* |
10
|
|
|
* Provides a Cash on Delivery Payment Gateway. |
11
|
|
|
* |
12
|
|
|
* @class WC_Gateway_COD |
13
|
|
|
* @extends WC_Payment_Gateway |
14
|
|
|
* @version 2.1.0 |
15
|
|
|
* @package WooCommerce/Classes/Payment |
16
|
|
|
* @author WooThemes |
17
|
|
|
*/ |
18
|
|
|
class WC_Gateway_COD extends WC_Payment_Gateway { |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Constructor for the gateway. |
22
|
|
|
*/ |
23
|
|
|
public function __construct() { |
24
|
|
|
$this->id = 'cod'; |
25
|
|
|
$this->icon = apply_filters( 'woocommerce_cod_icon', '' ); |
26
|
|
|
$this->method_title = __( 'Cash on Delivery', 'woocommerce' ); |
27
|
|
|
$this->method_description = __( 'Have your customers pay with cash (or by other means) upon delivery.', 'woocommerce' ); |
28
|
|
|
$this->has_fields = false; |
29
|
|
|
|
30
|
|
|
// Load the settings |
31
|
|
|
$this->init_form_fields(); |
32
|
|
|
$this->init_settings(); |
33
|
|
|
|
34
|
|
|
// Get settings |
35
|
|
|
$this->title = $this->get_option( 'title' ); |
36
|
|
|
$this->description = $this->get_option( 'description' ); |
37
|
|
|
$this->instructions = $this->get_option( 'instructions', $this->description ); |
38
|
|
|
$this->enable_for_methods = $this->get_option( 'enable_for_methods', array() ); |
39
|
|
|
$this->enable_for_virtual = $this->get_option( 'enable_for_virtual', 'yes' ) === 'yes' ? true : false; |
40
|
|
|
|
41
|
|
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); |
42
|
|
|
add_action( 'woocommerce_thankyou_cod', array( $this, 'thankyou_page' ) ); |
43
|
|
|
|
44
|
|
|
// Customer Emails |
45
|
|
|
add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 ); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Initialise Gateway Settings Form Fields. |
50
|
|
|
*/ |
51
|
|
|
public function init_form_fields() { |
52
|
|
|
$shipping_methods = array(); |
53
|
|
|
|
54
|
|
|
foreach ( WC()->shipping()->load_shipping_methods() as $method ) { |
|
|
|
|
55
|
|
|
$shipping_methods[ $method->id ] = $method->get_method_title(); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
$this->form_fields = array( |
59
|
|
|
'enabled' => array( |
60
|
|
|
'title' => __( 'Enable COD', 'woocommerce' ), |
61
|
|
|
'label' => __( 'Enable Cash on Delivery', 'woocommerce' ), |
62
|
|
|
'type' => 'checkbox', |
63
|
|
|
'description' => '', |
64
|
|
|
'default' => 'no', |
65
|
|
|
), |
66
|
|
|
'title' => array( |
67
|
|
|
'title' => __( 'Title', 'woocommerce' ), |
68
|
|
|
'type' => 'text', |
69
|
|
|
'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ), |
70
|
|
|
'default' => __( 'Cash on Delivery', 'woocommerce' ), |
71
|
|
|
'desc_tip' => true, |
72
|
|
|
), |
73
|
|
|
'description' => array( |
74
|
|
|
'title' => __( 'Description', 'woocommerce' ), |
75
|
|
|
'type' => 'textarea', |
76
|
|
|
'description' => __( 'Payment method description that the customer will see on your website.', 'woocommerce' ), |
77
|
|
|
'default' => __( 'Pay with cash upon delivery.', 'woocommerce' ), |
78
|
|
|
'desc_tip' => true, |
79
|
|
|
), |
80
|
|
|
'instructions' => array( |
81
|
|
|
'title' => __( 'Instructions', 'woocommerce' ), |
82
|
|
|
'type' => 'textarea', |
83
|
|
|
'description' => __( 'Instructions that will be added to the thank you page.', 'woocommerce' ), |
84
|
|
|
'default' => __( 'Pay with cash upon delivery.', 'woocommerce' ), |
85
|
|
|
'desc_tip' => true, |
86
|
|
|
), |
87
|
|
|
'enable_for_methods' => array( |
88
|
|
|
'title' => __( 'Enable for shipping methods', 'woocommerce' ), |
89
|
|
|
'type' => 'multiselect', |
90
|
|
|
'class' => 'wc-enhanced-select', |
91
|
|
|
'css' => 'width: 450px;', |
92
|
|
|
'default' => '', |
93
|
|
|
'description' => __( 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woocommerce' ), |
94
|
|
|
'options' => $shipping_methods, |
95
|
|
|
'desc_tip' => true, |
96
|
|
|
'custom_attributes' => array( |
97
|
|
|
'data-placeholder' => __( 'Select shipping methods', 'woocommerce' ), |
98
|
|
|
), |
99
|
|
|
), |
100
|
|
|
'enable_for_virtual' => array( |
101
|
|
|
'title' => __( 'Accept for virtual orders', 'woocommerce' ), |
102
|
|
|
'label' => __( 'Accept COD if the order is virtual', 'woocommerce' ), |
103
|
|
|
'type' => 'checkbox', |
104
|
|
|
'default' => 'yes', |
105
|
|
|
), |
106
|
|
|
); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Check If The Gateway Is Available For Use. |
111
|
|
|
* |
112
|
|
|
* @return bool |
113
|
|
|
*/ |
114
|
|
|
public function is_available() { |
115
|
|
|
$order = null; |
116
|
|
|
$needs_shipping = false; |
117
|
|
|
|
118
|
|
|
// Test if shipping is needed first |
119
|
|
|
if ( WC()->cart && WC()->cart->needs_shipping() ) { |
120
|
|
|
$needs_shipping = true; |
121
|
|
|
} elseif ( is_page( wc_get_page_id( 'checkout' ) ) && 0 < get_query_var( 'order-pay' ) ) { |
122
|
|
|
$order_id = absint( get_query_var( 'order-pay' ) ); |
123
|
|
|
$order = wc_get_order( $order_id ); |
124
|
|
|
|
125
|
|
|
// Test if order needs shipping. |
126
|
|
|
if ( 0 < sizeof( $order->get_items() ) ) { |
127
|
|
|
foreach ( $order->get_items() as $item ) { |
128
|
|
|
$_product = $item->get_product(); |
129
|
|
|
if ( $_product && $_product->needs_shipping() ) { |
130
|
|
|
$needs_shipping = true; |
131
|
|
|
break; |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
$needs_shipping = apply_filters( 'woocommerce_cart_needs_shipping', $needs_shipping ); |
138
|
|
|
|
139
|
|
|
// Virtual order, with virtual disabled |
140
|
|
|
if ( ! $this->enable_for_virtual && ! $needs_shipping ) { |
141
|
|
|
return false; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
// Check methods |
145
|
|
|
if ( ! empty( $this->enable_for_methods ) && $needs_shipping ) { |
146
|
|
|
|
147
|
|
|
// Only apply if all packages are being shipped via chosen methods, or order is virtual |
148
|
|
|
$chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' ); |
149
|
|
|
|
150
|
|
|
if ( isset( $chosen_shipping_methods_session ) ) { |
151
|
|
|
$chosen_shipping_methods = array_unique( $chosen_shipping_methods_session ); |
152
|
|
|
} else { |
153
|
|
|
$chosen_shipping_methods = array(); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
$check_method = false; |
157
|
|
|
|
158
|
|
|
if ( is_object( $order ) ) { |
159
|
|
|
if ( $order->shipping_method ) { |
160
|
|
|
$check_method = $order->shipping_method; |
161
|
|
|
} |
162
|
|
|
} elseif ( empty( $chosen_shipping_methods ) || sizeof( $chosen_shipping_methods ) > 1 ) { |
163
|
|
|
$check_method = false; |
164
|
|
|
} elseif ( sizeof( $chosen_shipping_methods ) == 1 ) { |
165
|
|
|
$check_method = $chosen_shipping_methods[0]; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
if ( ! $check_method ) { |
169
|
|
|
return false; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$found = false; |
173
|
|
|
|
174
|
|
|
foreach ( $this->enable_for_methods as $method_id ) { |
175
|
|
|
if ( strpos( $check_method, $method_id ) === 0 ) { |
176
|
|
|
$found = true; |
177
|
|
|
break; |
178
|
|
|
} |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
if ( ! $found ) { |
182
|
|
|
return false; |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
return parent::is_available(); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Process the payment and return the result. |
192
|
|
|
* |
193
|
|
|
* @param int $order_id |
194
|
|
|
* @return array |
195
|
|
|
*/ |
196
|
|
|
public function process_payment( $order_id ) { |
197
|
|
|
$order = wc_get_order( $order_id ); |
198
|
|
|
|
199
|
|
|
// Mark as processing or on-hold (payment won't be taken until delivery) |
200
|
|
|
$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' ) ); |
201
|
|
|
|
202
|
|
|
// Reduce stock levels |
203
|
|
|
wc_reduce_stock_levels( $order_id ); |
204
|
|
|
|
205
|
|
|
// Remove cart |
206
|
|
|
WC()->cart->empty_cart(); |
207
|
|
|
|
208
|
|
|
// Return thankyou redirect |
209
|
|
|
return array( |
210
|
|
|
'result' => 'success', |
211
|
|
|
'redirect' => $this->get_return_url( $order ), |
|
|
|
|
212
|
|
|
); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Output for the order received page. |
217
|
|
|
*/ |
218
|
|
|
public function thankyou_page() { |
219
|
|
|
if ( $this->instructions ) { |
220
|
|
|
echo wpautop( wptexturize( $this->instructions ) ); |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Add content to the WC emails. |
226
|
|
|
* |
227
|
|
|
* @access public |
228
|
|
|
* @param WC_Order $order |
229
|
|
|
* @param bool $sent_to_admin |
230
|
|
|
* @param bool $plain_text |
231
|
|
|
*/ |
232
|
|
|
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) { |
|
|
|
|
233
|
|
View Code Duplication |
if ( $this->instructions && ! $sent_to_admin && 'cod' === $order->get_payment_method() ) { |
|
|
|
|
234
|
|
|
echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL; |
235
|
|
|
} |
236
|
|
|
} |
237
|
|
|
} |
238
|
|
|
|
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.