135 lines
5.2 KiB
PHP
135 lines
5.2 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: WooCommerce Pay for Order Address
|
|
* Plugin URI: https://plugins.cleverogre.com/plugin/woocommerce-form-pay-address/
|
|
* Description: Allow users to edit the billing and shipping address on WooCommerce orders awaiting payment
|
|
* Version: 1.0.0
|
|
* Requires at Least: 6.0
|
|
* Requires PHP: 8.3
|
|
* Author: CleverOgre
|
|
* Author URI: https://cleverogre.com/
|
|
* License: GPLv3 or later
|
|
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
|
* Text Domain: woocommerce-form-pay-address
|
|
* Domain Path: /lang
|
|
* Update URI: https://plugins.cleverogre.com/plugin/woocommerce-form-pay-address/
|
|
* Icon1x: https://plugins.cleverogre.com/plugin/woocommerce-form-pay-address/?asset=icon-sm
|
|
* Icon2x: https://plugins.cleverogre.com/plugin/woocommerce-form-pay-address/?asset=icon
|
|
* BannerHigh: https://plugins.cleverogre.com/plugin/woocommerce-form-pay-address/?asset=banner
|
|
* BannerLow: https://plugins.cleverogre.com/plugin/woocommerce-form-pay-address/?asset=banner-sm
|
|
* Copyright: © 2025 CleverOgre, Inc. All rights reserved.
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
use Ogre\Plugin;
|
|
use Automattic\WooCommerce\Enums\OrderInternalStatus;
|
|
|
|
require_once 'vendor/autoload.php';
|
|
|
|
class WCFPA extends Plugin {
|
|
|
|
public function load():void {
|
|
parent::load();
|
|
add_action('before_woocommerce_pay', [$this, 'render_order_details']);
|
|
add_action('woocommerce_order_details_after_customer_address', [$this, 'render_edit_address_link'], 10, 2);
|
|
add_action('woocommerce_customer_save_address', [$this, 'save_address'], 10, 4);
|
|
}
|
|
|
|
private function is_page():bool {
|
|
return is_checkout() && is_wc_endpoint_url('order-pay') && isset($_GET['pay_for_order'], $_GET['key']);
|
|
}
|
|
|
|
private function get_order_id():?int {
|
|
if (!$this->is_page()) return null;
|
|
return intval(basename(strtok($_SERVER["REQUEST_URI"], '?')));
|
|
}
|
|
|
|
private function get_order():?WC_Order {
|
|
if (is_null($order_id = $this->get_order_id())) return null;
|
|
return wc_get_order($order_id);
|
|
}
|
|
|
|
private function current_user_can(WC_Order $order):bool {
|
|
return is_user_logged_in() && get_current_user_id() === $order->get_user_id();
|
|
}
|
|
|
|
public function render_order_details():void {
|
|
$order = $this->get_order();
|
|
if (!$this->current_user_can($order)) return;
|
|
wc_get_template('order/order-details-customer.php', ['order' => $order]);
|
|
}
|
|
|
|
private function get_address_title(string $address_type, int $customer_id = 0):string {
|
|
if (!$customer_id) $customer_id = get_current_user_id();
|
|
$addresses = apply_filters(
|
|
'woocommerce_my_account_get_addresses',
|
|
[
|
|
'billing' => __('Billing address', 'woocommerce'),
|
|
'shipping' => __('Shipping address', 'woocommerce'),
|
|
],
|
|
$customer_id
|
|
);
|
|
if (!array_key_exists($address_type, $addresses)) return ucwords($address_type);
|
|
return $addresses[$address_type];
|
|
}
|
|
|
|
public function render_edit_address_link(string $address_type, WC_Order $order):void {
|
|
if (!$this->is_page()) return;
|
|
printf(
|
|
'<p class="woocommerce-customer-details--edit"><a href="%s" class="edit button" style="display:inline-block;">%s</a></p>',
|
|
esc_url(wc_get_endpoint_url('edit-address', $address_type, get_permalink(get_option('woocommerce_myaccount_page_id')))),
|
|
esc_html(sprintf(
|
|
__('Edit %s', 'woocommerce'),
|
|
$this->get_address_title($address_type, $order->get_user_id())
|
|
))
|
|
);
|
|
}
|
|
|
|
private function get_incomplete_order_statuses():array {
|
|
return array_unique(array_merge(wc_get_is_pending_statuses(), [
|
|
OrderInternalStatus::PENDING,
|
|
OrderInternalStatus::FAILED,
|
|
]));
|
|
}
|
|
|
|
private function get_incomplete_orders(int $user_id):array {
|
|
return wc_get_orders([
|
|
'limit' => -1,
|
|
'customer_id' => $user_id,
|
|
'date_created' => '<=' . time(),
|
|
'orderby' => 'date',
|
|
'order' => 'DESC',
|
|
'status' => $this->get_incomplete_order_statuses(),
|
|
]);
|
|
}
|
|
|
|
public function save_address(int $user_id, string $address_type, array $address_fields = [], WC_Customer|null $customer = null):void {
|
|
if (empty($address_fields) || is_null($customer)) return;
|
|
if (!in_array($address_type, ['billing', 'shipping'])) return;
|
|
|
|
// Get customer's incomplete orders
|
|
if (empty($orders = $this->get_incomplete_orders($user_id))) return;
|
|
|
|
// Get address data from customer
|
|
$address_data = [];
|
|
foreach ($address_fields as $key => $field) {
|
|
$data_key = strpos($key, "{$address_type}_") === 0 ? substr($key, strlen("{$address_type}_")) : "";
|
|
if (is_callable([$customer, "get_{$key}"])) {
|
|
$address_data[$data_key] = $customer->{"get_{$key}"}();
|
|
} else {
|
|
$address_data[$data_key] = $customer->get_meta($key);
|
|
}
|
|
}
|
|
|
|
// Update orders with new address data
|
|
foreach ($orders as $order) {
|
|
$order->{"set_{$address_type}"}($address_data);
|
|
$order->save();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
WCFPA::instance();
|