From 243695679f7709167a4bd763aeeb729e09b93019 Mon Sep 17 00:00:00 2001
From: Brian DiChiara <122309362+bd-viget@users.noreply.github.com>
Date: Mon, 18 Mar 2024 12:16:07 -0500
Subject: [PATCH] All The Fixes (#787)
* [#684] WIP Support Request Form
* [#684] Added form dependencies and populate data
* [#684] Wiring up HTMX
* [#684] HTMX Fix
* [#684] Now just need it to submit
* [#684] Styling the support form
* [#684] adjusting loading icon
* [#684] updating textarea
* [#684] Form Submission finally done.
* [#684] Submit Request from Bid Order page
* [#684] Support Request from Reward Order page
* [#684] Request Class (lost this code somehow)
* [#684] Admin Views
* [#684] Request Details
* [#684] WP Screen updates, unbolded "read" messages
* [#684] Support Request Email and Success Message
* [#684] Remove unused stuff
* [#684] Send Support Email to Super Admins
* [#684] Fixed removal of WC Settings tabs for nonprofits
* [#684] Create Support Page
* [#684] Actually trigger creation of support page
* [#684] Minor Adjustments
* [#684] Remove use of wp_die()
* [#684] Prevent Changes to Support Page
* [#684] Format bid amount
* [#684] Dynamic page URL
* [#684] Unnecessary comment
* [#781] Fix Free Bids Issue
* [#781] Fix filter count
* [#779] Auction End Bug fixes
* [#779] Update invalid check for Nonprofit
* [N/A] Fix Merge Bug
* [#779] puts the submit button on top
* [#784] Rename Support Requests Menu to "Support"
* [#784] PR Feedback
* [N/A] Adjust Bid Extension Formatted Text
* [N/A] Removes unused class reference
* [N/A] Init WC Emails class when it's not already loaded
* [N/A] Remove Debugging Plugins
* [#787] Move array_filter to ALL the returned pages.
* [#684] PR Feedback
* [#781] PR Feedback
* [NA] Updated to use existing constant
* [#779] PR Feedback
* [N/A] I18n Some Text
* [N/A] Fix bug with Reward arg vs Bid arg
---------
Co-authored-by: Nathan Schmidt <91974372+nathan-schmidt-viget@users.noreply.github.com>
---
.../goodbids/blocks/bid-now/block.php | 2 +-
.../blocks/support-request-form/block.json | 15 +
.../blocks/support-request-form/block.php | 130 ++
.../blocks/support-request-form/render.php | 17 +
client-mu-plugins/goodbids/composer.json | 2 -
client-mu-plugins/goodbids/composer.lock | 38 +-
.../goodbids/src/classes/Admin/Admin.php | 67 +-
.../goodbids/src/classes/Auctions/Admin.php | 9 +-
.../goodbids/src/classes/Auctions/Auction.php | 87 +-
.../src/classes/Auctions/Auctions.php | 7 +-
.../goodbids/src/classes/Auctions/Bids.php | 49 +-
.../goodbids/src/classes/Auctions/Cron.php | 7 +-
.../goodbids/src/classes/Auctions/FreeBid.php | 423 +-----
.../classes/Auctions/FundraisingFields.php | 12 +-
.../goodbids/src/classes/Auctions/Wizard.php | 3 +-
.../goodbids/src/classes/Core.php | 90 +-
.../goodbids/src/classes/Frontend/Forms.php | 79 +
.../goodbids/src/classes/Frontend/Notices.php | 30 +
.../goodbids/src/classes/Frontend/Request.php | 382 +++++
.../src/classes/Frontend/SupportRequest.php | 1277 +++++++++++++++++
.../goodbids/src/classes/Network/Auctions.php | 9 +-
.../goodbids/src/classes/Network/Bidders.php | 9 +-
.../goodbids/src/classes/Network/Logs.php | 2 +-
.../goodbids/src/classes/Network/Network.php | 1 -
.../src/classes/Network/Nonprofit.php | 2 +-
.../src/classes/Network/Nonprofits.php | 9 +-
.../goodbids/src/classes/Network/Settings.php | 2 +-
.../goodbids/src/classes/Network/Sites.php | 56 +-
.../src/classes/Nonprofits/Invoices.php | 2 +-
.../src/classes/Nonprofits/Verification.php | 2 +-
.../src/classes/Plugins/WooCommerce.php | 61 -
.../classes/Plugins/WooCommerce/Account.php | 2 +-
.../src/classes/Plugins/WooCommerce/Admin.php | 39 +-
.../src/classes/Plugins/WooCommerce/Cart.php | 2 -
.../classes/Plugins/WooCommerce/Checkout.php | 8 +-
.../classes/Plugins/WooCommerce/Coupons.php | 12 +-
.../classes/Plugins/WooCommerce/Emails.php | 4 +
.../Plugins/WooCommerce/Emails/Email.php | 79 +-
.../WooCommerce/Emails/FreeBidEarned.php | 2 +-
.../WooCommerce/Emails/SupportRequest.php | 101 ++
.../classes/Plugins/WooCommerce/Orders.php | 2 +-
.../goodbids/src/classes/Users/Bidder.php | 2 +-
.../goodbids/src/classes/Users/FreeBid.php | 438 ++++++
.../goodbids/src/classes/Users/FreeBids.php | 422 ++++++
.../goodbids/src/classes/Users/Referrals.php | 4 +-
.../src/classes/Users/Referrals/Admin.php | 3 -
.../src/classes/Users/Referrals/Track.php | 3 +-
.../goodbids/src/classes/Users/Users.php | 330 -----
.../src/classes/Utilities/Payload.php | 6 +-
.../src/classes/Utilities/Utilities.php | 14 +
.../src/views/auction-wizard/clone/index.tsx | 102 +-
client-mu-plugins/goodbids/tailwind.config.js | 3 +
.../goodbids/views/admin/invoices/details.php | 6 +-
.../views/admin/support-requests/details.php | 35 +
.../views/admin/users/grant-free-bid.php | 8 +-
.../goodbids/views/forms/callback.php | 10 +
.../goodbids/views/forms/select.php | 96 ++
.../goodbids/views/forms/text.php | 76 +
.../goodbids/views/forms/textarea.php | 75 +
.../goodbids/views/forms/unsupported.php | 10 +
.../goodbids/views/parts/die.php | 143 ++
.../template-support-request-page.php | 21 +
.../emails/plain/support-request.php | 57 +
.../woocommerce/emails/support-request.php | 72 +
.../myaccount/dashboard-header.php | 4 +-
.../myaccount/free-bids-header.php | 8 +-
.../views/woocommerce/myaccount/free-bids.php | 2 +-
.../woocommerce/myaccount/view-order.php | 35 +-
.../patterns/template-home-nonprofit.php | 4 +-
69 files changed, 4027 insertions(+), 1094 deletions(-)
create mode 100644 client-mu-plugins/goodbids/blocks/support-request-form/block.json
create mode 100644 client-mu-plugins/goodbids/blocks/support-request-form/block.php
create mode 100644 client-mu-plugins/goodbids/blocks/support-request-form/render.php
create mode 100644 client-mu-plugins/goodbids/src/classes/Frontend/Forms.php
create mode 100644 client-mu-plugins/goodbids/src/classes/Frontend/Request.php
create mode 100644 client-mu-plugins/goodbids/src/classes/Frontend/SupportRequest.php
create mode 100644 client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/SupportRequest.php
create mode 100644 client-mu-plugins/goodbids/src/classes/Users/FreeBid.php
create mode 100644 client-mu-plugins/goodbids/src/classes/Users/FreeBids.php
create mode 100644 client-mu-plugins/goodbids/views/admin/support-requests/details.php
create mode 100644 client-mu-plugins/goodbids/views/forms/callback.php
create mode 100644 client-mu-plugins/goodbids/views/forms/select.php
create mode 100644 client-mu-plugins/goodbids/views/forms/text.php
create mode 100644 client-mu-plugins/goodbids/views/forms/textarea.php
create mode 100644 client-mu-plugins/goodbids/views/forms/unsupported.php
create mode 100644 client-mu-plugins/goodbids/views/parts/die.php
create mode 100644 client-mu-plugins/goodbids/views/patterns/template-support-request-page.php
create mode 100644 client-mu-plugins/goodbids/views/woocommerce/emails/plain/support-request.php
create mode 100644 client-mu-plugins/goodbids/views/woocommerce/emails/support-request.php
diff --git a/client-mu-plugins/goodbids/blocks/bid-now/block.php b/client-mu-plugins/goodbids/blocks/bid-now/block.php
index 00f87026d..4b91e0105 100644
--- a/client-mu-plugins/goodbids/blocks/bid-now/block.php
+++ b/client-mu-plugins/goodbids/blocks/bid-now/block.php
@@ -208,7 +208,7 @@ public function show_free_bid_button(): bool {
}
// Make sure the user has free bids.
- if ( ! goodbids()->users->get_available_free_bid_count() ) {
+ if ( ! goodbids()->free_bids->get_available_count() ) {
return false;
}
diff --git a/client-mu-plugins/goodbids/blocks/support-request-form/block.json b/client-mu-plugins/goodbids/blocks/support-request-form/block.json
new file mode 100644
index 000000000..1727d70b2
--- /dev/null
+++ b/client-mu-plugins/goodbids/blocks/support-request-form/block.json
@@ -0,0 +1,15 @@
+{
+ "name": "support-request-form",
+ "title": "Support Request Form",
+ "description": "Displays a support request form.",
+ "icon": "sos",
+ "category": "goodbids",
+ "textdomain": "goodbids",
+ "keywords": ["form", "support", "report", "help", "problem", "issue" ],
+ "acf": {
+ "mode": "preview"
+ },
+ "supports": {
+ "jsx": true
+ }
+}
diff --git a/client-mu-plugins/goodbids/blocks/support-request-form/block.php b/client-mu-plugins/goodbids/blocks/support-request-form/block.php
new file mode 100644
index 000000000..331a09d6d
--- /dev/null
+++ b/client-mu-plugins/goodbids/blocks/support-request-form/block.php
@@ -0,0 +1,130 @@
+support->submission_processed() ) {
+ goodbids()->notices->display_notice( Notices::REQUEST_SUBMITTED );
+ } else {
+ $form_data = goodbids()->support->get_form_data();
+ }
+
+ $button_class = 'btn-fill-secondary text-md';
+
+ if ( is_admin() ) {
+ $button_class .= ' pointer-events-none';
+ }
+ ?>
+
+ support->get_error() ) {
+ return;
+ }
+ ?>
+
+
+ support->get_error() ); ?>
+
+
+ 'base-2',
+ 'content' => __( 'Request Support from', 'goodbids' ) . ' ' . $nonprofit->get_name(),
+ ],
+ ],
+ [
+ 'core/paragraph',
+ [
+ 'content' => __( 'Use the form below to submit a support request to this Nonprofit. Your submission will be visible to administrators for this Nonprofit site as well as the GOODBIDS support team. We will respond as soon as we can.', 'goodbids' ),
+ 'textColor' => 'base-2',
+ ],
+ ],
+ ];
+
+ printf(
+ '',
+ esc_attr( wp_json_encode( $template ) )
+ );
+ }
+}
diff --git a/client-mu-plugins/goodbids/blocks/support-request-form/render.php b/client-mu-plugins/goodbids/blocks/support-request-form/render.php
new file mode 100644
index 000000000..a8b20faa8
--- /dev/null
+++ b/client-mu-plugins/goodbids/blocks/support-request-form/render.php
@@ -0,0 +1,17 @@
+
+
diff --git a/client-mu-plugins/goodbids/composer.json b/client-mu-plugins/goodbids/composer.json
index a7678e663..3a3baf329 100644
--- a/client-mu-plugins/goodbids/composer.json
+++ b/client-mu-plugins/goodbids/composer.json
@@ -55,12 +55,10 @@
"vlucas/phpdotenv": "^5.5",
"wpackagist-plugin/accessibility-checker": "^1.9.3",
"wpackagist-plugin/svg-support": "^2.5",
- "wpackagist-plugin/user-role-editor": "^4.64",
"wpackagist-plugin/user-switching": "^1.7",
"wpackagist-plugin/woocommerce": "^8.6",
"wpackagist-plugin/woocommerce-gateway-stripe": "^8.0",
"wpackagist-plugin/woocommerce-services": "^2.5",
- "wpackagist-plugin/wp-mail-log": "^1.1",
"wpackagist-plugin/zapier": "^1.0",
"wpengine/advanced-custom-fields-pro": "^6.2"
},
diff --git a/client-mu-plugins/goodbids/composer.lock b/client-mu-plugins/goodbids/composer.lock
index 33ff81a73..fa5cc135c 100644
--- a/client-mu-plugins/goodbids/composer.lock
+++ b/client-mu-plugins/goodbids/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "0f7a18aedff95f21ea9bec5229e265d0",
+ "content-hash": "5856604c72040bce64ad4a5ccf6bfbf3",
"packages": [
{
"name": "composer/installers",
@@ -1265,24 +1265,6 @@
"type": "wordpress-plugin",
"homepage": "https://wordpress.org/plugins/svg-support/"
},
- {
- "name": "wpackagist-plugin/user-role-editor",
- "version": "4.64.2",
- "source": {
- "type": "svn",
- "url": "https://plugins.svn.wordpress.org/user-role-editor/",
- "reference": "tags/4.64.2"
- },
- "dist": {
- "type": "zip",
- "url": "https://downloads.wordpress.org/plugin/user-role-editor.4.64.2.zip"
- },
- "require": {
- "composer/installers": "^1.0 || ^2.0"
- },
- "type": "wordpress-plugin",
- "homepage": "https://wordpress.org/plugins/user-role-editor/"
- },
{
"name": "wpackagist-plugin/user-switching",
"version": "1.7.3",
@@ -1355,24 +1337,6 @@
"type": "wordpress-plugin",
"homepage": "https://wordpress.org/plugins/woocommerce-services/"
},
- {
- "name": "wpackagist-plugin/wp-mail-log",
- "version": "1.1.3",
- "source": {
- "type": "svn",
- "url": "https://plugins.svn.wordpress.org/wp-mail-log/",
- "reference": "tags/1.1.3"
- },
- "dist": {
- "type": "zip",
- "url": "https://downloads.wordpress.org/plugin/wp-mail-log.1.1.3.zip"
- },
- "require": {
- "composer/installers": "^1.0 || ^2.0"
- },
- "type": "wordpress-plugin",
- "homepage": "https://wordpress.org/plugins/wp-mail-log/"
- },
{
"name": "wpackagist-plugin/zapier",
"version": "1.0.6",
diff --git a/client-mu-plugins/goodbids/src/classes/Admin/Admin.php b/client-mu-plugins/goodbids/src/classes/Admin/Admin.php
index 8a0fd13ab..3f36e9b7a 100644
--- a/client-mu-plugins/goodbids/src/classes/Admin/Admin.php
+++ b/client-mu-plugins/goodbids/src/classes/Admin/Admin.php
@@ -8,6 +8,7 @@
namespace GoodBids\Admin;
+use GoodBids\Network\Sites;
use GoodBids\Users\Permissions;
/**
@@ -31,6 +32,9 @@ public function __construct() {
// Remove Nav Items for Jr Admins
$this->jr_admin_nav_cleanup();
+
+ // Limit access to pages
+ $this->limit_access_to_pages();
}
/**
@@ -81,7 +85,7 @@ public function add_menu_separator( mixed $position ): void {
* @return void
*/
public function render_field( string $key, array $field, string $prefix = '', array $data = [], bool $wrap = true ) : void {
- $required = ! empty( $field['required'] ) && true === $field['required'];
+ $required = ! empty( $field['required'] );
$placeholder = $field['placeholder'] ?? '';
$field_id = $prefix ? $prefix . '-' . $key : $key;
$value = $data[ $key ] ?? '';
@@ -211,4 +215,65 @@ function ( array $features ): array {
}
);
}
+
+ /**
+ * Limit access to specific pages for non-Super Admins.
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function limit_access_to_pages(): void {
+ add_action(
+ 'admin_init',
+ function () {
+ $pages = array_filter(
+ apply_filters(
+ 'goodbids_restrict_pages',
+ [
+ intval( get_option( Sites::SUPPORT_OPTION ) ),
+ ]
+ )
+ );
+
+ // Block access to Specific Pages
+ add_filter(
+ 'user_has_cap',
+ function ( array $all_caps, array $caps, array $args ) use ( $pages ) {
+ if ( is_super_admin() ) {
+ return $all_caps;
+ }
+
+ $post_id = get_the_ID();
+
+ if ( ! $post_id && isset( $args[2] ) ) {
+ $post_id = $args[2];
+ }
+
+ if ( ! $post_id || 'page' !== get_post_type( $post_id ) ) {
+ return $all_caps;
+ }
+
+ if ( ! in_array( $post_id, $pages, true ) ) {
+ return $all_caps;
+ }
+
+ $all_caps['publish_pages'] = false;
+ $all_caps['edit_pages'] = false;
+ $all_caps['edit_others_pages'] = false;
+ $all_caps['edit_published_pages'] = false;
+ $all_caps['edit_private_pages'] = false;
+ $all_caps['delete_pages'] = false;
+ $all_caps['delete_private_pages'] = false;
+ $all_caps['delete_others_pages'] = false;
+ $all_caps['delete_published_pages'] = false;
+
+ return $all_caps;
+ },
+ 10,
+ 3
+ );
+ }
+ );
+ }
}
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/Admin.php b/client-mu-plugins/goodbids/src/classes/Auctions/Admin.php
index 0865c7dbd..17aa6f7d4 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/Admin.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/Admin.php
@@ -10,6 +10,7 @@
use WC_Product_Variation;
use WP_Post;
+use WP_Screen;
/**
* Auction Admin Class
@@ -57,9 +58,7 @@ public function __construct() {
private function add_info_meta_box(): void {
add_action(
'current_screen',
- function (): void {
- $screen = get_current_screen();
-
+ function ( WP_Screen $screen ): void {
if ( goodbids()->auctions->get_post_type() !== $screen->id ) {
return;
}
@@ -236,8 +235,8 @@ function () {
private function live_auction_restrictions(): void {
add_action(
'current_screen',
- function () {
- if ( ! $this->is_restricted() ) {
+ function ( WP_Screen $screen ): void {
+ if ( $screen->id !== goodbids()->auctions->get_post_type() || ! $this->is_restricted() ) {
return;
}
?>
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/Auction.php b/client-mu-plugins/goodbids/src/classes/Auctions/Auction.php
index aea125fae..018fd90be 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/Auction.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/Auction.php
@@ -12,6 +12,7 @@
use DateTimeImmutable;
use Exception;
use GoodBids\Nonprofits\Invoices;
+use GoodBids\Users\FreeBid;
use GoodBids\Utilities\Log;
use WC_Order;
use WC_Product;
@@ -67,6 +68,12 @@ class Auction {
*/
const AUCTION_EXTENSIONS_META_KEY = '_auction_extensions';
+ /**
+ * @since 1.0.0
+ * @var string
+ */
+ const FREE_BIDS_META_KEY = '_goodbids_free_bids';
+
/**
* @since 1.0.0
* @var string
@@ -155,7 +162,7 @@ public function get_id(): ?int {
* @return bool
*/
public function is_valid(): bool {
- return is_null( $this->post );
+ return ! is_null( $this->post );
}
/**
@@ -591,27 +598,59 @@ public function get_bid_extension_formatted(): string {
$sec = $seconds % MINUTE_IN_SECONDS;
if ( $seconds < HOUR_IN_SECONDS ) {
- return sprintf(
- '%d %s and %d %s',
+ $return = sprintf(
+ '%d %s',
$min,
- _n( 'minute', 'minutes', $min, 'goodbids' ),
- $sec,
- _n( 'second', 'seconds', $sec, 'goodbids' )
+ _n( 'minute', 'minutes', $min, 'goodbids' )
);
+
+ if ( $sec ) {
+ $return .= sprintf(
+ ' and %d %s',
+ $sec,
+ _n( 'second', 'seconds', $sec, 'goodbids' )
+ );
+ }
+
+ return $return;
}
$hr = floor( $seconds / HOUR_IN_SECONDS );
$min = floor( ( $seconds % HOUR_IN_SECONDS ) / MINUTE_IN_SECONDS );
- return sprintf(
- '%d %s, %d %s, and %d %s',
+ $return = sprintf(
+ '%d %s',
$hr,
- _n( 'hour', 'hours', $hr, 'goodbids' ),
- $min,
- _n( 'minute', 'minutes', $min, 'goodbids' ),
- $sec,
- _n( 'second', 'seconds', $sec, 'goodbids' )
+ _n( 'hour', 'hours', $hr, 'goodbids' )
);
+
+ if ( ! $min && ! $sec ) {
+ return $return;
+ }
+
+ if ( $min && ! $sec ) {
+ $return .= sprintf(
+ ' and %d %s',
+ $min,
+ _n( 'minute', 'minutes', $min, 'goodbids' )
+ );
+ } else if ( ! $min && $sec ) {
+ $return .= sprintf(
+ ' and %d %s',
+ $sec,
+ _n( 'second', 'seconds', $sec, 'goodbids' )
+ );
+ } else {
+ $return .= sprintf(
+ ', %d %s, and %d %s',
+ $min,
+ _n( 'minute', 'minutes', $min, 'goodbids' ),
+ $sec,
+ _n( 'second', 'seconds', $sec, 'goodbids' )
+ );
+ }
+
+ return $return;
}
/**
@@ -739,12 +778,12 @@ public function are_free_bids_allowed(): bool {
* @return int
*/
public function get_free_bids_available(): int {
- $free_bids = get_post_meta( $this->get_id(), Bids::FREE_BIDS_META_KEY, true );
+ $free_bids = get_post_meta( $this->get_id(), self::FREE_BIDS_META_KEY, true );
// Return the default value if we have no value.
if ( ! $free_bids && 0 !== $free_bids && '0' !== $free_bids ) {
$free_bids = goodbids()->get_config( 'auctions.default-free-bids' );
- update_post_meta( $this->get_id(), Bids::FREE_BIDS_META_KEY, $free_bids );
+ update_post_meta( $this->get_id(), self::FREE_BIDS_META_KEY, $free_bids );
}
return intval( $free_bids );
@@ -760,7 +799,7 @@ public function get_free_bids_available(): int {
* @return void
*/
public function update_free_bids( int $free_bids ): void {
- update_post_meta( $this->get_id(), Bids::FREE_BIDS_META_KEY, $free_bids );
+ update_post_meta( $this->get_id(), self::FREE_BIDS_META_KEY, $free_bids );
}
/**
@@ -770,14 +809,13 @@ public function update_free_bids( int $free_bids ): void {
*
* @param ?int $user_id
* @param string $details
- * @param string $type
* @param bool $notify_later
*
* @return bool
*/
- public function maybe_award_free_bid( ?int $user_id = null, string $details = '', string $type = FreeBid::TYPE_PAID_BID, bool $notify_later = false ): bool {
- $free_bids = $this->get_free_bids_available();
- if ( ! $free_bids ) {
+ public function maybe_award_free_bid( ?int $user_id = null, string $details = '', bool $notify_later = false ): bool {
+ $auction_free_bids = $this->get_free_bids_available();
+ if ( ! $auction_free_bids ) {
return false;
}
@@ -785,9 +823,10 @@ public function maybe_award_free_bid( ?int $user_id = null, string $details = ''
$user_id = get_current_user_id();
}
- if ( goodbids()->users->award_free_bid( $user_id, $this->get_id(), $type, $details, $notify_later ) ) {
- --$free_bids;
- $this->update_free_bids( $free_bids );
+ if ( goodbids()->free_bids->award( $user_id, $this->get_id(), FreeBid::TYPE_PAID_BID, $details, $notify_later ) ) {
+ // Update the Auction's available free bids.
+ --$auction_free_bids;
+ $this->update_free_bids( $auction_free_bids );
return true;
}
@@ -1191,7 +1230,7 @@ public function trigger_close(): void {
* @return bool
*/
public function end_triggered(): bool {
- return boolval( get_post_meta( $this->get_id(), self::AUCTION_CLOSE_META_KEY, true ) );
+ return boolval( get_post_meta( $this->get_id(), self::AUCTION_CLOSED_META_KEY, true ) );
}
/**
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/Auctions.php b/client-mu-plugins/goodbids/src/classes/Auctions/Auctions.php
index e88c90477..5089a444d 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/Auctions.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/Auctions.php
@@ -17,6 +17,7 @@
use WP_Post;
use WP_Query;
use WP_REST_Response;
+use WP_Screen;
/**
* Class for Auctions
@@ -770,8 +771,7 @@ public function should_hide_reward_product(): bool {
private function hide_auction_title(): void {
add_action(
'current_screen',
- function (): void {
- $screen = get_current_screen();
+ function ( WP_Screen $screen ): void {
if ( $this->get_post_type() !== $screen->post_type ) {
return;
}
@@ -802,8 +802,7 @@ function () {
);
add_action(
'current_screen',
- function (): void {
- $screen = get_current_screen();
+ function ( WP_Screen $screen ): void {
if ( $this->get_post_type() !== $screen->post_type ) {
return;
}
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/Bids.php b/client-mu-plugins/goodbids/src/classes/Auctions/Bids.php
index d1825422d..f1fd2877a 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/Bids.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/Bids.php
@@ -9,6 +9,8 @@
namespace GoodBids\Auctions;
use GoodBids\Frontend\Notices;
+use GoodBids\Users\FreeBid;
+use GoodBids\Users\FreeBids;
use GoodBids\Utilities\Log;
use WC_Data_Exception;
use WC_Product;
@@ -48,36 +50,6 @@ class Bids {
*/
const AUCTION_BID_VARIATION_META_KEY = '_gb_bid_variation_id';
- /**
- * @since 1.0.0
- * @var string
- */
- const FREE_BIDS_META_KEY = '_goodbids_free_bids';
-
- /**
- * @since 1.0.0
- * @var string
- */
- const FREE_BID_STATUS_ALL = 'all';
-
- /**
- * @since 1.0.0
- * @var string
- */
- const FREE_BID_STATUS_UNUSED = 'unused';
-
- /**
- * @since 1.0.0
- * @var string
- */
- const FREE_BID_STATUS_USED = 'used';
-
- /**
- * @since 1.0.0
- * @var string
- */
- const USE_FREE_BID_PARAM = 'use-free-bid';
-
/**
* Initialize Bids
*
@@ -515,7 +487,7 @@ public function get_place_bid_url( int $auction_id, bool $is_free_bid = false ):
$url = trailingslashit( get_permalink( $auction_id ) ) . self::PLACE_BID_SLUG . '/';
if ( $is_free_bid ) {
- $url = add_query_arg( self::USE_FREE_BID_PARAM, 1, $url );
+ $url = add_query_arg( FreeBids::USE_FREE_BID_PARAM, 1, $url );
}
return $url;
@@ -719,7 +691,7 @@ function ( int $order_id, int $auction_id ) {
// Do not award free bids if this order contains a free bid.
if ( goodbids()->woocommerce->orders->is_free_bid_order( $order_id ) ) {
// Reduce the Free Bid Count for the user.
- if ( goodbids()->users->redeem_free_bid( $auction_id, $order_id ) ) {
+ if ( goodbids()->free_bids->redeem( $auction_id, $order_id ) ) {
goodbids()->notices->add_notice( Notices::FREE_BID_REDEEMED );
}
return;
@@ -731,7 +703,7 @@ function ( int $order_id, int $auction_id ) {
$bid_order = wc_get_order( $order_id );
// Do not award a free bid if payment didn't go through.
- if ( $bid_order->needs_payment() ) {
+ if ( $bid_order->get_total( 'edit' ) > 0 && $bid_order->needs_payment() ) {
return;
}
@@ -747,7 +719,6 @@ function ( int $order_id, int $auction_id ) {
$auction->maybe_award_free_bid(
get_current_user_id(),
$details,
- FreeBid::TYPE_PAID_BID,
true
);
},
@@ -767,8 +738,7 @@ function () {
$type = FreeBid::TYPE_ADMIN_GRANT;
}
- $free_bids = goodbids()->users->get_free_bids( get_current_user_id(), Bids::FREE_BID_STATUS_UNUSED, $type );
- $do_update = false;
+ $free_bids = goodbids()->free_bids->get( get_current_user_id(), FreeBids::STATUS_UNUSED, $type );
foreach ( $free_bids as $free_bid ) {
if ( $free_bid->did_awarded_notification() ) {
@@ -776,15 +746,12 @@ function () {
}
$free_bid->mark_as_notified();
+ goodbids()->free_bids->update( get_current_user_id(), $free_bid->get_id(), $free_bid );
+
goodbids()->notices->add_notice( Notices::EARNED_FREE_BID );
- $do_update = true;
break;
}
-
- if ( $do_update ) {
- goodbids()->users->save_free_bids( get_current_user_id(), $free_bids );
- }
}
);
}
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/Cron.php b/client-mu-plugins/goodbids/src/classes/Auctions/Cron.php
index 125b3748f..68ce65660 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/Cron.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/Cron.php
@@ -9,7 +9,6 @@
namespace GoodBids\Auctions;
use DateInterval;
-use GoodBids\Core;
use GoodBids\Utilities\Log;
use WP_Query;
@@ -45,7 +44,7 @@ class Cron {
*/
public function __construct() {
// Disable Auctions on Main Site.
- if ( is_main_site() && ! Core::is_local_env() ) {
+ if ( is_main_site() ) {
return;
}
@@ -337,6 +336,10 @@ private function maybe_trigger_events(): void {
add_action(
'template_redirect',
function (): void {
+ if ( get_post_type() !== goodbids()->auctions->get_post_type() ) {
+ return;
+ }
+
$auction = goodbids()->auctions->get();
if ( ! $auction->is_valid() ) {
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/FreeBid.php b/client-mu-plugins/goodbids/src/classes/Auctions/FreeBid.php
index 74c8506e8..c65b649d8 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/FreeBid.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/FreeBid.php
@@ -1,7 +1,8 @@
set_auction_id( $auction_id_earned );
- }
-
- if ( ! $this->id ) {
- $this->id = uniqid( 'GBFB-' );
- }
-
- if ( ! $this->earned_date ) {
- $this->earned_date = current_time( 'Y-m-d H:i:s' );
- }
-
- return $this;
- }
-
- /**
- * Set the Auction ID
- *
- * @since 1.0.0
- *
- * @param int $auction_id
- *
- * @return FreeBid
- */
- public function set_auction_id( int $auction_id ): FreeBid {
- $this->auction_id_earned = $auction_id;
- return $this;
- }
-
- /**
- * Sets the status of the Free Bid.
- *
- * @since 1.0.0
- *
- * @param string $status
- *
- * @return FreeBid
- */
- public function set_status( string $status ): FreeBid {
- $this->status = $status;
- return $this;
- }
-
- /**
- * Returns the status of the Free Bid
- *
- * @since 1.0.0
- *
- * @return string
- */
- public function get_status(): string {
- return $this->status;
- }
-
- /**
- * Displays the status of the Free Bid
- *
- * @since 1.0.0
- *
- * @return void
- */
- public function display_status(): void {
- echo esc_html( ucwords( $this->get_status() ) );
- }
-
- /**
- * Sets the Free Earned Type.
- *
- * @since 1.0.0
- *
- * @param string $type
- *
- * @return FreeBid
- */
- public function set_type( string $type ): FreeBid {
- $this->type = $type;
- return $this;
- }
-
- /**
- * Returns the type of the Free Bid
- *
- * @since 1.0.0
- *
- * @return string
- */
- public function get_type(): string {
- if ( ! $this->type ) {
- return self::TYPE_PAID_BID;
- }
- return $this->type;
- }
-
- /**
- * Returns the type of the Free Bid for display
- *
- * @since 1.0.0
- *
- * @return string
- */
- public function get_type_display(): string {
- return ucwords( str_replace( '_', ' ', $this->get_type() ) );
- }
-
- /**
- * Displays the type of the Free Bid
- *
- * @since 1.0.0
- *
- * @return void
- */
- public function display_type(): void {
- echo esc_html( $this->get_type_display() );
- }
-
- /**
- * Get the type action performed to be awarded free bid.
- *
- * @since 1.0.0
- *
- * @return string
- */
- public function get_type_action(): string {
- if ( $this->get_type() === self::TYPE_REFERRAL ) {
- return __( 'Referral', 'goodbids' );
- }
-
- if ( $this->get_type() === self::TYPE_ADMIN_GRANT ) {
- return __( 'admin grant', 'goodbids' );
- }
-
- // Default to Bid.
- return __( 'Bid', 'goodbids' );
- }
-
- /**
- * Sets the Details for the Free Earned Bid.
- *
- * @since 1.0.0
- *
- * @param string $details
- *
- * @return FreeBid
- */
- public function set_details( string $details ): FreeBid {
- $this->details = $details;
- return $this;
- }
-
- /**
- * Get the Free Bid Details
- *
- * @since 1.0.0
- *
- * @return string
- */
- public function get_details(): string {
- if ( ! empty( $this->details ) ) {
- return $this->details;
- }
-
- if ( ! empty( $this->description ) ) {
- return $this->description;
- }
-
- return '';
- }
-
- /**
- * Display formatted Earned Date
- *
- * @since 1.0.0
- *
- * @param string $format
- *
- * @return void
- */
- public function display_earned_date( string $format = 'n/j/y g:i a' ): void {
- echo wp_kses_post( goodbids()->utilities->format_date_time( $this->earned_date, $format ) );
- }
-
- /**
- * Display formatted Earned Date
- *
- * @since 1.0.0
- *
- * @param string $format
- *
- * @return void
- */
- public function display_used_date( string $format = 'n/j/y g:i a' ): void {
- if ( ! $this->used_date ) {
- esc_html_e( 'N/A', 'goodbids' );
- return;
- }
-
- echo wp_kses_post( goodbids()->utilities->format_date_time( $this->used_date, $format ) );
- }
-
- /**
- * Display a link to an Auction by ID.
- *
- * @since 1.0.0
- *
- * @param ?string $title
- *
- * @return void
- */
- public function display_auction_link( ?string $title = '' ): void {
- if ( ! $this->auction_id_used || ! $this->site_id_used ) {
- esc_html_e( 'N/A', 'goodbids' );
- return;
- }
-
- goodbids()->sites->swap(
- function () use ( $title ) {
- printf(
- '%s (ID: %s)',
- esc_url( get_permalink( $this->auction_id_used ) ),
- $title ? esc_attr( $title ) : '',
- esc_html( get_the_title( $this->auction_id_used ) ),
- esc_html( $this->auction_id_used )
- );
- },
- $this->site_id_used
- );
- }
-
- /**
- * Redeem this Free Bid
- *
- * @since 1.0.0
- *
- * @param int $auction_id
- * @param int $order_id
- *
- * @return bool
- */
- public function redeem( int $auction_id, int $order_id ): bool {
- $order = wc_get_order( $order_id );
-
- // Verify order exists.
- if ( ! $order ) {
- return false;
- }
-
- if ( $this->get_status() !== Bids::FREE_BID_STATUS_UNUSED ) {
- return false;
- }
-
- $this->used_date = current_time( 'Y-m-d H:i:s' );
- $this->status = Bids::FREE_BID_STATUS_USED;
- $this->auction_id_used = $auction_id;
- $this->site_id_used = get_current_blog_id();
- $this->order_id_redeemed = $order->get_id();
- $this->bid_value = $order->get_subtotal();
-
- return true;
- }
-
- /**
- * Used to notify users of awarded free bids later then when they were awarded.
- *
- * @since 1.0.0
- *
- * @return bool
- */
- public function did_awarded_notification(): bool {
- return false !== $this->awarded_notification;
- }
-
- /**
- * Mark the Free Bid as Notified.
- *
- * @since 1.0.0
- *
- * @return void
- */
- public function mark_as_notified(): void {
- $this->awarded_notification = true;
- }
-}
+class FreeBid extends \GoodBids\Users\FreeBid {}
diff --git a/client-mu-plugins/goodbids/src/classes/Auctions/FundraisingFields.php b/client-mu-plugins/goodbids/src/classes/Auctions/FundraisingFields.php
index 901649398..9898e5a53 100644
--- a/client-mu-plugins/goodbids/src/classes/Auctions/FundraisingFields.php
+++ b/client-mu-plugins/goodbids/src/classes/Auctions/FundraisingFields.php
@@ -8,6 +8,8 @@
namespace GoodBids\Auctions;
+use WP_Screen;
+
/**
* Fundraising Fields Class
*
@@ -36,16 +38,10 @@ public function __construct() {
private function disable_fundraising_fields(): void {
add_action(
'current_screen',
- function(): void {
- if ( is_super_admin() ) {
- return;
- }
-
- $screen = get_current_screen();
- if ( goodbids()->auctions->get_post_type() !== $screen->id ) {
+ function( WP_Screen $screen ): void {
+ if ( goodbids()->auctions->get_post_type() !== $screen->id || is_super_admin() ) {
return;
}
-
?>
', esc_html( $post_id ) );
+ }
+ } elseif ( Request::FIELD_AUCTION === $column ) {
+ echo wp_kses_post( $request->get_auction_html() );
+ } elseif ( Request::FIELD_TYPE === $column ) {
+ echo esc_html( $request->get_field( Request::FIELD_TYPE ) );
+ } elseif ( Request::FIELD_NATURE === $column ) {
+ echo esc_html( $request->get_field( Request::FIELD_NATURE ) );
+ }
+ },
+ 10,
+ 2
+ );
+ }
+
+ /**
+ * Create a new support request
+ *
+ * @since 1.0.0
+ *
+ * @param array $post_data
+ *
+ * @return int|bool
+ */
+ public function create_request( array $post_data ): int|bool {
+ $request_id = wp_insert_post( $post_data );
+
+ if ( is_wp_error( $request_id ) ) {
+ Log::error( 'Error creating support request: ' . $request_id->get_error_message(), compact( 'post_data' ) );
+ return false;
+ }
+
+ if ( ! $request_id ) {
+ Log::error( 'Unknown error creating support request.', compact( 'post_data' ) );
+ return false;
+ }
+
+ return $request_id;
+ }
+
+ /**
+ * Check if submission was processed.
+ *
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ public function submission_processed(): bool {
+ return ! empty( $_GET[ self::FORM_SLUG ] ) && 'submitted' === $_GET[ self::FORM_SLUG ]; // phpcs:ignore
+ }
+
+ /**
+ * Check for a value.
+ *
+ * @since 1.0.0
+ *
+ * @param array $items
+ * @param array $form_data
+ *
+ * @return bool
+ */
+ private function has_value( array $items, array $form_data ): bool {
+ foreach ( $items as $item ) {
+ if ( ! empty( $item ) ) {
+ continue;
+ }
+
+ if ( in_array( $form_data[ $item ], [ '0', 0 ], true ) ) {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check all required fields.
+ *
+ * @since 1.0.0
+ *
+ * @param array $form_data
+ *
+ * @return bool
+ */
+ private function passed_validation( array $form_data ): bool {
+ foreach ( $this->get_fields() as $key => $field ) {
+ if ( empty( $field['required'] ) ) {
+ continue;
+ }
+
+ if ( 'dependencies' === $field['required'] && ! empty( $field['dependencies'] ) ) {
+ $required = array_keys( $field['dependencies'] );
+ if ( ! $this->has_value( $required, $form_data ) ) {
+ continue;
+ }
+ } elseif ( is_array( $field['required'] ) ) {
+ if ( ! $this->has_value( $field['required'], $form_data ) ) {
+ continue;
+ }
+ }
+
+ if ( $this->has_value( [ $key ], $form_data ) ) {
+ continue;
+ }
+
+ $this->error = sprintf(
+ /* translators: %s: Field Label */
+ __( 'The %s field is required.', 'goodbids' ),
+ $field['label']
+ );
+
+ break;
+ }
+
+ return empty( $this->error );
+ }
+
+ /**
+ * Get the Form Fields
+ *
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ public function get_fields(): array {
+ return $this->fields;
+ }
+
+ /**
+ * Get the Error
+ *
+ * @since 1.0.0
+ *
+ * @return ?string
+ */
+ public function get_error(): ?string {
+ return $this->error;
+ }
+
+ /**
+ * Populate the Auctions Select with the user's auctions
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function insert_auction_options(): void {
+ add_filter(
+ 'goodbids_support_request_form_fields',
+ function ( array $fields ): array {
+ if ( ! is_user_logged_in() || is_admin() ) {
+ return $fields;
+ }
+
+ $options = [];
+ $auctions = goodbids()->sites->get_user_participating_auctions();
+
+ foreach ( $auctions as $auction ) {
+ goodbids()->sites->swap(
+ function () use ( $auction, &$options ) {
+ $options[] = [
+ 'value' => $auction['site_id'] . '|' . $auction['auction_id'],
+ 'label' => get_the_title( $auction['auction_id'] ),
+ ];
+ },
+ $auction['site_id']
+ );
+ }
+
+ if ( empty( $options ) ) {
+ $fields[ Request::FIELD_AUCTION ]['options'] = [
+ [
+ 'value' => 'unknown',
+ 'label' => __( 'No auctions found. Select this to submit your request anyway.', 'goodbids' ),
+ ],
+ ];
+ return $fields;
+ }
+
+ $options = collect( $options )
+ ->sortBy( 'label' )
+ ->values()
+ ->all();
+
+ $fields[ Request::FIELD_AUCTION ]['options'] = $options;
+ $fields[ Request::FIELD_AUCTION ]['options'][] = [
+ 'value' => 'unlisted',
+ 'label' => __( 'The Auction is not listed.', 'goodbids' ),
+ ];
+
+ return $fields;
+ }
+ );
+ }
+
+ /**
+ * Populate the Bids Select with the user's bids
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function insert_bid_options(): void {
+ add_filter(
+ 'goodbids_support_request_form_fields',
+ function ( array $fields, array $form_data ): array {
+ if ( ! is_user_logged_in() || is_admin() ) {
+ return $fields;
+ }
+
+ $options = [];
+
+ if ( empty( $form_data[ Request::FIELD_AUCTION ] ) ) {
+ $fields[ Request::FIELD_BID ]['options'] = [
+ [
+ 'value' => '',
+ 'label' => __( 'Select an Auction first', 'goodbids' ),
+ ],
+ ];
+ return $fields;
+ }
+
+ list( $site_id, $auction_id ) = array_map( 'intval', explode( '|', $form_data[ Request::FIELD_AUCTION ] ) );
+ $bids = goodbids()->sites->get_user_bid_orders( get_current_user_id() );
+ $bids = collect( $bids )
+ ->filter(
+ fn ( $bid_data ) => $bid_data['site_id'] === $site_id
+ )
+ ->filter(
+ function ( $bid_data ) use ( $auction_id ) {
+ return goodbids()->sites->swap(
+ function () use ( $bid_data, $auction_id ) {
+ return goodbids()->woocommerce->orders->get_auction_id( $bid_data['order_id'] ) === $auction_id;
+ },
+ $bid_data['site_id']
+ );
+ }
+ )
+ ->values()
+ ->all();
+
+ if ( empty( $bids ) ) {
+ $fields[ Request::FIELD_BID ]['options'] = [
+ [
+ 'value' => '',
+ 'label' => __( 'No bids found. Select this to submit your request anyway.', 'goodbids' ),
+ ],
+ ];
+ return $fields;
+ }
+
+ foreach ( $bids as $bid_data ) {
+ goodbids()->sites->swap(
+ function () use ( $bid_data, &$options ) {
+ $order = wc_get_order( $bid_data['order_id'] );
+ $title = __( 'Bid Order #', 'goodbids' ) . $bid_data['order_id'];
+ $title .= $bid_data['order_id'];
+ $title .= ' (' . wp_strip_all_tags( wc_price( $order->get_total( 'edit' ) ) ) . ')';
+
+ $options[] = [
+ 'value' => $bid_data['site_id'] . '|' . $bid_data['order_id'],
+ 'label' => $title,
+ ];
+ },
+ $bid_data['site_id']
+ );
+ }
+
+ $fields[ Request::FIELD_BID ]['options'] = $options;
+ $fields[ Request::FIELD_BID ]['options'][] = [
+ 'value' => 'unlisted',
+ 'label' => __( 'The Bid Order is not listed.', 'goodbids' ),
+ ];
+
+ return $fields;
+ },
+ 10,
+ 2
+ );
+ }
+
+ /**
+ * Populate the Rewards Select with the user's bids
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function insert_reward_options(): void {
+ add_filter(
+ 'goodbids_support_request_form_fields',
+ function ( array $fields, array $form_data ): array {
+ if ( ! is_user_logged_in() || is_admin() ) {
+ return $fields;
+ }
+
+ $options = [];
+
+ if ( empty( $form_data[ Request::FIELD_AUCTION ] ) ) {
+ $fields[ Request::FIELD_REWARD ]['options'] = [
+ [
+ 'value' => '',
+ 'label' => __( 'Select an Auction first', 'goodbids' ),
+ ],
+ ];
+ return $fields;
+ }
+
+ list( $site_id, $auction_id ) = array_map( 'intval', explode( '|', $form_data[ Request::FIELD_AUCTION ] ) );
+ $rewards = goodbids()->sites->get_user_reward_orders( get_current_user_id() );
+ $rewards = collect( $rewards )
+ ->filter(
+ fn ( $reward_data ) => $reward_data['site_id'] === $site_id
+ )
+ ->filter(
+ fn ( $reward_data ) => goodbids()->sites->swap(
+ fn () => goodbids()->woocommerce->orders->get_auction_id( $reward_data['order_id'] ) === $auction_id,
+ $reward_data['site_id']
+ )
+ )
+ ->values()
+ ->all();
+
+ if ( empty( $rewards ) ) {
+ $fields[ Request::FIELD_REWARD ]['options'] = [
+ [
+ 'value' => 'unknown',
+ 'label' => __( 'No rewards found. Select this to submit your request anyway.', 'goodbids' ),
+ ],
+ ];
+ return $fields;
+ }
+
+ foreach ( $rewards as $reward_data ) {
+ goodbids()->sites->swap(
+ function () use ( $reward_data, &$options ) {
+ $order = wc_get_order( $reward_data['order_id'] );
+ $title = __( 'Reward Order #', 'goodbids' ) . $reward_data['order_id'];
+ foreach ( $order->get_items() as $item ) {
+ $product = wc_get_product( $item['product_id'] );
+
+ if ( $product ) {
+ $title = $product->get_title();
+ }
+ }
+
+ $options[] = [
+ 'value' => $reward_data['site_id'] . '|' . $reward_data['order_id'],
+ 'label' => $title,
+ ];
+ },
+ $reward_data['site_id']
+ );
+ }
+
+ $fields[ Request::FIELD_REWARD ]['options'] = $options;
+ $fields[ Request::FIELD_REWARD ]['options'][] = [
+ 'value' => 'unlisted',
+ 'label' => __( 'The Reward Order is not listed.', 'goodbids' ),
+ ];
+
+ return $fields;
+ },
+ 10,
+ 2
+ );
+ }
+
+ /**
+ * Update fields with dependencies
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function modify_for_dependencies(): void {
+ add_filter(
+ 'goodbids_support_request_form_fields',
+ function ( array $fields, array $form_data ): array {
+ return $this->handle_dependencies( $fields, $form_data );
+ },
+ 10,
+ 2
+ );
+ }
+
+ /**
+ * Hide fields based on dependencies
+ *
+ * @since 1.0.0
+ *
+ * @param array $fields
+ * @param array $form_data
+ *
+ * @return array
+ */
+ private function handle_dependencies( array $fields, array $form_data ): array {
+ foreach ( $fields as $key => &$field ) {
+ if ( ! empty( $field['options'] ) ) {
+ $field['options'] = $this->handle_dependencies( $field['options'], $form_data );
+ }
+
+ if ( empty( $field['dependencies'] ) ) {
+ continue;
+ }
+
+ $dependencies = $field['dependencies'];
+
+ foreach ( $dependencies as $dependency_key => $dependency_value ) {
+ if ( empty( $form_data[ $dependency_key ] ) ) {
+ $fields[ $key ]['hidden'] = true;
+ break;
+ }
+
+ if ( is_null( $dependency_value ) ) {
+ continue;
+ }
+
+ if ( is_string( $dependency_value ) && $form_data[ $dependency_key ] === $dependency_value ) {
+ continue;
+ }
+
+ if ( is_array( $dependency_value ) && in_array( $form_data[ $dependency_key ], $dependency_value, true ) ) {
+ continue;
+ }
+
+ $fields[ $key ]['hidden'] = true;
+ break;
+ }
+ }
+
+ return $fields;
+ }
+
+ /**
+ * Initialize the form fields
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function init_fields(): void {
+ $init_fields = function () {
+ $current_url = $this->get_current_url();
+ $form_data = $this->get_form_data();
+
+ // Dynamic Dependencies for the 2 Request Fields
+ $extra_deps = [
+ Request::FIELD_TYPE => null,
+ ];
+
+ $type = ! empty( $form_data[ Request::FIELD_TYPE ] ) ? $form_data[ Request::FIELD_TYPE ] : null;
+
+ if ( in_array( $type, [ Request::TYPE_BID, Request::TYPE_REWARD ], true ) ) {
+ $extra_deps[ Request::FIELD_AUCTION ] = null;
+
+ if ( $type === Request::TYPE_BID ) {
+ $extra_deps[ Request::FIELD_BID ] = null;
+ } elseif ( $type === Request::TYPE_REWARD ) {
+ $extra_deps[ Request::FIELD_REWARD ] = null;
+ }
+ }
+
+ $hx_target = '#gb-support-form-target';
+ $hx_spinner = 'form[data-form-spinner]';
+
+ /**
+ * Adjust the Support Request Form Fields
+ *
+ * @since 1.0.0
+ *
+ * @param array $fields
+ * @param array $form_data
+ */
+ $this->fields = apply_filters(
+ 'goodbids_support_request_form_fields',
+ [
+ Request::FIELD_TYPE => [
+ 'type' => 'select',
+ 'label' => __( 'What do you need help with?', 'goodbids' ),
+ 'required' => true,
+ 'options' => [
+ Request::TYPE_BID => __( 'A bid I placed', 'goodbids' ),
+ Request::TYPE_REWARD => __( 'A reward I claimed', 'goodbids' ),
+ Request::TYPE_AUCTION => __( 'An auction', 'goodbids' ),
+ Request::TYPE_OTHER => __( 'Something else', 'goodbids' ),
+ ],
+ 'attr' => [
+ 'hx-trigger' => 'change',
+ 'hx-get' => $current_url,
+ 'hx-target' => $hx_target,
+ 'hx-select' => $hx_target,
+ 'hx-indicator' => $hx_spinner,
+ ],
+ ],
+ Request::FIELD_AUCTION => [
+ 'type' => 'select',
+ 'label' => __( 'Which Auction are you referencing?', 'goodbids' ),
+ 'options' => [
+ 'Auction 1',
+ 'Auction 2',
+ 'Auction 3',
+ ],
+ 'attr' => [
+ 'hx-trigger' => 'change',
+ 'hx-get' => $current_url,
+ 'hx-target' => $hx_target,
+ 'hx-select' => $hx_target,
+ 'hx-indicator' => $hx_spinner,
+ ],
+ 'required' => 'dependencies',
+ 'dependencies' => [
+ Request::FIELD_TYPE => [ Request::TYPE_BID, Request::TYPE_REWARD, Request::TYPE_AUCTION ],
+ ],
+ ],
+ Request::FIELD_BID => [
+ 'type' => 'select',
+ 'label' => __( 'Which bid are you referencing?', 'goodbids' ),
+ 'options' => [
+ 'Bid 1',
+ 'Bid 2',
+ 'Bid 3',
+ ],
+ 'required' => 'dependencies',
+ 'dependencies' => [
+ Request::FIELD_TYPE => Request::TYPE_BID,
+ Request::FIELD_AUCTION => null,
+ ],
+ 'attr' => [
+ 'hx-trigger' => 'change',
+ 'hx-get' => $current_url,
+ 'hx-target' => $hx_target,
+ 'hx-select' => $hx_target,
+ 'hx-indicator' => $hx_spinner,
+ ],
+ ],
+ Request::FIELD_REWARD => [
+ 'type' => 'select',
+ 'label' => __( 'Which reward are you referencing?', 'goodbids' ),
+ 'options' => [
+ 'Reward 1',
+ 'Reward 2',
+ 'Reward 3',
+ ],
+ 'required' => 'dependencies',
+ 'dependencies' => [
+ Request::FIELD_TYPE => Request::TYPE_REWARD,
+ Request::FIELD_AUCTION => null,
+ ],
+ 'attr' => [
+ 'hx-trigger' => 'change',
+ 'hx-get' => $current_url,
+ 'hx-target' => $hx_target,
+ 'hx-select' => $hx_target,
+ 'hx-indicator' => $hx_spinner,
+ ],
+ ],
+ Request::FIELD_NATURE => [
+ 'type' => 'select',
+ 'label' => __( 'What is the nature of your request?', 'goodbids' ),
+ 'options' => [
+ [
+ 'label' => __( 'Report an issue', 'goodbids' ),
+ 'value' => __( 'Issue', 'goodbids' ),
+ ],
+ [
+ 'label' => __( 'Request a refund', 'goodbids' ),
+ 'value' => __( 'Refund', 'goodbids' ),
+ 'dependencies' => [
+ Request::FIELD_TYPE => Request::TYPE_BID,
+ ],
+ ],
+ [
+ 'label' => __( 'Ask a question', 'goodbids' ),
+ 'value' => __( 'Question', 'goodbids' ),
+ ],
+ ],
+ 'required' => 'dependencies',
+ 'dependencies' => $extra_deps,
+ ],
+ Request::FIELD_REQUEST => [
+ 'type' => 'textarea',
+ 'label' => __( 'Please describe your request', 'goodbids' ),
+ 'placeholder' => __( 'Tell us what\'s going on', 'goodbids' ),
+ 'required' => 'dependencies',
+ 'dependencies' => $extra_deps,
+ ],
+ ],
+ $form_data
+ );
+ };
+
+ add_action( 'template_redirect', $init_fields );
+ add_action( 'admin_init', $init_fields );
+ }
+
+ /**
+ * Get the Current URL with Query Parameters added.
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ private function get_current_url(): string {
+ global $wp;
+ $current_url = home_url( $wp->request );
+ $form_data = $this->get_form_data();
+ $append_fields = [
+ Request::FIELD_TYPE,
+ Request::FIELD_AUCTION,
+ Request::FIELD_BID,
+ Request::FIELD_REWARD,
+ ];
+
+ foreach ( $append_fields as $data_field ) {
+ if ( ! empty( $form_data[ $data_field ] ) ) {
+ $current_url = add_query_arg( $data_field, urlencode( $form_data[ $data_field ] ), $current_url );
+ }
+ }
+
+ return $current_url;
+ }
+
+ /**
+ * Get pre-populated field values from URL.
+ *
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ private function get_url_vars(): array {
+ $form_data = [];
+ $query_vars = [
+ 'type' => Request::FIELD_TYPE,
+ 'auction' => Request::FIELD_AUCTION,
+ 'bid' => Request::FIELD_BID,
+ 'reward' => Request::FIELD_REWARD,
+ ];
+
+ // Check both values for data.
+ foreach ( $query_vars as $query_var => $field_key ) {
+ if ( ! empty( $_GET[ $query_var ] ) ) { // phpcs:ignore
+ $form_data[ $field_key ] = sanitize_text_field( $_GET[ $query_var ] ); // phpcs:ignore
+ }
+ if ( ! empty( $_GET[ $field_key ] ) ) { // phpcs:ignore
+ $form_data[ $field_key ] = sanitize_text_field( $_GET[ $field_key ] ); // phpcs:ignore
+ }
+ }
+
+ return $form_data;
+ }
+
+ /**
+ * Grab the posted form data.
+ *
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ public function get_form_data(): array {
+ $form_data = $this->get_url_vars();
+
+ if ( ! $this->verify_nonce() || empty( $this->fields ) ) {
+ return $form_data;
+ }
+
+ foreach ( $this->get_fields() as $key => $field ) {
+ $form_data[ $key ] = ! empty( $_POST[ $key ] ) ? sanitize_text_field( $_POST[ $key ] ) : ''; // phpcs:ignore
+ }
+
+ return $form_data;
+ }
+
+ /**
+ * Verify the Nonce
+ *
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ public function verify_nonce(): bool {
+ if ( empty( $_POST[ self::FORM_NONCE_ACTION . '_nonce' ] ) ) {
+ return false;
+ }
+
+ if ( ! wp_verify_nonce( sanitize_text_field( $_POST[ self::FORM_NONCE_ACTION . '_nonce' ] ), self::FORM_NONCE_ACTION ) ) { // phpcs:ignore
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Process the Form Submission
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function handle_form_submission(): void {
+ add_action(
+ 'template_redirect',
+ function () {
+ if ( ! $this->verify_nonce() ) { // phpcs:ignore
+ return;
+ }
+
+ $form_data = $this->get_form_data();
+
+ if ( ! $this->passed_validation( $form_data ) ) {
+ return;
+ }
+
+ $metadata = [
+ Request::FIELD_USER_ID => get_current_user_id(),
+ Request::FIELD_TYPE => $form_data[ Request::FIELD_TYPE ] ?? '',
+ Request::FIELD_AUCTION => $form_data[ Request::FIELD_AUCTION ] ?? '',
+ Request::FIELD_BID => $form_data[ Request::FIELD_BID ] ?? '',
+ Request::FIELD_REWARD => $form_data[ Request::FIELD_REWARD ] ?? '',
+ Request::FIELD_NATURE => $form_data[ Request::FIELD_NATURE ] ?? '',
+ Request::FIELD_REQUEST => $form_data[ Request::FIELD_REQUEST ] ?? '',
+ ];
+
+ $user = new Bidder();
+ $title = sprintf(
+ '%s %s %s',
+ $metadata[ Request::FIELD_TYPE ],
+ __( 'Request from', 'goodbids' ),
+ $user->get_username()
+ );
+
+ $support_post = [
+ 'post_type' => $this->get_post_type(),
+ 'author' => 1,
+ 'post_title' => $title,
+ 'post_status' => 'private',
+ 'meta_input' => $metadata,
+ ];
+
+ $request_id = $this->create_request( $support_post );
+ if ( ! $request_id ) {
+ return;
+ }
+
+ /**
+ * Fires after a support request is received.
+ *
+ * @since 1.0.0
+ *
+ * @param int $request_id The ID of the support request.
+ */
+ do_action( 'goodbids_support_request_received', $request_id );
+
+ global $wp;
+ $redirect = trailingslashit( home_url( $wp->request ) );
+ $redirect = add_query_arg( self::FORM_SLUG, 'submitted', $redirect );
+ wp_safe_redirect( $redirect );
+ exit;
+ },
+ 100
+ );
+ }
+
+ /**
+ * Get the Support Request form URL
+ *
+ * @since 1.0.0
+ *
+ * @param array $args
+ *
+ * @return string
+ */
+ public function get_form_url( array $args = [] ): string {
+ $page_id = get_option( Sites::SUPPORT_OPTION );
+
+ if ( ! $page_id ) {
+ $existing = get_page_by_path( self::FORM_SLUG );
+
+ if ( ! $existing ) {
+ return '#' . self::FORM_SLUG;
+ }
+
+ $page_id = $existing->ID;
+ update_option( Sites::SUPPORT_OPTION, $page_id );
+ }
+
+ $url = get_permalink( $page_id );
+
+ if ( empty( $args ) ) {
+ return $url;
+ }
+
+ foreach ( $args as $arg => $val ) {
+ $url = add_query_arg( $arg, $val, $url );
+ }
+
+ return $url;
+ }
+
+ /**
+ * Get the number of unread support requests
+ *
+ * @since 1.0.0
+ *
+ * @return int
+ */
+ public function get_unread_count(): int {
+ $args = [
+ 'post_type' => self::POST_TYPE,
+ 'post_status' => 'private',
+ 'posts_per_page' => -1,
+ 'fields' => 'ids',
+ 'meta_key' => Request::READ_DATE_META_KEY,
+ 'meta_compare' =>'NOT EXISTS',
+ ];
+
+ $unread = new \WP_Query( $args );
+ return $unread->found_posts;
+ }
+
+ /**
+ * Mark a Request as read
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function handle_mark_as_read(): void {
+ add_action(
+ 'current_screen',
+ function ( WP_Screen $screen ) {
+ if ( self::POST_TYPE !== $screen->id || empty( $_GET['post'] ) ) { // phpcs:ignore
+ return;
+ }
+
+ $request_id = absint( sanitize_text_field( $_GET['post'] ) ); // phpcs:ignore
+ $request = new Request( $request_id );
+
+ if ( ! $request->is_valid() ) {
+ return;
+ }
+
+ if ( $request->is_unread() ) {
+ $request->mark_as_read();
+ }
+ }
+ );
+ }
+
+ /**
+ * Display the unread count in the WP Admin menu
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function display_unread_count(): void {
+ add_action(
+ 'admin_menu',
+ function () {
+ global $menu;
+
+ $unread_count = $this->get_unread_count();
+
+ // Loop through the menu items
+ foreach ( $menu as $key => $value ) {
+ // Check if the menu item is for our post type
+ if ( 'edit.php?post_type=' . self::POST_TYPE !== $value[2] ) {
+ continue;
+ }
+
+ // If there are unread items, add the count to the menu item title
+ if ( $unread_count > 0 ) {
+ $menu[ $key ][0] .= ' ' . esc_html( $unread_count ) . ''; // phpcs:ignore
+ }
+ break;
+ }
+ }
+ );
+ }
+}
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Auctions.php b/client-mu-plugins/goodbids/src/classes/Network/Auctions.php
index dcc1a3963..3664efab0 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Auctions.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Auctions.php
@@ -9,6 +9,7 @@
namespace GoodBids\Network;
use GoodBids\Admin\ScreenOptions;
+use WP_Screen;
/**
* Network Admin Auctions Class
@@ -71,14 +72,12 @@ function () {
add_action(
'current_screen',
- function () {
- $current_screen = get_current_screen();
-
- if ( ! str_contains( $current_screen->id, self::PAGE_SLUG ) ) {
+ function ( WP_Screen $screen ) {
+ if ( ! str_contains( $screen->id, self::PAGE_SLUG ) ) {
return;
}
- $this->screen_options->init( $current_screen->id );
+ $this->screen_options->init( $screen->id );
}
);
}
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Bidders.php b/client-mu-plugins/goodbids/src/classes/Network/Bidders.php
index c4a542a18..aaa8191dd 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Bidders.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Bidders.php
@@ -9,6 +9,7 @@
namespace GoodBids\Network;
use GoodBids\Admin\ScreenOptions;
+use WP_Screen;
/**
* Network Admin Bidders Class
@@ -71,14 +72,12 @@ function () {
add_action(
'current_screen',
- function () {
- $current_screen = get_current_screen();
-
- if ( ! str_contains( $current_screen->id, self::PAGE_SLUG ) ) {
+ function ( WP_Screen $screen ) {
+ if ( ! str_contains( $screen->id, self::PAGE_SLUG ) ) {
return;
}
- $this->screen_options->init( $current_screen->id );
+ $this->screen_options->init( $screen->id );
}
);
}
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Logs.php b/client-mu-plugins/goodbids/src/classes/Network/Logs.php
index 6c4000d53..40fee864c 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Logs.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Logs.php
@@ -222,7 +222,7 @@ function() {
$file_path = Log::get_logs_dir() . $file_name;
if ( ! file_exists( $file_path ) ) {
- wp_die( 'Error: File not found.' );
+ goodbids()->utilities->die( esc_html__( 'Error: File not found.', 'goodbids' ) );
}
header( 'Content-Description: File Transfer' );
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Network.php b/client-mu-plugins/goodbids/src/classes/Network/Network.php
index 00c5fac97..da1b380b5 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Network.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Network.php
@@ -64,7 +64,6 @@ public function __construct() {
$this->invoices = new Invoices();
$this->auctions = new Auctions();
$this->bidders = new Bidders();
-
$this->logs = new Logs();
// Setup API Endpoints.
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Nonprofit.php b/client-mu-plugins/goodbids/src/classes/Network/Nonprofit.php
index 3669bd1ac..1e121ada3 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Nonprofit.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Nonprofit.php
@@ -76,7 +76,7 @@ public function get_id(): int {
* @return bool
*/
public function is_valid(): bool {
- return (bool) $this->site;
+ return ! is_null( $this->site );
}
/**
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Nonprofits.php b/client-mu-plugins/goodbids/src/classes/Network/Nonprofits.php
index 39bf42567..fdfd4299b 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Nonprofits.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Nonprofits.php
@@ -9,6 +9,7 @@
namespace GoodBids\Network;
use GoodBids\Admin\ScreenOptions;
+use WP_Screen;
/**
* Network Admin Nonprofits Class
@@ -96,14 +97,12 @@ function () {
add_action(
'current_screen',
- function () {
- $current_screen = get_current_screen();
-
- if ( ! str_contains( $current_screen->id, self::PAGE_SLUG ) ) {
+ function ( WP_Screen $screen ) {
+ if ( ! str_contains( $screen->id, self::PAGE_SLUG ) ) {
return;
}
- $this->screen_options->init( $current_screen->id );
+ $this->screen_options->init( $screen->id );
}
);
}
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Settings.php b/client-mu-plugins/goodbids/src/classes/Network/Settings.php
index 52cd0ccc2..e89d1703c 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Settings.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Settings.php
@@ -234,7 +234,7 @@ private function is_overridden( string $key, mixed $config_value = null ): bool
$stored = boolval( $stored );
}
- return $stored_has_value && $stored !== $config_value;
+ return $stored_has_value && $stored != $config_value;
}
/**
diff --git a/client-mu-plugins/goodbids/src/classes/Network/Sites.php b/client-mu-plugins/goodbids/src/classes/Network/Sites.php
index 9607a49d8..c79848702 100644
--- a/client-mu-plugins/goodbids/src/classes/Network/Sites.php
+++ b/client-mu-plugins/goodbids/src/classes/Network/Sites.php
@@ -12,6 +12,7 @@
use GoodBids\Auctions\Auction;
use GoodBids\Auctions\Bids;
use GoodBids\Auctions\Rewards;
+use GoodBids\Frontend\SupportRequest;
use GoodBids\Nonprofits\Verification;
use GoodBids\Users\Permissions;
use GoodBids\Utilities\Log;
@@ -46,6 +47,12 @@ class Sites {
*/
const AUCTIONS_OPTION = 'gb_auctions_page';
+ /**
+ * @since 1.0.0
+ * @var string
+ */
+ const SUPPORT_OPTION = 'gb_support_page';
+
/**
* @since 1.0.0
* @var string
@@ -70,11 +77,16 @@ public function __construct() {
// New Site Initialization
$this->activate_child_theme_on_new_site();
+ $this->set_default_posts_per_page();
+
+ // Create new pages on new sites.
$this->create_about_page();
+ $this->create_support_page();
$this->create_all_auctions_page();
+
+ // Delete Sample content
$this->delete_sample_page();
$this->delete_sample_post();
- $this->set_default_posts_per_page();
// Lock down the block editor.
$this->lock_block_editor();
@@ -474,6 +486,48 @@ function (): void {
);
}
+ /**
+ * Creates the Support Request page
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function create_support_page(): void {
+ add_action(
+ 'goodbids_initialize_site',
+ function (): void {
+ $page_slug = SupportRequest::FORM_SLUG;
+ $existing = get_option( self::SUPPORT_OPTION );
+
+ // Make sure it doesn't already exist.
+ if ( $existing || get_page_by_path( $page_slug ) ) {
+ return;
+ }
+
+ $nonprofit = new Nonprofit( get_current_blog_id() );
+ $page_args = [
+ 'post_title' => __( 'Request Support from', 'goodbids' ) . ' ' . $nonprofit->get_name() ,
+ 'post_content' => goodbids()->get_view( 'patterns/template-support-request-page.php' ),
+ 'post_type' => 'page',
+ 'post_status' => 'publish',
+ 'post_author' => 1,
+ 'post_name' => $page_slug,
+ ];
+
+ $page_id = wp_insert_post( $page_args );
+
+ if ( is_wp_error( $page_id ) ) {
+ Log::error( $page_id->get_error_message() );
+ return;
+ }
+
+ update_option( self::SUPPORT_OPTION, $page_id );
+ },
+ 105
+ );
+ }
+
/**
* Create the Explore Auctions page and sets the pattern template
*
diff --git a/client-mu-plugins/goodbids/src/classes/Nonprofits/Invoices.php b/client-mu-plugins/goodbids/src/classes/Nonprofits/Invoices.php
index 8b603ff6a..81311112c 100644
--- a/client-mu-plugins/goodbids/src/classes/Nonprofits/Invoices.php
+++ b/client-mu-plugins/goodbids/src/classes/Nonprofits/Invoices.php
@@ -81,7 +81,7 @@ public function __construct() {
// Disable Bulk Actions.
$this->disable_bulk_actions();
- // Add custom Admin Columns for Watchers.
+ // Add custom Admin Columns.
$this->add_admin_columns();
// Generate Invoice on Auction Close.
diff --git a/client-mu-plugins/goodbids/src/classes/Nonprofits/Verification.php b/client-mu-plugins/goodbids/src/classes/Nonprofits/Verification.php
index 366ac69fb..dd5d79374 100644
--- a/client-mu-plugins/goodbids/src/classes/Nonprofits/Verification.php
+++ b/client-mu-plugins/goodbids/src/classes/Nonprofits/Verification.php
@@ -830,7 +830,7 @@ function (): void {
}
if ( ! $this->is_verified( get_current_blog_id() ) ) {
- wp_die( esc_html__( 'This site must be verified first.', 'goodbids' ) );
+ goodbids()->utilities->die( __( 'This site must be verified first.', 'goodbids' ) );
}
}
);
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce.php
index 369f4ed01..6d767b2dc 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce.php
@@ -157,9 +157,6 @@ public function __construct() {
$this->modify_login_page();
$this->modify_register_page();
- // Limit access to pages
- $this->limit_access_to_pages();
-
// Skip some of the Setup Tasks
$this->skip_setup_tasks();
}
@@ -600,64 +597,6 @@ function () {
);
}
- /**
- * Limit access from WooCommerce pages for non-Super Admins.
- *
- * @since 1.0.0
- *
- * @return void
- */
- private function limit_access_to_pages(): void {
- $pages = array_filter(
- [
- intval( get_option( 'woocommerce_cart_page_id' ) ),
- intval( get_option( 'woocommerce_checkout_page_id' ) ),
- intval( get_option( 'woocommerce_myaccount_page_id' ) ),
- intval( get_option( 'woocommerce_shop_page_id' ) ),
- intval( get_option( 'woocommerce_view_order_page_id' ) ),
- intval( get_option( 'woocommerce_authentication_page_id' ) ),
- ]
- );
-
- // Block access to Specific Pages
- add_filter(
- 'user_has_cap',
- function ( array $all_caps, array $caps, array $args ) use ( $pages ) {
- if ( is_super_admin() ) {
- return $all_caps;
- }
-
- $post_id = get_the_ID();
-
- if ( ! $post_id && isset( $args[2] ) ) {
- $post_id = $args[2];
- }
-
- if ( ! $post_id || 'page' !== get_post_type( $post_id ) ) {
- return $all_caps;
- }
-
- if ( ! in_array( $post_id, $pages, true ) ) {
- return $all_caps;
- }
-
- $all_caps['publish_pages'] = false;
- $all_caps['edit_pages'] = false;
- $all_caps['edit_others_pages'] = false;
- $all_caps['edit_published_pages'] = false;
- $all_caps['edit_private_pages'] = false;
- $all_caps['delete_pages'] = false;
- $all_caps['delete_private_pages'] = false;
- $all_caps['delete_others_pages'] = false;
- $all_caps['delete_published_pages'] = false;
-
- return $all_caps;
- },
- 10,
- 3
- );
- }
-
/**
* Skip setup tasks
*
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Account.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Account.php
index a57945ed2..aa7d22fc0 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Account.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Account.php
@@ -147,7 +147,7 @@ private function add_free_bids_tab(): void {
add_filter(
'goodbids_account_' . self::FREE_BIDS_SLUG . '_args',
function ( $args ) {
- $args['free_bids'] = goodbids()->users->get_free_bids();
+ $args['free_bids'] = goodbids()->free_bids->get();
return $args;
}
);
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Admin.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Admin.php
index d957f6706..89b9ecff7 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Admin.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Admin.php
@@ -10,6 +10,7 @@
use GoodBids\Utilities\Log;
use WP_Post;
+use WP_Screen;
/**
* Class for Admin Methods
@@ -38,6 +39,9 @@ public function __construct() {
// Remove WooCommerce Features on Main site
$this->main_site_cleanup();
+
+ // Limit access to pages
+ $this->limit_access_to_pages();
}
/**
@@ -50,9 +54,7 @@ public function __construct() {
private function add_auction_meta_box(): void {
add_action(
'current_screen',
- function (): void {
- $screen = get_current_screen();
-
+ function ( WP_Screen $screen ): void {
if ( 'woocommerce_page_wc-orders' !== $screen->id ) {
return;
}
@@ -296,6 +298,10 @@ function ( string $enabled ): string {
add_filter(
'woocommerce_settings_tabs_array',
function ( array $tabs ): array {
+ if ( ! is_main_site() ) {
+ return $tabs;
+ }
+
unset( $tabs['products'] );
unset( $tabs['tax'] );
unset( $tabs['shipping'] );
@@ -305,4 +311,31 @@ function ( array $tabs ): array {
100
);
}
+
+ /**
+ * Limit access from WooCommerce pages
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function limit_access_to_pages(): void {
+ add_filter(
+ 'goodbids_restrict_pages',
+ function ( array $pages ): array {
+ $wc_pages = array_filter(
+ [
+ intval( get_option( 'woocommerce_cart_page_id' ) ),
+ intval( get_option( 'woocommerce_checkout_page_id' ) ),
+ intval( get_option( 'woocommerce_myaccount_page_id' ) ),
+ intval( get_option( 'woocommerce_shop_page_id' ) ),
+ intval( get_option( 'woocommerce_view_order_page_id' ) ),
+ intval( get_option( 'woocommerce_authentication_page_id' ) ),
+ ]
+ );
+
+ return array_merge( $pages, $wc_pages );
+ }
+ );
+ }
}
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Cart.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Cart.php
index 8cbcee007..6d884d4a5 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Cart.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Cart.php
@@ -10,10 +10,8 @@
use GoodBids\Auctions\Bids;
use GoodBids\Auctions\Rewards;
-use GoodBids\Frontend\Notices;
use GoodBids\Plugins\WooCommerce;
use WC_Order_Item_Product;
-use WC_Product;
/**
* Class for Cart Methods
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Checkout.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Checkout.php
index e906726e6..1e110ffd0 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Checkout.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Checkout.php
@@ -138,7 +138,7 @@ function ( $order, $request = [] ) {
}
// Make sure the current user has available Free Bids.
- if ( ! goodbids()->users->get_available_free_bid_count() ) {
+ if ( ! goodbids()->free_bids->get_available_count() ) {
goodbids()->notices->add_notice( Notices::NO_AVAILABLE_FREE_BIDS );
return;
}
@@ -198,7 +198,7 @@ function ( $order_id ): void {
$order = wc_get_order( $order_id );
- if ( $order->needs_payment() ) {
+ if ( $order->get_total( 'edit' ) > 0 && $order->needs_payment() ) {
return;
}
@@ -230,9 +230,9 @@ function ( string $block_content, array $block ): string {
$nonprofit = new Nonprofit( get_current_blog_id() );
$block_content .= sprintf(
- '%s $%s %s %s. %s
',
+ '%s %s %s %s. %s
',
__( 'By placing this bid, you are making a donation for your full bid amount of', 'goodbids' ),
- esc_html( $bid_amount ),
+ wp_kses_post( wc_price( $bid_amount ) ),
__( 'to', 'goodbids' ),
esc_html( $nonprofit->get_name() ),
__( 'This is a non-refundable donation, and is in addition to any previous donations you\'ve made in this auction.', 'goodbids' )
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Coupons.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Coupons.php
index 26aaa21f1..452ed12f5 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Coupons.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Coupons.php
@@ -9,12 +9,10 @@
namespace GoodBids\Plugins\WooCommerce;
use GoodBids\Auctions\Auction;
-use GoodBids\Auctions\Bids;
-use GoodBids\Auctions\Rewards;
use GoodBids\Frontend\Notices;
+use GoodBids\Users\FreeBids;
use GoodBids\Utilities\Log;
use WC_Coupon;
-use WC_Product;
/**
* Class for Coupons Functionality
@@ -191,7 +189,7 @@ private function apply_cart_coupons(): void {
add_action(
'goodbids_place_bid',
function ( int $auction_id, int $product_id, int $variation_id ): void {
- if ( empty( $_REQUEST[ Bids::USE_FREE_BID_PARAM ] ) ) { // phpcs:ignore
+ if ( empty( $_REQUEST[ FreeBids::USE_FREE_BID_PARAM ] ) ) { // phpcs:ignore
return;
}
@@ -202,7 +200,7 @@ function ( int $auction_id, int $product_id, int $variation_id ): void {
return;
}
- if ( ! goodbids()->users->get_available_free_bid_count() ) {
+ if ( ! goodbids()->free_bids->get_available_count() ) {
goodbids()->notices->add_notice( Notices::NO_AVAILABLE_FREE_BIDS );
return;
}
@@ -246,7 +244,7 @@ private function apply_the_coupon_code( string $coupon_code, Auction $auction, s
goodbids()->notices->add_notice( Notices::GET_REWARD_COUPON_ERROR );
add_filter(
$redirect_hook,
- function ( $redirect_url ) use ( $auction ) {
+ function () use ( $auction ) {
return $auction->get_url();
}
);
@@ -269,7 +267,7 @@ function ( $redirect_url ) use ( $auction ) {
add_filter(
$redirect_hook,
- function ( $redirect_url ) use ( $auction ) {
+ function () use ( $auction ) {
return $auction->get_url();
}
);
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails.php
index 63759d125..c5aface2b 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails.php
@@ -19,6 +19,7 @@
use GoodBids\Plugins\WooCommerce\Emails\AuctionSummaryAdmin;
use GoodBids\Plugins\WooCommerce\Emails\AuctionWinnerConfirmation;
use GoodBids\Plugins\WooCommerce\Emails\FreeBidEarned;
+use GoodBids\Plugins\WooCommerce\Emails\SupportRequest;
/**
* Class for Email functions
@@ -101,6 +102,7 @@ public function load_email_classes(): void {
'AuctionSummaryAdmin' => new AuctionSummaryAdmin(),
'AuctionWinnerConfirmation' => new AuctionWinnerConfirmation(),
'FreeBidEarned' => new FreeBidEarned(),
+ 'SupportRequest' => new SupportRequest(),
];
}
@@ -120,6 +122,8 @@ private function load_wc_email_class(): bool {
}
require_once $wc_email_path;
+
+ \WC_Emails::instance();
}
return true;
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/Email.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/Email.php
index 617cd0d5b..e9bde19b0 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/Email.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/Email.php
@@ -11,7 +11,8 @@
defined( 'ABSPATH' ) || exit;
use GoodBids\Auctions\Auction;
-use GoodBids\Auctions\FreeBid;
+use GoodBids\Frontend\Request;
+use GoodBids\Users\FreeBid;
use GoodBids\Users\Referrals\Referrer;
use WC_Email;
use WC_Order;
@@ -49,6 +50,14 @@ class Email extends WC_Email {
*/
protected bool $admin_email = false;
+ /**
+ * If email is sent to Super Admins.
+ *
+ * @since 1.0.0
+ * @var bool
+ */
+ protected bool $super_admins_email = false;
+
/**
* If email is sent to Bidders.
*
@@ -374,13 +383,12 @@ private function default_placeholders(): void {
);
// Get Email Object
- $auction = $this->object instanceof Auction ? $this->object : null;
- $order = $this->object instanceof WC_Order ? $this->object : null;
- $free_bid = $this->object instanceof FreeBid ? $this->object : null;
- $order_type = false;
+ $auction = $this->object instanceof Auction ? $this->object : null;
+ $order = $this->object instanceof WC_Order ? $this->object : null;
+ $free_bid = $this->object instanceof FreeBid ? $this->object : null;
+ $request = $this->object instanceof Request ? $this->object : null;
if ( $order ) {
- $order_type = goodbids()->woocommerce->orders->get_type( $order->get_id() );
$auction_id = goodbids()->woocommerce->orders->get_auction_id( $order->get_id() );
$auction = goodbids()->auctions->get( $auction_id );
}
@@ -434,7 +442,7 @@ private function default_placeholders(): void {
$referrer = new Referrer( $this->user_id );
$this->add_placeholder( '{user.name}', $this->get_user_name() );
$this->add_placeholder( '{user.account_url}', wc_get_page_permalink( 'myaccount' ) );
- $this->add_placeholder( '{user.free_bid_count}', goodbids()->users->get_available_free_bid_count( $this->user_id ) );
+ $this->add_placeholder( '{user.free_bid_count}', goodbids()->free_bids->get_available_count( $this->user_id ) );
$this->add_placeholder( '{user.referral_link}', $referrer->get_link() );
// Order Details
@@ -445,6 +453,17 @@ private function default_placeholders(): void {
// Free Bid Details
$this->add_placeholder( '{free_bid.type}', $free_bid?->get_type_display() );
$this->add_placeholder( '{free_bid.type_action}', $free_bid?->get_type_action() );
+
+ // Request Details
+ $support_admin_url = add_query_arg( 'post_type', goodbids()->support->get_post_type(), admin_url( 'edit.php' ) );
+ $request_url = get_edit_post_link( $request?->get_id() );
+ $this->add_placeholder( '{support_request_admin_url}', $support_admin_url );
+ $this->add_placeholder( '{request.url}', $request_url );
+ $this->add_placeholder( '{request.user.name}', $request?->get_user()?->get_username() );
+ $this->add_placeholder( '{request.user.email}', $request?->get_user()?->get_email() );
+ $this->add_placeholder( '{request.type}', $request?->get_field( Request::FIELD_TYPE ) );
+ $this->add_placeholder( '{request.nature}', $request?->get_field( Request::FIELD_NATURE ) );
+ $this->add_placeholder( '{request.request}', $request?->get_field( Request::FIELD_REQUEST ) );
}
/**
@@ -559,6 +578,10 @@ private function admin_screen_recipients(): string {
$recipients[] = __( 'Admin', 'goodbids' );
}
+ if ( $this->is_super_admins_email() ) {
+ $recipients[] = __( 'Super Admins', 'goodbids' );
+ }
+
if ( ! $recipients ) {
return __( 'Not Set', 'goodbids' );
}
@@ -576,6 +599,16 @@ public function is_admin_email(): bool {
return $this->admin_email;
}
+ /**
+ * Check if the email is sent to Super Admins.
+ *
+ * @since 1.0.0
+ * @return bool
+ */
+ public function is_super_admins_email(): bool {
+ return $this->super_admins_email;
+ }
+
/**
* Check if the email is sent to the Bidders.
*
@@ -815,20 +848,36 @@ public function send_to_bidders( Auction $auction ): void {
/**
* Send the email to all Admins
*
- * TODO: Get all site admin emails.
- *
- * @param Auction $auction
+ * @param mixed $object
*
* @since 1.0.0
*
* @return void
*/
- public function send_to_admins( Auction $auction ): void {
- $admin = get_user_by( 'email', get_option( 'admin_email' ) );
- $admins = [ $admin->ID ];
+ public function send_to_admins( mixed $object ): void {
+ $admins = get_users( [ 'role' => 'administrator', 'fields' => 'ID' ] );
+
+ if ( $this->is_super_admins_email() ) {
+ $super_admins = get_super_admins();
+ $super_ids = [];
+ foreach ( $super_admins as $username ) {
+ $super_admin = get_user_by( 'login', $username );
+ if ( ! $super_admin || ! $super_admin->user_email ) {
+ continue;
+ }
+ $super_ids[] = $super_admin->ID;
+ }
+ $admins = array_merge( $admins, $super_ids );
+ }
- foreach ( $admins as $user_id ) {
- $this->trigger( $auction, $user_id );
+ $admins = array_unique( $admins );
+
+ if ( empty( $admins ) ) {
+ Log::error( 'No Admins found to send email to', [ 'object' => $object ] );
+ }
+
+ foreach ( $admins as $admin_id ) {
+ $this->trigger( $object, $admin_id );
}
}
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/FreeBidEarned.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/FreeBidEarned.php
index cc0399c44..c79b2ff6e 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/FreeBidEarned.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/FreeBidEarned.php
@@ -8,8 +8,8 @@
namespace GoodBids\Plugins\WooCommerce\Emails;
-use GoodBids\Auctions\FreeBid;
use GoodBids\Plugins\WooCommerce\Account;
+use GoodBids\Users\FreeBid;
defined( 'ABSPATH' ) || exit;
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/SupportRequest.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/SupportRequest.php
new file mode 100644
index 000000000..b9ad01cbe
--- /dev/null
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Emails/SupportRequest.php
@@ -0,0 +1,101 @@
+id = 'goodbids_support_request';
+ $this->title = __( 'Support Request', 'goodbids' );
+ $this->description = __( 'Notification email sent to all site admins when a new support request is received.', 'goodbids' );
+ $this->template_html = 'emails/support-request.php';
+ $this->template_plain = 'emails/plain/support-request.php';
+ $this->admin_email = true;
+ $this->super_admins_email = true;
+
+ $this->trigger_on_new_support_request();
+ }
+
+ /**
+ * Trigger this email when a new Support Request is Received.
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function trigger_on_new_support_request(): void {
+ add_action(
+ 'goodbids_support_request_received',
+ function ( int $request_id ) {
+ $request = new Request( $request_id );
+ $this->send_to_admins( $request );
+ }
+ );
+ }
+
+ /**
+ * Get email subject.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ public function get_default_subject(): string {
+ return sprintf(
+ /* translators: %1$s: site title */
+ __( '[%1$s] Support Request Received', 'goodbids' ),
+ '{site_title}'
+ );
+ }
+
+ /**
+ * Get email heading.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ public function get_default_heading(): string {
+ return sprintf(
+ /* translators: %1$s: Requesting user's Username */
+ __( 'New Support Request from %1$s', 'goodbids' ),
+ '{user.name}',
+ '{site_title}'
+ );
+ }
+
+ /**
+ * Init Form Fields
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ public function init_form_fields(): void {
+ parent::init_form_fields();
+
+ // Prevent email from being disabled
+ $this->form_fields['enabled']['disabled'] = true;
+ }
+}
diff --git a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Orders.php b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Orders.php
index 5f523669c..c22ece61e 100644
--- a/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Orders.php
+++ b/client-mu-plugins/goodbids/src/classes/Plugins/WooCommerce/Orders.php
@@ -188,7 +188,7 @@ public function is_free_bid_order( int $order_id ): bool {
$order = wc_get_order( $order_id );
- if ( 0 < $order->get_total( 'edit' ) ) {
+ if ( $order->get_total( 'edit' ) > 0 ) {
return false;
}
diff --git a/client-mu-plugins/goodbids/src/classes/Users/Bidder.php b/client-mu-plugins/goodbids/src/classes/Users/Bidder.php
index 2f71ae012..e6cfc7517 100644
--- a/client-mu-plugins/goodbids/src/classes/Users/Bidder.php
+++ b/client-mu-plugins/goodbids/src/classes/Users/Bidder.php
@@ -138,7 +138,7 @@ public function get_total_donated(): int {
* @return int
*/
public function get_total_free_bids(): int {
- return count( goodbids()->users->get_free_bids( $this->get_id() ) );
+ return count( goodbids()->free_bids->get( $this->get_id() ) );
}
/**
diff --git a/client-mu-plugins/goodbids/src/classes/Users/FreeBid.php b/client-mu-plugins/goodbids/src/classes/Users/FreeBid.php
new file mode 100644
index 000000000..c14bf6023
--- /dev/null
+++ b/client-mu-plugins/goodbids/src/classes/Users/FreeBid.php
@@ -0,0 +1,438 @@
+id ) {
+ $this->id = uniqid( 'GBFB-' );
+ }
+
+ if ( ! $this->earned_date ) {
+ $this->earned_date = current_time( 'Y-m-d H:i:s' );
+ }
+ }
+
+ /**
+ * Get the Free Bid ID.
+ *
+ * @since 1.0.0
+ *
+ * @return ?string
+ */
+ public function get_id(): ?string {
+ return $this->id;
+ }
+
+ /**
+ * Set the Auction ID
+ *
+ * @since 1.0.0
+ *
+ * @param int $auction_id
+ *
+ * @return FreeBid
+ */
+ public function set_auction_id( int $auction_id ): FreeBid {
+ $this->auction_id_earned = $auction_id;
+ return $this;
+ }
+
+ /**
+ * Sets the status of the Free Bid.
+ *
+ * @since 1.0.0
+ *
+ * @param string $status
+ *
+ * @return FreeBid
+ */
+ public function set_status( string $status ): FreeBid {
+ $this->status = $status;
+ return $this;
+ }
+
+ /**
+ * Returns the status of the Free Bid
+ *
+ * @since 1.0.0
+ *
+ * @return ?string
+ */
+ public function get_status(): ?string {
+ if ( ! empty( $this->status ) ) {
+ return $this->status;
+ }
+
+ return FreeBids::STATUS_UNUSED;
+ }
+
+ /**
+ * Displays the status of the Free Bid
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ public function display_status(): void {
+ echo esc_html( ucwords( $this->get_status() ) );
+ }
+
+ /**
+ * Sets the Free Earned Type.
+ *
+ * @since 1.0.0
+ *
+ * @param string $type
+ *
+ * @return FreeBid
+ */
+ public function set_type( string $type ): FreeBid {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * Returns the type of the Free Bid
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ public function get_type(): string {
+ if ( ! $this->type ) {
+ return self::TYPE_PAID_BID;
+ }
+ return $this->type;
+ }
+
+ /**
+ * Returns the type of the Free Bid for display
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ public function get_type_display(): string {
+ return ucwords( str_replace( '_', ' ', $this->get_type() ) );
+ }
+
+ /**
+ * Displays the type of the Free Bid
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ public function display_type(): void {
+ echo esc_html( $this->get_type_display() );
+ }
+
+ /**
+ * Get the type action performed to be awarded free bid.
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ public function get_type_action(): string {
+ if ( $this->get_type() === self::TYPE_REFERRAL ) {
+ return __( 'Referral', 'goodbids' );
+ }
+
+ if ( $this->get_type() === self::TYPE_ADMIN_GRANT ) {
+ return __( 'admin grant', 'goodbids' );
+ }
+
+ // Default to Bid.
+ return __( 'Bid', 'goodbids' );
+ }
+
+ /**
+ * Sets the Details for the Free Earned Bid.
+ *
+ * @since 1.0.0
+ *
+ * @param string $details
+ *
+ * @return FreeBid
+ */
+ public function set_details( string $details ): FreeBid {
+ $this->details = $details;
+ return $this;
+ }
+
+ /**
+ * Get the Free Bid Details
+ *
+ * @since 1.0.0
+ *
+ * @return string
+ */
+ public function get_details(): string {
+ if ( ! empty( $this->details ) ) {
+ return $this->details;
+ }
+
+ if ( ! empty( $this->description ) ) {
+ return $this->description;
+ }
+
+ return '';
+ }
+
+ /**
+ * Display formatted Earned Date
+ *
+ * @since 1.0.0
+ *
+ * @param string $format
+ *
+ * @return void
+ */
+ public function display_earned_date( string $format = 'n/j/y g:i a' ): void {
+ echo wp_kses_post( goodbids()->utilities->format_date_time( $this->earned_date, $format ) );
+ }
+
+ /**
+ * Display formatted Earned Date
+ *
+ * @since 1.0.0
+ *
+ * @param string $format
+ *
+ * @return void
+ */
+ public function display_used_date( string $format = 'n/j/y g:i a' ): void {
+ if ( empty( $this->used_date ) ) {
+ esc_html_e( 'N/A', 'goodbids' );
+ return;
+ }
+
+ echo wp_kses_post( goodbids()->utilities->format_date_time( $this->used_date, $format ) );
+ }
+
+ /**
+ * Display a link to an Auction by ID.
+ *
+ * @since 1.0.0
+ *
+ * @param ?string $title
+ *
+ * @return void
+ */
+ public function display_auction_link( ?string $title = '' ): void {
+ if ( empty( $this->auction_id_used ) || empty( $this->site_id_used ) ) {
+ esc_html_e( 'N/A', 'goodbids' );
+ return;
+ }
+
+ goodbids()->sites->swap(
+ function () use ( $title ) {
+ printf(
+ '%s (ID: %s)',
+ esc_url( get_permalink( $this->auction_id_used ) ),
+ $title ? esc_attr( $title ) : '',
+ esc_html( get_the_title( $this->auction_id_used ) ),
+ esc_html( $this->auction_id_used )
+ );
+ },
+ $this->site_id_used
+ );
+ }
+
+ /**
+ * Redeem this Free Bid
+ *
+ * @since 1.0.0
+ *
+ * @param int $auction_id
+ * @param int $order_id
+ *
+ * @return bool
+ */
+ public function redeem( int $auction_id, int $order_id ): bool {
+ $order = wc_get_order( $order_id );
+
+ // Verify order exists.
+ if ( ! $order ) {
+ return false;
+ }
+
+ if ( $this->get_status() !== FreeBids::STATUS_UNUSED ) {
+ return false;
+ }
+
+ $this->used_date = current_time( 'mysql' );
+ $this->status = FreeBids::STATUS_USED;
+ $this->auction_id_used = $auction_id;
+ $this->site_id_used = get_current_blog_id();
+ $this->order_id_redeemed = $order->get_id();
+ $this->bid_value = $order->get_subtotal();
+
+ return true;
+ }
+
+ /**
+ * Used to notify users of awarded free bids later then when they were awarded.
+ *
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ public function did_awarded_notification(): bool {
+ return false !== $this->awarded_notification;
+ }
+
+ /**
+ * Mark the Free Bid as Notified.
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ public function mark_as_notified(): void {
+ $this->awarded_notification = true;
+ }
+}
diff --git a/client-mu-plugins/goodbids/src/classes/Users/FreeBids.php b/client-mu-plugins/goodbids/src/classes/Users/FreeBids.php
new file mode 100644
index 000000000..3969bdcbc
--- /dev/null
+++ b/client-mu-plugins/goodbids/src/classes/Users/FreeBids.php
@@ -0,0 +1,422 @@
+free_bid_user_fields();
+
+ // Handle Free Bid via AJAX.
+ $this->grant_free_bid_ajax();
+
+ // Set up JS Vars.
+ $this->free_bid_js_vars();
+ }
+
+ /**
+ * Display the Grant Free Bid Admin UI
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function free_bid_user_fields(): void {
+ $profile_fields = function ( WP_User $user ): void {
+ if ( is_user_admin() || get_current_user_id() === $user->ID ) {
+ return;
+ }
+
+ $user_id = $user->ID;
+
+ goodbids()->load_view( 'admin/users/grant-free-bid.php', compact( 'user_id' ) );
+ };
+
+ add_action( 'show_user_profile', $profile_fields, 1 );
+ add_action( 'edit_user_profile', $profile_fields, 1 );
+ }
+
+ /**
+ * Set up JS Vars
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ public function free_bid_js_vars(): void {
+ add_action(
+ 'goodbids_enqueue_admin_scripts',
+ function ( $handle ) {
+ wp_localize_script(
+ $handle,
+ 'goodbidsFreeBids',
+ [
+ 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
+ 'reasonFieldId' => self::REASON_FIELD,
+ 'validationAlert' => [
+ 'title' => __( 'Validation Error', 'goodbids' ),
+ 'error' => __( 'Missing reason for granting free bid.', 'goodbids' ),
+ ],
+ 'errorAlert' => [
+ 'title' => __( 'Error', 'goodbids' ),
+ ],
+ 'confirmedAlert' => [
+ 'title' => __( 'Success!', 'goodbids' ),
+ 'text' => __( 'The free bid was successfully granted.', 'goodbids' ),
+ ],
+ 'grantAction' => 'goodbids_admin_grant_free_bid',
+ 'nonceGrant' => wp_create_nonce( self::NONCE_ACTION ),
+ ]
+ );
+ }
+ );
+ }
+
+ /**
+ * Handle the AJAX action to grant the free bid.
+ *
+ * @since 1.0.0
+ *
+ * @return void
+ */
+ private function grant_free_bid_ajax(): void {
+ add_action(
+ 'wp_ajax_goodbids_admin_grant_free_bid',
+ function () {
+ list( $user_id, $reason ) = $this->ajax_request_validation();
+
+ if ( $user_id === get_current_user_id() ) {
+ wp_send_json_error(
+ [
+ 'error' => __( 'You are not allowed to grant free bids to yourself.', 'goodbids' ),
+ ],
+ 200
+ );
+ }
+
+ if ( ! $reason ) {
+ wp_send_json_error(
+ [
+ 'error' => __( 'Missing reason for granting free bid.', 'goodbids' ),
+ ],
+ 200
+ );
+ }
+
+ if ( ! $this->award( $user_id, null, FreeBid::TYPE_ADMIN_GRANT, $reason, true ) ) {
+ wp_send_json_error(
+ [
+ 'error' => __( 'There was a problem granting the free bid.', 'goodbids' ),
+ ],
+ 200
+ );
+ }
+
+ wp_send_json_success( [ 'done' ] );
+ }
+ );
+ }
+
+ /**
+ * Validate Free Bid Grant Nonce and return user_id and details
+ *
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ private function ajax_request_validation(): array {
+ check_ajax_referer( self::NONCE_ACTION, 'nonce' );
+
+ $data = wp_unslash( $_POST );
+ $user_id = intvaL( sanitize_text_field( $data['user_id'] ) );
+ $reason = sanitize_text_field( $data['reason'] );
+
+ if ( ! $user_id || ! ( new WP_User( $user_id ) ) ) {
+ wp_send_json_error(
+ [
+ 'error' => __( 'Invalid data', 'goodbids' ),
+ ],
+ 200
+ );
+ }
+
+ return [ $user_id, $reason ];
+ }
+
+ /**
+ * Get an array of all free bids for a User, filterable by status.
+ *
+ * @since 1.0.0
+ *
+ * @param ?int $user_id
+ * @param string $status
+ * @param ?string $type
+ *
+ * @return FreeBid[]
+ */
+ public function get( ?int $user_id = null, string $status = self::STATUS_ALL, ?string $type = null ): array {
+ if ( null === $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ /** @var FreeBid[] $free_bids */
+ $all_free_bids = get_user_meta( $user_id, self::META_KEY, true );
+
+ if ( ! $all_free_bids || ! is_array( $all_free_bids ) ) {
+ return [];
+ }
+
+ $collection = collect( $all_free_bids );
+
+ if ( self::STATUS_ALL !== $status ) {
+ $collection = $collection->filter(
+ fn ( $free_bid ) => $status === $free_bid->get_status()
+ );
+ }
+
+ if ( $type ) {
+ $collection = $collection->filter(
+ fn ( $free_bid ) => $type === $free_bid->get_type()
+ );
+ }
+
+ return $collection
+ ->values()
+ ->all();
+ }
+
+ /**
+ * Get count of free bids
+ *
+ * @since 1.0.0
+ *
+ * @param ?int $user_id
+ * @param string $status
+ * @param ?string $type
+ *
+ * @return int
+ */
+ public function get_count( ?int $user_id = null, string $status = self::STATUS_ALL, ?string $type = null ): int {
+ return count( $this->get( $user_id, $status, $type ) );
+ }
+
+ /**
+ * Get total available free bids for a user.
+ *
+ * @since 1.0.0
+ *
+ * @param ?int $user_id
+ *
+ * @return int
+ */
+ public function get_available_count( ?int $user_id = null ): int {
+ return $this->get_count( $user_id, self::STATUS_UNUSED );
+ }
+
+ /**
+ * Award a Free Bid to a User
+ *
+ * @since 1.0.0
+ *
+ * @param int $user_id
+ * @param ?int $auction_id
+ * @param string $type
+ * @param string $details
+ * @param bool $notify_later
+ *
+ * @return bool
+ */
+ public function award( int $user_id, ?int $auction_id = null, string $type = FreeBid::TYPE_PAID_BID, string $details = '', bool $notify_later = false ): bool {
+ $free_bid = new FreeBid();
+
+ if ( $auction_id ) {
+ $free_bid->set_auction_id( $auction_id );
+ }
+
+ $free_bid->set_type( $type );
+ $free_bid->set_details( $details );
+
+ if ( $notify_later ) {
+ $free_bid->awarded_notification = false;
+ }
+
+ $all_free_bids = $this->get( $user_id );
+ $all_free_bids[] = $free_bid;
+
+ /**
+ * Called when a Free Bid is awarded to a User
+ *
+ * @since 1.0.0
+ *
+ * @param FreeBid $free_bid
+ * @param int $user_id
+ */
+ do_action( 'goodbids_award_free_bid', $free_bid, $user_id );
+
+ return $this->save( $user_id, $all_free_bids );
+ }
+
+ /**
+ * Save Free Bids array to User Meta
+ *
+ * @since 1.0.0
+ *
+ * @param int $user_id
+ * @param FreeBid[] $free_bids
+ *
+ * @return bool
+ */
+ public function save( int $user_id, array $free_bids ): bool {
+ $original = get_user_meta( $user_id, self::META_KEY, true );
+
+ if ( $original === $free_bids ) {
+ // Data is unchanged.
+ return false;
+ }
+
+ return boolval( update_user_meta( $user_id, self::META_KEY, $free_bids ) );
+ }
+
+ /**
+ * Redeem a Free Bid
+ *
+ * @since 1.0.0
+ *
+ * @param int $auction_id
+ * @param int $order_id
+ * @param ?int $user_id
+ *
+ * @return bool
+ */
+ public function redeem( int $auction_id, int $order_id, ?int $user_id = null ): bool {
+ if ( ! $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ // Clear Cached Free Bid.
+ $auction = goodbids()->auctions->get( $auction_id );
+ delete_user_meta( $user_id, sprintf( Coupons::FREE_BID_COUPON_META_KEY, $auction->get_id(), $auction->get_variation_id() ) );
+
+ // Locate the free bid to use.
+ $all_free_bids = $this->get( $user_id );
+ $unused_free_bids = $this->get( $user_id, self::STATUS_UNUSED );
+
+ if ( ! count( $unused_free_bids ) ) {
+ Log::error( 'No available Free Bids to redeem', compact( 'user_id', 'auction_id', 'order_id' ) );
+ return false;
+ }
+
+ // Use the first available free bid.
+ foreach ( $all_free_bids as $free_bid ) {
+ if ( self::STATUS_UNUSED !== $free_bid->get_status() ) {
+ continue;
+ }
+
+ if ( $free_bid->redeem( $auction_id, $order_id ) ) {
+ return $this->update( $user_id, $free_bid->get_id(), $free_bid );
+ }
+
+ Log::error( 'There was a problem redeeming the free bid.', compact( 'user_id', 'auction_id', 'order_id' ) );
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Update a free bid
+ *
+ * @since 1.0.0
+ *
+ * @param ?int $user_id
+ * @param string $free_bid_id
+ * @param FreeBid $free_bid
+ *
+ * @return bool
+ */
+ public function update( ?int $user_id, string $free_bid_id, FreeBid $free_bid ): bool {
+ $all_free_bids = $this->get( $user_id );
+ $free_bid_index = array_search( $free_bid_id, array_column( $all_free_bids, 'id' ) );
+
+ if ( false === $free_bid_index ) {
+ return false;
+ }
+
+ $updated = $all_free_bids[ $free_bid_index ];
+
+ // Don't update if there are no changes.
+ if ( $updated === $free_bid ) {
+ return false;
+ }
+
+ $all_free_bids[ $free_bid_index ] = $free_bid;
+
+ return $this->save( $user_id, $all_free_bids );
+ }
+}
diff --git a/client-mu-plugins/goodbids/src/classes/Users/Referrals.php b/client-mu-plugins/goodbids/src/classes/Users/Referrals.php
index 9940a8b43..0a555c0ee 100644
--- a/client-mu-plugins/goodbids/src/classes/Users/Referrals.php
+++ b/client-mu-plugins/goodbids/src/classes/Users/Referrals.php
@@ -8,7 +8,6 @@
namespace GoodBids\Users;
-use GoodBids\Auctions\FreeBid;
use GoodBids\Core;
use GoodBids\Users\Referrals\Admin;
use GoodBids\Users\Referrals\Generator;
@@ -249,7 +248,6 @@ public function get_user_id_by_referral_code( string $code ): int|false {
);
if ( empty( $user ) ) {
- Log::warning( 'Unable to locate user by Referral Code: ' . $code );
return false;
}
@@ -370,7 +368,7 @@ public function convert( int $referrer_id, int $user_id, int $auction_id, int $o
$auction_id
);
- goodbids()->users->award_free_bid( $referrer_id, $auction_id, FreeBid::TYPE_REFERRAL, $details, true );
+ goodbids()->free_bids->award( $referrer_id, $auction_id, FreeBid::TYPE_REFERRAL, $details, true );
return true;
}
diff --git a/client-mu-plugins/goodbids/src/classes/Users/Referrals/Admin.php b/client-mu-plugins/goodbids/src/classes/Users/Referrals/Admin.php
index aff6cd3c6..b3db4120e 100644
--- a/client-mu-plugins/goodbids/src/classes/Users/Referrals/Admin.php
+++ b/client-mu-plugins/goodbids/src/classes/Users/Referrals/Admin.php
@@ -184,7 +184,6 @@ function () {
),
200
);
- wp_die();
}
$referred_by = goodbids()->referrals->get_referrer_id( $user_id );
@@ -196,7 +195,6 @@ function () {
],
200
);
- wp_die();
}
goodbids()->referrals->add_referral( $referrer_id, $user_id );
@@ -340,7 +338,6 @@ private function ajax_request_validation( string $nonce_action ): array {
],
422
);
- wp_die();
}
return [ $user_id, $referrer_id ];
diff --git a/client-mu-plugins/goodbids/src/classes/Users/Referrals/Track.php b/client-mu-plugins/goodbids/src/classes/Users/Referrals/Track.php
index 098987005..58690fa8b 100644
--- a/client-mu-plugins/goodbids/src/classes/Users/Referrals/Track.php
+++ b/client-mu-plugins/goodbids/src/classes/Users/Referrals/Track.php
@@ -9,7 +9,6 @@
namespace GoodBids\Users\Referrals;
use GoodBids\Utilities\Cookies;
-use GoodBids\Utilities\Log;
/**
* Class for Tracking Referrals
@@ -202,7 +201,7 @@ function ( int $order_id, int $auction_id ) {
$order = wc_get_order( $order_id );
// Don't award if payment didn't go through.
- if ( $order->needs_payment() ) {
+ if ( $order->get_total( 'edit' ) > 0 && $order->needs_payment() ) {
return;
}
diff --git a/client-mu-plugins/goodbids/src/classes/Users/Users.php b/client-mu-plugins/goodbids/src/classes/Users/Users.php
index 71ec4161e..bed2d607b 100644
--- a/client-mu-plugins/goodbids/src/classes/Users/Users.php
+++ b/client-mu-plugins/goodbids/src/classes/Users/Users.php
@@ -8,12 +8,6 @@
namespace GoodBids\Users;
-use GoodBids\Auctions\Bids;
-use GoodBids\Auctions\FreeBid;
-use GoodBids\Plugins\WooCommerce\Coupons;
-use GoodBids\Utilities\Log;
-use WP_User;
-
/**
* User Class
*
@@ -21,16 +15,6 @@
*/
class Users {
- /**
- * @since 1.0.0
- */
- const FREE_BID_NONCE_ACTION = 'admin_grant_free_bid';
-
- /**
- * @since 1.0.0
- */
- const FREE_BID_REASON_FIELD = 'free_bid_reason';
-
/**
* Constructor
*
@@ -39,187 +23,6 @@ class Users {
public function __construct() {
// Update Email Content for User.
$this->update_user_email_content();
-
- // Add UI for Super Admins to grant free bids to users.
- $this->free_bid_user_fields();
-
- // Handle Free Bid via AJAX.
- $this->grant_free_bid_ajax();
-
- // Set up JS Vars.
- $this->free_bid_js_vars();
- }
-
- /**
- * Get an array of all free bids for a User, filterable by status.
- *
- * @since 1.0.0
- *
- * @param ?int $user_id
- * @param string $status
- * @param ?string $type
- *
- * @return FreeBid[]
- */
- public function get_free_bids( ?int $user_id = null, string $status = Bids::FREE_BID_STATUS_ALL, ?string $type = null ): array {
- if ( null === $user_id ) {
- $user_id = get_current_user_id();
- }
-
- /** @var FreeBid[] $free_bids */
- $free_bids = get_user_meta( $user_id, Bids::FREE_BIDS_META_KEY, true );
-
- if ( ! $free_bids || ! is_array( $free_bids ) ) {
- return [];
- }
-
- $collection = collect( $free_bids )
- ->filter(
- fn ( $free_bid ) => (
- // When status is Bids::FREE_BID_STATUS_ALL, always returns true.
- Bids::FREE_BID_STATUS_ALL === $status
- // Otherwise bid must match status.
- || $status === $free_bid->get_status()
- )
- );
-
- if ( $type ) {
- $collection = $collection->filter(
- fn ( $free_bid ) => $type === $free_bid->get_type()
- );
- }
-
- return $collection
- ->values()
- ->all();
- }
-
- /**
- * Get total available free bids for a user.
- *
- * @since 1.0.0
- *
- * @param ?int $user_id
- *
- * @return int
- */
- public function get_available_free_bid_count( ?int $user_id = null ): int {
- return count( $this->get_free_bids( $user_id, Bids::FREE_BID_STATUS_UNUSED ) );
- }
-
- /**
- * Award a Free Bid to a User
- *
- * @since 1.0.0
- *
- * @param int $user_id
- * @param ?int $auction_id
- * @param string $type
- * @param string $details
- * @param bool $notify_later
- *
- * @return bool
- */
- public function award_free_bid( int $user_id, ?int $auction_id = null, string $type = FreeBid::TYPE_PAID_BID, string $details = '', bool $notify_later = false ): bool {
- $free_bid = new FreeBid();
-
- if ( $auction_id ) {
- $free_bid->set_auction_id( $auction_id );
- }
-
- $free_bid->set_type( $type );
- $free_bid->set_details( $details );
-
- if ( $notify_later ) {
- $free_bid->awarded_notification = false;
- }
-
- $free_bids = $this->get_free_bids( $user_id );
- $free_bids[] = $free_bid;
-
- /**
- * Called when a Free Bid is awarded to a User
- *
- * @since 1.0.0
- *
- * @param FreeBid $free_bid
- * @param int $user_id
- */
- do_action( 'goodbids_award_free_bid', $free_bid, $user_id );
-
- return $this->save_free_bids( $user_id, $free_bids );
- }
-
- /**
- * Save Free Bids array to User Meta
- *
- * @since 1.0.0
- *
- * @param int $user_id
- * @param FreeBid[] $free_bids
- *
- * @return bool
- */
- public function save_free_bids( int $user_id, array $free_bids ): bool {
- $original = get_user_meta( $user_id, Bids::FREE_BIDS_META_KEY, true );
-
- if ( $original === $free_bids ) {
- // Data is unchanged.
- return false;
- }
-
- return boolval( update_user_meta( $user_id, Bids::FREE_BIDS_META_KEY, $free_bids ) );
- }
-
- /**
- * Redeem a Free Bid
- *
- * @since 1.0.0
- *
- * @param int $auction_id
- * @param int $order_id
- * @param ?int $user_id
- *
- * @return bool
- */
- public function redeem_free_bid( int $auction_id, int $order_id, ?int $user_id = null ): bool {
- if ( ! $user_id ) {
- $user_id = get_current_user_id();
- }
-
- $all_free_bids = $this->get_free_bids( $user_id );
- $unused_free_bids = $this->get_free_bids( $user_id, Bids::FREE_BID_STATUS_UNUSED );
-
- if ( ! count( $unused_free_bids ) ) {
- Log::error( 'No available Free Bids to redeem', compact( 'user_id', 'auction_id', 'order_id' ) );
- return false;
- }
-
- $redeemed = false;
-
- // Use the first available free bid.
- foreach ( $all_free_bids as $free_bid ) {
- if ( Bids::FREE_BID_STATUS_UNUSED !== $free_bid->get_status() ) {
- continue;
- }
-
- if ( $free_bid->redeem( $auction_id, $order_id ) ) {
- $redeemed = true;
- break;
- }
- }
-
- if ( ! $redeemed ) {
- Log::error( 'There was a problem redeeming the free bid.', compact( 'user_id', 'auction_id', 'order_id' ) );
- return false;
- }
-
- $auction = goodbids()->auctions->get( $auction_id );
-
- // Clear Cached Free Bid.
- delete_user_meta( $user_id, sprintf( Coupons::FREE_BID_COUPON_META_KEY, $auction->get_id(), $auction->get_variation_id() ) );
-
- return $this->save_free_bids( $user_id, $all_free_bids );
}
/**
@@ -280,137 +83,4 @@ function ( $email ) {
11
);
}
-
- /**
- * Display the Grant Free Bid Admin UI
- *
- * @since 1.0.0
- *
- * @return void
- */
- private function free_bid_user_fields(): void {
- $profile_fields = function ( WP_User $user ): void {
- if ( is_user_admin() || get_current_user_id() === $user->ID ) {
- return;
- }
-
- $user_id = $user->ID;
-
- goodbids()->load_view( 'admin/users/grant-free-bid.php', compact( 'user_id' ) );
- };
-
- add_action( 'show_user_profile', $profile_fields, 1 );
- add_action( 'edit_user_profile', $profile_fields, 1 );
- }
-
- /**
- * Set up JS Vars
- *
- * @since 1.0.0
- *
- * @return void
- */
- public function free_bid_js_vars(): void {
- add_action(
- 'goodbids_enqueue_admin_scripts',
- function ( $handle ) {
- wp_localize_script(
- $handle,
- 'goodbidsFreeBids',
- [
- 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
- 'reasonFieldId' => self::FREE_BID_REASON_FIELD,
- 'validationAlert' => [
- 'title' => __( 'Validation Error', 'goodbids' ),
- 'error' => __( 'Missing reason for granting free bid.', 'goodbids' ),
- ],
- 'errorAlert' => [
- 'title' => __( 'Error', 'goodbids' ),
- ],
- 'confirmedAlert' => [
- 'title' => __( 'Success!', 'goodbids' ),
- 'text' => __( 'The free bid was successfully granted.', 'goodbids' ),
- ],
- 'grantAction' => 'goodbids_admin_grant_free_bid',
- 'nonceGrant' => wp_create_nonce( self::FREE_BID_NONCE_ACTION ),
- ]
- );
- }
- );
- }
-
- /**
- * Handle the AJAX action to grant the free bid.
- *
- * @since 1.0.0
- *
- * @return void
- */
- private function grant_free_bid_ajax(): void {
- add_action(
- 'wp_ajax_goodbids_admin_grant_free_bid',
- function () {
- list( $user_id, $reason ) = $this->ajax_request_validation();
-
- if ( $user_id === get_current_user_id() ) {
- wp_send_json_error(
- [
- 'error' => __( 'You are not allowed to grant free bids to yourself.', 'goodbids' ),
- ],
- 200
- );
- wp_die();
- }
-
- if ( ! $reason ) {
- wp_send_json_error(
- [
- 'error' => __( 'Missing reason for granting free bid.', 'goodbids' ),
- ],
- 200
- );
- wp_die();
- }
-
- if ( ! $this->award_free_bid( $user_id, null, FreeBid::TYPE_ADMIN_GRANT, $reason, true ) ) {
- wp_send_json_error(
- [
- 'error' => __( 'There was a problem granting the free bid.', 'goodbids' ),
- ],
- 200
- );
- wp_die();
- }
-
- wp_send_json_success( [ 'done' ] );
- }
- );
- }
-
- /**
- * Validate Free Bid Grant Nonce and return user_id and details
- *
- * @since 1.0.0
- *
- * @return array
- */
- private function ajax_request_validation(): array {
- check_ajax_referer( self::FREE_BID_NONCE_ACTION, 'nonce' );
-
- $data = wp_unslash( $_POST );
- $user_id = intvaL( sanitize_text_field( $data['user_id'] ) );
- $reason = sanitize_text_field( $data['reason'] );
-
- if ( ! $user_id || ! ( new WP_User( $user_id ) ) ) {
- wp_send_json_error(
- [
- 'error' => __( 'Invalid data', 'goodbids' ),
- ],
- 200
- );
- wp_die();
- }
-
- return [ $user_id, $reason ];
- }
}
diff --git a/client-mu-plugins/goodbids/src/classes/Utilities/Payload.php b/client-mu-plugins/goodbids/src/classes/Utilities/Payload.php
index 3bb681625..760fe9bcc 100644
--- a/client-mu-plugins/goodbids/src/classes/Utilities/Payload.php
+++ b/client-mu-plugins/goodbids/src/classes/Utilities/Payload.php
@@ -9,7 +9,7 @@
namespace GoodBids\Utilities;
use GoodBids\Auctions\Auction;
-use GoodBids\Auctions\Bids;
+use GoodBids\Users\FreeBids;
use WC_Order;
use WC_Product;
use WP_User;
@@ -226,8 +226,8 @@ private function get_payload_item( string $item ): mixed {
'startTime' => $this->auction->get_start_date_time( 'c' ),
'totalBids' => $this->auction->get_bid_count(),
'totalRaised' => $this->auction->get_total_raised(),
- 'useFreeBidParam' => Bids::USE_FREE_BID_PARAM,
- 'userFreeBids' => goodbids()->users->get_available_free_bid_count( $this->get_user_id() ),
+ 'useFreeBidParam' => FreeBids::USE_FREE_BID_PARAM,
+ 'userFreeBids' => goodbids()->free_bids->get_available_count( $this->get_user_id() ),
'userId' => $this->get_user_id(),
'userTotalBids' => $this->auction->get_user_bid_count( $this->get_user_id() ),
'userTotalDonated' => $this->auction->get_user_total_donated( $this->get_user_id() ),
diff --git a/client-mu-plugins/goodbids/src/classes/Utilities/Utilities.php b/client-mu-plugins/goodbids/src/classes/Utilities/Utilities.php
index 7489347f6..2ff0445d4 100644
--- a/client-mu-plugins/goodbids/src/classes/Utilities/Utilities.php
+++ b/client-mu-plugins/goodbids/src/classes/Utilities/Utilities.php
@@ -23,6 +23,20 @@ class Utilities {
*/
public function __construct() {}
+ /**
+ * Render a custom message and exit.
+ *
+ * @since 1.0.0
+ *
+ * @param string $message
+ *
+ * @return void
+ */
+ public function die( string $message ): void {
+ goodbids()->load_view( 'parts/die.php', compact( 'message' ) );
+ exit;
+ }
+
/**
* Format a date/time string.
*
diff --git a/client-mu-plugins/goodbids/src/views/auction-wizard/clone/index.tsx b/client-mu-plugins/goodbids/src/views/auction-wizard/clone/index.tsx
index 5da3dbf8e..43600cbc3 100644
--- a/client-mu-plugins/goodbids/src/views/auction-wizard/clone/index.tsx
+++ b/client-mu-plugins/goodbids/src/views/auction-wizard/clone/index.tsx
@@ -88,60 +88,60 @@ function CloneContent({ auctionId, rewardId }: CloneProps) {
}, [getProduct.data]);
useEffect(() => {
- if (getAuction.data) {
- let startTimeWarning: string | undefined;
- let endTimeWarning: string | undefined;
-
- if (getAuction.data.acf.auction_start === '') {
- startTimeWarning = __(
- 'Cloned auction start date is in the past. Click edit auction to add a new date.',
- 'goodbids',
- );
- }
+ if (!getAuction.data) {
+ return;
+ }
- if (getAuction.data.acf.auction_end === '') {
- endTimeWarning = __(
- 'Cloned auction end date is in the past. Click edit auction to add a new date.',
- 'goodbids',
- );
- }
+ let startTimeWarning: string | undefined;
+ let endTimeWarning: string | undefined;
- setAuction({
- title: { value: getAuction.data.title.raw },
- excerpt: {
- value: getAuction.data.excerpt.raw,
- },
- startDate: {
- value: getAuction.data.acf.auction_start,
- error: startTimeWarning,
- },
- endDate: {
- value: getAuction.data.acf.auction_end,
- error: endTimeWarning,
- },
- bidIncrement: {
- value: getAuction.data.acf.bid_increment.toString(),
- },
- startingBid: {
- value: getAuction.data.acf.starting_bid.toString(),
- },
- bidExtensionMinutes: {
- value: getAuction.data.acf.bid_extension.minutes.toString(),
- },
- auctionGoal: {
- value: getAuction.data.acf.auction_goal?.toString() || '',
- },
- expectedHighBid: {
- value:
- getAuction.data.acf.expected_high_bid?.toString() || '',
- },
- estimatedRetailValue: {
- value:
- getAuction.data.acf.estimated_value?.toString() || '',
- },
- clonedContent: getAuction.data.content.raw,
- });
+ if (getAuction.data.acf.auction_start === '') {
+ startTimeWarning = __(
+ 'Cloned auction start date is in the past. Click edit auction to add a new date.',
+ 'goodbids',
+ );
+ }
+
+ if (getAuction.data.acf.auction_end === '') {
+ endTimeWarning = __(
+ 'Cloned auction end date is in the past. Click edit auction to add a new date.',
+ 'goodbids',
+ );
}
+
+ setAuction({
+ title: { value: getAuction.data.title.raw },
+ excerpt: {
+ value: getAuction.data.excerpt.raw,
+ },
+ startDate: {
+ value: getAuction.data.acf.auction_start,
+ error: startTimeWarning,
+ },
+ endDate: {
+ value: getAuction.data.acf.auction_end,
+ error: endTimeWarning,
+ },
+ bidIncrement: {
+ value: getAuction.data.acf.bid_increment.toString(),
+ },
+ startingBid: {
+ value: getAuction.data.acf.starting_bid.toString(),
+ },
+ bidExtensionMinutes: {
+ value: getAuction.data.acf.bid_extension.minutes.toString(),
+ },
+ auctionGoal: {
+ value: getAuction.data.acf.auction_goal?.toString() || '',
+ },
+ expectedHighBid: {
+ value: getAuction.data.acf.expected_high_bid?.toString() || '',
+ },
+ estimatedRetailValue: {
+ value: getAuction.data.acf.estimated_value?.toString() || '',
+ },
+ clonedContent: getAuction.data.content.raw,
+ });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [getAuction.data]);
diff --git a/client-mu-plugins/goodbids/tailwind.config.js b/client-mu-plugins/goodbids/tailwind.config.js
index dc775b44c..c69127ae4 100644
--- a/client-mu-plugins/goodbids/tailwind.config.js
+++ b/client-mu-plugins/goodbids/tailwind.config.js
@@ -20,6 +20,8 @@ module.exports = {
backgroundImage: {
'select-arrow':
'url(\'data:image/svg+xml,\')',
+ 'select-arrow-reverse':
+ 'url(\'data:image/svg+xml,\')',
},
borderRadius: {
xs: '0.5rem',
@@ -71,6 +73,7 @@ module.exports = {
},
green: {
100: '#D9FFD2',
+ 300: '#70FF8F',
500: '#125E3E',
700: '#0A3624',
900: '#232826',
diff --git a/client-mu-plugins/goodbids/views/admin/invoices/details.php b/client-mu-plugins/goodbids/views/admin/invoices/details.php
index 29dabe3b7..efa1cead1 100644
--- a/client-mu-plugins/goodbids/views/admin/invoices/details.php
+++ b/client-mu-plugins/goodbids/views/admin/invoices/details.php
@@ -2,13 +2,15 @@
/**
* Admin Invoice Details
*
- * @global GoodBids\Nonprofits\Invoice $invoice
- * @global int $auction_id
+ * @global Invoice $invoice
+ * @global int $auction_id
*
* @since 1.0.0
* @package GoodBids
*/
+use GoodBids\Nonprofits\Invoice;
+
$auction = goodbids()->auctions->get( $auction_id );
?>
diff --git a/client-mu-plugins/goodbids/views/admin/support-requests/details.php b/client-mu-plugins/goodbids/views/admin/support-requests/details.php
new file mode 100644
index 000000000..a6abfc052
--- /dev/null
+++ b/client-mu-plugins/goodbids/views/admin/support-requests/details.php
@@ -0,0 +1,35 @@
+get_user();
+?>
+
+
+ get_username() ); ?>
+
+
+ support->get_fields() as $key => $field ) :
+ if ( method_exists( $request, 'get' . $key . '_html' ) ) {
+ $value = $request->{'get' . $key . '_html'}();
+ } else {
+ $value = $request->get_field( $key );
+ }
+ if ( ! $value ) {
+ continue;
+ }
+ ?>
+
+
+
+
diff --git a/client-mu-plugins/goodbids/views/admin/users/grant-free-bid.php b/client-mu-plugins/goodbids/views/admin/users/grant-free-bid.php
index 11347150f..c6b3b5d80 100644
--- a/client-mu-plugins/goodbids/views/admin/users/grant-free-bid.php
+++ b/client-mu-plugins/goodbids/views/admin/users/grant-free-bid.php
@@ -8,7 +8,7 @@
* @package GoodBids
*/
-use GoodBids\Users\Users;
+use GoodBids\Users\FreeBids;
?>
@@ -16,7 +16,7 @@