1. Admin Store Link - Add to WP admin bar (Menu.php) with proper option check 2. Activity Log - Fix Loading text to show correct state after data loads 3. Avatar Upload - Use correct option key woonoow_allow_custom_avatar 4. Downloadable Files - Connect to WooCommerce native: - Add downloads array to format_product_full - Add downloads/download_limit/download_expiry handling in update_product - Add downloads handling in create_product
1429 lines
41 KiB
PHP
1429 lines
41 KiB
PHP
<?php
|
|
/**
|
|
* Products REST API Controller
|
|
*
|
|
* Handles CRUD operations for WooCommerce products
|
|
* Supports simple and variable products with comprehensive data
|
|
*
|
|
* @package WooNooW\Api
|
|
*/
|
|
|
|
namespace WooNooW\Api;
|
|
|
|
use WP_REST_Request;
|
|
use WP_REST_Response;
|
|
use WP_Error;
|
|
use WC_Product;
|
|
use WC_Product_Simple;
|
|
use WC_Product_Variable;
|
|
use WC_Product_Variation;
|
|
|
|
class ProductsController {
|
|
|
|
/**
|
|
* Sanitize text field
|
|
*/
|
|
private static function sanitize_text($value) {
|
|
if (!isset($value) || $value === '') {
|
|
return '';
|
|
}
|
|
$sanitized = sanitize_text_field($value);
|
|
return trim($sanitized);
|
|
}
|
|
|
|
/**
|
|
* Sanitize textarea (allows newlines)
|
|
*/
|
|
private static function sanitize_textarea($value) {
|
|
if (!isset($value) || $value === '') {
|
|
return '';
|
|
}
|
|
$sanitized = sanitize_textarea_field($value);
|
|
return trim($sanitized);
|
|
}
|
|
|
|
/**
|
|
* Sanitize numeric value
|
|
*/
|
|
private static function sanitize_number($value) {
|
|
if (!isset($value) || $value === '') {
|
|
return '';
|
|
}
|
|
// Remove non-numeric except decimal point and minus
|
|
$sanitized = preg_replace('/[^0-9.-]/', '', $value);
|
|
return $sanitized !== '' ? $sanitized : '';
|
|
}
|
|
|
|
/**
|
|
* Sanitize slug
|
|
*/
|
|
private static function sanitize_slug($value) {
|
|
if (!isset($value) || $value === '') {
|
|
return '';
|
|
}
|
|
return sanitize_title($value);
|
|
}
|
|
|
|
/**
|
|
* Register REST API routes
|
|
*/
|
|
public static function register_routes() {
|
|
// List products
|
|
register_rest_route('woonoow/v1', '/products', [
|
|
'methods' => 'GET',
|
|
'callback' => [__CLASS__, 'get_products'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Get single product
|
|
register_rest_route('woonoow/v1', '/products/(?P<id>\d+)', [
|
|
'methods' => 'GET',
|
|
'callback' => [__CLASS__, 'get_product'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Create product
|
|
register_rest_route('woonoow/v1', '/products', [
|
|
'methods' => 'POST',
|
|
'callback' => [__CLASS__, 'create_product'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Update product
|
|
register_rest_route('woonoow/v1', '/products/(?P<id>\d+)', [
|
|
'methods' => 'PUT',
|
|
'callback' => [__CLASS__, 'update_product'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Delete product
|
|
register_rest_route('woonoow/v1', '/products/(?P<id>\d+)', [
|
|
'methods' => 'DELETE',
|
|
'callback' => [__CLASS__, 'delete_product'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Get product categories
|
|
register_rest_route('woonoow/v1', '/products/categories', [
|
|
'methods' => 'GET',
|
|
'callback' => [__CLASS__, 'get_categories'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Get product tags
|
|
register_rest_route('woonoow/v1', '/products/tags', [
|
|
'methods' => 'GET',
|
|
'callback' => [__CLASS__, 'get_tags'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Get product attributes
|
|
register_rest_route('woonoow/v1', '/products/attributes', [
|
|
'methods' => 'GET',
|
|
'callback' => [__CLASS__, 'get_attributes'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Create category
|
|
register_rest_route('woonoow/v1', '/products/categories', [
|
|
'methods' => 'POST',
|
|
'callback' => [__CLASS__, 'create_category'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Update category
|
|
register_rest_route('woonoow/v1', '/products/categories/(?P<id>\d+)', [
|
|
'methods' => 'PUT',
|
|
'callback' => [__CLASS__, 'update_category'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Delete category
|
|
register_rest_route('woonoow/v1', '/products/categories/(?P<id>\d+)', [
|
|
'methods' => 'DELETE',
|
|
'callback' => [__CLASS__, 'delete_category'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Create tag
|
|
register_rest_route('woonoow/v1', '/products/tags', [
|
|
'methods' => 'POST',
|
|
'callback' => [__CLASS__, 'create_tag'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Update tag
|
|
register_rest_route('woonoow/v1', '/products/tags/(?P<id>\d+)', [
|
|
'methods' => 'PUT',
|
|
'callback' => [__CLASS__, 'update_tag'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Delete tag
|
|
register_rest_route('woonoow/v1', '/products/tags/(?P<id>\d+)', [
|
|
'methods' => 'DELETE',
|
|
'callback' => [__CLASS__, 'delete_tag'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Create attribute
|
|
register_rest_route('woonoow/v1', '/products/attributes', [
|
|
'methods' => 'POST',
|
|
'callback' => [__CLASS__, 'create_attribute'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Update attribute
|
|
register_rest_route('woonoow/v1', '/products/attributes/(?P<id>\d+)', [
|
|
'methods' => 'PUT',
|
|
'callback' => [__CLASS__, 'update_attribute'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
|
|
// Delete attribute
|
|
register_rest_route('woonoow/v1', '/products/attributes/(?P<id>\d+)', [
|
|
'methods' => 'DELETE',
|
|
'callback' => [__CLASS__, 'delete_attribute'],
|
|
'permission_callback' => [Permissions::class, 'check_admin_permission'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Get products list with filters
|
|
*/
|
|
public static function get_products(WP_REST_Request $request) {
|
|
try {
|
|
$page = max(1, (int) $request->get_param('page'));
|
|
$per_page = min(100, max(1, (int) ($request->get_param('per_page') ?: 20)));
|
|
$search = $request->get_param('search');
|
|
$status = $request->get_param('status');
|
|
$category = $request->get_param('category');
|
|
$type = $request->get_param('type');
|
|
$stock_status = $request->get_param('stock_status');
|
|
$orderby = $request->get_param('orderby') ?: 'date';
|
|
$order = $request->get_param('order') ?: 'DESC';
|
|
|
|
$args = [
|
|
'post_type' => 'product',
|
|
'posts_per_page' => $per_page,
|
|
'paged' => $page,
|
|
'orderby' => $orderby,
|
|
'order' => $order,
|
|
];
|
|
|
|
// Search
|
|
if ($search) {
|
|
$args['s'] = sanitize_text_field($search);
|
|
}
|
|
|
|
// Status filter
|
|
if ($status) {
|
|
$args['post_status'] = $status;
|
|
} else {
|
|
$args['post_status'] = ['publish', 'draft', 'pending', 'private'];
|
|
}
|
|
|
|
// Category filter
|
|
if ($category) {
|
|
$args['tax_query'] = [
|
|
[
|
|
'taxonomy' => 'product_cat',
|
|
'field' => 'term_id',
|
|
'terms' => (int) $category,
|
|
],
|
|
];
|
|
}
|
|
|
|
// Type filter
|
|
if ($type) {
|
|
$args['tax_query'] = $args['tax_query'] ?? [];
|
|
$args['tax_query'][] = [
|
|
'taxonomy' => 'product_type',
|
|
'field' => 'slug',
|
|
'terms' => $type,
|
|
];
|
|
}
|
|
|
|
// Stock status filter
|
|
if ($stock_status) {
|
|
$args['meta_query'] = [
|
|
[
|
|
'key' => '_stock_status',
|
|
'value' => $stock_status,
|
|
],
|
|
];
|
|
}
|
|
|
|
$query = new \WP_Query($args);
|
|
$products = [];
|
|
|
|
foreach ($query->posts as $post) {
|
|
$product = wc_get_product($post->ID);
|
|
if ($product) {
|
|
$products[] = self::format_product_list_item($product);
|
|
}
|
|
}
|
|
|
|
$response = new WP_REST_Response([
|
|
'rows' => $products,
|
|
'total' => $query->found_posts,
|
|
'page' => $page,
|
|
'per_page' => $per_page,
|
|
'pages' => $query->max_num_pages,
|
|
'_debug' => 'ProductsController-v2-' . time(), // Verify this code is running
|
|
], 200);
|
|
|
|
// Prevent caching
|
|
$response->header('Cache-Control', 'no-cache, no-store, must-revalidate');
|
|
$response->header('Pragma', 'no-cache');
|
|
$response->header('Expires', '0');
|
|
|
|
return $response;
|
|
|
|
} catch (\Exception $e) {
|
|
return new WP_Error('products_error', $e->getMessage(), ['status' => 500]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get single product
|
|
*/
|
|
public static function get_product(WP_REST_Request $request) {
|
|
$id = (int) $request->get_param('id');
|
|
$product = wc_get_product($id);
|
|
|
|
if (!$product) {
|
|
return new WP_Error('product_not_found', __('Product not found', 'woonoow'), ['status' => 404]);
|
|
}
|
|
|
|
return new WP_REST_Response(self::format_product_full($product), 200);
|
|
}
|
|
|
|
/**
|
|
* Create new product
|
|
*/
|
|
public static function create_product(WP_REST_Request $request) {
|
|
try {
|
|
$data = $request->get_json_params();
|
|
|
|
// Validate required fields
|
|
if (empty($data['name'])) {
|
|
return new WP_Error('missing_name', __('Product name is required', 'woonoow'), ['status' => 400]);
|
|
}
|
|
|
|
// Determine product type
|
|
$type = $data['type'] ?? 'simple';
|
|
|
|
if ($type === 'variable') {
|
|
$product = new WC_Product_Variable();
|
|
} else {
|
|
$product = new WC_Product_Simple();
|
|
}
|
|
|
|
// Set basic data - sanitize all inputs
|
|
$product->set_name(self::sanitize_text($data['name']));
|
|
if (!empty($data['slug'])) {
|
|
$product->set_slug(self::sanitize_slug($data['slug']));
|
|
}
|
|
$product->set_status(sanitize_key($data['status'] ?? 'publish'));
|
|
$product->set_description(self::sanitize_textarea($data['description'] ?? ''));
|
|
$product->set_short_description(self::sanitize_textarea($data['short_description'] ?? ''));
|
|
|
|
if (!empty($data['sku'])) {
|
|
$product->set_sku(self::sanitize_text($data['sku']));
|
|
}
|
|
|
|
if (!empty($data['regular_price'])) {
|
|
$product->set_regular_price(self::sanitize_number($data['regular_price']));
|
|
}
|
|
if (!empty($data['sale_price'])) {
|
|
$product->set_sale_price(self::sanitize_number($data['sale_price']));
|
|
}
|
|
|
|
$product->set_manage_stock($data['manage_stock'] ?? false);
|
|
|
|
if (!empty($data['manage_stock'])) {
|
|
$product->set_stock_quantity($data['stock_quantity'] ?? 0);
|
|
}
|
|
$product->set_stock_status($data['stock_status'] ?? 'instock');
|
|
|
|
// Optional fields - sanitize dimensions
|
|
if (!empty($data['weight'])) {
|
|
$product->set_weight(self::sanitize_number($data['weight']));
|
|
}
|
|
if (!empty($data['length'])) {
|
|
$product->set_length(self::sanitize_number($data['length']));
|
|
}
|
|
if (!empty($data['width'])) {
|
|
$product->set_width(self::sanitize_number($data['width']));
|
|
}
|
|
if (!empty($data['height'])) {
|
|
$product->set_height(self::sanitize_number($data['height']));
|
|
}
|
|
|
|
// Virtual and downloadable
|
|
if (isset($data['virtual'])) {
|
|
$product->set_virtual((bool) $data['virtual']);
|
|
}
|
|
if (isset($data['downloadable'])) {
|
|
$product->set_downloadable((bool) $data['downloadable']);
|
|
}
|
|
if (isset($data['featured'])) {
|
|
$product->set_featured((bool) $data['featured']);
|
|
}
|
|
|
|
// Categories
|
|
if (!empty($data['categories']) && is_array($data['categories'])) {
|
|
$product->set_category_ids($data['categories']);
|
|
}
|
|
|
|
// Tags
|
|
if (!empty($data['tags']) && is_array($data['tags'])) {
|
|
$product->set_tag_ids($data['tags']);
|
|
}
|
|
|
|
// Images - support both image_id/gallery_image_ids and images array
|
|
if (!empty($data['images']) && is_array($data['images'])) {
|
|
// Convert URLs to attachment IDs
|
|
$image_ids = [];
|
|
foreach ($data['images'] as $image_url) {
|
|
$attachment_id = attachment_url_to_postid($image_url);
|
|
if ($attachment_id) {
|
|
$image_ids[] = $attachment_id;
|
|
}
|
|
}
|
|
|
|
if (!empty($image_ids)) {
|
|
// First image is featured
|
|
$product->set_image_id($image_ids[0]);
|
|
// Rest are gallery
|
|
if (count($image_ids) > 1) {
|
|
$product->set_gallery_image_ids(array_slice($image_ids, 1));
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy support for direct IDs
|
|
if (!empty($data['image_id'])) {
|
|
$product->set_image_id($data['image_id']);
|
|
}
|
|
if (!empty($data['gallery_image_ids']) && is_array($data['gallery_image_ids'])) {
|
|
$product->set_gallery_image_ids($data['gallery_image_ids']);
|
|
}
|
|
}
|
|
|
|
$product->save();
|
|
|
|
// Handle variations for variable products
|
|
if ($type === 'variable' && !empty($data['attributes']) && is_array($data['attributes'])) {
|
|
self::save_product_attributes($product, $data['attributes']);
|
|
|
|
if (!empty($data['variations']) && is_array($data['variations'])) {
|
|
self::save_product_variations($product, $data['variations']);
|
|
}
|
|
}
|
|
|
|
return new WP_REST_Response(self::format_product_full($product), 201);
|
|
} catch (Exception $e) {
|
|
return new WP_Error('create_failed', $e->getMessage(), ['status' => 500]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update product
|
|
*/
|
|
public static function update_product(WP_REST_Request $request) {
|
|
$id = (int) $request->get_param('id');
|
|
$data = $request->get_json_params();
|
|
|
|
$product = wc_get_product($id);
|
|
if (!$product) {
|
|
return new WP_Error('product_not_found', __('Product not found', 'woonoow'), ['status' => 404]);
|
|
}
|
|
|
|
// Update basic data - sanitize all inputs
|
|
if (isset($data['name'])) $product->set_name(self::sanitize_text($data['name']));
|
|
if (isset($data['slug'])) $product->set_slug(self::sanitize_slug($data['slug']));
|
|
if (isset($data['status'])) $product->set_status(sanitize_key($data['status']));
|
|
if (isset($data['description'])) $product->set_description(self::sanitize_textarea($data['description']));
|
|
if (isset($data['short_description'])) $product->set_short_description(self::sanitize_textarea($data['short_description']));
|
|
if (isset($data['sku'])) $product->set_sku(self::sanitize_text($data['sku']));
|
|
|
|
if (isset($data['regular_price'])) $product->set_regular_price(self::sanitize_number($data['regular_price']));
|
|
if (isset($data['sale_price'])) $product->set_sale_price(self::sanitize_number($data['sale_price']));
|
|
|
|
if (isset($data['manage_stock'])) {
|
|
$product->set_manage_stock($data['manage_stock']);
|
|
if ($data['manage_stock']) {
|
|
if (isset($data['stock_quantity'])) $product->set_stock_quantity($data['stock_quantity']);
|
|
}
|
|
}
|
|
|
|
if (isset($data['stock_status'])) $product->set_stock_status(sanitize_key($data['stock_status']));
|
|
if (isset($data['weight'])) $product->set_weight(self::sanitize_number($data['weight']));
|
|
if (isset($data['length'])) $product->set_length(self::sanitize_number($data['length']));
|
|
if (isset($data['width'])) $product->set_width(self::sanitize_number($data['width']));
|
|
if (isset($data['height'])) $product->set_height(self::sanitize_number($data['height']));
|
|
|
|
// Virtual and downloadable
|
|
if (isset($data['virtual'])) {
|
|
$product->set_virtual((bool) $data['virtual']);
|
|
}
|
|
if (isset($data['downloadable'])) {
|
|
$product->set_downloadable((bool) $data['downloadable']);
|
|
}
|
|
if (isset($data['featured'])) {
|
|
$product->set_featured((bool) $data['featured']);
|
|
}
|
|
|
|
// Downloadable files
|
|
if (isset($data['downloads']) && is_array($data['downloads'])) {
|
|
$wc_downloads = [];
|
|
foreach ($data['downloads'] as $download) {
|
|
if (!empty($download['file'])) {
|
|
$wc_downloads[] = [
|
|
'id' => $download['id'] ?? md5($download['file']),
|
|
'name' => self::sanitize_text($download['name'] ?? ''),
|
|
'file' => esc_url_raw($download['file']),
|
|
];
|
|
}
|
|
}
|
|
$product->set_downloads($wc_downloads);
|
|
}
|
|
if (isset($data['download_limit'])) {
|
|
$limit = $data['download_limit'] === '' ? -1 : (int) $data['download_limit'];
|
|
$product->set_download_limit($limit);
|
|
}
|
|
if (isset($data['download_expiry'])) {
|
|
$expiry = $data['download_expiry'] === '' ? -1 : (int) $data['download_expiry'];
|
|
$product->set_download_expiry($expiry);
|
|
}
|
|
|
|
// Categories
|
|
if (isset($data['categories'])) {
|
|
$product->set_category_ids($data['categories']);
|
|
}
|
|
|
|
// Tags
|
|
if (isset($data['tags'])) {
|
|
$product->set_tag_ids($data['tags']);
|
|
}
|
|
|
|
// Images - support both image_id/gallery_image_ids and images array
|
|
if (isset($data['images']) && is_array($data['images']) && !empty($data['images'])) {
|
|
// Convert URLs to attachment IDs
|
|
$image_ids = [];
|
|
foreach ($data['images'] as $image_url) {
|
|
$attachment_id = attachment_url_to_postid($image_url);
|
|
if ($attachment_id) {
|
|
$image_ids[] = $attachment_id;
|
|
}
|
|
}
|
|
|
|
if (!empty($image_ids)) {
|
|
// First image is featured
|
|
$product->set_image_id($image_ids[0]);
|
|
// Rest are gallery
|
|
if (count($image_ids) > 1) {
|
|
$product->set_gallery_image_ids(array_slice($image_ids, 1));
|
|
} else {
|
|
$product->set_gallery_image_ids([]);
|
|
}
|
|
}
|
|
} else {
|
|
// Legacy support for direct IDs
|
|
if (isset($data['image_id'])) {
|
|
$product->set_image_id($data['image_id']);
|
|
}
|
|
if (isset($data['gallery_image_ids'])) {
|
|
$product->set_gallery_image_ids($data['gallery_image_ids']);
|
|
}
|
|
}
|
|
|
|
// Update custom meta fields (Level 1 compatibility)
|
|
if (isset($data['meta']) && is_array($data['meta'])) {
|
|
self::update_product_meta_data($product, $data['meta']);
|
|
}
|
|
|
|
$product->save();
|
|
|
|
// Allow plugins to perform additional updates (Level 1 compatibility)
|
|
do_action('woonoow/product_updated', $product, $data, $request);
|
|
|
|
// Handle variations for variable products
|
|
if ($product->is_type('variable')) {
|
|
if (isset($data['attributes'])) {
|
|
self::save_product_attributes($product, $data['attributes']);
|
|
}
|
|
if (isset($data['variations'])) {
|
|
self::save_product_variations($product, $data['variations']);
|
|
}
|
|
}
|
|
|
|
return new WP_REST_Response(self::format_product_full($product), 200);
|
|
}
|
|
|
|
/**
|
|
* Delete product
|
|
*/
|
|
public static function delete_product(WP_REST_Request $request) {
|
|
$id = (int) $request->get_param('id');
|
|
$force = $request->get_param('force') === 'true';
|
|
|
|
$product = wc_get_product($id);
|
|
if (!$product) {
|
|
return new WP_Error('product_not_found', __('Product not found', 'woonoow'), ['status' => 404]);
|
|
}
|
|
|
|
$result = $product->delete($force);
|
|
|
|
if (!$result) {
|
|
return new WP_Error('delete_failed', __('Failed to delete product', 'woonoow'), ['status' => 500]);
|
|
}
|
|
|
|
return new WP_REST_Response(['success' => true, 'id' => $id], 200);
|
|
}
|
|
|
|
/**
|
|
* Get product categories
|
|
*/
|
|
public static function get_categories(WP_REST_Request $request) {
|
|
$terms = get_terms([
|
|
'taxonomy' => 'product_cat',
|
|
'hide_empty' => false,
|
|
]);
|
|
|
|
if (is_wp_error($terms)) {
|
|
return new WP_REST_Response([], 200); // Return empty array on error
|
|
}
|
|
|
|
$categories = [];
|
|
foreach ($terms as $term) {
|
|
$categories[] = [
|
|
'term_id' => $term->term_id,
|
|
'name' => $term->name,
|
|
'slug' => $term->slug,
|
|
'description' => $term->description,
|
|
'parent' => $term->parent,
|
|
'count' => $term->count,
|
|
];
|
|
}
|
|
|
|
return new WP_REST_Response($categories, 200);
|
|
}
|
|
|
|
/**
|
|
* Get product tags
|
|
*/
|
|
public static function get_tags(WP_REST_Request $request) {
|
|
$terms = get_terms([
|
|
'taxonomy' => 'product_tag',
|
|
'hide_empty' => false,
|
|
]);
|
|
|
|
if (is_wp_error($terms)) {
|
|
return new WP_REST_Response([], 200); // Return empty array on error
|
|
}
|
|
|
|
$tags = [];
|
|
foreach ($terms as $term) {
|
|
$tags[] = [
|
|
'term_id' => $term->term_id,
|
|
'name' => $term->name,
|
|
'slug' => $term->slug,
|
|
'description' => $term->description,
|
|
'count' => $term->count,
|
|
];
|
|
}
|
|
|
|
return new WP_REST_Response($tags, 200);
|
|
}
|
|
|
|
/**
|
|
* Get product attributes
|
|
*/
|
|
public static function get_attributes(WP_REST_Request $request) {
|
|
$attributes = wc_get_attribute_taxonomies();
|
|
$result = [];
|
|
|
|
foreach ($attributes as $attribute) {
|
|
$result[] = [
|
|
'attribute_id' => $attribute->attribute_id,
|
|
'attribute_name' => $attribute->attribute_name,
|
|
'attribute_label' => $attribute->attribute_label,
|
|
'attribute_type' => $attribute->attribute_type,
|
|
'attribute_orderby' => $attribute->attribute_orderby,
|
|
'attribute_public' => $attribute->attribute_public,
|
|
];
|
|
}
|
|
|
|
return new WP_REST_Response($result, 200);
|
|
}
|
|
|
|
/**
|
|
* Format product for list view
|
|
* Returns all essential product fields including type, status, prices, stock, etc.
|
|
*/
|
|
private static function format_product_list_item($product) {
|
|
$image = wp_get_attachment_image_src($product->get_image_id(), 'thumbnail');
|
|
|
|
// Get price HTML - for variable products, show price range
|
|
$price_html = $product->get_price_html();
|
|
if (empty($price_html) && $product->is_type('variable')) {
|
|
$prices = $product->get_variation_prices(true);
|
|
if (!empty($prices['price'])) {
|
|
$min_price = min($prices['price']);
|
|
$max_price = max($prices['price']);
|
|
if ($min_price !== $max_price) {
|
|
$price_html = wc_format_price_range($min_price, $max_price);
|
|
} else {
|
|
$price_html = wc_price($min_price);
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
'id' => $product->get_id(),
|
|
'name' => $product->get_name(),
|
|
'sku' => $product->get_sku(),
|
|
'type' => $product->get_type(),
|
|
'status' => $product->get_status(),
|
|
'price' => $product->get_price(),
|
|
'regular_price' => $product->get_regular_price(),
|
|
'sale_price' => $product->get_sale_price(),
|
|
'price_html' => $price_html,
|
|
'stock_status' => $product->get_stock_status(),
|
|
'stock_quantity' => $product->get_stock_quantity(),
|
|
'manage_stock' => $product->get_manage_stock(),
|
|
'image_url' => $image ? $image[0] : '',
|
|
'permalink' => get_permalink($product->get_id()),
|
|
'date_created' => $product->get_date_created() ? $product->get_date_created()->date('Y-m-d H:i:s') : '',
|
|
'date_modified' => $product->get_date_modified() ? $product->get_date_modified()->date('Y-m-d H:i:s') : '',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Format product with full details
|
|
*/
|
|
private static function format_product_full($product) {
|
|
$data = self::format_product_list_item($product);
|
|
|
|
// Add full details
|
|
$data['description'] = $product->get_description();
|
|
$data['short_description'] = $product->get_short_description();
|
|
$data['slug'] = $product->get_slug();
|
|
$data['weight'] = $product->get_weight();
|
|
$data['length'] = $product->get_length();
|
|
$data['width'] = $product->get_width();
|
|
$data['height'] = $product->get_height();
|
|
$data['categories'] = $product->get_category_ids();
|
|
$data['tags'] = $product->get_tag_ids();
|
|
$data['image_id'] = $product->get_image_id();
|
|
$data['gallery_image_ids'] = $product->get_gallery_image_ids();
|
|
$data['virtual'] = $product->is_virtual();
|
|
$data['downloadable'] = $product->is_downloadable();
|
|
$data['featured'] = $product->is_featured();
|
|
|
|
// Downloadable files
|
|
if ($product->is_downloadable()) {
|
|
$downloads = [];
|
|
foreach ($product->get_downloads() as $download_id => $download) {
|
|
$downloads[] = [
|
|
'id' => $download_id,
|
|
'name' => $download->get_name(),
|
|
'file' => $download->get_file(),
|
|
];
|
|
}
|
|
$data['downloads'] = $downloads;
|
|
$data['download_limit'] = $product->get_download_limit() !== -1 ? (string) $product->get_download_limit() : '';
|
|
$data['download_expiry'] = $product->get_download_expiry() !== -1 ? (string) $product->get_download_expiry() : '';
|
|
}
|
|
|
|
// Images array (URLs) for frontend - featured + gallery
|
|
$images = [];
|
|
$featured_image_id = $product->get_image_id();
|
|
if ($featured_image_id) {
|
|
$featured_url = wp_get_attachment_url($featured_image_id);
|
|
if ($featured_url) {
|
|
$images[] = $featured_url;
|
|
}
|
|
}
|
|
foreach ($product->get_gallery_image_ids() as $image_id) {
|
|
$url = wp_get_attachment_url($image_id);
|
|
if ($url) {
|
|
$images[] = $url;
|
|
}
|
|
}
|
|
$data['images'] = $images;
|
|
|
|
// Gallery images (detailed info)
|
|
$gallery = [];
|
|
foreach ($product->get_gallery_image_ids() as $image_id) {
|
|
$image = wp_get_attachment_image_src($image_id, 'full');
|
|
if ($image) {
|
|
$gallery[] = [
|
|
'id' => $image_id,
|
|
'url' => $image[0],
|
|
'width' => $image[1],
|
|
'height' => $image[2],
|
|
];
|
|
}
|
|
}
|
|
$data['gallery'] = $gallery;
|
|
|
|
// Variable product specifics
|
|
if ($product->is_type('variable')) {
|
|
$data['attributes'] = self::get_product_attributes($product);
|
|
$data['variations'] = self::get_product_variations($product);
|
|
}
|
|
|
|
// Expose meta data (Level 1 compatibility)
|
|
$data['meta'] = self::get_product_meta_data($product);
|
|
|
|
// Allow plugins to modify response (Level 1 compatibility)
|
|
$data = apply_filters('woonoow/product_api_data', $data, $product);
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Get product attributes
|
|
*/
|
|
private static function get_product_attributes($product) {
|
|
$attributes = [];
|
|
foreach ($product->get_attributes() as $attribute) {
|
|
$attributes[] = [
|
|
'id' => $attribute->get_id(),
|
|
'name' => $attribute->get_name(),
|
|
'options' => $attribute->get_options(),
|
|
'position' => $attribute->get_position(),
|
|
'visible' => $attribute->get_visible(),
|
|
'variation' => $attribute->get_variation(),
|
|
];
|
|
}
|
|
return $attributes;
|
|
}
|
|
|
|
/**
|
|
* Get product variations
|
|
*/
|
|
private static function get_product_variations($product) {
|
|
$variations = [];
|
|
foreach ($product->get_children() as $variation_id) {
|
|
$variation = wc_get_product($variation_id);
|
|
if ($variation) {
|
|
$image = wp_get_attachment_image_src($variation->get_image_id(), 'thumbnail');
|
|
|
|
// Format attributes with human-readable names and values
|
|
$formatted_attributes = [];
|
|
|
|
// Get parent product attributes to know what to look for
|
|
$parent_attributes = $product->get_attributes();
|
|
|
|
foreach ($parent_attributes as $parent_attr) {
|
|
if (!$parent_attr->get_variation()) {
|
|
continue; // Skip non-variation attributes
|
|
}
|
|
|
|
$attr_name = $parent_attr->get_name();
|
|
$clean_name = $attr_name;
|
|
|
|
// Get the variation's value for this attribute
|
|
if (strpos($attr_name, 'pa_') === 0) {
|
|
// Global/taxonomy attribute
|
|
$clean_name = wc_attribute_label($attr_name);
|
|
$value = $variation->get_attribute($attr_name);
|
|
|
|
// Convert slug to term name
|
|
if (!empty($value)) {
|
|
$term = get_term_by('slug', $value, $attr_name);
|
|
$value = $term ? $term->name : $value;
|
|
}
|
|
} else {
|
|
// Custom attribute - stored as lowercase in meta
|
|
$meta_key = 'attribute_' . strtolower($attr_name);
|
|
$value = get_post_meta($variation_id, $meta_key, true);
|
|
|
|
// Capitalize the attribute name for display to match admin SPA
|
|
$clean_name = ucfirst($attr_name);
|
|
}
|
|
|
|
// Only add if value exists
|
|
if (!empty($value)) {
|
|
$formatted_attributes[$clean_name] = $value;
|
|
}
|
|
}
|
|
|
|
$image_url = $image ? $image[0] : '';
|
|
if (!$image_url && $variation->get_image_id()) {
|
|
$image_url = wp_get_attachment_url($variation->get_image_id());
|
|
}
|
|
|
|
$variations[] = [
|
|
'id' => $variation->get_id(),
|
|
'sku' => $variation->get_sku(),
|
|
'price' => $variation->get_price(),
|
|
'regular_price' => $variation->get_regular_price(),
|
|
'sale_price' => $variation->get_sale_price(),
|
|
'stock_status' => $variation->get_stock_status(),
|
|
'stock_quantity' => $variation->get_stock_quantity(),
|
|
'manage_stock' => $variation->get_manage_stock(),
|
|
'attributes' => $formatted_attributes,
|
|
'image_id' => $variation->get_image_id(),
|
|
'image_url' => $image_url,
|
|
'image' => $image_url, // For form compatibility
|
|
];
|
|
}
|
|
}
|
|
return $variations;
|
|
}
|
|
|
|
/**
|
|
* Save product attributes
|
|
*/
|
|
private static function save_product_attributes($product, $attributes_data) {
|
|
$attributes = [];
|
|
foreach ($attributes_data as $attr_data) {
|
|
$attribute = new \WC_Product_Attribute();
|
|
$attribute->set_name($attr_data['name']);
|
|
$attribute->set_options($attr_data['options']);
|
|
$attribute->set_position($attr_data['position'] ?? 0);
|
|
$attribute->set_visible($attr_data['visible'] ?? true);
|
|
$attribute->set_variation($attr_data['variation'] ?? true);
|
|
$attributes[] = $attribute;
|
|
}
|
|
$product->set_attributes($attributes);
|
|
$product->save();
|
|
}
|
|
|
|
/**
|
|
* Save product variations
|
|
*/
|
|
private static function save_product_variations($product, $variations_data) {
|
|
// Get existing variation IDs
|
|
$existing_variation_ids = $product->get_children();
|
|
$variations_to_keep = [];
|
|
|
|
foreach ($variations_data as $var_data) {
|
|
if (isset($var_data['id']) && $var_data['id']) {
|
|
$variation = wc_get_product($var_data['id']);
|
|
if (!$variation) continue;
|
|
$variations_to_keep[] = $var_data['id'];
|
|
} else {
|
|
$variation = new WC_Product_Variation();
|
|
$variation->set_parent_id($product->get_id());
|
|
}
|
|
|
|
// Build attributes array
|
|
$wc_attributes = [];
|
|
if (isset($var_data['attributes']) && is_array($var_data['attributes'])) {
|
|
$parent_attributes = $product->get_attributes();
|
|
|
|
foreach ($var_data['attributes'] as $display_name => $value) {
|
|
if (empty($value)) continue;
|
|
|
|
foreach ($parent_attributes as $attr_name => $parent_attr) {
|
|
if (!$parent_attr->get_variation()) continue;
|
|
if (strcasecmp($display_name, $attr_name) === 0 || strcasecmp($display_name, ucfirst($attr_name)) === 0) {
|
|
$wc_attributes[strtolower($attr_name)] = strtolower($value);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($wc_attributes)) {
|
|
$variation->set_attributes($wc_attributes);
|
|
}
|
|
|
|
if (isset($var_data['sku'])) $variation->set_sku($var_data['sku']);
|
|
|
|
// Set prices - if not provided, use parent's price as fallback
|
|
if (isset($var_data['regular_price']) && $var_data['regular_price'] !== '') {
|
|
$variation->set_regular_price($var_data['regular_price']);
|
|
} elseif (!$variation->get_regular_price()) {
|
|
// Fallback to parent price if variation has no price
|
|
$parent_price = $product->get_regular_price();
|
|
if ($parent_price) {
|
|
$variation->set_regular_price($parent_price);
|
|
}
|
|
}
|
|
|
|
if (isset($var_data['sale_price']) && $var_data['sale_price'] !== '') {
|
|
$variation->set_sale_price($var_data['sale_price']);
|
|
}
|
|
|
|
if (isset($var_data['stock_status'])) $variation->set_stock_status($var_data['stock_status']);
|
|
if (isset($var_data['manage_stock'])) $variation->set_manage_stock($var_data['manage_stock']);
|
|
if (isset($var_data['stock_quantity'])) $variation->set_stock_quantity($var_data['stock_quantity']);
|
|
|
|
if (isset($var_data['image']) && !empty($var_data['image'])) {
|
|
$image_id = attachment_url_to_postid($var_data['image']);
|
|
if ($image_id) $variation->set_image_id($image_id);
|
|
} elseif (isset($var_data['image_id'])) {
|
|
$variation->set_image_id($var_data['image_id']);
|
|
}
|
|
|
|
// Save variation first
|
|
$saved_id = $variation->save();
|
|
$variations_to_keep[] = $saved_id;
|
|
|
|
// Manually save attributes using direct database insert
|
|
if (!empty($wc_attributes)) {
|
|
global $wpdb;
|
|
|
|
foreach ($wc_attributes as $attr_name => $attr_value) {
|
|
$meta_key = 'attribute_' . $attr_name;
|
|
|
|
$wpdb->delete(
|
|
$wpdb->postmeta,
|
|
['post_id' => $saved_id, 'meta_key' => $meta_key],
|
|
['%d', '%s']
|
|
);
|
|
|
|
$wpdb->insert(
|
|
$wpdb->postmeta,
|
|
[
|
|
'post_id' => $saved_id,
|
|
'meta_key' => $meta_key,
|
|
'meta_value' => $attr_value
|
|
],
|
|
['%d', '%s', '%s']
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete variations that are no longer in the list
|
|
$variations_to_delete = array_diff($existing_variation_ids, $variations_to_keep);
|
|
foreach ($variations_to_delete as $variation_id) {
|
|
$variation_to_delete = wc_get_product($variation_id);
|
|
if ($variation_to_delete) {
|
|
$variation_to_delete->delete(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get product meta data for API exposure (Level 1 compatibility)
|
|
* Filters out internal meta unless explicitly allowed
|
|
*
|
|
* @param \WC_Product $product
|
|
* @return array
|
|
*/
|
|
private static function get_product_meta_data($product) {
|
|
$meta_data = [];
|
|
|
|
foreach ($product->get_meta_data() as $meta) {
|
|
$key = $meta->key;
|
|
$value = $meta->value;
|
|
|
|
// Skip internal WooCommerce meta (starts with _wc_)
|
|
if (strpos($key, '_wc_') === 0) {
|
|
continue;
|
|
}
|
|
|
|
// Skip WooNooW internal meta
|
|
if (strpos($key, '_woonoow_') === 0) {
|
|
continue;
|
|
}
|
|
|
|
// Public meta (no underscore) - always expose
|
|
if (strpos($key, '_') !== 0) {
|
|
$meta_data[$key] = $value;
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
return $meta_data;
|
|
}
|
|
|
|
/**
|
|
* Update product meta data from API (Level 1 compatibility)
|
|
*
|
|
* @param \WC_Product $product
|
|
* @param array $meta_updates
|
|
*/
|
|
private static function update_product_meta_data($product, $meta_updates) {
|
|
// Get allowed updatable meta keys
|
|
// Core has ZERO defaults - plugins register via filter
|
|
$allowed = apply_filters('woonoow/product_updatable_meta', [], $product);
|
|
|
|
foreach ($meta_updates as $key => $value) {
|
|
// Skip internal WooCommerce meta
|
|
if (strpos($key, '_wc_') === 0) {
|
|
continue;
|
|
}
|
|
|
|
// Skip WooNooW internal meta
|
|
if (strpos($key, '_woonoow_') === 0) {
|
|
continue;
|
|
}
|
|
|
|
// Public meta (no underscore) - always allow
|
|
if (strpos($key, '_') !== 0) {
|
|
$product->update_meta_data($key, $value);
|
|
continue;
|
|
}
|
|
|
|
// Private meta - check if allowed
|
|
if (in_array($key, $allowed, true)) {
|
|
$product->update_meta_data($key, $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create product category
|
|
*/
|
|
public static function create_category(WP_REST_Request $request) {
|
|
try {
|
|
$name = sanitize_text_field($request->get_param('name'));
|
|
$slug = sanitize_title($request->get_param('slug') ?: $name);
|
|
$description = sanitize_textarea_field($request->get_param('description') ?: '');
|
|
$parent = (int) ($request->get_param('parent') ?: 0);
|
|
|
|
$result = wp_insert_term($name, 'product_cat', [
|
|
'slug' => $slug,
|
|
'description' => $description,
|
|
'parent' => $parent,
|
|
]);
|
|
|
|
if (is_wp_error($result)) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $result->get_error_message(),
|
|
], 400);
|
|
}
|
|
|
|
$term = get_term($result['term_id'], 'product_cat');
|
|
|
|
return new WP_REST_Response([
|
|
'success' => true,
|
|
'data' => [
|
|
'term_id' => $term->term_id,
|
|
'name' => $term->name,
|
|
'slug' => $term->slug,
|
|
'description' => $term->description,
|
|
'parent' => $term->parent,
|
|
'count' => $term->count,
|
|
],
|
|
], 201);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update product category
|
|
*/
|
|
public static function update_category(WP_REST_Request $request) {
|
|
try {
|
|
$term_id = (int) $request->get_param('id');
|
|
$name = sanitize_text_field($request->get_param('name'));
|
|
$slug = sanitize_title($request->get_param('slug') ?: $name);
|
|
$description = sanitize_textarea_field($request->get_param('description') ?: '');
|
|
$parent = (int) ($request->get_param('parent') ?: 0);
|
|
|
|
$result = wp_update_term($term_id, 'product_cat', [
|
|
'name' => $name,
|
|
'slug' => $slug,
|
|
'description' => $description,
|
|
'parent' => $parent,
|
|
]);
|
|
|
|
if (is_wp_error($result)) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $result->get_error_message(),
|
|
], 400);
|
|
}
|
|
|
|
$term = get_term($term_id, 'product_cat');
|
|
|
|
return new WP_REST_Response([
|
|
'success' => true,
|
|
'data' => [
|
|
'term_id' => $term->term_id,
|
|
'name' => $term->name,
|
|
'slug' => $term->slug,
|
|
'description' => $term->description,
|
|
'parent' => $term->parent,
|
|
'count' => $term->count,
|
|
],
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete product category
|
|
*/
|
|
public static function delete_category(WP_REST_Request $request) {
|
|
try {
|
|
$term_id = (int) $request->get_param('id');
|
|
|
|
$result = wp_delete_term($term_id, 'product_cat');
|
|
|
|
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,
|
|
'message' => 'Category deleted successfully',
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create product tag
|
|
*/
|
|
public static function create_tag(WP_REST_Request $request) {
|
|
try {
|
|
$name = sanitize_text_field($request->get_param('name'));
|
|
$slug = sanitize_title($request->get_param('slug') ?: $name);
|
|
$description = sanitize_textarea_field($request->get_param('description') ?: '');
|
|
|
|
$result = wp_insert_term($name, 'product_tag', [
|
|
'slug' => $slug,
|
|
'description' => $description,
|
|
]);
|
|
|
|
if (is_wp_error($result)) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $result->get_error_message(),
|
|
], 400);
|
|
}
|
|
|
|
$term = get_term($result['term_id'], 'product_tag');
|
|
|
|
return new WP_REST_Response([
|
|
'success' => true,
|
|
'data' => [
|
|
'term_id' => $term->term_id,
|
|
'name' => $term->name,
|
|
'slug' => $term->slug,
|
|
'description' => $term->description,
|
|
'count' => $term->count,
|
|
],
|
|
], 201);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update product tag
|
|
*/
|
|
public static function update_tag(WP_REST_Request $request) {
|
|
try {
|
|
$term_id = (int) $request->get_param('id');
|
|
$name = sanitize_text_field($request->get_param('name'));
|
|
$slug = sanitize_title($request->get_param('slug') ?: $name);
|
|
$description = sanitize_textarea_field($request->get_param('description') ?: '');
|
|
|
|
$result = wp_update_term($term_id, 'product_tag', [
|
|
'name' => $name,
|
|
'slug' => $slug,
|
|
'description' => $description,
|
|
]);
|
|
|
|
if (is_wp_error($result)) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $result->get_error_message(),
|
|
], 400);
|
|
}
|
|
|
|
$term = get_term($term_id, 'product_tag');
|
|
|
|
return new WP_REST_Response([
|
|
'success' => true,
|
|
'data' => [
|
|
'term_id' => $term->term_id,
|
|
'name' => $term->name,
|
|
'slug' => $term->slug,
|
|
'description' => $term->description,
|
|
'count' => $term->count,
|
|
],
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete product tag
|
|
*/
|
|
public static function delete_tag(WP_REST_Request $request) {
|
|
try {
|
|
$term_id = (int) $request->get_param('id');
|
|
|
|
$result = wp_delete_term($term_id, 'product_tag');
|
|
|
|
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,
|
|
'message' => 'Tag deleted successfully',
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create product attribute
|
|
*/
|
|
public static function create_attribute(WP_REST_Request $request) {
|
|
try {
|
|
$label = sanitize_text_field($request->get_param('label'));
|
|
$name = sanitize_title($request->get_param('name') ?: $label);
|
|
$type = sanitize_text_field($request->get_param('type') ?: 'select');
|
|
$orderby = sanitize_text_field($request->get_param('orderby') ?: 'menu_order');
|
|
$public = (int) ($request->get_param('public') ?: 1);
|
|
|
|
$attribute_id = wc_create_attribute([
|
|
'name' => $label,
|
|
'slug' => $name,
|
|
'type' => $type,
|
|
'order_by' => $orderby,
|
|
'has_archives' => $public,
|
|
]);
|
|
|
|
if (is_wp_error($attribute_id)) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $attribute_id->get_error_message(),
|
|
], 400);
|
|
}
|
|
|
|
$attribute = wc_get_attribute($attribute_id);
|
|
|
|
return new WP_REST_Response([
|
|
'success' => true,
|
|
'data' => [
|
|
'attribute_id' => $attribute->id,
|
|
'attribute_name' => $attribute->slug,
|
|
'attribute_label' => $attribute->name,
|
|
'attribute_type' => $attribute->type,
|
|
'attribute_orderby' => $attribute->order_by,
|
|
'attribute_public' => $attribute->has_archives,
|
|
],
|
|
], 201);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update product attribute
|
|
*/
|
|
public static function update_attribute(WP_REST_Request $request) {
|
|
try {
|
|
$attribute_id = (int) $request->get_param('id');
|
|
$label = sanitize_text_field($request->get_param('label'));
|
|
$name = sanitize_title($request->get_param('name') ?: $label);
|
|
$type = sanitize_text_field($request->get_param('type') ?: 'select');
|
|
$orderby = sanitize_text_field($request->get_param('orderby') ?: 'menu_order');
|
|
$public = (int) ($request->get_param('public') ?: 1);
|
|
|
|
$result = wc_update_attribute($attribute_id, [
|
|
'name' => $label,
|
|
'slug' => $name,
|
|
'type' => $type,
|
|
'order_by' => $orderby,
|
|
'has_archives' => $public,
|
|
]);
|
|
|
|
if (is_wp_error($result)) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $result->get_error_message(),
|
|
], 400);
|
|
}
|
|
|
|
$attribute = wc_get_attribute($attribute_id);
|
|
|
|
return new WP_REST_Response([
|
|
'success' => true,
|
|
'data' => [
|
|
'attribute_id' => $attribute->id,
|
|
'attribute_name' => $attribute->slug,
|
|
'attribute_label' => $attribute->name,
|
|
'attribute_type' => $attribute->type,
|
|
'attribute_orderby' => $attribute->order_by,
|
|
'attribute_public' => $attribute->has_archives,
|
|
],
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete product attribute
|
|
*/
|
|
public static function delete_attribute(WP_REST_Request $request) {
|
|
try {
|
|
$attribute_id = (int) $request->get_param('id');
|
|
|
|
$result = wc_delete_attribute($attribute_id);
|
|
|
|
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,
|
|
'message' => 'Attribute deleted successfully',
|
|
], 200);
|
|
} catch (\Exception $e) {
|
|
return new WP_REST_Response([
|
|
'success' => false,
|
|
'message' => $e->getMessage(),
|
|
], 500);
|
|
}
|
|
}
|
|
}
|