| |
| <?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| if (!function_exists('cortex_ecommerce_check_woo')) {
|
| function cortex_ecommerce_check_woo() {
|
| return class_exists('WooCommerce');
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| add_action('rest_api_init', function() {
|
|
|
|
|
| if (!cortex_ecommerce_check_woo()) {
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/status', array(
|
| 'methods' => 'GET',
|
| 'callback' => function() {
|
| return new WP_Error('woo_not_active', 'WooCommerce is not active on this site', array('status' => 503));
|
| },
|
| 'permission_callback' => '__return_true',
|
| ));
|
| return;
|
| }
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/status', array(
|
| 'methods' => 'GET',
|
| 'callback' => 'cortex_ecommerce_status',
|
| 'permission_callback' => '__return_true',
|
| ));
|
|
|
|
|
|
|
|
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/products', array(
|
| 'methods' => 'GET',
|
| 'callback' => 'cortex_ecommerce_get_products',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/products/(?P<id>\d+)', array(
|
| 'methods' => 'GET',
|
| 'callback' => 'cortex_ecommerce_get_product',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/products/(?P<id>\d+)', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_update_product',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/products/bulk', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_bulk_update_products',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/products/bulk-get', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_bulk_get_products',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/products/mass-categorize', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_mass_categorize_products',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
|
|
|
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-categories', array(
|
| 'methods' => 'GET',
|
| 'callback' => 'cortex_ecommerce_get_product_categories',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-categories/(?P<id>\d+)', array(
|
| 'methods' => 'GET',
|
| 'callback' => 'cortex_ecommerce_get_product_category',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-categories', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_create_product_category',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-categories/(?P<id>\d+)', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_update_product_category',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-categories/(?P<id>\d+)', array(
|
| 'methods' => 'DELETE',
|
| 'callback' => 'cortex_ecommerce_delete_product_category',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-categories/bulk', array(
|
| 'methods' => 'POST',
|
| 'callback' => 'cortex_ecommerce_bulk_update_product_categories',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
|
|
|
|
|
|
|
|
|
|
|
|
| register_rest_route('cortex-ecommerce/v1', '/product-tags', array(
|
| 'methods' => 'GET',
|
| 'callback' => 'cortex_ecommerce_get_product_tags',
|
| 'permission_callback' => 'cortex_ecommerce_permission_check',
|
| ));
|
| });
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_permission_check() {
|
| return current_user_can('edit_products');
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_status() {
|
| $product_count = wp_count_posts('product');
|
| $category_count = wp_count_terms('product_cat');
|
|
|
| return array(
|
| 'status' => 'active',
|
| 'api_version' => '1.0',
|
| 'woocommerce_active' => true,
|
| 'woocommerce_version' => defined('WC_VERSION') ? WC_VERSION : 'unknown',
|
| 'products' => array(
|
| 'published' => intval($product_count->publish),
|
| 'draft' => intval($product_count->draft),
|
| 'total' => intval($product_count->publish) + intval($product_count->draft)
|
| ),
|
| 'product_categories' => is_wp_error($category_count) ? 0 : intval($category_count),
|
| 'endpoints' => array(
|
| 'products' => '/cortex-ecommerce/v1/products',
|
| 'product_single' => '/cortex-ecommerce/v1/products/{id}',
|
| 'products_bulk' => '/cortex-ecommerce/v1/products/bulk',
|
| 'products_bulk_get' => '/cortex-ecommerce/v1/products/bulk-get',
|
| 'products_mass_categorize' => '/cortex-ecommerce/v1/products/mass-categorize',
|
| 'product_categories' => '/cortex-ecommerce/v1/product-categories',
|
| 'product_category_single' => '/cortex-ecommerce/v1/product-categories/{id}',
|
| 'product_tags' => '/cortex-ecommerce/v1/product-tags'
|
| )
|
| );
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_get_product_cats($product_id) {
|
| $terms = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'all'));
|
| $cat_data = array();
|
|
|
| if (!is_wp_error($terms)) {
|
| foreach ($terms as $term) {
|
| $cat_data[] = array(
|
| 'id' => $term->term_id,
|
| 'name' => $term->name,
|
| 'slug' => $term->slug,
|
| 'link' => get_term_link($term)
|
| );
|
| }
|
| }
|
|
|
| return $cat_data;
|
| }
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_get_product_tag_data($product_id) {
|
| $terms = wp_get_post_terms($product_id, 'product_tag', array('fields' => 'all'));
|
| $tag_data = array();
|
|
|
| if (!is_wp_error($terms)) {
|
| foreach ($terms as $term) {
|
| $tag_data[] = array(
|
| 'id' => $term->term_id,
|
| 'name' => $term->name,
|
| 'slug' => $term->slug
|
| );
|
| }
|
| }
|
|
|
| return $tag_data;
|
| }
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_build_product_data($post, $include_categories = true) {
|
|
|
| $product = wc_get_product($post->ID);
|
|
|
| if (!$product) {
|
| return null;
|
| }
|
|
|
|
|
| $excerpt = $post->post_excerpt;
|
| if (empty($excerpt)) {
|
| $excerpt = '';
|
| }
|
|
|
|
|
| $excerpt_word_count = str_word_count(strip_tags($excerpt));
|
|
|
|
|
| $focus_keyword = get_post_meta($post->ID, 'rank_math_focus_keyword', true);
|
| $focus_keywords_array = array_map('trim', explode(',', $focus_keyword));
|
| $focus_keyword_count = count(array_filter($focus_keywords_array));
|
| $primary_keyword = !empty($focus_keywords_array[0]) ? $focus_keywords_array[0] : '';
|
|
|
|
|
| $item = array(
|
| 'id' => $post->ID,
|
| 'slug' => $post->post_name,
|
| 'post_type' => 'product',
|
| 'product_type' => $product->get_type(),
|
| 'link' => get_permalink($post->ID),
|
| 'status' => $post->post_status,
|
|
|
|
|
| 'post_title' => $post->post_title,
|
| 'rank_math_title' => get_post_meta($post->ID, 'rank_math_title', true),
|
| 'rank_math_description' => get_post_meta($post->ID, 'rank_math_description', true),
|
| 'rank_math_focus_keyword' => $focus_keyword,
|
| 'rank_math_facebook_title' => get_post_meta($post->ID, 'rank_math_facebook_title', true),
|
| 'rank_math_facebook_description' => get_post_meta($post->ID, 'rank_math_facebook_description', true),
|
| 'rank_math_twitter_title' => get_post_meta($post->ID, 'rank_math_twitter_title', true),
|
| 'rank_math_twitter_description' => get_post_meta($post->ID, 'rank_math_twitter_description', true),
|
| 'excerpt' => $excerpt,
|
|
|
|
|
| 'woo_context' => array(
|
| 'sku' => $product->get_sku(),
|
| 'price' => $product->get_price(),
|
| 'regular_price' => $product->get_regular_price(),
|
| 'sale_price' => $product->get_sale_price(),
|
| 'on_sale' => $product->is_on_sale(),
|
| 'stock_status' => $product->get_stock_status(),
|
| 'stock_quantity' => $product->get_stock_quantity(),
|
| 'total_sales' => $product->get_total_sales(),
|
| 'average_rating' => $product->get_average_rating(),
|
| 'review_count' => $product->get_review_count(),
|
| 'is_featured' => $product->is_featured(),
|
| 'is_virtual' => $product->is_virtual(),
|
| 'is_downloadable' => $product->is_downloadable(),
|
| ),
|
|
|
|
|
| 'audit_meta' => array(
|
| 'post_title_chars' => strlen($post->post_title),
|
| 'meta_title_chars' => strlen(get_post_meta($post->ID, 'rank_math_title', true)),
|
| 'meta_desc_chars' => strlen(get_post_meta($post->ID, 'rank_math_description', true)),
|
| 'excerpt_words' => $excerpt_word_count,
|
| 'focus_keyword_count' => $focus_keyword_count,
|
| 'primary_keyword' => $primary_keyword,
|
| 'fb_title_chars' => strlen(get_post_meta($post->ID, 'rank_math_facebook_title', true)),
|
| 'fb_desc_chars' => strlen(get_post_meta($post->ID, 'rank_math_facebook_description', true)),
|
| 'twitter_title_chars' => strlen(get_post_meta($post->ID, 'rank_math_twitter_title', true)),
|
| 'twitter_desc_chars' => strlen(get_post_meta($post->ID, 'rank_math_twitter_description', true)),
|
| 'has_price_in_meta' => (
|
| stripos(get_post_meta($post->ID, 'rank_math_description', true), '$') !== false ||
|
| stripos(get_post_meta($post->ID, 'rank_math_description', true), 'price') !== false
|
| ),
|
| ),
|
| );
|
|
|
| if ($include_categories) {
|
| $item['categories'] = cortex_ecommerce_get_product_cats($post->ID);
|
| $item['category_ids'] = wp_get_post_terms($post->ID, 'product_cat', array('fields' => 'ids'));
|
| $item['tags'] = cortex_ecommerce_get_product_tag_data($post->ID);
|
| $item['tag_ids'] = wp_get_post_terms($post->ID, 'product_tag', array('fields' => 'ids'));
|
| }
|
|
|
| return $item;
|
| }
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_process_product_update($product_id, $data) {
|
| $post = get_post($product_id);
|
|
|
| if (!$post || $post->post_type !== 'product') {
|
| return array('success' => false, 'error' => 'Product not found', 'id' => $product_id);
|
| }
|
|
|
| $updated = array();
|
| $post_updates = array();
|
|
|
|
|
| if (isset($data['post_title'])) {
|
| $post_updates['post_title'] = sanitize_text_field($data['post_title']);
|
| $updated['post_title'] = $data['post_title'];
|
| }
|
|
|
|
|
| if (isset($data['slug'])) {
|
| $post_updates['post_name'] = sanitize_title($data['slug']);
|
| $updated['slug'] = $data['slug'];
|
| }
|
|
|
|
|
| if (isset($data['excerpt'])) {
|
| $post_updates['post_excerpt'] = wp_kses_post($data['excerpt']);
|
| $updated['excerpt'] = $data['excerpt'];
|
| }
|
|
|
|
|
| if (isset($data['short_description'])) {
|
| $post_updates['post_excerpt'] = wp_kses_post($data['short_description']);
|
| $updated['short_description'] = $data['short_description'];
|
| }
|
|
|
| if (!empty($post_updates)) {
|
| $post_updates['ID'] = $product_id;
|
| wp_update_post($post_updates);
|
| }
|
|
|
|
|
|
|
| if (isset($data['category_ids']) && is_array($data['category_ids'])) {
|
| $category_ids = array_map('intval', $data['category_ids']);
|
| wp_set_post_terms($product_id, $category_ids, 'product_cat');
|
| $updated['category_ids'] = $category_ids;
|
| }
|
|
|
|
|
| if (isset($data['categories']) && is_array($data['categories'])) {
|
| $cat_ids = array();
|
| foreach ($data['categories'] as $cat_name) {
|
| $cat_name = sanitize_text_field($cat_name);
|
| $term = get_term_by('name', $cat_name, 'product_cat');
|
| if ($term) {
|
| $cat_ids[] = $term->term_id;
|
| } else {
|
| $new_term = wp_insert_term($cat_name, 'product_cat');
|
| if (!is_wp_error($new_term)) {
|
| $cat_ids[] = $new_term['term_id'];
|
| }
|
| }
|
| }
|
| wp_set_post_terms($product_id, $cat_ids, 'product_cat');
|
| $updated['categories'] = $data['categories'];
|
| $updated['category_ids'] = $cat_ids;
|
| }
|
|
|
|
|
| if (isset($data['add_categories']) && is_array($data['add_categories'])) {
|
| $existing_cats = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
|
| $new_cats = array();
|
|
|
| foreach ($data['add_categories'] as $cat) {
|
| if (is_numeric($cat)) {
|
| $new_cats[] = intval($cat);
|
| } else {
|
| $cat_name = sanitize_text_field($cat);
|
| $term = get_term_by('name', $cat_name, 'product_cat');
|
| if ($term) {
|
| $new_cats[] = $term->term_id;
|
| } else {
|
| $new_term = wp_insert_term($cat_name, 'product_cat');
|
| if (!is_wp_error($new_term)) {
|
| $new_cats[] = $new_term['term_id'];
|
| }
|
| }
|
| }
|
| }
|
|
|
| $merged = array_unique(array_merge($existing_cats, $new_cats));
|
| wp_set_post_terms($product_id, $merged, 'product_cat');
|
| $updated['add_categories'] = $data['add_categories'];
|
| }
|
|
|
|
|
| if (isset($data['remove_categories']) && is_array($data['remove_categories'])) {
|
| $existing_cats = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
|
| $remove_ids = array();
|
|
|
| foreach ($data['remove_categories'] as $cat) {
|
| if (is_numeric($cat)) {
|
| $remove_ids[] = intval($cat);
|
| } else {
|
| $term = get_term_by('name', sanitize_text_field($cat), 'product_cat');
|
| if ($term) {
|
| $remove_ids[] = $term->term_id;
|
| }
|
| }
|
| }
|
|
|
| $remaining = array_diff($existing_cats, $remove_ids);
|
| wp_set_post_terms($product_id, $remaining, 'product_cat');
|
| $updated['remove_categories'] = $data['remove_categories'];
|
| }
|
|
|
|
|
| if (isset($data['tag_ids']) && is_array($data['tag_ids'])) {
|
| $tag_ids = array_map('intval', $data['tag_ids']);
|
| wp_set_post_terms($product_id, $tag_ids, 'product_tag');
|
| $updated['tag_ids'] = $tag_ids;
|
| }
|
|
|
| if (isset($data['tags']) && is_array($data['tags'])) {
|
| $tag_ids = array();
|
| foreach ($data['tags'] as $tag_name) {
|
| $tag_name = sanitize_text_field($tag_name);
|
| $term = get_term_by('name', $tag_name, 'product_tag');
|
| if ($term) {
|
| $tag_ids[] = $term->term_id;
|
| } else {
|
| $new_term = wp_insert_term($tag_name, 'product_tag');
|
| if (!is_wp_error($new_term)) {
|
| $tag_ids[] = $new_term['term_id'];
|
| }
|
| }
|
| }
|
| wp_set_post_terms($product_id, $tag_ids, 'product_tag');
|
| $updated['tags'] = $data['tags'];
|
| }
|
|
|
|
|
| $meta_fields = array(
|
| 'rank_math_title',
|
| 'rank_math_description',
|
| 'rank_math_focus_keyword',
|
| 'rank_math_facebook_title',
|
| 'rank_math_facebook_description',
|
| 'rank_math_twitter_title',
|
| 'rank_math_twitter_description'
|
| );
|
|
|
| foreach ($meta_fields as $field) {
|
| if (isset($data[$field])) {
|
| update_post_meta($product_id, $field, sanitize_text_field($data[$field]));
|
| $updated[$field] = $data[$field];
|
| }
|
| }
|
|
|
| return array(
|
| 'success' => true,
|
| 'id' => $product_id,
|
| 'updated_fields' => $updated,
|
| 'fields_count' => count($updated)
|
| );
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_get_products($request) {
|
| $per_page = $request->get_param('per_page') ? intval($request->get_param('per_page')) : 100;
|
| $page = $request->get_param('page') ? intval($request->get_param('page')) : 1;
|
| $status = $request->get_param('status') ? sanitize_text_field($request->get_param('status')) : 'publish';
|
| $category = $request->get_param('category') ? intval($request->get_param('category')) : null;
|
| $category_ids = $request->get_param('category_ids');
|
| $uncategorized = $request->get_param('uncategorized');
|
| $on_sale = $request->get_param('on_sale');
|
| $featured = $request->get_param('featured');
|
|
|
| $args = array(
|
| 'post_type' => 'product',
|
| 'posts_per_page' => min($per_page, 100),
|
| 'paged' => $page,
|
| 'post_status' => $status
|
| );
|
|
|
|
|
| if ($category) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => 'term_id',
|
| 'terms' => $category
|
| )
|
| );
|
| }
|
|
|
|
|
| if ($category_ids && is_array($category_ids)) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => 'term_id',
|
| 'terms' => array_map('intval', $category_ids),
|
| 'operator' => 'IN'
|
| )
|
| );
|
| }
|
|
|
|
|
| if ($uncategorized === 'true' || $uncategorized === '1') {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'operator' => 'NOT EXISTS'
|
| )
|
| );
|
| }
|
|
|
|
|
| if ($on_sale === 'true' || $on_sale === '1') {
|
| $args['meta_query'] = array(
|
| 'relation' => 'OR',
|
| array(
|
| 'key' => '_sale_price',
|
| 'value' => 0,
|
| 'compare' => '>',
|
| 'type' => 'NUMERIC'
|
| ),
|
| array(
|
| 'key' => '_min_variation_sale_price',
|
| 'value' => 0,
|
| 'compare' => '>',
|
| 'type' => 'NUMERIC'
|
| )
|
| );
|
| }
|
|
|
|
|
| if ($featured === 'true' || $featured === '1') {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_visibility',
|
| 'field' => 'name',
|
| 'terms' => 'featured',
|
| )
|
| );
|
| }
|
|
|
| $products = get_posts($args);
|
| $total = wp_count_posts('product');
|
| $total_count = ($status === 'publish') ? $total->publish : $total->$status;
|
|
|
| $result = array();
|
| $primary_keywords = array();
|
|
|
| foreach ($products as $product) {
|
| $item = cortex_ecommerce_build_product_data($product);
|
| if ($item) {
|
| $result[] = $item;
|
|
|
|
|
| if (!empty($item['audit_meta']['primary_keyword'])) {
|
| $pk = strtolower(trim($item['audit_meta']['primary_keyword']));
|
| if (!isset($primary_keywords[$pk])) {
|
| $primary_keywords[$pk] = array();
|
| }
|
| $primary_keywords[$pk][] = array(
|
| 'id' => $item['id'],
|
| 'slug' => $item['slug'],
|
| 'post_title' => $item['post_title'],
|
| 'sku' => $item['woo_context']['sku']
|
| );
|
| }
|
| }
|
| }
|
|
|
|
|
| $cannibalization = array();
|
| foreach ($primary_keywords as $keyword => $pages) {
|
| if (count($pages) > 1) {
|
| $cannibalization[] = array(
|
| 'keyword' => $keyword,
|
| 'count' => count($pages),
|
| 'products' => $pages
|
| );
|
| }
|
| }
|
|
|
| return array(
|
| 'items' => $result,
|
| 'pagination' => array(
|
| 'total' => intval($total_count),
|
| 'per_page' => $per_page,
|
| 'current_page' => $page,
|
| 'total_pages' => ceil($total_count / $per_page)
|
| ),
|
| 'cannibalization' => $cannibalization,
|
| 'cannibalization_count' => count($cannibalization)
|
| );
|
| }
|
|
|
| function cortex_ecommerce_get_product($request) {
|
| $product_id = $request->get_param('id');
|
| $post = get_post($product_id);
|
|
|
| if (!$post || $post->post_type !== 'product') {
|
| return new WP_Error('not_found', 'Product not found', array('status' => 404));
|
| }
|
|
|
| $item = cortex_ecommerce_build_product_data($post);
|
|
|
| if (!$item) {
|
| return new WP_Error('not_found', 'Product not found', array('status' => 404));
|
| }
|
|
|
| return $item;
|
| }
|
|
|
| function cortex_ecommerce_update_product($request) {
|
| $product_id = $request->get_param('id');
|
| $data = $request->get_params();
|
|
|
| $result = cortex_ecommerce_process_product_update($product_id, $data);
|
|
|
| if (!$result['success']) {
|
| return new WP_Error('not_found', $result['error'], array('status' => 404));
|
| }
|
|
|
| if (empty($result['updated_fields'])) {
|
| return new WP_Error('no_fields', 'No valid fields provided to update', array('status' => 400));
|
| }
|
|
|
| $post = get_post($product_id);
|
|
|
| return array(
|
| 'success' => true,
|
| 'product_id' => $product_id,
|
| 'updated_fields' => $result['updated_fields'],
|
| 'current_data' => cortex_ecommerce_build_product_data($post),
|
| 'message' => $result['fields_count'] . ' field(s) updated successfully'
|
| );
|
| }
|
|
|
| function cortex_ecommerce_bulk_update_products($request) {
|
| $items = $request->get_param('items');
|
|
|
| if (!$items || !is_array($items)) {
|
| return new WP_Error('invalid_payload', 'Expected "items" array in request body', array('status' => 400));
|
| }
|
|
|
| if (count($items) > 50) {
|
| return new WP_Error('too_many_items', 'Maximum 50 items per bulk request', array('status' => 400));
|
| }
|
|
|
| $results = array(
|
| 'success' => array(),
|
| 'failed' => array(),
|
| 'summary' => array(
|
| 'total' => count($items),
|
| 'succeeded' => 0,
|
| 'failed' => 0,
|
| 'fields_updated' => 0
|
| )
|
| );
|
|
|
| foreach ($items as $item) {
|
| if (!isset($item['id'])) {
|
| $results['failed'][] = array('error' => 'Missing id field', 'item' => $item);
|
| $results['summary']['failed']++;
|
| continue;
|
| }
|
|
|
| $product_id = intval($item['id']);
|
| $result = cortex_ecommerce_process_product_update($product_id, $item);
|
|
|
| if ($result['success']) {
|
| $results['success'][] = $result;
|
| $results['summary']['succeeded']++;
|
| $results['summary']['fields_updated'] += $result['fields_count'];
|
| } else {
|
| $results['failed'][] = $result;
|
| $results['summary']['failed']++;
|
| }
|
| }
|
|
|
| return $results;
|
| }
|
|
|
| function cortex_ecommerce_bulk_get_products($request) {
|
| $body = $request->get_json_params();
|
|
|
| $ids = isset($body['ids']) ? $body['ids'] : $request->get_param('ids');
|
| $category = isset($body['category']) ? $body['category'] : $request->get_param('category');
|
| $category_ids = isset($body['category_ids']) ? $body['category_ids'] : null;
|
| $uncategorized = isset($body['uncategorized']) ? $body['uncategorized'] : false;
|
| $missing_meta = isset($body['missing_meta']) ? $body['missing_meta'] : $request->get_param('missing_meta');
|
|
|
|
|
| if ($ids && is_array($ids)) {
|
| if (count($ids) > 100) {
|
| return new WP_Error('too_many_ids', 'Maximum 100 IDs per request', array('status' => 400));
|
| }
|
|
|
| $results = array();
|
| $not_found = array();
|
| $primary_keywords = array();
|
|
|
| foreach ($ids as $id) {
|
| $post = get_post(intval($id));
|
| if ($post && $post->post_type === 'product') {
|
| $item = cortex_ecommerce_build_product_data($post);
|
| if ($item) {
|
| $results[] = $item;
|
|
|
|
|
| if (!empty($item['audit_meta']['primary_keyword'])) {
|
| $pk = strtolower(trim($item['audit_meta']['primary_keyword']));
|
| if (!isset($primary_keywords[$pk])) {
|
| $primary_keywords[$pk] = array();
|
| }
|
| $primary_keywords[$pk][] = array(
|
| 'id' => $item['id'],
|
| 'slug' => $item['slug'],
|
| 'sku' => $item['woo_context']['sku']
|
| );
|
| }
|
| }
|
| } else {
|
| $not_found[] = intval($id);
|
| }
|
| }
|
|
|
|
|
| $cannibalization = array();
|
| foreach ($primary_keywords as $keyword => $pages) {
|
| if (count($pages) > 1) {
|
| $cannibalization[] = array(
|
| 'keyword' => $keyword,
|
| 'count' => count($pages),
|
| 'products' => $pages
|
| );
|
| }
|
| }
|
|
|
| return array(
|
| 'items' => $results,
|
| 'not_found' => $not_found,
|
| 'count' => count($results),
|
| 'cannibalization' => $cannibalization
|
| );
|
| }
|
|
|
|
|
| $per_page = isset($body['per_page']) ? min(intval($body['per_page']), 100) : 50;
|
| $page = isset($body['page']) ? intval($body['page']) : 1;
|
|
|
| $args = array(
|
| 'post_type' => 'product',
|
| 'posts_per_page' => $per_page,
|
| 'paged' => $page,
|
| 'post_status' => 'publish'
|
| );
|
|
|
|
|
| if ($category) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => is_numeric($category) ? 'term_id' : 'slug',
|
| 'terms' => $category
|
| )
|
| );
|
| }
|
|
|
| elseif ($category_ids && is_array($category_ids)) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => 'term_id',
|
| 'terms' => array_map('intval', $category_ids),
|
| 'operator' => 'IN'
|
| )
|
| );
|
| }
|
|
|
| elseif ($uncategorized) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'operator' => 'NOT EXISTS'
|
| )
|
| );
|
| }
|
|
|
|
|
| if ($missing_meta) {
|
| $args['meta_query'] = array(
|
| 'relation' => 'OR',
|
| array('key' => 'rank_math_title', 'compare' => 'NOT EXISTS'),
|
| array('key' => 'rank_math_title', 'value' => '', 'compare' => '='),
|
| array('key' => 'rank_math_description', 'compare' => 'NOT EXISTS'),
|
| array('key' => 'rank_math_description', 'value' => '', 'compare' => '=')
|
| );
|
| }
|
|
|
| $products = get_posts($args);
|
|
|
|
|
| $count_args = $args;
|
| $count_args['posts_per_page'] = -1;
|
| $count_args['fields'] = 'ids';
|
| $total_in_filter = count(get_posts($count_args));
|
|
|
| $results = array();
|
| $primary_keywords = array();
|
|
|
| foreach ($products as $product) {
|
| $item = cortex_ecommerce_build_product_data($product);
|
| if ($item) {
|
| $results[] = $item;
|
|
|
|
|
| if (!empty($item['audit_meta']['primary_keyword'])) {
|
| $pk = strtolower(trim($item['audit_meta']['primary_keyword']));
|
| if (!isset($primary_keywords[$pk])) {
|
| $primary_keywords[$pk] = array();
|
| }
|
| $primary_keywords[$pk][] = array(
|
| 'id' => $item['id'],
|
| 'slug' => $item['slug']
|
| );
|
| }
|
| }
|
| }
|
|
|
|
|
| $cannibalization = array();
|
| foreach ($primary_keywords as $keyword => $pages) {
|
| if (count($pages) > 1) {
|
| $cannibalization[] = array(
|
| 'keyword' => $keyword,
|
| 'count' => count($pages),
|
| 'products' => $pages
|
| );
|
| }
|
| }
|
|
|
| return array(
|
| 'items' => $results,
|
| 'pagination' => array(
|
| 'total' => intval($total),
|
| 'per_page' => $per_page,
|
| 'current_page' => $page,
|
| 'total_pages' => ceil($total / $per_page)
|
| ),
|
| 'count' => count($results),
|
| 'cannibalization' => $cannibalization
|
| );
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_get_product_categories($request) {
|
| $args = array(
|
| 'taxonomy' => 'product_cat',
|
| 'hide_empty' => false,
|
| 'orderby' => 'name',
|
| 'order' => 'ASC'
|
| );
|
|
|
| $parent = $request->get_param('parent');
|
| if ($parent !== null) {
|
| $args['parent'] = intval($parent);
|
| }
|
|
|
| $hide_empty = $request->get_param('hide_empty');
|
| if ($hide_empty === 'true' || $hide_empty === '1') {
|
| $args['hide_empty'] = true;
|
| }
|
|
|
| $categories = get_terms($args);
|
|
|
| if (is_wp_error($categories)) {
|
| return new WP_Error('error', 'Failed to retrieve product categories', array('status' => 500));
|
| }
|
|
|
| $result = array();
|
| foreach ($categories as $cat) {
|
|
|
| $thumbnail_id = get_term_meta($cat->term_id, 'thumbnail_id', true);
|
| $thumbnail_url = $thumbnail_id ? wp_get_attachment_url($thumbnail_id) : '';
|
|
|
| $result[] = array(
|
| 'id' => $cat->term_id,
|
| 'name' => $cat->name,
|
| 'slug' => $cat->slug,
|
| 'description' => $cat->description,
|
| 'parent' => $cat->parent,
|
| 'count' => $cat->count,
|
| 'link' => get_term_link($cat),
|
| 'thumbnail_url' => $thumbnail_url,
|
| 'rank_math_title' => get_term_meta($cat->term_id, 'rank_math_title', true),
|
| 'rank_math_description' => get_term_meta($cat->term_id, 'rank_math_description', true),
|
| 'rank_math_focus_keyword' => get_term_meta($cat->term_id, 'rank_math_focus_keyword', true),
|
| 'rank_math_facebook_title' => get_term_meta($cat->term_id, 'rank_math_facebook_title', true),
|
| 'rank_math_facebook_description' => get_term_meta($cat->term_id, 'rank_math_facebook_description', true),
|
| 'rank_math_twitter_title' => get_term_meta($cat->term_id, 'rank_math_twitter_title', true),
|
| 'rank_math_twitter_description' => get_term_meta($cat->term_id, 'rank_math_twitter_description', true),
|
| );
|
| }
|
|
|
| return $result;
|
| }
|
|
|
| function cortex_ecommerce_get_product_category($request) {
|
| $term_id = $request->get_param('id');
|
| $cat = get_term($term_id, 'product_cat');
|
|
|
| if (!$cat || is_wp_error($cat)) {
|
| return new WP_Error('not_found', 'Product category not found', array('status' => 404));
|
| }
|
|
|
|
|
| $thumbnail_id = get_term_meta($cat->term_id, 'thumbnail_id', true);
|
| $thumbnail_url = $thumbnail_id ? wp_get_attachment_url($thumbnail_id) : '';
|
|
|
|
|
| $products = get_posts(array(
|
| 'post_type' => 'product',
|
| 'posts_per_page' => -1,
|
| 'post_status' => 'publish',
|
| 'fields' => 'ids',
|
| 'tax_query' => array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => 'term_id',
|
| 'terms' => $term_id
|
| )
|
| )
|
| ));
|
|
|
| return array(
|
| 'id' => $cat->term_id,
|
| 'name' => $cat->name,
|
| 'slug' => $cat->slug,
|
| 'description' => $cat->description,
|
| 'parent' => $cat->parent,
|
| 'count' => $cat->count,
|
| 'link' => get_term_link($cat),
|
| 'thumbnail_url' => $thumbnail_url,
|
| 'product_ids' => $products,
|
| 'rank_math_title' => get_term_meta($cat->term_id, 'rank_math_title', true),
|
| 'rank_math_description' => get_term_meta($cat->term_id, 'rank_math_description', true),
|
| 'rank_math_focus_keyword' => get_term_meta($cat->term_id, 'rank_math_focus_keyword', true),
|
| 'rank_math_facebook_title' => get_term_meta($cat->term_id, 'rank_math_facebook_title', true),
|
| 'rank_math_facebook_description' => get_term_meta($cat->term_id, 'rank_math_facebook_description', true),
|
| 'rank_math_twitter_title' => get_term_meta($cat->term_id, 'rank_math_twitter_title', true),
|
| 'rank_math_twitter_description' => get_term_meta($cat->term_id, 'rank_math_twitter_description', true),
|
| 'audit_meta' => array(
|
| 'name_chars' => strlen($cat->name),
|
| 'desc_chars' => strlen($cat->description),
|
| 'meta_title_chars' => strlen(get_term_meta($cat->term_id, 'rank_math_title', true)),
|
| 'meta_desc_chars' => strlen(get_term_meta($cat->term_id, 'rank_math_description', true)),
|
| )
|
| );
|
| }
|
|
|
| function cortex_ecommerce_create_product_category($request) {
|
| $name = $request->get_param('name');
|
|
|
| if (empty($name)) {
|
| return new WP_Error('missing_name', 'Category name is required', array('status' => 400));
|
| }
|
|
|
| $args = array();
|
|
|
| $slug = $request->get_param('slug');
|
| if ($slug) $args['slug'] = sanitize_title($slug);
|
|
|
| $description = $request->get_param('description');
|
| if ($description) $args['description'] = sanitize_textarea_field($description);
|
|
|
| $parent = $request->get_param('parent');
|
| if ($parent) $args['parent'] = intval($parent);
|
|
|
| $result = wp_insert_term(sanitize_text_field($name), 'product_cat', $args);
|
|
|
| if (is_wp_error($result)) {
|
| return new WP_Error('create_failed', $result->get_error_message(), array('status' => 400));
|
| }
|
|
|
| $term_id = $result['term_id'];
|
|
|
|
|
| $seo_fields = array(
|
| 'rank_math_title', 'rank_math_description', 'rank_math_focus_keyword',
|
| 'rank_math_facebook_title', 'rank_math_facebook_description',
|
| 'rank_math_twitter_title', 'rank_math_twitter_description'
|
| );
|
|
|
| foreach ($seo_fields as $field) {
|
| $value = $request->get_param($field);
|
| if ($value !== null) {
|
| update_term_meta($term_id, $field, sanitize_text_field($value));
|
| }
|
| }
|
|
|
| $cat = get_term($term_id, 'product_cat');
|
|
|
| return array(
|
| 'success' => true,
|
| 'message' => 'Product category created successfully',
|
| 'category' => array(
|
| 'id' => $cat->term_id,
|
| 'name' => $cat->name,
|
| 'slug' => $cat->slug,
|
| 'description' => $cat->description,
|
| 'parent' => $cat->parent,
|
| 'link' => get_term_link($cat),
|
| )
|
| );
|
| }
|
|
|
| function cortex_ecommerce_update_product_category($request) {
|
| $term_id = $request->get_param('id');
|
| $cat = get_term($term_id, 'product_cat');
|
|
|
| if (!$cat || is_wp_error($cat)) {
|
| return new WP_Error('not_found', 'Product category not found', array('status' => 404));
|
| }
|
|
|
| $updated = array();
|
| $term_args = array();
|
|
|
| $name = $request->get_param('name');
|
| if ($name !== null) { $term_args['name'] = sanitize_text_field($name); $updated['name'] = $name; }
|
|
|
| $slug = $request->get_param('slug');
|
| if ($slug !== null) { $term_args['slug'] = sanitize_title($slug); $updated['slug'] = $slug; }
|
|
|
| $description = $request->get_param('description');
|
| if ($description !== null) { $term_args['description'] = sanitize_textarea_field($description); $updated['description'] = $description; }
|
|
|
| $parent = $request->get_param('parent');
|
| if ($parent !== null) { $term_args['parent'] = intval($parent); $updated['parent'] = intval($parent); }
|
|
|
| if (!empty($term_args)) {
|
| $result = wp_update_term($term_id, 'product_cat', $term_args);
|
| if (is_wp_error($result)) {
|
| return new WP_Error('update_failed', $result->get_error_message(), array('status' => 400));
|
| }
|
| }
|
|
|
|
|
| $seo_fields = array(
|
| 'rank_math_title', 'rank_math_description', 'rank_math_focus_keyword',
|
| 'rank_math_facebook_title', 'rank_math_facebook_description',
|
| 'rank_math_twitter_title', 'rank_math_twitter_description'
|
| );
|
|
|
| foreach ($seo_fields as $field) {
|
| $value = $request->get_param($field);
|
| if ($value !== null) {
|
| update_term_meta($term_id, $field, sanitize_text_field($value));
|
| $updated[$field] = $value;
|
| }
|
| }
|
|
|
| if (empty($updated)) {
|
| return new WP_Error('no_fields', 'No valid fields provided to update', array('status' => 400));
|
| }
|
|
|
| $cat = get_term($term_id, 'product_cat');
|
|
|
| return array(
|
| 'success' => true,
|
| 'message' => count($updated) . ' field(s) updated successfully',
|
| 'updated_fields' => $updated,
|
| 'category' => array(
|
| 'id' => $cat->term_id,
|
| 'name' => $cat->name,
|
| 'slug' => $cat->slug,
|
| 'description' => $cat->description,
|
| 'parent' => $cat->parent,
|
| 'link' => get_term_link($cat),
|
| 'rank_math_title' => get_term_meta($term_id, 'rank_math_title', true),
|
| 'rank_math_description' => get_term_meta($term_id, 'rank_math_description', true),
|
| )
|
| );
|
| }
|
|
|
| function cortex_ecommerce_delete_product_category($request) {
|
| $term_id = $request->get_param('id');
|
| $cat = get_term($term_id, 'product_cat');
|
|
|
| if (!$cat || is_wp_error($cat)) {
|
| return new WP_Error('not_found', 'Product category not found', array('status' => 404));
|
| }
|
|
|
|
|
| $default_cat = get_option('default_product_cat');
|
| if ($term_id == $default_cat) {
|
| return new WP_Error('cannot_delete', 'Cannot delete the default product category', array('status' => 400));
|
| }
|
|
|
| $cat_name = $cat->name;
|
| $result = wp_delete_term($term_id, 'product_cat');
|
|
|
| if (is_wp_error($result)) {
|
| return new WP_Error('delete_failed', $result->get_error_message(), array('status' => 400));
|
| }
|
|
|
| return array(
|
| 'success' => true,
|
| 'message' => 'Product category "' . $cat_name . '" deleted successfully',
|
| 'deleted_id' => $term_id
|
| );
|
| }
|
|
|
| function cortex_ecommerce_bulk_update_product_categories($request) {
|
| $items = $request->get_param('items');
|
|
|
| if (!$items || !is_array($items)) {
|
| return new WP_Error('invalid_payload', 'Expected "items" array in request body', array('status' => 400));
|
| }
|
|
|
| if (count($items) > 50) {
|
| return new WP_Error('too_many_items', 'Maximum 50 items per bulk request', array('status' => 400));
|
| }
|
|
|
| $results = array(
|
| 'success' => array(),
|
| 'failed' => array(),
|
| 'summary' => array('total' => count($items), 'succeeded' => 0, 'failed' => 0)
|
| );
|
|
|
| $seo_fields = array(
|
| 'rank_math_title', 'rank_math_description', 'rank_math_focus_keyword',
|
| 'rank_math_facebook_title', 'rank_math_facebook_description',
|
| 'rank_math_twitter_title', 'rank_math_twitter_description'
|
| );
|
|
|
| foreach ($items as $item) {
|
| if (!isset($item['id'])) {
|
| $results['failed'][] = array('error' => 'Missing id field', 'item' => $item);
|
| $results['summary']['failed']++;
|
| continue;
|
| }
|
|
|
| $term_id = intval($item['id']);
|
| $cat = get_term($term_id, 'product_cat');
|
|
|
| if (!$cat || is_wp_error($cat)) {
|
| $results['failed'][] = array('id' => $term_id, 'error' => 'Product category not found');
|
| $results['summary']['failed']++;
|
| continue;
|
| }
|
|
|
| $updated = array();
|
| $term_args = array();
|
|
|
| if (isset($item['name'])) { $term_args['name'] = sanitize_text_field($item['name']); $updated['name'] = $item['name']; }
|
| if (isset($item['slug'])) { $term_args['slug'] = sanitize_title($item['slug']); $updated['slug'] = $item['slug']; }
|
| if (isset($item['description'])) { $term_args['description'] = sanitize_textarea_field($item['description']); $updated['description'] = $item['description']; }
|
|
|
| if (!empty($term_args)) wp_update_term($term_id, 'product_cat', $term_args);
|
|
|
| foreach ($seo_fields as $field) {
|
| if (isset($item[$field])) {
|
| update_term_meta($term_id, $field, sanitize_text_field($item[$field]));
|
| $updated[$field] = $item[$field];
|
| }
|
| }
|
|
|
| $results['success'][] = array('id' => $term_id, 'updated_fields' => $updated, 'fields_count' => count($updated));
|
| $results['summary']['succeeded']++;
|
| }
|
|
|
| return $results;
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_get_product_tags($request) {
|
| $args = array(
|
| 'taxonomy' => 'product_tag',
|
| 'hide_empty' => false,
|
| 'orderby' => 'count',
|
| 'order' => 'DESC'
|
| );
|
|
|
| $hide_empty = $request->get_param('hide_empty');
|
| if ($hide_empty === 'true' || $hide_empty === '1') {
|
| $args['hide_empty'] = true;
|
| }
|
|
|
| $tags = get_terms($args);
|
|
|
| if (is_wp_error($tags)) {
|
| return new WP_Error('error', 'Failed to retrieve product tags', array('status' => 500));
|
| }
|
|
|
| $result = array();
|
| foreach ($tags as $tag) {
|
| $result[] = array(
|
| 'id' => $tag->term_id,
|
| 'name' => $tag->name,
|
| 'slug' => $tag->slug,
|
| 'description' => $tag->description,
|
| 'count' => $tag->count,
|
| 'link' => get_term_link($tag),
|
| );
|
| }
|
|
|
| return $result;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_mass_categorize_products($request) {
|
| $body = $request->get_json_params();
|
|
|
| $source = isset($body['source']) ? $body['source'] : array();
|
| $rules = isset($body['rules']) ? $body['rules'] : array();
|
| $dry_run = isset($body['dry_run']) ? (bool)$body['dry_run'] : true;
|
| $limit = isset($body['limit']) ? min(intval($body['limit']), 5000) : 1000;
|
| $return_matches = isset($body['return_matches']) ? (bool)$body['return_matches'] : false;
|
|
|
|
|
| if (empty($rules)) {
|
| return new WP_Error('no_rules', 'At least one categorization rule is required', array('status' => 400));
|
| }
|
|
|
| if (empty($source)) {
|
| return new WP_Error('no_source', 'Source filter is required (category_id, category_ids, uncategorized, or all)', array('status' => 400));
|
| }
|
|
|
|
|
| $args = array(
|
| 'post_type' => 'product',
|
| 'posts_per_page' => $limit,
|
| 'post_status' => 'publish',
|
| 'fields' => 'ids'
|
| );
|
|
|
|
|
| if (!empty($source['category_id'])) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => 'term_id',
|
| 'terms' => intval($source['category_id'])
|
| )
|
| );
|
| }
|
|
|
| elseif (!empty($source['category_ids']) && is_array($source['category_ids'])) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'field' => 'term_id',
|
| 'terms' => array_map('intval', $source['category_ids']),
|
| 'operator' => 'IN'
|
| )
|
| );
|
| }
|
|
|
| elseif (!empty($source['uncategorized'])) {
|
| $args['tax_query'] = array(
|
| array(
|
| 'taxonomy' => 'product_cat',
|
| 'operator' => 'NOT EXISTS'
|
| )
|
| );
|
| }
|
|
|
| elseif (empty($source['all'])) {
|
| return new WP_Error('invalid_source', 'Invalid source. Use category_id, category_ids, uncategorized, or all', array('status' => 400));
|
| }
|
|
|
|
|
| $product_ids = get_posts($args);
|
|
|
| $results = array(
|
| 'success' => true,
|
| 'dry_run' => $dry_run,
|
| 'source' => $source,
|
| 'summary' => array(
|
| 'products_scanned' => count($product_ids),
|
| 'products_matched' => 0,
|
| 'products_updated' => 0,
|
| 'rules_applied' => count($rules)
|
| ),
|
| 'rules_summary' => array(),
|
| 'matches' => array()
|
| );
|
|
|
|
|
| $resolved_categories = array();
|
|
|
|
|
| foreach ($rules as $rule_index => $rule) {
|
| $match_criteria = isset($rule['match']) ? $rule['match'] : array();
|
| $action = isset($rule['action']) ? $rule['action'] : array();
|
|
|
| $rule_matches = 0;
|
| $rule_updated = 0;
|
|
|
|
|
| foreach ($product_ids as $product_id) {
|
|
|
| $product = wc_get_product($product_id);
|
| if (!$product) continue;
|
|
|
| $title = strtolower($product->get_name());
|
| $sku = strtolower($product->get_sku());
|
| $price = floatval($product->get_price());
|
|
|
|
|
| $matches = true;
|
|
|
|
|
| if (!empty($match_criteria['title_contains'])) {
|
| $title_match = false;
|
| foreach ((array)$match_criteria['title_contains'] as $term) {
|
| if (strpos($title, strtolower($term)) !== false) {
|
| $title_match = true;
|
| break;
|
| }
|
| }
|
| if (!$title_match) $matches = false;
|
| }
|
|
|
|
|
| if ($matches && !empty($match_criteria['title_contains_all'])) {
|
| foreach ((array)$match_criteria['title_contains_all'] as $term) {
|
| if (strpos($title, strtolower($term)) === false) {
|
| $matches = false;
|
| break;
|
| }
|
| }
|
| }
|
|
|
|
|
| if ($matches && !empty($match_criteria['sku_prefix'])) {
|
| if (strpos($sku, strtolower($match_criteria['sku_prefix'])) !== 0) {
|
| $matches = false;
|
| }
|
| }
|
|
|
|
|
| if ($matches && !empty($match_criteria['sku_contains'])) {
|
| if (strpos($sku, strtolower($match_criteria['sku_contains'])) === false) {
|
| $matches = false;
|
| }
|
| }
|
|
|
|
|
| if ($matches && isset($match_criteria['price_min'])) {
|
| if ($price < floatval($match_criteria['price_min'])) {
|
| $matches = false;
|
| }
|
| }
|
| if ($matches && isset($match_criteria['price_max'])) {
|
| if ($price > floatval($match_criteria['price_max'])) {
|
| $matches = false;
|
| }
|
| }
|
|
|
|
|
| if ($matches) {
|
| $rule_matches++;
|
|
|
|
|
| if ($return_matches) {
|
| $current_cats = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'names'));
|
| $results['matches'][] = array(
|
| 'id' => $product_id,
|
| 'title' => $product->get_name(),
|
| 'sku' => $product->get_sku(),
|
| 'price' => $price,
|
| 'rule_index' => $rule_index,
|
| 'current_categories' => $current_cats
|
| );
|
| }
|
|
|
|
|
| if (!$dry_run) {
|
| $updated = cortex_ecommerce_apply_category_action($product_id, $action, $resolved_categories);
|
| if ($updated) {
|
| $rule_updated++;
|
| }
|
| }
|
| }
|
| }
|
|
|
| $results['rules_summary'][] = array(
|
| 'rule_index' => $rule_index,
|
| 'match_criteria' => $match_criteria,
|
| 'matched' => $rule_matches,
|
| 'updated' => $dry_run ? 0 : $rule_updated
|
| );
|
|
|
| $results['summary']['products_matched'] += $rule_matches;
|
| $results['summary']['products_updated'] += $rule_updated;
|
| }
|
|
|
|
|
| if ($dry_run) {
|
| $results['message'] = sprintf(
|
| 'DRY RUN: %d products would be updated. Set "dry_run": false to apply changes.',
|
| $results['summary']['products_matched']
|
| );
|
| } else {
|
| $results['message'] = sprintf(
|
| '%d products updated successfully.',
|
| $results['summary']['products_updated']
|
| );
|
| }
|
|
|
| return $results;
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_apply_category_action($product_id, $action, &$resolved_categories) {
|
| $updated = false;
|
|
|
|
|
| if (!empty($action['set_category_ids'])) {
|
| $cat_ids = array_map('intval', (array)$action['set_category_ids']);
|
| wp_set_post_terms($product_id, $cat_ids, 'product_cat');
|
| $updated = true;
|
| }
|
|
|
| elseif (!empty($action['set_categories'])) {
|
| $cat_ids = array();
|
| foreach ((array)$action['set_categories'] as $cat_name) {
|
| $cat_id = cortex_ecommerce_resolve_category($cat_name, $resolved_categories);
|
| if ($cat_id) $cat_ids[] = $cat_id;
|
| }
|
| if (!empty($cat_ids)) {
|
| wp_set_post_terms($product_id, $cat_ids, 'product_cat');
|
| $updated = true;
|
| }
|
| }
|
| else {
|
| $existing_cats = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
|
| $new_cats = $existing_cats;
|
|
|
|
|
| if (!empty($action['add_category_ids'])) {
|
| $add_ids = array_map('intval', (array)$action['add_category_ids']);
|
| $new_cats = array_unique(array_merge($new_cats, $add_ids));
|
| $updated = true;
|
| }
|
|
|
|
|
| if (!empty($action['add_categories'])) {
|
| foreach ((array)$action['add_categories'] as $cat_name) {
|
| $cat_id = cortex_ecommerce_resolve_category($cat_name, $resolved_categories, true);
|
| if ($cat_id && !in_array($cat_id, $new_cats)) {
|
| $new_cats[] = $cat_id;
|
| $updated = true;
|
| }
|
| }
|
| }
|
|
|
|
|
| if (!empty($action['remove_category_ids'])) {
|
| $remove_ids = array_map('intval', (array)$action['remove_category_ids']);
|
| $new_cats = array_diff($new_cats, $remove_ids);
|
| $updated = true;
|
| }
|
|
|
|
|
| if (!empty($action['remove_categories'])) {
|
| foreach ((array)$action['remove_categories'] as $cat_name) {
|
| $cat_id = cortex_ecommerce_resolve_category($cat_name, $resolved_categories);
|
| if ($cat_id) {
|
| $new_cats = array_diff($new_cats, array($cat_id));
|
| $updated = true;
|
| }
|
| }
|
| }
|
|
|
| if ($updated) {
|
| wp_set_post_terms($product_id, array_values($new_cats), 'product_cat');
|
| }
|
| }
|
|
|
| return $updated;
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function cortex_ecommerce_resolve_category($cat_name, &$cache, $create = false) {
|
| $cat_name = sanitize_text_field($cat_name);
|
| $cache_key = strtolower($cat_name);
|
|
|
|
|
| if (isset($cache[$cache_key])) {
|
| return $cache[$cache_key];
|
| }
|
|
|
|
|
| $term = get_term_by('name', $cat_name, 'product_cat');
|
| if ($term) {
|
| $cache[$cache_key] = $term->term_id;
|
| return $term->term_id;
|
| }
|
|
|
|
|
| if ($create) {
|
| $new_term = wp_insert_term($cat_name, 'product_cat');
|
| if (!is_wp_error($new_term)) {
|
| $cache[$cache_key] = $new_term['term_id'];
|
| return $new_term['term_id'];
|
| }
|
| }
|
|
|
| return null;
|
| }
|
| |
| |
Comments