WooCommerce Plugin for payment method "Cash on Pickup"
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

345 lines
11 KiB

<?php
/**
* WooCommerce Cash On Pickup
* Copyright (C) 2013-2014 Pinch Of Code. All rights reserved.
* Copyright (C) 2017-2018 Marian Kadanka. All rights reserved.
* Copyright (C) 2020 Björn Hase, Tentakelfabrik. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* Main plugin class
*
* Provides a Cash on Pickup Payment Gateway.
*
* @class WooChop_Gateway_Cash_On_Pickup
* @extends WC_Payment_Gateway
*/
class WooChop_Gateway_Cash_On_Pickup extends WC_Payment_Gateway
{
const WOO_CHOP_ID = WOOCHOP_CASH_ON_PICKUP_ID;
/**
*
*
*/
public function __construct()
{
load_plugin_textdomain('woochop-cash-on-pickup', false, dirname(dirname(plugin_basename( __FILE__ ))).'/i18n/');
// Setup general properties
$this->setup_properties();
// Load the settings
$this->init_form_fields();
$this->init_settings();
// Get settings
$this->enabled = $this->get_option('enabled');
$this->title = $this->get_option('title');
$this->description = $this->get_option('description');
$this->instructions = $this->get_option('instructions');
$this->enable_for_methods = $this->get_option('enable_for_methods', array() );
$this->default_order_status = $this->get_option('default_order_status', apply_filters('wc_cop_default_order_status', 'on-hold'));
$this->exclusive_for_local = $this->get_option('exclusive_for_local');
$this->enable_for_virtual = $this->get_option('enable_for_virtual', 'yes') === 'yes' ? true : false;
add_action('woocommerce_update_options_payment_gateways_'.$this->id, array($this, 'process_admin_options'));
add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page'));
// Customer Emails
add_action('woocommerce_email_before_order_table', array($this, 'email_instructions'), 10, 3);
if (!is_admin()) {
// Disable other payment methods if local pickup shippings
if ('yes' === $this->enabled && 'yes' === $this->exclusive_for_local) {
add_filter('woocommerce_available_payment_gateways', array($this, 'maybe_cop_only_if_local_pickup_shipping'));
}
}
}
/**
* Setup general properties for the gateway.
*/
protected function setup_properties() {
$this->id = self::WOO_CHOP_ID;
$this->icon = apply_filters('woocommerce_cop_icon', '');
$this->method_title = __('Cash on pickup', 'woochop-cash-on-pickup');
$this->method_description = __('Have your customers pay with cash on pickup.', 'woochop-cash-on-pickup');
$this->has_fields = false;
}
/**
* Get part of a string before :.
*
* Used for example in shipping methods ids where they take the format
* method_id:instance_id
*
* @param string $string
* @return string
*/
private function get_string_before_colon( $string )
{
return trim(current(explode(':', (string) $string)));
}
/**
* Check if every of the shipping methods is local pickup
*
* @param array $shipping_methods Shipping methods to check.
* @return bool
*/
private function only_local_pickups_selected( $shipping_methods )
{
// Local Pickup Plus fix
unset($shipping_methods['undefined']);
foreach($shipping_methods as $shipping_method) {
if (strpos($shipping_method, 'local_pickup') === false) {
return false;
}
}
return true;
}
/**
* COP will be the only payment method available if each of the shipping methods chosen is local pickup only
*
* @param array $gateways Payment methods to filter.
* @return array of filtered methods
*/
public function maybe_cop_only_if_local_pickup_shipping($gateways)
{
if (WC()->session) {
$chosen_shipping_methods_session = WC()->session->get('chosen_shipping_methods');
if ($chosen_shipping_methods_session && $this->only_local_pickups_selected($chosen_shipping_methods_session)) {
if (isset($gateways[self::WOO_CHOP_ID])) {
return array(self::WOO_CHOP_ID => $gateways[self::WOO_CHOP_ID]);
} else {
return array();
}
}
}
return $gateways;
}
/**
* Initialise Gateway Settings Form Fields.
*/
public function init_form_fields()
{
$shipping_methods = array();
$order_statuses = array();
if (is_admin()) {
foreach (WC()->shipping->load_shipping_methods() as $method) {
$shipping_methods[$method->id] = $method->get_method_title();
}
$statuses = function_exists('wc_get_order_statuses') ? wc_get_order_statuses() : array();
foreach ($statuses as $status => $status_name) {
$order_statuses[substr( $status, 3)] = $status_name;
}
}
$this->form_fields = array(
'enabled' => array(
'title' => __('Enable/Disable', 'woocommerce'),
'label' => __('Enable cash on pickup', 'woochop-cash-on-pickup'),
'type' => 'checkbox',
'description' => '',
'default' => 'no',
),
'title' => array(
'title' => __('Title', 'woocommerce'),
'type' => 'text',
'description' => __('Payment method description that the customer will see on your checkout.', 'woocommerce'),
'default' => __('Cash on pickup', 'woochop-cash-on-pickup'),
'desc_tip' => true,
),
'description' => array(
'title' => __('Description', 'woocommerce'),
'type' => 'textarea',
'description' => __('Payment method description that the customer will see on your website.', 'woocommerce'),
'default' => __('Pay with cash on pickup.', 'woochop-cash-on-pickup'),
'desc_tip' => true,
),
'instructions' => array(
'title' => __('Instructions', 'woocommerce'),
'type' => 'textarea',
'description' => __('Instructions that will be added to the thank you page.', 'woocommerce'),
'default' => __('Pay with cash on pickup.', 'woochop-cash-on-pickup'),
'desc_tip' => true,
),
'enable_for_methods' => array(
'title' => __('Enable for shipping methods', 'woocommerce'),
'type' => 'multiselect',
'class' => 'chosen_select',
'css' => 'width: 450px;',
'default' => '',
'description' => __('If COP is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woochop-cash-on-pickup'),
'options' => $shipping_methods,
'desc_tip' => true,
),
'default_order_status' => array(
'title' => __('Default order status', 'woochop-cash-on-pickup'),
'type' => 'select',
'default' => apply_filters('wc_cop_default_order_status', 'on-hold'),
'options' => $order_statuses,
),
'exclusive_for_local' => array(
'title' => __('Disable other payment methods if local pickup', 'woochop-cash-on-pickup'),
'label' => __('Cash on pickup will be the only payment method available if local pickup is selected on checkout', 'woochop-cash-on-pickup'),
'type' => 'checkbox',
'description' => '',
'default' => 'no',
),
'enable_for_virtual' => array(
'title' => __('Accept for virtual orders', 'woocommerce'),
'label' => __('Accept COP if the order is virtual', 'woochop-cash-on-pickup'),
'type' => 'checkbox',
'default' => 'yes',
),
);
}
/**
* Check If The Gateway Is Available For Use.
*
* @return bool
*
*/
public function is_available()
{
$order = null;
$needs_shipping = false;
// Test if shipping is needed first
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.
if (0 < sizeof($order->get_items())) {
foreach ($order->get_items() as $item) {
if (version_compare( WC_VERSION, '3.0', '<')) {
$_product = $order->get_product_from_item($item);
} else {
$_product = $item->get_product();
}
if ($_product && $_product->needs_shipping()) {
$needs_shipping = true;
break;
}
}
}
}
$needs_shipping = apply_filters('woocommerce_cart_needs_shipping', $needs_shipping);
// Virtual order, with virtual disabled
if (!$this->enable_for_virtual && ! $needs_shipping) {
return false;
}
// Only apply if all packages are being shipped via chosen method, or order is virtual.
if (!empty($this->enable_for_methods) && $needs_shipping) {
$chosen_shipping_methods = array();
if (is_object($order)) {
$chosen_shipping_methods = array_unique(array_map(array($this, 'get_string_before_colon'), $order->get_shipping_methods()));
} elseif ( $chosen_shipping_methods_session = WC()->session->get('chosen_shipping_methods')) {
$chosen_shipping_methods = array_unique(array_map(array($this, 'get_string_before_colon'), $chosen_shipping_methods_session));
}
// Local Pickup Plus fix
unset($chosen_shipping_methods['undefined']);
if ( 0 < count(array_diff($chosen_shipping_methods, $this->enable_for_methods)) && !('yes' === $this->exclusive_for_local && $this->only_local_pickups_selected($chosen_shipping_methods))) {
return false;
}
}
return parent::is_available();
}
/**
* Process the payment and return the result.
*
* @param int $order_id
* @return array
*/
public function process_payment($order_id)
{
$order = wc_get_order($order_id);
$order->update_status(apply_filters('wc_cop_default_order_status', $this->default_order_status));
// Reduce stock levels
if (version_compare(WC_VERSION, '3.0', '>=')) {
wc_reduce_stock_levels($order_id);
} else {
$order->reduce_order_stock();
}
// Remove cart
WC()->cart->empty_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => $this->get_return_url($order),
);
}
/**
* Output for the order received page.
*/
public function thankyou_page()
{
if ($this->instructions) {
echo wp_kses_post(wpautop(wptexturize($this->instructions)));
}
}
/**
* Add content to the WC emails.
*
* @access public
* @param WC_Order $order
* @param bool $sent_to_admin
* @param bool $plain_text
*/
public function email_instructions($order, $sent_to_admin, $plain_text = false)
{
$payment_method = version_compare(WC_VERSION, '3.0', '>=') ? $order->get_payment_method() : $order->payment_method;
if ($this->instructions && !$sent_to_admin && $this->id === $payment_method && $order->has_status($this->default_order_status)) {
echo wp_kses_post(wpautop(wptexturize($this->instructions)).PHP_EOL);
}
}
}