api_client = $api_client; $this->settings = $settings; $this->init_hooks(); } /** * Initialize WordPress hooks */ private function init_hooks() { // Register REST API endpoints. add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) ); } /** * Register REST API routes */ public function register_rest_routes() { register_rest_route( 'activetrail-for-woocommerce/v1', '/catalog', array( 'methods' => 'GET', 'callback' => array( $this, 'get_catalog' ), 'permission_callback' => '__return_true', ) ); } /** * Get catalog endpoint callback * * @param WP_REST_Request $request Request object * @return WP_REST_Response */ public function get_catalog( $request ) { $this->log( 'Catalog API endpoint called' ); // Switch to plugin's language setting for translations. $locale_switched = $this->switch_to_plugin_language(); try { // Get all published products. $args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'fields' => 'ids', ); $product_ids = get_posts( $args ); $this->log( 'Found ' . count( $product_ids ) . ' products' ); $items = array(); foreach ( $product_ids as $pid ) { $product = wc_get_product( $pid ); if ( ! $product ) { continue; } // Get product image. $image_url = ''; if ( $product->get_image_id() ) { $image_url = wp_get_attachment_url( $product->get_image_id() ); } elseif ( $product->is_type( 'variation' ) && $product->get_parent_id() ) { $parent = wc_get_product( $product->get_parent_id() ); if ( $parent && $parent->get_image_id() ) { $image_url = wp_get_attachment_url( $parent->get_image_id() ); } } // Use placeholder if no image found. if ( empty( $image_url ) ) { $image_url = wc_placeholder_img_src(); } // Get full description, fallback to short description. $description = $product->get_description(); if ( empty( $description ) ) { $description = $product->get_short_description(); } $description = wp_strip_all_tags( $description ); // Get product tags. $tags = array(); $terms = wp_get_post_terms( $pid, 'product_tag', array( 'fields' => 'names' ) ); if ( ! is_wp_error( $terms ) ) { $tags = $terms; } $items[] = array( 'id' => (int) $pid, 'title' => $product->get_name(), 'link' => get_permalink( $pid ), 'image_link' => $image_url, 'availability' => $product->is_in_stock() ? 'in stock' : 'out of stock', 'description' => $description, 'price' => (string) wc_get_price_to_display( $product ), 'sale_price' => $product->get_sale_price() ? (string) wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) ) : '', 'condition' => 'New', 'product_type' => $product->get_type(), 'quantity' => (int) ( $product->get_stock_quantity() ?? 0 ), 'variant' => (int) ( $product->is_type( 'variation' ) ? $pid : 0 ), 'parent_id' => (int) ( $product->is_type( 'variation' ) ? $product->get_parent_id() : 0 ), 'tags' => $tags, 'sku' => (string) ( $product->get_sku() ?: '' ), 'created_at' => (int) get_post_time( 'U', true, $pid ), 'updated_at' => (int) get_post_modified_time( 'U', true, $pid ), ); } // Return data in the requested format. return rest_ensure_response( array( 'data' => $items ) ); } finally { // Restore original locale. if ( $locale_switched ) { $this->restore_plugin_language(); } } } /** * Switch to plugin's configured language * * @return bool True if locale was switched, false otherwise */ private function switch_to_plugin_language() { if ( ! class_exists( 'ActiveTrail_Settings' ) ) { require_once ACTIVETRAIL_WC_PLUGIN_DIR . 'includes/settings/class-settings.php'; } $current_language = ActiveTrail_Settings::get_current_language(); if ( empty( $current_language ) ) { return false; } // Support WPML if installed. if ( function_exists( 'icl_object_id' ) && function_exists( 'do_action' ) ) { global $sitepress; if ( $sitepress ) { // Convert language code format if needed (e.g., en_US -> en). $wpml_lang = strstr( $current_language, '_', true ) ?: $current_language; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML hook do_action( 'wpml_switch_language', $wpml_lang ); } } // Support Polylang if installed. if ( function_exists( 'pll_current_language' ) && function_exists( 'PLL' ) ) { $polylang = PLL(); if ( $polylang ) { // Convert language code format if needed. $pll_lang = strstr( $current_language, '_', true ) ?: $current_language; $polylang->curlang = $polylang->model->get_language( $pll_lang ); if ( ! $polylang->curlang ) { // Try full code. $polylang->curlang = $polylang->model->get_language( $current_language ); } } } // Switch WordPress locale for text domain translations. if ( function_exists( 'switch_to_locale' ) ) { return switch_to_locale( $current_language ); } return false; } /** * Restore original locale */ private function restore_plugin_language() { // Restore WordPress locale. if ( function_exists( 'restore_current_locale' ) ) { restore_current_locale(); } // WPML and Polylang don't need explicit restoration as they handle it automatically. } /** * Log message * * @param string $message Log message * @param string $level Log level */ private function log( $message, $level = 'info' ) { if ( function_exists( 'activetrail_logger' ) ) { $level_map = array( 'info' => 'INFO', 'debug' => 'DEBUG', 'warning' => 'WARNING', 'error' => 'ERROR', ); $mapped_level = isset( $level_map[ $level ] ) ? $level_map[ $level ] : 'INFO'; activetrail_logger()->log( $message, $mapped_level, 'GENERAL' ); } } }