228 lines
6.1 KiB
PHP
228 lines
6.1 KiB
PHP
<?php
|
|
class WPI_Product_Mapper
|
|
{
|
|
|
|
public static function upsert($data)
|
|
{
|
|
if (empty($data['sku'])) return;
|
|
|
|
$product_id = wc_get_product_id_by_sku($data['sku']);
|
|
|
|
$product = $product_id
|
|
? wc_get_product($product_id)
|
|
: new WC_Product_Simple();
|
|
|
|
$product->set_name($data['name'] ?? '');
|
|
$product->set_sku($data['sku']);
|
|
$product->set_regular_price($data['price'] ?? 0);
|
|
$product->set_stock_quantity($data['stock'] ?? 0);
|
|
$product->set_manage_stock(true);
|
|
|
|
|
|
if (!empty($data['description'])) {
|
|
$product->set_description(wp_kses_post($data['description']));
|
|
}
|
|
|
|
if (!empty($data['short_description'])) {
|
|
$product->set_short_description(wp_kses_post($data['short_description']));
|
|
}
|
|
|
|
return $product->save();
|
|
}
|
|
|
|
protected static function attach_images(int $product_id, array $urls)
|
|
{
|
|
require_once ABSPATH . 'wp-admin/includes/file.php';
|
|
require_once ABSPATH . 'wp-admin/includes/media.php';
|
|
require_once ABSPATH . 'wp-admin/includes/image.php';
|
|
|
|
$gallery_ids = [];
|
|
|
|
foreach ($urls as $index => $url) {
|
|
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
|
continue;
|
|
}
|
|
|
|
$attachment_id = media_sideload_image($url, $product_id, null, 'id');
|
|
|
|
if (is_wp_error($attachment_id)) {
|
|
continue;
|
|
}
|
|
|
|
if ($index === 0) {
|
|
set_post_thumbnail($product_id, $attachment_id);
|
|
} else {
|
|
$gallery_ids[] = $attachment_id;
|
|
}
|
|
}
|
|
|
|
if ($gallery_ids) {
|
|
update_post_meta(
|
|
$product_id,
|
|
'_product_image_gallery',
|
|
implode(',', $gallery_ids)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
public static function upsert_from_api(array $data)
|
|
{
|
|
if (empty($data['sku'])) return;
|
|
|
|
$product_id = self::upsert($data);
|
|
|
|
if (!$product_id) return;
|
|
|
|
if (!empty($data['brand'])) {
|
|
self::sync_brand($product_id, $data['brand']);
|
|
}
|
|
|
|
if (!empty($data['categories'])) {
|
|
self::sync_categories($product_id, $data['categories']);
|
|
}
|
|
|
|
if (!empty($data['images'])) {
|
|
self::sync_images($product_id, $data['images']);
|
|
}
|
|
|
|
return $product_id;
|
|
}
|
|
|
|
protected static function sync_categories(int $product_id, array $categories)
|
|
{
|
|
if (empty($categories)) return;
|
|
|
|
$term_ids = [];
|
|
|
|
foreach ($categories as $cat_id) {
|
|
// chỉ nhận số
|
|
if (is_numeric($cat_id)) {
|
|
$term_ids[] = (int) $cat_id;
|
|
}
|
|
}
|
|
|
|
if (!$term_ids) return;
|
|
|
|
// gán trực tiếp, KHÔNG tạo mới
|
|
wp_set_object_terms(
|
|
$product_id,
|
|
array_unique($term_ids),
|
|
'product_cat'
|
|
);
|
|
}
|
|
|
|
|
|
|
|
protected static function sync_images(int $product_id, array $images)
|
|
{
|
|
if (empty($images)) return;
|
|
|
|
$urls = array_filter(array_map('trim', $images));
|
|
if (!$urls) return;
|
|
|
|
self::attach_images($product_id, $urls);
|
|
}
|
|
|
|
|
|
protected static function sync_brand(int $product_id, string $brand)
|
|
{
|
|
$brand = trim($brand);
|
|
if (!$brand) return;
|
|
|
|
$taxonomy = 'product_brand';
|
|
|
|
// Kiểm tra taxonomy tồn tại
|
|
if (!taxonomy_exists($taxonomy)) {
|
|
return;
|
|
}
|
|
|
|
// Check brand đã tồn tại chưa
|
|
$term = term_exists($brand, $taxonomy);
|
|
|
|
// Chưa có → tạo mới
|
|
if (!$term) {
|
|
$term = wp_insert_term($brand, $taxonomy);
|
|
}
|
|
|
|
if (is_wp_error($term)) {
|
|
return;
|
|
}
|
|
|
|
$term_id = (int) $term['term_id'];
|
|
|
|
// Gán brand cho product
|
|
wp_set_object_terms($product_id, [$term_id], $taxonomy);
|
|
|
|
// Đảm bảo attribute xuất hiện trong product
|
|
$product = wc_get_product($product_id);
|
|
if (!$product) return;
|
|
|
|
$attributes = $product->get_attributes();
|
|
|
|
if (!isset($attributes[$taxonomy])) {
|
|
$attr = new WC_Product_Attribute();
|
|
$attr->set_name($taxonomy);
|
|
$attr->set_options([$brand]);
|
|
$attr->set_visible(true);
|
|
$attr->set_variation(false);
|
|
|
|
$attributes[$taxonomy] = $attr;
|
|
$product->set_attributes($attributes);
|
|
$product->save();
|
|
}
|
|
}
|
|
|
|
protected static function create_wp_categories_from_tree(
|
|
array $categories,
|
|
int $parent_id = 0,
|
|
string $taxonomy = 'category'
|
|
) {
|
|
foreach ($categories as $item) {
|
|
if (empty($item['name']) || empty($item['id'])) {
|
|
continue;
|
|
}
|
|
|
|
$name = $item['name'];
|
|
$slug = sanitize_title($name);
|
|
$description = (string) $item['id']; // 👈 external ID
|
|
|
|
// Check if term exists under same parent
|
|
$existing = term_exists($slug, $taxonomy, $parent_id);
|
|
|
|
if ($existing) {
|
|
$term_id = is_array($existing)
|
|
? $existing['term_id']
|
|
: $existing;
|
|
|
|
// Update description if changed
|
|
wp_update_term($term_id, $taxonomy, [
|
|
'description' => $description,
|
|
]);
|
|
} else {
|
|
$result = wp_insert_term($name, $taxonomy, [
|
|
'slug' => $slug,
|
|
'parent' => $parent_id,
|
|
'description' => $description,
|
|
]);
|
|
|
|
if (is_wp_error($result)) {
|
|
error_log('[CATEGORY_SYNC] ' . $result->get_error_message());
|
|
continue;
|
|
}
|
|
|
|
$term_id = $result['term_id'];
|
|
}
|
|
|
|
// Recurse children
|
|
if (!empty($item['children']) && is_array($item['children'])) {
|
|
self::create_wp_categories_from_tree(
|
|
$item['children'],
|
|
$term_id,
|
|
$taxonomy
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|