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