feat: Add product images support with WP Media Library integration
- Add WP Media Library integration for product and variation images - Support images array (URLs) conversion to attachment IDs - Add images array to API responses (Admin & Customer SPA) - Implement drag-and-drop sortable images in Admin product form - Add image gallery thumbnails in Customer SPA product page - Initialize WooCommerce session for guest cart operations - Fix product variations and attributes display in Customer SPA - Add variation image field in Admin SPA Changes: - includes/Api/ProductsController.php: Handle images array, add to responses - includes/Frontend/ShopController.php: Add images array for customer SPA - includes/Frontend/CartController.php: Initialize WC session for guests - admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function - admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images - admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field - customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
This commit is contained in:
365
includes/Frontend/AccountController.php
Normal file
365
includes/Frontend/AccountController.php
Normal file
@@ -0,0 +1,365 @@
|
||||
<?php
|
||||
namespace WooNooW\Frontend;
|
||||
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Account Controller - Customer account API
|
||||
* Handles customer account operations for customer-spa
|
||||
*/
|
||||
class AccountController {
|
||||
|
||||
/**
|
||||
* Register REST API routes
|
||||
*/
|
||||
public static function register_routes() {
|
||||
$namespace = 'woonoow/v1';
|
||||
|
||||
// Get customer orders
|
||||
register_rest_route($namespace, '/account/orders', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [__CLASS__, 'get_orders'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
'args' => [
|
||||
'page' => [
|
||||
'default' => 1,
|
||||
'sanitize_callback' => 'absint',
|
||||
],
|
||||
'per_page' => [
|
||||
'default' => 10,
|
||||
'sanitize_callback' => 'absint',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Get single order
|
||||
register_rest_route($namespace, '/account/orders/(?P<id>\d+)', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [__CLASS__, 'get_order'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
'args' => [
|
||||
'id' => [
|
||||
'validate_callback' => function($param) {
|
||||
return is_numeric($param);
|
||||
},
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Get customer profile
|
||||
register_rest_route($namespace, '/account/profile', [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [__CLASS__, 'get_profile'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
],
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [__CLASS__, 'update_profile'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
],
|
||||
]);
|
||||
|
||||
// Update password
|
||||
register_rest_route($namespace, '/account/password', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [__CLASS__, 'update_password'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
'args' => [
|
||||
'current_password' => [
|
||||
'required' => true,
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
],
|
||||
'new_password' => [
|
||||
'required' => true,
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// Get addresses
|
||||
register_rest_route($namespace, '/account/addresses', [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [__CLASS__, 'get_addresses'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
],
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [__CLASS__, 'update_addresses'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
],
|
||||
]);
|
||||
|
||||
// Get downloads (for digital products)
|
||||
register_rest_route($namespace, '/account/downloads', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [__CLASS__, 'get_downloads'],
|
||||
'permission_callback' => [__CLASS__, 'check_customer_permission'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is logged in
|
||||
*/
|
||||
public static function check_customer_permission() {
|
||||
return is_user_logged_in();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer orders
|
||||
*/
|
||||
public static function get_orders(WP_REST_Request $request) {
|
||||
$customer_id = get_current_user_id();
|
||||
$page = $request->get_param('page');
|
||||
$per_page = $request->get_param('per_page');
|
||||
|
||||
$args = [
|
||||
'customer_id' => $customer_id,
|
||||
'limit' => $per_page,
|
||||
'page' => $page,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
|
||||
$orders = wc_get_orders($args);
|
||||
|
||||
$formatted_orders = array_map(function($order) {
|
||||
return self::format_order($order);
|
||||
}, $orders);
|
||||
|
||||
// Get total count
|
||||
$total_args = [
|
||||
'customer_id' => $customer_id,
|
||||
'return' => 'ids',
|
||||
];
|
||||
$total = count(wc_get_orders($total_args));
|
||||
|
||||
return new WP_REST_Response([
|
||||
'orders' => $formatted_orders,
|
||||
'total' => $total,
|
||||
'total_pages' => ceil($total / $per_page),
|
||||
'page' => $page,
|
||||
'per_page' => $per_page,
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single order
|
||||
*/
|
||||
public static function get_order(WP_REST_Request $request) {
|
||||
$order_id = $request->get_param('id');
|
||||
$customer_id = get_current_user_id();
|
||||
|
||||
$order = wc_get_order($order_id);
|
||||
|
||||
if (!$order) {
|
||||
return new WP_Error('order_not_found', 'Order not found', ['status' => 404]);
|
||||
}
|
||||
|
||||
// Check if order belongs to customer
|
||||
if ($order->get_customer_id() !== $customer_id) {
|
||||
return new WP_Error('forbidden', 'You do not have permission to view this order', ['status' => 403]);
|
||||
}
|
||||
|
||||
return new WP_REST_Response(self::format_order($order, true), 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer profile
|
||||
*/
|
||||
public static function get_profile(WP_REST_Request $request) {
|
||||
$user_id = get_current_user_id();
|
||||
$user = get_userdata($user_id);
|
||||
|
||||
if (!$user) {
|
||||
return new WP_Error('user_not_found', 'User not found', ['status' => 404]);
|
||||
}
|
||||
|
||||
return new WP_REST_Response([
|
||||
'id' => $user->ID,
|
||||
'email' => $user->user_email,
|
||||
'first_name' => get_user_meta($user_id, 'first_name', true),
|
||||
'last_name' => get_user_meta($user_id, 'last_name', true),
|
||||
'username' => $user->user_login,
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update customer profile
|
||||
*/
|
||||
public static function update_profile(WP_REST_Request $request) {
|
||||
$user_id = get_current_user_id();
|
||||
$first_name = $request->get_param('first_name');
|
||||
$last_name = $request->get_param('last_name');
|
||||
$email = $request->get_param('email');
|
||||
|
||||
// Update user meta
|
||||
if ($first_name !== null) {
|
||||
update_user_meta($user_id, 'first_name', sanitize_text_field($first_name));
|
||||
}
|
||||
|
||||
if ($last_name !== null) {
|
||||
update_user_meta($user_id, 'last_name', sanitize_text_field($last_name));
|
||||
}
|
||||
|
||||
// Update email if changed
|
||||
if ($email !== null && is_email($email)) {
|
||||
$user = get_userdata($user_id);
|
||||
if ($user->user_email !== $email) {
|
||||
wp_update_user([
|
||||
'ID' => $user_id,
|
||||
'user_email' => $email,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return new WP_REST_Response([
|
||||
'message' => 'Profile updated successfully',
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update password
|
||||
*/
|
||||
public static function update_password(WP_REST_Request $request) {
|
||||
$user_id = get_current_user_id();
|
||||
$current_password = $request->get_param('current_password');
|
||||
$new_password = $request->get_param('new_password');
|
||||
|
||||
$user = get_userdata($user_id);
|
||||
|
||||
// Verify current password
|
||||
if (!wp_check_password($current_password, $user->user_pass, $user_id)) {
|
||||
return new WP_Error('invalid_password', 'Current password is incorrect', ['status' => 400]);
|
||||
}
|
||||
|
||||
// Update password
|
||||
wp_set_password($new_password, $user_id);
|
||||
|
||||
return new WP_REST_Response([
|
||||
'message' => 'Password updated successfully',
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer addresses
|
||||
*/
|
||||
public static function get_addresses(WP_REST_Request $request) {
|
||||
$customer_id = get_current_user_id();
|
||||
$customer = new \WC_Customer($customer_id);
|
||||
|
||||
return new WP_REST_Response([
|
||||
'billing' => [
|
||||
'first_name' => $customer->get_billing_first_name(),
|
||||
'last_name' => $customer->get_billing_last_name(),
|
||||
'company' => $customer->get_billing_company(),
|
||||
'address_1' => $customer->get_billing_address_1(),
|
||||
'address_2' => $customer->get_billing_address_2(),
|
||||
'city' => $customer->get_billing_city(),
|
||||
'state' => $customer->get_billing_state(),
|
||||
'postcode' => $customer->get_billing_postcode(),
|
||||
'country' => $customer->get_billing_country(),
|
||||
'email' => $customer->get_billing_email(),
|
||||
'phone' => $customer->get_billing_phone(),
|
||||
],
|
||||
'shipping' => [
|
||||
'first_name' => $customer->get_shipping_first_name(),
|
||||
'last_name' => $customer->get_shipping_last_name(),
|
||||
'company' => $customer->get_shipping_company(),
|
||||
'address_1' => $customer->get_shipping_address_1(),
|
||||
'address_2' => $customer->get_shipping_address_2(),
|
||||
'city' => $customer->get_shipping_city(),
|
||||
'state' => $customer->get_shipping_state(),
|
||||
'postcode' => $customer->get_shipping_postcode(),
|
||||
'country' => $customer->get_shipping_country(),
|
||||
],
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update customer addresses
|
||||
*/
|
||||
public static function update_addresses(WP_REST_Request $request) {
|
||||
$customer_id = get_current_user_id();
|
||||
$customer = new \WC_Customer($customer_id);
|
||||
|
||||
$billing = $request->get_param('billing');
|
||||
$shipping = $request->get_param('shipping');
|
||||
|
||||
// Update billing address
|
||||
if ($billing) {
|
||||
foreach ($billing as $key => $value) {
|
||||
$method = 'set_billing_' . $key;
|
||||
if (method_exists($customer, $method)) {
|
||||
$customer->$method(sanitize_text_field($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update shipping address
|
||||
if ($shipping) {
|
||||
foreach ($shipping as $key => $value) {
|
||||
$method = 'set_shipping_' . $key;
|
||||
if (method_exists($customer, $method)) {
|
||||
$customer->$method(sanitize_text_field($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$customer->save();
|
||||
|
||||
return new WP_REST_Response([
|
||||
'message' => 'Addresses updated successfully',
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer downloads
|
||||
*/
|
||||
public static function get_downloads(WP_REST_Request $request) {
|
||||
$customer_id = get_current_user_id();
|
||||
$downloads = wc_get_customer_available_downloads($customer_id);
|
||||
|
||||
return new WP_REST_Response($downloads, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format order data for API response
|
||||
*/
|
||||
private static function format_order($order, $detailed = false) {
|
||||
$data = [
|
||||
'id' => $order->get_id(),
|
||||
'order_number' => $order->get_order_number(),
|
||||
'status' => $order->get_status(),
|
||||
'date_created' => $order->get_date_created()->date('Y-m-d H:i:s'),
|
||||
'total' => $order->get_total(),
|
||||
'currency' => $order->get_currency(),
|
||||
'payment_method' => $order->get_payment_method_title(),
|
||||
];
|
||||
|
||||
if ($detailed) {
|
||||
$data['items'] = array_map(function($item) {
|
||||
$product = $item->get_product();
|
||||
return [
|
||||
'id' => $item->get_id(),
|
||||
'name' => $item->get_name(),
|
||||
'quantity' => $item->get_quantity(),
|
||||
'total' => $item->get_total(),
|
||||
'image' => $product ? wp_get_attachment_url($product->get_image_id()) : '',
|
||||
];
|
||||
}, $order->get_items());
|
||||
|
||||
$data['billing'] = $order->get_address('billing');
|
||||
$data['shipping'] = $order->get_address('shipping');
|
||||
$data['subtotal'] = $order->get_subtotal();
|
||||
$data['shipping_total'] = $order->get_shipping_total();
|
||||
$data['tax_total'] = $order->get_total_tax();
|
||||
$data['discount_total'] = $order->get_discount_total();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user