From d6f44cbf99e2ca0676b522894d4b25015f25751b Mon Sep 17 00:00:00 2001 From: Cooper Dalrymple Date: Tue, 19 Aug 2025 14:56:00 -0500 Subject: [PATCH] Initial build --- .gitignore | 7 ++ Makefile | 5 ++ README.md | 3 - composer.json | 47 +++++++++++ gulpfile.js | 55 +++++++++++++ package.json | 26 ++++++ readme.txt | 29 +++++++ woocommerce-form-pay-address.php | 134 +++++++++++++++++++++++++++++++ 8 files changed, 303 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile delete mode 100644 README.md create mode 100644 composer.json create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 readme.txt create mode 100644 woocommerce-form-pay-address.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3868316 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.vscode +lib +vendor +node_modules +composer.lock +package-lock.json +woocommerce-form-pay-address.zip diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d0c0b5a --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +clean: + rm -rf lib || true + rm -rf vendor || true + rm composer.lock || true + rm package-lock.json || true diff --git a/README.md b/README.md deleted file mode 100644 index 6a80609..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# woocommerce-form-pay-address - -Allow users to edit the billing and shipping address on WooCommerce orders awaiting payment \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..80c74de --- /dev/null +++ b/composer.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://getcomposer.org/schema.json", + "name": "cleverogre/woocommerce-form-pay-address", + "version": "1.0.0", + "title": "WooCommerce Pay for Order Address", + "description": "Allow users to edit the billing and shipping address on WooCommerce orders awaiting payment", + "author": "CleverOgre", + "license": "GPL-3.0+", + "keywords": [ + "WordPress", + "Plugin", + "WooCommerce" + ], + "homepage": "https://cleverogre.com", + "repositories": { + "cleverogre/plugin-framework": { + "type": "vcs", + "url": "git@git.cleverogre.com:cleverogre/plugin-framework.git" + }, + "wp-package-updater": { + "type": "package", + "package": { + "name": "froger-me/wp-package-updater", + "version": "1.4.0", + "source": { + "url": "https://github.com/froger-me/wp-package-updater.git", + "type": "git", + "reference": "master" + } + } + } + }, + "require": { + "cleverogre/plugin-framework": "dev-main" + }, + "replace": { + "wpengine/advanced-custom-fields-pro": "*" + }, + "scripts": { + "post-update-cmd": [ + "php vendor/magicoli/wp-package-updater-lib/install.php" + ] + }, + "config": { + "optimize-autoloader": true + } +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..4cd11fb --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,55 @@ +const fs = require('fs'), + path = require('path'), + gulp = require('gulp'), + clean = require('gulp-clean'), + zip = require('gulp-zip').default; + +const PACKAGE = path.basename(__dirname); + +// Clean Tasks + +gulp.task('clean-package', () => { + return gulp.src(`${PACKAGE}.zip`, { + read: false, + allowEmpty: true, + }).pipe(clean()); +}); + +gulp.task( + 'clean', + gulp.series( + 'clean-package' + ) +); + +// Package Tasks + +gulp.task('package-compress', () => { + return gulp.src([ + (fs.existsSync('lang') ? 'lang/**/*' : null), + 'lib/**/*', + 'vendor/**/*', + 'LICENSE', + 'readme.txt', + 'woocommerce-form-pay-address.php' + ].filter(x => x), { base: './' }) + .pipe(zip(`${PACKAGE}.zip`)) + .pipe(gulp.dest('./')); +}); + +gulp.task( + 'package', + gulp.series( + 'clean-package', + 'package-compress' + ) +); + +// Default Tasks + +gulp.task( + 'default', + gulp.series( + 'package' + ) +); diff --git a/package.json b/package.json new file mode 100644 index 0000000..183dd52 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://www.schemastore.org/package.json", + "name": "woocommerce-form-pay-address", + "version": "1.0.0", + "title": "WooCommerce Pay for Order Address", + "description": "Allow users to edit the billing and shipping address on WooCommerce orders awaiting payment", + "author": "CleverOgre", + "license": "GPL-3.0+", + "keywords": [ + "WordPress", + "Plugin", + "WooCommerce" + ], + "homepage": "https://cleverogre.com", + "engines": { + "node": ">=6.9.4", + "npm": ">=1.1.0" + }, + "devDependencies": { + "gulp": "^5.0.0", + "gulp-clean": "^0.4.0", + "gulp-cli": "^2.3.0", + "gulp-zip": "^6.1.0", + "path": "^0.12.7" + } +} diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..3da347b --- /dev/null +++ b/readme.txt @@ -0,0 +1,29 @@ +=== WooCommerce Pay for Order Address === +Contributors: ogrecooper, cleverogre +Tested up to: 6.8 +Requires at least: 5.0 +Requires PHP: 8.3 +Version: 1.0.0 +License: GPLv3 or later +License URI: https://www.gnu.org/licenses/gpl-3.0.html +Copyright: CleverOgre +Donate link: https://cleverogre.com/ +Tags: wordpress, plugin, woocommerce, order, address, billing + +Allow users to edit the billing and shipping address on WooCommerce orders awaiting payment. + +== Installation == + +1. Upload the plugin files to the `/wp-content/plugins/woocommerce-form-pay-address` directory and ensure that it is active. +2. Activate the plugin through the 'Plugins' screen in WordPress. + +== FAQ == + += What is this plugin? = + +If you don't know what plugin you have downloaded, please contact [CleverOgre](team@cleverogre.com) for more information. This plugin is only developed for a small, private audience. + +== Changelog == + += 1.0.0 - 2025-08-19 = +* Initial release diff --git a/woocommerce-form-pay-address.php b/woocommerce-form-pay-address.php new file mode 100644 index 0000000..9ab5c4c --- /dev/null +++ b/woocommerce-form-pay-address.php @@ -0,0 +1,134 @@ +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( + '

%s

', + 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();