From 747d741293e064a979d7bf6c143ef969ea6d7629 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 24 May 2026 20:49:44 +0000
Subject: [PATCH] =GMBReview block minor tweaks. Refactored ReferralManager.php and ReferralRoutes.php to utilize the manager for all logic, and CustomTable for table interactions.
---
inc/rest/routes/ReferralRoutes.php | 625 ++++++++++++++++++--------------------------------------
1 files changed, 203 insertions(+), 422 deletions(-)
diff --git a/inc/rest/routes/ReferralRoutes.php b/inc/rest/routes/ReferralRoutes.php
index aec6c55..a1e3f3e 100644
--- a/inc/rest/routes/ReferralRoutes.php
+++ b/inc/rest/routes/ReferralRoutes.php
@@ -1,10 +1,12 @@
<?php
namespace JVBase\rest\routes;
+use JVBase\base\Site;
use JVBase\importers\JaneAppClientImporter;
-use JVBase\managers\JaneSalesImporter;
-use JVBase\managers\MagicLinkManager;
-use JVBase\rest\RestRouteManager;
+use JVBase\importers\JaneAppSalesImporter;
+use JVBase\managers\CustomTable;
+use JVBase\rest\Rest;
+use JVBase\rest\Route;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
@@ -16,130 +18,80 @@
/**
* REST API routes for referral system
*/
-class ReferralRoutes extends RestRouteManager
+class ReferralRoutes extends Rest
{
- protected string $referrals_table;
- protected string $rewards_table;
- protected $wpdb;
-
public function __construct()
{
- $this->route = 'referrals';
- $this->cache_name = 'referrals';
+ $this->cacheName = 'referrals';
+ $this->cacheTtl = (int)HOUR_IN_SECONDS;
parent::__construct();
- global $wpdb;
- $this->wpdb = $wpdb;
- $this->referrals_table = $wpdb->prefix . BASE . 'referrals';
- $this->rewards_table = $wpdb->prefix . BASE . 'referral_rewards';
-
add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
}
public function registerRoutes(): void
{
- /**
- * Main referrals endpoint
- * GET: List referrals with filters
- * POST: Perform actions (invite, consulted, treated, remove, resend)
- */
- register_rest_route($this->namespace, "/{$this->route}", [
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'getReferrals'],
- 'permission_callback' => [$this, 'checkPermission'],
- 'args' => [
- 'user' => ['type' => 'integer', 'sanitize_callback' => 'absint'],
- 'status' => ['type' => 'string', 'enum' => ['all', 'pending', 'consulted', 'treated', 'unused', 'registered', 'completed']],
- 'date_start' => ['type' => 'string'],
- 'date_end' => ['type' => 'string'],
- 'limit' => ['type' => 'integer', 'default' => 50],
- 'offset' => ['type' => 'integer', 'default' => 0],
- 'format' => ['type' => 'string', 'enum' => ['simple', 'formatted'], 'default' => 'formatted'],
- 'search' => ['type' => 'string']
- ]
- ],
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'handleAction'],
- 'permission_callback' => [$this, 'checkPermission'],
- 'args' => [
- 'action' => [
- 'required' => true,
- 'type' => 'string',
- 'enum' => ['invite', 'consulted', 'treated', 'remove', 'resend']
- ]
- ]
- ]
- ]);
+ // Main referrals endpoint - list and manage referrals
+ Route::for('referrals')
+ ->get([$this, 'getReferrals'])
+ ->args([
+ 'user' => 'integer',
+ 'status' => 'string|enum:all,pending,consulted,treated,unused,registered,completed|default:all',
+ 'date_start' => 'string',
+ 'date_end' => 'string',
+ 'limit' => 'integer|default:50',
+ 'offset' => 'integer|default:0',
+ 'search' => 'string'
+ ])
+ ->rateLimit()
+ ->post([$this, 'handleAction'])
+ ->args([
+ 'action' => 'string|required|enum:invite,consulted,treated,remove,resend'
+ ])
+ ->auth('user')
+ ->rateLimit(10)
+ ->register();
- /**
- * Referral code endpoint
- * GET: Get user's referral code
- * POST: Validate a referral code
- */
- register_rest_route($this->namespace, "/{$this->route}/code", [
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'getCode'],
- 'permission_callback' => [$this, 'checkPermission'],
- 'args' => [
- 'user' => ['type' => 'integer', 'sanitize_callback' => 'absint']
- ]
- ],
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'validateCode'],
- 'permission_callback' => '__return_true', // Public endpoint
- 'args' => [
- 'code' => ['required' => true, 'type' => 'string']
- ]
- ]
- ]);
+ // Referral code endpoint
+ Route::for('referrals/code')
+ ->get([$this, 'getCode'])
+ ->args(['user' => 'integer'])
+ ->auth('user')
+ ->rateLimit(30)
+ ->post([$this, 'validateCode'])
+ ->args(['code' => 'string|required'])
+ ->auth('public')
+ ->rateLimit(10)
+ ->register();
- /**
- * Stats endpoint
- * GET: Get user's referral statistics
- */
- register_rest_route($this->namespace, "/{$this->route}/stats", [
- 'methods' => 'GET',
- 'callback' => [$this, 'getStats'],
- 'permission_callback' => [$this, 'checkPermission'],
- 'args' => [
- 'user' => ['type' => 'integer', 'sanitize_callback' => 'absint'],
- ]
- ]);
+ // Stats endpoint
+ Route::for('referrals/stats')
+ ->get([$this, 'getStats'])
+ ->args(['user' => 'integer'])
+ ->auth('user')
+ ->rateLimit(30)
+ ->register();
- /**
- * Settings endpoint (admin only)
- */
- register_rest_route($this->namespace, "/{$this->route}/settings", [
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'getSettings'],
- 'permission_callback' => [$this, 'checkAdminPermission']
- ],
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'updateSettings'],
- 'permission_callback' => [$this, 'checkAdminPermission']
- ]
- ]);
+ // Settings endpoint (admin only)
+ Route::for('referrals/settings')
+ ->get([$this, 'getSettings'])
+ ->post([$this, 'updateSettings'])
+ ->auth('admin')
+ ->rateLimit(10)
+ ->register();
- /**
- * CSV Upload endpoints (admin only)
- */
- register_rest_route($this->namespace, "/{$this->route}/upload-clients", [
- 'methods' => 'POST',
- 'callback' => [$this, 'handleClientUpload'],
- 'permission_callback' => [$this, 'checkAdminPermission']
- ]);
+ // CSV Upload endpoints (admin only)
+ Route::for('referrals/upload-clients')
+ ->post([$this, 'handleClientUpload'])
+ ->auth('admin')
+ ->rateLimit(3)
+ ->register();
- register_rest_route($this->namespace, "/{$this->route}/upload-sales", [
- 'methods' => 'POST',
- 'callback' => [$this, 'handleSalesUpload'],
- 'permission_callback' => [$this, 'checkAdminPermission']
- ]);
+ Route::for('referrals/upload-sales')
+ ->post([$this, 'handleSalesUpload'])
+ ->auth('admin')
+ ->rateLimit(3)
+ ->register();
}
/**
@@ -152,19 +104,16 @@
{
$user_id = $request->get_param('user');
- // Determine scope
+ // Determine scope: admin without user param gets all referrals
if (!$user_id) {
$current_user_id = get_current_user_id();
- $is_admin = current_user_can('manage_options');
- if ($is_admin) {
- // Admin with no user param = get all referrals
+ if (current_user_can('manage_options')) {
return $this->getAllReferrals($request);
}
$user_id = $current_user_id;
}
-
- // Get user's referrals
+ // Build cache key
$args = [
'status' => $request->get_param('status') ?? 'all',
'limit' => $request->get_param('limit') ?? 50,
@@ -172,14 +121,15 @@
'date_start' => $request->get_param('date_start'),
'date_end' => $request->get_param('date_end'),
];
+ $cache_key = "user_{$user_id}_" . $this->cache->generateKey($args);
- $cache_key = "ref_{$user_id}_" . md5(serialize($args));
- // Check headers for 304 Not Modified
+ // Check 304 Not Modified
$cache_check = $this->checkHeaders($request, $cache_key);
if ($cache_check instanceof WP_REST_Response) {
- return $cache_check; // Returns 304 if not modified
+ return $cache_check;
}
+ // Get referrals from manager
$referrals = JVB()->referrals()->getUserReferrals($user_id, $args);
$data = [
@@ -187,11 +137,8 @@
'total' => count($referrals)
];
- // Create response with cache headers
$response = $this->success($data);
-
- // Add ETag and Last-Modified headers
- return $this->addCacheHeaders($response, $cache_key, $data);
+ return $this->addCacheHeaders($response);
}
/**
@@ -217,51 +164,53 @@
*/
protected function actionInvite(WP_REST_Request $request): WP_REST_Response
{
- $data = $request->get_params();
- error_log('Send Referral Invitations:'.print_r($data, true));
$user = absint($request->get_param('user'));
- if (!$this->checkUser($user)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'No user found'
- ]);
+ if (!$user || !get_userdata($user)) {
+ return $this->error('Invalid user', 'invalid_user', 400);
}
+
+ //Additional check to not send too many emails in an hour
+ $user = absint($request->get_param('user'));
+ $transient_key = "referral_invite_limit_{$user}";
+ $recent_invites = get_transient($transient_key) ?: 0;
+
+ if ($recent_invites >= 20) { // Max 5 batch invites per hour
+ return $this->error('Too many invitations sent. Please try again later.', 'rate_limit', 429);
+ }
+ set_transient($transient_key, $recent_invites + 1, HOUR_IN_SECONDS);
+
$subject = sanitize_text_field($request->get_param('subject'));
$message = sanitize_textarea_field($request->get_param('message'));
$invitations = $request->get_param('invite');
- // Validate invitation format
- foreach ($invitations as $key => $invite) {
- if (!array_key_exists('name', $invite) || !array_key_exists('email', $invite)) {
- unset($invitations[$key]);
- } else {
- $temp = [
- 'name' => sanitize_text_field($invite['name']),
- 'email' => sanitize_email($invite['email'])
+ // Validate and sanitize invitations
+ $sanitized_invitations = [];
+ foreach ($invitations as $invite) {
+ if (isset($invite['name'], $invite['email'])) {
+ $sanitized_invitations[] = [
+ 'name' => sanitize_text_field($invite['name']),
+ 'email' => sanitize_email($invite['email'])
];
- $invitations[$key] = $temp;
}
}
+ if (empty($sanitized_invitations)) {
+ return $this->error('No valid invitations provided', 'no_invitations', 400);
+ }
+
$operationID = sanitize_text_field($request->get_param('id'));
- $operation = JVB()->queue()->queueOperation(
+ JVB()->queue()->queueOperation(
'referral_invite',
$user,
[
'subject' => $subject,
'message' => $message,
- 'invitations' => $invitations
+ 'invitations' => $sanitized_invitations
],
- [
- 'operation_id' => $operationID
- ]
+ ['operation_id' => $operationID]
);
- return new WP_REST_Response([
- 'success' => true,
- 'message' => 'Queued for Processing',
- 'operation' => $operationID
- ]);
+ return $this->queued($operationID, 'Referral invitations queued');
}
/**
@@ -270,7 +219,7 @@
protected function actionUpdateStatus(WP_REST_Request $request, string $status): WP_REST_Response
{
if (!current_user_can('manage_options')) {
- return $this->error('Admin permission required', 'unauthorized', 403);
+ return $this->forbidden('Admin permission required');
}
$referral_id = $request->get_param('referral_id');
@@ -278,42 +227,16 @@
return $this->error('referral_id required', 'missing_id', 400);
}
- $referral = $this->wpdb->get_row($this->wpdb->prepare(
- "SELECT * FROM {$this->referrals_table} WHERE id = %d",
- $referral_id
- ));
+ $result = JVB()->referrals()->updateStatus($referral_id, $status);
- if (!$referral) {
- return $this->error('Referral not found', 'not_found', 404);
+ if (is_wp_error($result)) {
+ $code = $result->get_error_code();
+ return $code === 'not_found'
+ ? $this->notFound($result->get_error_message())
+ : $this->error($result->get_error_message(), $code, 500);
}
- // Update status
- $update_data = ['status' => $status];
- $update_data["{$status}_at"] = current_time('mysql');
-
- if ($status === 'treated') {
- $update_data['treatment_count'] = ($referral->treatment_count ?? 0) + 1;
- }
-
- $updated = $this->wpdb->update(
- $this->referrals_table,
- $update_data,
- ['id' => $referral_id],
- array_fill(0, count($update_data), '%s'),
- ['%d']
- );
-
-
-
- if ($updated) {
- // Also create rewards if treated
- if ($status === 'treated') {
- $this->createRewards($referral);
- }
- }
-
- $this->cache->clear();
-
+ $this->cache->flush();
return $this->success(['message' => "Referral marked as {$status}"]);
}
@@ -327,29 +250,20 @@
return $this->error('referral_id required', 'missing_id', 400);
}
- $referral = $this->wpdb->get_row($this->wpdb->prepare(
- "SELECT * FROM {$this->referrals_table} WHERE id = %d",
- $referral_id
- ));
+ $result = JVB()->referrals()->removeReferral($referral_id, get_current_user_id());
- if (!$referral) {
- return $this->error('Referral not found', 'not_found', 404);
+ if (is_wp_error($result)) {
+ $code = $result->get_error_code();
+ $status = match($code) {
+ 'not_found' => 404,
+ 'unauthorized' => 403,
+ 'invalid_status' => 400,
+ default => 500
+ };
+ return $this->error($result->get_error_message(), $code, $status);
}
- // Check ownership
- $current_user_id = get_current_user_id();
- if ($referral->referrer_id != $current_user_id && !current_user_can('manage_options')) {
- return $this->error('Unauthorized', 'unauthorized', 403);
- }
-
- // Can only remove pending referrals
- if ($referral->status !== 'pending') {
- return $this->error('Can only remove pending referrals', 'invalid_status', 400);
- }
-
- $this->wpdb->delete($this->referrals_table, ['id' => $referral_id], ['%d']);
- $this->cache->clear();
-
+ $this->cache->flush();
return $this->success(['message' => 'Referral removed']);
}
@@ -363,45 +277,18 @@
return $this->error('referral_id required', 'missing_id', 400);
}
- $current_user_id = get_current_user_id();
- $referral = $this->wpdb->get_row($this->wpdb->prepare(
- "SELECT * FROM {$this->referrals_table} WHERE id = %d AND referrer_id = %d",
- $referral_id,
- $current_user_id
- ));
-
- if (!$referral) {
- return $this->error('Referral not found', 'not_found', 404);
- }
-
- // Check rate limit (once per week)
- $transient_key = 'referral_last_invite_' . md5($referral->referee_email);
- $last_invite = get_transient($transient_key);
-
- if ($last_invite && (time() - $last_invite) < WEEK_IN_SECONDS) {
- return $this->error(
- 'Can only resend once per week',
- 'rate_limit',
- 429
- );
- }
-
- // Resend via referral manager
- $result = JVB()->referrals()->sendReferralInvitation(
- $current_user_id,
- $referral->referee_email,
- $referral->referee_name,
- sprintf('Reminder: Join %s', get_bloginfo('name')),
- 'Just a friendly reminder about my invitation!'
- );
+ $result = JVB()->referrals()->resendInvitation($referral_id, get_current_user_id());
if (is_wp_error($result)) {
- return $this->error($result->get_error_message(), 'send_failed', 500);
+ $code = $result->get_error_code();
+ $status = match($code) {
+ 'not_found' => 404,
+ 'rate_limit' => 429,
+ default => 500
+ };
+ return $this->error($result->get_error_message(), $code, $status);
}
- // Set rate limit
- set_transient($transient_key, time(), WEEK_IN_SECONDS);
-
return $this->success(['message' => 'Invitation resent']);
}
@@ -415,7 +302,7 @@
// Check permission
if ($user_id != get_current_user_id() && !current_user_can('manage_options')) {
- return $this->error('Unauthorized', 'unauthorized', 403);
+ return $this->forbidden('Unauthorized');
}
$code = JVB()->referrals()->getUserReferralCode($user_id);
@@ -466,11 +353,10 @@
*/
public function getStats(WP_REST_Request $request): WP_REST_Response
{
- $user_id = $request->get_param('user');
-
+ $user_id = $request->get_param('user') ?? get_current_user_id();
$cache_key = "stats_{$user_id}";
- // Check for 304 Not Modified
+ // Check 304 Not Modified
$cache_check = $this->checkHeaders($request, $cache_key);
if ($cache_check instanceof WP_REST_Response) {
return $cache_check;
@@ -479,9 +365,7 @@
$stats = JVB()->referrals()->getUserStats($user_id);
$response = $this->success(['items' => [$stats]]);
-
- // Add cache headers (5 minutes for stats)
- return $this->addCacheHeaders($response, $cache_key, $stats, 5 * MINUTE_IN_SECONDS);
+ return $this->addCacheHeaders($response);
}
/**
@@ -508,7 +392,7 @@
];
update_option(BASE . 'referral_settings', $settings);
- $this->cache->clear();
+ $this->cache->flush();
return $this->success([
'message' => 'Settings updated',
@@ -521,106 +405,18 @@
*/
protected function getAllReferrals(WP_REST_Request $request): WP_REST_Response
{
- $where = ['1=1'];
- $where_params = [];
-
- $status = $request->get_param('status');
- if ($status && $status !== 'all') {
- $where[] = 'status = %s';
- $where_params[] = $status;
- }
-
- if ($date_start = $request->get_param('date_start')) {
- $where[] = 'referred_at >= %s';
- $where_params[] = $date_start;
- }
-
- if ($date_end = $request->get_param('date_end')) {
- $where[] = 'referred_at <= %s';
- $where_params[] = $date_end;
- }
-
- $search = $request->get_param('search');
- if (!empty($search)) {
- $search_term = '%' . $this->wpdb->esc_like($search) . '%';
- $where[] = '(r.referee_name LIKE %s OR r.referee_email LIKE %s OR r.referral_code LIKE %s OR u.display_name LIKE %s OR ru.display_name LIKE %s OR ru.user_email LIKE %s)';
- $where_params[] = $search_term;
- $where_params[] = $search_term;
- $where_params[] = $search_term;
- $where_params[] = $search_term;
- $where_params[] = $search_term;
- $where_params[] = $search_term;
- }
-
- $limit = $request->get_param('limit') ?? 50;
- $offset = $request->get_param('offset') ?? 0;
-
- $where_params[] = $limit;
- $where_params[] = $offset;
-
- $query = "SELECT r.*, u.display_name as referrer_name
- FROM {$this->referrals_table} r
- LEFT JOIN {$this->wpdb->users} u ON r.referrer_id = u.ID
- WHERE " . implode(' AND ', $where) . "
- ORDER BY referred_at DESC
- LIMIT %d OFFSET %d";
-
- $items = $this->wpdb->get_results($this->wpdb->prepare($query, $where_params));
-
- error_log('All Referrals result: '.print_r($items, true));
- return $this->success([
- 'items' => $items,
- 'total' => count($items)
+ $items = JVB()->referrals()->getAllReferrals([
+ 'status' => $request->get_param('status') ?? 'all',
+ 'search' => $request->get_param('search'),
+ 'date_start' => $request->get_param('date_start'),
+ 'date_end' => $request->get_param('date_end'),
+ 'limit' => $request->get_param('limit') ?? 50,
+ 'offset' => $request->get_param('offset') ?? 0,
]);
+
+ return $this->success(['items' => $items, 'total' => count($items)]);
}
- /**
- * Helper: Create rewards for completed referral
- */
- protected function createRewards(object $referral): void
- {
- $settings = JVB()->referrals()->getRewardSettings();
-
- // 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'],
- 'reward_calculation' => $settings['referrer_reward_type'],
- 'status' => 'available',
- 'created_at' => current_time('mysql')
- ],
- ['%d', '%d', '%s', '%f', '%s', '%s', '%s']
- );
-
- // Referee reward
- if ($referral->referee_id) {
- $this->wpdb->insert(
- $this->rewards_table,
- [
- 'referral_id' => $referral->id,
- 'user_id' => $referral->referee_id,
- 'reward_type' => 'referee',
- 'amount' => $settings['referee_reward_amount'],
- 'reward_calculation' => $settings['referee_reward_type'],
- 'status' => 'available',
- 'created_at' => current_time('mysql')
- ],
- ['%d', '%d', '%s', '%f', '%s', '%s', '%s']
- );
- }
- }
-
- /**
- * Check admin permission
- */
- public function checkAdminPermission(WP_REST_Request $request): bool
- {
- return current_user_can('manage_options') && parent::checkPermission($request);
- }
/**
* Process queued referral operations
@@ -637,11 +433,24 @@
$data['subject'],
$data['message']
);
+
if ($result['success']) {
- $this->cache->clear();
+ $this->cache->flush();
}
- error_log('Result: '.print_r($result, true));
- return $result;
+
+ return [
+ 'success' => true,
+ 'message' => sprintf(
+ 'Sent invitations. Success: %d. Failed: %d.',
+ count($result['result']['success']),
+ count($result['result']['failed'])
+ ),
+ 'details' => [
+ 'successful' => $result['result']['success'],
+ 'failed' => $result['result']['failed'],
+ 'total' => count($data['invitations'])
+ ]
+ ];
}
/**
@@ -649,37 +458,34 @@
*/
public function handleClientUpload(WP_REST_Request $request): WP_REST_Response
{
- $files = $request->get_file_params();
-
- if (!isset($files['file'])) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'No file uploaded'
- ], 400);
+ if (empty($_FILES['file'])) {
+ return $this->error('No file uploaded', 'no_file', 400);
}
- $file = $files['file'];
+ $file = $_FILES['file'];
+
+ if ($file['error'] !== UPLOAD_ERR_OK) {
+ return $this->error('File upload error: ' . $file['error'], 'upload_error', 400);
+ }
// Validate file type
$allowed_types = ['text/csv', 'application/vnd.ms-excel', 'text/plain'];
- if (!in_array($file['type'], $allowed_types)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'File must be a CSV'
- ], 400);
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
+ $mime_type = finfo_file($finfo, $file['tmp_name']);
+ finfo_close($finfo);
+
+ if (!in_array($mime_type, $allowed_types) && !in_array($file['type'], $allowed_types)) {
+ return $this->error('File must be a CSV', 'invalid_file_type', 400);
}
// Validate file size (10MB max)
if ($file['size'] > 10 * 1024 * 1024) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'File size exceeds 10MB limit'
- ], 400);
+ return $this->error('File size exceeds 10MB limit', 'file_too_large', 400);
}
// Import using JaneAppClientImporter
$importer = new JaneAppClientImporter();
- $default_role = get_option(BASE . 'client_import_role', JVB_USER);
+ $default_role = get_option(BASE . 'referral_role', Site::getDefaultReferralRole());
$options = [
'update_existing' => true,
@@ -691,33 +497,20 @@
$result = $importer->importFromCSV($file['tmp_name'], $options);
if (is_wp_error($result)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => $result->get_error_message()
- ], 500);
+ return $this->error($result->get_error_message(), 'import_failed', 500);
}
- // Build detailed message
- $message = sprintf(
- 'Import complete: %d created, %d updated, %d skipped',
- $result['created'],
- $result['updated'],
- $result['skipped']
- );
+ $this->cache->flush();
- $details = [];
- if (!empty($result['skipped_details'])) {
- $details = $result['skipped_details'];
- }
-
- // Clear cache
- $this->cache->clear();
-
- return new WP_REST_Response([
- 'success' => true,
- 'message' => $message,
- 'items' => $result,
- 'skipped_details' => $details
+ return $this->success([
+ 'message' => sprintf(
+ 'Import complete: %d created, %d updated, %d skipped',
+ $result['created'],
+ $result['updated'],
+ $result['skipped']
+ ),
+ 'stats' => $result,
+ 'skipped_details' => $result['skipped_details'] ?? []
]);
}
@@ -726,54 +519,42 @@
*/
public function handleSalesUpload(WP_REST_Request $request): WP_REST_Response
{
- $files = $request->get_file_params();
-
- if (!isset($files['file'])) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'No file uploaded'
- ], 400);
+ if (empty($_FILES['file'])) {
+ return $this->error('No file uploaded', 'no_file', 400);
}
- $file = $files['file'];
+ $file = $_FILES['file'];
+
+ if ($file['error'] !== UPLOAD_ERR_OK) {
+ return $this->error('File upload error: ' . $file['error'], 'upload_error', 400);
+ }
// Validate file type
$allowed_types = ['text/csv', 'application/vnd.ms-excel', 'text/plain'];
- if (!in_array($file['type'], $allowed_types)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'File must be a CSV'
- ], 400);
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
+ $mime_type = finfo_file($finfo, $file['tmp_name']);
+ finfo_close($finfo);
+
+ if (!in_array($mime_type, $allowed_types) && !in_array($file['type'], $allowed_types)) {
+ return $this->error('File must be a CSV', 'invalid_file_type', 400);
}
// Validate file size (10MB max)
if ($file['size'] > 10 * 1024 * 1024) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => 'File size exceeds 10MB limit'
- ], 400);
+ return $this->error('File size exceeds 10MB limit', 'file_too_large', 400);
}
- // Import using JaneSalesImporter
- $importer = new JaneSalesImporter();
- $options = [
- 'skip_existing' => true
- ];
-
- $result = $importer->importFromCSV($file['tmp_name'], $options);
+ // Import using JaneAppSalesImporter
+ $importer = new JaneAppSalesImporter();
+ $result = $importer->importFromCSV($file['tmp_name'], ['skip_existing' => true]);
if (is_wp_error($result)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => $result->get_error_message()
- ], 500);
+ return $this->error($result->get_error_message(), 'import_failed', 500);
}
- // Clear cache
- $this->cache->clear();
+ $this->cache->flush();
- return new WP_REST_Response([
- 'success' => true,
+ return $this->success([
'message' => 'Sales imported successfully',
'stats' => $result
]);
--
Gitblit v1.10.0