This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Class WC_Gateway_COD file. |
||
4 | * |
||
5 | * @package WooCommerce\Gateways |
||
6 | */ |
||
7 | |||
8 | 1 | if ( ! defined( 'ABSPATH' ) ) { |
|
9 | exit; // Exit if accessed directly. |
||
10 | } |
||
11 | |||
12 | /** |
||
13 | * Cash on Delivery Gateway. |
||
14 | * |
||
15 | * Provides a Cash on Delivery Payment Gateway. |
||
16 | * |
||
17 | * @class WC_Gateway_COD |
||
18 | * @extends WC_Payment_Gateway |
||
19 | * @version 2.1.0 |
||
20 | * @package WooCommerce/Classes/Payment |
||
21 | */ |
||
22 | class WC_Gateway_COD extends WC_Payment_Gateway { |
||
23 | |||
24 | /** |
||
25 | * Constructor for the gateway. |
||
26 | */ |
||
27 | 1 | public function __construct() { |
|
28 | // Setup general properties. |
||
29 | 1 | $this->setup_properties(); |
|
30 | |||
31 | // Load the settings. |
||
32 | 1 | $this->init_form_fields(); |
|
33 | 1 | $this->init_settings(); |
|
34 | |||
35 | // Get settings. |
||
36 | 1 | $this->title = $this->get_option( 'title' ); |
|
37 | 1 | $this->description = $this->get_option( 'description' ); |
|
38 | 1 | $this->instructions = $this->get_option( 'instructions' ); |
|
39 | 1 | $this->enable_for_methods = $this->get_option( 'enable_for_methods', array() ); |
|
40 | 1 | $this->enable_for_virtual = $this->get_option( 'enable_for_virtual', 'yes' ) === 'yes'; |
|
41 | |||
42 | 1 | add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); |
|
43 | 1 | add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) ); |
|
44 | 1 | add_filter( 'woocommerce_payment_complete_order_status', array( $this, 'change_payment_complete_order_status' ), 10, 3 ); |
|
45 | |||
46 | // Customer Emails. |
||
47 | 1 | add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 ); |
|
48 | } |
||
49 | |||
50 | /** |
||
51 | * Setup general properties for the gateway. |
||
52 | */ |
||
53 | 1 | protected function setup_properties() { |
|
54 | 1 | $this->id = 'cod'; |
|
55 | 1 | $this->icon = apply_filters( 'woocommerce_cod_icon', '' ); |
|
56 | 1 | $this->method_title = __( 'Cash on delivery', 'woocommerce' ); |
|
57 | 1 | $this->method_description = __( 'Have your customers pay with cash (or by other means) upon delivery.', 'woocommerce' ); |
|
58 | 1 | $this->has_fields = false; |
|
59 | } |
||
60 | |||
61 | /** |
||
62 | * Initialise Gateway Settings Form Fields. |
||
63 | */ |
||
64 | 1 | public function init_form_fields() { |
|
65 | |||
66 | 1 | $options = array(); |
|
67 | 1 | $data_store = WC_Data_Store::load( 'shipping-zone' ); |
|
68 | 1 | $raw_zones = $data_store->get_zones(); |
|
69 | |||
70 | 1 | foreach ( $raw_zones as $raw_zone ) { |
|
71 | $zones[] = new WC_Shipping_Zone( $raw_zone ); |
||
72 | } |
||
73 | |||
74 | 1 | $zones[] = new WC_Shipping_Zone( 0 ); |
|
75 | |||
76 | 1 | foreach ( WC()->shipping()->load_shipping_methods() as $method ) { |
|
77 | |||
78 | 1 | $options[ $method->get_method_title() ] = array(); |
|
79 | |||
80 | // Translators: %1$s shipping method name. |
||
81 | 1 | $options[ $method->get_method_title() ][ $method->id ] = sprintf( __( 'Any "%1$s" method', 'woocommerce' ), $method->get_method_title() ); |
|
82 | |||
83 | 1 | foreach ( $zones as $zone ) { |
|
84 | |||
85 | 1 | $shipping_method_instances = $zone->get_shipping_methods(); |
|
86 | |||
87 | 1 | foreach ( $shipping_method_instances as $shipping_method_instance_id => $shipping_method_instance ) { |
|
88 | |||
89 | if ( $shipping_method_instance->id !== $method->id ) { |
||
90 | continue; |
||
91 | } |
||
92 | |||
93 | $option_id = $shipping_method_instance->get_rate_id(); |
||
94 | |||
95 | // Translators: %1$s shipping method title, %2$s shipping method id. |
||
96 | $option_instance_title = sprintf( __( '%1$s (#%2$s)', 'woocommerce' ), $shipping_method_instance->get_title(), $shipping_method_instance_id ); |
||
97 | |||
98 | // Translators: %1$s zone name, %2$s shipping method instance name. |
||
99 | $option_title = sprintf( __( '%1$s – %2$s', 'woocommerce' ), $zone->get_id() ? $zone->get_zone_name() : __( 'Other locations', 'woocommerce' ), $option_instance_title ); |
||
100 | |||
101 | $options[ $method->get_method_title() ][ $option_id ] = $option_title; |
||
102 | } |
||
103 | } |
||
104 | } |
||
105 | |||
106 | 1 | $this->form_fields = array( |
|
107 | 'enabled' => array( |
||
108 | 1 | 'title' => __( 'Enable/Disable', 'woocommerce' ), |
|
109 | 1 | 'label' => __( 'Enable cash on delivery', 'woocommerce' ), |
|
110 | 1 | 'type' => 'checkbox', |
|
111 | 1 | 'description' => '', |
|
112 | 1 | 'default' => 'no', |
|
113 | ), |
||
114 | 'title' => array( |
||
115 | 1 | 'title' => __( 'Title', 'woocommerce' ), |
|
116 | 1 | 'type' => 'text', |
|
117 | 1 | 'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ), |
|
118 | 1 | 'default' => __( 'Cash on delivery', 'woocommerce' ), |
|
119 | 'desc_tip' => true, |
||
120 | ), |
||
121 | 'description' => array( |
||
122 | 1 | 'title' => __( 'Description', 'woocommerce' ), |
|
123 | 1 | 'type' => 'textarea', |
|
124 | 1 | 'description' => __( 'Payment method description that the customer will see on your website.', 'woocommerce' ), |
|
125 | 1 | 'default' => __( 'Pay with cash upon delivery.', 'woocommerce' ), |
|
126 | 'desc_tip' => true, |
||
127 | ), |
||
128 | 'instructions' => array( |
||
129 | 1 | 'title' => __( 'Instructions', 'woocommerce' ), |
|
130 | 1 | 'type' => 'textarea', |
|
131 | 1 | 'description' => __( 'Instructions that will be added to the thank you page.', 'woocommerce' ), |
|
132 | 1 | 'default' => __( 'Pay with cash upon delivery.', 'woocommerce' ), |
|
133 | 'desc_tip' => true, |
||
134 | ), |
||
135 | 'enable_for_methods' => array( |
||
136 | 1 | 'title' => __( 'Enable for shipping methods', 'woocommerce' ), |
|
137 | 1 | 'type' => 'multiselect', |
|
138 | 1 | 'class' => 'wc-enhanced-select', |
|
139 | 1 | 'css' => 'width: 400px;', |
|
140 | 1 | 'default' => '', |
|
141 | 1 | 'description' => __( 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woocommerce' ), |
|
142 | 1 | 'options' => $options, |
|
143 | 'desc_tip' => true, |
||
144 | 'custom_attributes' => array( |
||
145 | 1 | 'data-placeholder' => __( 'Select shipping methods', 'woocommerce' ), |
|
146 | ), |
||
147 | ), |
||
148 | 'enable_for_virtual' => array( |
||
149 | 1 | 'title' => __( 'Accept for virtual orders', 'woocommerce' ), |
|
150 | 1 | 'label' => __( 'Accept COD if the order is virtual', 'woocommerce' ), |
|
151 | 1 | 'type' => 'checkbox', |
|
152 | 1 | 'default' => 'yes', |
|
153 | ), |
||
154 | ); |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * Check If The Gateway Is Available For Use. |
||
159 | * |
||
160 | * @return bool |
||
161 | */ |
||
162 | 1 | public function is_available() { |
|
163 | 1 | $order = null; |
|
164 | 1 | $needs_shipping = false; |
|
165 | |||
166 | // Test if shipping is needed first. |
||
167 | 1 | if ( WC()->cart && WC()->cart->needs_shipping() ) { |
|
168 | $needs_shipping = true; |
||
169 | 1 | } elseif ( is_page( wc_get_page_id( 'checkout' ) ) && 0 < get_query_var( 'order-pay' ) ) { |
|
170 | $order_id = absint( get_query_var( 'order-pay' ) ); |
||
171 | $order = wc_get_order( $order_id ); |
||
172 | |||
173 | // Test if order needs shipping. |
||
174 | if ( 0 < count( $order->get_items() ) ) { |
||
175 | foreach ( $order->get_items() as $item ) { |
||
176 | $_product = $item->get_product(); |
||
177 | if ( $_product && $_product->needs_shipping() ) { |
||
178 | $needs_shipping = true; |
||
179 | break; |
||
180 | } |
||
181 | } |
||
182 | } |
||
183 | } |
||
184 | |||
185 | 1 | $needs_shipping = apply_filters( 'woocommerce_cart_needs_shipping', $needs_shipping ); |
|
186 | |||
187 | // Virtual order, with virtual disabled. |
||
188 | 1 | if ( ! $this->enable_for_virtual && ! $needs_shipping ) { |
|
189 | return false; |
||
190 | } |
||
191 | |||
192 | // Only apply if all packages are being shipped via chosen method, or order is virtual. |
||
193 | 1 | if ( ! empty( $this->enable_for_methods ) && $needs_shipping ) { |
|
194 | $order_shipping_items = is_object( $order ) ? $order->get_shipping_methods() : false; |
||
195 | $chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' ); |
||
196 | |||
197 | if ( $order_shipping_items ) { |
||
198 | $canonical_rate_ids = $this->get_canonical_order_shipping_item_rate_ids( $order_shipping_items ); |
||
199 | } else { |
||
200 | $canonical_rate_ids = $this->get_canonical_package_rate_ids( $chosen_shipping_methods_session ); |
||
201 | } |
||
202 | |||
203 | if ( ! count( $this->get_matching_rates( $canonical_rate_ids ) ) ) { |
||
204 | return false; |
||
205 | } |
||
206 | } |
||
207 | |||
208 | 1 | return parent::is_available(); |
|
209 | } |
||
210 | |||
211 | /** |
||
212 | * Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format. |
||
213 | * |
||
214 | * @since 3.4.0 |
||
215 | * |
||
216 | * @param array $order_shipping_items Array of WC_Order_Item_Shipping objects. |
||
217 | * @return array $canonical_rate_ids Rate IDs in a canonical format. |
||
218 | */ |
||
219 | private function get_canonical_order_shipping_item_rate_ids( $order_shipping_items ) { |
||
220 | |||
221 | $canonical_rate_ids = array(); |
||
222 | |||
223 | foreach ( $order_shipping_items as $order_shipping_item ) { |
||
224 | $canonical_rate_ids[] = $order_shipping_item->get_method_id() . ':' . $order_shipping_item->get_instance_id(); |
||
225 | } |
||
226 | |||
227 | return $canonical_rate_ids; |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format. |
||
232 | * |
||
233 | * @since 3.4.0 |
||
234 | * |
||
235 | * @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. |
||
236 | * @return array $canonical_rate_ids Rate IDs in a canonical format. |
||
237 | */ |
||
238 | private function get_canonical_package_rate_ids( $chosen_package_rate_ids ) { |
||
239 | |||
240 | $shipping_packages = WC()->shipping()->get_packages(); |
||
241 | $canonical_rate_ids = array(); |
||
242 | |||
243 | if ( ! empty( $chosen_package_rate_ids ) && is_array( $chosen_package_rate_ids ) ) { |
||
244 | foreach ( $chosen_package_rate_ids as $package_key => $chosen_package_rate_id ) { |
||
245 | if ( ! empty( $shipping_packages[ $package_key ]['rates'][ $chosen_package_rate_id ] ) ) { |
||
246 | $chosen_rate = $shipping_packages[ $package_key ]['rates'][ $chosen_package_rate_id ]; |
||
247 | $canonical_rate_ids[] = $chosen_rate->get_method_id() . ':' . $chosen_rate->get_instance_id(); |
||
248 | } |
||
249 | } |
||
250 | } |
||
251 | |||
252 | return $canonical_rate_ids; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * Indicates whether a rate exists in an array of canonically-formatted rate IDs that activates this gateway. |
||
257 | * |
||
258 | * @since 3.4.0 |
||
259 | * |
||
260 | * @param array $rate_ids Rate ids to check. |
||
261 | * @return boolean |
||
262 | */ |
||
263 | private function get_matching_rates( $rate_ids ) { |
||
264 | // 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. |
||
265 | 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 ) ) ) ) ); |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * Process the payment and return the result. |
||
270 | * |
||
271 | * @param int $order_id Order ID. |
||
272 | * @return array |
||
273 | */ |
||
274 | View Code Duplication | public function process_payment( $order_id ) { |
|
0 ignored issues
–
show
|
|||
275 | $order = wc_get_order( $order_id ); |
||
276 | |||
277 | if ( $order->get_total() > 0 ) { |
||
278 | // Mark as processing or on-hold (payment won't be taken until delivery). |
||
279 | $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' ) ); |
||
280 | } else { |
||
281 | $order->payment_complete(); |
||
282 | } |
||
283 | |||
284 | // Remove cart. |
||
285 | WC()->cart->empty_cart(); |
||
286 | |||
287 | // Return thankyou redirect. |
||
288 | return array( |
||
289 | 'result' => 'success', |
||
290 | 'redirect' => $this->get_return_url( $order ), |
||
291 | ); |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * Output for the order received page. |
||
296 | */ |
||
297 | public function thankyou_page() { |
||
298 | if ( $this->instructions ) { |
||
299 | echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) ); |
||
300 | } |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | * Change payment complete order status to completed for COD orders. |
||
305 | * |
||
306 | * @since 3.1.0 |
||
307 | * @param string $status Current order status. |
||
308 | * @param int $order_id Order ID. |
||
309 | * @param WC_Order|false $order Order object. |
||
310 | * @return string |
||
311 | */ |
||
312 | public function change_payment_complete_order_status( $status, $order_id = 0, $order = false ) { |
||
313 | if ( $order && 'cod' === $order->get_payment_method() ) { |
||
314 | $status = 'completed'; |
||
315 | } |
||
316 | return $status; |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Add content to the WC emails. |
||
321 | * |
||
322 | * @access public |
||
323 | * @param WC_Order $order Order object. |
||
324 | * @param bool $sent_to_admin Sent to admin. |
||
325 | * @param bool $plain_text Email format: plain text or HTML. |
||
326 | */ |
||
327 | public function email_instructions( $order, $sent_to_admin, $plain_text = false ) { |
||
328 | View Code Duplication | if ( $this->instructions && ! $sent_to_admin && $this->id === $order->get_payment_method() ) { |
|
329 | echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL ); |
||
330 | } |
||
331 | } |
||
332 | } |
||
333 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.