From 42fa8304ddb811b0f725f245130f70c0f5e86a6c Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 04 Nov 2025 06:12:02 +0000
Subject: [PATCH] =Refactored LoginManager to be more extensible and configurable, as well as an AjaxRateLimiter
---
inc/managers/ReferralManager.php | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 364 insertions(+), 2 deletions(-)
diff --git a/inc/managers/ReferralManager.php b/inc/managers/ReferralManager.php
index 9777fa4..1bac16a 100644
--- a/inc/managers/ReferralManager.php
+++ b/inc/managers/ReferralManager.php
@@ -40,7 +40,7 @@
{
global $wpdb;
$this->wpdb = $wpdb;
- $this->cache = new CacheManager('referrals');
+ $this->cache = CacheManager::for('referrals', WEEK_IN_SECONDS);
$this->referrals_table = BASE . 'referrals';
$this->rewards_table = BASE . 'referral_rewards';
$this->magic_link = new MagicLinkManager();
@@ -64,6 +64,21 @@
add_action('wp_enqueue_scripts', [$this, 'enqueueScripts']);
// Schedule cron jobs for reports
$this->registerCronJobs();
+
+ // Register admin subpage
+ add_filter('jvbAdminSubpages', [$this, 'addSubpage'], 10, 1);
+
+ // Add admin bar label for referral page
+ add_action('admin_bar_menu', [$this, 'addReferralPageLabel'], 999);
+
+ // Add admin notice to referral page edit screen
+ add_action('admin_notices', [$this, 'showReferralPageNotice']);
+
+
+ add_filter('jvbDashboardPage', [$this, 'renderDashPage'], 10, 2);
+
+ // Handle settings save
+ add_action('admin_init', [$this, 'registerSettings']);
}
public function enqueueScripts():void
@@ -887,7 +902,7 @@
$content .= '</aside>';
$actions[] =[
- 'button' => '<button type="button" class="toggle-referral row" title="Your Referrals" data-action="toggle-referral" aria-label="Open Referral Sidebar" aria-controls="referral" aria-expanded="false">
+ 'button' => '<button type="button" class="attn toggle-referral row" title="Your Referrals" data-action="toggle-referral" aria-label="Open Referral Sidebar" aria-controls="referral" aria-expanded="false">
'.jvbIcon('hand-heart').'<span class="screen-reader-text"></span>
</button>',
'content' => $content
@@ -1447,5 +1462,352 @@
return $csv_content;
}
+
+ /**
+ * Add referral settings subpage to admin menu
+ *
+ * @param array $subpages
+ * @return array
+ */
+ public function addSubpage(array $subpages): array
+ {
+ $subpages[] = [
+ 'page_title' => 'Referral Settings',
+ 'menu_title' => 'Referrals',
+ 'capability' => 'manage_options',
+ 'menu_slug' => 'jvb-referrals',
+ 'callback' => [$this, 'renderAdminPage'],
+ 'icon' => 'users',
+ ];
+
+ return $subpages;
+ }
+
+ /**
+ * Register settings
+ */
+ public function registerSettings(): void
+ {
+ register_setting(
+ BASE . 'referral_settings',
+ BASE . 'referral_page_id',
+ [
+ 'type' => 'integer',
+ 'sanitize_callback' => 'absint',
+ 'default' => 0
+ ]
+ );
+
+ register_setting(
+ BASE . 'referral_settings',
+ BASE . 'referral_reward_settings',
+ [
+ 'type' => 'array',
+ 'sanitize_callback' => [$this, 'sanitizeRewardSettings'],
+ 'default' => $this->default_settings
+ ]
+ );
+ }
+
+ /**
+ * Sanitize reward settings
+ */
+ public function sanitizeRewardSettings(array $settings): array
+ {
+ return [
+ 'referrer_reward_applies_to' => in_array($settings['referrer_reward_applies_to'] ?? '', ['per_user', 'flat_total'])
+ ? $settings['referrer_reward_applies_to']
+ : 'per_user',
+ 'referrer_reward_amount' => floatval($settings['referrer_reward_amount'] ?? 25.00),
+ 'referrer_reward_type' => in_array($settings['referrer_reward_type'] ?? '', ['fixed', 'percentage'])
+ ? $settings['referrer_reward_type']
+ : 'fixed',
+ 'referee_reward_type' => in_array($settings['referee_reward_type'] ?? '', ['percentage', 'fixed'])
+ ? $settings['referee_reward_type']
+ : 'percentage',
+ 'referee_reward_amount' => floatval($settings['referee_reward_amount'] ?? 20),
+ 'referee_reward_applies_to' => in_array($settings['referee_reward_applies_to'] ?? '', ['first_order', 'all_orders'])
+ ? $settings['referee_reward_applies_to']
+ : 'first_order',
+ ];
+ }
+
+ /**
+ * Render the admin settings page
+ */
+ public function renderAdminPage(): void
+ {
+ // Handle form submission
+ if (isset($_POST['submit']) && check_admin_referer(BASE . 'referral_settings_nonce')) {
+ update_option(BASE . 'referral_page_id', absint($_POST[BASE . 'referral_page_id'] ?? 0));
+
+ $reward_settings = [
+ 'referrer_reward_applies_to' => sanitize_text_field($_POST['referrer_reward_applies_to'] ?? 'per_user'),
+ 'referrer_reward_amount' => floatval($_POST['referrer_reward_amount'] ?? 25.00),
+ 'referrer_reward_type' => sanitize_text_field($_POST['referrer_reward_type'] ?? 'fixed'),
+ 'referee_reward_type' => sanitize_text_field($_POST['referee_reward_type'] ?? 'percentage'),
+ 'referee_reward_amount' => floatval($_POST['referee_reward_amount'] ?? 20),
+ 'referee_reward_applies_to' => sanitize_text_field($_POST['referee_reward_applies_to'] ?? 'first_order'),
+ ];
+
+ update_option(BASE . 'referral_reward_settings', $this->sanitizeRewardSettings($reward_settings));
+
+ echo '<div class="notice notice-success is-dismissible"><p>Settings saved successfully.</p></div>';
+ }
+
+ $referral_page_id = $this->getReferralPageId();
+ $settings = $this->getRewardSettings();
+
+ echo $this->renderAdminHTML();
+ }
+
+ protected function renderAdminHTML():string
+ {
+ ob_start();
+ ?>
+ <div class="wrap">
+ <h1>Referral Settings</h1>
+
+ <form method="post" action="">
+ <?php wp_nonce_field(BASE . 'referral_settings_nonce'); ?>
+
+ <div class="card">
+ <h2>Referral Page</h2>
+ <p>Select the page where users can access their referral dashboard.</p>
+
+ <table class="form-table">
+ <tr>
+ <th scope="row">
+ <label for="<?= BASE ?>referral_page_id">Referral Page</label>
+ </th>
+ <td>
+ <?php
+ wp_dropdown_pages([
+ 'name' => BASE . 'referral_page_id',
+ 'id' => BASE . 'referral_page_id',
+ 'selected' => $referral_page_id,
+ 'show_option_none' => __('— Select —', 'jvbase'),
+ 'option_none_value' => '0'
+ ]);
+ ?>
+ <p class="description">
+ This page will show "Referral Page" in the admin bar when editing.
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div class="card">
+ <h2>Reward Settings</h2>
+
+ <table class="form-table">
+ <tr>
+ <th colspan="2"><h3>Referrer Rewards</h3></th>
+ </tr>
+ <tr>
+ <th scope="row">
+ <label for="referrer_reward_type">Reward Type</label>
+ </th>
+ <td>
+ <select name="referrer_reward_type" id="referrer_reward_type">
+ <option value="fixed" <?php selected($settings['referrer_reward_type'], 'fixed'); ?>>Fixed Amount</option>
+ <option value="percentage" <?php selected($settings['referrer_reward_type'], 'percentage'); ?>>Percentage</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">
+ <label for="referrer_reward_amount">Reward Amount</label>
+ </th>
+ <td>
+ <input type="number"
+ name="referrer_reward_amount"
+ id="referrer_reward_amount"
+ value="<?= esc_attr($settings['referrer_reward_amount']) ?>"
+ step="0.01"
+ min="0">
+ <p class="description">Amount in dollars or percentage</p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">
+ <label for="referrer_reward_applies_to">Applies To</label>
+ </th>
+ <td>
+ <select name="referrer_reward_applies_to" id="referrer_reward_applies_to">
+ <option value="per_user" <?php selected($settings['referrer_reward_applies_to'], 'per_user'); ?>>Per User Referred</option>
+ <option value="flat_total" <?php selected($settings['referrer_reward_applies_to'], 'flat_total'); ?>>Flat Total</option>
+ </select>
+ </td>
+ </tr>
+
+ <tr>
+ <th colspan="2"><h3>Referee (New User) Rewards</h3></th>
+ </tr>
+ <tr>
+ <th scope="row">
+ <label for="referee_reward_type">Reward Type</label>
+ </th>
+ <td>
+ <select name="referee_reward_type" id="referee_reward_type">
+ <option value="percentage" <?php selected($settings['referee_reward_type'], 'percentage'); ?>>Percentage</option>
+ <option value="fixed" <?php selected($settings['referee_reward_type'], 'fixed'); ?>>Fixed Amount</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">
+ <label for="referee_reward_amount">Reward Amount</label>
+ </th>
+ <td>
+ <input type="number"
+ name="referee_reward_amount"
+ id="referee_reward_amount"
+ value="<?= esc_attr($settings['referee_reward_amount']) ?>"
+ step="0.01"
+ min="0">
+ <p class="description">Amount in dollars or percentage</p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row">
+ <label for="referee_reward_applies_to">Applies To</label>
+ </th>
+ <td>
+ <select name="referee_reward_applies_to" id="referee_reward_applies_to">
+ <option value="first_order" <?php selected($settings['referee_reward_applies_to'], 'first_order'); ?>>First Order Only</option>
+ <option value="all_orders" <?php selected($settings['referee_reward_applies_to'], 'all_orders'); ?>>All Orders</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <p class="submit">
+ <button type="submit" name="submit" class="button button-primary">Save Settings</button>
+ </p>
+ </form>
+
+ <?= $this->renderReferralStats(true) ?>
+ </div>
+ <?php
+ return ob_get_clean();
+ }
+
+ /**
+ * Render referral statistics
+ */
+ protected function renderReferralStats(bool $wrapCard = false):string
+ {
+ ob_start();
+ global $wpdb;
+
+ $total_referrals = $wpdb->get_var("SELECT COUNT(*) FROM {$this->referrals_table}");
+ $pending_referrals = $wpdb->get_var("SELECT COUNT(*) FROM {$this->referrals_table} WHERE status = 'pending'");
+ $treated_referrals = $wpdb->get_var("SELECT COUNT(*) FROM {$this->referrals_table} WHERE status = 'treated'");
+
+ ?>
+ <table class="widefat">
+ <tr>
+ <th>Total Referrals</th>
+ <td><?= esc_html($total_referrals) ?></td>
+ </tr>
+ <tr>
+ <th>Pending</th>
+ <td><?= esc_html($pending_referrals) ?></td>
+ </tr>
+ <tr>
+ <th>Treated</th>
+ <td><?= esc_html($treated_referrals) ?></td>
+ </tr>
+ </table>
+ <?php
+ $table = ob_get_clean();
+ if ($wrapCard) {
+ $table = '<div class="card">
+ <h2>Referral Statistics</h2>
+ '.$table.'
+ </div>';
+ }
+ return $table;
+ }
+
+ /**
+ * Add "Referral Page" label to admin bar
+ *
+ * @param WP_Admin_Bar $wp_admin_bar
+ */
+ public function addReferralPageLabel($wp_admin_bar): void
+ {
+ if (!is_admin()) {
+ return;
+ }
+
+ $referral_page_id = $this->getReferralPageId();
+
+ if (!$referral_page_id) {
+ return;
+ }
+
+ global $pagenow, $post;
+
+ // Check if we're editing the referral page
+ if ('post.php' === $pagenow && $post && $post->ID === $referral_page_id) {
+ $wp_admin_bar->add_node([
+ 'id' => 'referral-page',
+ 'parent' => 'top-secondary',
+ 'title' => __('Referral Page', 'jvbase'),
+ 'meta' => [
+ 'class' => 'referral-page-notice'
+ ]
+ ]);
+ }
+ }
+
+ /**
+ * Get the referral page ID
+ *
+ * @return int|null
+ */
+ public function getReferralPageId(): ?int
+ {
+ $page_id = get_option(BASE . 'referral_page_id');
+ return $page_id ? (int) $page_id : null;
+ }
+
+ /**
+ * Show admin notice on referral page edit screen
+ */
+ public function showReferralPageNotice(): void
+ {
+ global $pagenow, $post;
+
+ if ('post.php' !== $pagenow || !$post) {
+ return;
+ }
+
+ $referral_page_id = $this->getReferralPageId();
+
+ if ($post->ID === $referral_page_id) {
+ echo '<div class="notice notice-info">';
+ echo '<p>' . __('This page is designated as the <strong>Referral Page</strong>.', 'jvbase') . '</p>';
+ echo '</div>';
+ }
+ }
+
+ public function renderDashPage(string $content, string $page):string
+ {
+ if ($page !== 'referrals') {
+ return $content;
+ }
+ $out = '';
+ if (current_user_can('manage_options')) {
+ $out .= $this->renderAdminHTML();
+ } else {
+ $out .= $this->renderReferralStats(true);
+ }
+ return ($out === '') ? $content : '<form id="referrals" class="col" data-save="referrals">'.$out.'</form>';
+ }
}
--
Gitblit v1.10.0