<?php
|
namespace JVBase\rest\routes;
|
|
use JVBase\rest\RestRouteManager;
|
use WP_REST_Request;
|
use WP_REST_Response;
|
use WP_Error;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
/**
|
* REST API routes for referral system
|
*/
|
class ReferralRoutes extends RestRouteManager
|
{
|
|
public function __construct()
|
{
|
$this->route = 'referrals';
|
parent::__construct();
|
}
|
|
public function registerRoutes(): void
|
{
|
// Get user's referrals
|
register_rest_route($this->namespace, "/{$this->route}", [
|
'methods' => 'GET',
|
'callback' => [$this, 'getUserReferrals'],
|
'permission_callback' => [$this, 'checkPermission']
|
]);
|
|
register_rest_route($this->namespace, '/referrals/register', [
|
'methods' => 'POST',
|
'callback' => [$this, 'registerWithReferral'],
|
'permission_callback' => '__return_true',
|
'args' => [
|
'name' => [
|
'required' => true,
|
'type' => 'string',
|
'sanitize_callback' => 'sanitize_text_field'
|
],
|
'email' => [
|
'required' => true,
|
'type' => 'string',
|
'format' => 'email',
|
'validate_callback' => function($param) {
|
return is_email($param);
|
}
|
],
|
'code' => [
|
'required' => true,
|
'type' => 'string',
|
'sanitize_callback' => function($code) {
|
return strtoupper(sanitize_text_field($code));
|
}
|
]
|
]
|
]);
|
|
register_rest_route($this->namespace, '/referrals/check-code', [
|
'methods' => 'POST',
|
'callback' => [$this, 'checkReferralCode'],
|
'permission_callback' => '__return_true',
|
'args' => [
|
'code' => [
|
'required' => true,
|
'type' => 'string',
|
'sanitize_callback' => function($code) {
|
return strtoupper(sanitize_text_field($code));
|
}
|
]
|
]
|
]);
|
|
// Get or create referral code
|
register_rest_route($this->namespace, "/{$this->route}/code", [
|
'methods' => 'GET',
|
'callback' => [$this, 'getReferralCode'],
|
'permission_callback' => [$this, 'checkPermission']
|
]);
|
|
// Track referral click (public endpoint)
|
register_rest_route($this->namespace, "/{$this->route}/track", [
|
'methods' => 'POST',
|
'callback' => [$this, 'trackReferralClick'],
|
'permission_callback' => '__return_true',
|
'args' => [
|
'code' => [
|
'required' => true,
|
'type' => 'string'
|
]
|
]
|
]);
|
|
// Mark referral as treated
|
register_rest_route($this->namespace, "/{$this->route}/(?P<id>\d+)/treat", [
|
'methods' => 'POST',
|
'callback' => [$this, 'markAsTreated'],
|
'permission_callback' => function() {
|
return current_user_can('manage_options');
|
},
|
'args' => [
|
'id' => [
|
'required' => true,
|
'validate_callback' => function($param) {
|
return is_numeric($param);
|
}
|
]
|
]
|
]);
|
|
// Send referral invitation
|
register_rest_route($this->namespace, '/'.$this->route.'/invite', [
|
'methods' => 'POST',
|
'callback' => [$this, 'sendInvitation'],
|
'permission_callback' => [$this, 'checkPermission'],
|
'args' => [
|
'email' => [
|
'required' => true,
|
'type' => 'string',
|
'format' => 'email',
|
'validate_callback' => function($param) {
|
return is_email($param);
|
}
|
],
|
'name' => [
|
'required' => true,
|
'type' => 'string',
|
'sanitize_callback' => 'sanitize_text_field'
|
]
|
]
|
]);
|
|
// Send batch invitations
|
register_rest_route($this->namespace, '/'.$this->route.'/invite/batch', [
|
'methods' => 'POST',
|
'callback' => [$this, 'sendBatchInvitations'],
|
'permission_callback' => [$this, 'checkPermission'],
|
'args' => [
|
'invitations' => [
|
'required' => true,
|
'type' => 'array',
|
'validate_callback' => function($param) {
|
return is_array($param) && !empty($param);
|
}
|
]
|
]
|
]);
|
|
// Get invitation stats for current user
|
register_rest_route($this->namespace, '/'.$this->route.'/invite/stats', [
|
'methods' => 'GET',
|
'callback' => [$this, 'getInvitationStats'],
|
'permission_callback' => [$this, 'checkPermission']
|
]);
|
|
// Export referrals for Jane App
|
register_rest_route($this->namespace, '/'.$this->route.'/export', [
|
'methods' => 'POST',
|
'callback' => [$this, 'exportReferrals'],
|
'permission_callback' => function() {
|
return current_user_can('manage_options');
|
},
|
'args' => [
|
'start_date' => [
|
'required' => true,
|
'type' => 'string',
|
'validate_callback' => function($param) {
|
return (bool) strtotime($param);
|
}
|
],
|
'end_date' => [
|
'required' => true,
|
'type' => 'string',
|
'validate_callback' => function($param) {
|
return (bool) strtotime($param);
|
}
|
]
|
]
|
]);
|
|
// Get top referrers (admin only)
|
register_rest_route($this->namespace, "/{$this->route}/leaderboard", [
|
'methods' => 'GET',
|
'callback' => [$this, 'getTopReferrers'],
|
'permission_callback' => function() {
|
return current_user_can('manage_options');
|
},
|
'args' => [
|
'period' => [
|
'default' => 'week',
|
'enum' => ['day', 'week', 'month', 'all']
|
],
|
'limit' => [
|
'default' => 10,
|
'type' => 'integer'
|
]
|
]
|
]);
|
|
// Get/Update referral settings (admin only)
|
register_rest_route($this->namespace, "/{$this->route}/settings", [
|
[
|
'methods' => 'GET',
|
'callback' => [$this, 'getSettings'],
|
'permission_callback' => function() {
|
return current_user_can('manage_options');
|
}
|
],
|
[
|
'methods' => 'POST',
|
'callback' => [$this, 'updateSettings'],
|
'permission_callback' => function() {
|
return current_user_can('manage_options');
|
}
|
]
|
]);
|
}
|
|
public function checkPermission(WP_REST_Request $request): bool
|
{
|
return is_user_logged_in();
|
}
|
|
/**
|
* Get user's referrals
|
*/
|
public function getUserReferrals(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
|
$args = [
|
'status' => $request->get_param('status') ?? 'all',
|
'limit' => $request->get_param('limit') ?? 50,
|
'offset' => $request->get_param('offset') ?? 0
|
];
|
|
$referrals = JVB()->referrals()->getUserReferrals($user_id, $args);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'referrals' => $referrals
|
]);
|
}
|
|
/**
|
* Get user's referral code
|
*/
|
public function getReferralCode(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
$code = JVB()->referrals()->getUserReferralCode($user_id);
|
|
if (is_wp_error($code)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => $code->get_error_message()
|
], 400);
|
}
|
|
return new WP_REST_Response([
|
'success' => true,
|
'code' => $code,
|
'share_url' => home_url('/?ref=' . $code)
|
]);
|
}
|
|
/**
|
* Update user's referral code
|
*/
|
public function updateReferralCode(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
$new_code = strtoupper(sanitize_text_field($request->get_param('code')));
|
|
$result = JVB()->referrals()->getUserReferralCode($user_id, $new_code);
|
|
if (is_wp_error($result)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => $result->get_error_message()
|
], 400);
|
}
|
|
return new WP_REST_Response([
|
'success' => true,
|
'code' => $result,
|
'message' => 'Referral code updated successfully'
|
]);
|
}
|
|
/**
|
* Track referral click and store in session
|
*/
|
public function trackReferralClick(WP_REST_Request $request): WP_REST_Response
|
{
|
$code = strtoupper(sanitize_text_field($request->get_param('code')));
|
|
// Start session if not already started
|
if (session_status() === PHP_SESSION_NONE) {
|
session_start();
|
}
|
|
// Store referral code in both session and cookie (30 day expiry)
|
$_SESSION[BASE . 'referral_code'] = $code;
|
setcookie(BASE . 'referral_code', $code, time() + (30 * DAY_IN_SECONDS), '/');
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => 'Referral tracked'
|
]);
|
}
|
|
/**
|
* Mark referral as treated
|
*/
|
public function markAsTreated(WP_REST_Request $request): WP_REST_Response
|
{
|
$referral_id = intval($request->get_param('id'));
|
|
$result = JVB()->referrals()->markAsTreated($referral_id, true);
|
|
if (!$result) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Failed to update referral'
|
], 400);
|
}
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => 'Referral marked as treated and rewards created'
|
]);
|
}
|
|
/**
|
* Get user stats
|
*/
|
public function getUserStats(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
$stats = JVB()->referrals()->getUserStats($user_id);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'stats' => $stats
|
]);
|
}
|
|
/**
|
* Get top referrers
|
*/
|
public function getTopReferrers(WP_REST_Request $request): WP_REST_Response
|
{
|
$period = $request->get_param('period') ?? 'week';
|
$limit = $request->get_param('limit') ?? 10;
|
|
$top_referrers = JVB()->referrals()->getTopReferrers($limit, $period);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'period' => $period,
|
'referrers' => $top_referrers
|
]);
|
}
|
|
/**
|
* Get referral settings
|
*/
|
public function getSettings(WP_REST_Request $request): WP_REST_Response
|
{
|
$settings = get_option(BASE . 'referral_settings', []);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'settings' => $settings
|
]);
|
}
|
|
/**
|
* Update referral settings
|
*/
|
public function updateSettings(WP_REST_Request $request): WP_REST_Response
|
{
|
$settings = [
|
'referrer_reward_type' => $request->get_param('referrer_reward_type') ?? 'per_user',
|
'referrer_reward_amount' => floatval($request->get_param('referrer_reward_amount') ?? 25),
|
'referee_reward_type' => $request->get_param('referee_reward_type') ?? 'percentage',
|
'referee_reward_amount' => floatval($request->get_param('referee_reward_amount') ?? 20),
|
'referee_reward_applies_to' => $request->get_param('referee_reward_applies_to') ?? 'first_order'
|
];
|
|
update_option(BASE . 'referral_settings', $settings);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => 'Settings updated successfully',
|
'settings' => $settings
|
]);
|
}
|
|
/**
|
* Send a single referral invitation
|
*
|
* @param WP_REST_Request $request
|
* @return WP_REST_Response
|
*/
|
public function sendInvitation(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
$email = sanitize_email($request->get_param('email'));
|
$name = sanitize_text_field($request->get_param('name'));
|
|
// Send invitation via ReferralManager
|
$referral_manager = JVB()->referrals();
|
$result = $referral_manager->sendReferralInvitation($user_id, $email, $name);
|
|
if (is_wp_error($result)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => $result->get_error_message(),
|
'code' => $result->get_error_code()
|
], 400);
|
}
|
|
return new WP_REST_Response($result, 200);
|
}
|
|
/**
|
* Send batch referral invitations
|
*
|
* @param WP_REST_Request $request
|
* @return WP_REST_Response
|
*/
|
public function sendBatchInvitations(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
$invitations = $request->get_param('invitations');
|
|
// Validate invitation format
|
foreach ($invitations as $invite) {
|
if (empty($invite['email']) || empty($invite['name'])) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Each invitation must have email and name'
|
], 400);
|
}
|
}
|
|
// Send batch via ReferralManager
|
$referral_manager = JVB()->referrals();
|
$result = $referral_manager->sendBatchReferralInvitations($user_id, $invitations);
|
|
return new WP_REST_Response($result, 200);
|
}
|
|
/**
|
* Get invitation stats for current user
|
*
|
* @param WP_REST_Request $request
|
* @return WP_REST_Response
|
*/
|
public function getInvitationStats(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = get_current_user_id();
|
|
$referral_manager = JVB()->referrals();
|
$stats = $referral_manager->getUserInvitationStats($user_id);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'stats' => $stats
|
], 200);
|
}
|
|
/**
|
* Export referrals for Jane App cross-reference
|
* Admin only
|
*
|
* @param WP_REST_Request $request
|
* @return WP_REST_Response
|
*/
|
public function exportReferrals(WP_REST_Request $request): WP_REST_Response
|
{
|
$start_date = sanitize_text_field($request->get_param('start_date'));
|
$end_date = sanitize_text_field($request->get_param('end_date'));
|
|
$referral_manager = JVB()->referrals();
|
$csv_content = $referral_manager->exportReferrals($start_date, $end_date);
|
|
// Return CSV for download
|
return new WP_REST_Response([
|
'success' => true,
|
'csv' => $csv_content,
|
'filename' => sprintf('referrals_%s_to_%s.csv', $start_date, $end_date)
|
], 200);
|
}
|
|
public function registerWithReferral(WP_REST_Request $request): WP_REST_Response
|
{
|
$name = sanitize_text_field($request->get_param('name'));
|
$email = sanitize_email($request->get_param('email'));
|
$code = strtoupper(sanitize_text_field($request->get_param('code')));
|
|
// Validate email
|
if (!is_email($email)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Invalid email address'
|
], 400);
|
}
|
|
// Check if user exists
|
if (email_exists($email)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'An account with this email already exists'
|
], 400);
|
}
|
|
// Validate referral code
|
$referral_manager = JVB()->referrals();
|
$referrer = $referral_manager->getUserByReferralCode($code);
|
|
if (!$referrer) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Invalid referral code'
|
], 404);
|
}
|
|
// Get reward text
|
$settings = $referral_manager->getRewardSettings();
|
$reward_amount = $settings['referee_reward_amount'] ?? 20;
|
$reward_type = $settings['referee_reward_type'] ?? 'percentage';
|
$reward_text = $reward_type === 'percentage'
|
? "{$reward_amount}% off your first treatment!"
|
: "\${$reward_amount} off your first treatment!";
|
|
// Send magic link with referral context via MagicLinkManager
|
$magic_link_manager = new \JVBase\managers\MagicLinkManager();
|
|
$result = $magic_link_manager->sendMagicLink(
|
$email,
|
\JVBase\managers\MagicLinkManager::TYPE_REFERRAL,
|
[
|
'name' => $name,
|
'referral_code' => $code,
|
'referrer_id' => $referrer->ID,
|
'referrer_name' => $referrer->display_name,
|
'reward_text' => $reward_text
|
]
|
);
|
|
if (is_wp_error($result)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Failed to send registration link. Please try again.'
|
], 500);
|
}
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => 'Check your email! We sent you a link to complete your registration.',
|
'email' => $email
|
], 200);
|
}
|
|
public function checkReferralCode(WP_REST_Request $request): WP_REST_Response
|
{
|
$code = strtoupper(sanitize_text_field($request->get_param('code')));
|
|
if (empty($code)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Code is required'
|
], 400);
|
}
|
|
$referral_manager = JVB()->referrals();
|
$referrer = $referral_manager->getUserByReferralCode($code);
|
|
if (!$referrer) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'Invalid referral code'
|
], 404);
|
}
|
|
// Return basic referrer info (no sensitive data)
|
return new WP_REST_Response([
|
'success' => true,
|
'code' => $code,
|
'referrer_name' => $referrer->display_name,
|
], 200);
|
}
|
}
|