| | |
| | | |
| | | use JVBase\managers\MagicLinkManager; |
| | | use JVBase\integrations\Cloudflare; |
| | | use JVBase\meta\MetaForm; |
| | | use JVBase\utility\Features; |
| | | use WP_User; |
| | | use WP_Error; |
| | |
| | | protected MagicLinkManager $magic_link; |
| | | protected CacheManager $cache; |
| | | protected string $referrals_table; |
| | | protected ?int $referralPage = null; |
| | | protected string $rewards_table; |
| | | |
| | | // Default reward settings |
| | |
| | | 'referee_reward_applies_to' => 'first_order' // 'first_order' or 'all_orders' |
| | | ]; |
| | | |
| | | protected array $settings; |
| | | |
| | | public function __construct() |
| | | { |
| | | 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(); |
| | | |
| | | // Hook into user registration to track referrals |
| | | add_action('user_register', [$this, 'processReferral'], 10, 1); |
| | | $this->referralPage = $this->getReferralPageId(); |
| | | $this->settings = $this->getRewardSettings(); |
| | | |
| | | |
| | | add_action('jvbUserRegistered', [$this, 'processRegistrationToken'], 10, 3); |
| | | add_action('jvb_add_token_inputs', [$this, 'addLoginInputs'], 10, 1); |
| | | add_action('jvbUserRegistered', [$this, 'processReferral'], 10, 1); |
| | | |
| | | // Add meta boxes for admin to manage referrals |
| | | add_action('show_user_profile', [$this, 'displayUserReferralInfo']); |
| | |
| | | add_action('personal_options_update', [$this, 'saveUserReferralCode']); |
| | | add_action('edit_user_profile_update', [$this, 'saveUserReferralCode']); |
| | | |
| | | add_filter(BASE.'new_user_email_content', [$this, 'addReferralToWelcomeEmail'], 99, 2); |
| | | add_filter('jvbNewUserEmail', [$this, 'addReferralToWelcomeEmail'], 99, 2); |
| | | |
| | | |
| | | add_action('jvbAdditionalActions', [$this, 'outputShareWidget']); |
| | | add_filter('jvbAdditionalActions', [$this, 'outputShareWidget']); |
| | | |
| | | 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 addLoginInputs(string $action):void |
| | | { |
| | | if (array_key_exists('ref', $_GET)) { |
| | | echo '<input type="hidden" name="referral_code" value="'.$_GET['ref'].'">'; |
| | | } |
| | | } |
| | | |
| | | public function modifyLoginText(array $defaults):array |
| | | { |
| | | if (!array_key_exists('ref', $_GET)){ |
| | | return $defaults; |
| | | } |
| | | |
| | | $code = $_GET['ref']; |
| | | $user = $this->getUserByReferralCode($code); |
| | | |
| | | $desc = ($user) ? strtok($user->display_name, ' ') . ' invited you ' : 'You\'ve been invited '; |
| | | |
| | | $defaults['title'] = 'Register your Account. Get Your Reward.'; |
| | | $defaults['description'] = [ |
| | | $desc.' to see the difference with us.', |
| | | 'Oh, and you\'ll get 20% off your first treatment!', |
| | | 'Finish this account creation (you\'ll still need to make an account on Jane App to book), or let us know when you come in for your appointment.' |
| | | ]; |
| | | $defaults['extra'] = [ |
| | | 'Once you\'re in, you\'ll get your own code you can share.', |
| | | 'Get a $25 credit for <b>each</b> person you send our way who comes in for their first treatment!' |
| | | ]; |
| | | return $defaults; |
| | | } |
| | | |
| | | public function enqueueScripts():void |
| | |
| | | return !empty($users); |
| | | } |
| | | |
| | | public function processRegistrationToken(int $user_id, string $email, array $data): void |
| | | { |
| | | // Check for referral code in data |
| | | $code = $data['referral_code'] ?? ''; |
| | | if (empty($code)) { |
| | | return; |
| | | } |
| | | |
| | | // Store in session/cookie for processReferral to pick up |
| | | if (session_status() === PHP_SESSION_NONE) { |
| | | session_start(); |
| | | } |
| | | $_SESSION[BASE . 'referral_code'] = sanitize_text_field($code); |
| | | setcookie( |
| | | BASE . 'referral_code', |
| | | sanitize_text_field($code), |
| | | time() + (86400 * 30), |
| | | '/' |
| | | ); |
| | | } |
| | | /** |
| | | * Track a new referral when user registers |
| | | * |
| | | * @param int $user_id |
| | | */ |
| | | public function processReferral(int $user_id): void |
| | | public function processReferral(int $user_id, string $email, array $data): void |
| | | { |
| | | // Check if user was created via referral magic link |
| | | $referral_code = get_user_meta($user_id, BASE . 'pending_referral_code', true); |
| | | // Try to get code from multiple sources |
| | | $referral_code = $data['referral_code'] ?? |
| | | get_user_meta($user_id, BASE . 'pending_referral_code', true); |
| | | |
| | | if (!$referral_code) { |
| | | // Check session/cookie if not in data |
| | | if (empty($referral_code)) { |
| | | if (session_status() === PHP_SESSION_NONE) { |
| | | session_start(); |
| | | } |
| | | $referral_code = $_SESSION[BASE . 'referral_code'] ?? $_COOKIE[BASE . 'referral_code'] ?? ''; |
| | | } |
| | | |
| | | if (empty($referral_code)) { |
| | | return; |
| | | } |
| | | |
| | |
| | | * @param string $code |
| | | * @return int|false |
| | | */ |
| | | protected function createReferral(int $referrer_id, int $referee_id, string $code) |
| | | public function createReferral(int $referrer_id, int $referee_id, string $code) |
| | | { |
| | | $user = get_user_by('ID', $referee_id); |
| | | |
| | |
| | | */ |
| | | public function getUserByReferralCode(string $code): ?WP_User |
| | | { |
| | | $users = get_users([ |
| | | 'meta_key' => BASE . 'referral_code', |
| | | 'meta_value' => $code, |
| | | 'number' => 1 |
| | | ]); |
| | | |
| | | return $users[0] ?? null; |
| | | return $this->cache->remember( |
| | | $code, |
| | | function () use ($code) { |
| | | $users = get_users([ |
| | | 'meta_key' => BASE . 'referral_code', |
| | | 'meta_value' => $code, |
| | | 'number' => 1 |
| | | ]); |
| | | return $users[0] ?? null; |
| | | } |
| | | ); |
| | | } |
| | | |
| | | /** |
| | |
| | | return; |
| | | } |
| | | |
| | | $settings = $this->getRewardSettings(); |
| | | |
| | | // Create referrer reward |
| | | $this->wpdb->insert( |
| | | $this->rewards_table, |
| | |
| | | 'referral_id' => $referral_id, |
| | | 'user_id' => $referral->referrer_id, |
| | | 'reward_type' => 'referrer', |
| | | 'amount' => $settings['referrer_reward_amount'], |
| | | 'amount' => $this->settings['referrer_reward_amount'], |
| | | 'status' => 'available', |
| | | 'created_at' => current_time('mysql') |
| | | ], |
| | |
| | | ); |
| | | |
| | | // Create referee reward |
| | | $referee_amount = $settings['referee_reward_type'] === 'percentage' |
| | | ? $settings['referee_reward_amount'] // Store as percentage |
| | | : $settings['referee_reward_amount']; // Store as fixed amount |
| | | $referee_amount = $this->settings['referee_reward_type'] === 'percentage' |
| | | ? $this->settings['referee_reward_amount'] // Store as percentage |
| | | : $this->settings['referee_reward_amount']; // Store as fixed amount |
| | | |
| | | $this->wpdb->insert( |
| | | $this->rewards_table, |
| | |
| | | 'user_id' => $referral->referee_id, |
| | | 'reward_type' => 'referee', |
| | | 'amount' => $referee_amount, |
| | | 'reward_calculation' => $settings['referee_reward_type'], |
| | | 'reward_calculation' => $this->settings['referee_reward_type'], |
| | | 'status' => 'available', |
| | | 'created_at' => current_time('mysql') |
| | | ], |
| | |
| | | { |
| | | |
| | | $user_id = get_current_user_id(); |
| | | jvbDump($user_id); |
| | | $content = '<aside class="jvb-referral right">'; |
| | | if (!$user_id) { |
| | | $content .= $this->getUnloggedInReferral(); |
| | | } else { |
| | | $content .= $this->getLoggedInReferral($user_id); |
| | | } |
| | | $content .= '<button type="button" class="close">'.jvbIcon('close').'</button></aside>'; |
| | | $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 |
| | |
| | | ob_start(); |
| | | JVB()->connect('cloudflare')->renderTurnstile(); |
| | | $turnstile = ob_get_clean(); |
| | | $meta = new MetaForm(); |
| | | $codeForm = '<form id="referral-code-form"> |
| | | <div class="status" hidden> |
| | | <div class="spinner"></div> |
| | | <p class="message"></p> |
| | | </div> |
| | | <div class="field text"> |
| | | <label for="referral-name">Your Name</label> |
| | | <input type="text" |
| | | id="referral-name" |
| | | name="name" |
| | | placeholder="Mister Meeseeks" |
| | | autocomplete="name" |
| | | required> |
| | | </div> |
| | | |
| | | <div class="field email"> |
| | | <label for="referral-email">Your Email</label> |
| | | <input type="email" |
| | | id="referral-email" |
| | | name="email" |
| | | placeholder="look@me.com" |
| | | autocomplete="email" |
| | | required> |
| | | </div> |
| | | |
| | | <div class="field text"> |
| | | <label for="referral-code-input">Referral Code</label> |
| | | <input type="text" |
| | | id="referral-code-input" |
| | | name="referral_code" |
| | | placeholder="e.g., THISISFAKE1234" |
| | | required |
| | | pattern="[A-Za-z0-9]+" |
| | | maxlength="20" |
| | | autocomplete="off" |
| | | style="text-transform: uppercase;"> |
| | | </div> |
| | | |
| | | '.jvbFormStatus().$meta->return('referral_name', null, [ |
| | | 'required' => true, |
| | | 'type' => 'text', |
| | | 'label' => 'Your Name', |
| | | 'placeholder'=> 'Mister Meeseeks', |
| | | 'autocomplete'=>'name' |
| | | ]). |
| | | $meta->return('referral_email', null, [ |
| | | 'required' => true, |
| | | 'type' => 'email', |
| | | 'label' => 'Your Email', |
| | | 'placeholder'=> 'look@me.com', |
| | | 'autocomplete'=> 'email' |
| | | ]). |
| | | $meta->return('referral_code', null, [ |
| | | 'required' => true, |
| | | 'type' => 'text', |
| | | 'label' => 'Referral Code', |
| | | 'pattern' => '[A-Za-z0-9]+', |
| | | 'maxLength' => 20, |
| | | 'autocomplete'=>'off' |
| | | ]).' |
| | | <button type="submit"> |
| | | Get Started |
| | | </button> |
| | |
| | | </div>'; |
| | | |
| | | $loginForm = '<form id ="login-form"> |
| | | <div class="status" hidden> |
| | | <div class="spinner"></div> |
| | | <p class="message"></p> |
| | | </div> |
| | | <div class="field email"> |
| | | <label for="login-email">Your Email</label> |
| | | <input id="login-email" name="login-email" type="email" autocomplete="email"> |
| | | </div> |
| | | '.jvbFormStatus().$meta->return('login_email', null, [ |
| | | 'required' => true, |
| | | 'type' => 'email', |
| | | 'label' => 'Your Email', |
| | | 'autocomplete'=>'email' |
| | | ]).' |
| | | '.$turnstile.' |
| | | <button type="submit">Login With Magic Link</button> |
| | | </form> |
| | |
| | | return ''; |
| | | } |
| | | |
| | | $settings = $this->getRewardSettings(); |
| | | $reward_amount = $settings['referee_reward_amount'] ?? 20; |
| | | $reward_type = $settings['referee_reward_type'] ?? 'percentage'; |
| | | $reward_amount = $this->settings['referee_reward_amount'] ?? 20; |
| | | $reward_type = $this->settings['referee_reward_type'] ?? 'percentage'; |
| | | |
| | | $reward_text = $reward_type === 'percentage' |
| | | ? $reward_amount . '% off' |
| | |
| | | return ob_get_clean(); |
| | | } |
| | | |
| | | function getLoggedInReferral(int $user_id):string |
| | | public function getLoggedInReferral(int $user_id):string |
| | | { |
| | | // Logged-in user widget |
| | | $referral_code = get_user_meta($user_id, BASE . 'referral_code', true); |
| | |
| | | } |
| | | } |
| | | |
| | | $share_url = home_url('/?ref=' . $referral_code); |
| | | $share_url = $this->getShareURL($referral_code); |
| | | |
| | | ob_start(); |
| | | ?> |
| | |
| | | target="_blank" |
| | | rel="noopener noreferrer" |
| | | class="share-btn facebook-share"> |
| | | <?php echo jvbIcon('facebook', ['size' => 20]); ?> |
| | | <?php echo jvbIcon('facebook-logo', ['size' => 20]); ?> |
| | | Facebook |
| | | </a> |
| | | <a href="https://twitter.com/intent/tweet?url=<?php echo urlencode($share_url); ?>&text=<?php echo urlencode('Check this out!'); ?>" |
| | | target="_blank" |
| | | rel="noopener noreferrer" |
| | | class="share-btn twitter-share"> |
| | | <?php echo jvbIcon('twitter', ['size' => 20]); ?> |
| | | <?php echo jvbIcon('twitter-logo', ['size' => 20]); ?> |
| | | Twitter |
| | | </a> |
| | | </div> |
| | |
| | | return $content; |
| | | } |
| | | |
| | | $settings = get_option(BASE . 'referral_settings', []); |
| | | $reward_amount = $settings['referee_reward_amount'] ?? 20; |
| | | $reward_type = $settings['referee_reward_type'] ?? 'percentage'; |
| | | $reward_amount = $this->settings['referee_reward_amount'] ?? 20; |
| | | $reward_type = $this->settings['referee_reward_type'] ?? 'percentage'; |
| | | |
| | | $reward_text = $reward_type === 'percentage' |
| | | ? $reward_amount . '% off' |
| | | : '$' . number_format($reward_amount, 2) . ' off'; |
| | | |
| | | $bonus_content = '<div style="background: #e7f5ff; padding: 20px; border-radius: 8px; margin: 20px 0;">'; |
| | | $bonus_content .= '<h3 style="margin-top: 0; color: #2271b1;">🎉 Welcome Bonus!</h3>'; |
| | | $bonus_content .= '<p>Since you were referred by a friend, you\'ve earned <strong>' . $reward_text . '</strong> your first booking!</p>'; |
| | | $bonus_content .= '<p>Your reward will be automatically applied when you book.</p>'; |
| | | $bonus_content .= '</div>'; |
| | | $bonus_content = sprintf( |
| | | ' |
| | | <h3>Thanks for the ♡</h3> |
| | | <p>Since you were referred by a friend, you\'ve earned <strong>%s</strong> your first booking!</p> |
| | | <p>Your reward will be automatically applied when you book.</p>', |
| | | $reward_text, |
| | | ); |
| | | |
| | | // Insert bonus content after the first paragraph |
| | | $parts = explode('</p>', $content, 2); |
| | | if (count($parts) === 2) { |
| | | return $parts[0] . '</p>' . $bonus_content . $parts[1]; |
| | | |
| | | $code = $this->getUserReferralCode($user->ID); |
| | | $yourCode = ''; |
| | | if (!is_wp_error($code)) { |
| | | $share_url = $this->getShareURL($code); |
| | | $yourCode = sprintf( |
| | | '<div class="callout"> |
| | | <h3>Share the ♡ with Friends</h3> |
| | | <p>If you find you love what we can do for you, you can share your own code!</p> |
| | | <p>Your Referral Code: <strong>%s</strong></p> |
| | | <p>Or click the button below:</p> |
| | | %s |
| | | </div>', |
| | | jvbEmailLink($code), |
| | | jvbMailButton($share_url, 'Share Your Code') |
| | | ); |
| | | } |
| | | |
| | | return $content . $bonus_content; |
| | | |
| | | return $content . $bonus_content . $yourCode; |
| | | } |
| | | |
| | | public function getShareURL(string $code):string |
| | | { |
| | | return add_query_arg( |
| | | [ |
| | | 'ref' => $code, |
| | | 'action' => 'register' |
| | | ], |
| | | wp_login_url() |
| | | ); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | // Get reward text for email |
| | | $settings = $this->getRewardSettings(); |
| | | $reward_text = $settings['referee_reward_type'] === 'percentage' |
| | | ? "Get {$settings['referee_reward_amount']}% off your first treatment!" |
| | | : "Get \${$settings['referee_reward_amount']} off your first treatment!"; |
| | | $reward_text = $this->settings['referee_reward_type'] === 'percentage' |
| | | ? "Get {$this->settings['referee_reward_amount']}% off your first treatment!" |
| | | : "Get \${$this->settings['referee_reward_amount']} off your first treatment!"; |
| | | |
| | | // Record the invitation attempt (for tracking) |
| | | $this->recordInvitationAttempt($user_id, $invitee_email, $invitee_name); |
| | |
| | | |
| | | 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>'; |
| | | } |
| | | |
| | | 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' => $this->referralPage, |
| | | '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($this->settings['referrer_reward_type'], 'fixed'); ?>>Fixed Amount</option> |
| | | <option value="percentage" <?php selected($this->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($this->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($this->settings['referrer_reward_applies_to'], 'per_user'); ?>>Per User Referred</option> |
| | | <option value="flat_total" <?php selected($this->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($this->settings['referee_reward_type'], 'percentage'); ?>>Percentage</option> |
| | | <option value="fixed" <?php selected($this->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($this->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($this->settings['referee_reward_applies_to'], 'first_order'); ?>>First Order Only</option> |
| | | <option value="all_orders" <?php selected($this->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; |
| | | } |
| | | |
| | | if (!$this->referralPage) { |
| | | return; |
| | | } |
| | | |
| | | global $pagenow, $post; |
| | | |
| | | // Check if we're editing the referral page |
| | | if ('post.php' === $pagenow && $post && $post->ID === $this->referralPage) { |
| | | $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; |
| | | } |
| | | |
| | | if ($post->ID === $this->referralPage) { |
| | | 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>'; |
| | | } |
| | | } |
| | | |